project-graph-mcp 1.5.0 → 2.0.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 +128 -8
- package/package.json +12 -8
- package/src/.project-graph-cache.json +1 -1
- package/src/analysis/analysis-cache.js +7 -0
- package/src/analysis/complexity.js +14 -0
- package/src/analysis/custom-rules.js +36 -0
- package/src/analysis/db-analysis.js +9 -0
- package/src/analysis/dead-code.js +19 -0
- package/src/analysis/full-analysis.js +18 -0
- package/src/analysis/jsdoc-checker.js +24 -0
- package/src/analysis/jsdoc-generator.js +10 -0
- package/src/analysis/large-files.js +11 -0
- package/src/analysis/outdated-patterns.js +12 -0
- package/src/analysis/similar-functions.js +16 -0
- package/src/analysis/test-annotations.js +21 -0
- package/src/analysis/type-checker.js +8 -0
- package/src/analysis/undocumented.js +14 -0
- package/src/cli/cli-handlers.js +4 -0
- package/src/cli/cli.js +5 -0
- package/src/compact/ai-context.js +7 -0
- package/src/compact/compact.js +18 -0
- package/src/compact/compress.js +13 -0
- package/src/compact/ctx-to-jsdoc.js +29 -0
- package/src/compact/doc-dialect.js +30 -0
- package/src/compact/expand.js +37 -0
- package/src/compact/framework-references.js +5 -0
- package/src/compact/instructions.js +3 -0
- package/src/compact/mode-config.js +8 -0
- package/src/compact/validate-pipeline.js +9 -0
- package/src/core/event-bus.js +9 -0
- package/src/core/filters.js +14 -0
- package/src/core/graph-builder.js +12 -0
- package/src/core/parser.js +31 -0
- package/src/core/workspace.js +8 -0
- package/src/lang/lang-go.js +17 -0
- package/src/lang/lang-python.js +12 -0
- package/src/lang/lang-sql.js +23 -0
- package/src/lang/lang-typescript.js +9 -0
- package/src/lang/lang-utils.js +4 -0
- package/src/mcp/mcp-server.js +17 -0
- package/src/mcp/tool-defs.js +3 -0
- package/src/mcp/tools.js +25 -0
- package/src/network/backend-lifecycle.js +19 -0
- package/src/network/backend.js +5 -0
- package/src/network/local-gateway.js +23 -0
- package/src/network/mdns.js +13 -0
- package/src/network/server.js +10 -0
- package/src/network/web-server.js +34 -0
- package/web/.project-graph-cache.json +1 -0
- package/web/app.js +16 -0
- package/web/components/code-block.js +3 -0
- package/web/components/quick-open.js +5 -0
- package/web/dashboard-state.js +3 -0
- package/web/dashboard.html +27 -0
- package/web/dashboard.js +8 -0
- package/web/highlight.js +13 -0
- package/web/index.html +35 -0
- package/web/panels/ActionBoard/ActionBoard.css.js +1 -0
- package/web/panels/ActionBoard/ActionBoard.js +4 -0
- package/web/panels/ActionBoard/ActionBoard.tpl.js +1 -0
- package/web/panels/EventItem/EventItem.css.js +1 -0
- package/web/panels/EventItem/EventItem.js +4 -0
- package/web/panels/EventItem/EventItem.tpl.js +1 -0
- package/web/panels/ProjectItem/ProjectItem.css.js +1 -0
- package/web/panels/ProjectItem/ProjectItem.js +5 -0
- package/web/panels/ProjectItem/ProjectItem.tpl.js +1 -0
- package/web/panels/ProjectList/ProjectList.css.js +1 -0
- package/web/panels/ProjectList/ProjectList.js +4 -0
- package/web/panels/ProjectList/ProjectList.tpl.js +1 -0
- package/web/panels/SettingsPanel/.project-graph-cache.json +1 -0
- package/web/panels/SettingsPanel/SettingsPanel.css.js +1 -0
- package/web/panels/SettingsPanel/SettingsPanel.js +7 -0
- package/web/panels/SettingsPanel/SettingsPanel.tpl.js +1 -0
- package/web/panels/code-viewer.js +5 -0
- package/web/panels/ctx-panel.js +4 -0
- package/web/panels/dep-graph.js +6 -0
- package/web/panels/file-tree.js +188 -0
- package/web/panels/health-panel.js +3 -0
- package/web/panels/live-monitor.js +3 -0
- package/web/state.js +17 -0
- package/web/style.css +157 -0
- package/references/symbiote-3x.md +0 -834
- package/src/ai-context.js +0 -113
- package/src/analysis-cache.js +0 -155
- package/src/cli-handlers.js +0 -271
- package/src/cli.js +0 -95
- package/src/compact.js +0 -207
- package/src/complexity.js +0 -237
- package/src/compress.js +0 -319
- package/src/ctx-to-jsdoc.js +0 -514
- package/src/custom-rules.js +0 -584
- package/src/db-analysis.js +0 -194
- package/src/dead-code.js +0 -468
- package/src/doc-dialect.js +0 -716
- package/src/filters.js +0 -227
- package/src/framework-references.js +0 -177
- package/src/full-analysis.js +0 -470
- package/src/graph-builder.js +0 -299
- package/src/instructions.js +0 -73
- package/src/jsdoc-checker.js +0 -351
- package/src/jsdoc-generator.js +0 -203
- package/src/lang-go.js +0 -285
- package/src/lang-python.js +0 -197
- package/src/lang-sql.js +0 -309
- package/src/lang-typescript.js +0 -190
- package/src/lang-utils.js +0 -124
- package/src/large-files.js +0 -163
- package/src/mcp-server.js +0 -675
- package/src/mode-config.js +0 -127
- package/src/outdated-patterns.js +0 -296
- package/src/parser.js +0 -662
- package/src/server.js +0 -28
- package/src/similar-functions.js +0 -279
- package/src/test-annotations.js +0 -323
- package/src/tool-defs.js +0 -793
- package/src/tools.js +0 -470
- package/src/type-checker.js +0 -188
- package/src/undocumented.js +0 -259
- package/src/workspace.js +0 -70
- /package/{AGENT_ROLE.md → docs/examples/AGENT_ROLE.md} +0 -0
- /package/{AGENT_ROLE_MINIMAL.md → docs/examples/AGENT_ROLE_MINIMAL.md} +0 -0
package/README.md
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
[](https://www.npmjs.com/package/project-graph-mcp)
|
|
2
2
|
[](https://opensource.org/licenses/MIT)
|
|
3
3
|
[](https://nodejs.org)
|
|
4
|
-
[](https://www.npmjs.com/package/project-graph-mcp)
|
|
5
4
|
|
|
6
5
|
# project-graph-mcp
|
|
7
6
|
|
|
8
7
|
An MCP server that parses your source code into a **10-50x compressed skeleton** — classes, functions, imports, and dependencies in a minified JSON. Agents navigate the graph using `expand`, `deps`, and `usages` without reading irrelevant files. The **AI Context Layer** compresses an entire codebase into ~1700 tokens (97% savings) with a single `get_ai_context` call. Supports **monorepo scanning** and **streaming analysis** for large codebases.
|
|
9
8
|
|
|
10
9
|
> [!TIP]
|
|
11
|
-
> **
|
|
10
|
+
> **18 MCP tools.** Add one line to your MCP config and the server downloads itself on the next IDE restart.
|
|
12
11
|
|
|
13
12
|
### Project Skeleton (10-50x compression)
|
|
14
13
|
|
|
@@ -60,14 +59,20 @@ get_ai_context({ path: "src/" })
|
|
|
60
59
|
|
|
61
60
|
- **Code compression** — Terser-minified source with export legend headers (20-55% per file)
|
|
62
61
|
- **Compact Code Mode** — project-wide `compact`/`beautify` (preserves all names, strips comments/whitespace)
|
|
63
|
-
- **Doc Dialect** — compact `.context/` documentation format, auto-generated from AST with `{DESCRIBE}` markers
|
|
62
|
+
- **Doc Dialect** — compact `.context/` documentation format, auto-generated from AST with `{DESCRIBE}` markers. Descriptions use a **simplified English dialect** — max 80 characters, pipe-separated, with standard abbreviations (`fn/ret/cfg/init/auth/db/msg`):
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
generateJSDoc(t)→e.push,e.join|build /** */ JSDoc block from .ctx signature
|
|
66
|
+
export expandFile(e,n)→beautify,inject|beautify compact JS + inject JSDoc from .ctx
|
|
67
|
+
PATTERNS: Terser beautify|AST walk for injection points|reverse-order insertion
|
|
68
|
+
```
|
|
64
69
|
- **Two-tier `.ctx`** — `.ctx` (machine-generated, AST signatures) + `.ctx.md` (agent notes, TODO, decisions)
|
|
65
70
|
- **Self-enriching** — `@enrich` instructions embedded in `.ctx` files guide any AI agent to fill descriptions
|
|
66
71
|
- **Staleness detection** — `@sig` hashes track structural changes; `check_stale_docs` identifies outdated docs
|
|
67
72
|
- **Merge strategy** — regenerating `.ctx` files preserves existing descriptions
|
|
68
73
|
- **Boot aggregator** — `get_ai_context` combines skeleton + docs + compressed files in one response
|
|
69
74
|
|
|
70
|
-
```
|
|
75
|
+
```bash
|
|
71
76
|
# Generate .context/ documentation templates
|
|
72
77
|
npx project-graph-mcp generate-ctx src/
|
|
73
78
|
|
|
@@ -75,9 +80,52 @@ npx project-graph-mcp generate-ctx src/
|
|
|
75
80
|
npx project-graph-mcp docs src/
|
|
76
81
|
|
|
77
82
|
# Compress a single file for AI
|
|
78
|
-
npx project-graph-mcp compress src/parser.js
|
|
83
|
+
npx project-graph-mcp compress src/core/parser.js
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Two-Tier Context: Overview → Focus
|
|
87
|
+
|
|
88
|
+
Agents don't need full context for every file. The server provides a **progressive loading model**:
|
|
89
|
+
|
|
90
|
+
| Mode | What agent reads | Token cost | Use case |
|
|
91
|
+
|------|-----------------|------------|----------|
|
|
92
|
+
| **Overview** | `get_skeleton()` + compact code | codeTok only | Understand project structure |
|
|
93
|
+
| **Focus** | compact code + `.ctx` for specific files | codeTok + ctxTok (per file) | Deep work on area of interest |
|
|
94
|
+
| **Traditional** | All raw source files | expanded | Reading source directly |
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
// 1. Overview: read entire project structure (cheap, no .ctx)
|
|
98
|
+
get_skeleton({ path: "src/" })
|
|
99
|
+
// → Legend, stats, all classes/functions/exports — ~2-5K tokens
|
|
100
|
+
|
|
101
|
+
// 2. Focus: get enriched context ONLY for area of interest
|
|
102
|
+
get_focus_zone({ recentFiles: ["src/core/parser.js", "src/mcp/tools.js"] })
|
|
103
|
+
// → Compact code + .ctx documentation for just those 2 files
|
|
104
|
+
|
|
105
|
+
// 3. Or auto-detect from git diff
|
|
106
|
+
get_focus_zone({ path: ".", useGitDiff: true })
|
|
107
|
+
// → Context for recently changed files only
|
|
79
108
|
```
|
|
80
109
|
|
|
110
|
+
**Real-world token budget** (45-file project):
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
Traditional (raw sources): 64K tok — read everything expanded
|
|
114
|
+
Overview (compact, no .ctx): 47K tok — 27% savings, full project
|
|
115
|
+
Focus (compact + 3 files ctx): 47.6K tok — same savings + semantic descriptions
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Compact code saves **27% on average** (34-38% for typical files) by stripping whitespace and comments while preserving all names. The `.ctx` cost is **per-file** (~200 tok each) and only loaded for the focus area — the agent gets typed signatures and descriptions that the raw source never had.
|
|
119
|
+
|
|
120
|
+
**Per-file metrics breakdown:**
|
|
121
|
+
|
|
122
|
+
| Layer | What | Tokens |
|
|
123
|
+
|-------|------|--------|
|
|
124
|
+
| Code (compact .js) | Minified source, all names preserved | codeTok |
|
|
125
|
+
| Context (.ctx) | AST signatures, types, descriptions | ctxTok |
|
|
126
|
+
| Total (focus mode) | What agent reads when focusing | codeTok + ctxTok |
|
|
127
|
+
| Expanded (beautified) | What a human would read (raw source) | expanded |
|
|
128
|
+
|
|
81
129
|
### Compact Code Architecture
|
|
82
130
|
|
|
83
131
|
Three modes for AI-native codebase editing — configure per project via `.context/config.json`:
|
|
@@ -119,6 +167,22 @@ npx project-graph-mcp set-mode . 2
|
|
|
119
167
|
npx project-graph-mcp validate-ctx . --strict
|
|
120
168
|
```
|
|
121
169
|
|
|
170
|
+
### Expand & Validate Pipeline
|
|
171
|
+
|
|
172
|
+
The compact→expand pipeline is **fully reversible**. Verify round-trip integrity:
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
// Expand a compact file back to full formatted + JSDoc
|
|
176
|
+
compact({ action: "expand_file", path: "src/parser.js" })
|
|
177
|
+
|
|
178
|
+
// Expand entire project
|
|
179
|
+
compact({ action: "expand_project", path: ".", dryRun: true })
|
|
180
|
+
|
|
181
|
+
// Validate compact ↔ expand round-trip
|
|
182
|
+
compact({ action: "validate_pipeline", path: ".", strict: true })
|
|
183
|
+
// → Reports any functions in source missing from .ctx
|
|
184
|
+
```
|
|
185
|
+
|
|
122
186
|
### Test Checklists
|
|
123
187
|
|
|
124
188
|
Test checklists live in `.ctx.md` files (alongside documentation), not in source code:
|
|
@@ -136,6 +200,47 @@ The agent calls `get_pending_tests`, runs the test, then `mark_test_passed` (whi
|
|
|
136
200
|
|
|
137
201
|
`discover_sub_projects` scans standard monorepo directories (`packages/`, `apps/`, `services/`, `modules/`, `libs/`, `plugins/`) for sub-projects with `package.json`. Combined with `parseProject({ recursive: true })`, agents can analyze entire monorepos.
|
|
138
202
|
|
|
203
|
+
### Database Analysis
|
|
204
|
+
|
|
205
|
+
Scan SQL migrations and code for database schema insights:
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
// Extract schema from SQL/migration files
|
|
209
|
+
db({ action: "schema", path: "src/" })
|
|
210
|
+
|
|
211
|
+
// Find where each table is referenced in code
|
|
212
|
+
db({ action: "table_usage", path: "src/", table: "users" })
|
|
213
|
+
|
|
214
|
+
// Detect tables defined but never queried
|
|
215
|
+
db({ action: "dead_tables", path: "src/" })
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Web Dashboard
|
|
219
|
+
|
|
220
|
+
Every project-graph-mcp instance includes a built-in web UI at `http://localhost:{port}/`:
|
|
221
|
+
|
|
222
|
+
- **Multi-project dashboard** — overview of all registered projects with token metrics
|
|
223
|
+
- **File tree** — navigate project structure
|
|
224
|
+
- **Code viewer** — compact/raw toggle with syntax highlighting and per-file compression stats
|
|
225
|
+
- **Dependency graph** — visual dependency exploration
|
|
226
|
+
- **Health panel** — analysis results
|
|
227
|
+
- **Live monitor** — real-time agent activity via WebSocket
|
|
228
|
+
|
|
229
|
+
With the optional gateway, all projects are accessible under `http://project-graph.local/{project-name}/`.
|
|
230
|
+
|
|
231
|
+
### Compression Metrics
|
|
232
|
+
|
|
233
|
+
Token-level metrics are available project-wide and per-file:
|
|
234
|
+
|
|
235
|
+
```javascript
|
|
236
|
+
// Project-wide: how many tokens for the entire codebase
|
|
237
|
+
// GET /api/compression-stats
|
|
238
|
+
// → { files: 45, codeTok: 47000, ctxTok: 9500, totalTok: 56500 }
|
|
239
|
+
|
|
240
|
+
// Per-file: shown in code viewer header
|
|
241
|
+
// 2054 + 527 ctx = 2581 → 3340 tok (23% savings)
|
|
242
|
+
```
|
|
243
|
+
|
|
139
244
|
### Performance
|
|
140
245
|
|
|
141
246
|
- **Batch concurrency** — `generate_context_docs` processes 5 files in parallel
|
|
@@ -173,6 +278,19 @@ Add to your IDE's MCP configuration:
|
|
|
173
278
|
|
|
174
279
|
Restart your IDE — project-graph-mcp will be downloaded and started automatically.
|
|
175
280
|
|
|
281
|
+
#### Grouped Tools (v2.0)
|
|
282
|
+
|
|
283
|
+
v2.0 uses 18 domain-grouped tools instead of 49 individual endpoints. Grouped tools use an `action` parameter:
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
navigate({ action: "expand", symbol: "MyClass" })
|
|
287
|
+
analyze({ action: "complexity", path: "src/" })
|
|
288
|
+
docs({ action: "generate", path: ".", scope: "focus" })
|
|
289
|
+
compact({ action: "compact_file", path: "src/parser.js" })
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
10 standalone tools (`get_skeleton`, `get_ai_context`, `invalidate_cache`, etc.) remain unchanged.
|
|
293
|
+
|
|
176
294
|
<details>
|
|
177
295
|
<summary>Where is my MCP config file?</summary>
|
|
178
296
|
|
|
@@ -195,7 +313,7 @@ See **[CONFIGURATION.md](CONFIGURATION.md)** for all supported IDEs (Antigravity
|
|
|
195
313
|
git clone https://github.com/rnd-pro/project-graph-mcp
|
|
196
314
|
cd project-graph-mcp
|
|
197
315
|
# No npm install needed — zero dependencies
|
|
198
|
-
# Use "node /path/to/project-graph-mcp/src/server.js" as the command in MCP config
|
|
316
|
+
# Use "node /path/to/project-graph-mcp/src/network/server.js" as the command in MCP config
|
|
199
317
|
```
|
|
200
318
|
|
|
201
319
|
</details>
|
|
@@ -250,8 +368,10 @@ Best used together with [**agent-pool-mcp**](https://www.npmjs.com/package/agent
|
|
|
250
368
|
|
|
251
369
|
- [CONFIGURATION.md](CONFIGURATION.md) — Setup for all supported IDEs
|
|
252
370
|
- [ARCHITECTURE.md](ARCHITECTURE.md) — Source code structure
|
|
253
|
-
- [AGENT_ROLE.md](AGENT_ROLE.md) — Full system prompt for agents
|
|
254
|
-
- [AGENT_ROLE_MINIMAL.md](AGENT_ROLE_MINIMAL.md) — Minimal variant (agent self-discovers)
|
|
371
|
+
- [AGENT_ROLE.md](docs/examples/AGENT_ROLE.md) — Full system prompt for agents
|
|
372
|
+
- [AGENT_ROLE_MINIMAL.md](docs/examples/AGENT_ROLE_MINIMAL.md) — Minimal variant (agent self-discovers)
|
|
373
|
+
- [GUIDE.md](GUIDE.md) — Comprehensive usage guide with all tools
|
|
374
|
+
- [ROADMAP.md](docs/ROADMAP.md) — Feature roadmap and backlog
|
|
255
375
|
|
|
256
376
|
## Related Projects
|
|
257
377
|
- [agent-pool-mcp](https://github.com/rnd-pro/agent-pool-mcp) — Multi-agent orchestration via Gemini CLI
|
package/package.json
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "project-graph-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "MCP server for AI agents —
|
|
6
|
-
"main": "src/server.js",
|
|
5
|
+
"description": "MCP server for AI agents — project graph, code quality analysis, visual web explorer. JS, TS, Python, Go.",
|
|
6
|
+
"main": "src/network/server.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"project-graph-mcp": "src/server.js"
|
|
8
|
+
"project-graph-mcp": "src/network/server.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"src/",
|
|
12
|
+
"web/",
|
|
12
13
|
"vendor/",
|
|
13
14
|
"rules/",
|
|
14
|
-
"
|
|
15
|
-
"AGENT_ROLE.md",
|
|
16
|
-
"AGENT_ROLE_MINIMAL.md",
|
|
15
|
+
"docs/",
|
|
17
16
|
"CONFIGURATION.md",
|
|
18
17
|
"README.md",
|
|
19
18
|
"LICENSE"
|
|
20
19
|
],
|
|
21
20
|
"scripts": {
|
|
22
|
-
"start": "node src/server.js",
|
|
21
|
+
"start": "node src/network/server.js",
|
|
23
22
|
"test": "node --test tests/*.test.js"
|
|
24
23
|
},
|
|
25
24
|
"keywords": [
|
|
@@ -45,6 +44,11 @@
|
|
|
45
44
|
"author": "RND-PRO",
|
|
46
45
|
"homepage": "https://github.com/rnd-pro/project-graph-mcp",
|
|
47
46
|
"license": "MIT",
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@symbiotejs/symbiote": "^3.2.1",
|
|
49
|
+
"symbiote-node": "^0.2.0",
|
|
50
|
+
"ws": "^8.20.0"
|
|
51
|
+
},
|
|
48
52
|
"engines": {
|
|
49
53
|
"node": ">=18.0.0"
|
|
50
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":1,"path":"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src","mtimes":{"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/ai-context.js":1775705820005.593,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis-cache.js":1775705820005.9824,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/cli-handlers.js":1775742844572.4338,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/cli.js":1775742927037.4722,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact.js":1775705820007.682,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/complexity.js":1775705820008.1265,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compress.js":1775708193583.2522,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/ctx-to-jsdoc.js":1775742405151.9907,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/custom-rules.js":1775705820009.4775,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/db-analysis.js":1775705820010.2769,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/dead-code.js":1775705820010.873,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/doc-dialect.js":1775707208614.9092,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/filters.js":1775705820011.479,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/framework-references.js":1775705820011.642,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/full-analysis.js":1775705820012.3645,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/graph-builder.js":1775705820012.8542,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/instructions.js":1775705820013.5242,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/jsdoc-checker.js":1775705820013.9524,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/jsdoc-generator.js":1775705820014.3755,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang-go.js":1775705820014.5596,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang-python.js":1775705820014.7178,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang-sql.js":1775705820015.08,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang-typescript.js":1775705820015.259,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang-utils.js":1775705820015.4016,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/large-files.js":1775705820015.7256,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/mcp-server.js":1775742958113.3992,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/mode-config.js":1775708353549.937,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/outdated-patterns.js":1775705820016.414,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/parser.js":1775707186671.276,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/server.js":1775705820017.2703,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/similar-functions.js":1775705820017.9243,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/test-annotations.js":1775705820018.533,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/tool-defs.js":1775708400999.8848,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/tools.js":1775705820019.4646,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/type-checker.js":1775705820019.783,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/undocumented.js":1775705820020.2156,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/workspace.js":1775705820020.5132},"graph":{"v":1,"legend":{"estimateTokens":"eT","getAiContext":"AC","computeSig":"cS","computeContentHash":"CH","getCachePath":"CP","readCache":"rC","writeCache":"wC","isCacheValid":"CV","invalidateAllCaches":"AC1","getArg":"gA","getPath":"gP","printHelp":"pH","runCLI":"CLI","walkJSFiles":"JSF","compactFile":"cF","beautifyFile":"bF","compactProject":"cP","expandProject":"eP","findJSFiles":"JSF1","calculateComplexity":"cC","getRating":"gR","analyzeComplexityFile":"CF","analyzeFile":"aF","getComplexity":"gC","extractLegend":"eL","compressFile":"cF1","editCompressed":"eC","findSymbolRange":"SR","parseCtxFile":"CF1","buildJSDocBlock":"JSD","findCtxFile":"CF2","findExportStart":"ES","injectJSDoc":"JSD1","stripJSDoc":"JSD2","splitTopLevelParams":"TLP","validateCtxContracts":"CC","parseGraphignore":"pG","isGraphignored":"iG","loadRuleSets":"RS","saveRuleSet":"RS1","findFiles":"fF","isExcluded":"iE","isInStringOrComment":"ISO","isWithinContext":"WC","checkFileAgainstRule":"FAR","getCustomRules":"CR","setCustomRule":"CR1","deleteCustomRule":"CR2","detectProjectRuleSets":"PRS","checkCustomRules":"CR3","getDBSchema":"DBS","getTableUsage":"TU","getDBDeadTables":"DBD","collectReferencedColumns":"RC","findProjectRoot":"PR","analyzeFileLocals":"FL","getDeadCode":"DC","generateDocDialect":"DD","walkCtxFiles":"CF3","resolveCtxPath":"CP1","resolveCtxMdPath":"CMP","readContextDocs":"CD","getProjectDocs":"PD","computeSignature":"cS1","parseCtxDescriptions":"CD1","checkStaleness":"cS2","buildFileTemplate":"FT","generateContextFiles":"CF4","processFileCtx":"FC","getFilters":"gF","setFilters":"sF","addExcludes":"aE","removeExcludes":"rE","resetFilters":"rF","parseGitignore":"pG1","shouldExcludeDir":"ED","shouldExcludeFile":"EF","matchWildcard":"mW","matchGitignorePattern":"GP","fetchReference":"fR","listAvailable":"lA","getFrameworkReference":"FR","calculateHealthScore":"HS","runCacheableAnalyses":"CA","aggregateComplexity":"aC","aggregateUndocumented":"aU","aggregateJSDoc":"JSD3","getFullAnalysis":"FA","getAnalysisSummaryOnly":"ASO","getFullAnalysisStreaming":"FAS","minifyLegend":"mL","createShortName":"SN","buildGraph":"bG","createSkeleton":"cS3","getInstructions":"gI","extractJSDocComments":"JSD4","findJSDocBefore":"JSD5","extractParamName":"PN","inferTypeFromDefault":"TFD","hasReturnValue":"RV","validateFunction":"vF","checkJSDocFile":"JSD6","checkJSDocConsistency":"JSD7","generateJSDoc":"JSD8","buildJSDoc":"JSD9","inferParamType":"PT","generateJSDocFor":"JSD10","parseGo":"pG2","extractImports":"eI","getBody":"gB","extractCalls":"eC1","parsePython":"pP","isSQLString":"SQL","isValidTableName":"VTN","extractSQLFromString":"SQL1","parseSQL":"SQL2","parseColumns":"pC","splitByTopLevelComma":"BTL","extractSQLFromCode":"SQL3","parseTypeScript":"TS","extractParams":"eP1","stripStringsAndComments":"SAC","getLargeFiles":"LF","createServer":"cS4","startStdioServer":"SS","getConfig":"gC1","setConfig":"sC","getModeDescription":"MD","getModeWorkflow":"MW","analyzeFilePatterns":"FP","analyzePackageJson":"PJ","getOutdatedPatterns":"OP","parseFile":"pF","extractCallsAndSQL":"CAS","getTagName":"TN","getCallMethodName":"CMN","extractStringValue":"SV","templateToString":"TS1","discoverSubProjects":"SP","parseProject":"pP1","parseFileByExtension":"FBE","isSourceFile":"SF","buildJSDocTypeMap":"JSD11","findJSDocForNode":"JSD12","enrichParamsWithTypes":"PWT","extractSignatures":"eS","buildSignature":"bS","hashBodyStructure":"BS","calculateSimilarity":"cS5","getSimilarFunctions":"SF1","findCtxMdFiles":"CMF","parseAnnotations":"pA","groupByName":"BN","getAllFeatures":"AF","getPendingTests":"PT1","markTestPassed":"TP","markTestFailed":"TF","updateTestState":"TS2","getTestSummary":"TS3","resetTestState":"TS4","saveDiskCache":"DC1","loadDiskCache":"DC2","getGraph":"gG","detectChanges":"dC","snapshotMtimes":"sM","getSkeleton":"gS","getFocusZone":"FZ","expand":"ex","deps":"de","usages":"us","extractMethod":"eM","getCallChain":"CC1","invalidateCache":"iC","detectTsc":"dT","parseDiagnosticLine":"DL","buildArgs":"bA","checkTypes":"cT","extractComments":"eC2","checkMissing":"cM","checkUndocumentedFile":"UF","getUndocumented":"gU","getUndocumentedSummary":"US","setRoots":"sR","getWorkspaceRoot":"WR","resolvePath":"rP"},"reverseLegend":{"eT":"estimateTokens","AC":"getAiContext","cS":"computeSig","CH":"computeContentHash","CP":"getCachePath","rC":"readCache","wC":"writeCache","CV":"isCacheValid","AC1":"invalidateAllCaches","gA":"getArg","gP":"getPath","pH":"printHelp","CLI":"runCLI","JSF":"walkJSFiles","cF":"compactFile","bF":"beautifyFile","cP":"compactProject","eP":"expandProject","JSF1":"findJSFiles","cC":"calculateComplexity","gR":"getRating","CF":"analyzeComplexityFile","aF":"analyzeFile","gC":"getComplexity","eL":"extractLegend","cF1":"compressFile","eC":"editCompressed","SR":"findSymbolRange","CF1":"parseCtxFile","JSD":"buildJSDocBlock","CF2":"findCtxFile","ES":"findExportStart","JSD1":"injectJSDoc","JSD2":"stripJSDoc","TLP":"splitTopLevelParams","CC":"validateCtxContracts","pG":"parseGraphignore","iG":"isGraphignored","RS":"loadRuleSets","RS1":"saveRuleSet","fF":"findFiles","iE":"isExcluded","ISO":"isInStringOrComment","WC":"isWithinContext","FAR":"checkFileAgainstRule","CR":"getCustomRules","CR1":"setCustomRule","CR2":"deleteCustomRule","PRS":"detectProjectRuleSets","CR3":"checkCustomRules","DBS":"getDBSchema","TU":"getTableUsage","DBD":"getDBDeadTables","RC":"collectReferencedColumns","PR":"findProjectRoot","FL":"analyzeFileLocals","DC":"getDeadCode","DD":"generateDocDialect","CF3":"walkCtxFiles","CP1":"resolveCtxPath","CMP":"resolveCtxMdPath","CD":"readContextDocs","PD":"getProjectDocs","cS1":"computeSignature","CD1":"parseCtxDescriptions","cS2":"checkStaleness","FT":"buildFileTemplate","CF4":"generateContextFiles","FC":"processFileCtx","gF":"getFilters","sF":"setFilters","aE":"addExcludes","rE":"removeExcludes","rF":"resetFilters","pG1":"parseGitignore","ED":"shouldExcludeDir","EF":"shouldExcludeFile","mW":"matchWildcard","GP":"matchGitignorePattern","fR":"fetchReference","lA":"listAvailable","FR":"getFrameworkReference","HS":"calculateHealthScore","CA":"runCacheableAnalyses","aC":"aggregateComplexity","aU":"aggregateUndocumented","JSD3":"aggregateJSDoc","FA":"getFullAnalysis","ASO":"getAnalysisSummaryOnly","FAS":"getFullAnalysisStreaming","mL":"minifyLegend","SN":"createShortName","bG":"buildGraph","cS3":"createSkeleton","gI":"getInstructions","JSD4":"extractJSDocComments","JSD5":"findJSDocBefore","PN":"extractParamName","TFD":"inferTypeFromDefault","RV":"hasReturnValue","vF":"validateFunction","JSD6":"checkJSDocFile","JSD7":"checkJSDocConsistency","JSD8":"generateJSDoc","JSD9":"buildJSDoc","PT":"inferParamType","JSD10":"generateJSDocFor","pG2":"parseGo","eI":"extractImports","gB":"getBody","eC1":"extractCalls","pP":"parsePython","SQL":"isSQLString","VTN":"isValidTableName","SQL1":"extractSQLFromString","SQL2":"parseSQL","pC":"parseColumns","BTL":"splitByTopLevelComma","SQL3":"extractSQLFromCode","TS":"parseTypeScript","eP1":"extractParams","SAC":"stripStringsAndComments","LF":"getLargeFiles","cS4":"createServer","SS":"startStdioServer","gC1":"getConfig","sC":"setConfig","MD":"getModeDescription","MW":"getModeWorkflow","FP":"analyzeFilePatterns","PJ":"analyzePackageJson","OP":"getOutdatedPatterns","pF":"parseFile","CAS":"extractCallsAndSQL","TN":"getTagName","CMN":"getCallMethodName","SV":"extractStringValue","TS1":"templateToString","SP":"discoverSubProjects","pP1":"parseProject","FBE":"parseFileByExtension","SF":"isSourceFile","JSD11":"buildJSDocTypeMap","JSD12":"findJSDocForNode","PWT":"enrichParamsWithTypes","eS":"extractSignatures","bS":"buildSignature","BS":"hashBodyStructure","cS5":"calculateSimilarity","SF1":"getSimilarFunctions","CMF":"findCtxMdFiles","pA":"parseAnnotations","BN":"groupByName","AF":"getAllFeatures","PT1":"getPendingTests","TP":"markTestPassed","TF":"markTestFailed","TS2":"updateTestState","TS3":"getTestSummary","TS4":"resetTestState","DC1":"saveDiskCache","DC2":"loadDiskCache","gG":"getGraph","dC":"detectChanges","sM":"snapshotMtimes","gS":"getSkeleton","FZ":"getFocusZone","ex":"expand","de":"deps","us":"usages","eM":"extractMethod","CC1":"getCallChain","iC":"invalidateCache","dT":"detectTsc","DL":"parseDiagnosticLine","bA":"buildArgs","cT":"checkTypes","eC2":"extractComments","cM":"checkMissing","UF":"checkUndocumentedFile","gU":"getUndocumented","US":"getUndocumentedSummary","sR":"setRoots","WR":"getWorkspaceRoot","rP":"resolvePath"},"stats":{"files":37,"classes":0,"functions":200,"tables":0},"nodes":{"eT":{"t":"F","e":false,"f":"compress.js"},"AC":{"t":"F","e":true,"f":"ai-context.js"},"cS":{"t":"F","e":true,"f":"analysis-cache.js"},"CH":{"t":"F","e":true,"f":"analysis-cache.js"},"CP":{"t":"F","e":true,"f":"analysis-cache.js"},"rC":{"t":"F","e":true,"f":"analysis-cache.js"},"wC":{"t":"F","e":true,"f":"analysis-cache.js"},"CV":{"t":"F","e":true,"f":"analysis-cache.js"},"AC1":{"t":"F","e":true,"f":"analysis-cache.js"},"gA":{"t":"F","e":false,"f":"cli-handlers.js"},"gP":{"t":"F","e":false,"f":"cli-handlers.js"},"pH":{"t":"F","e":true,"f":"cli.js"},"CLI":{"t":"F","e":true,"f":"cli.js"},"JSF":{"t":"F","e":false,"f":"ctx-to-jsdoc.js"},"cF":{"t":"F","e":false,"f":"compact.js"},"bF":{"t":"F","e":false,"f":"compact.js"},"cP":{"t":"F","e":true,"f":"compact.js"},"eP":{"t":"F","e":true,"f":"compact.js"},"JSF1":{"t":"F","e":false,"f":"undocumented.js"},"cC":{"t":"F","e":false,"f":"complexity.js"},"gR":{"t":"F","e":false,"f":"complexity.js"},"CF":{"t":"F","e":true,"f":"complexity.js"},"aF":{"t":"F","e":false,"f":"large-files.js"},"gC":{"t":"F","e":true,"f":"complexity.js"},"eL":{"t":"F","e":false,"f":"compress.js"},"cF1":{"t":"F","e":true,"f":"compress.js"},"eC":{"t":"F","e":true,"f":"compress.js"},"SR":{"t":"F","e":false,"f":"compress.js"},"CF1":{"t":"F","e":true,"f":"ctx-to-jsdoc.js"},"JSD":{"t":"F","e":false,"f":"ctx-to-jsdoc.js"},"CF2":{"t":"F","e":false,"f":"ctx-to-jsdoc.js"},"ES":{"t":"F","e":false,"f":"ctx-to-jsdoc.js"},"JSD1":{"t":"F","e":true,"f":"ctx-to-jsdoc.js"},"JSD2":{"t":"F","e":true,"f":"ctx-to-jsdoc.js"},"TLP":{"t":"F","e":false,"f":"ctx-to-jsdoc.js"},"CC":{"t":"F","e":true,"f":"ctx-to-jsdoc.js"},"pG":{"t":"F","e":false,"f":"custom-rules.js"},"iG":{"t":"F","e":false,"f":"custom-rules.js"},"RS":{"t":"F","e":false,"f":"custom-rules.js"},"RS1":{"t":"F","e":false,"f":"custom-rules.js"},"fF":{"t":"F","e":false,"f":"custom-rules.js"},"iE":{"t":"F","e":false,"f":"custom-rules.js"},"ISO":{"t":"F","e":false,"f":"custom-rules.js"},"WC":{"t":"F","e":false,"f":"custom-rules.js"},"FAR":{"t":"F","e":false,"f":"custom-rules.js"},"CR":{"t":"F","e":true,"f":"custom-rules.js"},"CR1":{"t":"F","e":true,"f":"custom-rules.js"},"CR2":{"t":"F","e":true,"f":"custom-rules.js"},"PRS":{"t":"F","e":true,"f":"custom-rules.js"},"CR3":{"t":"F","e":true,"f":"custom-rules.js"},"DBS":{"t":"F","e":true,"f":"db-analysis.js"},"TU":{"t":"F","e":true,"f":"db-analysis.js"},"DBD":{"t":"F","e":true,"f":"db-analysis.js"},"RC":{"t":"F","e":false,"f":"db-analysis.js"},"PR":{"t":"F","e":false,"f":"dead-code.js"},"FL":{"t":"F","e":false,"f":"dead-code.js"},"DC":{"t":"F","e":true,"f":"dead-code.js"},"DD":{"t":"F","e":true,"f":"doc-dialect.js"},"CF3":{"t":"F","e":false,"f":"doc-dialect.js"},"CP1":{"t":"F","e":false,"f":"doc-dialect.js"},"CMP":{"t":"F","e":false,"f":"doc-dialect.js"},"CD":{"t":"F","e":true,"f":"doc-dialect.js"},"PD":{"t":"F","e":true,"f":"doc-dialect.js"},"cS1":{"t":"F","e":false,"f":"doc-dialect.js"},"CD1":{"t":"F","e":false,"f":"doc-dialect.js"},"cS2":{"t":"F","e":true,"f":"doc-dialect.js"},"FT":{"t":"F","e":false,"f":"doc-dialect.js"},"CF4":{"t":"F","e":true,"f":"doc-dialect.js"},"FC":{"t":"F","e":false,"f":"doc-dialect.js"},"gF":{"t":"F","e":true,"f":"filters.js"},"sF":{"t":"F","e":true,"f":"filters.js"},"aE":{"t":"F","e":true,"f":"filters.js"},"rE":{"t":"F","e":true,"f":"filters.js"},"rF":{"t":"F","e":true,"f":"filters.js"},"pG1":{"t":"F","e":true,"f":"filters.js"},"ED":{"t":"F","e":true,"f":"filters.js"},"EF":{"t":"F","e":true,"f":"filters.js"},"mW":{"t":"F","e":false,"f":"filters.js"},"GP":{"t":"F","e":false,"f":"filters.js"},"fR":{"t":"F","e":false,"f":"framework-references.js"},"lA":{"t":"F","e":false,"f":"framework-references.js"},"FR":{"t":"F","e":true,"f":"framework-references.js"},"HS":{"t":"F","e":false,"f":"full-analysis.js"},"CA":{"t":"F","e":false,"f":"full-analysis.js"},"aC":{"t":"F","e":false,"f":"full-analysis.js"},"aU":{"t":"F","e":false,"f":"full-analysis.js"},"JSD3":{"t":"F","e":false,"f":"full-analysis.js"},"FA":{"t":"F","e":true,"f":"full-analysis.js"},"ASO":{"t":"F","e":true,"f":"full-analysis.js"},"FAS":{"t":"F","e":true,"f":"full-analysis.js"},"mL":{"t":"F","e":true,"f":"graph-builder.js"},"SN":{"t":"F","e":false,"f":"graph-builder.js"},"bG":{"t":"F","e":true,"f":"graph-builder.js"},"cS3":{"t":"F","e":true,"f":"graph-builder.js"},"gI":{"t":"F","e":true,"f":"instructions.js"},"JSD4":{"t":"F","e":false,"f":"jsdoc-checker.js"},"JSD5":{"t":"F","e":false,"f":"undocumented.js"},"PN":{"t":"F","e":false,"f":"similar-functions.js"},"TFD":{"t":"F","e":false,"f":"jsdoc-checker.js"},"RV":{"t":"F","e":false,"f":"jsdoc-checker.js"},"vF":{"t":"F","e":false,"f":"jsdoc-checker.js"},"JSD6":{"t":"F","e":true,"f":"jsdoc-checker.js"},"JSD7":{"t":"F","e":true,"f":"jsdoc-checker.js"},"JSD8":{"t":"F","e":true,"f":"jsdoc-generator.js"},"JSD9":{"t":"F","e":false,"f":"jsdoc-generator.js"},"PT":{"t":"F","e":false,"f":"jsdoc-generator.js"},"JSD10":{"t":"F","e":true,"f":"jsdoc-generator.js"},"pG2":{"t":"F","e":true,"f":"lang-go.js"},"eI":{"t":"F","e":false,"f":"lang-go.js"},"gB":{"t":"F","e":false,"f":"lang-go.js"},"eC1":{"t":"F","e":false,"f":"lang-go.js"},"pP":{"t":"F","e":true,"f":"lang-python.js"},"SQL":{"t":"F","e":true,"f":"lang-sql.js"},"VTN":{"t":"F","e":false,"f":"lang-sql.js"},"SQL1":{"t":"F","e":true,"f":"lang-sql.js"},"SQL2":{"t":"F","e":true,"f":"lang-sql.js"},"pC":{"t":"F","e":false,"f":"lang-sql.js"},"BTL":{"t":"F","e":false,"f":"lang-sql.js"},"SQL3":{"t":"F","e":true,"f":"lang-sql.js"},"TS":{"t":"F","e":true,"f":"lang-typescript.js"},"eP1":{"t":"F","e":false,"f":"lang-typescript.js"},"SAC":{"t":"F","e":true,"f":"lang-utils.js"},"LF":{"t":"F","e":true,"f":"large-files.js"},"cS4":{"t":"F","e":true,"f":"mcp-server.js"},"SS":{"t":"F","e":true,"f":"mcp-server.js"},"gC1":{"t":"F","e":true,"f":"mode-config.js"},"sC":{"t":"F","e":true,"f":"mode-config.js"},"MD":{"t":"F","e":true,"f":"mode-config.js"},"MW":{"t":"F","e":true,"f":"mode-config.js"},"FP":{"t":"F","e":false,"f":"outdated-patterns.js"},"PJ":{"t":"F","e":false,"f":"outdated-patterns.js"},"OP":{"t":"F","e":true,"f":"outdated-patterns.js"},"pF":{"t":"F","e":true,"f":"parser.js"},"CAS":{"t":"F","e":false,"f":"parser.js"},"TN":{"t":"F","e":false,"f":"parser.js"},"CMN":{"t":"F","e":false,"f":"parser.js"},"SV":{"t":"F","e":false,"f":"parser.js"},"TS1":{"t":"F","e":false,"f":"parser.js"},"SP":{"t":"F","e":true,"f":"parser.js"},"pP1":{"t":"F","e":true,"f":"parser.js"},"FBE":{"t":"F","e":false,"f":"parser.js"},"SF":{"t":"F","e":false,"f":"parser.js"},"JSD11":{"t":"F","e":false,"f":"parser.js"},"JSD12":{"t":"F","e":false,"f":"parser.js"},"PWT":{"t":"F","e":false,"f":"parser.js"},"eS":{"t":"F","e":false,"f":"similar-functions.js"},"bS":{"t":"F","e":false,"f":"similar-functions.js"},"BS":{"t":"F","e":false,"f":"similar-functions.js"},"cS5":{"t":"F","e":false,"f":"similar-functions.js"},"SF1":{"t":"F","e":true,"f":"similar-functions.js"},"CMF":{"t":"F","e":false,"f":"test-annotations.js"},"pA":{"t":"F","e":true,"f":"test-annotations.js"},"BN":{"t":"F","e":false,"f":"test-annotations.js"},"AF":{"t":"F","e":true,"f":"test-annotations.js"},"PT1":{"t":"F","e":true,"f":"test-annotations.js"},"TP":{"t":"F","e":true,"f":"test-annotations.js"},"TF":{"t":"F","e":true,"f":"test-annotations.js"},"TS2":{"t":"F","e":false,"f":"test-annotations.js"},"TS3":{"t":"F","e":true,"f":"test-annotations.js"},"TS4":{"t":"F","e":true,"f":"test-annotations.js"},"DC1":{"t":"F","e":false,"f":"tools.js"},"DC2":{"t":"F","e":false,"f":"tools.js"},"gG":{"t":"F","e":true,"f":"tools.js"},"dC":{"t":"F","e":false,"f":"tools.js"},"sM":{"t":"F","e":false,"f":"tools.js"},"gS":{"t":"F","e":true,"f":"tools.js"},"FZ":{"t":"F","e":true,"f":"tools.js"},"ex":{"t":"F","e":true,"f":"tools.js"},"de":{"t":"F","e":true,"f":"tools.js"},"us":{"t":"F","e":true,"f":"tools.js"},"eM":{"t":"F","e":false,"f":"tools.js"},"CC1":{"t":"F","e":true,"f":"tools.js"},"iC":{"t":"F","e":true,"f":"tools.js"},"dT":{"t":"F","e":false,"f":"type-checker.js"},"DL":{"t":"F","e":false,"f":"type-checker.js"},"bA":{"t":"F","e":false,"f":"type-checker.js"},"cT":{"t":"F","e":true,"f":"type-checker.js"},"eC2":{"t":"F","e":false,"f":"undocumented.js"},"cM":{"t":"F","e":false,"f":"undocumented.js"},"UF":{"t":"F","e":true,"f":"undocumented.js"},"gU":{"t":"F","e":true,"f":"undocumented.js"},"US":{"t":"F","e":true,"f":"undocumented.js"},"sR":{"t":"F","e":true,"f":"workspace.js"},"WR":{"t":"F","e":true,"f":"workspace.js"},"rP":{"t":"F","e":true,"f":"workspace.js"}},"edges":[],"orphans":["estimateTokens","getArg","getPath","walkJSFiles","compactFile","beautifyFile","findJSFiles","calculateComplexity","getRating","analyzeFile","extractLegend","findSymbolRange","buildJSDocBlock","findCtxFile","findExportStart","splitTopLevelParams","parseGraphignore","isGraphignored","loadRuleSets","saveRuleSet","findFiles","isExcluded","isInStringOrComment","isWithinContext","checkFileAgainstRule","collectReferencedColumns","findProjectRoot","analyzeFileLocals","walkCtxFiles","resolveCtxPath","resolveCtxMdPath","computeSignature","parseCtxDescriptions","buildFileTemplate","processFileCtx","matchWildcard","matchGitignorePattern","fetchReference","listAvailable","calculateHealthScore","runCacheableAnalyses","aggregateComplexity","aggregateUndocumented","aggregateJSDoc","createShortName","extractJSDocComments","findJSDocBefore","extractParamName","inferTypeFromDefault","hasReturnValue","validateFunction","buildJSDoc","inferParamType","extractImports","getBody","extractCalls","isValidTableName","parseColumns","splitByTopLevelComma","extractParams","analyzeFilePatterns","analyzePackageJson","extractCallsAndSQL","getTagName","getCallMethodName","extractStringValue","templateToString","parseFileByExtension","isSourceFile","buildJSDocTypeMap","findJSDocForNode","enrichParamsWithTypes","extractSignatures","buildSignature","hashBodyStructure","calculateSimilarity","findCtxMdFiles","groupByName","updateTestState","saveDiskCache","loadDiskCache","detectChanges","snapshotMtimes","extractMethod","detectTsc","parseDiagnosticLine","buildArgs","extractComments","checkMissing"],"duplicates":{},"files":["ai-context.js","analysis-cache.js","cli-handlers.js","cli.js","compact.js","complexity.js","compress.js","ctx-to-jsdoc.js","custom-rules.js","db-analysis.js","dead-code.js","doc-dialect.js","filters.js","framework-references.js","full-analysis.js","graph-builder.js","instructions.js","jsdoc-checker.js","jsdoc-generator.js","lang-go.js","lang-python.js","lang-sql.js","lang-typescript.js","lang-utils.js","large-files.js","mcp-server.js","mode-config.js","outdated-patterns.js","parser.js","server.js","similar-functions.js","test-annotations.js","tool-defs.js","tools.js","type-checker.js","undocumented.js","workspace.js"]}}
|
|
1
|
+
{"version":1,"path":"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src","mtimes":{"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/analysis-cache.js":1775932068076.741,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/complexity.js":1775932068098.837,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/custom-rules.js":1775932068138.1648,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/db-analysis.js":1775932068151.1123,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/dead-code.js":1775932068179.2783,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/full-analysis.js":1775932068199.422,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/jsdoc-checker.js":1775932068214.1042,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/jsdoc-generator.js":1775932068226.255,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/large-files.js":1775932068231.2554,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/outdated-patterns.js":1775932068241.3853,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/similar-functions.js":1775932068258.163,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/test-annotations.js":1775932068268.5154,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/type-checker.js":1775932068273.1277,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/analysis/undocumented.js":1775932068287.6243,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/cli/cli-handlers.js":1775932068298.3313,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/cli/cli.js":1775932068300.5159,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/ai-context.js":1775932068307.1665,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/compact.js":1775932562256.5852,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/compress.js":1775932068329.118,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/ctx-to-jsdoc.js":1775932068348.9448,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/doc-dialect.js":1775932068402.0254,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/expand.js":1775932068432.0977,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/framework-references.js":1775932068436.373,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/instructions.js":1775932068437.6816,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/mode-config.js":1775932068441.0076,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/compact/validate-pipeline.js":1775932068445.2222,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/core/event-bus.js":1775932068446.521,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/core/filters.js":1775932068453.1003,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/core/graph-builder.js":1775932068467.494,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/core/parser.js":1775932068524.0032,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/core/workspace.js":1775932068530.74,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang/lang-go.js":1775932068546.679,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang/lang-python.js":1775932068554.9434,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang/lang-sql.js":1775932068573.637,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang/lang-typescript.js":1775932068582.2983,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/lang/lang-utils.js":1775932068585.4934,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/mcp/mcp-server.js":1775932068611.3706,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/mcp/tool-defs.js":1775932068615.0066,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/mcp/tools.js":1775932068628.6646,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/network/backend-lifecycle.js":1775932068638.9226,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/network/backend.js":1775932249992.6167,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/network/local-gateway.js":1775932068657.378,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/network/mdns.js":1775932068663.7195,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/network/server.js":1775932211325.8235,"/Users/v.matiyasevich/Documents/GitHub/project-graph-mcp/src/network/web-server.js":1775937659045.6243},"graph":{"v":1,"legend":{"computeContentHash":"CH","getCachePath":"CP","readCache":"rC","writeCache":"wC","isCacheValid":"CV","findJSFiles":"JSF","calculateComplexity":"cC","getRating":"gR","analyzeComplexityFile":"CF","analyzeFile":"aF","getComplexity":"gC","parseGraphignore":"pG","isGraphignored":"iG","loadRuleSets":"RS","saveRuleSet":"RS1","findFiles":"fF","isExcluded":"iE","isInStringOrComment":"ISO","isWithinContext":"WC","checkFileAgainstRule":"FAR","getCustomRules":"CR","setCustomRule":"CR1","deleteCustomRule":"CR2","detectProjectRuleSets":"PRS","checkCustomRules":"CR3","getDBSchema":"DBS","getTableUsage":"TU","getDBDeadTables":"DBD","collectReferencedColumns":"RC","findProjectRoot":"PR","analyzeFileLocals":"FL","getDeadCode":"DC","calculateHealthScore":"HS","runCacheableAnalyses":"CA","aggregateComplexity":"aC","aggregateUndocumented":"aU","aggregateJSDoc":"JSD","getFullAnalysis":"FA","getAnalysisSummaryOnly":"ASO","extractJSDocComments":"JSD1","findJSDocBefore":"JSD2","extractParamName":"PN","inferTypeFromDefault":"TFD","hasReturnValue":"RV","validateFunction":"vF","checkJSDocFile":"JSD3","checkJSDocConsistency":"JSD4","generateJSDoc":"JSD5","buildJSDoc":"JSD6","inferParamType":"PT","generateJSDocFor":"JSD7","getLargeFiles":"LF","analyzeFilePatterns":"FP","analyzePackageJson":"PJ","getOutdatedPatterns":"OP","extractSignatures":"eS","buildSignature":"bS","hashBodyStructure":"BS","calculateSimilarity":"cS","getSimilarFunctions":"SF","findCtxMdFiles":"CMF","parseAnnotations":"pA","groupByName":"BN","getAllFeatures":"AF","getPendingTests":"PT1","markTestPassed":"TP","markTestFailed":"TF","updateTestState":"TS","getTestSummary":"TS1","resetTestState":"TS2","detectTsc":"dT","parseDiagnosticLine":"DL","buildArgs":"bA","checkTypes":"cT","extractComments":"eC","checkMissing":"cM","checkUndocumentedFile":"UF","getUndocumented":"gU","getUndocumentedSummary":"US","getArg":"gA","getPath":"gP","printHelp":"pH","runCLI":"CLI","estimateTokens":"eT","getAiContext":"AC","walkJSFiles":"JSF1","addTopLevelNewlines":"TLN","resolveCtxPath":"CP1","compactFile":"cF","beautifyFile":"bF","compactProject":"cP","expandProject":"eP","extractLegend":"eL","compressFile":"cF1","editCompressed":"eC1","findSymbolRange":"SR","parseCtxFile":"CF1","buildJSDocBlock":"JSD8","findCtxFile":"CF2","findExportStart":"ES","injectJSDoc":"JSD9","stripJSDoc":"JSD10","splitTopLevelParams":"TLP","validateCtxContracts":"CC","generateDocDialect":"DD","walkCtxFiles":"CF3","resolveCtxMdPath":"CMP","readContextDocs":"CD","getProjectDocs":"PD","computeSignature":"cS1","parseCtxDescriptions":"CD1","checkStaleness":"cS2","buildFileTemplate":"FT","generateContextFiles":"CF4","processFileCtx":"FC","parseCtxSignatures":"CS","parseCtxParams":"CP2","extractReturnType":"RT","sanitizeJSDocText":"JSD11","parseCtxVars":"CV1","parseCtxNames":"CN","collectLocals":"cL","collectLocalDecls":"LD","restoreNames":"rN","expandFile":"eF","resolveCtx":"rC1","fetchReference":"fR","listAvailable":"lA","getFrameworkReference":"FR","getInstructions":"gI","getConfig":"gC1","setConfig":"sC","getModeDescription":"MD","getModeWorkflow":"MW","validatePipeline":"vP","emitToolCall":"TC","emitToolResult":"TR","onToolCall":"TC1","onToolResult":"TR1","removeToolListener":"TL","getFilters":"gF","setFilters":"sF","addExcludes":"aE","removeExcludes":"rE","resetFilters":"rF","parseGitignore":"pG1","shouldExcludeDir":"ED","shouldExcludeFile":"EF","matchWildcard":"mW","matchGitignorePattern":"GP","minifyLegend":"mL","createShortName":"SN","buildGraph":"bG","createSkeleton":"cS3","parseFile":"pF","extractCallsAndSQL":"CAS","getTagName":"TN","getCallMethodName":"CMN","extractStringValue":"SV","templateToString":"TS3","discoverSubProjects":"SP","parseProject":"pP","parseFileByExtension":"FBE","isSourceFile":"SF1","findAllProjectFiles":"APF","buildJSDocTypeMap":"JSD12","findJSDocForNode":"JSD13","enrichParamsWithTypes":"PWT","setRoots":"sR","getWorkspaceRoot":"WR","resolvePath":"rP","parseGo":"pG2","extractImports":"eI","getBody":"gB","extractCalls":"eC2","parsePython":"pP1","isSQLString":"SQL","isValidTableName":"VTN","extractSQLFromString":"SQL1","parseSQL":"SQL2","parseColumns":"pC","splitByTopLevelComma":"BTL","extractSQLFromCode":"SQL3","extractORMFromCode":"ORM","parseTypeScript":"TS4","extractParams":"eP1","stripStringsAndComments":"SAC","createServer":"cS4","startStdioServer":"SS","saveDiskCache":"DC1","loadDiskCache":"DC2","getGraph":"gG","detectChanges":"dC","snapshotMtimes":"sM","getSkeleton":"gS","getFocusZone":"FZ","expand":"ex","deps":"de","usages":"us","extractMethod":"eM","getCallChain":"CC1","invalidateCache":"iC","getPortFilePath":"PFP","readPortFile":"PF","writePortFile":"PF1","removePortFile":"PF2","listBackends":"lB","ensureBackend":"eB","encodeClientFrame":"CF5","decodeFrame":"dF","startStdioProxy":"SP1","cleanup":"cl","readRegistry":"rR","writeRegistry":"wR","registerService":"rS","resolveBackend":"rB","readGatewayPid":"GP1","isGatewayRunning":"GR","getGatewayPort":"GP2","startListening":"sL","ensureGateway":"eG","stopGateway":"sG","registerLocal":"rL","registerDnsSd":"DS","tryAvahi":"tA","registerMcast":"rM","serveStatic":"sS","computeWSAccept":"WSA","encodeWSFrame":"WSF","decodeWSFrame":"WSF1","broadcastRPC":"RPC","patchState":"pS","ensureSkeleton":"eS1","hasActiveClients":"AC1","resetShutdownTimer":"ST","startShutdownTimer":"ST1","touchActivity":"tA1","handleAPI":"API","startWebServer":"WS"},"reverseLegend":{"CH":"computeContentHash","CP":"getCachePath","rC":"readCache","wC":"writeCache","CV":"isCacheValid","JSF":"findJSFiles","cC":"calculateComplexity","gR":"getRating","CF":"analyzeComplexityFile","aF":"analyzeFile","gC":"getComplexity","pG":"parseGraphignore","iG":"isGraphignored","RS":"loadRuleSets","RS1":"saveRuleSet","fF":"findFiles","iE":"isExcluded","ISO":"isInStringOrComment","WC":"isWithinContext","FAR":"checkFileAgainstRule","CR":"getCustomRules","CR1":"setCustomRule","CR2":"deleteCustomRule","PRS":"detectProjectRuleSets","CR3":"checkCustomRules","DBS":"getDBSchema","TU":"getTableUsage","DBD":"getDBDeadTables","RC":"collectReferencedColumns","PR":"findProjectRoot","FL":"analyzeFileLocals","DC":"getDeadCode","HS":"calculateHealthScore","CA":"runCacheableAnalyses","aC":"aggregateComplexity","aU":"aggregateUndocumented","JSD":"aggregateJSDoc","FA":"getFullAnalysis","ASO":"getAnalysisSummaryOnly","JSD1":"extractJSDocComments","JSD2":"findJSDocBefore","PN":"extractParamName","TFD":"inferTypeFromDefault","RV":"hasReturnValue","vF":"validateFunction","JSD3":"checkJSDocFile","JSD4":"checkJSDocConsistency","JSD5":"generateJSDoc","JSD6":"buildJSDoc","PT":"inferParamType","JSD7":"generateJSDocFor","LF":"getLargeFiles","FP":"analyzeFilePatterns","PJ":"analyzePackageJson","OP":"getOutdatedPatterns","eS":"extractSignatures","bS":"buildSignature","BS":"hashBodyStructure","cS":"calculateSimilarity","SF":"getSimilarFunctions","CMF":"findCtxMdFiles","pA":"parseAnnotations","BN":"groupByName","AF":"getAllFeatures","PT1":"getPendingTests","TP":"markTestPassed","TF":"markTestFailed","TS":"updateTestState","TS1":"getTestSummary","TS2":"resetTestState","dT":"detectTsc","DL":"parseDiagnosticLine","bA":"buildArgs","cT":"checkTypes","eC":"extractComments","cM":"checkMissing","UF":"checkUndocumentedFile","gU":"getUndocumented","US":"getUndocumentedSummary","gA":"getArg","gP":"getPath","pH":"printHelp","CLI":"runCLI","eT":"estimateTokens","AC":"getAiContext","JSF1":"walkJSFiles","TLN":"addTopLevelNewlines","CP1":"resolveCtxPath","cF":"compactFile","bF":"beautifyFile","cP":"compactProject","eP":"expandProject","eL":"extractLegend","cF1":"compressFile","eC1":"editCompressed","SR":"findSymbolRange","CF1":"parseCtxFile","JSD8":"buildJSDocBlock","CF2":"findCtxFile","ES":"findExportStart","JSD9":"injectJSDoc","JSD10":"stripJSDoc","TLP":"splitTopLevelParams","CC":"validateCtxContracts","DD":"generateDocDialect","CF3":"walkCtxFiles","CMP":"resolveCtxMdPath","CD":"readContextDocs","PD":"getProjectDocs","cS1":"computeSignature","CD1":"parseCtxDescriptions","cS2":"checkStaleness","FT":"buildFileTemplate","CF4":"generateContextFiles","FC":"processFileCtx","CS":"parseCtxSignatures","CP2":"parseCtxParams","RT":"extractReturnType","JSD11":"sanitizeJSDocText","CV1":"parseCtxVars","CN":"parseCtxNames","cL":"collectLocals","LD":"collectLocalDecls","rN":"restoreNames","eF":"expandFile","rC1":"resolveCtx","fR":"fetchReference","lA":"listAvailable","FR":"getFrameworkReference","gI":"getInstructions","gC1":"getConfig","sC":"setConfig","MD":"getModeDescription","MW":"getModeWorkflow","vP":"validatePipeline","TC":"emitToolCall","TR":"emitToolResult","TC1":"onToolCall","TR1":"onToolResult","TL":"removeToolListener","gF":"getFilters","sF":"setFilters","aE":"addExcludes","rE":"removeExcludes","rF":"resetFilters","pG1":"parseGitignore","ED":"shouldExcludeDir","EF":"shouldExcludeFile","mW":"matchWildcard","GP":"matchGitignorePattern","mL":"minifyLegend","SN":"createShortName","bG":"buildGraph","cS3":"createSkeleton","pF":"parseFile","CAS":"extractCallsAndSQL","TN":"getTagName","CMN":"getCallMethodName","SV":"extractStringValue","TS3":"templateToString","SP":"discoverSubProjects","pP":"parseProject","FBE":"parseFileByExtension","SF1":"isSourceFile","APF":"findAllProjectFiles","JSD12":"buildJSDocTypeMap","JSD13":"findJSDocForNode","PWT":"enrichParamsWithTypes","sR":"setRoots","WR":"getWorkspaceRoot","rP":"resolvePath","pG2":"parseGo","eI":"extractImports","gB":"getBody","eC2":"extractCalls","pP1":"parsePython","SQL":"isSQLString","VTN":"isValidTableName","SQL1":"extractSQLFromString","SQL2":"parseSQL","pC":"parseColumns","BTL":"splitByTopLevelComma","SQL3":"extractSQLFromCode","ORM":"extractORMFromCode","TS4":"parseTypeScript","eP1":"extractParams","SAC":"stripStringsAndComments","cS4":"createServer","SS":"startStdioServer","DC1":"saveDiskCache","DC2":"loadDiskCache","gG":"getGraph","dC":"detectChanges","sM":"snapshotMtimes","gS":"getSkeleton","FZ":"getFocusZone","ex":"expand","de":"deps","us":"usages","eM":"extractMethod","CC1":"getCallChain","iC":"invalidateCache","PFP":"getPortFilePath","PF":"readPortFile","PF1":"writePortFile","PF2":"removePortFile","lB":"listBackends","eB":"ensureBackend","CF5":"encodeClientFrame","dF":"decodeFrame","SP1":"startStdioProxy","cl":"cleanup","rR":"readRegistry","wR":"writeRegistry","rS":"registerService","rB":"resolveBackend","GP1":"readGatewayPid","GR":"isGatewayRunning","GP2":"getGatewayPort","sL":"startListening","eG":"ensureGateway","sG":"stopGateway","rL":"registerLocal","DS":"registerDnsSd","tA":"tryAvahi","rM":"registerMcast","sS":"serveStatic","WSA":"computeWSAccept","WSF":"encodeWSFrame","WSF1":"decodeWSFrame","RPC":"broadcastRPC","pS":"patchState","eS1":"ensureSkeleton","AC1":"hasActiveClients","ST":"resetShutdownTimer","ST1":"startShutdownTimer","tA1":"touchActivity","API":"handleAPI","WS":"startWebServer"},"stats":{"files":45,"classes":0,"functions":260,"tables":0},"nodes":{"CH":{"t":"F","e":true,"f":"analysis/analysis-cache.js"},"CP":{"t":"F","e":true,"f":"analysis/analysis-cache.js"},"rC":{"t":"F","e":true,"f":"analysis/analysis-cache.js"},"wC":{"t":"F","e":true,"f":"analysis/analysis-cache.js"},"CV":{"t":"F","e":true,"f":"analysis/analysis-cache.js"},"JSF":{"t":"F","e":true,"f":"core/parser.js"},"cC":{"t":"F","e":false,"f":"analysis/complexity.js"},"gR":{"t":"F","e":false,"f":"analysis/complexity.js"},"CF":{"t":"F","e":true,"f":"analysis/complexity.js"},"aF":{"t":"F","e":false,"f":"analysis/large-files.js"},"gC":{"t":"F","e":true,"f":"analysis/complexity.js"},"pG":{"t":"F","e":false,"f":"analysis/custom-rules.js"},"iG":{"t":"F","e":false,"f":"analysis/custom-rules.js"},"RS":{"t":"F","e":false,"f":"analysis/custom-rules.js"},"RS1":{"t":"F","e":false,"f":"analysis/custom-rules.js"},"fF":{"t":"F","e":false,"f":"analysis/custom-rules.js"},"iE":{"t":"F","e":false,"f":"analysis/custom-rules.js"},"ISO":{"t":"F","e":false,"f":"analysis/custom-rules.js"},"WC":{"t":"F","e":false,"f":"analysis/custom-rules.js"},"FAR":{"t":"F","e":false,"f":"analysis/custom-rules.js"},"CR":{"t":"F","e":true,"f":"analysis/custom-rules.js"},"CR1":{"t":"F","e":true,"f":"analysis/custom-rules.js"},"CR2":{"t":"F","e":true,"f":"analysis/custom-rules.js"},"PRS":{"t":"F","e":true,"f":"analysis/custom-rules.js"},"CR3":{"t":"F","e":true,"f":"analysis/custom-rules.js"},"DBS":{"t":"F","e":true,"f":"analysis/db-analysis.js"},"TU":{"t":"F","e":true,"f":"analysis/db-analysis.js"},"DBD":{"t":"F","e":true,"f":"analysis/db-analysis.js"},"RC":{"t":"F","e":false,"f":"analysis/db-analysis.js"},"PR":{"t":"F","e":false,"f":"analysis/dead-code.js"},"FL":{"t":"F","e":false,"f":"analysis/dead-code.js"},"DC":{"t":"F","e":true,"f":"analysis/dead-code.js"},"HS":{"t":"F","e":false,"f":"analysis/full-analysis.js"},"CA":{"t":"F","e":false,"f":"analysis/full-analysis.js"},"aC":{"t":"F","e":false,"f":"analysis/full-analysis.js"},"aU":{"t":"F","e":false,"f":"analysis/full-analysis.js"},"JSD":{"t":"F","e":false,"f":"analysis/full-analysis.js"},"FA":{"t":"F","e":true,"f":"analysis/full-analysis.js"},"ASO":{"t":"F","e":true,"f":"analysis/full-analysis.js"},"JSD1":{"t":"F","e":false,"f":"analysis/jsdoc-checker.js"},"JSD2":{"t":"F","e":false,"f":"analysis/undocumented.js"},"PN":{"t":"F","e":false,"f":"analysis/similar-functions.js"},"TFD":{"t":"F","e":false,"f":"analysis/jsdoc-checker.js"},"RV":{"t":"F","e":false,"f":"analysis/jsdoc-checker.js"},"vF":{"t":"F","e":false,"f":"analysis/jsdoc-checker.js"},"JSD3":{"t":"F","e":true,"f":"analysis/jsdoc-checker.js"},"JSD4":{"t":"F","e":true,"f":"analysis/jsdoc-checker.js"},"JSD5":{"t":"F","e":false,"f":"compact/expand.js"},"JSD6":{"t":"F","e":false,"f":"analysis/jsdoc-generator.js"},"PT":{"t":"F","e":false,"f":"analysis/jsdoc-generator.js"},"JSD7":{"t":"F","e":true,"f":"analysis/jsdoc-generator.js"},"LF":{"t":"F","e":true,"f":"analysis/large-files.js"},"FP":{"t":"F","e":false,"f":"analysis/outdated-patterns.js"},"PJ":{"t":"F","e":false,"f":"analysis/outdated-patterns.js"},"OP":{"t":"F","e":true,"f":"analysis/outdated-patterns.js"},"eS":{"t":"F","e":false,"f":"analysis/similar-functions.js"},"bS":{"t":"F","e":false,"f":"analysis/similar-functions.js"},"BS":{"t":"F","e":false,"f":"analysis/similar-functions.js"},"cS":{"t":"F","e":false,"f":"analysis/similar-functions.js"},"SF":{"t":"F","e":true,"f":"analysis/similar-functions.js"},"CMF":{"t":"F","e":false,"f":"analysis/test-annotations.js"},"pA":{"t":"F","e":true,"f":"analysis/test-annotations.js"},"BN":{"t":"F","e":false,"f":"analysis/test-annotations.js"},"AF":{"t":"F","e":true,"f":"analysis/test-annotations.js"},"PT1":{"t":"F","e":true,"f":"analysis/test-annotations.js"},"TP":{"t":"F","e":true,"f":"analysis/test-annotations.js"},"TF":{"t":"F","e":true,"f":"analysis/test-annotations.js"},"TS":{"t":"F","e":false,"f":"analysis/test-annotations.js"},"TS1":{"t":"F","e":true,"f":"analysis/test-annotations.js"},"TS2":{"t":"F","e":true,"f":"analysis/test-annotations.js"},"dT":{"t":"F","e":false,"f":"analysis/type-checker.js"},"DL":{"t":"F","e":false,"f":"analysis/type-checker.js"},"bA":{"t":"F","e":false,"f":"analysis/type-checker.js"},"cT":{"t":"F","e":true,"f":"analysis/type-checker.js"},"eC":{"t":"F","e":false,"f":"analysis/undocumented.js"},"cM":{"t":"F","e":false,"f":"analysis/undocumented.js"},"UF":{"t":"F","e":true,"f":"analysis/undocumented.js"},"gU":{"t":"F","e":true,"f":"analysis/undocumented.js"},"US":{"t":"F","e":true,"f":"analysis/undocumented.js"},"gA":{"t":"F","e":false,"f":"cli/cli-handlers.js"},"gP":{"t":"F","e":false,"f":"cli/cli-handlers.js"},"pH":{"t":"F","e":true,"f":"cli/cli.js"},"CLI":{"t":"F","e":true,"f":"cli/cli.js"},"eT":{"t":"F","e":false,"f":"compact/validate-pipeline.js"},"AC":{"t":"F","e":true,"f":"compact/ai-context.js"},"JSF1":{"t":"F","e":false,"f":"compact/validate-pipeline.js"},"TLN":{"t":"F","e":false,"f":"compact/compact.js"},"CP1":{"t":"F","e":false,"f":"compact/doc-dialect.js"},"cF":{"t":"F","e":false,"f":"compact/compact.js"},"bF":{"t":"F","e":false,"f":"compact/compact.js"},"cP":{"t":"F","e":true,"f":"compact/compact.js"},"eP":{"t":"F","e":true,"f":"compact/expand.js"},"eL":{"t":"F","e":false,"f":"compact/compress.js"},"cF1":{"t":"F","e":true,"f":"compact/compress.js"},"eC1":{"t":"F","e":true,"f":"compact/compress.js"},"SR":{"t":"F","e":false,"f":"compact/compress.js"},"CF1":{"t":"F","e":true,"f":"compact/ctx-to-jsdoc.js"},"JSD8":{"t":"F","e":false,"f":"compact/ctx-to-jsdoc.js"},"CF2":{"t":"F","e":false,"f":"compact/ctx-to-jsdoc.js"},"ES":{"t":"F","e":false,"f":"compact/ctx-to-jsdoc.js"},"JSD9":{"t":"F","e":true,"f":"compact/ctx-to-jsdoc.js"},"JSD10":{"t":"F","e":true,"f":"compact/ctx-to-jsdoc.js"},"TLP":{"t":"F","e":false,"f":"compact/ctx-to-jsdoc.js"},"CC":{"t":"F","e":true,"f":"compact/ctx-to-jsdoc.js"},"DD":{"t":"F","e":true,"f":"compact/doc-dialect.js"},"CF3":{"t":"F","e":false,"f":"compact/doc-dialect.js"},"CMP":{"t":"F","e":false,"f":"compact/doc-dialect.js"},"CD":{"t":"F","e":true,"f":"compact/doc-dialect.js"},"PD":{"t":"F","e":true,"f":"compact/doc-dialect.js"},"cS1":{"t":"F","e":false,"f":"compact/doc-dialect.js"},"CD1":{"t":"F","e":false,"f":"compact/doc-dialect.js"},"cS2":{"t":"F","e":true,"f":"compact/doc-dialect.js"},"FT":{"t":"F","e":false,"f":"compact/doc-dialect.js"},"CF4":{"t":"F","e":true,"f":"compact/doc-dialect.js"},"FC":{"t":"F","e":false,"f":"compact/doc-dialect.js"},"CS":{"t":"F","e":false,"f":"compact/expand.js"},"CP2":{"t":"F","e":false,"f":"compact/expand.js"},"RT":{"t":"F","e":false,"f":"compact/expand.js"},"JSD11":{"t":"F","e":false,"f":"compact/expand.js"},"CV1":{"t":"F","e":false,"f":"compact/expand.js"},"CN":{"t":"F","e":false,"f":"compact/expand.js"},"cL":{"t":"F","e":false,"f":"compact/expand.js"},"LD":{"t":"F","e":false,"f":"compact/expand.js"},"rN":{"t":"F","e":false,"f":"compact/expand.js"},"eF":{"t":"F","e":true,"f":"compact/expand.js"},"rC1":{"t":"F","e":false,"f":"compact/expand.js"},"fR":{"t":"F","e":false,"f":"compact/framework-references.js"},"lA":{"t":"F","e":false,"f":"compact/framework-references.js"},"FR":{"t":"F","e":true,"f":"compact/framework-references.js"},"gI":{"t":"F","e":true,"f":"compact/instructions.js"},"gC1":{"t":"F","e":true,"f":"compact/mode-config.js"},"sC":{"t":"F","e":true,"f":"compact/mode-config.js"},"MD":{"t":"F","e":true,"f":"compact/mode-config.js"},"MW":{"t":"F","e":true,"f":"compact/mode-config.js"},"vP":{"t":"F","e":true,"f":"compact/validate-pipeline.js"},"TC":{"t":"F","e":true,"f":"core/event-bus.js"},"TR":{"t":"F","e":true,"f":"core/event-bus.js"},"TC1":{"t":"F","e":true,"f":"core/event-bus.js"},"TR1":{"t":"F","e":true,"f":"core/event-bus.js"},"TL":{"t":"F","e":true,"f":"core/event-bus.js"},"gF":{"t":"F","e":true,"f":"core/filters.js"},"sF":{"t":"F","e":true,"f":"core/filters.js"},"aE":{"t":"F","e":true,"f":"core/filters.js"},"rE":{"t":"F","e":true,"f":"core/filters.js"},"rF":{"t":"F","e":true,"f":"core/filters.js"},"pG1":{"t":"F","e":true,"f":"core/filters.js"},"ED":{"t":"F","e":true,"f":"core/filters.js"},"EF":{"t":"F","e":true,"f":"core/filters.js"},"mW":{"t":"F","e":false,"f":"core/filters.js"},"GP":{"t":"F","e":false,"f":"core/filters.js"},"mL":{"t":"F","e":true,"f":"core/graph-builder.js"},"SN":{"t":"F","e":false,"f":"core/graph-builder.js"},"bG":{"t":"F","e":true,"f":"core/graph-builder.js"},"cS3":{"t":"F","e":true,"f":"core/graph-builder.js"},"pF":{"t":"F","e":true,"f":"core/parser.js"},"CAS":{"t":"F","e":false,"f":"core/parser.js"},"TN":{"t":"F","e":false,"f":"core/parser.js"},"CMN":{"t":"F","e":false,"f":"core/parser.js"},"SV":{"t":"F","e":false,"f":"core/parser.js"},"TS3":{"t":"F","e":false,"f":"core/parser.js"},"SP":{"t":"F","e":true,"f":"core/parser.js"},"pP":{"t":"F","e":true,"f":"core/parser.js"},"FBE":{"t":"F","e":false,"f":"core/parser.js"},"SF1":{"t":"F","e":false,"f":"core/parser.js"},"APF":{"t":"F","e":true,"f":"core/parser.js"},"JSD12":{"t":"F","e":false,"f":"core/parser.js"},"JSD13":{"t":"F","e":false,"f":"core/parser.js"},"PWT":{"t":"F","e":false,"f":"core/parser.js"},"sR":{"t":"F","e":true,"f":"core/workspace.js"},"WR":{"t":"F","e":true,"f":"core/workspace.js"},"rP":{"t":"F","e":true,"f":"core/workspace.js"},"pG2":{"t":"F","e":true,"f":"lang/lang-go.js"},"eI":{"t":"F","e":false,"f":"lang/lang-go.js"},"gB":{"t":"F","e":false,"f":"lang/lang-go.js"},"eC2":{"t":"F","e":false,"f":"lang/lang-go.js"},"pP1":{"t":"F","e":true,"f":"lang/lang-python.js"},"SQL":{"t":"F","e":true,"f":"lang/lang-sql.js"},"VTN":{"t":"F","e":false,"f":"lang/lang-sql.js"},"SQL1":{"t":"F","e":true,"f":"lang/lang-sql.js"},"SQL2":{"t":"F","e":true,"f":"lang/lang-sql.js"},"pC":{"t":"F","e":false,"f":"lang/lang-sql.js"},"BTL":{"t":"F","e":false,"f":"lang/lang-sql.js"},"SQL3":{"t":"F","e":true,"f":"lang/lang-sql.js"},"ORM":{"t":"F","e":true,"f":"lang/lang-sql.js"},"TS4":{"t":"F","e":true,"f":"lang/lang-typescript.js"},"eP1":{"t":"F","e":false,"f":"lang/lang-typescript.js"},"SAC":{"t":"F","e":true,"f":"lang/lang-utils.js"},"cS4":{"t":"F","e":true,"f":"mcp/mcp-server.js"},"SS":{"t":"F","e":true,"f":"mcp/mcp-server.js"},"DC1":{"t":"F","e":false,"f":"mcp/tools.js"},"DC2":{"t":"F","e":false,"f":"mcp/tools.js"},"gG":{"t":"F","e":true,"f":"mcp/tools.js"},"dC":{"t":"F","e":false,"f":"mcp/tools.js"},"sM":{"t":"F","e":false,"f":"mcp/tools.js"},"gS":{"t":"F","e":true,"f":"mcp/tools.js"},"FZ":{"t":"F","e":true,"f":"mcp/tools.js"},"ex":{"t":"F","e":true,"f":"mcp/tools.js"},"de":{"t":"F","e":true,"f":"mcp/tools.js"},"us":{"t":"F","e":true,"f":"mcp/tools.js"},"eM":{"t":"F","e":false,"f":"mcp/tools.js"},"CC1":{"t":"F","e":true,"f":"mcp/tools.js"},"iC":{"t":"F","e":true,"f":"mcp/tools.js"},"PFP":{"t":"F","e":false,"f":"network/backend-lifecycle.js"},"PF":{"t":"F","e":false,"f":"network/backend-lifecycle.js"},"PF1":{"t":"F","e":true,"f":"network/backend-lifecycle.js"},"PF2":{"t":"F","e":true,"f":"network/backend-lifecycle.js"},"lB":{"t":"F","e":true,"f":"network/backend-lifecycle.js"},"eB":{"t":"F","e":true,"f":"network/backend-lifecycle.js"},"CF5":{"t":"F","e":false,"f":"network/backend-lifecycle.js"},"dF":{"t":"F","e":false,"f":"network/backend-lifecycle.js"},"SP1":{"t":"F","e":true,"f":"network/backend-lifecycle.js"},"cl":{"t":"F","e":false,"f":"network/backend.js"},"rR":{"t":"F","e":false,"f":"network/local-gateway.js"},"wR":{"t":"F","e":false,"f":"network/local-gateway.js"},"rS":{"t":"F","e":true,"f":"network/local-gateway.js"},"rB":{"t":"F","e":false,"f":"network/local-gateway.js"},"GP1":{"t":"F","e":false,"f":"network/local-gateway.js"},"GR":{"t":"F","e":false,"f":"network/local-gateway.js"},"GP2":{"t":"F","e":true,"f":"network/local-gateway.js"},"sL":{"t":"F","e":false,"f":"network/local-gateway.js"},"eG":{"t":"F","e":false,"f":"network/local-gateway.js"},"sG":{"t":"F","e":false,"f":"network/local-gateway.js"},"rL":{"t":"F","e":true,"f":"network/mdns.js"},"DS":{"t":"F","e":false,"f":"network/mdns.js"},"tA":{"t":"F","e":false,"f":"network/mdns.js"},"rM":{"t":"F","e":false,"f":"network/mdns.js"},"sS":{"t":"F","e":false,"f":"network/web-server.js"},"WSA":{"t":"F","e":false,"f":"network/web-server.js"},"WSF":{"t":"F","e":false,"f":"network/web-server.js"},"WSF1":{"t":"F","e":false,"f":"network/web-server.js"},"RPC":{"t":"F","e":false,"f":"network/web-server.js"},"pS":{"t":"F","e":false,"f":"network/web-server.js"},"eS1":{"t":"F","e":false,"f":"network/web-server.js"},"AC1":{"t":"F","e":false,"f":"network/web-server.js"},"ST":{"t":"F","e":false,"f":"network/web-server.js"},"ST1":{"t":"F","e":false,"f":"network/web-server.js"},"tA1":{"t":"F","e":false,"f":"network/web-server.js"},"API":{"t":"F","e":false,"f":"network/web-server.js"},"WS":{"t":"F","e":true,"f":"network/web-server.js"}},"edges":[],"orphans":["calculateComplexity","getRating","analyzeFile","parseGraphignore","isGraphignored","loadRuleSets","saveRuleSet","findFiles","isExcluded","isInStringOrComment","isWithinContext","checkFileAgainstRule","collectReferencedColumns","findProjectRoot","analyzeFileLocals","calculateHealthScore","runCacheableAnalyses","aggregateComplexity","aggregateUndocumented","aggregateJSDoc","extractJSDocComments","findJSDocBefore","extractParamName","inferTypeFromDefault","hasReturnValue","validateFunction","generateJSDoc","buildJSDoc","inferParamType","analyzeFilePatterns","analyzePackageJson","extractSignatures","buildSignature","hashBodyStructure","calculateSimilarity","findCtxMdFiles","groupByName","updateTestState","detectTsc","parseDiagnosticLine","buildArgs","extractComments","checkMissing","getArg","getPath","estimateTokens","walkJSFiles","addTopLevelNewlines","resolveCtxPath","compactFile","beautifyFile","extractLegend","findSymbolRange","buildJSDocBlock","findCtxFile","findExportStart","splitTopLevelParams","walkCtxFiles","resolveCtxMdPath","computeSignature","parseCtxDescriptions","buildFileTemplate","processFileCtx","parseCtxSignatures","parseCtxParams","extractReturnType","sanitizeJSDocText","parseCtxVars","parseCtxNames","collectLocals","collectLocalDecls","restoreNames","resolveCtx","fetchReference","listAvailable","matchWildcard","matchGitignorePattern","createShortName","extractCallsAndSQL","getTagName","getCallMethodName","extractStringValue","templateToString","parseFileByExtension","isSourceFile","buildJSDocTypeMap","findJSDocForNode","enrichParamsWithTypes","extractImports","getBody","extractCalls","isValidTableName","parseColumns","splitByTopLevelComma","extractParams","saveDiskCache","loadDiskCache","detectChanges","snapshotMtimes","extractMethod","getPortFilePath","readPortFile","encodeClientFrame","decodeFrame","cleanup","readRegistry","writeRegistry","resolveBackend","readGatewayPid","isGatewayRunning","startListening","ensureGateway","stopGateway","registerDnsSd","tryAvahi","registerMcast","serveStatic","computeWSAccept","encodeWSFrame","decodeWSFrame","broadcastRPC","patchState","ensureSkeleton","hasActiveClients","resetShutdownTimer","startShutdownTimer","touchActivity","handleAPI"],"duplicates":{},"files":["analysis/analysis-cache.js","analysis/complexity.js","analysis/custom-rules.js","analysis/db-analysis.js","analysis/dead-code.js","analysis/full-analysis.js","analysis/jsdoc-checker.js","analysis/jsdoc-generator.js","analysis/large-files.js","analysis/outdated-patterns.js","analysis/similar-functions.js","analysis/test-annotations.js","analysis/type-checker.js","analysis/undocumented.js","cli/cli-handlers.js","cli/cli.js","compact/ai-context.js","compact/compact.js","compact/compress.js","compact/ctx-to-jsdoc.js","compact/doc-dialect.js","compact/expand.js","compact/framework-references.js","compact/instructions.js","compact/mode-config.js","compact/validate-pipeline.js","core/event-bus.js","core/filters.js","core/graph-builder.js","core/parser.js","core/workspace.js","lang/lang-go.js","lang/lang-python.js","lang/lang-sql.js","lang/lang-typescript.js","lang/lang-utils.js","mcp/mcp-server.js","mcp/tool-defs.js","mcp/tools.js","network/backend-lifecycle.js","network/backend.js","network/local-gateway.js","network/mdns.js","network/server.js","network/web-server.js"]}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// @ctx .context/src/analysis/analysis-cache.ctx
|
|
2
|
+
import{readFileSync as t,writeFileSync as e,mkdirSync as n,existsSync as r}from"fs";import{join as c,dirname as a}from"path";import{createHash as i}from"crypto";
|
|
3
|
+
export function computeContentHash(t){return i("md5").update(t).digest("hex").slice(0,8)}
|
|
4
|
+
export function getCachePath(t,e){const n=e.replace(/\.[^.]+$/,".json");return c(t,".cache",n)}
|
|
5
|
+
export function readCache(e,n){const c=getCachePath(e,n);try{return r(c)?JSON.parse(t(c,"utf-8")):null}catch(t){return null}}
|
|
6
|
+
export function writeCache(t,r,c){const i=getCachePath(t,r);try{n(a(i),{recursive:!0}),e(i,JSON.stringify({...c,cachedAt:(new Date).toISOString()},null,2))}catch(t){}}
|
|
7
|
+
export function isCacheValid(t,e,n,r="content"){return!(!t||!t.sig||!t.contentHash||("sig"===r?t.sig!==e:t.sig!==e||t.contentHash!==n))}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @ctx .context/src/analysis/complexity.ctx
|
|
2
|
+
import{readFileSync as t,readdirSync as e,statSync as i}from"fs";import{join as n,relative as o,resolve as r}from"path";import{parse as a}from"../../vendor/acorn.mjs";import*as l from"../../vendor/walk.mjs";import{shouldExcludeDir as s,shouldExcludeFile as c,parseGitignore as m}from"../core/filters.js";function findJSFiles(t,r=t){t===r&&m(r);
|
|
3
|
+
const a=[];try{for(const l of e(t)){const e=n(t,l),m=o(r,e);i(e).isDirectory()?s(l,m)||a.push(...findJSFiles(e,r)):!l.endsWith(".js")||l.endsWith(".css.js")||l.endsWith(".tpl.js")||c(l,m)||a.push(e)}}catch(t){}return a}
|
|
4
|
+
function calculateComplexity(t){let e=1;return l.simple(t,{IfStatement(){e++},ConditionalExpression(){e++},ForStatement(){e++},ForOfStatement(){e++},ForInStatement(){e++},WhileStatement(){e++},DoWhileStatement(){e++},SwitchCase(t){t.test&&e++},LogicalExpression(t){"&&"!==t.operator&&"||"!==t.operator||e++},BinaryExpression(t){"??"===t.operator&&e++},CatchClause(){e++}}),e}
|
|
5
|
+
function getRating(t){return t<=5?"low":t<=10?"moderate":t<=20?"high":"critical"}
|
|
6
|
+
export function analyzeComplexityFile(t,e){const i=[];
|
|
7
|
+
let n;try{n=a(t,{ecmaVersion:"latest",sourceType:"module",locations:!0})}catch(t){return i}return l.simple(n,{FunctionDeclaration(t){if(!t.id)return;
|
|
8
|
+
const n=calculateComplexity(t.body);i.push({name:t.id.name,type:"function",file:e,line:t.loc.start.line,complexity:n,rating:getRating(n)})},ArrowFunctionExpression(t){if("BlockStatement"!==t.body.type)return;
|
|
9
|
+
const n=calculateComplexity(t.body);n>5&&i.push({name:"(arrow)",type:"function",file:e,line:t.loc.start.line,complexity:n,rating:getRating(n)})},MethodDefinition(t){if("method"!==t.kind)return;
|
|
10
|
+
const n=t.key.name||t.key.value,o=calculateComplexity(t.value.body);i.push({name:n,type:"method",file:e,line:t.loc.start.line,complexity:o,rating:getRating(o)})}}),i}
|
|
11
|
+
function analyzeFile(e,i){let n;try{n=t(e,"utf-8")}catch(t){return[]}return analyzeComplexityFile(n,o(i,e))}
|
|
12
|
+
export async function getComplexity(t,e={}){const i=e.minComplexity||1,n=e.onlyProblematic||!1,o=r(t),a=findJSFiles(t);
|
|
13
|
+
let l=[];for(const t of a)l.push(...analyzeFile(t,o));l=l.filter(t=>!(t.complexity<i||n&&("low"===t.rating||"moderate"===t.rating))),l.sort((t,e)=>e.complexity-t.complexity);
|
|
14
|
+
const s={low:l.filter(t=>"low"===t.rating).length,moderate:l.filter(t=>"moderate"===t.rating).length,high:l.filter(t=>"high"===t.rating).length,critical:l.filter(t=>"critical"===t.rating).length,average:l.length>0?Math.round(l.reduce((t,e)=>t+e.complexity,0)/l.length*10)/10:0};return{total:l.length,stats:s,items:l.slice(0,30)}}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// @ctx .context/src/analysis/custom-rules.ctx
|
|
2
|
+
import{readFileSync as e,writeFileSync as t,readdirSync as s,existsSync as n,statSync as r}from"fs";import{join as o,relative as i,dirname as c,resolve as l}from"path";import{fileURLToPath as u}from"url";import{shouldExcludeDir as f,shouldExcludeFile as a,parseGitignore as d}from"../core/filters.js";
|
|
3
|
+
const p=c(u(import.meta.url)),h=o(p,"..","..","rules");
|
|
4
|
+
let m=[];function parseGraphignore(t){m=[];
|
|
5
|
+
let s=t;for(;s!==c(s);){const t=o(s,".graphignore");if(n(t))try{const s=e(t,"utf-8");return void(m=s.split("\n").map(e=>e.trim()).filter(e=>e&&!e.startsWith("#")))}catch(e){}s=c(s)}}
|
|
6
|
+
function isGraphignored(e){const t=e.split("/").pop();for(const s of m)if(s.endsWith("*")){const n=s.slice(0,-1);if(e.startsWith(n)||t.startsWith(n))return!0}else if(s.startsWith("*")){const n=s.slice(1);if(e.endsWith(n)||t.endsWith(n))return!0}else if(e.includes(s)||t===s)return!0;return!1}
|
|
7
|
+
function loadRuleSets(){const t={};if(!n(h))return t;for(const n of s(h))if(n.endsWith(".json"))try{const s=e(o(h,n),"utf-8"),r=JSON.parse(s);t[r.name]=r}catch(e){}return t}
|
|
8
|
+
function saveRuleSet(e){const s=o(h,`${e.name}.json`);t(s,JSON.stringify(e,null,2))}
|
|
9
|
+
function findFiles(e,t,n=e){e===n&&(d(n),parseGraphignore(n));
|
|
10
|
+
const c=[],l=t.replace("*","");try{for(const u of s(e)){const s=o(e,u),d=i(n,s);r(s).isDirectory()?f(u,d)||c.push(...findFiles(s,t,n)):u.endsWith(l)&&(a(u,d)||isGraphignored(d)||c.push(s))}}catch(e){}return c}
|
|
11
|
+
function isExcluded(e,t=[]){for(const s of t){const t=s.replace("*","");if(e.endsWith(t))return!0}return!1}
|
|
12
|
+
function isInStringOrComment(e,t){const s=e.indexOf("//");if(-1!==s&&t>s)return!0;
|
|
13
|
+
let n=!1,r=null;for(let s=0;s<t;s++){const t=e[s],o=s>0?e[s-1]:"";n||'"'!==t&&"'"!==t&&"`"!==t?n&&t===r&&"\\"!==o&&(n=!1,r=null):(n=!0,r=t)}return n}
|
|
14
|
+
function isWithinContext(e,t,s){const n=s,r=`</${n.replace(/[<>]/g,"")}>`;
|
|
15
|
+
let o=0;for(let s=0;s<=t;s++){const t=e[s];
|
|
16
|
+
let i=0;for(;i<t.length;){const e=t.indexOf(n,i),s=t.indexOf(r,i);if(-1===e&&-1===s)break;-1!==e&&(-1===s||e<s)?(o++,i=e+n.length):(o--,i=s+r.length)}}return o>0}
|
|
17
|
+
function checkFileAgainstRule(t,s,n){if(isExcluded(t,s.exclude))return[];
|
|
18
|
+
const r=[],o=e(t,"utf-8").split("\n"),c=i(n,t);for(let e=0;e<o.length;e++){const t=o[e];
|
|
19
|
+
let n=!1,i="";if("regex"===s.patternType)try{const e=new RegExp(s.pattern,"g");
|
|
20
|
+
let r;for(;null!==(r=e.exec(t));)if(!isInStringOrComment(t,r.index)){n=!0,i=r[0];break}}catch(e){}else{const e=t.indexOf(s.pattern);-1===e||isInStringOrComment(t,e)||(n=!0,i=s.pattern)}n&&s.contextRequired&&!isWithinContext(o,e,s.contextRequired)||n&&r.push({ruleId:s.id,ruleName:s.name,severity:s.severity,file:c,line:e+1,match:i,replacement:s.replacement})}return r}
|
|
21
|
+
export async function getCustomRules(){const e=loadRuleSets();
|
|
22
|
+
let t=0;
|
|
23
|
+
const s={};for(const[n,r]of Object.entries(e))s[n]={description:r.description,ruleCount:r.rules.length,rules:r.rules.map(e=>({id:e.id,name:e.name,severity:e.severity}))},t+=r.rules.length;return{ruleSets:s,totalRules:t}}
|
|
24
|
+
export async function setCustomRule(e,t){const s=loadRuleSets();s[e]||(s[e]={name:e,description:`Custom rules for ${e}`,rules:[]});
|
|
25
|
+
const n=s[e],r=n.rules.findIndex(e=>e.id===t.id);return r>=0?n.rules[r]=t:n.rules.push(t),saveRuleSet(n),{success:!0,message:r>=0?`Updated rule "${t.id}" in ${e}`:`Added rule "${t.id}" to ${e}`}}
|
|
26
|
+
export async function deleteCustomRule(e,t){const s=loadRuleSets();if(!s[e])return{success:!1,message:`Ruleset "${e}" not found`};
|
|
27
|
+
const n=s[e],r=n.rules.findIndex(e=>e.id===t);return r<0?{success:!1,message:`Rule "${t}" not found`}:(n.rules.splice(r,1),saveRuleSet(n),{success:!0,message:`Deleted rule "${t}" from ${e}`})}
|
|
28
|
+
export function detectProjectRuleSets(t){const s=loadRuleSets(),r=[],c={};
|
|
29
|
+
let l=[];try{const s=o(t,"package.json");if(n(s)){const t=JSON.parse(e(s,"utf-8"));l=[...Object.keys(t.dependencies||{}),...Object.keys(t.devDependencies||{})]}}catch(e){}for(const[n,o]of Object.entries(s)){if(!o.detect)continue;
|
|
30
|
+
const s=o.detect;if(s.packageJson)for(const e of s.packageJson)if(l.includes(e)){r.push(n),c[n]=`Found "${e}" in package.json`;break}if(!r.includes(n)&&(s.imports||s.patterns)){const o=findFiles(t,"*.js");e:for(const l of o.slice(0,50))try{const o=e(l,"utf-8");if(s.imports)for(const e of s.imports)if(o.includes(e)){r.push(n),c[n]=`Found "${e}" in ${i(t,l)}`;break e}if(s.patterns)for(const e of s.patterns)if(o.includes(e)){r.push(n),c[n]=`Found "${e}" in ${i(t,l)}`;break e}}catch(e){}}}return{detected:r,reasons:c}}
|
|
31
|
+
export async function checkCustomRules(e,t={}){const s=l(e),n=loadRuleSets();
|
|
32
|
+
let r=[],o=null;if(t.ruleSet)n[t.ruleSet]&&(r=n[t.ruleSet].rules);else if(!1!==t.autoDetect){if(o=detectProjectRuleSets(e),o.detected.length>0)for(const e of o.detected)n[e]&&r.push(...n[e].rules);for(const[e,t]of Object.entries(n))t.alwaysApply&&!o.detected.includes(e)&&r.push(...t.rules)}else for(const e of Object.values(n))r.push(...e.rules);
|
|
33
|
+
const i={};for(const e of r){const t=e.filePattern||"*.js";i[t]||(i[t]=[]),i[t].push(e)}const c=[];for(const[t,n]of Object.entries(i)){const r=findFiles(e,t);for(const e of r)for(const t of n){const n=checkFileAgainstRule(e,t,s);c.push(...n)}}const u=new Set,f=c.filter(e=>{const t=`${e.file}:${e.line}:${e.match}`;return!u.has(t)&&(u.add(t),!0)});
|
|
34
|
+
let a=f;t.severity&&(a=f.filter(e=>e.severity===t.severity));
|
|
35
|
+
const d={error:0,warning:1,info:2};a.sort((e,t)=>{const s=d[e.severity]-d[t.severity];return 0!==s?s:e.file.localeCompare(t.file)});
|
|
36
|
+
const p={error:a.filter(e=>"error"===e.severity).length,warning:a.filter(e=>"warning"===e.severity).length,info:a.filter(e=>"info"===e.severity).length},h={};for(const e of a)h[e.ruleId]=(h[e.ruleId]||0)+1;return{basePath:e,total:a.length,bySeverity:p,byRule:h,violations:a.slice(0,50),...o&&{detected:o}}}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// @ctx .context/src/analysis/db-analysis.ctx
|
|
2
|
+
import{parseProject as e}from"../core/parser.js";import{buildGraph as t}from"../core/graph-builder.js";
|
|
3
|
+
export async function getDBSchema(t){const a=(await e(t)).tables||[];return{tables:a.map(e=>({name:e.name,columns:e.columns,file:e.file,line:e.line})),totalTables:a.length,totalColumns:a.reduce((e,t)=>e+t.columns.length,0)}}
|
|
4
|
+
export async function getTableUsage(a,s){const n=await e(a),o=t(n),r={};for(const[e,t,a]of o.edges){if("R→"!==t&&"W→"!==t)continue;
|
|
5
|
+
const n=a;if(s&&n!==s)continue;r[n]||(r[n]={readers:[],writers:[]});
|
|
6
|
+
const l=o.reverseLegend[e]||e,d=o.nodes[e],c={name:l,file:d?.f||"?"};"R→"===t?r[n].readers.some(e=>e.name===l)||r[n].readers.push(c):r[n].writers.some(e=>e.name===l)||r[n].writers.push(c)}const l=Object.entries(r).map(([e,t])=>({table:e,readers:t.readers,writers:t.writers,totalReaders:t.readers.length,totalWriters:t.writers.length})).sort((e,t)=>t.totalReaders+t.totalWriters-(e.totalReaders+e.totalWriters));return{tables:l,totalTables:l.length,totalQueries:l.reduce((e,t)=>e+t.totalReaders+t.totalWriters,0)}}
|
|
7
|
+
export async function getDBDeadTables(a){const s=await e(a),n=t(s),o=s.tables||[],r=new Set;for(const[,e,t]of n.edges)"R→"!==e&&"W→"!==e||r.add(t);
|
|
8
|
+
const l=o.filter(e=>!r.has(e.name)).map(e=>({name:e.name,file:e.file,line:e.line,columnCount:e.columns.length})),d=collectReferencedColumns(s),c=[];for(const e of o)if(r.has(e.name))for(const t of e.columns)d.has(t.name)||c.push({table:e.name,column:t.name,type:t.type});return{deadTables:l,deadColumns:c,stats:{totalSchemaTables:o.length,totalSchemaColumns:o.reduce((e,t)=>e+t.columns.length,0),deadTableCount:l.length,deadColumnCount:c.length}}}
|
|
9
|
+
function collectReferencedColumns(e){const t=new Set;for(const a of e.functions||[])if(a.dbReads?.length||a.dbWrites?.length)for(const e of[...a.dbReads||[],...a.dbWrites||[]])t.add(e);for(const a of e.classes||[])if(a.dbReads?.length||a.dbWrites?.length)for(const e of[...a.dbReads||[],...a.dbWrites||[]])t.add(e);return t.add("id"),t.add("uuid"),t.add("created_at"),t.add("updated_at"),t}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// @ctx .context/src/analysis/dead-code.ctx
|
|
2
|
+
import{readFileSync as e,readdirSync as t,statSync as n,existsSync as s}from"fs";import{join as o,relative as i,resolve as a,dirname as r}from"path";import{parse as c}from"../../vendor/acorn.mjs";import*as l from"../../vendor/walk.mjs";import{shouldExcludeDir as d,shouldExcludeFile as f,parseGitignore as p}from"../core/filters.js";function findJSFiles(e,s=e){e===s&&p(s);
|
|
3
|
+
const a=[];try{for(const r of t(e)){const t=o(e,r),c=i(s,t);n(t).isDirectory()?d(r,c)||a.push(...findJSFiles(t,s)):!r.endsWith(".js")||r.endsWith(".css.js")||r.endsWith(".tpl.js")?(r.endsWith(".css.js")||r.endsWith(".tpl.js"))&&(f(r,c)||a.push(t)):f(r,c)||a.push(t)}}catch(e){}return a}
|
|
4
|
+
function findProjectRoot(e){let t=a(e);for(;t!==r(t);){if(s(o(t,"package.json")))return t;t=r(t)}return a(e)}
|
|
5
|
+
function analyzeFile(e){const t=new Set,n=new Set,s=new Set,o=[],i=[];
|
|
6
|
+
let a;try{a=c(e,{ecmaVersion:"latest",sourceType:"module",locations:!0})}catch(e){return{definitions:t,calls:n,exports:s,imports:o,namedExports:i}}return l.simple(a,{FunctionDeclaration(e){e.id&&t.add(e.id.name)},ClassDeclaration(e){e.id&&t.add(e.id.name)},CallExpression(e){"Identifier"===e.callee.type?n.add(e.callee.name):"MemberExpression"===e.callee.type&&"Identifier"===e.callee.object.type&&n.add(e.callee.object.name);for(const t of e.arguments)"Identifier"===t.type&&n.add(t.name)},NewExpression(e){"Identifier"===e.callee.type&&n.add(e.callee.name)},ImportDeclaration(e){const t=e.source.value;for(const n of e.specifiers)"ImportSpecifier"===n.type?o.push({name:n.imported.name,source:t}):"ImportDefaultSpecifier"===n.type&&o.push({name:"default",source:t})},ExportNamedDeclaration(e){if(e.declaration)if(e.declaration.id){const t=e.declaration.id.name;s.add(t),i.push({name:t,line:e.loc.start.line})}else if(e.declaration.declarations)for(const t of e.declaration.declarations)if("Identifier"===t.id.type){const n=t.id.name;s.add(n),i.push({name:n,line:e.loc.start.line})}if(e.specifiers)for(const t of e.specifiers){const n=t.exported.name;s.add(n),i.push({name:n,line:e.loc.start.line})}},ExportDefaultDeclaration(e){e.declaration?.id&&s.add(e.declaration.id.name)}}),{definitions:t,calls:n,exports:s,imports:o,namedExports:i}}
|
|
7
|
+
function analyzeFileLocals(e){const t=[],n=[];
|
|
8
|
+
let s;try{s=c(e,{ecmaVersion:"latest",sourceType:"module",locations:!0})}catch(e){return{unusedVars:t,unusedImports:n}}const o=new Set,i=[],a=[],r=new Set;l.simple(s,{VariableDeclaration(e){const t="ExportNamedDeclaration"===e.parent?.type;for(const n of e.declarations)"Identifier"===n.id.type&&(i.push({name:n.id.name,line:n.loc.start.line,isExported:t}),r.add(n.id))},ImportDeclaration(e){for(const t of e.specifiers){const n=t.local.name,s="ImportSpecifier"===t.type?t.imported.name:"ImportDefaultSpecifier"===t.type?"default":"*";a.push({name:s,local:n,source:e.source.value,line:e.loc.start.line}),r.add(t.local)}}});
|
|
9
|
+
const d=new Set;for(const e of s.body){if("ExportNamedDeclaration"===e.type&&e.declaration){if(e.declaration.declarations)for(const t of e.declaration.declarations)"Identifier"===t.id.type&&d.add(t.id.name);e.declaration.id&&d.add(e.declaration.id.name)}if("ExportNamedDeclaration"===e.type&&e.specifiers)for(const t of e.specifiers)d.add(t.local.name)}l.simple(s,{Identifier(e){o.add(e.name)}});for(const n of i){if(d.has(n.name))continue;if(n.name.startsWith("_"))continue;
|
|
10
|
+
const s=new RegExp(`\\b${n.name.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\b`,"g"),o=e.match(s);o&&o.length<=1&&t.push({name:n.name,line:n.line})}for(const t of a){if("*"===t.name)continue;
|
|
11
|
+
const s=new RegExp(`\\b${t.local.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\b`,"g"),o=e.match(s);o&&o.length<=1&&n.push(t)}return{unusedVars:t,unusedImports:n}}
|
|
12
|
+
export async function getDeadCode(t){const n=a(t),s=findJSFiles(t),o=[],d=new Set,f=new Set,p=[],m=new Map,u=findJSFiles(findProjectRoot(t));for(const t of u){let s;try{s=e(t,"utf-8")}catch{continue}const o=i(n,t),{imports:c}=analyzeFile(s);for(const e of c){if(!e.source.startsWith("."))continue;
|
|
13
|
+
const s=r(t);
|
|
14
|
+
let c=a(s,e.source);c.endsWith(".js")||(c+=".js");
|
|
15
|
+
const l=i(n,c),d=`${e.name}@${l}`;m.has(d)||m.set(d,new Set),m.get(d).add(o)}}for(const t of s){const s=e(t,"utf-8"),o=i(n,t),{definitions:a,calls:r,exports:c,namedExports:l}=analyzeFile(s);for(const e of r)d.add(e);for(const e of c)f.add(e);p.push({file:o,code:s,definitions:a,calls:r,exports:c,namedExports:l})}for(const{file:e,code:t,definitions:n,exports:s}of p){if(e.includes(".test.")||e.includes("/tests/"))continue;if(e.endsWith(".css.js")||e.endsWith(".tpl.js"))continue;
|
|
16
|
+
let n;try{n=c(t,{ecmaVersion:"latest",sourceType:"module",locations:!0})}catch(e){continue}l.simple(n,{FunctionDeclaration(t){if(!t.id)return;
|
|
17
|
+
const n=t.id.name;s.has(n)||f.has(n)||d.has(n)||n.startsWith("_")||o.push({name:n,type:"function",file:e,line:t.loc.start.line,reason:"Never called"})},ClassDeclaration(t){if(!t.id)return;
|
|
18
|
+
const n=t.id.name;s.has(n)||f.has(n)||d.has(n)||o.push({name:n,type:"class",file:e,line:t.loc.start.line,reason:"Never instantiated"})}})}for(const{file:e,calls:t,namedExports:n}of p)if(!e.includes(".test.")&&!e.includes("/tests/"))for(const s of n){if(t.has(s.name))continue;
|
|
19
|
+
const n=`${s.name}@${e}`,i=m.get(n);i&&0!==i.size||o.push({name:s.name,type:"export",file:e,line:s.line,reason:"Exported but never imported"})}for(const{file:e,code:t}of p){if(e.includes(".test.")||e.includes("/tests/"))continue;if(e.endsWith(".css.js")||e.endsWith(".tpl.js"))continue;const{unusedVars:n,unusedImports:s}=analyzeFileLocals(t);for(const t of n)o.push({name:t.name,type:"variable",file:e,line:t.line,reason:"Declared but never used"});for(const t of s)o.push({name:t.local,type:"import",file:e,line:t.line,reason:`Imported from '${t.source}' but never used`})}const h={function:o.filter(e=>"function"===e.type).length,class:o.filter(e=>"class"===e.type).length,export:o.filter(e=>"export"===e.type).length,variable:o.filter(e=>"variable"===e.type).length,import:o.filter(e=>"import"===e.type).length};return{total:o.length,byType:h,items:o.slice(0,50)}}
|