diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9ef6858 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +# EditorConfig: https://editorconfig.org +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[*.json] +indent_size = 2 + +[*.{yml,yaml}] +indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e69de29..60d8d8d 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -0,0 +1,267 @@ +# Copilot Instructions for lxDIG MCP + +Dynamic Intelligence Graph (DIG) MCP server for code graph intelligence, agent memory, and multi-agent coordination — beyond RAG and GraphRAG — for VS Code Copilot, Claude Code, Claude Desktop, and Cursor. + +## Primary Goal + +Understand the codebase before reading files. Use graph-backed tools first for code intelligence, fall back to file reads only when needed. + +## Runtime Truths + +- **Stack**: TypeScript, Docker +- **Source root**: `src/` +- **Key directories**: `src/cli`, `src/engines`, `src/graph`, `src/parsers`, `src/response`, `src/tools`, `src/types`, `src/utils`, `src/vector` +- **Transport**: stdio (default) or HTTP (`MCP_TRANSPORT=http MCP_PORT=9000`) +- **Databases**: Memgraph (port 7687), Qdrant (port 6333) — both must be running + +## Available Commands + +- `build`: `tsc` +- `dev`: `tsc --watch` +- `start`: `node dist/server.js` +- `start:http`: `node scripts/start-http-supervisor.mjs` +- `start:http:raw`: `MCP_TRANSPORT=http MCP_PORT=9000 node dist/server.js` +- `test`: `vitest run` +- `test:watch`: `vitest watch` +- `test:coverage`: `vitest run --coverage` +- `lint`: `eslint src --ext .ts` +- `benchmark:check-regression`: `python3 scripts/check_benchmark_regression.py` + +## Required Session Flow + +**One-shot (recommended):** +``` +init_project_setup({ projectId: "my-proj", workspaceRoot: "/abs/path" }) +``` +This sets workspace context, triggers a full graph rebuild, and writes copilot instructions in one call. + +**Manual (step-by-step):** +1. `graph_set_workspace({ projectId, workspaceRoot })` — anchor the session +2. `graph_rebuild({ projectId, mode: "full", workspaceRoot })` — index source; **capture `txId` from the response** +3. `graph_health({ profile: "balanced" })` — verify nodes > 0 +4. `graph_query({ query: "MATCH (n) RETURN labels(n)[0], count(n) ORDER BY count(n) DESC LIMIT 8", projectId })` — confirm data + +**HTTP transport extra steps:** +- Capture `mcp-session-id` header from `initialize` response +- Include it on every subsequent request + +## Tool Decision Guide + +| Goal | First choice | Fallback | +|---|---|---| +| Count/list nodes | `graph_query` (Cypher) | `graph_health` | +| Understand a symbol | `code_explain` (symbol name) | `semantic_slice` | +| Find related code | `find_similar_code` | `semantic_search` | +| Check arch violations | `arch_validate` | `blocking_issues` | +| Place new code | `arch_suggest` | — | +| Docs lookup | `search_docs` → `index_docs` if empty | file read | +| Tests after change | `test_select` → `test_run` | `suggest_tests` | +| Track decisions | `episode_add` (DECISION) | — | +| Release agent lock | `agent_release` with `claimId` | — | + +## Correct Tool Signatures (tested & verified) + +### graph +```jsonc +graph_set_workspace({ "projectId": "proj", "workspaceRoot": "/abs/path" }) +graph_rebuild({ "projectId": "proj", "mode": "full", "workspaceRoot": "/abs/path" }) +// ↳ response contains { txId: "tx-..." } — save it for diff_since +graph_health({ "profile": "balanced" }) +graph_query({ "query": "MATCH (f:FILE) RETURN f.relativePath LIMIT 10", "projectId": "proj" }) +diff_since({ "since": "", "projectId": "proj" }) +ref_query({ "query": "natural language or symbol", "repoPath": "/abs/path", "limit": 5 }) +tools_list({}) +``` + +### semantic / code intelligence +```jsonc +semantic_search({ "query": "text description", "projectId": "proj", "limit": 5 }) +// ↳ requires graph_rebuild to have run first; returns error otherwise + +find_pattern({ "pattern": "handler registry pattern", "projectId": "proj", "limit": 5 }) +find_similar_code({ "elementId": "proj:file.ts:FunctionName:12", "projectId": "proj", "limit": 5 }) +// ↳ elementId format: "projectId:filename:symbolName:line" + +code_explain({ "element": "SymbolName", "depth": 2, "projectId": "proj" }) +// ↳ "element" accepts symbol name or relative file path — NOT a qualified ID + +semantic_diff({ "elementId1": "proj:a.ts:fn:10", "elementId2": "proj:b.ts:fn:20", "projectId": "proj" }) +// ↳ fields: elementId1 / elementId2 (NOT elementA / elementB) + +semantic_slice({ "symbol": "MyClass", "context": "body", "projectId": "proj" }) +// ↳ accepts symbol | query | file (NOT entryPoint) +``` + +### clustering & architecture +```jsonc +code_clusters({ "type": "file", "count": 10, "projectId": "proj" }) +// ↳ "type" enum: "function" | "class" | "file" (NOT granularity) + +arch_validate({ "projectId": "proj", "files": ["src/engines/my-engine.ts"] }) +arch_suggest({ "name": "MyNewEngine", "codeType": "engine", "dependencies": ["utils", "types"], "projectId": "proj" }) +// ↳ "name" field (NOT codeName) + +blocking_issues({ "projectId": "proj" }) +``` + +### docs +```jsonc +index_docs({ "projectId": "proj", "paths": ["/abs/README.md", "/abs/docs/GUIDE.md"] }) +// ↳ call this before search_docs if search returns 0 results + +search_docs({ "query": "architecture layers", "limit": 5, "projectId": "proj" }) +search_docs({ "symbol": "HandlerBridge", "limit": 3, "projectId": "proj" }) +// ↳ can search by free-text query OR by code symbol name +``` + +### impact & tests +```jsonc +impact_analyze({ "changedFiles": ["src/engines/x.ts", "src/config.ts"], "projectId": "proj" }) +contract_validate({ "tool": "graph_rebuild", "arguments": { "projectId": "proj", "mode": "full" } }) + +test_categorize({ "projectId": "proj" }) +test_select({ "changedFiles": ["src/engines/x.ts"], "projectId": "proj" }) +suggest_tests({ "elementId": "proj:file.ts:symbolName:line", "limit": 5 }) +// ↳ requires a FULLY QUALIFIED element ID (projectId:file:symbol:line) + +test_run({ "testFiles": ["src/utils/__tests__/validation.test.ts"], "parallel": false }) +``` + +### progress & features +```jsonc +feature_status({ "featureId": "list" }) // list all feature IDs +feature_status({ "featureId": "phase-1" }) // detail for one feature +progress_query({ "query": "completed features", "projectId": "proj" }) +// ↳ "query" is REQUIRED (NOT "status") + +task_update({ "taskId": "my-task", "status": "completed", "note": "done", "projectId": "proj" }) +``` + +### memory (episodes) +```jsonc +episode_add({ + "type": "DECISION", // "DECISION" | "LEARNING" | "OBSERVATION" (uppercase) + "content": "Adopted X because Y", + "entities": ["SymbolA", "SymbolB"], + "outcome": "success", // "success" | "failure" | "partial" + "metadata": { "rationale": "..." } // DECISION REQUIRES metadata.rationale +}) +episode_add({ + "type": "LEARNING", + "content": "Observed that X leads to Y", + "outcome": "success" + // LEARNING does not require metadata.rationale +}) +episode_recall({ "query": "language agnostic", "limit": 5 }) +decision_query({ "query": "architecture decisions", "limit": 5 }) +// ↳ "query" field (NOT "topic") + +reflect({ "limit": 10, "profile": "balanced" }) +``` + +### coordination +```jsonc +agent_claim({ + "agentId": "agent-01", + "targetId": "src/engines/my-engine.ts", // file path or element — field is "targetId" (NOT "target") + "intent": "Refactoring engine for multi-lang", + "taskId": "refactor-task", + "sessionId": "session-001" +}) +// ↳ response contains { claimId: "claim-xxx..." } — save it for agent_release + +agent_status({ "agentId": "agent-01" }) +coordination_overview({ "projectId": "proj" }) + +context_pack({ + "task": "Implement multi-tenant support", // REQUIRED free-text task description + "taskId": "my-task-id", + "agentId": "agent-01", + "includeLearnings": true +}) + +agent_release({ + "claimId": "claim-xxx...", // captured from agent_claim response (NOT agentId/taskId) + "outcome": "Refactor complete" +}) +``` + +### setup +```jsonc +init_project_setup({ "projectId": "proj", "workspaceRoot": "/abs/path" }) +setup_copilot_instructions({ "targetPath": "/abs/path", "projectName": "MyProj", "overwrite": true }) +``` + +## Common Pitfalls + +| Wrong | Correct | +|---|---| +| `code_explain({ elementId: "proj:f.ts:fn:10" })` | `code_explain({ element: "SymbolName" })` | +| `semantic_diff({ elementA: ..., elementB: ... })` | `semantic_diff({ elementId1: ..., elementId2: ... })` | +| `semantic_slice({ entryPoint: "X" })` | `semantic_slice({ symbol: "X" })` | +| `code_clusters({ granularity: "module" })` | `code_clusters({ type: "file" })` | +| `arch_suggest({ codeName: "X" })` | `arch_suggest({ name: "X" })` | +| `episode_add({ type: "decision" })` | `episode_add({ type: "DECISION" })` (uppercase) | +| `episode_add` DECISION without `metadata.rationale` | always include `metadata: { rationale: "..." }` | +| `decision_query({ topic: "X" })` | `decision_query({ query: "X" })` | +| `progress_query({ status: "active" })` | `progress_query({ query: "active tasks" })` | +| `agent_claim({ target: "file.ts" })` | `agent_claim({ targetId: "file.ts" })` | +| `agent_release({ agentId, taskId })` | `agent_release({ claimId: "claim-xxx" })` | +| `context_pack({})` without `task` | `context_pack({ task: "Description..." })` | +| `diff_since({ since: "HEAD~3" })` | `diff_since({ since: txId })` from rebuild response | +| `suggest_tests({ elementId: "symbolName" })` | `suggest_tests({ elementId: "proj:file.ts:symbol:line" })` | + +## Copilot Skills — Usage Patterns + +### Skill: Explore unfamiliar codebase +``` +1. init_project_setup({ projectId, workspaceRoot }) — init + rebuild +2. graph_query("MATCH (n) RETURN labels(n)[0], count(n) ORDER BY count(n) DESC LIMIT 10") +3. code_explain({ element: "MainClass" }) — key entry point +4. find_similar_code({ elementId: "proj:server.ts:fn:10" }) — discover siblings +``` + +### Skill: Safe refactor + test impact +``` +1. impact_analyze({ changedFiles: ["src/x.ts"] }) +2. test_select({ changedFiles: ["src/x.ts"] }) +3. arch_validate({ files: ["src/x.ts"] }) +4. test_run({ testFiles: [...from test_select result...] }) +5. episode_add({ type: "DECISION", content: "...", metadata: { rationale: "..." } }) +``` + +### Skill: Find where to add new code +``` +1. arch_suggest({ name: "NewFeature", codeType: "engine", dependencies: ["utils"] }) +2. blocking_issues({}) — check blockers first +3. semantic_search({ query: "similar existing pattern" }) +``` + +### Skill: Multi-agent safe edit +``` +1. agent_claim({ agentId, targetId: "src/file.ts", intent: "..." }) → save claimId +2. … make changes … +3. agent_release({ claimId, outcome: "done" }) +``` + +### Skill: Track architectural decisions +``` +episode_add({ + type: "DECISION", + content: "Chose X over Y because Z", + entities: ["AffectedClass"], + outcome: "success", + metadata: { rationale: "Z is faster and simpler" } +}) +``` + +### Skill: Docs workflow (cold start) +``` +1. search_docs({ query: "topic" }) — if count=0: +2. index_docs({ paths: ["/abs/README.md", "/abs/docs/..."] }) +3. search_docs({ query: "topic" }) — now returns results +``` + +## Source of Truth + +`README.md`, `QUICK_START.md`, `ARCHITECTURE.md`, `docs/TOOL_PATTERNS.md`. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..43f9fe2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,79 @@ +# ── Continuous Integration ───────────────────────────────────────────────────── +# +# Runs on every push to main/test/* branches and on all pull requests. +# Steps: checkout → install → build → lint → test (with coverage) +# +# Memgraph / Qdrant are NOT required — the entire test suite uses vi.fn() mocks +# and does not open real network connections to databases. + +name: CI + +on: + push: + branches: + - main + - "test/**" + - "feature/**" + - "fix/**" + pull_request: + branches: + - main + +jobs: + build-and-test: + name: Build, Lint & Test + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: ["24"] + + steps: + # ── Checkout ────────────────────────────────────────────────────────────── + - name: Checkout repository + uses: actions/checkout@v4 + + # ── Node.js setup ───────────────────────────────────────────────────────── + - name: Set up Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + + # ── Install ─────────────────────────────────────────────────────────────── + - name: Install dependencies + run: npm ci + + # ── Build ───────────────────────────────────────────────────────────────── + - name: TypeScript build + run: npm run build + + # ── Lint ────────────────────────────────────────────────────────────────── + - name: ESLint (errors only) + # We allow warnings (no-console, no-explicit-any) but fail on any error. + run: npm run lint -- --max-warnings 9999 + + # ── Test + Coverage ─────────────────────────────────────────────────────── + - name: Run tests with coverage + run: npm run test:coverage + env: + # Suppress INFO-level log output during test runs for cleaner CI logs. + LXDIG_LOG_LEVEL: error + + # ── Upload coverage report ──────────────────────────────────────────────── + - name: Upload coverage to GitHub Actions artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: coverage-report-node-${{ matrix.node-version }} + path: coverage/ + retention-days: 14 + + # ── Optional: post coverage summary to PR ───────────────────────────────── + - name: Report coverage summary + if: github.event_name == 'pull_request' + uses: davelosert/vitest-coverage-report-action@v2 + with: + name: "lxDIG MCP" + json-summary-compare-path: coverage/coverage-summary.json + continue-on-error: true diff --git a/.gitignore b/.gitignore index ce1f4ee..2445980 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ __pycache__/ # benchmarks benchmarks/agent_mode_artifacts/ benchmarks/graph_tools_benchmark_results.json +plan \ No newline at end of file diff --git a/.lxdig/cache/file-hashes.json b/.lxdig/cache/file-hashes.json new file mode 100644 index 0000000..781c03c --- /dev/null +++ b/.lxdig/cache/file-hashes.json @@ -0,0 +1,12 @@ +{ + "version": "1.0", + "lastBuild": 1772246889405, + "files": { + "../../../../tmp/orch-sync-I9dD7K/src/app.ts": { + "path": "../../../../tmp/orch-sync-I9dD7K/src/app.ts", + "hash": "6c64008f", + "timestamp": 1772246889405, + "LOC": 2 + } + } +} \ No newline at end of file diff --git a/.lxrag/config.json b/.lxdig/config.json similarity index 100% rename from .lxrag/config.json rename to .lxdig/config.json diff --git a/.lxrag/cache/file-hashes.json b/.lxrag/cache/file-hashes.json deleted file mode 100644 index 29f5e1c..0000000 --- a/.lxrag/cache/file-hashes.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": "1.0", - "lastBuild": 1771990664210, - "files": { - "../../../../tmp/orch-sync-Vkhebk/src/app.ts": { - "path": "../../../../tmp/orch-sync-Vkhebk/src/app.ts", - "hash": "6c64008f", - "timestamp": 1771990664210, - "LOC": 2 - } - } -} \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..9d02e47 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": false, + "quoteProps": "as-needed", + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 13b55b6..d72bbb9 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,20 +1,19 @@ -# Graph Server Architecture +# lxDIG — Dynamic Intelligence Graph Architecture ## Overview -lxRAG MCP is a production MCP server that turns any repository into a queryable graph + retrieval system. It exposes **33 MCP tools** across code intelligence, architecture validation, test selection, agent memory, and multi-agent coordination. +lxDIG MCP is a production Dynamic Intelligence Graph (DIG) server — the next evolution beyond static RAG and batch GraphRAG — that turns any repository into a queryable, incrementally-updated graph + retrieval system. It exposes **33 MCP tools** across code intelligence, architecture validation, test selection, agent memory, and multi-agent coordination. ## Server Implementation Two server entry points exist — both production-ready: -| File | Transport | Use case | -| ------------------- | -------------------------- | ---------------------------------------- | -| `src/server.ts` | MCP HTTP (Streamable HTTP) | Production — multi-client, multi-session | -| `src/mcp-server.ts` | stdio | Editor integrations (single client) | -| `src/index.ts` | stdio (legacy) | Backward compat only | +| File | Transport | Use case | +| --------------- | -------------------------- | ---------------------------------------- | +| `src/server.ts` | MCP HTTP (Streamable HTTP) | Production — multi-client, multi-session | +| `src/index.ts` | stdio (legacy) | Backward compat only | -**Recommended**: `src/server.ts` via `npm run start:http` for agent fleets; stdio entry (`src/mcp-server.ts`) for local editor use. +**Recommended**: `src/server.ts` via `npm run start:http` for agent fleets; stdio for local editor use via `npm run start`. ## Key Architectural Properties @@ -32,7 +31,7 @@ Two server entry points exist — both production-ready: │ MCP HTTP (Streamable HTTP) ┌──────────────────▼───────────────────────────────────────────┐ │ src/server.ts — McpServer (MCP SDK) │ -│ 33 registered tools → ToolHandlers │ +│ 39 registered tools → ToolHandlers │ └────────┬──────────────────────────────────────────┬──────────┘ │ │ ┌────────▼──────────┐ ┌────────────▼──────────┐ @@ -74,16 +73,16 @@ Parsing is handled in `src/graph/orchestrator.ts` which dispatches to the approp ### Parser registry -| Language | Extensions | Parser (default) | Parser (tree-sitter, `LXRAG_USE_TREE_SITTER=true`) | -| ---------- | --------------------- | ---------------------------- | --------------------------------------------------- | -| TypeScript | `.ts` | regex (typescript-parser.ts) | `TreeSitterTypeScriptParser` | -| TSX | `.tsx` | regex fallback | `TreeSitterTSXParser` | -| JavaScript | `.js`, `.mjs`, `.cjs` | FILE node only | `TreeSitterJavaScriptParser` | -| JSX | `.jsx` | FILE node only | `TreeSitterJSXParser` | -| Python | `.py` | regex | `TreeSitterPythonParser` | -| Go | `.go` | regex | `TreeSitterGoParser` | -| Rust | `.rs` | regex | `TreeSitterRustParser` | -| Java | `.java` | regex | `TreeSitterJavaParser` | +| Language | Extensions | Parser (default) | Parser (tree-sitter, `LXDIG_USE_TREE_SITTER=true`) | +| ---------- | --------------------- | ---------------------------- | -------------------------------------------------- | +| TypeScript | `.ts` | regex (typescript-parser.ts) | `TreeSitterTypeScriptParser` | +| TSX | `.tsx` | regex fallback | `TreeSitterTSXParser` | +| JavaScript | `.js`, `.mjs`, `.cjs` | FILE node only | `TreeSitterJavaScriptParser` | +| JSX | `.jsx` | FILE node only | `TreeSitterJSXParser` | +| Python | `.py` | regex | `TreeSitterPythonParser` | +| Go | `.go` | regex | `TreeSitterGoParser` | +| Rust | `.rs` | regex | `TreeSitterRustParser` | +| Java | `.java` | regex | `TreeSitterJavaParser` | Tree-sitter grammars are `optionalDependencies`. Missing grammars fall back silently per language. @@ -122,7 +121,7 @@ Result objects include a `mode` field (`"mage_leiden"`, `"directory_heuristic"`, | `HybridRetriever` | `src/graph/hybrid-retriever.ts` | RRF fusion of vector + BM25 + graph expansion | | `PPR` | `src/graph/ppr.ts` | Personalized PageRank for relevance ranking | -## Tool Surface (33 tools) +## Tool Surface (39 tools) **Graph/querying** (4): `graph_set_workspace`, `graph_rebuild`, `graph_health`, `graph_query` @@ -160,8 +159,8 @@ GET http://localhost:9000/info MEMGRAPH_HOST=localhost # default: localhost MEMGRAPH_PORT=7687 # default: 7687 MCP_PORT=9000 # default: 9000 -LXRAG_PROJECT_ID=my-repo # optional default project namespace -LXRAG_USE_TREE_SITTER=true # enable tree-sitter AST parsers +LXDIG_PROJECT_ID=my-repo # optional default project namespace +LXDIG_USE_TREE_SITTER=true # enable tree-sitter AST parsers ``` ## Build & Run @@ -205,12 +204,11 @@ All tools accept `profile` parameter: ``` src/ - server.ts MCP HTTP surface (33 tools) - mcp-server.ts stdio MCP surface + server.ts MCP HTTP surface (39 tools) index.ts legacy stdio entry config.ts environment config tools/ - tool-handlers.ts all 33 tool implementations + tool-handlers.ts all 39 tool implementations graph/ orchestrator.ts file discovery + parse dispatch + Memgraph writes client.ts Memgraph Bolt client @@ -230,7 +228,7 @@ src/ episode-engine.ts coordination-engine.ts community-detector.ts - migration-engine.ts + migration-engine.ts Schema migration helpers (internal, not exposed as tools) vector/ embedding-engine.ts qdrant-client.ts diff --git a/ERROR_REPORT.md b/ERROR_REPORT.md index 5f46fa2..12231da 100644 --- a/ERROR_REPORT.md +++ b/ERROR_REPORT.md @@ -1,4 +1,4 @@ -# lxRAG Analysis - Error Report +# lxDIG Analysis - Error Report ## Errors Encountered @@ -6,10 +6,10 @@ **Status**: CRITICAL **Error Message**: `TypeError: Cannot mix BigInt and other types, use explicit conversions` -**Tool**: `mcp_lxrag_graph_health` +**Tool**: `mcp_lxdig_graph_health` **Severity**: Recoverable -**Description**: The lxRAG backend is throwing type conversion errors when attempting to query graph health metrics. This appears to be a backend implementation issue where BigInt values are being mixed with other numeric types without proper type conversion. +**Description**: The lxDIG backend is throwing type conversion errors when attempting to query graph health metrics. This appears to be a backend implementation issue where BigInt values are being mixed with other numeric types without proper type conversion. **Impact**: @@ -22,7 +22,7 @@ ### 2. Tool Not Available **Status**: ERROR -**Tool**: `mcp_lxrag_search_docs` +**Tool**: `mcp_lxdig_search_docs` **Error**: Tool is currently disabled by user **Reason**: Documentation search feature is not enabled in the current environment @@ -46,7 +46,7 @@ **Current Issues**: -- Empty graph results from `mcp_lxrag_context_pack` +- Empty graph results from `mcp_lxdig_context_pack` - No entry points found - No symbols detected - No decisions/learnings/episodes available yet @@ -57,15 +57,15 @@ | Operation | Status | Result | | ------------------------------ | ---------- | ----------------------------------------- | -| `mcp_lxrag_init_project_setup` | ✓ OK | Project initialized, graph rebuild queued | -| `mcp_lxrag_graph_health` | ✗ FAILED | BigInt type conversion error | -| `mcp_lxrag_graph_rebuild` | ✓ QUEUED | Full rebuild initiated (in progress) | -| `mcp_lxrag_index_docs` | ✓ OK | 26 markdown files indexed successfully | -| `mcp_lxrag_context_pack` | ✓ OK | No data returned (graph still building) | -| `mcp_lxrag_reflect` | ✓ OK | 0 episodes found (graph empty) | -| `mcp_lxrag_find_pattern` | ✓ OK | Pattern search implemented but no results | -| `mcp_lxrag_arch_validate` | ✓ OK | 0 violations, 0 files checked | -| `mcp_lxrag_search_docs` | ✗ DISABLED | Tool not available in environment | +| `mcp_lxdig_init_project_setup` | ✓ OK | Project initialized, graph rebuild queued | +| `mcp_lxdig_graph_health` | ✗ FAILED | BigInt type conversion error | +| `mcp_lxdig_graph_rebuild` | ✓ QUEUED | Full rebuild initiated (in progress) | +| `mcp_lxdig_index_docs` | ✓ OK | 26 markdown files indexed successfully | +| `mcp_lxdig_context_pack` | ✓ OK | No data returned (graph still building) | +| `mcp_lxdig_reflect` | ✓ OK | 0 episodes found (graph empty) | +| `mcp_lxdig_find_pattern` | ✓ OK | Pattern search implemented but no results | +| `mcp_lxdig_arch_validate` | ✓ OK | 0 violations, 0 files checked | +| `mcp_lxdig_search_docs` | ✗ DISABLED | Tool not available in environment | --- @@ -126,7 +126,7 @@ Working Categories: **Files Affected**: src/index.ts, src/mcp-server.ts, src/engines/\*\* **Resolution Applied**: -Created `.lxrag/config.json` with layer definitions and import rules. +Created `.lxdig/config.json` with layer definitions and import rules. ### Finding #2: Backend BigInt Error @@ -140,7 +140,7 @@ Created `.lxrag/config.json` with layer definitions and import rules. - Added regression test: `handles BigInt metrics in graph_health without type errors` **Current Gap**: -`mcp_lxrag_graph_health` tool still reports the same error from the active hosted/runtime process, indicating deployment/runtime mismatch rather than source-code mismatch. +`mcp_lxdig_graph_health` tool still reports the same error from the active hosted/runtime process, indicating deployment/runtime mismatch rather than source-code mismatch. ### Finding #3: Graph Still Building @@ -161,7 +161,7 @@ Created `.lxrag/config.json` with layer definitions and import rules. 2. **Post-restart validation**: -- Re-run `mcp_lxrag_graph_health` +- Re-run `mcp_lxdig_graph_health` - Confirm it no longer returns BigInt type errors. 3. **Proceed with plan**: @@ -174,7 +174,7 @@ Created `.lxrag/config.json` with layer definitions and import rules. For complete analysis and plan, see: -- **LXRAG_ANALYSIS_REPORT.md** - Detailed findings & task catalog +- **LXDIG_ANALYSIS_REPORT.md** - Detailed findings & task catalog - **RESOLUTION_PLAN.md** - Step-by-step implementation guide - **PROJECT_ANALYSIS_SUMMARY.md** - Executive overview @@ -182,12 +182,12 @@ For complete analysis and plan, see: ## Environment Details -- **Project**: lexrag-mcp -- **Workspace Root**: `/home/alex_rod/projects/lexRAG-MCP` +- **Project**: lexdig-mcp +- **Workspace Root**: `/home/alex_rod/projects/lexDIG-MCP` - **Source Dir**: `src` - **Graph Mode**: Full rebuild - **Analysis Date**: 2026-02-22 -- **Analysis Method**: lxRAG Tools Only (no file reads) +- **Analysis Method**: lxDIG Tools Only (no file reads) - **Tools Used**: 12/38 - **Documents Indexed**: 26 - **Analysis Duration**: ~15 minutes @@ -229,7 +229,7 @@ For complete analysis and plan, see: ``` Phase 1: Backend Configuration - ├─ Configuration Missing ❌ [CRITICAL] → FIX: create .lxrag/config.json + ├─ Configuration Missing ❌ [CRITICAL] → FIX: create .lxdig/config.json ├─ BigInt Error ⚠️ [CRITICAL] → FIX: backend type conversions ├─ Graph Rebuilding ⏳ [HIGH] → WAIT: 2-5 minutes └─ Estimated Time to Resolve: 1 day @@ -253,7 +253,7 @@ Overall Status: 95% Ready → 5% Blocked by External Runtime Sync ## Analysis Completion -✓ All available lxRAG tools executed +✓ All available lxDIG tools executed ✓ All errors documented ✓ All findings analyzed ✓ Complete resolution plan created diff --git a/QUICK_REFERENCE.md b/QUICK_REFERENCE.md index ac577ea..6f2a1dd 100644 --- a/QUICK_REFERENCE.md +++ b/QUICK_REFERENCE.md @@ -1,4 +1,4 @@ -# lxRAG MCP — Quick Reference +# lxDIG MCP — Quick Reference ## Session Flow (MCP HTTP) @@ -28,7 +28,7 @@ npm run start:http curl http://localhost:9000/health ``` -## 33 MCP Tools +## 39 MCP Tools ### Graph / Querying @@ -104,9 +104,25 @@ curl http://localhost:9000/health ### Utility -| Tool | Purpose | -| ------------------- | ---------------------------------- | -| `contract_validate` | Normalize and validate tool inputs | +| Tool | Purpose | +| ------------------- | ------------------------------------------- | +| `contract_validate` | Normalize and validate tool inputs | +| `tools_list` | List all registered tools with descriptions | + +### Setup + +| Tool | Purpose | +| ---------------------------- | ---------------------------------------------- | +| `init_project_setup` | One-shot workspace init: set context + rebuild | +| `setup_copilot_instructions` | Generate `.github/copilot-instructions.md` | + +### Docs & Reference + +| Tool | Purpose | +| ------------- | ------------------------------------------- | +| `index_docs` | Index markdown documentation into the graph | +| `search_docs` | Search indexed docs by text or symbol | +| `ref_query` | Query a reference repository for patterns | ## Common Workflows @@ -149,13 +165,13 @@ curl http://localhost:9000/health MEMGRAPH_HOST=localhost # default: localhost MEMGRAPH_PORT=7687 # default: 7687 MCP_PORT=9000 # default: 9000 -LXRAG_PROJECT_ID=my-repo # optional: default project namespace -LXRAG_USE_TREE_SITTER=true # enable AST-accurate parsers (requires optional deps) +LXDIG_PROJECT_ID=my-repo # optional: default project namespace +LXDIG_USE_TREE_SITTER=true # enable AST-accurate parsers (requires optional deps) ``` ## Tree-sitter Parsers -When `LXRAG_USE_TREE_SITTER=true`, AST-accurate parsers activate for: +When `LXDIG_USE_TREE_SITTER=true`, AST-accurate parsers activate for: | Language | Extensions | Fallback | | ---------- | --------------------- | -------------- | @@ -181,7 +197,7 @@ Grammars are `optionalDependencies` — missing grammars fall back silently. | Other language parsers | `src/parsers/tree-sitter-parser.ts` | | Engines | `src/engines/` | | Docker stack | `docker-compose.yml` | -| Runbook | `docs/GRAPH_EXPERT_AGENT.md` | +| Runbook | `docs/TOOL_PATTERNS.md` | ## Troubleshooting diff --git a/QUICK_START.md b/QUICK_START.md index 9b7576f..48728d4 100644 --- a/QUICK_START.md +++ b/QUICK_START.md @@ -1,6 +1,6 @@ -# Setup & Quick Start — LxRAG MCP Server +# Setup & Quick Start — lxDIG MCP Server -Everything you need to go from zero to a fully wired LxRAG instance: infrastructure up, server running, your project indexed, and your editor connected. +Everything you need to go from zero to a fully wired lxDIG instance: infrastructure up, server running, your project indexed, and your editor connected. The server supports two transports — pick the one that matches your client: @@ -25,8 +25,8 @@ Both transports expose all 38 tools and require the same infrastructure (Memgrap | VS Code | 1.99+ (for MCP agent mode in Copilot) | ```bash -git clone https://github.com/lexCoder2/lxRAG-MCP.git -cd lxRAG-MCP +git clone https://github.com/lexCoder2/lxDIG-MCP.git +cd lxDIG-MCP npm install && npm run build ``` @@ -155,10 +155,10 @@ Create `.vscode/mcp.json` in the root of **your project** and commit it. VS Code ```json { "servers": { - "lxrag": { + "lxdig": { "type": "stdio", "command": "node", - "args": ["/absolute/path/to/lxRAG-MCP/dist/server.js"], + "args": ["/absolute/path/to/lxDIG-MCP/dist/server.js"], "env": { "MCP_TRANSPORT": "stdio", "MEMGRAPH_HOST": "localhost", @@ -182,7 +182,7 @@ Open Copilot Chat → switch to **Agent** mode → the 38 tools are available im ```json { "servers": { - "lxrag": { + "lxdig": { "type": "http", "url": "http://localhost:9000/mcp" } @@ -194,7 +194,7 @@ Or add it globally via **VS Code Settings** (`Cmd/Ctrl+,`) → search `mcp`: ```json "github.copilot.chat.mcp.servers": { - "lxrag": { + "lxdig": { "type": "http", "url": "http://localhost:9000/mcp" } @@ -228,7 +228,7 @@ Edit the config file for your OS: "mcpServers": { "code-graph": { "command": "node", - "args": ["/absolute/path/to/lxRAG-MCP/dist/server.js"], + "args": ["/absolute/path/to/lxDIG-MCP/dist/server.js"], "env": { "MCP_TRANSPORT": "stdio", "MEMGRAPH_HOST": "localhost", @@ -257,7 +257,7 @@ Copy the provided instructions template into **your project** so your agent auto ```bash mkdir -p /path/to/your-project/.github -cp /path/to/lxRAG-MCP/.github/copilot-instructions.md \ +cp /path/to/lxDIG-MCP/.github/copilot-instructions.md \ /path/to/your-project/.github/copilot-instructions.md ``` diff --git a/README.md b/README.md index 6c44b10..8bc61a0 100644 --- a/README.md +++ b/README.md @@ -1,227 +1,217 @@
- lxRAG MCP Logo -
- LxRAG MCP -

short for lexic RAG

-

A memory and code intelligence layer for LLM agents.

+ lxDIG MCP — Code Graph Intelligence for AI Coding Agents +

lxDIG MCP

+

Dynamic Intelligence Graph · Agent Memory · Multi-Agent Coordination

+

A Dynamic Intelligence Graph (DIG) MCP server that gives AI coding assistants persistent memory,
structural code understanding, and safe multi-agent coordination — beyond static RAG and GraphRAG.

-![MCP](https://img.shields.io/badge/MCP-JSON--RPC%202.0-7A52F4) -![Transport](https://img.shields.io/badge/Transport-stdio%20%7C%20http-0EA5E9) -![Runtime](https://img.shields.io/badge/Node.js-24%2B-339933) -![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178C6) -![Graph](https://img.shields.io/badge/Graph-Memgraph-00B894) -![License](https://img.shields.io/badge/License-MIT-F59E0B) +[![MCP](https://img.shields.io/badge/MCP-JSON--RPC%202.0-7A52F4?logo=data:image/svg+xml;base64,)](https://modelcontextprotocol.io) +[![npm](https://img.shields.io/badge/npm-%40stratsolver%2Fgraph--server-CB3837?logo=npm)](https://www.npmjs.com/package/@stratsolver/graph-server) +[![Node.js](https://img.shields.io/badge/Node.js-24%2B-339933?logo=nodedotjs)](https://nodejs.org) +[![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178C6?logo=typescript)](https://www.typescriptlang.org) +[![Memgraph](https://img.shields.io/badge/Graph-Memgraph-00B894)](https://memgraph.com) +[![Qdrant](https://img.shields.io/badge/Vector-Qdrant-DC244C)](https://qdrant.tech) +[![License: MIT](https://img.shields.io/badge/License-MIT-F59E0B)](LICENSE) +[![Tests](https://img.shields.io/badge/Tests-402%20passing-22C55E)](src) +[![Transport](https://img.shields.io/badge/Transport-stdio%20%7C%20HTTP-0EA5E9)](QUICK_START.md) +[![Status](https://img.shields.io/badge/Status-Beta-orange)](QUICK_START.md)
--- -LxRAG Server is your MCP-native memory and code intelligence layer for smarter, faster AI-assisted development. +> **Works with:** VS Code Copilot · Claude Code · Claude Desktop · Cursor · any MCP-compatible AI assistant -Turn your repository into a queryable graph so your agents can answer architecture, impact, and planning questions without re-reading the entire codebase on every turn — and so you can stop wasting context budget on files that haven't changed. - -**[→ QUICK_START.md](QUICK_START.md)** — deploy, connect your vscode editor with ease, wire Copilot or Claude, make your first query (~5 min). -**[→ QUICK_REFERENCE.md](QUICK_REFERENCE.md)** — all 38 tools with parameters, look the process. - -If you find this project helpful (I hope you do) consider [buying me a coffee ☕](https://buymeacoffee.com/hi8g) +--- -## At a glance +## What is lxDIG MCP? -| Capability | What you get | -| --------------------------- | --------------------------------------------------------------------- | -| **Code graph intelligence** | Cross-file dependency answers instead of raw file dumps | -| **Agent memory** | Persistent decisions and episodes that survive session restarts | -| **Hybrid retrieval** | Better relevance for natural-language code questions | -| **Temporal model** | Historical queries (`asOf`) and change diffs (`diff_since`) | -| **Test intelligence** | Impact-scoped test selection so you only run what matters | -| **Docs & ADR indexing** | Search your READMEs and decision records the same way you search code | -| **MCP-native runtime** | Works with VS Code Copilot, Claude, and any MCP-compatible client | +**lxDIG MCP** (_lexic Dynamic Intelligence Graph_) is an open-source [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that adds a **persistent code intelligence layer** to AI coding assistants. Unlike static RAG or batch-oriented GraphRAG, lxDIG is a live, incrementally-updated intelligence graph that turns any repository into a queryable knowledge graph — so agents can answer architectural questions, track decisions across sessions, coordinate safely in multi-agent workflows, and run only the tests that actually changed — without re-reading the entire codebase on every turn. -## Why you need this +It is purpose-built for the **agentic coding loop**: the cycle of understand → plan → implement → verify → remember that AI agents (Claude, Copilot, Cursor) repeat continuously. -Most code intelligence tools cover one layer — RAG embeddings, graph structure, or agent memory — but not all three. That means: +**The core problem it solves:** most AI coding assistants are stateless and architecturally blind. They re-read unchanged files on every session, miss cross-file relationships, forget past decisions, and collide when multiple agents work in parallel. lxDIG is the memory and structure layer that fixes all four. -- ❌ Context lost between sessions — re-reading unchanged files on every restart -- ❌ Probabilistic retrieval misses architectural relationships -- ❌ No temporal reasoning — can't query past states or track change impact -- ❌ Multi-agent collisions with no built-in coordination +--- -### The LxRAG Advantage +## Table of Contents + +- [Why lxDIG?](#why-lxdig) +- [Key capabilities](#key-capabilities) +- [How it works](#how-it-works) +- [Quick start](#quick-start) +- [38 MCP tools — at a glance](#38-mcp-tools--at-a-glance) +- [Use cases](#use-cases) +- [Comparison with alternatives](#comparison-with-alternatives) +- [Performance](#performance) +- [Roadmap](#roadmap) +- [Contributing](#contributing) +- [Support the project](#support-the-project) +- [License](#license) -LxRAG uniquely combines all three layers purpose-built for code: +--- -**1. Graph Structure — not RAG embeddings** +## Why lxDIG? -- Files, symbols, and relationships in a queryable graph (Memgraph) -- **Deterministic structural reasoning** (vs probabilistic embeddings) -- Cross-file dependency answers instead of relevance-ranked chunks -- Understands architecture; embeddings miss it +Most code intelligence tools solve **one** of these problems. lxDIG solves all of them together: -**2. Session Persistence & Agent Memory — survives restarts** +| Problem | Without lxDIG | With lxDIG | +| ----------------------------------- | ------------------------------------------------- | ---------------------------------------------------------- | +| **Context loss between sessions** | Agent re-reads everything on restart | Persistent episode + decision memory survives restarts | +| **Architecturally blind retrieval** | Embeddings miss cross-file relationships | Graph traversal finds structural dependencies | +| **Probabilistic search misses** | Semantic search returns nearest chunks, not facts | Hybrid graph + vector + BM25 fused with RRF | +| **Multi-agent collisions** | Two agents edit the same file simultaneously | Claims/release protocol with conflict detection | +| **Wasted CI time** | Full test suite on every change | Impact-scoped test selection — only affected tests run | +| **Stale architecture knowledge** | Agent guesses at layer boundaries | Graph-validated architecture rules + placement suggestions | +| **Queries eat context budget** | Raw file dumps, hundreds of tokens per answer | Cross-file answers in compact, budget-aware responses | -- Persistent episode memory: observations, decisions, edits, test results -- Temporal reasoning: query code state at any point in history (`asOf`, `diff_since`) -- Claims/release workflow prevents multi-agent collisions -- **No external database setup required** (baked into Memgraph) +--- -**3. Hybrid Retrieval — graph + vector + BM25** +## Key capabilities -- Graph traversal (finds architectural connections) -- Vector similarity (finds semantic concepts) -- BM25 lexical search (finds keywords) -- Reciprocal Rank Fusion merges all three signals -- **Result**: 10x-6000x more accurate than embeddings alone +### 1. Code graph intelligence -**4. MCP Tools — 38 deterministic, automatable actions** +Turn your repository into a **queryable property graph** of files, functions, classes, imports, and their relationships. Ask questions in plain English or Cypher. -- `graph_query` — Natural language + Cypher code discovery -- `code_explain` — Full dependency context (not just definition) -- `impact_analyze` — Blast radius of changes (not manual checking) -- `test_select` — Exact affected tests (not full suite) -- `arch_validate` — Rule-based violation detection (not keyword search) -- - 33 more specialized tools built for code intelligence +- Natural-language + Cypher graph queries (`graph_query`) +- Symbol-level explanation with full dependency context (`code_explain`) +- Pattern detection and architecture rule validation (`find_pattern`, `arch_validate`) +- Architecture placement suggestions for new code (`arch_suggest`) +- Semantic code slicing — targeted line ranges from a natural query (`semantic_slice`) +- Find duplicate or similar code across the codebase (`find_similar_code`, `code_clusters`) -### What lxRAG covers that others don't +### 2. Persistent agent memory -| Capability | lxRAG | Others | -|---|---|---| -| Session persistence | ✅ Native | ❌ / ⚠️ External setup | -| Agent memory + temporal reasoning | ✅ Episodes + `asOf` | ❌ Not available | -| Cross-file graph reasoning | ✅ Graph edges | ⚠️ Shallow or manual | -| Multi-agent safety | ✅ Claims/releases | ❌ No coordination | -| Impact-scoped test selection | ✅ Built-in | ❌ Full suite or manual | -| Architecture validation | ✅ Rule-based | ❌ Generic or none | -| Open source / cost | ✅ MIT · $0 | ❌/⚠️ Closed or paid | +Your agent **remembers** what it decided, what it changed, what broke, and what it observed — even after a VS Code restart or a Claude Desktop session ends. -### Performance Gains +- Episode memory: observations, decisions, edits, test results, errors, learnings (`episode_add`, `episode_recall`) +- Decision log with semantic query (`decision_query`) +- Reflection synthesis from recent episodes (`reflect`) +- Temporal graph model: query any past code state with `asOf`, compare drift with `diff_since` -**vs Grep/Manual (9x-6000x faster, <1% false positives)** -**vs Vector RAG (5x token savings, 10x more relevant)** +### 3. Multi-agent coordination -## What you get +Run **multiple AI agents in parallel** on the same repository without conflicts. -### 1) Code intelligence on demand +- Claim/release protocol for file, function, or task ownership (`agent_claim`, `agent_release`) +- Fleet-wide coordination view — see what every agent is doing (`coordination_overview`, `agent_status`) +- Context packs that assemble high-signal task briefings under strict token budgets (`context_pack`) +- Blocker detection across agents and tasks (`blocking_issues`) -Ask questions about your codebase in plain English or Cypher — your agent gets cross-file dependency answers, not raw file dumps. +### 4. Test and change intelligence -- Natural-language and Cypher graph querying via `graph_query` -- Symbol-level explanation with full dependency context (`code_explain`) -- Pattern detection and architecture rule validation (`find_pattern`, `arch_validate`) -- Semantic code slicing for targeted line ranges (`semantic_slice`) +Stop running your **full test suite** on every change. Know exactly what's affected. -### 2) Memory that survives sessions +- Change impact analysis — blast radius of modified files (`impact_analyze`) +- Selective test execution — only the tests that can fail (`test_select`, `test_run`) +- Test categorization for parallelization and prioritization (`test_categorize`, `suggest_tests`) -Your agent remembers what it decided, what it changed, and what broke — even after a VS Code restart. +### 5. Documentation as a first-class knowledge source -- Persistent episode memory: observations, decisions, edits, test results, errors -- Claim/release workflow to prevent multi-agent collisions -- Coordination views so you always know what's in flight +Your **READMEs, ADRs, and changelogs** become searchable graph nodes, linked to the code they describe. -### 3) Smarter test runs +- Index all markdown docs in one call (`index_docs`) +- Full-text BM25 search across headings and content (`search_docs?query=...`) +- Symbol-linked lookup — every doc that references a class or function (`search_docs?symbol=MyClass`) +- Incremental re-index: only changed files are re-parsed -Stop running your full test suite on every change. LxRAG tells your agent exactly which tests are affected. +### 6. Architecture governance -- Impact analysis scoped to changed files (`impact_analyze`) -- Selective test execution — only tests that can actually fail (`test_select`, `test_run`) -- Test categorisation for parallelisation and prioritisation (`test_categorize`, `suggest_tests`) +Enforce **architectural boundaries** automatically and get placement guidance for new code. -### 4) Documentation you can query like code +- Layer/boundary rule validation (`arch_validate`) +- Graph-topology-aware placement suggestions (`arch_suggest`) +- Circular dependency and unused-code detection (`find_pattern`) -Your READMEs, architecture decision records, and changelogs become first-class searchable graph nodes. +### 7. One-shot project setup -- Index all markdown docs in one call (`index_docs`) -- BM25 full-text search across headings and content (`search_docs?query=...`) -- Symbol-linked lookup — find every doc that references a class or function (`search_docs?symbol=MyClass`) -- Incremental re-index: only changed files are re-parsed on subsequent runs +Go from a fresh clone to a fully wired AI assistant in **one tool call**. -### 5) Delivery acceleration +- `init_project_setup` — sets workspace, rebuilds graph, generates Copilot instructions +- `setup_copilot_instructions` — generates `.github/copilot-instructions.md` from your repo's topology +- Works with VS Code Copilot, Claude Code, Claude Desktop, and any MCP-compatible client -- Graph-backed progress and task tracking (`progress_query`, `task_update`, `feature_status`) -- Context packs that assemble high-signal context under strict token budgets (`context_pack`) -- Blocker detection across tasks and agents (`blocking_issues`) +--- ## How it works -LxRAG runs as an MCP server over stdio or HTTP and coordinates three data planes behind a single tool interface: +lxDIG runs as an **MCP server** over stdio or HTTP and coordinates three data planes behind a single tool interface: + +``` +┌─────────────────────────────────────────────────────────────┐ +│ MCP Tool Surface (39 tools) │ +│ stdio transport (local) │ HTTP transport (remote/fleet) │ +└──────────────┬────────────┴────────────────┬────────────────┘ + │ │ + ┌───────────▼────────────┐ ┌────────────▼────────────┐ + │ Graph Plane │ │ Vector Plane │ + │ Memgraph (Bolt) │ │ Qdrant │ + │ ───────────────── │ │ ───────────────────── │ + │ FILE · FUNC · CLASS │ │ Semantic embeddings │ + │ IMPORT · CALL edges │ │ Nearest-neighbor search│ + │ Temporal tx history │ │ Natural-language code │ + └────────────────────────┘ └─────────────────────────┘ + │ + ┌───────────▼────────────────────────────────────────────┐ + │ Hybrid Retrieval (RRF fusion) │ + │ Graph expansion + Vector similarity + BM25 lexical │ + └────────────────────────────────────────────────────────┘ +``` -- **Graph plane (Memgraph)** — structural and temporal truth: FILE, FUNCTION, CLASS, IMPORT nodes + relationships + full transaction history -- **Vector plane (Qdrant)** — semantic retrieval for natural-language questions; optional but recommended for large codebases -- **Response plane** — answer-first shaping with profile budgets so you choose between token-light (`compact`) and detail-rich (`debug`) responses +When you call `graph_query` in natural language mode, retrieval runs as **hybrid fusion**: -When you call `graph_query` in natural mode, retrieval runs as hybrid fusion: +1. Vector similarity search (semantic concepts) +2. BM25 lexical search (keyword matches) +3. Graph expansion from seed nodes (structural relationships) +4. **Reciprocal Rank Fusion (RRF)** merges all three signals into a single ranked result -1. Vector similarity search -2. BM25 / lexical search (Memgraph `text_search` when available, local fallback otherwise) -3. Graph expansion from seed nodes -4. Reciprocal Rank Fusion (RRF) merges all signals into a single ranked list +The result: structurally accurate, semantically relevant answers — not just the closest embedding match. ### System diagram ![System Architecture](docs/diagrams/system-architecture.svg) -## Tooling surface - -The server exposes **38 MCP tools** across: - -- Graph/querying (4): `graph_set_workspace`, `graph_rebuild`, `graph_health`, `graph_query` -- Code intelligence (5): `code_explain`, `find_pattern`, `semantic_slice`, `context_pack`, `diff_since` -- Architecture (2): `arch_validate`, `arch_suggest` -- Semantic/similarity (4): `semantic_search`, `find_similar_code`, `code_clusters`, `semantic_diff` -- Test intelligence (5): `test_select`, `test_categorize`, `impact_analyze`, `test_run`, `suggest_tests` -- Progress/operations (4): `progress_query`, `task_update`, `feature_status`, `blocking_issues` -- Memory/coordination (8): `episode_add`, `episode_recall`, `decision_query`, `reflect`, `agent_claim`, `agent_release`, `agent_status`, `coordination_overview` -- Runtime controls (1): `contract_validate` -- Documentation (2): `index_docs`, `search_docs` -- Reference (1): `ref_query` — query a sibling repo for architecture insights, patterns, and code examples -- Setup (2): `init_project_setup`, `setup_copilot_instructions` — one-shot onboarding and AI assistant scaffolding +--- ## Quick start -> **Recommended setup:** run Memgraph and Qdrant in Docker (`docker compose up -d memgraph qdrant`), then run the MCP server on your host via stdio. Your editor spawns the process directly — native filesystem paths, no HTTP port, no session headers. +> **Recommended setup:** Memgraph + Qdrant in Docker, MCP server on your host via stdio. Your editor spawns and owns the process — no HTTP ports, no session headers. ### Prerequisites -- Node.js 24+ -- Docker + Docker Compose - -> See [QUICK_START.md](QUICK_START.md) for full VS Code + Copilot/Claude wiring instructions. +| Requirement | Version | +| ----------------------- | -------- | +| Node.js | 24+ | +| Docker + Docker Compose | 24+ (v2) | -### 1) Clone and build +### 1. Clone and build ```bash -git clone https://github.com/lexCoder2/lxRAG-MCP.git -cd lxRAG-MCP +git clone https://github.com/lexCoder2/lxDIG-MCP.git +cd lxDIG-MCP npm install && npm run build ``` -### 2) Start the databases - -Launch only Memgraph and Qdrant — the MCP server runs locally via stdio, not in Docker: +### 2. Start the databases ```bash docker compose up -d memgraph qdrant +docker compose ps # wait for "healthy" (~30 s) ``` -Verify they are healthy: - -```bash -docker compose ps memgraph qdrant # both should show "healthy" / "running" -``` +### 3. Wire your editor -### 3) Configure stdio in your editor - -**VS Code** — add to your `.vscode/mcp.json` (or user `settings.json`): +**VS Code — add to `.vscode/mcp.json`:** ```json { "servers": { - "lxrag": { + "lxdig": { "type": "stdio", "command": "node", - "args": ["/absolute/path/to/lxRAG-MCP/dist/server.js"], + "args": ["/absolute/path/to/lxDIG-MCP/dist/server.js"], "env": { "MCP_TRANSPORT": "stdio", "MEMGRAPH_HOST": "localhost", @@ -234,14 +224,14 @@ docker compose ps memgraph qdrant # both should show "healthy" / "running" } ``` -**Claude Desktop** — add to `claude_desktop_config.json`: +**Claude Desktop — add to `claude_desktop_config.json`:** ```json { "mcpServers": { - "lxrag": { + "lxdig": { "command": "node", - "args": ["/absolute/path/to/lxRAG-MCP/dist/server.js"], + "args": ["/absolute/path/to/lxDIG-MCP/dist/server.js"], "env": { "MCP_TRANSPORT": "stdio", "MEMGRAPH_HOST": "localhost", @@ -254,9 +244,7 @@ docker compose ps memgraph qdrant # both should show "healthy" / "running" } ``` -### 4) Initialize your project - -Once the server is connected in your editor, run this single tool call to set context, index the graph, and generate copilot instructions in one step: +### 4. Initialize your project (one call) ```json { @@ -269,168 +257,219 @@ Once the server is connected in your editor, run this single tool call to set co } ``` -That's it — the graph rebuild runs in the background and your project is ready to query. +This single call sets the workspace context, rebuilds the code graph, and generates `.github/copilot-instructions.md` for your project. Your agent is ready to query. -### Session flow diagram +**Total setup time: ~5 minutes.** See [QUICK_START.md](QUICK_START.md) for the full guide including Docker, Claude Desktop, and HTTP transport. -![MCP HTTP Session Flow](docs/diagrams/mcp-session-flow.svg) +--- -### Visual examples +## 38 MCP tools — at a glance + +| Category | Tools | What they do | +| ------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------- | +| **Graph / querying** | `graph_set_workspace` `graph_rebuild` `graph_health` `graph_query` | Index and query the code graph | +| **Code intelligence** | `code_explain` `find_pattern` `semantic_slice` `context_pack` `diff_since` | Understand structure and change | +| **Architecture** | `arch_validate` `arch_suggest` | Enforce boundaries, guide placement | +| **Semantic / similarity** | `semantic_search` `find_similar_code` `code_clusters` `semantic_diff` | Find related code by meaning | +| **Test intelligence** | `test_select` `test_categorize` `impact_analyze` `test_run` `suggest_tests` | Run only what matters | +| **Progress / ops** | `progress_query` `task_update` `feature_status` `blocking_issues` | Track delivery and blockers | +| **Agent memory** | `episode_add` `episode_recall` `decision_query` `reflect` | Persist and retrieve agent knowledge | +| **Coordination** | `agent_claim` `agent_release` `agent_status` `coordination_overview` | Safe multi-agent parallelism | +| **Documentation** | `index_docs` `search_docs` | Search your READMEs and ADRs like code | +| **Reference** | `ref_query` | Query a sibling repo for patterns and examples | +| **Setup** | `init_project_setup` `setup_copilot_instructions` `contract_validate` `tools_list` | One-shot onboarding | -| Workflow | Minimal tool sequence | Outcome | -| ------------------------------ | ------------------------------------------------------ | ---------------------------------------------- | -| **Boot a project context** | `initialize` → `graph_set_workspace` → `graph_rebuild` | Graph becomes query-ready for that MCP session | -| **Understand a subsystem** | `graph_query` → `code_explain` → `semantic_slice` | Dependency map + concrete code slice | -| **Plan safe changes** | `impact_analyze` → `test_select` → `test_run` | Change radius + focused test execution | -| **Coordinate multiple agents** | `agent_claim` → `context_pack` → `task_update` | Ownership, task context, and durable progress | +--- -#### Example A — Set workspace context +## Use cases -```json -{ - "name": "graph_set_workspace", - "arguments": { - "workspaceRoot": "/workspace", - "sourceDir": "src", - "projectId": "my-repo" - } -} -``` +### Individual developer — Claude Code or VS Code Copilot -#### Example B — Natural graph query +- Ask "what calls `AuthService.login` across the whole repo?" and get a graph answer, not a file dump +- Resume a refactoring task after a VS Code restart — your agent remembers every decision +- Run `impact_analyze` before committing — know exactly which tests to run +- Use `arch_validate` to catch layer violations before they become bugs -```json -{ - "name": "graph_query", - "arguments": { - "query": "find key graph files", - "language": "natural", - "mode": "local", - "limit": 5 - } -} -``` +### Engineering team — multi-agent workflows -#### Example C — Context pack for an active task +- Run a planning agent and an implementation agent in parallel without file conflicts +- Use `coordination_overview` to see what every agent is working on +- `context_pack` hands off a high-signal task briefing between agents in one call +- Persistent decision memory means the second agent doesn't repeat work the first already did -```json -{ - "name": "context_pack", - "arguments": { - "task": "stabilize hybrid retrieval outputs", - "taskId": "PHASE8-RET-01", - "agentId": "agent-copilot", - "profile": "compact" - } -} -``` +### CI / automation pipeline -## Runtime modes +- `graph_health` as a startup readiness gate +- `test_select` + `test_run` for impact-scoped CI that's 5–10x faster than full suite +- `arch_validate` as an automated architecture compliance check on every PR -- **stdio** ✅ recommended for local editor integrations (VS Code, Claude Desktop, Cursor) — simplest setup, no HTTP port or session headers needed -- **http** — for multi-client agent fleets, remote access, or automation pipelines that need concurrent sessions +### Repository onboarding -### Useful scripts +- `init_project_setup` on a new codebase — graph + copilot instructions in ~30 seconds +- `code_explain` to understand unfamiliar subsystems with full dependency context +- `setup_copilot_instructions` generates AI assistant instructions tailored to your repo's topology -```bash -npm run start # stdio server (recommended for editor use) -npm run start:http # HTTP supervisor (multi-session / remote) -npm run build # compile TypeScript -npm test # run all 109 tests -``` +--- -## Repository map +## Comparison with alternatives -| Path | What's inside | -| ------------------------------------ | ------------------------------------------------------------------- | -| `src/server.ts`, `src/mcp-server.ts` | MCP / HTTP transport surfaces | -| `src/tools/tool-handlers.ts` | all 35 tool implementations | -| `src/graph/` | graph client, orchestrator, hybrid retriever, watcher, docs builder | -| `src/engines/` | architecture, test, progress, community, episode, docs engines | -| `src/parsers/` | AST and markdown parsers (tree-sitter + regex fallback) | -| `src/response/` | response shaping, profile budgets, summarization | -| `docs/AGENT_CONTEXT_ENGINE_PLAN.md` | implementation plan and phase status | -| `docs/GRAPH_EXPERT_AGENT.md` | full agent runbook | +| Feature | lxDIG MCP | Plain RAG / embeddings | GitHub Copilot (built-in) | Custom LangChain agent | +| ------------------------------- | ------------------------ | ---------------------- | ------------------------- | ---------------------- | +| Cross-file structural reasoning | ✅ Graph edges | ❌ Chunks only | ⚠️ Limited | ⚠️ Manual setup | +| Persistent agent memory | ✅ Episodes + decisions | ❌ Stateless | ❌ Stateless | ⚠️ Custom DB needed | +| Multi-agent coordination | ✅ Claims/releases | ❌ None | ❌ None | ❌ Custom setup | +| Temporal code model | ✅ `asOf` + `diff_since` | ❌ | ❌ | ❌ | +| Impact-scoped test selection | ✅ Built-in | ❌ | ❌ | ❌ | +| Architecture validation | ✅ Rule-based | ❌ | ❌ | ❌ | +| MCP-native (any AI client) | ✅ 39 tools | ❌ | ❌ | ❌ | +| Open source / self-hosted | ✅ MIT | ⚠️ Varies | ❌ Closed | ✅ | +| Setup complexity | Medium (Docker) | Low | None | High | + +--- + +## Performance + +Benchmarks run against a synthetic 20-scenario agent task suite (`benchmarks/`): + +| Metric | Result | +| ----------------------------------------------------------- | ----------------------------------------------- | +| Scenarios where lxDIG was faster than baseline | **15 / 20** | +| MCP-only successful scenarios (baseline could not complete) | **4 / 20** | +| vs Grep / manual file reads | **9x–6000x faster**, <1% false positives | +| vs pure vector RAG | **5x token savings**, 10x more relevant results | + +> Benchmarks are workload-dependent. Run `npm run benchmark:check-regression` against your own repository for accurate numbers. + +--- ## What's already shipped -Every feature below is production-ready today: +Every feature below is **production-ready today**: -- ✅ Hybrid retrieval for `graph_query` — vector + BM25 + graph expansion fused with RRF -- ✅ AST-accurate parsers via tree-sitter for TypeScript, TSX, JS/MJS/CJS, JSX, Python, Go, Rust, Java (activate with `LXRAG_USE_TREE_SITTER=true`) -- ✅ Watcher-driven incremental rebuilds — your graph stays fresh without manual intervention -- ✅ Temporal query and diff support — query any past graph state with `asOf`, compare changes with `diff_since` -- ✅ Indexing-time symbol summarization — compact-profile answers stay useful even in tight token budgets -- ✅ MAGE-native Leiden community detection and PageRank PPR with JS fallbacks for non-MAGE environments -- ✅ SCIP IDs on all FILE, FUNCTION, and CLASS nodes for precise cross-tool symbol references -- ✅ Episode memory, agent coordination, context packs, and response budget shaping -- ✅ Docs & ADR indexing — `index_docs` parses all your markdown into graph nodes; `search_docs` queries them with BM25 or by symbol association +- ✅ **Hybrid retrieval** for `graph_query` — vector + BM25 + graph expansion fused with RRF +- ✅ **AST-accurate parsers** via tree-sitter for TypeScript, TSX, JS/MJS/CJS, JSX, Python, Go, Rust, Java +- ✅ **Watcher-driven incremental rebuilds** — graph stays fresh without manual intervention *(requires `LXDIG_ENABLE_WATCHER=true`)* +- ✅ **Temporal code model** — `asOf` queries any past graph state; `diff_since` shows what changed +- ✅ **Indexing-time symbol summaries** — compact-profile answers stay useful in tight token budgets +- ✅ **Leiden community detection + PageRank PPR** with JS fallbacks for non-MAGE environments +- ✅ **SCIP IDs** on all FILE, FUNCTION, and CLASS nodes for precise cross-tool symbol references +- ✅ **Episode memory, agent coordination, context packs, and response budget shaping** +- ✅ **Docs & ADR indexing** — markdown parsed into graph nodes; queried by text or symbol association +- ✅ **402 tests** across parsers, builders, engines, and tool handlers — all green -## Release highlights +--- -- **Hybrid natural retrieval** — your `graph_query` calls blend vector, BM25, and graph signals with RRF so you get the most relevant results across the whole codebase, not just the closest embedding match. -- **Multi-language AST parsers** — tree-sitter gives you accurate symbol extraction for TypeScript, TSX, JavaScript, JSX, Python, Go, Rust, and Java. Enable with `LXRAG_USE_TREE_SITTER=true`; each language falls back gracefully if the grammar isn't installed. -- **Impact-scoped test runs** — `impact_analyze` + `test_select` tell your agent exactly which tests to run after a change, cutting unnecessary CI time without sacrificing coverage confidence. -- **Docs & ADR indexing** — your documentation is now searchable the same way your code is. `index_docs` walks the workspace, parses every markdown file into `DOCUMENT` and `SECTION` nodes, and stores them in the graph. `search_docs` retrieves them by text query or by symbol association. -- **Persistent agent memory** — episodes, decisions, and claims survive across VS Code restarts so your agent can pick up exactly where it left off. -- **Temporal code model** — `asOf` and `diff_since` let you or your agent reason about the state of any file or symbol at any point in the past. -- **Always-current graph** — the file watcher triggers incremental rebuilds on save so your graph never goes stale. -- **Lower-token answers** — indexing-time symbol summaries keep `compact`-profile responses genuinely useful without growing the payload. -- **Safer BM25 fallback** — Memgraph `text_search` is used when available; the server falls back to a local lexical scorer automatically so retrieval never breaks. +## Runtime modes -## Tests and quality gates +| Mode | Best for | Command | +| ------------------------ | ---------------------------------------------------- | -------------------- | +| **stdio** ✅ recommended | VS Code Copilot, Claude Code, Claude Desktop, Cursor | `npm run start` | +| **HTTP** | Remote agents, multi-client fleets, CI pipelines | `npm run start:http` | -The test suite covers all parsers, builders, engines, and tool handlers — 109 tests across 5 files, all green. +### Useful scripts ```bash -npm test # run all 109 unit tests -npm run benchmark:check-regression # check latency / token-efficiency regressions +npm run start # stdio server (recommended) +npm run start:http # HTTP supervisor (multi-session) +npm run build # compile TypeScript +npm test # run all 402 tests +npm run benchmark:check-regression # check latency/token regressions ``` -Benchmark scripts under `scripts/` and `benchmarks/` track: +--- -- Query latency and token efficiency -- Retrieval accuracy trends -- Compact-profile response budget compliance -- Agent-mode synthetic task benchmarks +## Repository map -All new features ship with tests. The docs feature alone added 101 tests (50 parser + 23 builder + 17 engine + 11 tool-handler contract tests) before landing. +| Path | What's inside | +| ------------------------------------ | ------------------------------------------------------------------- | +| `src/server.ts`, `src/mcp-server.ts` | MCP + HTTP transport surfaces | +| `src/tools/` | Tool handlers, registry, all 39 tool implementations | +| `src/graph/` | Graph client, orchestrator, hybrid retriever, watcher, docs builder | +| `src/engines/` | Architecture, test, progress, coordination, episode, docs engines | +| `src/parsers/` | AST + markdown parsers (tree-sitter + regex fallback) | +| `src/response/` | Response shaping, profile budgets, summarization | +| `docs/GRAPH_EXPERT_AGENT.md` | Full agent runbook — tool priority, path rules, response shaping | +| `docs/MCP_INTEGRATION_GUIDE.md` | Deep-dive integration guide | +| `QUICK_START.md` | Step-by-step deployment + editor wiring (~5 min) | + +--- ## Integration tips -A few habits that make a big difference: +- **Start every session** with `graph_set_workspace` → `graph_rebuild` (or configure `init_project_setup` to run automatically) +- **Prefer `graph_query` over file reads** for discovery — far fewer tokens, cross-file context included +- **Use `profile: compact`** in autonomous loops; switch to `balanced` or `debug` when you need detail +- **Rebuild incrementally** after meaningful edits; the file watcher handles this automatically during active sessions +- **Run `impact_analyze` before tests** so your agent only executes what's actually affected + +--- + +## Roadmap -- **Start every session** with `graph_set_workspace` → `graph_rebuild` (or let your configured client do it automatically via `.github/copilot-instructions.md`) -- **Prefer `graph_query` over file reads** for discovery — you'll use far fewer tokens and get cross-file context for free -- **Use `profile: compact`** for autonomous loops where every token counts; switch to `balanced` or `debug` when you need more detail -- **Rebuild incrementally** after meaningful edits (`graph_rebuild` with `mode: incremental`); the file watcher handles this for you during active sessions -- **Run `impact_analyze` before tests** so your agent only executes what's actually affected by a change +lxDIG is open source and self-hosted today. Planned work ahead — see [ROADMAP.md](ROADMAP.md) for the full prioritized backlog with detail on each item. -See: +- [ ] Language server protocol (LSP) integration for deeper symbol resolution +- [ ] Go, Rust, Java parser improvements +- [ ] MCP `resources` surface (expose graph nodes as MCP resources) +- [ ] Webhook-triggered graph rebuilds for CI environments +- [ ] Plugin API for custom tool registration +- [ ] **Real-time transparent graph sync** — continuous file-watching with live graph and vector index updates surfaced as observable events, so agents and users always know when the graph is current without polling `graph_health` or triggering manual rebuilds +- [ ] **Domain knowledge layer** — attach external knowledge sources (documentation, standards, specs, research articles) directly to code symbols as graph nodes; a `calculateBMI` function links to CDC/WHO references, a payment function links to PCI-DSS rules, a GDPR-scoped model links to regulation articles — giving agents real-world context alongside structural context +- [ ] Multi-user coordination — shared agent memory, task ownership, and conflict detection across multiple developers on the same repository +- [ ] lxDIG Cloud — hosted, zero-infrastructure version for individuals and teams -- `.github/copilot-instructions.md` -- `docs/GRAPH_EXPERT_AGENT.md` -- [QUICK_START.md](QUICK_START.md): step-by-step deployment, VS Code project wiring, and Copilot / Claude extension configuration +--- ## Contributing -Pull requests are welcome! Whether it's a new parser, a tool improvement, a bug fix, or better docs — open an issue to discuss what you'd like to change, or just send a PR directly. +Pull requests are welcome. Whether it's a new parser, a tool improvement, a bug fix, or better docs — contributions of all sizes move this project forward. -- **Bugs / features** — open an issue first so we can align on scope -- **New tools** — follow the handler + registration pattern in `src/tools/tool-handlers.ts` and `src/server.ts`; include tests +- **Bugs / features** — open an issue first to align on scope +- **New tools** — follow the handler + registration pattern in `src/tools/`; include tests +- **New language parsers** — add tree-sitter grammar + tests in `src/parsers/` - **Docs** — typos, clarifications, and examples are always appreciated -[→ Open a pull request](https://github.com/lexCoder2/lxRAG-MCP/pulls) +[→ Open a pull request](https://github.com/lexCoder2/lxDIG-MCP/pulls) · [→ Browse open issues](https://github.com/lexCoder2/lxDIG-MCP/issues) -## Support this project +--- + +## Support the project -LxRAG MCP is built and maintained in my personal time — researching graph retrieval techniques, designing the tool surface, writing tests, and keeping everything working across MCP protocol updates. a cup of coffe or any help you can provide will make a difference, If it saves you time or makes your AI-assisted workflows meaningfully better, consider supporting the work: +lxDIG MCP is built and maintained in personal time — researching graph retrieval techniques, designing the tool surface, writing tests, and keeping everything working across MCP protocol updates. If it saves you time or makes your AI-assisted workflows meaningfully better, consider supporting the work: - **GitHub Sponsors** → [github.com/sponsors/lexCoder2](https://github.com/sponsors/lexCoder2) - **Buy Me a Coffee** → [buymeacoffee.com/hi8g](https://buymeacoffee.com/hi8g) -Every contribution — no matter the size — helps keep the project active and lets me prioritize new features and support over other obligations. Thank you. 🙏 +--- + +## FAQ + +**Q: Does lxDIG require a cloud service or API key?** +No. lxDIG runs entirely on your machine. Memgraph and Qdrant run in Docker containers you control. No data leaves your environment. + +**Q: Does it work with Cursor?** +Yes. Any MCP-compatible client works. Add the stdio config to Cursor's MCP settings the same way as VS Code. + +**Q: How large a codebase can it handle?** +The graph plane (Memgraph) scales to millions of nodes. For very large monorepos, use `sourceDir` to scope indexing to the relevant subdirectory. Incremental rebuilds keep the graph fresh without re-indexing everything. + +**Q: Do I need to run Qdrant?** +Qdrant is optional but recommended for large codebases. Without it, `semantic_search` and `find_similar_code` are unavailable; all other tools continue to work via graph-only or BM25 retrieval. + +**Q: Can multiple developers on a team share one lxDIG instance?** +Yes, via HTTP transport. One running instance handles multiple independent sessions. Team-level shared memory is on the lxDIG Cloud roadmap. + +**Q: Is this production-ready?** +The core tools are stable and tested (402 tests, all green). Treat it as beta — APIs may change before a 1.0 release. Pin your version and watch the changelog. + +--- ## License -MIT +[MIT](LICENSE) — free to use, modify, and distribute. + +--- + +
+ Built with care for the agentic coding era · github.com/lexCoder2/lxDIG-MCP +
diff --git a/RESOLUTION_PLAN.md b/RESOLUTION_PLAN.md index 5b156d2..a511c7d 100644 --- a/RESOLUTION_PLAN.md +++ b/RESOLUTION_PLAN.md @@ -1,14 +1,14 @@ -# LexRAG-MCP Resolution Plan +# LexDIG-MCP Resolution Plan **Status**: Ready for Implementation **Last Updated**: 2026-02-22 -**Analysis Method**: lxRAG Tools Only +**Analysis Method**: lxDIG Tools Only --- ## Executive Summary -Analysis using only lxRAG tools has identified **3 critical blockers** preventing full code intelligence: +Analysis using only lxDIG tools has identified **3 critical blockers** preventing full code intelligence: 1. **Backend BigInt Error** - Prevents graph health verification 2. **Missing Architecture Configuration** - Files unassigned to layers @@ -26,12 +26,12 @@ Analysis using only lxRAG tools has identified **3 critical blockers** preventin **Problem**: `TypeError: Cannot mix BigInt and other types, use explicit conversions` -**Location**: lxRAG backend graph_health check +**Location**: lxDIG backend graph_health check **Resolution Steps**: ```bash -# 1. Check lxRAG setup +# 1. Check lxDIG setup docker ps | grep -E "memgraph|qdrant" # 2. Verify MCP server status @@ -55,15 +55,15 @@ npm run test:mcp-integration ### 1.2 Create Architecture Configuration -**Problem**: `.lxrag/config.json` missing or incomplete +**Problem**: `.lxdig/config.json` missing or incomplete -**File**: `.lxrag/config.json` (create if missing) +**File**: `.lxdig/config.json` (create if missing) **Required Content**: ```json { - "projectId": "lexrag-mcp", + "projectId": "lexdig-mcp", "sourceDir": "src", "layers": [ { @@ -335,25 +335,25 @@ npm run test:episodes -- --scenario "memory-recall" **Build Command**: ```bash -lxrag build [--project projectId] [--full|--incremental] +lxdig build [--project projectId] [--full|--incremental] ``` **Query Command**: ```bash -lxrag query "find all HTTP handlers" [--project projectId] +lxdig query "find all HTTP handlers" [--project projectId] ``` **Test Affected**: ```bash -lxrag test-affected [files...] [--report json] +lxdig test-affected [files...] [--report json] ``` **Validate**: ```bash -lxrag validate [--strict] [--fix] +lxdig validate [--strict] [--fix] ``` ### 4.2 Testing Infrastructure @@ -396,12 +396,12 @@ From `benchmarks/` directory: ### Phase 1: Backend (1 day) -- [x] Create `.lxrag/config.json` +- [x] Create `.lxdig/config.json` - [x] Fix BigInt error in local source (`src/tools/tool-handlers.ts`) - [x] Add regression test coverage for BigInt health metrics - [x] Force graph rebuild - [x] Validate all systems locally (`npm run build`, `npm test`) -- [ ] Validate hosted/runtime `mcp_lxrag_graph_health` after service restart +- [ ] Validate hosted/runtime `mcp_lxdig_graph_health` after service restart **Completion Criteria**: @@ -514,7 +514,7 @@ From `benchmarks/` directory: ### Overall Success: -**Full lxRAG suite operational with agent memory integration** +**Full lxDIG suite operational with agent memory integration** --- @@ -566,7 +566,7 @@ Phase 5: 1. **Right Now**: - Review this plan - - Create `.lxrag/config.json` (provided above) + - Create `.lxdig/config.json` (provided above) 2. **Within 1 hour**: - Run Phase 1 validation checklist @@ -582,6 +582,6 @@ Phase 5: --- -**Plan created by**: lxRAG Analysis Tools +**Plan created by**: lxDIG Analysis Tools **Confidence**: High (based on actual project analysis) **Ready for**: Immediate implementation diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..5683f8f --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,360 @@ +# lxDIG MCP — Roadmap + +This document is the single source of truth for planned and pending work. It consolidates findings from audit reports, internal action plans, the alternatives research, and feature requests into one prioritized backlog. + +Items are organized by tier — near-term reliability work first, then capability expansion, then platform and scale. Within each tier, items are ordered by impact. + +--- + +## How to read this file + +| Symbol | Meaning | +|---|---| +| 🔴 | Known bug or active degradation — affects users today | +| 🟡 | Gap or limitation — degrades quality but does not break | +| 🟢 | Planned improvement — not a bug, adds new value | +| 🔵 | Long-term / strategic — significant scope or dependency | + +--- + +## Tier 1 — Stability and reliability + +These are bugs, active degradations, and hardening gaps identified across audit cycles. They should be resolved before the feature backlog is expanded. + +### 1.1 🔴 `test_run` inherits wrong Node.js from server PATH + +**Source:** Self-audit SX4 (2026-02-24) + +`test_run` calls `child_process.exec("npx vitest run ...")` and inherits the server process's `PATH`, which may resolve to the system Node (e.g. v10.19.0) instead of the project's managed Node (nvm/volta/pkgx). + +**Fix:** In `test_run`, resolve the `node` binary to `process.execPath` and derive `npx` from the same directory, instead of relying on inherited `PATH`. + +--- + +### 1.2 🔴 Graph/index readiness gates not enforced + +**Source:** PLANS_PENDING_ACTIONS_SUMMARY P0.1, AUDITS_EVALUATIONS_SUMMARY + +Analysis tools (`impact_analyze`, `test_select`, `semantic_search`, etc.) can be called before `graph_rebuild` completes and return empty or misleading results with no clear error. + +**Fix:** Add a readiness gate check at the start of all analysis tools. If graph state is stale or rebuild is in progress, return a structured error with a direct remediation hint (`graph_health` → `graph_rebuild`). + +--- + +### 1.3 🔴 REFERENCES edges not created for TypeScript `.js` imports + +**Source:** Self-audit SX3 (2026-02-24) — fix applied, requires restart + full rebuild + +`resolveImportPath()` in `builder.ts` did not strip `.js`/`.jsx` before probing disk candidates, producing 0 REFERENCES edges for TypeScript projects using `moduleResolution: node16/bundler`. Without REFERENCES edges, `impact_analyze` and `test_select` return 0 results. + +**Status:** Fix applied in source. Requires server restart + `graph_rebuild(mode: full)` to activate. + +--- + +### 1.4 🟡 CLASS and FUNCTION nodes missing `path` property + +**Source:** Self-audit SX2 + +All CLASS and FUNCTION nodes have `path: null`. Path is only accessible by traversing the `CONTAINS` edge to the parent FILE node. This forces an extra JOIN in any tool that resolves a symbol to a file path, and breaks community detection (see SX5). + +**Fix:** Add `filePath` property (= parent FILE's absolute path) to CLASS and FUNCTION nodes in `builder.ts` at index time. + +--- + +### 1.5 🟡 SECTION.title not populated without summarizer + +**Source:** Self-audit SX1 + +All 943 SECTION nodes have `title: null` when `LXDIG_SUMMARIZER_URL` is not configured. Search results and doc lookups surface no human-readable title. + +**Fix:** Add heuristic H1/H2 heading extraction to the markdown parser as a fallback, so SECTION nodes always have a title regardless of summarizer availability. + +--- + +### 1.6 🟡 Embedding coverage is zero when summarizer is unconfigured + +**Source:** Self-audit F5 (related to F8) + +When `LXDIG_SUMMARIZER_URL` is not set, 0 embeddings are generated across all FUNCTION and CLASS nodes. All semantic tools (`semantic_search`, `find_similar_code`, `code_clusters`) fall back to lexical-only results with no warning to the user. + +**Fix:** Surface a clear warning in `graph_health` output when embedding coverage is 0% — distinct from the normal "Qdrant not connected" case. Document the `LXDIG_SUMMARIZER_URL` requirement more prominently in setup. + +--- + +### 1.7 🟡 Contract strictness and argument normalization gaps + +**Source:** PLANS_PENDING_ACTIONS_SUMMARY P1.3, AUDITS_EVALUATIONS_SUMMARY + +Edge-case argument handling and input normalization is inconsistent across tools. Clients that pass slightly malformed arguments get varying error shapes. + +**Fix:** Sweep all tool contracts in `src/tools/registry.ts` and handler modules. Normalize edge cases. Align error envelopes to a single shape across all profile levels. + +--- + +### 1.8 🟡 Missing lifecycle failure-mode tests + +**Source:** PLANS_PENDING_ACTIONS_SUMMARY P1.4 + +No test coverage exists for: graph rebuild in-progress state, session reconnect after drop, stale index queries, or the stdio vs HTTP mode boundary conditions. + +**Fix:** Add integration tests covering these scenarios to prevent regressions in known failure families. + +--- + +### 1.9 🟡 Workspace/session path ambiguity at onboarding + +**Source:** PLANS_PENDING_ACTIONS_SUMMARY P0.2, AUDITS_EVALUATIONS_SUMMARY + +Host path vs `/workspace` container path confusion is the most common first-run failure. Documentation gives different examples in different places. + +**Fix:** Normalize all path examples in `README.md`, `QUICK_START.md`, and `docs/MCP_INTEGRATION_GUIDE.md` to one canonical section per transport mode. Add a runtime guard that detects Docker context and emits a path-format hint. + +--- + +## Tier 2 — Core capability improvements + +These are well-scoped improvements to existing tools and subsystems. They increase the quality and reliability of what lxDIG already does. + +### 2.1 🟢 Risk-aware metadata on `impact_analyze` and `code_explain` + +**Source:** Alternatives research (CodeMCP pattern) + +`impact_analyze` returns blast radius but does not attach ownership (who wrote the code being changed) or hotspot scoring (is this a frequently modified volatile file?). Agents making change decisions have to infer risk from the raw data. + +**Improvement:** Add `gitBlameOwner` (time-weighted last author) and `changeFrequency` (commits in last 90 days) fields to `impact_analyze` and `code_explain` responses. Return a pre-computed `riskScore` so agents do not need to infer it. + +--- + +### 2.2 🟢 Compound tool: `change_risk_pack` + +**Source:** Alternatives research (CodeMCP compound operations — up to 70% fewer tool calls) + +A common agent workflow requires 4 sequential calls to answer "is it safe to change this?": `graph_query` → `code_explain` → `impact_analyze` → `test_select`. Each round trip costs tokens and latency. + +**Improvement:** Add a compound tool `change_risk_pack` (or extend `context_pack`) that executes all four internally and returns a single structured answer: blast radius + owners + affected tests + architectural violations + risk score. + +--- + +### 2.3 🟢 Heuristic section title extraction (no summarizer required) + +**Source:** Self-audit SX1 + +Partial overlap with 1.5 — the broader improvement is making section/doc indexing genuinely useful at zero configuration, without requiring an external LLM summarizer endpoint. + +**Improvement:** Parse H1–H3 headings from markdown as section titles. Optionally use first non-empty paragraph as description. The summarizer, if configured, upgrades these with semantic titles. + +--- + +### 2.4 🟢 Observability and KPI cadence + +**Source:** PLANS_PENDING_ACTIONS_SUMMARY P2.6 + +No structured baseline exists for rebuild latency, health failures, contract failures, or benchmark drift. Regression detection is manual. + +**Improvement:** Define a recurring KPI set. Publish snapshot summaries per release. Wire `benchmark:check-regression` into CI as a non-blocking advisory check with drift thresholds. + +--- + +### 2.5 🟢 `test_run` resolves `vitest` from project's local `node_modules` + +**Source:** Self-audit SX4 (broader fix than the PATH workaround) + +Even after fixing the Node PATH issue, `test_run` needs to resolve `vitest` from the indexed project's own `node_modules/.bin`, not from the server's context. Projects may use different test runners or versions. + +**Improvement:** Make `test_run` resolve the test runner binary from `{workspaceRoot}/node_modules/.bin/` with a fallback to `npx`. Support configurable runner (`vitest`, `jest`, `mocha`) per project. + +--- + +## Tier 3 — New capabilities + +These are features that do not exist yet and expand what lxDIG can do. + +### 3.1 🟢 Real-time transparent graph sync + +Continuous file-watching already exists, but graph and vector index updates are not surfaced as observable events. Agents poll `graph_health` to know when the graph is current, and users have no passive signal. + +**Target:** Surface graph sync state as a live observable — emit events when files change, when a rebuild starts, and when the graph becomes consistent. Agents and IDE extensions can subscribe without polling. + +--- + +### 3.2 🟢 Automatic API surface mapping + +**Source:** Alternatives research (CIE kraklabs pattern) + +No framework-aware parsing exists. Express routes, Fastify plugins, FastAPI paths, and Spring endpoints are stored as generic function nodes — an agent must infer that a function is an HTTP endpoint. + +**Target:** Framework-aware parsers that tag `ENDPOINT` nodes with HTTP method + path on the graph. Support Express, Fastify (TypeScript/JS), FastAPI (Python), Spring (Java). An agent can ask "what routes does this service expose?" and get a structured list. + +--- + +### 3.3 🟢 Domain knowledge layer + +Link external knowledge sources — documentation, standards, specifications, research articles — directly to code symbols as graph nodes, connected via typed edges. + +**Examples:** +- `calculateBMI` function → linked to CDC/WHO clinical reference +- `processPayment` function → linked to PCI-DSS requirements +- `UserProfile` model with GDPR-scoped fields → linked to GDPR article nodes +- `encryptData` function → linked to NIST cryptographic standards + +**Target:** A `domain_link` tool to attach external sources to symbols. A `domain_search` tool to query what real-world context is attached to a symbol or file. Domain nodes are first-class graph citizens, searchable via BM25 and vector queries alongside code nodes. + +--- + +### 3.4 🟢 Language Server Protocol (LSP) integration + +**Source:** README roadmap + +Tree-sitter provides syntactic structure. LSP provides semantic structure: hover types, go-to-definition, find-all-references, rename symbols — compiler-accurate for any language with an LSP server. + +**Target:** Optional LSP backend (`LXDIG_LSP=true`) that enriches graph nodes with LSP-derived type information and cross-file reference resolution. Complements tree-sitter (which handles speed and zero-config) with semantic depth for projects that have a working language server. + +--- + +### 3.5 🟢 SCIP precision tier (opt-in) + +**Source:** Alternatives research (CodeMCP, CIE patterns) + +Tree-sitter is syntactic and struggles with polymorphic calls and implicit types. SCIP (Semantic Code Intelligence Protocol) is compiler-accurate: it resolves which concrete implementation is called, tracks interface dispatch, and produces stable cross-repository symbol IDs. + +**Target:** SCIP as an opt-in precision tier (`LXDIG_PARSER=scip`). Language support: TypeScript (via `scip-typescript`), Go (`scip-go`), Java (`scip-java`). SCIP symbol IDs are stored on graph nodes alongside SCIP IDs, enabling cross-repo graph linking. + +--- + +### 3.6 🟢 Interface dispatch resolution + +**Source:** Alternatives research (CIE pattern) + +`code_explain` on an interface or abstract class shows callers of the interface, but not which concrete implementation executes at runtime. Agents must guess. + +**Target:** Add `resolvedImplementations` to `code_explain` for interface/abstract symbols — "this `UserRepository` call resolves to `PostgresUserRepository` in the production config." Requires either LSP (3.4) or SCIP (3.5) as a backing parser. + +--- + +### 3.7 🟢 MCP `resources` surface + +**Source:** README roadmap, MCP specification 2025-06-18 + +The MCP protocol supports `resources` as a first-class concept (alongside `tools` and `prompts`). Graph nodes — files, functions, classes, documents — are natural resources. + +**Target:** Expose graph nodes as MCP resources so clients that support resource browsing (file trees, symbol lists) can navigate the graph without making tool calls. Resources stay in sync with the live graph. + +--- + +### 3.8 🟢 Webhook-triggered graph rebuilds + +**Source:** README roadmap + +Today, rebuilds are triggered manually or by the file watcher during active sessions. In CI environments, the server may be remote and the file watcher is not active. + +**Target:** HTTP endpoint (`POST /webhook/push`) that accepts a GitHub/GitLab/Gitea push event payload and triggers an incremental graph rebuild for the affected files. Enables CI-integrated graph freshness without a persistent watcher. + +--- + +### 3.9 🟢 Plugin API for custom tool registration + +**Source:** README roadmap + +All 39 tools are compiled into the server. There is no way to add domain-specific tools without modifying the source. + +**Target:** A plugin API that allows registering additional MCP tools from external modules. Plugins are loaded at startup from a configured directory or `package.json` `lxdig.plugins` field. Each plugin exports a tool definition and handler following the existing registry contract. + +--- + +### 3.10 🟢 Improved Go, Rust, and Java parser coverage + +**Source:** README roadmap + +Tree-sitter grammars for Go, Rust, and Java are listed as optional dependencies, but symbol extraction quality (especially for generics, traits, and annotations) lags behind TypeScript/Python. + +**Target:** Improve extractor coverage for: +- Go: interfaces, embedded structs, method sets +- Rust: traits, impl blocks, lifetimes (as metadata) +- Java: annotations, generics, Spring component scanning + +--- + +## Tier 4 — Platform and scale + +These are features that require significant architectural work or external dependencies. They are the longer-term direction. + +### 4.1 🔵 Multi-user coordination + +The current coordination model (claims, releases, agent_status) is designed for multiple AI agents. Human developers working on the same repository from different machines or sessions have no shared view. + +**Target:** Shared coordination state across multiple human developer sessions — shared agent memory, task ownership visible to the whole team, conflict detection when two developers (or their agents) claim the same file or task. Requires a shared Memgraph instance (already possible with HTTP transport) and an identity/session model. + +--- + +### 4.2 🔵 Pre-indexed bundle registry + +**Source:** Alternatives research (CodeGraphContext pattern) + +Every repository must be indexed from scratch. For popular open-source libraries (React, Express, Django, FastAPI, Spring Boot), this is redundant work that every user repeats. + +**Target:** A community-maintained registry of pre-built graph bundles for popular open-source libraries. Bundles are loaded alongside the project graph and enable agents to traverse into dependency internals. Natural seed for lxDIG Cloud's managed graph service. + +--- + +### 4.3 🔵 lxDIG Cloud + +A hosted, zero-infrastructure version of lxDIG for individuals and teams who want the full capability without running Memgraph and Qdrant themselves. + +**Scope:** +- Managed Memgraph + Qdrant, provisioned per workspace +- One-click GitHub/GitLab repository connect with webhook-driven graph sync +- Team workspaces with shared agent memory and multi-user coordination (4.1) +- Usage analytics: query patterns, agent activity, impact trends +- Subscription plans for individuals, teams, and organizations + +--- + +## Tracking template + +Use this in issues and PRs to link work back to this roadmap: + +| Item | Tier | Status | PR / Issue | +|---|---|---|---| +| 1.1 test_run Node PATH | T1 | Not started | — | +| 1.2 readiness gates | T1 | Not started | — | +| 1.3 REFERENCES edges | T1 | Fix applied, pending restart | — | +| 1.4 CLASS/FN path prop | T1 | Not started | — | +| 1.5 SECTION.title fallback | T1 | Not started | — | +| 1.6 embedding coverage warning | T1 | Not started | — | +| 1.7 contract normalization | T1 | Not started | — | +| 1.8 lifecycle tests | T1 | Not started | — | +| 1.9 path ambiguity docs | T1 | Not started | — | +| 2.1 risk-aware metadata | T2 | Not started | — | +| 2.2 change_risk_pack | T2 | Not started | — | +| 2.3 section title heuristics | T2 | Not started | — | +| 2.4 KPI cadence | T2 | Not started | — | +| 2.5 test runner resolution | T2 | Not started | — | +| 3.1 real-time graph sync | T3 | Not started | — | +| 3.2 API surface mapping | T3 | Not started | — | +| 3.3 domain knowledge layer | T3 | Not started | — | +| 3.4 LSP integration | T3 | Not started | — | +| 3.5 SCIP precision tier | T3 | Not started | — | +| 3.6 interface dispatch | T3 | Not started | — | +| 3.7 MCP resources surface | T3 | Not started | — | +| 3.8 webhook rebuilds | T3 | Not started | — | +| 3.9 plugin API | T3 | Not started | — | +| 3.10 Go/Rust/Java parsers | T3 | Not started | — | +| 4.1 multi-user coordination | T4 | Planning | — | +| 4.2 bundle registry | T4 | Planning | — | +| 4.3 lxDIG Cloud | T4 | Planning | — | + +--- + +## Sources + +Internal: +- `docs/PLANS_PENDING_ACTIONS_SUMMARY.md` +- `docs/AUDITS_EVALUATIONS_SUMMARY.md` +- `docs/lxdig-self-audit-2026-02-24.md` +- `docs/TOOLS_INFORMATION_GUIDE.md` +- `plan/Researching Alternative Solutions.md` +- `README.md` roadmap section + +External: +- MCP specification 2025-06-18 (modelcontextprotocol.io) +- Alternatives analysis: CodeGraphContext, CodeMCP (SimplyLiz), CIE (kraklabs), Scaffold diff --git a/benchmarks/GRAPH_TOOLS_BENCHMARK_MATRIX.md b/benchmarks/GRAPH_TOOLS_BENCHMARK_MATRIX.md index 1ccaabe..b834412 100644 --- a/benchmarks/GRAPH_TOOLS_BENCHMARK_MATRIX.md +++ b/benchmarks/GRAPH_TOOLS_BENCHMARK_MATRIX.md @@ -35,7 +35,7 @@ Generated: 2026-02-21T23:42:24.987677+00:00 | T014 | test_select | Test select for progress-engine change | 15.14 | 224.28 | 0.000 | 1.000 | 66 | 31 | baseline | Low MCP accuracy on this scenario | | T015 | test_select | Test select for orchestrator change | 14.56 | 206.63 | 0.000 | 0.000 | 65 | 22 | tie | Low MCP accuracy on this scenario | | T016 | test_select | Test select for contract test file | 14.79 | 226.22 | 0.000 | 1.000 | 68 | 22 | baseline | Low MCP accuracy on this scenario | -| T017 | graph_rebuild | Rebuild incremental (lxRAG-MCP src) | 15.84 | 205.97 | 0.000 | 1.000 | 64 | 11 | baseline | Low MCP accuracy on this scenario | +| T017 | graph_rebuild | Rebuild incremental (lxDIG MCP src) | 15.84 | 205.97 | 0.000 | 1.000 | 64 | 11 | baseline | Low MCP accuracy on this scenario | | T018 | graph_rebuild | Rebuild incremental verbose | 14.31 | 203.85 | 0.000 | 1.000 | 63 | 13 | baseline | Low MCP accuracy on this scenario | | T019 | graph_rebuild | Rebuild full mode | 15.11 | 218.72 | 0.000 | 1.000 | 62 | 12 | baseline | Low MCP accuracy on this scenario | | T020 | graph_rebuild | Rebuild full verbose | 14.50 | 204.09 | 0.000 | 1.000 | 62 | 7 | baseline | Low MCP accuracy on this scenario | diff --git a/coverage/clover.xml b/coverage/clover.xml deleted file mode 100644 index d56ec2b..0000000 --- a/coverage/clover.xml +++ /dev/null @@ -1,4223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/coverage/coverage-final.json b/coverage/coverage-final.json deleted file mode 100644 index ffaf471..0000000 --- a/coverage/coverage-final.json +++ /dev/null @@ -1,39 +0,0 @@ -{"/home/alex_rod/projects/lexRAG-MCP/src/env.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/env.ts","statementMap":{"0":{"start":{"line":14,"column":0},"end":{"line":14,"column":null}},"1":{"start":{"line":23,"column":44},"end":{"line":25,"column":null}},"2":{"start":{"line":28,"column":41},"end":{"line":28,"column":null}},"3":{"start":{"line":35,"column":13},"end":{"line":39,"column":null}},"4":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"5":{"start":{"line":38,"column":2},"end":{"line":38,"column":null}},"6":{"start":{"line":47,"column":2},"end":{"line":47,"column":null}},"7":{"start":{"line":50,"column":37},"end":{"line":50,"column":null}},"8":{"start":{"line":58,"column":2},"end":{"line":58,"column":null}},"9":{"start":{"line":68,"column":3},"end":{"line":68,"column":null}},"10":{"start":{"line":75,"column":32},"end":{"line":75,"column":null}},"11":{"start":{"line":83,"column":2},"end":{"line":83,"column":null}},"12":{"start":{"line":86,"column":38},"end":{"line":86,"column":null}},"13":{"start":{"line":95,"column":37},"end":{"line":95,"column":null}},"14":{"start":{"line":102,"column":37},"end":{"line":105,"column":null}},"15":{"start":{"line":114,"column":35},"end":{"line":114,"column":null}},"16":{"start":{"line":121,"column":35},"end":{"line":124,"column":null}},"17":{"start":{"line":134,"column":2},"end":{"line":134,"column":null}},"18":{"start":{"line":137,"column":41},"end":{"line":137,"column":null}},"19":{"start":{"line":147,"column":2},"end":{"line":147,"column":null}},"20":{"start":{"line":150,"column":35},"end":{"line":150,"column":null}},"21":{"start":{"line":160,"column":2},"end":{"line":160,"column":null}},"22":{"start":{"line":163,"column":42},"end":{"line":163,"column":null}},"23":{"start":{"line":174,"column":2},"end":{"line":174,"column":null}},"24":{"start":{"line":177,"column":41},"end":{"line":177,"column":null}},"25":{"start":{"line":184,"column":13},"end":{"line":189,"column":null}},"26":{"start":{"line":188,"column":14},"end":{"line":188,"column":22}},"27":{"start":{"line":192,"column":42},"end":{"line":192,"column":null}},"28":{"start":{"line":203,"column":2},"end":{"line":203,"column":null}},"29":{"start":{"line":207,"column":2},"end":{"line":207,"column":null}},"30":{"start":{"line":216,"column":58},"end":{"line":219,"column":null}},"31":{"start":{"line":227,"column":61},"end":{"line":230,"column":null}},"32":{"start":{"line":239,"column":49},"end":{"line":242,"column":null}},"33":{"start":{"line":251,"column":52},"end":{"line":254,"column":null}},"34":{"start":{"line":261,"column":60},"end":{"line":264,"column":null}},"35":{"start":{"line":271,"column":58},"end":{"line":274,"column":null}},"36":{"start":{"line":283,"column":52},"end":{"line":286,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":35,"column":41},"end":{"line":35,"column":47}},"loc":{"start":{"line":35,"column":47},"end":{"line":39,"column":3}},"line":35},"1":{"name":"(anonymous_1)","decl":{"start":{"line":188,"column":7},"end":{"line":188,"column":8}},"loc":{"start":{"line":188,"column":14},"end":{"line":188,"column":22}},"line":188}},"branchMap":{"0":{"loc":{"start":{"line":24,"column":2},"end":{"line":24,"column":null}},"type":"binary-expr","locations":[{"start":{"line":24,"column":2},"end":{"line":24,"column":38}},{"start":{"line":24,"column":38},"end":{"line":24,"column":null}}],"line":24},"1":{"loc":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"type":"binary-expr","locations":[{"start":{"line":37,"column":4},"end":{"line":37,"column":36}},{"start":{"line":37,"column":36},"end":{"line":37,"column":null}}],"line":37},"2":{"loc":{"start":{"line":38,"column":9},"end":{"line":38,"column":null}},"type":"cond-expr","locations":[{"start":{"line":38,"column":32},"end":{"line":38,"column":38}},{"start":{"line":38,"column":38},"end":{"line":38,"column":null}}],"line":38},"3":{"loc":{"start":{"line":47,"column":2},"end":{"line":47,"column":null}},"type":"binary-expr","locations":[{"start":{"line":47,"column":2},"end":{"line":47,"column":34}},{"start":{"line":47,"column":34},"end":{"line":47,"column":null}}],"line":47},"4":{"loc":{"start":{"line":58,"column":2},"end":{"line":58,"column":null}},"type":"binary-expr","locations":[{"start":{"line":58,"column":2},"end":{"line":58,"column":29}},{"start":{"line":58,"column":29},"end":{"line":58,"column":null}}],"line":58},"5":{"loc":{"start":{"line":68,"column":3},"end":{"line":68,"column":null}},"type":"binary-expr","locations":[{"start":{"line":68,"column":3},"end":{"line":68,"column":53}},{"start":{"line":68,"column":53},"end":{"line":68,"column":null}}],"line":68},"6":{"loc":{"start":{"line":75,"column":41},"end":{"line":75,"column":73}},"type":"binary-expr","locations":[{"start":{"line":75,"column":41},"end":{"line":75,"column":65}},{"start":{"line":75,"column":65},"end":{"line":75,"column":73}}],"line":75},"7":{"loc":{"start":{"line":83,"column":2},"end":{"line":83,"column":null}},"type":"binary-expr","locations":[{"start":{"line":83,"column":2},"end":{"line":83,"column":35}},{"start":{"line":83,"column":35},"end":{"line":83,"column":null}}],"line":83},"8":{"loc":{"start":{"line":95,"column":37},"end":{"line":95,"column":null}},"type":"binary-expr","locations":[{"start":{"line":95,"column":37},"end":{"line":95,"column":66}},{"start":{"line":95,"column":66},"end":{"line":95,"column":null}}],"line":95},"9":{"loc":{"start":{"line":103,"column":2},"end":{"line":103,"column":null}},"type":"binary-expr","locations":[{"start":{"line":103,"column":2},"end":{"line":103,"column":31}},{"start":{"line":103,"column":31},"end":{"line":103,"column":null}}],"line":103},"10":{"loc":{"start":{"line":114,"column":35},"end":{"line":114,"column":null}},"type":"binary-expr","locations":[{"start":{"line":114,"column":35},"end":{"line":114,"column":62}},{"start":{"line":114,"column":62},"end":{"line":114,"column":null}}],"line":114},"11":{"loc":{"start":{"line":122,"column":2},"end":{"line":122,"column":null}},"type":"binary-expr","locations":[{"start":{"line":122,"column":2},"end":{"line":122,"column":29}},{"start":{"line":122,"column":29},"end":{"line":122,"column":null}}],"line":122},"12":{"loc":{"start":{"line":134,"column":2},"end":{"line":134,"column":null}},"type":"binary-expr","locations":[{"start":{"line":134,"column":2},"end":{"line":134,"column":38}},{"start":{"line":134,"column":38},"end":{"line":134,"column":null}}],"line":134},"13":{"loc":{"start":{"line":147,"column":2},"end":{"line":147,"column":null}},"type":"binary-expr","locations":[{"start":{"line":147,"column":2},"end":{"line":147,"column":32}},{"start":{"line":147,"column":32},"end":{"line":147,"column":null}}],"line":147},"14":{"loc":{"start":{"line":185,"column":2},"end":{"line":185,"column":null}},"type":"binary-expr","locations":[{"start":{"line":185,"column":2},"end":{"line":185,"column":39}},{"start":{"line":185,"column":39},"end":{"line":185,"column":null}}],"line":185},"15":{"loc":{"start":{"line":217,"column":2},"end":{"line":217,"column":null}},"type":"binary-expr","locations":[{"start":{"line":217,"column":2},"end":{"line":217,"column":52}},{"start":{"line":217,"column":52},"end":{"line":217,"column":null}}],"line":217},"16":{"loc":{"start":{"line":228,"column":2},"end":{"line":228,"column":null}},"type":"binary-expr","locations":[{"start":{"line":228,"column":2},"end":{"line":228,"column":55}},{"start":{"line":228,"column":55},"end":{"line":228,"column":null}}],"line":228},"17":{"loc":{"start":{"line":240,"column":2},"end":{"line":240,"column":null}},"type":"binary-expr","locations":[{"start":{"line":240,"column":2},"end":{"line":240,"column":43}},{"start":{"line":240,"column":43},"end":{"line":240,"column":null}}],"line":240},"18":{"loc":{"start":{"line":252,"column":2},"end":{"line":252,"column":null}},"type":"binary-expr","locations":[{"start":{"line":252,"column":2},"end":{"line":252,"column":46}},{"start":{"line":252,"column":46},"end":{"line":252,"column":null}}],"line":252},"19":{"loc":{"start":{"line":262,"column":2},"end":{"line":262,"column":null}},"type":"binary-expr","locations":[{"start":{"line":262,"column":2},"end":{"line":262,"column":54}},{"start":{"line":262,"column":54},"end":{"line":262,"column":null}}],"line":262},"20":{"loc":{"start":{"line":272,"column":2},"end":{"line":272,"column":null}},"type":"binary-expr","locations":[{"start":{"line":272,"column":2},"end":{"line":272,"column":52}},{"start":{"line":272,"column":52},"end":{"line":272,"column":null}}],"line":272},"21":{"loc":{"start":{"line":284,"column":2},"end":{"line":284,"column":null}},"type":"binary-expr","locations":[{"start":{"line":284,"column":2},"end":{"line":284,"column":46}},{"start":{"line":284,"column":46},"end":{"line":284,"column":null}}],"line":284}},"s":{"0":7,"1":7,"2":7,"3":7,"4":7,"5":7,"6":7,"7":7,"8":7,"9":7,"10":7,"11":7,"12":7,"13":7,"14":7,"15":7,"16":7,"17":7,"18":7,"19":7,"20":7,"21":7,"22":7,"23":7,"24":7,"25":7,"26":7,"27":7,"28":7,"29":7,"30":7,"31":7,"32":7,"33":7,"34":7,"35":7,"36":7},"f":{"0":7,"1":7},"b":{"0":[7,7],"1":[7,7],"2":[7,0],"3":[7,7],"4":[7,7],"5":[7,0],"6":[7,0],"7":[7,7],"8":[7,0],"9":[7,0],"10":[7,0],"11":[7,0],"12":[7,7],"13":[7,7],"14":[7,7],"15":[7,7],"16":[7,7],"17":[7,7],"18":[7,7],"19":[7,7],"20":[7,7],"21":[7,7]},"meta":{"lastBranch":22,"lastFunction":2,"lastStatement":37,"seen":{"s:14:0:14:Infinity":0,"s:23:44:25:Infinity":1,"b:24:2:24:38:24:38:24:Infinity":0,"s:28:41:28:Infinity":2,"s:35:13:39:Infinity":3,"f:35:41:35:47":0,"s:37:4:37:Infinity":4,"b:37:4:37:36:37:36:37:Infinity":1,"s:38:2:38:Infinity":5,"b:38:32:38:38:38:38:38:Infinity":2,"s:47:2:47:Infinity":6,"b:47:2:47:34:47:34:47:Infinity":3,"s:50:37:50:Infinity":7,"s:58:2:58:Infinity":8,"b:58:2:58:29:58:29:58:Infinity":4,"s:68:3:68:Infinity":9,"b:68:3:68:53:68:53:68:Infinity":5,"s:75:32:75:Infinity":10,"b:75:41:75:65:75:65:75:73":6,"s:83:2:83:Infinity":11,"b:83:2:83:35:83:35:83:Infinity":7,"s:86:38:86:Infinity":12,"s:95:37:95:Infinity":13,"b:95:37:95:66:95:66:95:Infinity":8,"s:102:37:105:Infinity":14,"b:103:2:103:31:103:31:103:Infinity":9,"s:114:35:114:Infinity":15,"b:114:35:114:62:114:62:114:Infinity":10,"s:121:35:124:Infinity":16,"b:122:2:122:29:122:29:122:Infinity":11,"s:134:2:134:Infinity":17,"b:134:2:134:38:134:38:134:Infinity":12,"s:137:41:137:Infinity":18,"s:147:2:147:Infinity":19,"b:147:2:147:32:147:32:147:Infinity":13,"s:150:35:150:Infinity":20,"s:160:2:160:Infinity":21,"s:163:42:163:Infinity":22,"s:174:2:174:Infinity":23,"s:177:41:177:Infinity":24,"s:184:13:189:Infinity":25,"b:185:2:185:39:185:39:185:Infinity":14,"f:188:7:188:8":1,"s:188:14:188:22":26,"s:192:42:192:Infinity":27,"s:203:2:203:Infinity":28,"s:207:2:207:Infinity":29,"s:216:58:219:Infinity":30,"b:217:2:217:52:217:52:217:Infinity":15,"s:227:61:230:Infinity":31,"b:228:2:228:55:228:55:228:Infinity":16,"s:239:49:242:Infinity":32,"b:240:2:240:43:240:43:240:Infinity":17,"s:251:52:254:Infinity":33,"b:252:2:252:46:252:46:252:Infinity":18,"s:261:60:264:Infinity":34,"b:262:2:262:54:262:54:262:Infinity":19,"s:271:58:274:Infinity":35,"b:272:2:272:52:272:52:272:Infinity":20,"s:283:52:286:Infinity":36,"b:284:2:284:46:284:46:284:Infinity":21}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/request-context.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/request-context.ts","statementMap":{"0":{"start":{"line":7,"column":30},"end":{"line":7,"column":null}},"1":{"start":{"line":13,"column":2},"end":{"line":13,"column":null}},"2":{"start":{"line":17,"column":2},"end":{"line":17,"column":null}}},"fnMap":{"0":{"name":"runWithRequestContext","decl":{"start":{"line":9,"column":16},"end":{"line":9,"column":null}},"loc":{"start":{"line":12,"column":14},"end":{"line":14,"column":null}},"line":12},"1":{"name":"getRequestContext","decl":{"start":{"line":16,"column":16},"end":{"line":16,"column":52}},"loc":{"start":{"line":16,"column":52},"end":{"line":18,"column":null}},"line":16}},"branchMap":{"0":{"loc":{"start":{"line":17,"column":9},"end":{"line":17,"column":null}},"type":"binary-expr","locations":[{"start":{"line":17,"column":9},"end":{"line":17,"column":45}},{"start":{"line":17,"column":45},"end":{"line":17,"column":null}}],"line":17}},"s":{"0":2,"1":8,"2":72},"f":{"0":8,"1":72},"b":{"0":[72,50]},"meta":{"lastBranch":1,"lastFunction":2,"lastStatement":3,"seen":{"s:7:30:7:Infinity":0,"f:9:16:9:Infinity":0,"s:13:2:13:Infinity":1,"f:16:16:16:52":1,"s:17:2:17:Infinity":2,"b:17:9:17:45:17:45:17:Infinity":0}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/engines/architecture-engine.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/engines/architecture-engine.ts","statementMap":{"0":{"start":{"line":59,"column":4},"end":{"line":59,"column":null}},"1":{"start":{"line":59,"column":44},"end":{"line":59,"column":53}},"2":{"start":{"line":60,"column":4},"end":{"line":60,"column":null}},"3":{"start":{"line":67,"column":46},"end":{"line":67,"column":null}},"4":{"start":{"line":68,"column":24},"end":{"line":68,"column":null}},"5":{"start":{"line":72,"column":4},"end":{"line":80,"column":null}},"6":{"start":{"line":73,"column":6},"end":{"line":73,"column":null}},"7":{"start":{"line":76,"column":6},"end":{"line":79,"column":null}},"8":{"start":{"line":82,"column":4},"end":{"line":146,"column":null}},"9":{"start":{"line":83,"column":20},"end":{"line":83,"column":null}},"10":{"start":{"line":85,"column":6},"end":{"line":96,"column":null}},"11":{"start":{"line":86,"column":8},"end":{"line":94,"column":null}},"12":{"start":{"line":95,"column":8},"end":{"line":95,"column":null}},"13":{"start":{"line":99,"column":22},"end":{"line":101,"column":null}},"14":{"start":{"line":103,"column":6},"end":{"line":145,"column":null}},"15":{"start":{"line":105,"column":8},"end":{"line":110,"column":null}},"16":{"start":{"line":109,"column":10},"end":{"line":109,"column":null}},"17":{"start":{"line":113,"column":29},"end":{"line":113,"column":null}},"18":{"start":{"line":114,"column":8},"end":{"line":114,"column":null}},"19":{"start":{"line":114,"column":27},"end":{"line":114,"column":null}},"20":{"start":{"line":116,"column":30},"end":{"line":116,"column":null}},"21":{"start":{"line":117,"column":8},"end":{"line":117,"column":null}},"22":{"start":{"line":117,"column":28},"end":{"line":117,"column":null}},"23":{"start":{"line":120,"column":8},"end":{"line":129,"column":null}},"24":{"start":{"line":121,"column":10},"end":{"line":128,"column":null}},"25":{"start":{"line":132,"column":8},"end":{"line":144,"column":null}},"26":{"start":{"line":136,"column":10},"end":{"line":143,"column":null}},"27":{"start":{"line":149,"column":31},"end":{"line":149,"column":null}},"28":{"start":{"line":150,"column":4},"end":{"line":150,"column":null}},"29":{"start":{"line":152,"column":23},"end":{"line":152,"column":null}},"30":{"start":{"line":152,"column":48},"end":{"line":152,"column":70}},"31":{"start":{"line":153,"column":25},"end":{"line":153,"column":null}},"32":{"start":{"line":153,"column":50},"end":{"line":153,"column":71}},"33":{"start":{"line":155,"column":4},"end":{"line":164,"column":null}},"34":{"start":{"line":171,"column":4},"end":{"line":177,"column":null}},"35":{"start":{"line":172,"column":6},"end":{"line":176,"column":null}},"36":{"start":{"line":173,"column":8},"end":{"line":175,"column":null}},"37":{"start":{"line":174,"column":10},"end":{"line":174,"column":null}},"38":{"start":{"line":178,"column":4},"end":{"line":178,"column":null}},"39":{"start":{"line":189,"column":25},"end":{"line":194,"column":null}},"40":{"start":{"line":196,"column":18},"end":{"line":196,"column":null}},"41":{"start":{"line":197,"column":4},"end":{"line":197,"column":null}},"42":{"start":{"line":204,"column":4},"end":{"line":220,"column":null}},"43":{"start":{"line":205,"column":22},"end":{"line":205,"column":null}},"44":{"start":{"line":206,"column":35},"end":{"line":206,"column":null}},"45":{"start":{"line":210,"column":8},"end":{"line":210,"column":null}},"46":{"start":{"line":213,"column":6},"end":{"line":215,"column":null}},"47":{"start":{"line":214,"column":8},"end":{"line":214,"column":null}},"48":{"start":{"line":217,"column":6},"end":{"line":217,"column":null}},"49":{"start":{"line":219,"column":6},"end":{"line":219,"column":null}},"50":{"start":{"line":233,"column":4},"end":{"line":243,"column":null}},"51":{"start":{"line":235,"column":18},"end":{"line":235,"column":null}},"52":{"start":{"line":236,"column":6},"end":{"line":236,"column":null}},"53":{"start":{"line":237,"column":4},"end":{"line":243,"column":null}},"54":{"start":{"line":239,"column":6},"end":{"line":239,"column":null}},"55":{"start":{"line":242,"column":6},"end":{"line":242,"column":null}},"56":{"start":{"line":246,"column":18},"end":{"line":246,"column":null}},"57":{"start":{"line":247,"column":4},"end":{"line":249,"column":null}},"58":{"start":{"line":248,"column":6},"end":{"line":248,"column":null}},"59":{"start":{"line":252,"column":23},"end":{"line":258,"column":null}},"60":{"start":{"line":260,"column":4},"end":{"line":265,"column":null}},"61":{"start":{"line":261,"column":23},"end":{"line":261,"column":null}},"62":{"start":{"line":262,"column":6},"end":{"line":264,"column":null}},"63":{"start":{"line":263,"column":8},"end":{"line":263,"column":null}},"64":{"start":{"line":268,"column":4},"end":{"line":270,"column":null}},"65":{"start":{"line":281,"column":4},"end":{"line":283,"column":null}},"66":{"start":{"line":282,"column":6},"end":{"line":282,"column":null}},"67":{"start":{"line":286,"column":4},"end":{"line":288,"column":null}},"68":{"start":{"line":287,"column":6},"end":{"line":287,"column":null}},"69":{"start":{"line":290,"column":4},"end":{"line":290,"column":null}},"70":{"start":{"line":300,"column":4},"end":{"line":302,"column":null}},"71":{"start":{"line":301,"column":6},"end":{"line":301,"column":null}},"72":{"start":{"line":303,"column":4},"end":{"line":303,"column":null}},"73":{"start":{"line":310,"column":46},"end":{"line":310,"column":null}},"74":{"start":{"line":311,"column":24},"end":{"line":311,"column":null}},"75":{"start":{"line":312,"column":20},"end":{"line":312,"column":null}},"76":{"start":{"line":313,"column":27},"end":{"line":313,"column":null}},"77":{"start":{"line":314,"column":31},"end":{"line":314,"column":null}},"78":{"start":{"line":317,"column":24},"end":{"line":317,"column":null}},"79":{"start":{"line":318,"column":10},"end":{"line":321,"column":null}},"80":{"start":{"line":323,"column":4},"end":{"line":337,"column":null}},"81":{"start":{"line":324,"column":22},"end":{"line":324,"column":null}},"82":{"start":{"line":325,"column":40},"end":{"line":325,"column":null}},"83":{"start":{"line":327,"column":6},"end":{"line":334,"column":null}},"84":{"start":{"line":328,"column":8},"end":{"line":333,"column":null}},"85":{"start":{"line":329,"column":27},"end":{"line":329,"column":null}},"86":{"start":{"line":330,"column":10},"end":{"line":332,"column":null}},"87":{"start":{"line":331,"column":12},"end":{"line":331,"column":null}},"88":{"start":{"line":336,"column":6},"end":{"line":336,"column":null}},"89":{"start":{"line":340,"column":16},"end":{"line":362,"column":null}},"90":{"start":{"line":342,"column":25},"end":{"line":342,"column":null}},"91":{"start":{"line":343,"column":6},"end":{"line":346,"column":null}},"92":{"start":{"line":344,"column":8},"end":{"line":344,"column":null}},"93":{"start":{"line":345,"column":8},"end":{"line":345,"column":null}},"94":{"start":{"line":348,"column":6},"end":{"line":348,"column":null}},"95":{"start":{"line":348,"column":29},"end":{"line":348,"column":null}},"96":{"start":{"line":350,"column":6},"end":{"line":350,"column":null}},"97":{"start":{"line":351,"column":6},"end":{"line":351,"column":null}},"98":{"start":{"line":352,"column":6},"end":{"line":352,"column":null}},"99":{"start":{"line":354,"column":24},"end":{"line":354,"column":null}},"100":{"start":{"line":355,"column":6},"end":{"line":357,"column":null}},"101":{"start":{"line":356,"column":8},"end":{"line":356,"column":null}},"102":{"start":{"line":359,"column":6},"end":{"line":359,"column":null}},"103":{"start":{"line":360,"column":6},"end":{"line":360,"column":null}},"104":{"start":{"line":361,"column":6},"end":{"line":361,"column":null}},"105":{"start":{"line":365,"column":4},"end":{"line":369,"column":null}},"106":{"start":{"line":366,"column":6},"end":{"line":368,"column":null}},"107":{"start":{"line":367,"column":8},"end":{"line":367,"column":null}},"108":{"start":{"line":372,"column":27},"end":{"line":372,"column":null}},"109":{"start":{"line":373,"column":4},"end":{"line":388,"column":null}},"110":{"start":{"line":374,"column":6},"end":{"line":374,"column":null}},"111":{"start":{"line":374,"column":37},"end":{"line":374,"column":null}},"112":{"start":{"line":375,"column":23},"end":{"line":375,"column":null}},"113":{"start":{"line":376,"column":6},"end":{"line":387,"column":null}},"114":{"start":{"line":377,"column":8},"end":{"line":377,"column":null}},"115":{"start":{"line":378,"column":8},"end":{"line":386,"column":null}},"116":{"start":{"line":390,"column":4},"end":{"line":390,"column":null}},"117":{"start":{"line":406,"column":4},"end":{"line":428,"column":null}},"118":{"start":{"line":407,"column":25},"end":{"line":407,"column":null}},"119":{"start":{"line":409,"column":6},"end":{"line":417,"column":null}},"120":{"start":{"line":412,"column":25},"end":{"line":412,"column":null}},"121":{"start":{"line":413,"column":8},"end":{"line":416,"column":null}},"122":{"start":{"line":414,"column":10},"end":{"line":414,"column":null}},"123":{"start":{"line":415,"column":10},"end":{"line":415,"column":null}},"124":{"start":{"line":419,"column":6},"end":{"line":427,"column":null}},"125":{"start":{"line":421,"column":30},"end":{"line":421,"column":null}},"126":{"start":{"line":422,"column":8},"end":{"line":426,"column":null}},"127":{"start":{"line":430,"column":4},"end":{"line":430,"column":null}},"128":{"start":{"line":439,"column":24},"end":{"line":439,"column":null}},"129":{"start":{"line":440,"column":21},"end":{"line":440,"column":null}},"130":{"start":{"line":442,"column":19},"end":{"line":442,"column":null}},"131":{"start":{"line":443,"column":4},"end":{"line":452,"column":null}},"132":{"start":{"line":444,"column":6},"end":{"line":444,"column":null}},"133":{"start":{"line":445,"column":4},"end":{"line":452,"column":null}},"134":{"start":{"line":446,"column":6},"end":{"line":446,"column":null}},"135":{"start":{"line":447,"column":6},"end":{"line":447,"column":null}},"136":{"start":{"line":448,"column":4},"end":{"line":452,"column":null}},"137":{"start":{"line":449,"column":6},"end":{"line":451,"column":null}},"138":{"start":{"line":454,"column":4},"end":{"line":454,"column":null}},"139":{"start":{"line":464,"column":4},"end":{"line":464,"column":null}},"140":{"start":{"line":466,"column":42},"end":{"line":466,"column":null}},"141":{"start":{"line":469,"column":4},"end":{"line":482,"column":null}},"142":{"start":{"line":470,"column":6},"end":{"line":481,"column":null}},"143":{"start":{"line":485,"column":4},"end":{"line":516,"column":null}},"144":{"start":{"line":487,"column":6},"end":{"line":495,"column":null}},"145":{"start":{"line":499,"column":21},"end":{"line":499,"column":null}},"146":{"start":{"line":500,"column":6},"end":{"line":515,"column":null}},"147":{"start":{"line":501,"column":8},"end":{"line":514,"column":null}},"148":{"start":{"line":519,"column":20},"end":{"line":519,"column":null}},"149":{"start":{"line":522,"column":19},"end":{"line":522,"column":null}},"150":{"start":{"line":522,"column":41},"end":{"line":522,"column":48}},"151":{"start":{"line":523,"column":4},"end":{"line":530,"column":null}},"152":{"start":{"line":524,"column":6},"end":{"line":524,"column":null}},"153":{"start":{"line":525,"column":6},"end":{"line":525,"column":null}},"154":{"start":{"line":525,"column":40},"end":{"line":525,"column":72}},"155":{"start":{"line":527,"column":6},"end":{"line":529,"column":null}},"156":{"start":{"line":538,"column":4},"end":{"line":540,"column":null}},"157":{"start":{"line":549,"column":4},"end":{"line":560,"column":null}},"158":{"start":{"line":551,"column":8},"end":{"line":551,"column":null}},"159":{"start":{"line":553,"column":8},"end":{"line":553,"column":null}},"160":{"start":{"line":555,"column":8},"end":{"line":555,"column":null}},"161":{"start":{"line":557,"column":8},"end":{"line":557,"column":null}},"162":{"start":{"line":559,"column":8},"end":{"line":559,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":54,"column":2},"end":{"line":54,"column":null}},"loc":{"start":{"line":58,"column":4},"end":{"line":61,"column":null}},"line":58},"1":{"name":"(anonymous_1)","decl":{"start":{"line":59,"column":37},"end":{"line":59,"column":38}},"loc":{"start":{"line":59,"column":44},"end":{"line":59,"column":53}},"line":59},"2":{"name":"(anonymous_2)","decl":{"start":{"line":66,"column":8},"end":{"line":66,"column":17}},"loc":{"start":{"line":66,"column":62},"end":{"line":165,"column":null}},"line":66},"3":{"name":"(anonymous_3)","decl":{"start":{"line":152,"column":41},"end":{"line":152,"column":42}},"loc":{"start":{"line":152,"column":48},"end":{"line":152,"column":70}},"line":152},"4":{"name":"(anonymous_4)","decl":{"start":{"line":153,"column":43},"end":{"line":153,"column":44}},"loc":{"start":{"line":153,"column":50},"end":{"line":153,"column":71}},"line":153},"5":{"name":"(anonymous_5)","decl":{"start":{"line":170,"column":10},"end":{"line":170,"column":25}},"loc":{"start":{"line":170,"column":67},"end":{"line":179,"column":null}},"line":170},"6":{"name":"(anonymous_6)","decl":{"start":{"line":184,"column":10},"end":{"line":184,"column":25}},"loc":{"start":{"line":184,"column":69},"end":{"line":198,"column":null}},"line":184},"7":{"name":"(anonymous_7)","decl":{"start":{"line":203,"column":10},"end":{"line":203,"column":33}},"loc":{"start":{"line":203,"column":61},"end":{"line":221,"column":null}},"line":203},"8":{"name":"(anonymous_8)","decl":{"start":{"line":226,"column":10},"end":{"line":226,"column":null}},"loc":{"start":{"line":230,"column":19},"end":{"line":271,"column":null}},"line":230},"9":{"name":"(anonymous_9)","decl":{"start":{"line":276,"column":10},"end":{"line":276,"column":null}},"loc":{"start":{"line":279,"column":13},"end":{"line":291,"column":null}},"line":279},"10":{"name":"(anonymous_10)","decl":{"start":{"line":296,"column":10},"end":{"line":296,"column":null}},"loc":{"start":{"line":299,"column":13},"end":{"line":304,"column":null}},"line":299},"11":{"name":"(anonymous_11)","decl":{"start":{"line":309,"column":10},"end":{"line":309,"column":62}},"loc":{"start":{"line":309,"column":62},"end":{"line":391,"column":null}},"line":309},"12":{"name":"(anonymous_12)","decl":{"start":{"line":340,"column":16},"end":{"line":340,"column":17}},"loc":{"start":{"line":340,"column":63},"end":{"line":362,"column":null}},"line":340},"13":{"name":"(anonymous_13)","decl":{"start":{"line":396,"column":2},"end":{"line":396,"column":null}},"loc":{"start":{"line":404,"column":11},"end":{"line":431,"column":null}},"line":404},"14":{"name":"(anonymous_14)","decl":{"start":{"line":433,"column":10},"end":{"line":433,"column":null}},"loc":{"start":{"line":437,"column":12},"end":{"line":455,"column":null}},"line":437},"15":{"name":"(anonymous_15)","decl":{"start":{"line":460,"column":8},"end":{"line":460,"column":null}},"loc":{"start":{"line":463,"column":19},"end":{"line":531,"column":null}},"line":463},"16":{"name":"(anonymous_16)","decl":{"start":{"line":522,"column":34},"end":{"line":522,"column":35}},"loc":{"start":{"line":522,"column":41},"end":{"line":522,"column":48}},"line":522},"17":{"name":"(anonymous_17)","decl":{"start":{"line":525,"column":33},"end":{"line":525,"column":34}},"loc":{"start":{"line":525,"column":40},"end":{"line":525,"column":72}},"line":525},"18":{"name":"(anonymous_18)","decl":{"start":{"line":537,"column":2},"end":{"line":537,"column":9}},"loc":{"start":{"line":537,"column":62},"end":{"line":543,"column":null}},"line":537},"19":{"name":"(anonymous_19)","decl":{"start":{"line":548,"column":10},"end":{"line":548,"column":35}},"loc":{"start":{"line":548,"column":64},"end":{"line":561,"column":null}},"line":548}},"branchMap":{"0":{"loc":{"start":{"line":72,"column":4},"end":{"line":80,"column":null}},"type":"if","locations":[{"start":{"line":72,"column":4},"end":{"line":80,"column":null}},{"start":{"line":74,"column":11},"end":{"line":80,"column":null}}],"line":72},"1":{"loc":{"start":{"line":72,"column":8},"end":{"line":72,"column":35}},"type":"binary-expr","locations":[{"start":{"line":72,"column":8},"end":{"line":72,"column":17}},{"start":{"line":72,"column":17},"end":{"line":72,"column":35}}],"line":72},"2":{"loc":{"start":{"line":85,"column":6},"end":{"line":96,"column":null}},"type":"if","locations":[{"start":{"line":85,"column":6},"end":{"line":96,"column":null}},{"start":{},"end":{}}],"line":85},"3":{"loc":{"start":{"line":105,"column":8},"end":{"line":110,"column":null}},"type":"if","locations":[{"start":{"line":105,"column":8},"end":{"line":110,"column":null}},{"start":{},"end":{}}],"line":105},"4":{"loc":{"start":{"line":106,"column":10},"end":{"line":107,"column":null}},"type":"binary-expr","locations":[{"start":{"line":106,"column":10},"end":{"line":106,"column":null}},{"start":{"line":107,"column":11},"end":{"line":107,"column":44}},{"start":{"line":107,"column":44},"end":{"line":107,"column":null}}],"line":106},"5":{"loc":{"start":{"line":114,"column":8},"end":{"line":114,"column":null}},"type":"if","locations":[{"start":{"line":114,"column":8},"end":{"line":114,"column":null}},{"start":{},"end":{}}],"line":114},"6":{"loc":{"start":{"line":117,"column":8},"end":{"line":117,"column":null}},"type":"if","locations":[{"start":{"line":117,"column":8},"end":{"line":117,"column":null}},{"start":{},"end":{}}],"line":117},"7":{"loc":{"start":{"line":120,"column":8},"end":{"line":129,"column":null}},"type":"if","locations":[{"start":{"line":120,"column":8},"end":{"line":129,"column":null}},{"start":{},"end":{}}],"line":120},"8":{"loc":{"start":{"line":132,"column":8},"end":{"line":144,"column":null}},"type":"if","locations":[{"start":{"line":132,"column":8},"end":{"line":144,"column":null}},{"start":{},"end":{}}],"line":132},"9":{"loc":{"start":{"line":133,"column":10},"end":{"line":134,"column":null}},"type":"binary-expr","locations":[{"start":{"line":133,"column":10},"end":{"line":133,"column":null}},{"start":{"line":134,"column":10},"end":{"line":134,"column":null}}],"line":133},"10":{"loc":{"start":{"line":173,"column":8},"end":{"line":175,"column":null}},"type":"if","locations":[{"start":{"line":173,"column":8},"end":{"line":175,"column":null}},{"start":{},"end":{}}],"line":173},"11":{"loc":{"start":{"line":233,"column":4},"end":{"line":243,"column":null}},"type":"if","locations":[{"start":{"line":233,"column":4},"end":{"line":243,"column":null}},{"start":{"line":237,"column":4},"end":{"line":243,"column":null}}],"line":233},"12":{"loc":{"start":{"line":237,"column":4},"end":{"line":243,"column":null}},"type":"if","locations":[{"start":{"line":237,"column":4},"end":{"line":243,"column":null}},{"start":{"line":240,"column":11},"end":{"line":243,"column":null}}],"line":237},"13":{"loc":{"start":{"line":247,"column":4},"end":{"line":249,"column":null}},"type":"if","locations":[{"start":{"line":247,"column":4},"end":{"line":249,"column":null}},{"start":{},"end":{}}],"line":247},"14":{"loc":{"start":{"line":262,"column":6},"end":{"line":264,"column":null}},"type":"if","locations":[{"start":{"line":262,"column":6},"end":{"line":264,"column":null}},{"start":{},"end":{}}],"line":262},"15":{"loc":{"start":{"line":268,"column":11},"end":{"line":270,"column":null}},"type":"cond-expr","locations":[{"start":{"line":269,"column":8},"end":{"line":269,"column":null}},{"start":{"line":270,"column":8},"end":{"line":270,"column":null}}],"line":268},"16":{"loc":{"start":{"line":268,"column":11},"end":{"line":268,"column":null}},"type":"binary-expr","locations":[{"start":{"line":268,"column":11},"end":{"line":268,"column":38}},{"start":{"line":268,"column":38},"end":{"line":268,"column":null}}],"line":268},"17":{"loc":{"start":{"line":281,"column":4},"end":{"line":283,"column":null}},"type":"if","locations":[{"start":{"line":281,"column":4},"end":{"line":283,"column":null}},{"start":{},"end":{}}],"line":281},"18":{"loc":{"start":{"line":286,"column":4},"end":{"line":288,"column":null}},"type":"if","locations":[{"start":{"line":286,"column":4},"end":{"line":288,"column":null}},{"start":{},"end":{}}],"line":286},"19":{"loc":{"start":{"line":300,"column":4},"end":{"line":302,"column":null}},"type":"if","locations":[{"start":{"line":300,"column":4},"end":{"line":302,"column":null}},{"start":{},"end":{}}],"line":300},"20":{"loc":{"start":{"line":328,"column":8},"end":{"line":333,"column":null}},"type":"if","locations":[{"start":{"line":328,"column":8},"end":{"line":333,"column":null}},{"start":{},"end":{}}],"line":328},"21":{"loc":{"start":{"line":328,"column":12},"end":{"line":328,"column":59}},"type":"binary-expr","locations":[{"start":{"line":328,"column":12},"end":{"line":328,"column":35}},{"start":{"line":328,"column":35},"end":{"line":328,"column":59}}],"line":328},"22":{"loc":{"start":{"line":330,"column":10},"end":{"line":332,"column":null}},"type":"if","locations":[{"start":{"line":330,"column":10},"end":{"line":332,"column":null}},{"start":{},"end":{}}],"line":330},"23":{"loc":{"start":{"line":343,"column":6},"end":{"line":346,"column":null}},"type":"if","locations":[{"start":{"line":343,"column":6},"end":{"line":346,"column":null}},{"start":{},"end":{}}],"line":343},"24":{"loc":{"start":{"line":348,"column":6},"end":{"line":348,"column":null}},"type":"if","locations":[{"start":{"line":348,"column":6},"end":{"line":348,"column":null}},{"start":{},"end":{}}],"line":348},"25":{"loc":{"start":{"line":354,"column":24},"end":{"line":354,"column":null}},"type":"binary-expr","locations":[{"start":{"line":354,"column":24},"end":{"line":354,"column":49}},{"start":{"line":354,"column":49},"end":{"line":354,"column":null}}],"line":354},"26":{"loc":{"start":{"line":366,"column":6},"end":{"line":368,"column":null}},"type":"if","locations":[{"start":{"line":366,"column":6},"end":{"line":368,"column":null}},{"start":{},"end":{}}],"line":366},"27":{"loc":{"start":{"line":374,"column":6},"end":{"line":374,"column":null}},"type":"if","locations":[{"start":{"line":374,"column":6},"end":{"line":374,"column":null}},{"start":{},"end":{}}],"line":374},"28":{"loc":{"start":{"line":376,"column":6},"end":{"line":387,"column":null}},"type":"if","locations":[{"start":{"line":376,"column":6},"end":{"line":387,"column":null}},{"start":{},"end":{}}],"line":376},"29":{"loc":{"start":{"line":382,"column":17},"end":{"line":382,"column":null}},"type":"binary-expr","locations":[{"start":{"line":382,"column":17},"end":{"line":382,"column":54}},{"start":{"line":382,"column":54},"end":{"line":382,"column":null}}],"line":382},"30":{"loc":{"start":{"line":413,"column":8},"end":{"line":416,"column":null}},"type":"if","locations":[{"start":{"line":413,"column":8},"end":{"line":416,"column":null}},{"start":{},"end":{}}],"line":413},"31":{"loc":{"start":{"line":413,"column":12},"end":{"line":413,"column":64}},"type":"binary-expr","locations":[{"start":{"line":413,"column":12},"end":{"line":413,"column":24}},{"start":{"line":413,"column":24},"end":{"line":413,"column":64}}],"line":413},"32":{"loc":{"start":{"line":419,"column":6},"end":{"line":427,"column":null}},"type":"if","locations":[{"start":{"line":419,"column":6},"end":{"line":427,"column":null}},{"start":{},"end":{}}],"line":419},"33":{"loc":{"start":{"line":443,"column":4},"end":{"line":452,"column":null}},"type":"if","locations":[{"start":{"line":443,"column":4},"end":{"line":452,"column":null}},{"start":{"line":445,"column":4},"end":{"line":452,"column":null}}],"line":443},"34":{"loc":{"start":{"line":444,"column":17},"end":{"line":444,"column":null}},"type":"cond-expr","locations":[{"start":{"line":444,"column":45},"end":{"line":444,"column":56}},{"start":{"line":444,"column":56},"end":{"line":444,"column":null}}],"line":444},"35":{"loc":{"start":{"line":445,"column":4},"end":{"line":452,"column":null}},"type":"if","locations":[{"start":{"line":445,"column":4},"end":{"line":452,"column":null}},{"start":{"line":448,"column":4},"end":{"line":452,"column":null}}],"line":445},"36":{"loc":{"start":{"line":446,"column":17},"end":{"line":446,"column":null}},"type":"cond-expr","locations":[{"start":{"line":446,"column":46},"end":{"line":446,"column":57}},{"start":{"line":446,"column":57},"end":{"line":446,"column":null}}],"line":446},"37":{"loc":{"start":{"line":447,"column":17},"end":{"line":447,"column":null}},"type":"cond-expr","locations":[{"start":{"line":447,"column":44},"end":{"line":447,"column":55}},{"start":{"line":447,"column":55},"end":{"line":447,"column":null}}],"line":447},"38":{"loc":{"start":{"line":448,"column":4},"end":{"line":452,"column":null}},"type":"if","locations":[{"start":{"line":448,"column":4},"end":{"line":452,"column":null}},{"start":{},"end":{}}],"line":448},"39":{"loc":{"start":{"line":449,"column":17},"end":{"line":451,"column":null}},"type":"cond-expr","locations":[{"start":{"line":450,"column":10},"end":{"line":450,"column":null}},{"start":{"line":451,"column":10},"end":{"line":451,"column":null}}],"line":449},"40":{"loc":{"start":{"line":500,"column":6},"end":{"line":515,"column":null}},"type":"if","locations":[{"start":{"line":500,"column":6},"end":{"line":515,"column":null}},{"start":{},"end":{}}],"line":500},"41":{"loc":{"start":{"line":523,"column":4},"end":{"line":530,"column":null}},"type":"if","locations":[{"start":{"line":523,"column":4},"end":{"line":530,"column":null}},{"start":{"line":526,"column":11},"end":{"line":530,"column":null}}],"line":523},"42":{"loc":{"start":{"line":549,"column":4},"end":{"line":560,"column":null}},"type":"switch","locations":[{"start":{"line":550,"column":6},"end":{"line":551,"column":null}},{"start":{"line":552,"column":6},"end":{"line":553,"column":null}},{"start":{"line":554,"column":6},"end":{"line":555,"column":null}},{"start":{"line":556,"column":6},"end":{"line":557,"column":null}},{"start":{"line":558,"column":6},"end":{"line":559,"column":null}}],"line":549}},"s":{"0":3,"1":9,"2":3,"3":2,"4":2,"5":2,"6":1,"7":1,"8":2,"9":4,"10":4,"11":0,"12":0,"13":4,"14":4,"15":3,"16":0,"17":3,"18":3,"19":0,"20":3,"21":3,"22":0,"23":3,"24":1,"25":3,"26":1,"27":2,"28":2,"29":2,"30":4,"31":2,"32":4,"33":2,"34":9,"35":20,"36":20,"37":9,"38":0,"39":20,"40":20,"41":20,"42":8,"43":8,"44":8,"45":8,"46":8,"47":6,"48":8,"49":0,"50":6,"51":6,"52":6,"53":0,"54":0,"55":0,"56":6,"57":6,"58":0,"59":6,"60":6,"61":12,"62":12,"63":6,"64":0,"65":4,"66":3,"67":1,"68":0,"69":1,"70":3,"71":0,"72":3,"73":2,"74":2,"75":2,"76":2,"77":2,"78":2,"79":2,"80":2,"81":4,"82":4,"83":4,"84":3,"85":3,"86":3,"87":3,"88":4,"89":2,"90":9,"91":9,"92":2,"93":2,"94":7,"95":0,"96":7,"97":7,"98":7,"99":7,"100":9,"101":5,"102":7,"103":7,"104":7,"105":2,"106":4,"107":4,"108":2,"109":2,"110":2,"111":0,"112":2,"113":2,"114":2,"115":2,"116":2,"117":1,"118":1,"119":1,"120":1,"121":1,"122":0,"123":0,"124":1,"125":1,"126":1,"127":0,"128":1,"129":1,"130":1,"131":1,"132":0,"133":1,"134":0,"135":0,"136":1,"137":1,"138":1,"139":0,"140":0,"141":0,"142":0,"143":0,"144":0,"145":0,"146":0,"147":0,"148":0,"149":0,"150":0,"151":0,"152":0,"153":0,"154":0,"155":0,"156":0,"157":0,"158":0,"159":0,"160":0,"161":0,"162":0},"f":{"0":3,"1":9,"2":2,"3":4,"4":4,"5":9,"6":20,"7":8,"8":6,"9":4,"10":3,"11":2,"12":9,"13":1,"14":1,"15":0,"16":0,"17":0,"18":0,"19":0},"b":{"0":[1,1],"1":[2,1],"2":[0,4],"3":[0,3],"4":[3,3,0],"5":[0,3],"6":[0,3],"7":[1,2],"8":[1,2],"9":[3,3],"10":[9,11],"11":[6,0],"12":[0,0],"13":[0,6],"14":[6,6],"15":[0,0],"16":[0,0],"17":[3,1],"18":[0,1],"19":[0,3],"20":[3,0],"21":[3,0],"22":[3,0],"23":[2,7],"24":[0,7],"25":[7,0],"26":[4,0],"27":[0,2],"28":[2,0],"29":[2,0],"30":[0,1],"31":[1,1],"32":[1,0],"33":[0,1],"34":[0,0],"35":[0,1],"36":[0,0],"37":[0,0],"38":[1,0],"39":[0,1],"40":[0,0],"41":[0,0],"42":[0,0,0,0,0]},"meta":{"lastBranch":43,"lastFunction":20,"lastStatement":163,"seen":{"f:54:2:54:Infinity":0,"s:59:4:59:Infinity":0,"f:59:37:59:38":1,"s:59:44:59:53":1,"s:60:4:60:Infinity":2,"f:66:8:66:17":2,"s:67:46:67:Infinity":3,"s:68:24:68:Infinity":4,"b:72:4:80:Infinity:74:11:80:Infinity":0,"s:72:4:80:Infinity":5,"b:72:8:72:17:72:17:72:35":1,"s:73:6:73:Infinity":6,"s:76:6:79:Infinity":7,"s:82:4:146:Infinity":8,"s:83:20:83:Infinity":9,"b:85:6:96:Infinity:undefined:undefined:undefined:undefined":2,"s:85:6:96:Infinity":10,"s:86:8:94:Infinity":11,"s:95:8:95:Infinity":12,"s:99:22:101:Infinity":13,"s:103:6:145:Infinity":14,"b:105:8:110:Infinity:undefined:undefined:undefined:undefined":3,"s:105:8:110:Infinity":15,"b:106:10:106:Infinity:107:11:107:44:107:44:107:Infinity":4,"s:109:10:109:Infinity":16,"s:113:29:113:Infinity":17,"b:114:8:114:Infinity:undefined:undefined:undefined:undefined":5,"s:114:8:114:Infinity":18,"s:114:27:114:Infinity":19,"s:116:30:116:Infinity":20,"b:117:8:117:Infinity:undefined:undefined:undefined:undefined":6,"s:117:8:117:Infinity":21,"s:117:28:117:Infinity":22,"b:120:8:129:Infinity:undefined:undefined:undefined:undefined":7,"s:120:8:129:Infinity":23,"s:121:10:128:Infinity":24,"b:132:8:144:Infinity:undefined:undefined:undefined:undefined":8,"s:132:8:144:Infinity":25,"b:133:10:133:Infinity:134:10:134:Infinity":9,"s:136:10:143:Infinity":26,"s:149:31:149:Infinity":27,"s:150:4:150:Infinity":28,"s:152:23:152:Infinity":29,"f:152:41:152:42":3,"s:152:48:152:70":30,"s:153:25:153:Infinity":31,"f:153:43:153:44":4,"s:153:50:153:71":32,"s:155:4:164:Infinity":33,"f:170:10:170:25":5,"s:171:4:177:Infinity":34,"s:172:6:176:Infinity":35,"b:173:8:175:Infinity:undefined:undefined:undefined:undefined":10,"s:173:8:175:Infinity":36,"s:174:10:174:Infinity":37,"s:178:4:178:Infinity":38,"f:184:10:184:25":6,"s:189:25:194:Infinity":39,"s:196:18:196:Infinity":40,"s:197:4:197:Infinity":41,"f:203:10:203:33":7,"s:204:4:220:Infinity":42,"s:205:22:205:Infinity":43,"s:206:35:206:Infinity":44,"s:210:8:210:Infinity":45,"s:213:6:215:Infinity":46,"s:214:8:214:Infinity":47,"s:217:6:217:Infinity":48,"s:219:6:219:Infinity":49,"f:226:10:226:Infinity":8,"b:233:4:243:Infinity:237:4:243:Infinity":11,"s:233:4:243:Infinity":50,"s:235:18:235:Infinity":51,"s:236:6:236:Infinity":52,"b:237:4:243:Infinity:240:11:243:Infinity":12,"s:237:4:243:Infinity":53,"s:239:6:239:Infinity":54,"s:242:6:242:Infinity":55,"s:246:18:246:Infinity":56,"b:247:4:249:Infinity:undefined:undefined:undefined:undefined":13,"s:247:4:249:Infinity":57,"s:248:6:248:Infinity":58,"s:252:23:258:Infinity":59,"s:260:4:265:Infinity":60,"s:261:23:261:Infinity":61,"b:262:6:264:Infinity:undefined:undefined:undefined:undefined":14,"s:262:6:264:Infinity":62,"s:263:8:263:Infinity":63,"s:268:4:270:Infinity":64,"b:269:8:269:Infinity:270:8:270:Infinity":15,"b:268:11:268:38:268:38:268:Infinity":16,"f:276:10:276:Infinity":9,"b:281:4:283:Infinity:undefined:undefined:undefined:undefined":17,"s:281:4:283:Infinity":65,"s:282:6:282:Infinity":66,"b:286:4:288:Infinity:undefined:undefined:undefined:undefined":18,"s:286:4:288:Infinity":67,"s:287:6:287:Infinity":68,"s:290:4:290:Infinity":69,"f:296:10:296:Infinity":10,"b:300:4:302:Infinity:undefined:undefined:undefined:undefined":19,"s:300:4:302:Infinity":70,"s:301:6:301:Infinity":71,"s:303:4:303:Infinity":72,"f:309:10:309:62":11,"s:310:46:310:Infinity":73,"s:311:24:311:Infinity":74,"s:312:20:312:Infinity":75,"s:313:27:313:Infinity":76,"s:314:31:314:Infinity":77,"s:317:24:317:Infinity":78,"s:318:10:321:Infinity":79,"s:323:4:337:Infinity":80,"s:324:22:324:Infinity":81,"s:325:40:325:Infinity":82,"s:327:6:334:Infinity":83,"b:328:8:333:Infinity:undefined:undefined:undefined:undefined":20,"s:328:8:333:Infinity":84,"b:328:12:328:35:328:35:328:59":21,"s:329:27:329:Infinity":85,"b:330:10:332:Infinity:undefined:undefined:undefined:undefined":22,"s:330:10:332:Infinity":86,"s:331:12:331:Infinity":87,"s:336:6:336:Infinity":88,"s:340:16:362:Infinity":89,"f:340:16:340:17":12,"s:342:25:342:Infinity":90,"b:343:6:346:Infinity:undefined:undefined:undefined:undefined":23,"s:343:6:346:Infinity":91,"s:344:8:344:Infinity":92,"s:345:8:345:Infinity":93,"b:348:6:348:Infinity:undefined:undefined:undefined:undefined":24,"s:348:6:348:Infinity":94,"s:348:29:348:Infinity":95,"s:350:6:350:Infinity":96,"s:351:6:351:Infinity":97,"s:352:6:352:Infinity":98,"s:354:24:354:Infinity":99,"b:354:24:354:49:354:49:354:Infinity":25,"s:355:6:357:Infinity":100,"s:356:8:356:Infinity":101,"s:359:6:359:Infinity":102,"s:360:6:360:Infinity":103,"s:361:6:361:Infinity":104,"s:365:4:369:Infinity":105,"b:366:6:368:Infinity:undefined:undefined:undefined:undefined":26,"s:366:6:368:Infinity":106,"s:367:8:367:Infinity":107,"s:372:27:372:Infinity":108,"s:373:4:388:Infinity":109,"b:374:6:374:Infinity:undefined:undefined:undefined:undefined":27,"s:374:6:374:Infinity":110,"s:374:37:374:Infinity":111,"s:375:23:375:Infinity":112,"b:376:6:387:Infinity:undefined:undefined:undefined:undefined":28,"s:376:6:387:Infinity":113,"s:377:8:377:Infinity":114,"s:378:8:386:Infinity":115,"b:382:17:382:54:382:54:382:Infinity":29,"s:390:4:390:Infinity":116,"f:396:2:396:Infinity":13,"s:406:4:428:Infinity":117,"s:407:25:407:Infinity":118,"s:409:6:417:Infinity":119,"s:412:25:412:Infinity":120,"b:413:8:416:Infinity:undefined:undefined:undefined:undefined":30,"s:413:8:416:Infinity":121,"b:413:12:413:24:413:24:413:64":31,"s:414:10:414:Infinity":122,"s:415:10:415:Infinity":123,"b:419:6:427:Infinity:undefined:undefined:undefined:undefined":32,"s:419:6:427:Infinity":124,"s:421:30:421:Infinity":125,"s:422:8:426:Infinity":126,"s:430:4:430:Infinity":127,"f:433:10:433:Infinity":14,"s:439:24:439:Infinity":128,"s:440:21:440:Infinity":129,"s:442:19:442:Infinity":130,"b:443:4:452:Infinity:445:4:452:Infinity":33,"s:443:4:452:Infinity":131,"s:444:6:444:Infinity":132,"b:444:45:444:56:444:56:444:Infinity":34,"b:445:4:452:Infinity:448:4:452:Infinity":35,"s:445:4:452:Infinity":133,"s:446:6:446:Infinity":134,"b:446:46:446:57:446:57:446:Infinity":36,"s:447:6:447:Infinity":135,"b:447:44:447:55:447:55:447:Infinity":37,"b:448:4:452:Infinity:undefined:undefined:undefined:undefined":38,"s:448:4:452:Infinity":136,"s:449:6:451:Infinity":137,"b:450:10:450:Infinity:451:10:451:Infinity":39,"s:454:4:454:Infinity":138,"f:460:8:460:Infinity":15,"s:464:4:464:Infinity":139,"s:466:42:466:Infinity":140,"s:469:4:482:Infinity":141,"s:470:6:481:Infinity":142,"s:485:4:516:Infinity":143,"s:487:6:495:Infinity":144,"s:499:21:499:Infinity":145,"b:500:6:515:Infinity:undefined:undefined:undefined:undefined":40,"s:500:6:515:Infinity":146,"s:501:8:514:Infinity":147,"s:519:20:519:Infinity":148,"s:522:19:522:Infinity":149,"f:522:34:522:35":16,"s:522:41:522:48":150,"b:523:4:530:Infinity:526:11:530:Infinity":41,"s:523:4:530:Infinity":151,"s:524:6:524:Infinity":152,"s:525:6:525:Infinity":153,"f:525:33:525:34":17,"s:525:40:525:72":154,"s:527:6:529:Infinity":155,"f:537:2:537:9":18,"s:538:4:540:Infinity":156,"f:548:10:548:35":19,"b:550:6:551:Infinity:552:6:553:Infinity:554:6:555:Infinity:556:6:557:Infinity:558:6:559:Infinity":42,"s:549:4:560:Infinity":157,"s:551:8:551:Infinity":158,"s:553:8:553:Infinity":159,"s:555:8:555:Infinity":160,"s:557:8:557:Infinity":161,"s:559:8:559:Infinity":162}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/engines/community-detector.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/engines/community-detector.ts","statementMap":{"0":{"start":{"line":20,"column":22},"end":{"line":20,"column":48}},"1":{"start":{"line":24,"column":23},"end":{"line":33,"column":null}},"2":{"start":{"line":35,"column":10},"end":{"line":42,"column":null}},"3":{"start":{"line":36,"column":21},"end":{"line":41,"column":8}},"4":{"start":{"line":42,"column":23},"end":{"line":42,"column":40}},"5":{"start":{"line":44,"column":4},"end":{"line":46,"column":null}},"6":{"start":{"line":45,"column":6},"end":{"line":45,"column":null}},"7":{"start":{"line":49,"column":23},"end":{"line":49,"column":null}},"8":{"start":{"line":50,"column":4},"end":{"line":52,"column":null}},"9":{"start":{"line":51,"column":6},"end":{"line":51,"column":null}},"10":{"start":{"line":55,"column":4},"end":{"line":55,"column":null}},"11":{"start":{"line":66,"column":4},"end":{"line":119,"column":null}},"12":{"start":{"line":69,"column":23},"end":{"line":76,"column":null}},"13":{"start":{"line":78,"column":6},"end":{"line":84,"column":null}},"14":{"start":{"line":83,"column":8},"end":{"line":83,"column":null}},"15":{"start":{"line":87,"column":27},"end":{"line":87,"column":null}},"16":{"start":{"line":88,"column":6},"end":{"line":94,"column":null}},"17":{"start":{"line":89,"column":23},"end":{"line":89,"column":null}},"18":{"start":{"line":90,"column":20},"end":{"line":90,"column":null}},"19":{"start":{"line":91,"column":8},"end":{"line":93,"column":null}},"20":{"start":{"line":92,"column":10},"end":{"line":92,"column":null}},"21":{"start":{"line":96,"column":6},"end":{"line":96,"column":null}},"22":{"start":{"line":96,"column":35},"end":{"line":96,"column":null}},"23":{"start":{"line":99,"column":22},"end":{"line":99,"column":null}},"24":{"start":{"line":100,"column":6},"end":{"line":105,"column":null}},"25":{"start":{"line":101,"column":20},"end":{"line":101,"column":null}},"26":{"start":{"line":102,"column":8},"end":{"line":102,"column":null}},"27":{"start":{"line":102,"column":31},"end":{"line":102,"column":null}},"28":{"start":{"line":103,"column":8},"end":{"line":103,"column":null}},"29":{"start":{"line":103,"column":31},"end":{"line":103,"column":null}},"30":{"start":{"line":104,"column":8},"end":{"line":104,"column":null}},"31":{"start":{"line":107,"column":6},"end":{"line":107,"column":null}},"32":{"start":{"line":108,"column":6},"end":{"line":110,"column":null}},"33":{"start":{"line":111,"column":6},"end":{"line":115,"column":null}},"34":{"start":{"line":118,"column":6},"end":{"line":118,"column":null}},"35":{"start":{"line":129,"column":20},"end":{"line":129,"column":null}},"36":{"start":{"line":130,"column":4},"end":{"line":134,"column":null}},"37":{"start":{"line":131,"column":20},"end":{"line":131,"column":null}},"38":{"start":{"line":132,"column":6},"end":{"line":132,"column":null}},"39":{"start":{"line":132,"column":31},"end":{"line":132,"column":null}},"40":{"start":{"line":133,"column":6},"end":{"line":133,"column":null}},"41":{"start":{"line":137,"column":27},"end":{"line":137,"column":null}},"42":{"start":{"line":138,"column":14},"end":{"line":138,"column":null}},"43":{"start":{"line":139,"column":4},"end":{"line":142,"column":null}},"44":{"start":{"line":140,"column":6},"end":{"line":140,"column":null}},"45":{"start":{"line":141,"column":6},"end":{"line":141,"column":null}},"46":{"start":{"line":144,"column":4},"end":{"line":144,"column":null}},"47":{"start":{"line":145,"column":4},"end":{"line":147,"column":null}},"48":{"start":{"line":148,"column":4},"end":{"line":152,"column":null}},"49":{"start":{"line":163,"column":14},"end":{"line":163,"column":null}},"50":{"start":{"line":164,"column":4},"end":{"line":199,"column":null}},"51":{"start":{"line":165,"column":26},"end":{"line":165,"column":null}},"52":{"start":{"line":166,"column":20},"end":{"line":166,"column":null}},"53":{"start":{"line":167,"column":22},"end":{"line":167,"column":null}},"54":{"start":{"line":168,"column":26},"end":{"line":168,"column":null}},"55":{"start":{"line":170,"column":6},"end":{"line":186,"column":null}},"56":{"start":{"line":188,"column":6},"end":{"line":196,"column":null}},"57":{"start":{"line":189,"column":8},"end":{"line":195,"column":null}},"58":{"start":{"line":198,"column":6},"end":{"line":198,"column":null}},"59":{"start":{"line":204,"column":21},"end":{"line":204,"column":null}},"60":{"start":{"line":204,"column":38},"end":{"line":204,"column":69}},"61":{"start":{"line":205,"column":17},"end":{"line":205,"column":null}},"62":{"start":{"line":206,"column":4},"end":{"line":206,"column":null}},"63":{"start":{"line":206,"column":30},"end":{"line":206,"column":null}},"64":{"start":{"line":207,"column":4},"end":{"line":207,"column":null}},"65":{"start":{"line":207,"column":46},"end":{"line":207,"column":57}},"66":{"start":{"line":211,"column":21},"end":{"line":211,"column":null}},"67":{"start":{"line":212,"column":20},"end":{"line":212,"column":null}},"68":{"start":{"line":213,"column":20},"end":{"line":213,"column":null}},"69":{"start":{"line":213,"column":44},"end":{"line":213,"column":62}},"70":{"start":{"line":214,"column":4},"end":{"line":214,"column":null}},"71":{"start":{"line":218,"column":29},"end":{"line":218,"column":null}},"72":{"start":{"line":218,"column":50},"end":{"line":218,"column":74}},"73":{"start":{"line":219,"column":4},"end":{"line":219,"column":null}},"74":{"start":{"line":223,"column":18},"end":{"line":223,"column":null}},"75":{"start":{"line":224,"column":4},"end":{"line":226,"column":null}},"76":{"start":{"line":225,"column":6},"end":{"line":225,"column":null}},"77":{"start":{"line":227,"column":20},"end":{"line":231,"column":null}},"78":{"start":{"line":228,"column":22},"end":{"line":228,"column":33}},"79":{"start":{"line":229,"column":30},"end":{"line":229,"column":70}},"80":{"start":{"line":232,"column":4},"end":{"line":232,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":20,"column":2},"end":{"line":20,"column":22}},"loc":{"start":{"line":20,"column":48},"end":{"line":20,"column":null}},"line":20},"1":{"name":"(anonymous_1)","decl":{"start":{"line":22,"column":8},"end":{"line":22,"column":12}},"loc":{"start":{"line":22,"column":60},"end":{"line":56,"column":null}},"line":22},"2":{"name":"(anonymous_2)","decl":{"start":{"line":36,"column":11},"end":{"line":36,"column":12}},"loc":{"start":{"line":36,"column":21},"end":{"line":41,"column":8}},"line":36},"3":{"name":"(anonymous_3)","decl":{"start":{"line":42,"column":14},"end":{"line":42,"column":15}},"loc":{"start":{"line":42,"column":23},"end":{"line":42,"column":40}},"line":42},"4":{"name":"(anonymous_4)","decl":{"start":{"line":62,"column":16},"end":{"line":62,"column":null}},"loc":{"start":{"line":65,"column":40},"end":{"line":120,"column":null}},"line":65},"5":{"name":"(anonymous_5)","decl":{"start":{"line":125,"column":16},"end":{"line":125,"column":null}},"loc":{"start":{"line":128,"column":33},"end":{"line":153,"column":null}},"line":128},"6":{"name":"(anonymous_6)","decl":{"start":{"line":158,"column":16},"end":{"line":158,"column":null}},"loc":{"start":{"line":162,"column":19},"end":{"line":200,"column":null}},"line":162},"7":{"name":"(anonymous_7)","decl":{"start":{"line":202,"column":10},"end":{"line":202,"column":24}},"loc":{"start":{"line":202,"column":58},"end":{"line":208,"column":null}},"line":202},"8":{"name":"(anonymous_8)","decl":{"start":{"line":204,"column":31},"end":{"line":204,"column":32}},"loc":{"start":{"line":204,"column":38},"end":{"line":204,"column":69}},"line":204},"9":{"name":"(anonymous_9)","decl":{"start":{"line":207,"column":36},"end":{"line":207,"column":37}},"loc":{"start":{"line":207,"column":46},"end":{"line":207,"column":57}},"line":207},"10":{"name":"(anonymous_10)","decl":{"start":{"line":210,"column":10},"end":{"line":210,"column":25}},"loc":{"start":{"line":210,"column":51},"end":{"line":215,"column":null}},"line":210},"11":{"name":"(anonymous_11)","decl":{"start":{"line":213,"column":34},"end":{"line":213,"column":35}},"loc":{"start":{"line":213,"column":44},"end":{"line":213,"column":62}},"line":213},"12":{"name":"(anonymous_12)","decl":{"start":{"line":217,"column":10},"end":{"line":217,"column":22}},"loc":{"start":{"line":217,"column":56},"end":{"line":220,"column":null}},"line":217},"13":{"name":"(anonymous_13)","decl":{"start":{"line":218,"column":40},"end":{"line":218,"column":41}},"loc":{"start":{"line":218,"column":50},"end":{"line":218,"column":74}},"line":218},"14":{"name":"(anonymous_14)","decl":{"start":{"line":222,"column":10},"end":{"line":222,"column":23}},"loc":{"start":{"line":222,"column":74},"end":{"line":233,"column":null}},"line":222},"15":{"name":"(anonymous_15)","decl":{"start":{"line":228,"column":12},"end":{"line":228,"column":13}},"loc":{"start":{"line":228,"column":22},"end":{"line":228,"column":33}},"line":228},"16":{"name":"(anonymous_16)","decl":{"start":{"line":229,"column":11},"end":{"line":229,"column":12}},"loc":{"start":{"line":229,"column":30},"end":{"line":229,"column":70}},"line":229}},"branchMap":{"0":{"loc":{"start":{"line":35,"column":40},"end":{"line":35,"column":null}},"type":"binary-expr","locations":[{"start":{"line":35,"column":40},"end":{"line":35,"column":59}},{"start":{"line":35,"column":59},"end":{"line":35,"column":null}}],"line":35},"1":{"loc":{"start":{"line":37,"column":19},"end":{"line":37,"column":31}},"type":"binary-expr","locations":[{"start":{"line":37,"column":19},"end":{"line":37,"column":29}},{"start":{"line":37,"column":29},"end":{"line":37,"column":31}}],"line":37},"2":{"loc":{"start":{"line":38,"column":25},"end":{"line":38,"column":43}},"type":"binary-expr","locations":[{"start":{"line":38,"column":25},"end":{"line":38,"column":41}},{"start":{"line":38,"column":41},"end":{"line":38,"column":43}}],"line":38},"3":{"loc":{"start":{"line":39,"column":21},"end":{"line":39,"column":45}},"type":"binary-expr","locations":[{"start":{"line":39,"column":21},"end":{"line":39,"column":33}},{"start":{"line":39,"column":33},"end":{"line":39,"column":43}},{"start":{"line":39,"column":43},"end":{"line":39,"column":45}}],"line":39},"4":{"loc":{"start":{"line":40,"column":21},"end":{"line":40,"column":42}},"type":"binary-expr","locations":[{"start":{"line":40,"column":21},"end":{"line":40,"column":33}},{"start":{"line":40,"column":33},"end":{"line":40,"column":42}}],"line":40},"5":{"loc":{"start":{"line":44,"column":4},"end":{"line":46,"column":null}},"type":"if","locations":[{"start":{"line":44,"column":4},"end":{"line":46,"column":null}},{"start":{},"end":{}}],"line":44},"6":{"loc":{"start":{"line":50,"column":4},"end":{"line":52,"column":null}},"type":"if","locations":[{"start":{"line":50,"column":4},"end":{"line":52,"column":null}},{"start":{},"end":{}}],"line":50},"7":{"loc":{"start":{"line":78,"column":6},"end":{"line":84,"column":null}},"type":"if","locations":[{"start":{"line":78,"column":6},"end":{"line":84,"column":null}},{"start":{},"end":{}}],"line":78},"8":{"loc":{"start":{"line":79,"column":8},"end":{"line":81,"column":null}},"type":"binary-expr","locations":[{"start":{"line":79,"column":8},"end":{"line":79,"column":null}},{"start":{"line":80,"column":8},"end":{"line":80,"column":null}},{"start":{"line":81,"column":8},"end":{"line":81,"column":null}}],"line":79},"9":{"loc":{"start":{"line":89,"column":30},"end":{"line":89,"column":46}},"type":"binary-expr","locations":[{"start":{"line":89,"column":30},"end":{"line":89,"column":44}},{"start":{"line":89,"column":44},"end":{"line":89,"column":46}}],"line":89},"10":{"loc":{"start":{"line":90,"column":27},"end":{"line":90,"column":40}},"type":"binary-expr","locations":[{"start":{"line":90,"column":27},"end":{"line":90,"column":38}},{"start":{"line":90,"column":38},"end":{"line":90,"column":40}}],"line":90},"11":{"loc":{"start":{"line":91,"column":8},"end":{"line":93,"column":null}},"type":"if","locations":[{"start":{"line":91,"column":8},"end":{"line":93,"column":null}},{"start":{},"end":{}}],"line":91},"12":{"loc":{"start":{"line":91,"column":12},"end":{"line":91,"column":32}},"type":"binary-expr","locations":[{"start":{"line":91,"column":12},"end":{"line":91,"column":22}},{"start":{"line":91,"column":22},"end":{"line":91,"column":32}}],"line":91},"13":{"loc":{"start":{"line":96,"column":6},"end":{"line":96,"column":null}},"type":"if","locations":[{"start":{"line":96,"column":6},"end":{"line":96,"column":null}},{"start":{},"end":{}}],"line":96},"14":{"loc":{"start":{"line":102,"column":8},"end":{"line":102,"column":null}},"type":"if","locations":[{"start":{"line":102,"column":8},"end":{"line":102,"column":null}},{"start":{},"end":{}}],"line":102},"15":{"loc":{"start":{"line":103,"column":8},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":8},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":103},"16":{"loc":{"start":{"line":132,"column":6},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":132,"column":6},"end":{"line":132,"column":null}},{"start":{},"end":{}}],"line":132},"17":{"loc":{"start":{"line":206,"column":43},"end":{"line":206,"column":63}},"type":"binary-expr","locations":[{"start":{"line":206,"column":43},"end":{"line":206,"column":58}},{"start":{"line":206,"column":58},"end":{"line":206,"column":63}}],"line":206},"18":{"loc":{"start":{"line":207,"column":11},"end":{"line":207,"column":null}},"type":"binary-expr","locations":[{"start":{"line":207,"column":11},"end":{"line":207,"column":70}},{"start":{"line":207,"column":70},"end":{"line":207,"column":null}}],"line":207},"19":{"loc":{"start":{"line":214,"column":11},"end":{"line":214,"column":null}},"type":"binary-expr","locations":[{"start":{"line":214,"column":11},"end":{"line":214,"column":22}},{"start":{"line":214,"column":22},"end":{"line":214,"column":null}}],"line":214},"20":{"loc":{"start":{"line":219,"column":11},"end":{"line":219,"column":null}},"type":"binary-expr","locations":[{"start":{"line":219,"column":11},"end":{"line":219,"column":35}},{"start":{"line":219,"column":35},"end":{"line":219,"column":51}},{"start":{"line":219,"column":51},"end":{"line":219,"column":null}}],"line":219},"21":{"loc":{"start":{"line":225,"column":30},"end":{"line":225,"column":61}},"type":"binary-expr","locations":[{"start":{"line":225,"column":30},"end":{"line":225,"column":56}},{"start":{"line":225,"column":56},"end":{"line":225,"column":61}}],"line":225}},"s":{"0":57,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0},"f":{"0":57,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0,0],"21":[0,0]},"meta":{"lastBranch":22,"lastFunction":17,"lastStatement":81,"seen":{"f:20:2:20:22":0,"s:20:22:20:48":0,"f:22:8:22:12":1,"s:24:23:33:Infinity":1,"s:35:10:42:Infinity":2,"b:35:40:35:59:35:59:35:Infinity":0,"f:36:11:36:12":2,"s:36:21:41:8":3,"b:37:19:37:29:37:29:37:31":1,"b:38:25:38:41:38:41:38:43":2,"b:39:21:39:33:39:33:39:43:39:43:39:45":3,"b:40:21:40:33:40:33:40:42":4,"f:42:14:42:15":3,"s:42:23:42:40":4,"b:44:4:46:Infinity:undefined:undefined:undefined:undefined":5,"s:44:4:46:Infinity":5,"s:45:6:45:Infinity":6,"s:49:23:49:Infinity":7,"b:50:4:52:Infinity:undefined:undefined:undefined:undefined":6,"s:50:4:52:Infinity":8,"s:51:6:51:Infinity":9,"s:55:4:55:Infinity":10,"f:62:16:62:Infinity":4,"s:66:4:119:Infinity":11,"s:69:23:76:Infinity":12,"b:78:6:84:Infinity:undefined:undefined:undefined:undefined":7,"s:78:6:84:Infinity":13,"b:79:8:79:Infinity:80:8:80:Infinity:81:8:81:Infinity":8,"s:83:8:83:Infinity":14,"s:87:27:87:Infinity":15,"s:88:6:94:Infinity":16,"s:89:23:89:Infinity":17,"b:89:30:89:44:89:44:89:46":9,"s:90:20:90:Infinity":18,"b:90:27:90:38:90:38:90:40":10,"b:91:8:93:Infinity:undefined:undefined:undefined:undefined":11,"s:91:8:93:Infinity":19,"b:91:12:91:22:91:22:91:32":12,"s:92:10:92:Infinity":20,"b:96:6:96:Infinity:undefined:undefined:undefined:undefined":13,"s:96:6:96:Infinity":21,"s:96:35:96:Infinity":22,"s:99:22:99:Infinity":23,"s:100:6:105:Infinity":24,"s:101:20:101:Infinity":25,"b:102:8:102:Infinity:undefined:undefined:undefined:undefined":14,"s:102:8:102:Infinity":26,"s:102:31:102:Infinity":27,"b:103:8:103:Infinity:undefined:undefined:undefined:undefined":15,"s:103:8:103:Infinity":28,"s:103:31:103:Infinity":29,"s:104:8:104:Infinity":30,"s:107:6:107:Infinity":31,"s:108:6:110:Infinity":32,"s:111:6:115:Infinity":33,"s:118:6:118:Infinity":34,"f:125:16:125:Infinity":5,"s:129:20:129:Infinity":35,"s:130:4:134:Infinity":36,"s:131:20:131:Infinity":37,"b:132:6:132:Infinity:undefined:undefined:undefined:undefined":16,"s:132:6:132:Infinity":38,"s:132:31:132:Infinity":39,"s:133:6:133:Infinity":40,"s:137:27:137:Infinity":41,"s:138:14:138:Infinity":42,"s:139:4:142:Infinity":43,"s:140:6:140:Infinity":44,"s:141:6:141:Infinity":45,"s:144:4:144:Infinity":46,"s:145:4:147:Infinity":47,"s:148:4:152:Infinity":48,"f:158:16:158:Infinity":6,"s:163:14:163:Infinity":49,"s:164:4:199:Infinity":50,"s:165:26:165:Infinity":51,"s:166:20:166:Infinity":52,"s:167:22:167:Infinity":53,"s:168:26:168:Infinity":54,"s:170:6:186:Infinity":55,"s:188:6:196:Infinity":56,"s:189:8:195:Infinity":57,"s:198:6:198:Infinity":58,"f:202:10:202:24":7,"s:204:21:204:Infinity":59,"f:204:31:204:32":8,"s:204:38:204:69":60,"s:205:17:205:Infinity":61,"s:206:4:206:Infinity":62,"s:206:30:206:Infinity":63,"b:206:43:206:58:206:58:206:63":17,"s:207:4:207:Infinity":64,"b:207:11:207:70:207:70:207:Infinity":18,"f:207:36:207:37":9,"s:207:46:207:57":65,"f:210:10:210:25":10,"s:211:21:211:Infinity":66,"s:212:20:212:Infinity":67,"s:213:20:213:Infinity":68,"f:213:34:213:35":11,"s:213:44:213:62":69,"s:214:4:214:Infinity":70,"b:214:11:214:22:214:22:214:Infinity":19,"f:217:10:217:22":12,"s:218:29:218:Infinity":71,"f:218:40:218:41":13,"s:218:50:218:74":72,"s:219:4:219:Infinity":73,"b:219:11:219:35:219:35:219:51:219:51:219:Infinity":20,"f:222:10:222:23":14,"s:223:18:223:Infinity":74,"s:224:4:226:Infinity":75,"s:225:6:225:Infinity":76,"b:225:30:225:56:225:56:225:61":21,"s:227:20:231:Infinity":77,"f:228:12:228:13":15,"s:228:22:228:33":78,"f:229:11:229:12":16,"s:229:30:229:70":79,"s:232:4:232:Infinity":80}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/engines/coordination-engine.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/engines/coordination-engine.ts","statementMap":{"0":{"start":{"line":73,"column":22},"end":{"line":73,"column":48}},"1":{"start":{"line":76,"column":26},"end":{"line":88,"column":null}},"2":{"start":{"line":90,"column":21},"end":{"line":90,"column":null}},"3":{"start":{"line":91,"column":4},"end":{"line":102,"column":null}},"4":{"start":{"line":92,"column":6},"end":{"line":101,"column":null}},"5":{"start":{"line":104,"column":16},"end":{"line":104,"column":null}},"6":{"start":{"line":105,"column":20},"end":{"line":105,"column":null}},"7":{"start":{"line":106,"column":27},"end":{"line":109,"column":null}},"8":{"start":{"line":111,"column":4},"end":{"line":139,"column":null}},"9":{"start":{"line":141,"column":4},"end":{"line":152,"column":null}},"10":{"start":{"line":142,"column":6},"end":{"line":151,"column":null}},"11":{"start":{"line":154,"column":4},"end":{"line":158,"column":null}},"12":{"start":{"line":162,"column":4},"end":{"line":173,"column":null}},"13":{"start":{"line":177,"column":25},"end":{"line":185,"column":null}},"14":{"start":{"line":187,"column":27},"end":{"line":195,"column":null}},"15":{"start":{"line":197,"column":25},"end":{"line":199,"column":null}},"16":{"start":{"line":198,"column":20},"end":{"line":198,"column":40}},"17":{"start":{"line":199,"column":42},"end":{"line":199,"column":54}},"18":{"start":{"line":201,"column":4},"end":{"line":212,"column":null}},"19":{"start":{"line":204,"column":56},"end":{"line":210,"column":8}},"20":{"start":{"line":211,"column":48},"end":{"line":211,"column":69}},"21":{"start":{"line":222,"column":8},"end":{"line":271,"column":null}},"22":{"start":{"line":273,"column":4},"end":{"line":301,"column":null}},"23":{"start":{"line":275,"column":22},"end":{"line":275,"column":42}},"24":{"start":{"line":276,"column":44},"end":{"line":276,"column":56}},"25":{"start":{"line":278,"column":22},"end":{"line":278,"column":42}},"26":{"start":{"line":279,"column":44},"end":{"line":279,"column":56}},"27":{"start":{"line":280,"column":52},"end":{"line":294,"column":8}},"28":{"start":{"line":295,"column":53},"end":{"line":299,"column":8}},"29":{"start":{"line":305,"column":16},"end":{"line":305,"column":null}},"30":{"start":{"line":306,"column":24},"end":{"line":316,"column":null}},"31":{"start":{"line":318,"column":4},"end":{"line":318,"column":null}},"32":{"start":{"line":326,"column":4},"end":{"line":340,"column":null}},"33":{"start":{"line":347,"column":19},"end":{"line":356,"column":null}},"34":{"start":{"line":358,"column":4},"end":{"line":360,"column":null}},"35":{"start":{"line":359,"column":6},"end":{"line":359,"column":null}},"36":{"start":{"line":362,"column":16},"end":{"line":362,"column":null}},"37":{"start":{"line":364,"column":6},"end":{"line":367,"column":null}},"38":{"start":{"line":369,"column":4},"end":{"line":372,"column":null}},"39":{"start":{"line":377,"column":7},"end":{"line":379,"column":null}},"40":{"start":{"line":381,"column":4},"end":{"line":383,"column":null}},"41":{"start":{"line":382,"column":6},"end":{"line":382,"column":null}},"42":{"start":{"line":385,"column":4},"end":{"line":403,"column":null}},"43":{"start":{"line":407,"column":4},"end":{"line":407,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":73,"column":2},"end":{"line":73,"column":22}},"loc":{"start":{"line":73,"column":48},"end":{"line":73,"column":null}},"line":73},"1":{"name":"(anonymous_1)","decl":{"start":{"line":75,"column":8},"end":{"line":75,"column":14}},"loc":{"start":{"line":75,"column":55},"end":{"line":159,"column":null}},"line":75},"2":{"name":"(anonymous_2)","decl":{"start":{"line":161,"column":8},"end":{"line":161,"column":16}},"loc":{"start":{"line":161,"column":66},"end":{"line":174,"column":null}},"line":161},"3":{"name":"(anonymous_3)","decl":{"start":{"line":176,"column":8},"end":{"line":176,"column":15}},"loc":{"start":{"line":176,"column":73},"end":{"line":213,"column":null}},"line":176},"4":{"name":"(anonymous_4)","decl":{"start":{"line":198,"column":11},"end":{"line":198,"column":12}},"loc":{"start":{"line":198,"column":20},"end":{"line":198,"column":40}},"line":198},"5":{"name":"(anonymous_5)","decl":{"start":{"line":199,"column":14},"end":{"line":199,"column":15}},"loc":{"start":{"line":199,"column":42},"end":{"line":199,"column":54}},"line":199},"6":{"name":"(anonymous_6)","decl":{"start":{"line":204,"column":46},"end":{"line":204,"column":47}},"loc":{"start":{"line":204,"column":56},"end":{"line":210,"column":8}},"line":204},"7":{"name":"(anonymous_7)","decl":{"start":{"line":211,"column":37},"end":{"line":211,"column":38}},"loc":{"start":{"line":211,"column":48},"end":{"line":211,"column":69}},"line":211},"8":{"name":"(anonymous_8)","decl":{"start":{"line":215,"column":8},"end":{"line":215,"column":17}},"loc":{"start":{"line":215,"column":67},"end":{"line":302,"column":null}},"line":215},"9":{"name":"(anonymous_9)","decl":{"start":{"line":275,"column":13},"end":{"line":275,"column":14}},"loc":{"start":{"line":275,"column":22},"end":{"line":275,"column":42}},"line":275},"10":{"name":"(anonymous_10)","decl":{"start":{"line":276,"column":16},"end":{"line":276,"column":17}},"loc":{"start":{"line":276,"column":44},"end":{"line":276,"column":56}},"line":276},"11":{"name":"(anonymous_11)","decl":{"start":{"line":278,"column":13},"end":{"line":278,"column":14}},"loc":{"start":{"line":278,"column":22},"end":{"line":278,"column":42}},"line":278},"12":{"name":"(anonymous_12)","decl":{"start":{"line":279,"column":16},"end":{"line":279,"column":17}},"loc":{"start":{"line":279,"column":44},"end":{"line":279,"column":56}},"line":279},"13":{"name":"(anonymous_13)","decl":{"start":{"line":280,"column":42},"end":{"line":280,"column":43}},"loc":{"start":{"line":280,"column":52},"end":{"line":294,"column":8}},"line":280},"14":{"name":"(anonymous_14)","decl":{"start":{"line":295,"column":43},"end":{"line":295,"column":44}},"loc":{"start":{"line":295,"column":53},"end":{"line":299,"column":8}},"line":295},"15":{"name":"(anonymous_15)","decl":{"start":{"line":304,"column":8},"end":{"line":304,"column":30}},"loc":{"start":{"line":304,"column":66},"end":{"line":319,"column":null}},"line":304},"16":{"name":"(anonymous_16)","decl":{"start":{"line":321,"column":8},"end":{"line":321,"column":null}},"loc":{"start":{"line":325,"column":19},"end":{"line":341,"column":null}},"line":325},"17":{"name":"(anonymous_17)","decl":{"start":{"line":343,"column":16},"end":{"line":343,"column":null}},"loc":{"start":{"line":346,"column":66},"end":{"line":373,"column":null}},"line":346},"18":{"name":"(anonymous_18)","decl":{"start":{"line":375,"column":10},"end":{"line":375,"column":21}},"loc":{"start":{"line":375,"column":70},"end":{"line":404,"column":null}},"line":375},"19":{"name":"(anonymous_19)","decl":{"start":{"line":406,"column":10},"end":{"line":406,"column":17}},"loc":{"start":{"line":406,"column":41},"end":{"line":408,"column":null}},"line":406}},"branchMap":{"0":{"loc":{"start":{"line":91,"column":4},"end":{"line":102,"column":null}},"type":"if","locations":[{"start":{"line":91,"column":4},"end":{"line":102,"column":null}},{"start":{},"end":{}}],"line":91},"1":{"loc":{"start":{"line":96,"column":26},"end":{"line":96,"column":55}},"type":"binary-expr","locations":[{"start":{"line":96,"column":26},"end":{"line":96,"column":46}},{"start":{"line":96,"column":46},"end":{"line":96,"column":55}}],"line":96},"2":{"loc":{"start":{"line":97,"column":25},"end":{"line":97,"column":46}},"type":"binary-expr","locations":[{"start":{"line":97,"column":25},"end":{"line":97,"column":44}},{"start":{"line":97,"column":44},"end":{"line":97,"column":46}}],"line":97},"3":{"loc":{"start":{"line":98,"column":24},"end":{"line":98,"column":52}},"type":"binary-expr","locations":[{"start":{"line":98,"column":24},"end":{"line":98,"column":42}},{"start":{"line":98,"column":42},"end":{"line":98,"column":52}}],"line":98},"4":{"loc":{"start":{"line":131,"column":16},"end":{"line":131,"column":null}},"type":"binary-expr","locations":[{"start":{"line":131,"column":16},"end":{"line":131,"column":32}},{"start":{"line":131,"column":32},"end":{"line":131,"column":null}}],"line":131},"5":{"loc":{"start":{"line":141,"column":4},"end":{"line":152,"column":null}},"type":"if","locations":[{"start":{"line":141,"column":4},"end":{"line":152,"column":null}},{"start":{},"end":{}}],"line":141},"6":{"loc":{"start":{"line":171,"column":17},"end":{"line":171,"column":null}},"type":"binary-expr","locations":[{"start":{"line":171,"column":17},"end":{"line":171,"column":28}},{"start":{"line":171,"column":28},"end":{"line":171,"column":null}}],"line":171},"7":{"loc":{"start":{"line":206,"column":21},"end":{"line":206,"column":46}},"type":"binary-expr","locations":[{"start":{"line":206,"column":21},"end":{"line":206,"column":33}},{"start":{"line":206,"column":33},"end":{"line":206,"column":46}}],"line":206},"8":{"loc":{"start":{"line":207,"column":24},"end":{"line":207,"column":41}},"type":"binary-expr","locations":[{"start":{"line":207,"column":24},"end":{"line":207,"column":39}},{"start":{"line":207,"column":39},"end":{"line":207,"column":41}}],"line":207},"9":{"loc":{"start":{"line":208,"column":26},"end":{"line":208,"column":53}},"type":"binary-expr","locations":[{"start":{"line":208,"column":26},"end":{"line":208,"column":43}},{"start":{"line":208,"column":43},"end":{"line":208,"column":53}}],"line":208},"10":{"loc":{"start":{"line":209,"column":16},"end":{"line":209,"column":null}},"type":"cond-expr","locations":[{"start":{"line":209,"column":29},"end":{"line":209,"column":50}},{"start":{"line":209,"column":50},"end":{"line":209,"column":null}}],"line":209},"11":{"loc":{"start":{"line":281,"column":25},"end":{"line":281,"column":50}},"type":"binary-expr","locations":[{"start":{"line":281,"column":25},"end":{"line":281,"column":41}},{"start":{"line":281,"column":41},"end":{"line":281,"column":50}}],"line":281},"12":{"loc":{"start":{"line":283,"column":26},"end":{"line":283,"column":44}},"type":"binary-expr","locations":[{"start":{"line":283,"column":26},"end":{"line":283,"column":42}},{"start":{"line":283,"column":42},"end":{"line":283,"column":44}}],"line":283},"13":{"loc":{"start":{"line":284,"column":26},"end":{"line":284,"column":54}},"type":"binary-expr","locations":[{"start":{"line":284,"column":26},"end":{"line":284,"column":45}},{"start":{"line":284,"column":45},"end":{"line":284,"column":54}}],"line":284},"14":{"loc":{"start":{"line":285,"column":25},"end":{"line":285,"column":47}},"type":"binary-expr","locations":[{"start":{"line":285,"column":25},"end":{"line":285,"column":45}},{"start":{"line":285,"column":45},"end":{"line":285,"column":47}}],"line":285},"15":{"loc":{"start":{"line":286,"column":24},"end":{"line":286,"column":53}},"type":"binary-expr","locations":[{"start":{"line":286,"column":24},"end":{"line":286,"column":43}},{"start":{"line":286,"column":43},"end":{"line":286,"column":53}}],"line":286},"16":{"loc":{"start":{"line":289,"column":26},"end":{"line":289,"column":44}},"type":"binary-expr","locations":[{"start":{"line":289,"column":26},"end":{"line":289,"column":42}},{"start":{"line":289,"column":42},"end":{"line":289,"column":44}}],"line":289},"17":{"loc":{"start":{"line":290,"column":26},"end":{"line":290,"column":54}},"type":"binary-expr","locations":[{"start":{"line":290,"column":26},"end":{"line":290,"column":45}},{"start":{"line":290,"column":45},"end":{"line":290,"column":54}}],"line":290},"18":{"loc":{"start":{"line":291,"column":25},"end":{"line":291,"column":47}},"type":"binary-expr","locations":[{"start":{"line":291,"column":25},"end":{"line":291,"column":45}},{"start":{"line":291,"column":45},"end":{"line":291,"column":47}}],"line":291},"19":{"loc":{"start":{"line":292,"column":24},"end":{"line":292,"column":53}},"type":"binary-expr","locations":[{"start":{"line":292,"column":24},"end":{"line":292,"column":43}},{"start":{"line":292,"column":43},"end":{"line":292,"column":53}}],"line":292},"20":{"loc":{"start":{"line":296,"column":24},"end":{"line":296,"column":48}},"type":"binary-expr","locations":[{"start":{"line":296,"column":24},"end":{"line":296,"column":39}},{"start":{"line":296,"column":39},"end":{"line":296,"column":48}}],"line":296},"21":{"loc":{"start":{"line":297,"column":27},"end":{"line":297,"column":46}},"type":"binary-expr","locations":[{"start":{"line":297,"column":27},"end":{"line":297,"column":45}},{"start":{"line":297,"column":45},"end":{"line":297,"column":46}}],"line":297},"22":{"loc":{"start":{"line":298,"column":25},"end":{"line":298,"column":51}},"type":"binary-expr","locations":[{"start":{"line":298,"column":25},"end":{"line":298,"column":41}},{"start":{"line":298,"column":41},"end":{"line":298,"column":51}}],"line":298},"23":{"loc":{"start":{"line":300,"column":26},"end":{"line":300,"column":65}},"type":"binary-expr","locations":[{"start":{"line":300,"column":26},"end":{"line":300,"column":64}},{"start":{"line":300,"column":64},"end":{"line":300,"column":65}}],"line":300},"24":{"loc":{"start":{"line":318,"column":18},"end":{"line":318,"column":57}},"type":"binary-expr","locations":[{"start":{"line":318,"column":18},"end":{"line":318,"column":56}},{"start":{"line":318,"column":56},"end":{"line":318,"column":57}}],"line":318},"25":{"loc":{"start":{"line":358,"column":4},"end":{"line":360,"column":null}},"type":"if","locations":[{"start":{"line":358,"column":4},"end":{"line":360,"column":null}},{"start":{},"end":{}}],"line":358},"26":{"loc":{"start":{"line":362,"column":16},"end":{"line":362,"column":null}},"type":"binary-expr","locations":[{"start":{"line":362,"column":16},"end":{"line":362,"column":34}},{"start":{"line":362,"column":34},"end":{"line":362,"column":null}}],"line":362},"27":{"loc":{"start":{"line":364,"column":6},"end":{"line":367,"column":null}},"type":"binary-expr","locations":[{"start":{"line":364,"column":6},"end":{"line":364,"column":null}},{"start":{"line":365,"column":6},"end":{"line":365,"column":null}},{"start":{"line":366,"column":6},"end":{"line":366,"column":null}},{"start":{"line":367,"column":6},"end":{"line":367,"column":null}}],"line":364},"28":{"loc":{"start":{"line":367,"column":19},"end":{"line":367,"column":46}},"type":"binary-expr","locations":[{"start":{"line":367,"column":19},"end":{"line":367,"column":36}},{"start":{"line":367,"column":36},"end":{"line":367,"column":46}}],"line":367},"29":{"loc":{"start":{"line":377,"column":7},"end":{"line":379,"column":null}},"type":"binary-expr","locations":[{"start":{"line":377,"column":7},"end":{"line":377,"column":null}},{"start":{"line":378,"column":7},"end":{"line":378,"column":null}},{"start":{"line":379,"column":6},"end":{"line":379,"column":null}}],"line":377},"30":{"loc":{"start":{"line":381,"column":4},"end":{"line":383,"column":null}},"type":"if","locations":[{"start":{"line":381,"column":4},"end":{"line":383,"column":null}},{"start":{},"end":{}}],"line":381},"31":{"loc":{"start":{"line":381,"column":8},"end":{"line":381,"column":58}},"type":"binary-expr","locations":[{"start":{"line":381,"column":8},"end":{"line":381,"column":18}},{"start":{"line":381,"column":18},"end":{"line":381,"column":47}},{"start":{"line":381,"column":47},"end":{"line":381,"column":58}}],"line":381},"32":{"loc":{"start":{"line":387,"column":22},"end":{"line":387,"column":48}},"type":"binary-expr","locations":[{"start":{"line":387,"column":22},"end":{"line":387,"column":39}},{"start":{"line":387,"column":39},"end":{"line":387,"column":48}}],"line":387},"33":{"loc":{"start":{"line":388,"column":24},"end":{"line":388,"column":52}},"type":"binary-expr","locations":[{"start":{"line":388,"column":24},"end":{"line":388,"column":43}},{"start":{"line":388,"column":43},"end":{"line":388,"column":52}}],"line":388},"34":{"loc":{"start":{"line":389,"column":14},"end":{"line":389,"column":null}},"type":"cond-expr","locations":[{"start":{"line":389,"column":29},"end":{"line":389,"column":52}},{"start":{"line":389,"column":52},"end":{"line":389,"column":null}}],"line":389},"35":{"loc":{"start":{"line":390,"column":18},"end":{"line":390,"column":null}},"type":"binary-expr","locations":[{"start":{"line":390,"column":18},"end":{"line":390,"column":37}},{"start":{"line":390,"column":37},"end":{"line":390,"column":null}}],"line":390},"36":{"loc":{"start":{"line":391,"column":23},"end":{"line":391,"column":43}},"type":"binary-expr","locations":[{"start":{"line":391,"column":23},"end":{"line":391,"column":41}},{"start":{"line":391,"column":41},"end":{"line":391,"column":43}}],"line":391},"37":{"loc":{"start":{"line":392,"column":21},"end":{"line":392,"column":39}},"type":"binary-expr","locations":[{"start":{"line":392,"column":21},"end":{"line":392,"column":37}},{"start":{"line":392,"column":37},"end":{"line":392,"column":39}}],"line":392},"38":{"loc":{"start":{"line":393,"column":24},"end":{"line":393,"column":53}},"type":"binary-expr","locations":[{"start":{"line":393,"column":24},"end":{"line":393,"column":43}},{"start":{"line":393,"column":43},"end":{"line":393,"column":53}}],"line":393},"39":{"loc":{"start":{"line":394,"column":24},"end":{"line":396,"column":null}},"type":"cond-expr","locations":[{"start":{"line":395,"column":10},"end":{"line":395,"column":null}},{"start":{"line":396,"column":10},"end":{"line":396,"column":null}}],"line":394},"40":{"loc":{"start":{"line":397,"column":15},"end":{"line":397,"column":null}},"type":"cond-expr","locations":[{"start":{"line":397,"column":39},"end":{"line":397,"column":46}},{"start":{"line":397,"column":46},"end":{"line":397,"column":null}}],"line":397},"41":{"loc":{"start":{"line":398,"column":26},"end":{"line":400,"column":null}},"type":"cond-expr","locations":[{"start":{"line":399,"column":11},"end":{"line":399,"column":null}},{"start":{"line":400,"column":10},"end":{"line":400,"column":null}}],"line":398},"42":{"loc":{"start":{"line":401,"column":15},"end":{"line":401,"column":null}},"type":"cond-expr","locations":[{"start":{"line":401,"column":31},"end":{"line":401,"column":55}},{"start":{"line":401,"column":55},"end":{"line":401,"column":null}}],"line":401},"43":{"loc":{"start":{"line":402,"column":24},"end":{"line":402,"column":52}},"type":"binary-expr","locations":[{"start":{"line":402,"column":24},"end":{"line":402,"column":43}},{"start":{"line":402,"column":43},"end":{"line":402,"column":52}}],"line":402}},"s":{"0":57,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0},"f":{"0":57,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0,0,0],"28":[0,0],"29":[0,0,0],"30":[0,0],"31":[0,0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[0,0],"41":[0,0],"42":[0,0],"43":[0,0]},"meta":{"lastBranch":44,"lastFunction":20,"lastStatement":44,"seen":{"f:73:2:73:22":0,"s:73:22:73:48":0,"f:75:8:75:14":1,"s:76:26:88:Infinity":1,"s:90:21:90:Infinity":2,"b:91:4:102:Infinity:undefined:undefined:undefined:undefined":0,"s:91:4:102:Infinity":3,"s:92:6:101:Infinity":4,"b:96:26:96:46:96:46:96:55":1,"b:97:25:97:44:97:44:97:46":2,"b:98:24:98:42:98:42:98:52":3,"s:104:16:104:Infinity":5,"s:105:20:105:Infinity":6,"s:106:27:109:Infinity":7,"s:111:4:139:Infinity":8,"b:131:16:131:32:131:32:131:Infinity":4,"b:141:4:152:Infinity:undefined:undefined:undefined:undefined":5,"s:141:4:152:Infinity":9,"s:142:6:151:Infinity":10,"s:154:4:158:Infinity":11,"f:161:8:161:16":2,"s:162:4:173:Infinity":12,"b:171:17:171:28:171:28:171:Infinity":6,"f:176:8:176:15":3,"s:177:25:185:Infinity":13,"s:187:27:195:Infinity":14,"s:197:25:199:Infinity":15,"f:198:11:198:12":4,"s:198:20:198:40":16,"f:199:14:199:15":5,"s:199:42:199:54":17,"s:201:4:212:Infinity":18,"f:204:46:204:47":6,"s:204:56:210:8":19,"b:206:21:206:33:206:33:206:46":7,"b:207:24:207:39:207:39:207:41":8,"b:208:26:208:43:208:43:208:53":9,"b:209:29:209:50:209:50:209:Infinity":10,"f:211:37:211:38":7,"s:211:48:211:69":20,"f:215:8:215:17":8,"s:222:8:271:Infinity":21,"s:273:4:301:Infinity":22,"f:275:13:275:14":9,"s:275:22:275:42":23,"f:276:16:276:17":10,"s:276:44:276:56":24,"f:278:13:278:14":11,"s:278:22:278:42":25,"f:279:16:279:17":12,"s:279:44:279:56":26,"f:280:42:280:43":13,"s:280:52:294:8":27,"b:281:25:281:41:281:41:281:50":11,"b:283:26:283:42:283:42:283:44":12,"b:284:26:284:45:284:45:284:54":13,"b:285:25:285:45:285:45:285:47":14,"b:286:24:286:43:286:43:286:53":15,"b:289:26:289:42:289:42:289:44":16,"b:290:26:290:45:290:45:290:54":17,"b:291:25:291:45:291:45:291:47":18,"b:292:24:292:43:292:43:292:53":19,"f:295:43:295:44":14,"s:295:53:299:8":28,"b:296:24:296:39:296:39:296:48":20,"b:297:27:297:45:297:45:297:46":21,"b:298:25:298:41:298:41:298:51":22,"b:300:26:300:64:300:64:300:65":23,"f:304:8:304:30":15,"s:305:16:305:Infinity":29,"s:306:24:316:Infinity":30,"s:318:4:318:Infinity":31,"b:318:18:318:56:318:56:318:57":24,"f:321:8:321:Infinity":16,"s:326:4:340:Infinity":32,"f:343:16:343:Infinity":17,"s:347:19:356:Infinity":33,"b:358:4:360:Infinity:undefined:undefined:undefined:undefined":25,"s:358:4:360:Infinity":34,"s:359:6:359:Infinity":35,"s:362:16:362:Infinity":36,"b:362:16:362:34:362:34:362:Infinity":26,"s:364:6:367:Infinity":37,"b:364:6:364:Infinity:365:6:365:Infinity:366:6:366:Infinity:367:6:367:Infinity":27,"b:367:19:367:36:367:36:367:46":28,"s:369:4:372:Infinity":38,"f:375:10:375:21":18,"s:377:7:379:Infinity":39,"b:377:7:377:Infinity:378:7:378:Infinity:379:6:379:Infinity":29,"b:381:4:383:Infinity:undefined:undefined:undefined:undefined":30,"s:381:4:383:Infinity":40,"b:381:8:381:18:381:18:381:47:381:47:381:58":31,"s:382:6:382:Infinity":41,"s:385:4:403:Infinity":42,"b:387:22:387:39:387:39:387:48":32,"b:388:24:388:43:388:43:388:52":33,"b:389:29:389:52:389:52:389:Infinity":34,"b:390:18:390:37:390:37:390:Infinity":35,"b:391:23:391:41:391:41:391:43":36,"b:392:21:392:37:392:37:392:39":37,"b:393:24:393:43:393:43:393:53":38,"b:395:10:395:Infinity:396:10:396:Infinity":39,"b:397:39:397:46:397:46:397:Infinity":40,"b:399:11:399:Infinity:400:10:400:Infinity":41,"b:401:31:401:55:401:55:401:Infinity":42,"b:402:24:402:43:402:43:402:52":43,"f:406:10:406:17":19,"s:407:4:407:Infinity":43}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/engines/docs-engine.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/engines/docs-engine.ts","statementMap":{"0":{"start":{"line":56,"column":31},"end":{"line":56,"column":null}},"1":{"start":{"line":57,"column":32},"end":{"line":57,"column":null}},"2":{"start":{"line":72,"column":4},"end":{"line":72,"column":null}},"3":{"start":{"line":73,"column":4},"end":{"line":73,"column":null}},"4":{"start":{"line":74,"column":4},"end":{"line":74,"column":null}},"5":{"start":{"line":75,"column":4},"end":{"line":80,"column":null}},"6":{"start":{"line":78,"column":24},"end":{"line":78,"column":null}},"7":{"start":{"line":79,"column":8},"end":{"line":79,"column":null}},"8":{"start":{"line":95,"column":15},"end":{"line":95,"column":null}},"9":{"start":{"line":96,"column":24},"end":{"line":96,"column":null}},"10":{"start":{"line":98,"column":27},"end":{"line":98,"column":null}},"11":{"start":{"line":99,"column":17},"end":{"line":99,"column":null}},"12":{"start":{"line":101,"column":10},"end":{"line":101,"column":null}},"13":{"start":{"line":102,"column":36},"end":{"line":107,"column":null}},"14":{"start":{"line":110,"column":27},"end":{"line":112,"column":null}},"15":{"start":{"line":114,"column":4},"end":{"line":159,"column":null}},"16":{"start":{"line":115,"column":6},"end":{"line":158,"column":null}},"17":{"start":{"line":116,"column":20},"end":{"line":116,"column":null}},"18":{"start":{"line":119,"column":8},"end":{"line":122,"column":null}},"19":{"start":{"line":120,"column":10},"end":{"line":120,"column":null}},"20":{"start":{"line":121,"column":10},"end":{"line":121,"column":null}},"21":{"start":{"line":125,"column":22},"end":{"line":125,"column":null}},"22":{"start":{"line":126,"column":24},"end":{"line":126,"column":null}},"23":{"start":{"line":127,"column":27},"end":{"line":127,"column":null}},"24":{"start":{"line":127,"column":47},"end":{"line":127,"column":54}},"25":{"start":{"line":128,"column":8},"end":{"line":134,"column":null}},"26":{"start":{"line":129,"column":10},"end":{"line":132,"column":null}},"27":{"start":{"line":133,"column":10},"end":{"line":133,"column":null}},"28":{"start":{"line":137,"column":8},"end":{"line":150,"column":null}},"29":{"start":{"line":138,"column":10},"end":{"line":149,"column":null}},"30":{"start":{"line":139,"column":12},"end":{"line":139,"column":null}},"31":{"start":{"line":140,"column":12},"end":{"line":142,"column":null}},"32":{"start":{"line":144,"column":12},"end":{"line":147,"column":null}},"33":{"start":{"line":152,"column":8},"end":{"line":152,"column":null}},"34":{"start":{"line":154,"column":8},"end":{"line":157,"column":null}},"35":{"start":{"line":161,"column":4},"end":{"line":161,"column":null}},"36":{"start":{"line":162,"column":4},"end":{"line":162,"column":null}},"37":{"start":{"line":177,"column":18},"end":{"line":177,"column":null}},"38":{"start":{"line":178,"column":18},"end":{"line":181,"column":null}},"39":{"start":{"line":181,"column":21},"end":{"line":181,"column":33}},"40":{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},"41":{"start":{"line":183,"column":28},"end":{"line":183,"column":null}},"42":{"start":{"line":186,"column":26},"end":{"line":186,"column":null}},"43":{"start":{"line":187,"column":4},"end":{"line":187,"column":null}},"44":{"start":{"line":187,"column":32},"end":{"line":187,"column":null}},"45":{"start":{"line":190,"column":4},"end":{"line":190,"column":null}},"46":{"start":{"line":202,"column":18},"end":{"line":202,"column":null}},"47":{"start":{"line":203,"column":16},"end":{"line":218,"column":null}},"48":{"start":{"line":220,"column":4},"end":{"line":220,"column":null}},"49":{"start":{"line":220,"column":39},"end":{"line":220,"column":null}},"50":{"start":{"line":221,"column":4},"end":{"line":223,"column":null}},"51":{"start":{"line":222,"column":6},"end":{"line":222,"column":null}},"52":{"start":{"line":231,"column":16},"end":{"line":235,"column":null}},"53":{"start":{"line":236,"column":16},"end":{"line":236,"column":null}},"54":{"start":{"line":237,"column":4},"end":{"line":249,"column":null}},"55":{"start":{"line":238,"column":6},"end":{"line":248,"column":null}},"56":{"start":{"line":242,"column":8},"end":{"line":247,"column":null}},"57":{"start":{"line":246,"column":10},"end":{"line":246,"column":null}},"58":{"start":{"line":250,"column":4},"end":{"line":250,"column":null}},"59":{"start":{"line":258,"column":4},"end":{"line":258,"column":null}},"60":{"start":{"line":258,"column":24},"end":{"line":258,"column":null}},"61":{"start":{"line":259,"column":4},"end":{"line":283,"column":null}},"62":{"start":{"line":260,"column":18},"end":{"line":276,"column":null}},"63":{"start":{"line":277,"column":6},"end":{"line":277,"column":null}},"64":{"start":{"line":277,"column":46},"end":{"line":277,"column":null}},"65":{"start":{"line":278,"column":6},"end":{"line":280,"column":null}},"66":{"start":{"line":279,"column":8},"end":{"line":279,"column":null}},"67":{"start":{"line":282,"column":6},"end":{"line":282,"column":null}},"68":{"start":{"line":292,"column":25},"end":{"line":295,"column":null}},"69":{"start":{"line":294,"column":8},"end":{"line":294,"column":null}},"70":{"start":{"line":296,"column":44},"end":{"line":296,"column":null}},"71":{"start":{"line":297,"column":4},"end":{"line":299,"column":null}},"72":{"start":{"line":298,"column":6},"end":{"line":298,"column":null}},"73":{"start":{"line":301,"column":16},"end":{"line":316,"column":null}},"74":{"start":{"line":318,"column":4},"end":{"line":318,"column":null}},"75":{"start":{"line":318,"column":39},"end":{"line":318,"column":null}},"76":{"start":{"line":319,"column":4},"end":{"line":321,"column":null}},"77":{"start":{"line":320,"column":6},"end":{"line":320,"column":null}},"78":{"start":{"line":325,"column":4},"end":{"line":333,"column":null}},"79":{"start":{"line":339,"column":4},"end":{"line":339,"column":null}},"80":{"start":{"line":339,"column":22},"end":{"line":339,"column":null}},"81":{"start":{"line":340,"column":34},"end":{"line":354,"column":null}},"82":{"start":{"line":341,"column":21},"end":{"line":341,"column":36}},"83":{"start":{"line":342,"column":19},"end":{"line":354,"column":8}},"84":{"start":{"line":356,"column":4},"end":{"line":356,"column":null}},"85":{"start":{"line":364,"column":12},"end":{"line":364,"column":null}},"86":{"start":{"line":365,"column":4},"end":{"line":368,"column":null}},"87":{"start":{"line":365,"column":17},"end":{"line":365,"column":20}},"88":{"start":{"line":366,"column":6},"end":{"line":366,"column":null}},"89":{"start":{"line":367,"column":6},"end":{"line":367,"column":null}},"90":{"start":{"line":369,"column":4},"end":{"line":369,"column":null}},"91":{"start":{"line":378,"column":16},"end":{"line":378,"column":null}},"92":{"start":{"line":379,"column":19},"end":{"line":379,"column":null}},"93":{"start":{"line":380,"column":4},"end":{"line":387,"column":null}},"94":{"start":{"line":381,"column":14},"end":{"line":381,"column":null}},"95":{"start":{"line":382,"column":6},"end":{"line":384,"column":null}},"96":{"start":{"line":382,"column":19},"end":{"line":382,"column":22}},"97":{"start":{"line":383,"column":8},"end":{"line":383,"column":null}},"98":{"start":{"line":385,"column":18},"end":{"line":385,"column":null}},"99":{"start":{"line":386,"column":6},"end":{"line":386,"column":null}},"100":{"start":{"line":389,"column":17},"end":{"line":389,"column":null}},"101":{"start":{"line":389,"column":48},"end":{"line":389,"column":59}},"102":{"start":{"line":390,"column":4},"end":{"line":390,"column":null}},"103":{"start":{"line":390,"column":38},"end":{"line":390,"column":46}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":71,"column":2},"end":{"line":71,"column":14}},"loc":{"start":{"line":71,"column":70},"end":{"line":81,"column":null}},"line":71},"1":{"name":"(anonymous_1)","decl":{"start":{"line":77,"column":7},"end":{"line":77,"column":8}},"loc":{"start":{"line":77,"column":33},"end":{"line":80,"column":null}},"line":77},"2":{"name":"(anonymous_2)","decl":{"start":{"line":90,"column":8},"end":{"line":90,"column":null}},"loc":{"start":{"line":94,"column":30},"end":{"line":163,"column":null}},"line":94},"3":{"name":"(anonymous_3)","decl":{"start":{"line":127,"column":40},"end":{"line":127,"column":41}},"loc":{"start":{"line":127,"column":47},"end":{"line":127,"column":54}},"line":127},"4":{"name":"(anonymous_4)","decl":{"start":{"line":172,"column":8},"end":{"line":172,"column":null}},"loc":{"start":{"line":176,"column":33},"end":{"line":191,"column":null}},"line":176},"5":{"name":"(anonymous_5)","decl":{"start":{"line":181,"column":14},"end":{"line":181,"column":15}},"loc":{"start":{"line":181,"column":21},"end":{"line":181,"column":33}},"line":181},"6":{"name":"(anonymous_6)","decl":{"start":{"line":197,"column":8},"end":{"line":197,"column":null}},"loc":{"start":{"line":201,"column":33},"end":{"line":224,"column":null}},"line":201},"7":{"name":"(anonymous_7)","decl":{"start":{"line":221,"column":24},"end":{"line":221,"column":25}},"loc":{"start":{"line":222,"column":6},"end":{"line":222,"column":null}},"line":222},"8":{"name":"(anonymous_8)","decl":{"start":{"line":228,"column":16},"end":{"line":228,"column":null}},"loc":{"start":{"line":230,"column":34},"end":{"line":251,"column":null}},"line":230},"9":{"name":"(anonymous_9)","decl":{"start":{"line":253,"column":16},"end":{"line":253,"column":null}},"loc":{"start":{"line":257,"column":40},"end":{"line":284,"column":null}},"line":257},"10":{"name":"(anonymous_10)","decl":{"start":{"line":278,"column":26},"end":{"line":278,"column":27}},"loc":{"start":{"line":279,"column":8},"end":{"line":279,"column":null}},"line":279},"11":{"name":"(anonymous_11)","decl":{"start":{"line":286,"column":16},"end":{"line":286,"column":null}},"loc":{"start":{"line":290,"column":33},"end":{"line":322,"column":null}},"line":290},"12":{"name":"(anonymous_12)","decl":{"start":{"line":293,"column":6},"end":{"line":293,"column":7}},"loc":{"start":{"line":294,"column":8},"end":{"line":294,"column":null}},"line":294},"13":{"name":"(anonymous_13)","decl":{"start":{"line":297,"column":18},"end":{"line":297,"column":19}},"loc":{"start":{"line":297,"column":28},"end":{"line":299,"column":5}},"line":297},"14":{"name":"(anonymous_14)","decl":{"start":{"line":319,"column":24},"end":{"line":319,"column":25}},"loc":{"start":{"line":320,"column":6},"end":{"line":320,"column":null}},"line":320},"15":{"name":"(anonymous_15)","decl":{"start":{"line":324,"column":10},"end":{"line":324,"column":22}},"loc":{"start":{"line":324,"column":70},"end":{"line":334,"column":null}},"line":324},"16":{"name":"(anonymous_16)","decl":{"start":{"line":338,"column":16},"end":{"line":338,"column":25}},"loc":{"start":{"line":338,"column":75},"end":{"line":357,"column":null}},"line":338},"17":{"name":"(anonymous_17)","decl":{"start":{"line":341,"column":14},"end":{"line":341,"column":15}},"loc":{"start":{"line":341,"column":21},"end":{"line":341,"column":36}},"line":341},"18":{"name":"(anonymous_18)","decl":{"start":{"line":342,"column":11},"end":{"line":342,"column":12}},"loc":{"start":{"line":342,"column":19},"end":{"line":354,"column":8}},"line":342},"19":{"name":"(anonymous_19)","decl":{"start":{"line":363,"column":10},"end":{"line":363,"column":21}},"loc":{"start":{"line":363,"column":40},"end":{"line":370,"column":null}},"line":363},"20":{"name":"(anonymous_20)","decl":{"start":{"line":377,"column":10},"end":{"line":377,"column":22}},"loc":{"start":{"line":377,"column":46},"end":{"line":391,"column":null}},"line":377},"21":{"name":"(anonymous_21)","decl":{"start":{"line":389,"column":38},"end":{"line":389,"column":39}},"loc":{"start":{"line":389,"column":48},"end":{"line":389,"column":59}},"line":389},"22":{"name":"(anonymous_22)","decl":{"start":{"line":390,"column":31},"end":{"line":390,"column":32}},"loc":{"start":{"line":390,"column":38},"end":{"line":390,"column":46}},"line":390}},"branchMap":{"0":{"loc":{"start":{"line":71,"column":40},"end":{"line":71,"column":70}},"type":"default-arg","locations":[{"start":{"line":71,"column":66},"end":{"line":71,"column":70}}],"line":71},"1":{"loc":{"start":{"line":74,"column":18},"end":{"line":74,"column":null}},"type":"binary-expr","locations":[{"start":{"line":74,"column":18},"end":{"line":74,"column":33}},{"start":{"line":74,"column":33},"end":{"line":74,"column":null}}],"line":74},"2":{"loc":{"start":{"line":76,"column":6},"end":{"line":80,"column":null}},"type":"binary-expr","locations":[{"start":{"line":76,"column":6},"end":{"line":76,"column":null}},{"start":{"line":77,"column":7},"end":{"line":80,"column":null}}],"line":76},"3":{"loc":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"type":"default-arg","locations":[{"start":{"line":93,"column":29},"end":{"line":93,"column":null}}],"line":93},"4":{"loc":{"start":{"line":96,"column":24},"end":{"line":96,"column":null}},"type":"binary-expr","locations":[{"start":{"line":96,"column":24},"end":{"line":96,"column":44}},{"start":{"line":96,"column":44},"end":{"line":96,"column":null}}],"line":96},"5":{"loc":{"start":{"line":98,"column":27},"end":{"line":98,"column":null}},"type":"binary-expr","locations":[{"start":{"line":98,"column":27},"end":{"line":98,"column":50}},{"start":{"line":98,"column":50},"end":{"line":98,"column":null}}],"line":98},"6":{"loc":{"start":{"line":99,"column":17},"end":{"line":99,"column":null}},"type":"binary-expr","locations":[{"start":{"line":99,"column":17},"end":{"line":99,"column":30}},{"start":{"line":99,"column":30},"end":{"line":99,"column":null}}],"line":99},"7":{"loc":{"start":{"line":110,"column":27},"end":{"line":112,"column":null}},"type":"cond-expr","locations":[{"start":{"line":111,"column":8},"end":{"line":111,"column":null}},{"start":{"line":112,"column":8},"end":{"line":112,"column":null}}],"line":110},"8":{"loc":{"start":{"line":119,"column":8},"end":{"line":122,"column":null}},"type":"if","locations":[{"start":{"line":119,"column":8},"end":{"line":122,"column":null}},{"start":{},"end":{}}],"line":119},"9":{"loc":{"start":{"line":119,"column":12},"end":{"line":119,"column":78}},"type":"binary-expr","locations":[{"start":{"line":119,"column":12},"end":{"line":119,"column":27}},{"start":{"line":119,"column":27},"end":{"line":119,"column":78}}],"line":119},"10":{"loc":{"start":{"line":128,"column":8},"end":{"line":134,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":8},"end":{"line":134,"column":null}},{"start":{},"end":{}}],"line":128},"11":{"loc":{"start":{"line":137,"column":8},"end":{"line":150,"column":null}},"type":"if","locations":[{"start":{"line":137,"column":8},"end":{"line":150,"column":null}},{"start":{},"end":{}}],"line":137},"12":{"loc":{"start":{"line":137,"column":12},"end":{"line":137,"column":58}},"type":"binary-expr","locations":[{"start":{"line":137,"column":12},"end":{"line":137,"column":30}},{"start":{"line":137,"column":30},"end":{"line":137,"column":58}}],"line":137},"13":{"loc":{"start":{"line":156,"column":17},"end":{"line":156,"column":null}},"type":"cond-expr","locations":[{"start":{"line":156,"column":40},"end":{"line":156,"column":54}},{"start":{"line":156,"column":54},"end":{"line":156,"column":null}}],"line":156},"14":{"loc":{"start":{"line":175,"column":4},"end":{"line":175,"column":null}},"type":"default-arg","locations":[{"start":{"line":175,"column":30},"end":{"line":175,"column":null}}],"line":175},"15":{"loc":{"start":{"line":177,"column":27},"end":{"line":177,"column":45}},"type":"binary-expr","locations":[{"start":{"line":177,"column":27},"end":{"line":177,"column":41}},{"start":{"line":177,"column":41},"end":{"line":177,"column":45}}],"line":177},"16":{"loc":{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},"type":"if","locations":[{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},{"start":{},"end":{}}],"line":183},"17":{"loc":{"start":{"line":187,"column":4},"end":{"line":187,"column":null}},"type":"if","locations":[{"start":{"line":187,"column":4},"end":{"line":187,"column":null}},{"start":{},"end":{}}],"line":187},"18":{"loc":{"start":{"line":200,"column":4},"end":{"line":200,"column":null}},"type":"default-arg","locations":[{"start":{"line":200,"column":30},"end":{"line":200,"column":null}}],"line":200},"19":{"loc":{"start":{"line":202,"column":27},"end":{"line":202,"column":45}},"type":"binary-expr","locations":[{"start":{"line":202,"column":27},"end":{"line":202,"column":41}},{"start":{"line":202,"column":41},"end":{"line":202,"column":45}}],"line":202},"20":{"loc":{"start":{"line":220,"column":4},"end":{"line":220,"column":null}},"type":"if","locations":[{"start":{"line":220,"column":4},"end":{"line":220,"column":null}},{"start":{},"end":{}}],"line":220},"21":{"loc":{"start":{"line":220,"column":8},"end":{"line":220,"column":39}},"type":"binary-expr","locations":[{"start":{"line":220,"column":8},"end":{"line":220,"column":21}},{"start":{"line":220,"column":21},"end":{"line":220,"column":39}}],"line":220},"22":{"loc":{"start":{"line":237,"column":4},"end":{"line":249,"column":null}},"type":"if","locations":[{"start":{"line":237,"column":4},"end":{"line":249,"column":null}},{"start":{},"end":{}}],"line":237},"23":{"loc":{"start":{"line":242,"column":8},"end":{"line":247,"column":null}},"type":"if","locations":[{"start":{"line":242,"column":8},"end":{"line":247,"column":null}},{"start":{},"end":{}}],"line":242},"24":{"loc":{"start":{"line":243,"column":10},"end":{"line":244,"column":null}},"type":"binary-expr","locations":[{"start":{"line":243,"column":10},"end":{"line":243,"column":null}},{"start":{"line":244,"column":10},"end":{"line":244,"column":null}}],"line":243},"25":{"loc":{"start":{"line":258,"column":4},"end":{"line":258,"column":null}},"type":"if","locations":[{"start":{"line":258,"column":4},"end":{"line":258,"column":null}},{"start":{},"end":{}}],"line":258},"26":{"loc":{"start":{"line":277,"column":6},"end":{"line":277,"column":null}},"type":"if","locations":[{"start":{"line":277,"column":6},"end":{"line":277,"column":null}},{"start":{},"end":{}}],"line":277},"27":{"loc":{"start":{"line":277,"column":10},"end":{"line":277,"column":46}},"type":"binary-expr","locations":[{"start":{"line":277,"column":10},"end":{"line":277,"column":23}},{"start":{"line":277,"column":23},"end":{"line":277,"column":46}}],"line":277},"28":{"loc":{"start":{"line":318,"column":4},"end":{"line":318,"column":null}},"type":"if","locations":[{"start":{"line":318,"column":4},"end":{"line":318,"column":null}},{"start":{},"end":{}}],"line":318},"29":{"loc":{"start":{"line":318,"column":8},"end":{"line":318,"column":39}},"type":"binary-expr","locations":[{"start":{"line":318,"column":8},"end":{"line":318,"column":21}},{"start":{"line":318,"column":21},"end":{"line":318,"column":39}}],"line":318},"30":{"loc":{"start":{"line":326,"column":24},"end":{"line":326,"column":43}},"type":"binary-expr","locations":[{"start":{"line":326,"column":24},"end":{"line":326,"column":41}},{"start":{"line":326,"column":41},"end":{"line":326,"column":43}}],"line":326},"31":{"loc":{"start":{"line":327,"column":22},"end":{"line":327,"column":39}},"type":"binary-expr","locations":[{"start":{"line":327,"column":22},"end":{"line":327,"column":37}},{"start":{"line":327,"column":37},"end":{"line":327,"column":39}}],"line":327},"32":{"loc":{"start":{"line":328,"column":30},"end":{"line":328,"column":52}},"type":"binary-expr","locations":[{"start":{"line":328,"column":30},"end":{"line":328,"column":50}},{"start":{"line":328,"column":50},"end":{"line":328,"column":52}}],"line":328},"33":{"loc":{"start":{"line":329,"column":19},"end":{"line":329,"column":33}},"type":"binary-expr","locations":[{"start":{"line":329,"column":19},"end":{"line":329,"column":31}},{"start":{"line":329,"column":31},"end":{"line":329,"column":33}}],"line":329},"34":{"loc":{"start":{"line":330,"column":22},"end":{"line":330,"column":39}},"type":"binary-expr","locations":[{"start":{"line":330,"column":22},"end":{"line":330,"column":37}},{"start":{"line":330,"column":37},"end":{"line":330,"column":39}}],"line":330},"35":{"loc":{"start":{"line":331,"column":20},"end":{"line":331,"column":34}},"type":"binary-expr","locations":[{"start":{"line":331,"column":20},"end":{"line":331,"column":33}},{"start":{"line":331,"column":33},"end":{"line":331,"column":34}}],"line":331},"36":{"loc":{"start":{"line":332,"column":24},"end":{"line":332,"column":42}},"type":"binary-expr","locations":[{"start":{"line":332,"column":24},"end":{"line":332,"column":41}},{"start":{"line":332,"column":41},"end":{"line":332,"column":42}}],"line":332},"37":{"loc":{"start":{"line":339,"column":4},"end":{"line":339,"column":null}},"type":"if","locations":[{"start":{"line":339,"column":4},"end":{"line":339,"column":null}},{"start":{},"end":{}}],"line":339},"38":{"loc":{"start":{"line":379,"column":19},"end":{"line":379,"column":null}},"type":"binary-expr","locations":[{"start":{"line":379,"column":19},"end":{"line":379,"column":55}},{"start":{"line":379,"column":55},"end":{"line":379,"column":null}}],"line":379},"39":{"loc":{"start":{"line":389,"column":17},"end":{"line":389,"column":null}},"type":"binary-expr","locations":[{"start":{"line":389,"column":17},"end":{"line":389,"column":66}},{"start":{"line":389,"column":66},"end":{"line":389,"column":null}}],"line":389}},"s":{"0":4,"1":4,"2":75,"3":75,"4":75,"5":75,"6":21,"7":21,"8":9,"9":9,"10":9,"11":9,"12":9,"13":9,"14":9,"15":9,"16":27,"17":27,"18":27,"19":3,"20":3,"21":24,"22":24,"23":24,"24":24,"25":24,"26":3,"27":3,"28":21,"29":3,"30":3,"31":3,"32":0,"33":21,"34":0,"35":9,"36":9,"37":5,"38":5,"39":8,"40":5,"41":1,"42":4,"43":4,"44":2,"45":2,"46":3,"47":3,"48":3,"49":2,"50":1,"51":1,"52":8,"53":8,"54":8,"55":8,"56":3,"57":3,"58":8,"59":4,"60":0,"61":4,"62":4,"63":4,"64":2,"65":2,"66":2,"67":0,"68":2,"69":3,"70":2,"71":2,"72":3,"73":2,"74":2,"75":0,"76":2,"77":21,"78":24,"79":3,"80":0,"81":3,"82":24,"83":24,"84":3,"85":24,"86":24,"87":24,"88":441,"89":441,"90":24,"91":24,"92":24,"93":24,"94":379,"95":379,"96":379,"97":2235,"98":379,"99":379,"100":24,"101":9216,"102":24,"103":9216},"f":{"0":75,"1":21,"2":9,"3":24,"4":5,"5":8,"6":3,"7":1,"8":8,"9":4,"10":2,"11":2,"12":3,"13":3,"14":21,"15":24,"16":3,"17":24,"18":24,"19":24,"20":24,"21":9216,"22":9216},"b":{"0":[75],"1":[75,74],"2":[75,21],"3":[9],"4":[9,7],"5":[9,7],"6":[9,9],"7":[8,1],"8":[3,24],"9":[27,24],"10":[3,21],"11":[3,18],"12":[21,21],"13":[0,0],"14":[5],"15":[5,4],"16":[1,4],"17":[2,2],"18":[3],"19":[3,3],"20":[2,1],"21":[3,3],"22":[8,0],"23":[3,0],"24":[3,3],"25":[0,4],"26":[2,2],"27":[4,2],"28":[0,2],"29":[2,2],"30":[24,0],"31":[24,0],"32":[24,0],"33":[24,0],"34":[24,0],"35":[24,0],"36":[24,0],"37":[0,3],"38":[24,0],"39":[24,0]},"meta":{"lastBranch":40,"lastFunction":23,"lastStatement":104,"seen":{"s:56:31:56:Infinity":0,"s:57:32:57:Infinity":1,"f:71:2:71:14":0,"b:71:66:71:70":0,"s:72:4:72:Infinity":2,"s:73:4:73:Infinity":3,"s:74:4:74:Infinity":4,"b:74:18:74:33:74:33:74:Infinity":1,"s:75:4:80:Infinity":5,"b:76:6:76:Infinity:77:7:80:Infinity":2,"f:77:7:77:8":1,"s:78:24:78:Infinity":6,"s:79:8:79:Infinity":7,"f:90:8:90:Infinity":2,"b:93:29:93:Infinity":3,"s:95:15:95:Infinity":8,"s:96:24:96:Infinity":9,"b:96:24:96:44:96:44:96:Infinity":4,"s:98:27:98:Infinity":10,"b:98:27:98:50:98:50:98:Infinity":5,"s:99:17:99:Infinity":11,"b:99:17:99:30:99:30:99:Infinity":6,"s:101:10:101:Infinity":12,"s:102:36:107:Infinity":13,"s:110:27:112:Infinity":14,"b:111:8:111:Infinity:112:8:112:Infinity":7,"s:114:4:159:Infinity":15,"s:115:6:158:Infinity":16,"s:116:20:116:Infinity":17,"b:119:8:122:Infinity:undefined:undefined:undefined:undefined":8,"s:119:8:122:Infinity":18,"b:119:12:119:27:119:27:119:78":9,"s:120:10:120:Infinity":19,"s:121:10:121:Infinity":20,"s:125:22:125:Infinity":21,"s:126:24:126:Infinity":22,"s:127:27:127:Infinity":23,"f:127:40:127:41":3,"s:127:47:127:54":24,"b:128:8:134:Infinity:undefined:undefined:undefined:undefined":10,"s:128:8:134:Infinity":25,"s:129:10:132:Infinity":26,"s:133:10:133:Infinity":27,"b:137:8:150:Infinity:undefined:undefined:undefined:undefined":11,"s:137:8:150:Infinity":28,"b:137:12:137:30:137:30:137:58":12,"s:138:10:149:Infinity":29,"s:139:12:139:Infinity":30,"s:140:12:142:Infinity":31,"s:144:12:147:Infinity":32,"s:152:8:152:Infinity":33,"s:154:8:157:Infinity":34,"b:156:40:156:54:156:54:156:Infinity":13,"s:161:4:161:Infinity":35,"s:162:4:162:Infinity":36,"f:172:8:172:Infinity":4,"b:175:30:175:Infinity":14,"s:177:18:177:Infinity":37,"b:177:27:177:41:177:41:177:45":15,"s:178:18:181:Infinity":38,"f:181:14:181:15":5,"s:181:21:181:33":39,"b:183:4:183:Infinity:undefined:undefined:undefined:undefined":16,"s:183:4:183:Infinity":40,"s:183:28:183:Infinity":41,"s:186:26:186:Infinity":42,"b:187:4:187:Infinity:undefined:undefined:undefined:undefined":17,"s:187:4:187:Infinity":43,"s:187:32:187:Infinity":44,"s:190:4:190:Infinity":45,"f:197:8:197:Infinity":6,"b:200:30:200:Infinity":18,"s:202:18:202:Infinity":46,"b:202:27:202:41:202:41:202:45":19,"s:203:16:218:Infinity":47,"b:220:4:220:Infinity:undefined:undefined:undefined:undefined":20,"s:220:4:220:Infinity":48,"b:220:8:220:21:220:21:220:39":21,"s:220:39:220:Infinity":49,"s:221:4:223:Infinity":50,"f:221:24:221:25":7,"s:222:6:222:Infinity":51,"f:228:16:228:Infinity":8,"s:231:16:235:Infinity":52,"s:236:16:236:Infinity":53,"b:237:4:249:Infinity:undefined:undefined:undefined:undefined":22,"s:237:4:249:Infinity":54,"s:238:6:248:Infinity":55,"b:242:8:247:Infinity:undefined:undefined:undefined:undefined":23,"s:242:8:247:Infinity":56,"b:243:10:243:Infinity:244:10:244:Infinity":24,"s:246:10:246:Infinity":57,"s:250:4:250:Infinity":58,"f:253:16:253:Infinity":9,"b:258:4:258:Infinity:undefined:undefined:undefined:undefined":25,"s:258:4:258:Infinity":59,"s:258:24:258:Infinity":60,"s:259:4:283:Infinity":61,"s:260:18:276:Infinity":62,"b:277:6:277:Infinity:undefined:undefined:undefined:undefined":26,"s:277:6:277:Infinity":63,"b:277:10:277:23:277:23:277:46":27,"s:277:46:277:Infinity":64,"s:278:6:280:Infinity":65,"f:278:26:278:27":10,"s:279:8:279:Infinity":66,"s:282:6:282:Infinity":67,"f:286:16:286:Infinity":11,"s:292:25:295:Infinity":68,"f:293:6:293:7":12,"s:294:8:294:Infinity":69,"s:296:44:296:Infinity":70,"s:297:4:299:Infinity":71,"f:297:18:297:19":13,"s:298:6:298:Infinity":72,"s:301:16:316:Infinity":73,"b:318:4:318:Infinity:undefined:undefined:undefined:undefined":28,"s:318:4:318:Infinity":74,"b:318:8:318:21:318:21:318:39":29,"s:318:39:318:Infinity":75,"s:319:4:321:Infinity":76,"f:319:24:319:25":14,"s:320:6:320:Infinity":77,"f:324:10:324:22":15,"s:325:4:333:Infinity":78,"b:326:24:326:41:326:41:326:43":30,"b:327:22:327:37:327:37:327:39":31,"b:328:30:328:50:328:50:328:52":32,"b:329:19:329:31:329:31:329:33":33,"b:330:22:330:37:330:37:330:39":34,"b:331:20:331:33:331:33:331:34":35,"b:332:24:332:41:332:41:332:42":36,"f:338:16:338:25":16,"b:339:4:339:Infinity:undefined:undefined:undefined:undefined":37,"s:339:4:339:Infinity":79,"s:339:22:339:Infinity":80,"s:340:34:354:Infinity":81,"f:341:14:341:15":17,"s:341:21:341:36":82,"f:342:11:342:12":18,"s:342:19:354:8":83,"s:356:4:356:Infinity":84,"f:363:10:363:21":19,"s:364:12:364:Infinity":85,"s:365:4:368:Infinity":86,"s:365:17:365:20":87,"s:366:6:366:Infinity":88,"s:367:6:367:Infinity":89,"s:369:4:369:Infinity":90,"f:377:10:377:22":20,"s:378:16:378:Infinity":91,"s:379:19:379:Infinity":92,"b:379:19:379:55:379:55:379:Infinity":38,"s:380:4:387:Infinity":93,"s:381:14:381:Infinity":94,"s:382:6:384:Infinity":95,"s:382:19:382:22":96,"s:383:8:383:Infinity":97,"s:385:18:385:Infinity":98,"s:386:6:386:Infinity":99,"s:389:17:389:Infinity":100,"b:389:17:389:66:389:66:389:Infinity":39,"f:389:38:389:39":21,"s:389:48:389:59":101,"s:390:4:390:Infinity":102,"f:390:31:390:32":22,"s:390:38:390:46":103}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/engines/episode-engine.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/engines/episode-engine.ts","statementMap":{"0":{"start":{"line":50,"column":22},"end":{"line":50,"column":48}},"1":{"start":{"line":53,"column":15},"end":{"line":53,"column":null}},"2":{"start":{"line":54,"column":22},"end":{"line":54,"column":null}},"3":{"start":{"line":55,"column":10},"end":{"line":55,"column":null}},"4":{"start":{"line":57,"column":4},"end":{"line":86,"column":null}},"5":{"start":{"line":88,"column":4},"end":{"line":99,"column":null}},"6":{"start":{"line":89,"column":6},"end":{"line":98,"column":null}},"7":{"start":{"line":101,"column":4},"end":{"line":106,"column":null}},"8":{"start":{"line":107,"column":4},"end":{"line":107,"column":null}},"9":{"start":{"line":111,"column":23},"end":{"line":114,"column":null}},"10":{"start":{"line":115,"column":44},"end":{"line":118,"column":null}},"11":{"start":{"line":120,"column":4},"end":{"line":123,"column":null}},"12":{"start":{"line":121,"column":6},"end":{"line":121,"column":null}},"13":{"start":{"line":122,"column":6},"end":{"line":122,"column":null}},"14":{"start":{"line":124,"column":4},"end":{"line":127,"column":null}},"15":{"start":{"line":125,"column":6},"end":{"line":125,"column":null}},"16":{"start":{"line":126,"column":6},"end":{"line":126,"column":null}},"17":{"start":{"line":128,"column":4},"end":{"line":131,"column":null}},"18":{"start":{"line":129,"column":6},"end":{"line":129,"column":null}},"19":{"start":{"line":130,"column":6},"end":{"line":130,"column":null}},"20":{"start":{"line":132,"column":4},"end":{"line":135,"column":null}},"21":{"start":{"line":133,"column":6},"end":{"line":133,"column":null}},"22":{"start":{"line":134,"column":6},"end":{"line":134,"column":null}},"23":{"start":{"line":137,"column":19},"end":{"line":144,"column":null}},"24":{"start":{"line":146,"column":21},"end":{"line":148,"column":null}},"25":{"start":{"line":147,"column":20},"end":{"line":147,"column":59}},"26":{"start":{"line":148,"column":41},"end":{"line":148,"column":54}},"27":{"start":{"line":150,"column":23},"end":{"line":150,"column":null}},"28":{"start":{"line":151,"column":26},"end":{"line":151,"column":null}},"29":{"start":{"line":152,"column":16},"end":{"line":152,"column":null}},"30":{"start":{"line":154,"column":19},"end":{"line":171,"column":null}},"31":{"start":{"line":155,"column":27},"end":{"line":155,"column":null}},"32":{"start":{"line":156,"column":27},"end":{"line":156,"column":null}},"33":{"start":{"line":158,"column":22},"end":{"line":158,"column":null}},"34":{"start":{"line":159,"column":28},"end":{"line":159,"column":null}},"35":{"start":{"line":161,"column":30},"end":{"line":161,"column":null}},"36":{"start":{"line":163,"column":8},"end":{"line":165,"column":null}},"37":{"start":{"line":168,"column":8},"end":{"line":168,"column":null}},"38":{"start":{"line":170,"column":6},"end":{"line":170,"column":null}},"39":{"start":{"line":173,"column":4},"end":{"line":175,"column":null}},"40":{"start":{"line":174,"column":16},"end":{"line":174,"column":61}},"41":{"start":{"line":179,"column":4},"end":{"line":179,"column":null}},"42":{"start":{"line":188,"column":21},"end":{"line":194,"column":null}},"43":{"start":{"line":196,"column":22},"end":{"line":196,"column":null}},"44":{"start":{"line":197,"column":4},"end":{"line":201,"column":null}},"45":{"start":{"line":198,"column":6},"end":{"line":200,"column":null}},"46":{"start":{"line":199,"column":8},"end":{"line":199,"column":null}},"47":{"start":{"line":203,"column":21},"end":{"line":206,"column":null}},"48":{"start":{"line":204,"column":22},"end":{"line":204,"column":33}},"49":{"start":{"line":206,"column":31},"end":{"line":206,"column":47}},"50":{"start":{"line":208,"column":20},"end":{"line":213,"column":null}},"51":{"start":{"line":211,"column":25},"end":{"line":211,"column":34}},"52":{"start":{"line":215,"column":25},"end":{"line":227,"column":null}},"53":{"start":{"line":222,"column":38},"end":{"line":222,"column":44}},"54":{"start":{"line":229,"column":27},"end":{"line":229,"column":null}},"55":{"start":{"line":230,"column":4},"end":{"line":265,"column":null}},"56":{"start":{"line":231,"column":25},"end":{"line":231,"column":null}},"57":{"start":{"line":232,"column":27},"end":{"line":232,"column":null}},"58":{"start":{"line":234,"column":6},"end":{"line":251,"column":null}},"59":{"start":{"line":253,"column":6},"end":{"line":262,"column":null}},"60":{"start":{"line":264,"column":6},"end":{"line":264,"column":null}},"61":{"start":{"line":267,"column":4},"end":{"line":272,"column":null}},"62":{"start":{"line":281,"column":17},"end":{"line":291,"column":null}},"63":{"start":{"line":293,"column":19},"end":{"line":293,"column":null}},"64":{"start":{"line":294,"column":4},"end":{"line":296,"column":null}},"65":{"start":{"line":295,"column":6},"end":{"line":295,"column":null}},"66":{"start":{"line":298,"column":4},"end":{"line":303,"column":null}},"67":{"start":{"line":310,"column":20},"end":{"line":310,"column":null}},"68":{"start":{"line":312,"column":6},"end":{"line":314,"column":null}},"69":{"start":{"line":315,"column":4},"end":{"line":317,"column":null}},"70":{"start":{"line":316,"column":6},"end":{"line":316,"column":null}},"71":{"start":{"line":319,"column":4},"end":{"line":334,"column":null}},"72":{"start":{"line":327,"column":47},"end":{"line":327,"column":59}},"73":{"start":{"line":338,"column":4},"end":{"line":340,"column":null}},"74":{"start":{"line":339,"column":6},"end":{"line":339,"column":null}},"75":{"start":{"line":342,"column":4},"end":{"line":346,"column":null}},"76":{"start":{"line":343,"column":6},"end":{"line":343,"column":null}},"77":{"start":{"line":345,"column":6},"end":{"line":345,"column":null}},"78":{"start":{"line":350,"column":4},"end":{"line":355,"column":null}},"79":{"start":{"line":354,"column":27},"end":{"line":354,"column":43}},"80":{"start":{"line":359,"column":4},"end":{"line":361,"column":null}},"81":{"start":{"line":360,"column":6},"end":{"line":360,"column":null}},"82":{"start":{"line":362,"column":4},"end":{"line":364,"column":null}},"83":{"start":{"line":363,"column":6},"end":{"line":363,"column":null}},"84":{"start":{"line":366,"column":23},"end":{"line":366,"column":null}},"85":{"start":{"line":367,"column":4},"end":{"line":371,"column":null}},"86":{"start":{"line":368,"column":6},"end":{"line":370,"column":null}},"87":{"start":{"line":369,"column":8},"end":{"line":369,"column":null}},"88":{"start":{"line":372,"column":18},"end":{"line":372,"column":null}},"89":{"start":{"line":373,"column":4},"end":{"line":373,"column":null}},"90":{"start":{"line":377,"column":4},"end":{"line":377,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":50,"column":2},"end":{"line":50,"column":22}},"loc":{"start":{"line":50,"column":48},"end":{"line":50,"column":null}},"line":50},"1":{"name":"(anonymous_1)","decl":{"start":{"line":52,"column":8},"end":{"line":52,"column":12}},"loc":{"start":{"line":52,"column":69},"end":{"line":108,"column":null}},"line":52},"2":{"name":"(anonymous_2)","decl":{"start":{"line":110,"column":8},"end":{"line":110,"column":15}},"loc":{"start":{"line":110,"column":55},"end":{"line":176,"column":null}},"line":110},"3":{"name":"(anonymous_3)","decl":{"start":{"line":147,"column":11},"end":{"line":147,"column":12}},"loc":{"start":{"line":147,"column":20},"end":{"line":147,"column":59}},"line":147},"4":{"name":"(anonymous_4)","decl":{"start":{"line":148,"column":14},"end":{"line":148,"column":15}},"loc":{"start":{"line":148,"column":41},"end":{"line":148,"column":54}},"line":148},"5":{"name":"(anonymous_5)","decl":{"start":{"line":154,"column":32},"end":{"line":154,"column":33}},"loc":{"start":{"line":154,"column":45},"end":{"line":171,"column":5}},"line":154},"6":{"name":"(anonymous_6)","decl":{"start":{"line":174,"column":12},"end":{"line":174,"column":13}},"loc":{"start":{"line":174,"column":16},"end":{"line":174,"column":61}},"line":174},"7":{"name":"(anonymous_7)","decl":{"start":{"line":178,"column":8},"end":{"line":178,"column":22}},"loc":{"start":{"line":178,"column":77},"end":{"line":180,"column":null}},"line":178},"8":{"name":"(anonymous_8)","decl":{"start":{"line":182,"column":8},"end":{"line":182,"column":16}},"loc":{"start":{"line":187,"column":32},"end":{"line":273,"column":null}},"line":187},"9":{"name":"(anonymous_9)","decl":{"start":{"line":204,"column":12},"end":{"line":204,"column":13}},"loc":{"start":{"line":204,"column":22},"end":{"line":204,"column":33}},"line":204},"10":{"name":"(anonymous_10)","decl":{"start":{"line":206,"column":11},"end":{"line":206,"column":12}},"loc":{"start":{"line":206,"column":31},"end":{"line":206,"column":47}},"line":206},"11":{"name":"(anonymous_11)","decl":{"start":{"line":211,"column":15},"end":{"line":211,"column":16}},"loc":{"start":{"line":211,"column":25},"end":{"line":211,"column":34}},"line":211},"12":{"name":"(anonymous_12)","decl":{"start":{"line":222,"column":31},"end":{"line":222,"column":32}},"loc":{"start":{"line":222,"column":38},"end":{"line":222,"column":44}},"line":222},"13":{"name":"(anonymous_13)","decl":{"start":{"line":275,"column":16},"end":{"line":275,"column":null}},"loc":{"start":{"line":280,"column":19},"end":{"line":304,"column":null}},"line":280},"14":{"name":"(anonymous_14)","decl":{"start":{"line":306,"column":10},"end":{"line":306,"column":null}},"loc":{"start":{"line":309,"column":20},"end":{"line":335,"column":null}},"line":309},"15":{"name":"(anonymous_15)","decl":{"start":{"line":327,"column":28},"end":{"line":327,"column":29}},"loc":{"start":{"line":327,"column":47},"end":{"line":327,"column":59}},"line":327},"16":{"name":"(anonymous_16)","decl":{"start":{"line":337,"column":10},"end":{"line":337,"column":23}},"loc":{"start":{"line":337,"column":76},"end":{"line":347,"column":null}},"line":337},"17":{"name":"(anonymous_17)","decl":{"start":{"line":349,"column":10},"end":{"line":349,"column":19}},"loc":{"start":{"line":349,"column":46},"end":{"line":356,"column":null}},"line":349},"18":{"name":"(anonymous_18)","decl":{"start":{"line":354,"column":16},"end":{"line":354,"column":17}},"loc":{"start":{"line":354,"column":27},"end":{"line":354,"column":43}},"line":354},"19":{"name":"(anonymous_19)","decl":{"start":{"line":358,"column":10},"end":{"line":358,"column":18}},"loc":{"start":{"line":358,"column":65},"end":{"line":374,"column":null}},"line":358},"20":{"name":"(anonymous_20)","decl":{"start":{"line":376,"column":10},"end":{"line":376,"column":17}},"loc":{"start":{"line":376,"column":41},"end":{"line":378,"column":null}},"line":376}},"branchMap":{"0":{"loc":{"start":{"line":55,"column":22},"end":{"line":55,"column":44}},"type":"binary-expr","locations":[{"start":{"line":55,"column":22},"end":{"line":55,"column":40}},{"start":{"line":55,"column":40},"end":{"line":55,"column":44}}],"line":55},"1":{"loc":{"start":{"line":76,"column":16},"end":{"line":76,"column":null}},"type":"binary-expr","locations":[{"start":{"line":76,"column":16},"end":{"line":76,"column":32}},{"start":{"line":76,"column":32},"end":{"line":76,"column":null}}],"line":76},"2":{"loc":{"start":{"line":80,"column":17},"end":{"line":80,"column":null}},"type":"binary-expr","locations":[{"start":{"line":80,"column":17},"end":{"line":80,"column":34}},{"start":{"line":80,"column":34},"end":{"line":80,"column":null}}],"line":80},"3":{"loc":{"start":{"line":81,"column":33},"end":{"line":81,"column":53}},"type":"binary-expr","locations":[{"start":{"line":81,"column":33},"end":{"line":81,"column":51}},{"start":{"line":81,"column":51},"end":{"line":81,"column":53}}],"line":81},"4":{"loc":{"start":{"line":117,"column":34},"end":{"line":117,"column":52}},"type":"binary-expr","locations":[{"start":{"line":117,"column":34},"end":{"line":117,"column":49}},{"start":{"line":117,"column":49},"end":{"line":117,"column":52}}],"line":117},"5":{"loc":{"start":{"line":120,"column":4},"end":{"line":123,"column":null}},"type":"if","locations":[{"start":{"line":120,"column":4},"end":{"line":123,"column":null}},{"start":{},"end":{}}],"line":120},"6":{"loc":{"start":{"line":124,"column":4},"end":{"line":127,"column":null}},"type":"if","locations":[{"start":{"line":124,"column":4},"end":{"line":127,"column":null}},{"start":{},"end":{}}],"line":124},"7":{"loc":{"start":{"line":128,"column":4},"end":{"line":131,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":4},"end":{"line":131,"column":null}},{"start":{},"end":{}}],"line":128},"8":{"loc":{"start":{"line":132,"column":4},"end":{"line":135,"column":null}},"type":"if","locations":[{"start":{"line":132,"column":4},"end":{"line":135,"column":null}},{"start":{},"end":{}}],"line":132},"9":{"loc":{"start":{"line":151,"column":34},"end":{"line":151,"column":54}},"type":"binary-expr","locations":[{"start":{"line":151,"column":34},"end":{"line":151,"column":52}},{"start":{"line":151,"column":52},"end":{"line":151,"column":54}}],"line":151},"10":{"loc":{"start":{"line":161,"column":38},"end":{"line":161,"column":60}},"type":"binary-expr","locations":[{"start":{"line":161,"column":38},"end":{"line":161,"column":58}},{"start":{"line":161,"column":58},"end":{"line":161,"column":60}}],"line":161},"11":{"loc":{"start":{"line":163,"column":8},"end":{"line":165,"column":null}},"type":"cond-expr","locations":[{"start":{"line":164,"column":12},"end":{"line":164,"column":null}},{"start":{"line":165,"column":12},"end":{"line":165,"column":null}}],"line":163},"12":{"loc":{"start":{"line":174,"column":23},"end":{"line":174,"column":44}},"type":"binary-expr","locations":[{"start":{"line":174,"column":23},"end":{"line":174,"column":38}},{"start":{"line":174,"column":38},"end":{"line":174,"column":44}}],"line":174},"13":{"loc":{"start":{"line":174,"column":44},"end":{"line":174,"column":61}},"type":"binary-expr","locations":[{"start":{"line":174,"column":44},"end":{"line":174,"column":59}},{"start":{"line":174,"column":59},"end":{"line":174,"column":61}}],"line":174},"14":{"loc":{"start":{"line":189,"column":13},"end":{"line":189,"column":null}},"type":"binary-expr","locations":[{"start":{"line":189,"column":13},"end":{"line":189,"column":28}},{"start":{"line":189,"column":28},"end":{"line":189,"column":44}},{"start":{"line":189,"column":44},"end":{"line":189,"column":null}}],"line":189},"15":{"loc":{"start":{"line":193,"column":13},"end":{"line":193,"column":null}},"type":"binary-expr","locations":[{"start":{"line":193,"column":13},"end":{"line":193,"column":27}},{"start":{"line":193,"column":27},"end":{"line":193,"column":null}}],"line":193},"16":{"loc":{"start":{"line":198,"column":27},"end":{"line":198,"column":51}},"type":"binary-expr","locations":[{"start":{"line":198,"column":27},"end":{"line":198,"column":47}},{"start":{"line":198,"column":47},"end":{"line":198,"column":51}}],"line":198},"17":{"loc":{"start":{"line":199,"column":31},"end":{"line":199,"column":61}},"type":"binary-expr","locations":[{"start":{"line":199,"column":31},"end":{"line":199,"column":56}},{"start":{"line":199,"column":56},"end":{"line":199,"column":61}}],"line":199},"18":{"loc":{"start":{"line":208,"column":20},"end":{"line":213,"column":null}},"type":"cond-expr","locations":[{"start":{"line":209,"column":8},"end":{"line":212,"column":null}},{"start":{"line":213,"column":8},"end":{"line":213,"column":null}}],"line":208},"19":{"loc":{"start":{"line":217,"column":17},"end":{"line":217,"column":null}},"type":"binary-expr","locations":[{"start":{"line":217,"column":17},"end":{"line":217,"column":33}},{"start":{"line":217,"column":33},"end":{"line":217,"column":null}}],"line":217},"20":{"loc":{"start":{"line":294,"column":4},"end":{"line":296,"column":null}},"type":"if","locations":[{"start":{"line":294,"column":4},"end":{"line":296,"column":null}},{"start":{},"end":{}}],"line":294},"21":{"loc":{"start":{"line":310,"column":20},"end":{"line":310,"column":null}},"type":"binary-expr","locations":[{"start":{"line":310,"column":20},"end":{"line":310,"column":29}},{"start":{"line":310,"column":29},"end":{"line":310,"column":44}},{"start":{"line":310,"column":44},"end":{"line":310,"column":null}}],"line":310},"22":{"loc":{"start":{"line":312,"column":6},"end":{"line":314,"column":null}},"type":"cond-expr","locations":[{"start":{"line":313,"column":10},"end":{"line":313,"column":null}},{"start":{"line":314,"column":10},"end":{"line":314,"column":null}}],"line":312},"23":{"loc":{"start":{"line":312,"column":6},"end":{"line":312,"column":null}},"type":"binary-expr","locations":[{"start":{"line":312,"column":6},"end":{"line":312,"column":17}},{"start":{"line":312,"column":17},"end":{"line":312,"column":48}},{"start":{"line":312,"column":48},"end":{"line":312,"column":null}}],"line":312},"24":{"loc":{"start":{"line":315,"column":4},"end":{"line":317,"column":null}},"type":"if","locations":[{"start":{"line":315,"column":4},"end":{"line":317,"column":null}},{"start":{},"end":{}}],"line":315},"25":{"loc":{"start":{"line":315,"column":8},"end":{"line":315,"column":43}},"type":"binary-expr","locations":[{"start":{"line":315,"column":8},"end":{"line":315,"column":17}},{"start":{"line":315,"column":17},"end":{"line":315,"column":43}}],"line":315},"26":{"loc":{"start":{"line":321,"column":22},"end":{"line":321,"column":47}},"type":"binary-expr","locations":[{"start":{"line":321,"column":22},"end":{"line":321,"column":38}},{"start":{"line":321,"column":38},"end":{"line":321,"column":47}}],"line":321},"27":{"loc":{"start":{"line":322,"column":24},"end":{"line":322,"column":51}},"type":"binary-expr","locations":[{"start":{"line":322,"column":24},"end":{"line":322,"column":42}},{"start":{"line":322,"column":42},"end":{"line":322,"column":51}}],"line":322},"28":{"loc":{"start":{"line":323,"column":14},"end":{"line":323,"column":null}},"type":"cond-expr","locations":[{"start":{"line":323,"column":28},"end":{"line":323,"column":50}},{"start":{"line":323,"column":50},"end":{"line":323,"column":null}}],"line":323},"29":{"loc":{"start":{"line":324,"column":13},"end":{"line":324,"column":null}},"type":"binary-expr","locations":[{"start":{"line":324,"column":13},"end":{"line":324,"column":26}},{"start":{"line":324,"column":26},"end":{"line":324,"column":null}}],"line":324},"30":{"loc":{"start":{"line":325,"column":22},"end":{"line":325,"column":40}},"type":"binary-expr","locations":[{"start":{"line":325,"column":22},"end":{"line":325,"column":38}},{"start":{"line":325,"column":38},"end":{"line":325,"column":40}}],"line":325},"31":{"loc":{"start":{"line":326,"column":16},"end":{"line":328,"column":null}},"type":"cond-expr","locations":[{"start":{"line":327,"column":10},"end":{"line":327,"column":null}},{"start":{"line":328,"column":10},"end":{"line":328,"column":null}}],"line":326},"32":{"loc":{"start":{"line":329,"column":15},"end":{"line":329,"column":null}},"type":"binary-expr","locations":[{"start":{"line":329,"column":15},"end":{"line":329,"column":31}},{"start":{"line":329,"column":31},"end":{"line":329,"column":null}}],"line":329},"33":{"loc":{"start":{"line":332,"column":24},"end":{"line":332,"column":52}},"type":"binary-expr","locations":[{"start":{"line":332,"column":24},"end":{"line":332,"column":42}},{"start":{"line":332,"column":42},"end":{"line":332,"column":52}}],"line":332},"34":{"loc":{"start":{"line":338,"column":4},"end":{"line":340,"column":null}},"type":"if","locations":[{"start":{"line":338,"column":4},"end":{"line":340,"column":null}},{"start":{},"end":{}}],"line":338},"35":{"loc":{"start":{"line":338,"column":8},"end":{"line":338,"column":45}},"type":"binary-expr","locations":[{"start":{"line":338,"column":8},"end":{"line":338,"column":18}},{"start":{"line":338,"column":18},"end":{"line":338,"column":45}}],"line":338},"36":{"loc":{"start":{"line":359,"column":4},"end":{"line":361,"column":null}},"type":"if","locations":[{"start":{"line":359,"column":4},"end":{"line":361,"column":null}},{"start":{},"end":{}}],"line":359},"37":{"loc":{"start":{"line":359,"column":8},"end":{"line":359,"column":45}},"type":"binary-expr","locations":[{"start":{"line":359,"column":8},"end":{"line":359,"column":27}},{"start":{"line":359,"column":27},"end":{"line":359,"column":45}}],"line":359},"38":{"loc":{"start":{"line":362,"column":4},"end":{"line":364,"column":null}},"type":"if","locations":[{"start":{"line":362,"column":4},"end":{"line":364,"column":null}},{"start":{},"end":{}}],"line":362},"39":{"loc":{"start":{"line":362,"column":8},"end":{"line":362,"column":45}},"type":"binary-expr","locations":[{"start":{"line":362,"column":8},"end":{"line":362,"column":27}},{"start":{"line":362,"column":27},"end":{"line":362,"column":45}}],"line":362},"40":{"loc":{"start":{"line":368,"column":6},"end":{"line":370,"column":null}},"type":"if","locations":[{"start":{"line":368,"column":6},"end":{"line":370,"column":null}},{"start":{},"end":{}}],"line":368},"41":{"loc":{"start":{"line":373,"column":11},"end":{"line":373,"column":null}},"type":"cond-expr","locations":[{"start":{"line":373,"column":23},"end":{"line":373,"column":46}},{"start":{"line":373,"column":46},"end":{"line":373,"column":null}}],"line":373}},"s":{"0":57,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0},"f":{"0":57,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0,0],"22":[0,0],"23":[0,0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[0,0],"41":[0,0]},"meta":{"lastBranch":42,"lastFunction":21,"lastStatement":91,"seen":{"f:50:2:50:22":0,"s:50:22:50:48":0,"f:52:8:52:12":1,"s:53:15:53:Infinity":1,"s:54:22:54:Infinity":2,"s:55:10:55:Infinity":3,"b:55:22:55:40:55:40:55:44":0,"s:57:4:86:Infinity":4,"b:76:16:76:32:76:32:76:Infinity":1,"b:80:17:80:34:80:34:80:Infinity":2,"b:81:33:81:51:81:51:81:53":3,"s:88:4:99:Infinity":5,"s:89:6:98:Infinity":6,"s:101:4:106:Infinity":7,"s:107:4:107:Infinity":8,"f:110:8:110:15":2,"s:111:23:114:Infinity":9,"s:115:44:118:Infinity":10,"b:117:34:117:49:117:49:117:52":4,"b:120:4:123:Infinity:undefined:undefined:undefined:undefined":5,"s:120:4:123:Infinity":11,"s:121:6:121:Infinity":12,"s:122:6:122:Infinity":13,"b:124:4:127:Infinity:undefined:undefined:undefined:undefined":6,"s:124:4:127:Infinity":14,"s:125:6:125:Infinity":15,"s:126:6:126:Infinity":16,"b:128:4:131:Infinity:undefined:undefined:undefined:undefined":7,"s:128:4:131:Infinity":17,"s:129:6:129:Infinity":18,"s:130:6:130:Infinity":19,"b:132:4:135:Infinity:undefined:undefined:undefined:undefined":8,"s:132:4:135:Infinity":20,"s:133:6:133:Infinity":21,"s:134:6:134:Infinity":22,"s:137:19:144:Infinity":23,"s:146:21:148:Infinity":24,"f:147:11:147:12":3,"s:147:20:147:59":25,"f:148:14:148:15":4,"s:148:41:148:54":26,"s:150:23:150:Infinity":27,"s:151:26:151:Infinity":28,"b:151:34:151:52:151:52:151:54":9,"s:152:16:152:Infinity":29,"s:154:19:171:Infinity":30,"f:154:32:154:33":5,"s:155:27:155:Infinity":31,"s:156:27:156:Infinity":32,"s:158:22:158:Infinity":33,"s:159:28:159:Infinity":34,"s:161:30:161:Infinity":35,"b:161:38:161:58:161:58:161:60":10,"s:163:8:165:Infinity":36,"b:164:12:164:Infinity:165:12:165:Infinity":11,"s:168:8:168:Infinity":37,"s:170:6:170:Infinity":38,"s:173:4:175:Infinity":39,"f:174:12:174:13":6,"s:174:16:174:61":40,"b:174:23:174:38:174:38:174:44":12,"b:174:44:174:59:174:59:174:61":13,"f:178:8:178:22":7,"s:179:4:179:Infinity":41,"f:182:8:182:16":8,"s:188:21:194:Infinity":42,"b:189:13:189:28:189:28:189:44:189:44:189:Infinity":14,"b:193:13:193:27:193:27:193:Infinity":15,"s:196:22:196:Infinity":43,"s:197:4:201:Infinity":44,"s:198:6:200:Infinity":45,"b:198:27:198:47:198:47:198:51":16,"s:199:8:199:Infinity":46,"b:199:31:199:56:199:56:199:61":17,"s:203:21:206:Infinity":47,"f:204:12:204:13":9,"s:204:22:204:33":48,"f:206:11:206:12":10,"s:206:31:206:47":49,"s:208:20:213:Infinity":50,"b:209:8:212:Infinity:213:8:213:Infinity":18,"f:211:15:211:16":11,"s:211:25:211:34":51,"s:215:25:227:Infinity":52,"b:217:17:217:33:217:33:217:Infinity":19,"f:222:31:222:32":12,"s:222:38:222:44":53,"s:229:27:229:Infinity":54,"s:230:4:265:Infinity":55,"s:231:25:231:Infinity":56,"s:232:27:232:Infinity":57,"s:234:6:251:Infinity":58,"s:253:6:262:Infinity":59,"s:264:6:264:Infinity":60,"s:267:4:272:Infinity":61,"f:275:16:275:Infinity":13,"s:281:17:291:Infinity":62,"s:293:19:293:Infinity":63,"b:294:4:296:Infinity:undefined:undefined:undefined:undefined":20,"s:294:4:296:Infinity":64,"s:295:6:295:Infinity":65,"s:298:4:303:Infinity":66,"f:306:10:306:Infinity":14,"s:310:20:310:Infinity":67,"b:310:20:310:29:310:29:310:44:310:44:310:Infinity":21,"s:312:6:314:Infinity":68,"b:313:10:313:Infinity:314:10:314:Infinity":22,"b:312:6:312:17:312:17:312:48:312:48:312:Infinity":23,"b:315:4:317:Infinity:undefined:undefined:undefined:undefined":24,"s:315:4:317:Infinity":69,"b:315:8:315:17:315:17:315:43":25,"s:316:6:316:Infinity":70,"s:319:4:334:Infinity":71,"b:321:22:321:38:321:38:321:47":26,"b:322:24:322:42:322:42:322:51":27,"b:323:28:323:50:323:50:323:Infinity":28,"b:324:13:324:26:324:26:324:Infinity":29,"b:325:22:325:38:325:38:325:40":30,"b:327:10:327:Infinity:328:10:328:Infinity":31,"f:327:28:327:29":15,"s:327:47:327:59":72,"b:329:15:329:31:329:31:329:Infinity":32,"b:332:24:332:42:332:42:332:52":33,"f:337:10:337:23":16,"b:338:4:340:Infinity:undefined:undefined:undefined:undefined":34,"s:338:4:340:Infinity":73,"b:338:8:338:18:338:18:338:45":35,"s:339:6:339:Infinity":74,"s:342:4:346:Infinity":75,"s:343:6:343:Infinity":76,"s:345:6:345:Infinity":77,"f:349:10:349:19":17,"s:350:4:355:Infinity":78,"f:354:16:354:17":18,"s:354:27:354:43":79,"f:358:10:358:18":19,"b:359:4:361:Infinity:undefined:undefined:undefined:undefined":36,"s:359:4:361:Infinity":80,"b:359:8:359:27:359:27:359:45":37,"s:360:6:360:Infinity":81,"b:362:4:364:Infinity:undefined:undefined:undefined:undefined":38,"s:362:4:364:Infinity":82,"b:362:8:362:27:362:27:362:45":39,"s:363:6:363:Infinity":83,"s:366:23:366:Infinity":84,"s:367:4:371:Infinity":85,"b:368:6:370:Infinity:undefined:undefined:undefined:undefined":40,"s:368:6:370:Infinity":86,"s:369:8:369:Infinity":87,"s:372:18:372:Infinity":88,"s:373:4:373:Infinity":89,"b:373:23:373:46:373:46:373:Infinity":41,"f:376:10:376:17":20,"s:377:4:377:Infinity":90}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/engines/progress-engine.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/engines/progress-engine.ts","statementMap":{"0":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"1":{"start":{"line":68,"column":4},"end":{"line":68,"column":null}},"2":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"3":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"4":{"start":{"line":71,"column":4},"end":{"line":71,"column":null}},"5":{"start":{"line":79,"column":25},"end":{"line":79,"column":null}},"6":{"start":{"line":80,"column":4},"end":{"line":92,"column":null}},"7":{"start":{"line":81,"column":6},"end":{"line":91,"column":null}},"8":{"start":{"line":95,"column":22},"end":{"line":95,"column":null}},"9":{"start":{"line":96,"column":4},"end":{"line":109,"column":null}},"10":{"start":{"line":97,"column":6},"end":{"line":108,"column":null}},"11":{"start":{"line":112,"column":4},"end":{"line":119,"column":null}},"12":{"start":{"line":113,"column":6},"end":{"line":118,"column":null}},"13":{"start":{"line":114,"column":24},"end":{"line":114,"column":null}},"14":{"start":{"line":115,"column":8},"end":{"line":117,"column":null}},"15":{"start":{"line":116,"column":11},"end":{"line":116,"column":null}},"16":{"start":{"line":133,"column":38},"end":{"line":133,"column":null}},"17":{"start":{"line":135,"column":4},"end":{"line":147,"column":null}},"18":{"start":{"line":136,"column":6},"end":{"line":139,"column":null}},"19":{"start":{"line":137,"column":8},"end":{"line":137,"column":null}},"20":{"start":{"line":137,"column":64},"end":{"line":137,"column":null}},"21":{"start":{"line":138,"column":8},"end":{"line":138,"column":null}},"22":{"start":{"line":140,"column":4},"end":{"line":147,"column":null}},"23":{"start":{"line":141,"column":6},"end":{"line":146,"column":null}},"24":{"start":{"line":142,"column":8},"end":{"line":142,"column":null}},"25":{"start":{"line":142,"column":61},"end":{"line":142,"column":null}},"26":{"start":{"line":143,"column":8},"end":{"line":143,"column":null}},"27":{"start":{"line":143,"column":67},"end":{"line":143,"column":null}},"28":{"start":{"line":144,"column":8},"end":{"line":144,"column":null}},"29":{"start":{"line":144,"column":70},"end":{"line":144,"column":null}},"30":{"start":{"line":145,"column":8},"end":{"line":145,"column":null}},"31":{"start":{"line":150,"column":22},"end":{"line":150,"column":null}},"32":{"start":{"line":150,"column":42},"end":{"line":150,"column":66}},"33":{"start":{"line":151,"column":23},"end":{"line":151,"column":null}},"34":{"start":{"line":151,"column":43},"end":{"line":151,"column":69}},"35":{"start":{"line":152,"column":20},"end":{"line":152,"column":null}},"36":{"start":{"line":152,"column":40},"end":{"line":152,"column":62}},"37":{"start":{"line":154,"column":4},"end":{"line":160,"column":null}},"38":{"start":{"line":167,"column":17},"end":{"line":167,"column":null}},"39":{"start":{"line":168,"column":4},"end":{"line":168,"column":null}},"40":{"start":{"line":168,"column":15},"end":{"line":168,"column":null}},"41":{"start":{"line":170,"column":4},"end":{"line":170,"column":null}},"42":{"start":{"line":172,"column":4},"end":{"line":176,"column":null}},"43":{"start":{"line":173,"column":6},"end":{"line":173,"column":null}},"44":{"start":{"line":174,"column":4},"end":{"line":176,"column":null}},"45":{"start":{"line":175,"column":6},"end":{"line":175,"column":null}},"46":{"start":{"line":178,"column":4},"end":{"line":178,"column":null}},"47":{"start":{"line":185,"column":20},"end":{"line":185,"column":null}},"48":{"start":{"line":186,"column":4},"end":{"line":186,"column":null}},"49":{"start":{"line":186,"column":18},"end":{"line":186,"column":null}},"50":{"start":{"line":189,"column":18},"end":{"line":191,"column":null}},"51":{"start":{"line":190,"column":13},"end":{"line":190,"column":null}},"52":{"start":{"line":194,"column":40},"end":{"line":194,"column":null}},"53":{"start":{"line":195,"column":21},"end":{"line":197,"column":null}},"54":{"start":{"line":197,"column":21},"end":{"line":197,"column":44}},"55":{"start":{"line":198,"column":4},"end":{"line":203,"column":null}},"56":{"start":{"line":199,"column":19},"end":{"line":199,"column":null}},"57":{"start":{"line":200,"column":6},"end":{"line":202,"column":null}},"58":{"start":{"line":201,"column":8},"end":{"line":201,"column":null}},"59":{"start":{"line":206,"column":24},"end":{"line":206,"column":null}},"60":{"start":{"line":207,"column":21},"end":{"line":207,"column":null}},"61":{"start":{"line":209,"column":4},"end":{"line":223,"column":null}},"62":{"start":{"line":210,"column":24},"end":{"line":210,"column":null}},"63":{"start":{"line":211,"column":23},"end":{"line":211,"column":null}},"64":{"start":{"line":211,"column":45},"end":{"line":211,"column":75}},"65":{"start":{"line":212,"column":6},"end":{"line":212,"column":null}},"66":{"start":{"line":212,"column":21},"end":{"line":212,"column":null}},"67":{"start":{"line":214,"column":23},"end":{"line":216,"column":null}},"68":{"start":{"line":216,"column":23},"end":{"line":216,"column":44}},"69":{"start":{"line":217,"column":6},"end":{"line":222,"column":null}},"70":{"start":{"line":218,"column":21},"end":{"line":218,"column":null}},"71":{"start":{"line":219,"column":8},"end":{"line":219,"column":null}},"72":{"start":{"line":219,"column":19},"end":{"line":219,"column":null}},"73":{"start":{"line":220,"column":8},"end":{"line":220,"column":null}},"74":{"start":{"line":220,"column":38},"end":{"line":220,"column":null}},"75":{"start":{"line":221,"column":8},"end":{"line":221,"column":null}},"76":{"start":{"line":221,"column":35},"end":{"line":221,"column":null}},"77":{"start":{"line":226,"column":23},"end":{"line":236,"column":null}},"78":{"start":{"line":227,"column":24},"end":{"line":229,"column":null}},"79":{"start":{"line":229,"column":23},"end":{"line":229,"column":41}},"80":{"start":{"line":230,"column":6},"end":{"line":235,"column":null}},"81":{"start":{"line":231,"column":23},"end":{"line":231,"column":null}},"82":{"start":{"line":232,"column":8},"end":{"line":233,"column":null}},"83":{"start":{"line":238,"column":22},"end":{"line":248,"column":null}},"84":{"start":{"line":239,"column":23},"end":{"line":241,"column":null}},"85":{"start":{"line":241,"column":23},"end":{"line":241,"column":41}},"86":{"start":{"line":242,"column":6},"end":{"line":247,"column":null}},"87":{"start":{"line":243,"column":23},"end":{"line":243,"column":null}},"88":{"start":{"line":244,"column":8},"end":{"line":245,"column":null}},"89":{"start":{"line":251,"column":27},"end":{"line":251,"column":null}},"90":{"start":{"line":251,"column":47},"end":{"line":251,"column":69}},"91":{"start":{"line":254,"column":27},"end":{"line":254,"column":null}},"92":{"start":{"line":254,"column":47},"end":{"line":254,"column":71}},"93":{"start":{"line":256,"column":6},"end":{"line":256,"column":null}},"94":{"start":{"line":258,"column":4},"end":{"line":272,"column":null}},"95":{"start":{"line":279,"column":20},"end":{"line":281,"column":null}},"96":{"start":{"line":280,"column":13},"end":{"line":280,"column":null}},"97":{"start":{"line":283,"column":4},"end":{"line":285,"column":null}},"98":{"start":{"line":284,"column":6},"end":{"line":284,"column":null}},"99":{"start":{"line":284,"column":35},"end":{"line":284,"column":72}},"100":{"start":{"line":287,"column":4},"end":{"line":292,"column":null}},"101":{"start":{"line":288,"column":6},"end":{"line":291,"column":null}},"102":{"start":{"line":289,"column":24},"end":{"line":289,"column":null}},"103":{"start":{"line":290,"column":8},"end":{"line":290,"column":null}},"104":{"start":{"line":294,"column":4},"end":{"line":294,"column":null}},"105":{"start":{"line":302,"column":4},"end":{"line":306,"column":null}},"106":{"start":{"line":303,"column":6},"end":{"line":305,"column":null}},"107":{"start":{"line":308,"column":4},"end":{"line":308,"column":null}},"108":{"start":{"line":310,"column":4},"end":{"line":343,"column":null}},"109":{"start":{"line":311,"column":21},"end":{"line":325,"column":null}},"110":{"start":{"line":327,"column":6},"end":{"line":331,"column":null}},"111":{"start":{"line":328,"column":8},"end":{"line":330,"column":null}},"112":{"start":{"line":334,"column":6},"end":{"line":334,"column":null}},"113":{"start":{"line":335,"column":6},"end":{"line":337,"column":null}},"114":{"start":{"line":338,"column":6},"end":{"line":338,"column":null}},"115":{"start":{"line":340,"column":6},"end":{"line":342,"column":null}},"116":{"start":{"line":351,"column":4},"end":{"line":355,"column":null}},"117":{"start":{"line":352,"column":6},"end":{"line":354,"column":null}},"118":{"start":{"line":357,"column":4},"end":{"line":391,"column":null}},"119":{"start":{"line":358,"column":21},"end":{"line":375,"column":null}},"120":{"start":{"line":377,"column":6},"end":{"line":381,"column":null}},"121":{"start":{"line":378,"column":8},"end":{"line":380,"column":null}},"122":{"start":{"line":384,"column":6},"end":{"line":384,"column":null}},"123":{"start":{"line":385,"column":6},"end":{"line":385,"column":null}},"124":{"start":{"line":386,"column":6},"end":{"line":386,"column":null}},"125":{"start":{"line":388,"column":6},"end":{"line":390,"column":null}},"126":{"start":{"line":401,"column":4},"end":{"line":403,"column":null}},"127":{"start":{"line":402,"column":6},"end":{"line":402,"column":null}},"128":{"start":{"line":405,"column":4},"end":{"line":432,"column":null}},"129":{"start":{"line":406,"column":41},"end":{"line":422,"column":null}},"130":{"start":{"line":424,"column":21},"end":{"line":427,"column":null}},"131":{"start":{"line":428,"column":6},"end":{"line":428,"column":null}},"132":{"start":{"line":430,"column":6},"end":{"line":430,"column":null}},"133":{"start":{"line":431,"column":6},"end":{"line":431,"column":null}},"134":{"start":{"line":442,"column":4},"end":{"line":444,"column":null}},"135":{"start":{"line":443,"column":6},"end":{"line":443,"column":null}},"136":{"start":{"line":446,"column":4},"end":{"line":476,"column":null}},"137":{"start":{"line":447,"column":41},"end":{"line":463,"column":null}},"138":{"start":{"line":465,"column":21},"end":{"line":468,"column":null}},"139":{"start":{"line":469,"column":6},"end":{"line":469,"column":null}},"140":{"start":{"line":471,"column":6},"end":{"line":474,"column":null}},"141":{"start":{"line":475,"column":6},"end":{"line":475,"column":null}},"142":{"start":{"line":484,"column":4},"end":{"line":484,"column":null}},"143":{"start":{"line":486,"column":4},"end":{"line":486,"column":null}},"144":{"start":{"line":487,"column":4},"end":{"line":487,"column":null}},"145":{"start":{"line":488,"column":4},"end":{"line":488,"column":null}},"146":{"start":{"line":489,"column":4},"end":{"line":489,"column":null}},"147":{"start":{"line":492,"column":4},"end":{"line":504,"column":null}},"148":{"start":{"line":493,"column":6},"end":{"line":497,"column":null}},"149":{"start":{"line":494,"column":8},"end":{"line":496,"column":null}},"150":{"start":{"line":495,"column":10},"end":{"line":495,"column":null}},"151":{"start":{"line":499,"column":6},"end":{"line":503,"column":null}},"152":{"start":{"line":500,"column":8},"end":{"line":502,"column":null}},"153":{"start":{"line":501,"column":10},"end":{"line":501,"column":null}},"154":{"start":{"line":506,"column":25},"end":{"line":506,"column":null}},"155":{"start":{"line":507,"column":22},"end":{"line":507,"column":null}},"156":{"start":{"line":508,"column":4},"end":{"line":508,"column":null}},"157":{"start":{"line":515,"column":4},"end":{"line":535,"column":null}},"158":{"start":{"line":522,"column":19},"end":{"line":522,"column":null}},"159":{"start":{"line":526,"column":19},"end":{"line":526,"column":null}},"160":{"start":{"line":529,"column":19},"end":{"line":529,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":66,"column":2},"end":{"line":66,"column":14}},"loc":{"start":{"line":66,"column":67},"end":{"line":72,"column":null}},"line":66},"1":{"name":"(anonymous_1)","decl":{"start":{"line":77,"column":10},"end":{"line":77,"column":32}},"loc":{"start":{"line":77,"column":32},"end":{"line":120,"column":null}},"line":77},"2":{"name":"(anonymous_2)","decl":{"start":{"line":125,"column":2},"end":{"line":125,"column":null}},"loc":{"start":{"line":132,"column":25},"end":{"line":161,"column":null}},"line":132},"3":{"name":"(anonymous_3)","decl":{"start":{"line":150,"column":35},"end":{"line":150,"column":36}},"loc":{"start":{"line":150,"column":42},"end":{"line":150,"column":66}},"line":150},"4":{"name":"(anonymous_4)","decl":{"start":{"line":151,"column":36},"end":{"line":151,"column":37}},"loc":{"start":{"line":151,"column":43},"end":{"line":151,"column":69}},"line":151},"5":{"name":"(anonymous_5)","decl":{"start":{"line":152,"column":33},"end":{"line":152,"column":34}},"loc":{"start":{"line":152,"column":40},"end":{"line":152,"column":62}},"line":152},"6":{"name":"(anonymous_6)","decl":{"start":{"line":166,"column":2},"end":{"line":166,"column":13}},"loc":{"start":{"line":166,"column":66},"end":{"line":179,"column":null}},"line":166},"7":{"name":"(anonymous_7)","decl":{"start":{"line":184,"column":2},"end":{"line":184,"column":19}},"loc":{"start":{"line":184,"column":60},"end":{"line":273,"column":null}},"line":184},"8":{"name":"(anonymous_8)","decl":{"start":{"line":190,"column":6},"end":{"line":190,"column":7}},"loc":{"start":{"line":190,"column":13},"end":{"line":190,"column":null}},"line":190},"9":{"name":"(anonymous_9)","decl":{"start":{"line":197,"column":14},"end":{"line":197,"column":15}},"loc":{"start":{"line":197,"column":21},"end":{"line":197,"column":44}},"line":197},"10":{"name":"(anonymous_10)","decl":{"start":{"line":211,"column":38},"end":{"line":211,"column":39}},"loc":{"start":{"line":211,"column":45},"end":{"line":211,"column":75}},"line":211},"11":{"name":"(anonymous_11)","decl":{"start":{"line":216,"column":16},"end":{"line":216,"column":17}},"loc":{"start":{"line":216,"column":23},"end":{"line":216,"column":44}},"line":216},"12":{"name":"(anonymous_12)","decl":{"start":{"line":226,"column":70},"end":{"line":226,"column":71}},"loc":{"start":{"line":226,"column":77},"end":{"line":236,"column":5}},"line":226},"13":{"name":"(anonymous_13)","decl":{"start":{"line":229,"column":16},"end":{"line":229,"column":17}},"loc":{"start":{"line":229,"column":23},"end":{"line":229,"column":41}},"line":229},"14":{"name":"(anonymous_14)","decl":{"start":{"line":230,"column":28},"end":{"line":230,"column":29}},"loc":{"start":{"line":230,"column":35},"end":{"line":235,"column":7}},"line":230},"15":{"name":"(anonymous_15)","decl":{"start":{"line":238,"column":68},"end":{"line":238,"column":69}},"loc":{"start":{"line":238,"column":75},"end":{"line":248,"column":5}},"line":238},"16":{"name":"(anonymous_16)","decl":{"start":{"line":241,"column":16},"end":{"line":241,"column":17}},"loc":{"start":{"line":241,"column":23},"end":{"line":241,"column":41}},"line":241},"17":{"name":"(anonymous_17)","decl":{"start":{"line":242,"column":27},"end":{"line":242,"column":28}},"loc":{"start":{"line":242,"column":34},"end":{"line":247,"column":7}},"line":242},"18":{"name":"(anonymous_18)","decl":{"start":{"line":251,"column":40},"end":{"line":251,"column":41}},"loc":{"start":{"line":251,"column":47},"end":{"line":251,"column":69}},"line":251},"19":{"name":"(anonymous_19)","decl":{"start":{"line":254,"column":40},"end":{"line":254,"column":41}},"loc":{"start":{"line":254,"column":47},"end":{"line":254,"column":71}},"line":254},"20":{"name":"(anonymous_20)","decl":{"start":{"line":278,"column":2},"end":{"line":278,"column":20}},"loc":{"start":{"line":278,"column":78},"end":{"line":295,"column":null}},"line":278},"21":{"name":"(anonymous_21)","decl":{"start":{"line":280,"column":6},"end":{"line":280,"column":7}},"loc":{"start":{"line":280,"column":13},"end":{"line":280,"column":null}},"line":280},"22":{"name":"(anonymous_22)","decl":{"start":{"line":284,"column":28},"end":{"line":284,"column":29}},"loc":{"start":{"line":284,"column":35},"end":{"line":284,"column":72}},"line":284},"23":{"name":"(anonymous_23)","decl":{"start":{"line":288,"column":28},"end":{"line":288,"column":29}},"loc":{"start":{"line":288,"column":35},"end":{"line":291,"column":7}},"line":288},"24":{"name":"(anonymous_24)","decl":{"start":{"line":301,"column":8},"end":{"line":301,"column":22}},"loc":{"start":{"line":301,"column":58},"end":{"line":344,"column":null}},"line":301},"25":{"name":"(anonymous_25)","decl":{"start":{"line":350,"column":8},"end":{"line":350,"column":19}},"loc":{"start":{"line":350,"column":46},"end":{"line":392,"column":null}},"line":350},"26":{"name":"(anonymous_26)","decl":{"start":{"line":397,"column":8},"end":{"line":397,"column":null}},"loc":{"start":{"line":400,"column":22},"end":{"line":433,"column":null}},"line":400},"27":{"name":"(anonymous_27)","decl":{"start":{"line":438,"column":8},"end":{"line":438,"column":null}},"loc":{"start":{"line":441,"column":22},"end":{"line":477,"column":null}},"line":441},"28":{"name":"(anonymous_28)","decl":{"start":{"line":483,"column":2},"end":{"line":483,"column":9}},"loc":{"start":{"line":483,"column":61},"end":{"line":509,"column":null}},"line":483},"29":{"name":"(anonymous_29)","decl":{"start":{"line":514,"column":2},"end":{"line":514,"column":19}},"loc":{"start":{"line":514,"column":19},"end":{"line":536,"column":null}},"line":514},"30":{"name":"(anonymous_30)","decl":{"start":{"line":522,"column":12},"end":{"line":522,"column":13}},"loc":{"start":{"line":522,"column":19},"end":{"line":522,"column":null}},"line":522},"31":{"name":"(anonymous_31)","decl":{"start":{"line":526,"column":12},"end":{"line":526,"column":13}},"loc":{"start":{"line":526,"column":19},"end":{"line":526,"column":null}},"line":526},"32":{"name":"(anonymous_32)","decl":{"start":{"line":529,"column":12},"end":{"line":529,"column":13}},"loc":{"start":{"line":529,"column":19},"end":{"line":529,"column":null}},"line":529}},"branchMap":{"0":{"loc":{"start":{"line":84,"column":16},"end":{"line":84,"column":null}},"type":"binary-expr","locations":[{"start":{"line":84,"column":16},"end":{"line":84,"column":42}},{"start":{"line":84,"column":42},"end":{"line":84,"column":null}}],"line":84},"1":{"loc":{"start":{"line":101,"column":16},"end":{"line":101,"column":null}},"type":"binary-expr","locations":[{"start":{"line":101,"column":16},"end":{"line":101,"column":42}},{"start":{"line":101,"column":42},"end":{"line":101,"column":null}}],"line":101},"2":{"loc":{"start":{"line":107,"column":19},"end":{"line":107,"column":null}},"type":"binary-expr","locations":[{"start":{"line":107,"column":19},"end":{"line":107,"column":48}},{"start":{"line":107,"column":48},"end":{"line":107,"column":null}}],"line":107},"3":{"loc":{"start":{"line":113,"column":6},"end":{"line":118,"column":null}},"type":"if","locations":[{"start":{"line":113,"column":6},"end":{"line":118,"column":null}},{"start":{},"end":{}}],"line":113},"4":{"loc":{"start":{"line":115,"column":8},"end":{"line":117,"column":null}},"type":"if","locations":[{"start":{"line":115,"column":8},"end":{"line":117,"column":null}},{"start":{},"end":{}}],"line":115},"5":{"loc":{"start":{"line":115,"column":12},"end":{"line":115,"column":64}},"type":"binary-expr","locations":[{"start":{"line":115,"column":12},"end":{"line":115,"column":23}},{"start":{"line":115,"column":23},"end":{"line":115,"column":64}}],"line":115},"6":{"loc":{"start":{"line":135,"column":4},"end":{"line":147,"column":null}},"type":"if","locations":[{"start":{"line":135,"column":4},"end":{"line":147,"column":null}},{"start":{"line":140,"column":4},"end":{"line":147,"column":null}}],"line":135},"7":{"loc":{"start":{"line":137,"column":8},"end":{"line":137,"column":null}},"type":"if","locations":[{"start":{"line":137,"column":8},"end":{"line":137,"column":null}},{"start":{},"end":{}}],"line":137},"8":{"loc":{"start":{"line":137,"column":12},"end":{"line":137,"column":64}},"type":"binary-expr","locations":[{"start":{"line":137,"column":12},"end":{"line":137,"column":30}},{"start":{"line":137,"column":30},"end":{"line":137,"column":64}}],"line":137},"9":{"loc":{"start":{"line":140,"column":4},"end":{"line":147,"column":null}},"type":"if","locations":[{"start":{"line":140,"column":4},"end":{"line":147,"column":null}},{"start":{},"end":{}}],"line":140},"10":{"loc":{"start":{"line":142,"column":8},"end":{"line":142,"column":null}},"type":"if","locations":[{"start":{"line":142,"column":8},"end":{"line":142,"column":null}},{"start":{},"end":{}}],"line":142},"11":{"loc":{"start":{"line":142,"column":12},"end":{"line":142,"column":61}},"type":"binary-expr","locations":[{"start":{"line":142,"column":12},"end":{"line":142,"column":30}},{"start":{"line":142,"column":30},"end":{"line":142,"column":61}}],"line":142},"12":{"loc":{"start":{"line":143,"column":8},"end":{"line":143,"column":null}},"type":"if","locations":[{"start":{"line":143,"column":8},"end":{"line":143,"column":null}},{"start":{},"end":{}}],"line":143},"13":{"loc":{"start":{"line":143,"column":12},"end":{"line":143,"column":67}},"type":"binary-expr","locations":[{"start":{"line":143,"column":12},"end":{"line":143,"column":32}},{"start":{"line":143,"column":32},"end":{"line":143,"column":67}}],"line":143},"14":{"loc":{"start":{"line":144,"column":8},"end":{"line":144,"column":null}},"type":"if","locations":[{"start":{"line":144,"column":8},"end":{"line":144,"column":null}},{"start":{},"end":{}}],"line":144},"15":{"loc":{"start":{"line":144,"column":12},"end":{"line":144,"column":70}},"type":"binary-expr","locations":[{"start":{"line":144,"column":12},"end":{"line":144,"column":33}},{"start":{"line":144,"column":33},"end":{"line":144,"column":70}}],"line":144},"16":{"loc":{"start":{"line":168,"column":4},"end":{"line":168,"column":null}},"type":"if","locations":[{"start":{"line":168,"column":4},"end":{"line":168,"column":null}},{"start":{},"end":{}}],"line":168},"17":{"loc":{"start":{"line":172,"column":4},"end":{"line":176,"column":null}},"type":"if","locations":[{"start":{"line":172,"column":4},"end":{"line":176,"column":null}},{"start":{"line":174,"column":4},"end":{"line":176,"column":null}}],"line":172},"18":{"loc":{"start":{"line":174,"column":4},"end":{"line":176,"column":null}},"type":"if","locations":[{"start":{"line":174,"column":4},"end":{"line":176,"column":null}},{"start":{},"end":{}}],"line":174},"19":{"loc":{"start":{"line":174,"column":15},"end":{"line":174,"column":68}},"type":"binary-expr","locations":[{"start":{"line":174,"column":15},"end":{"line":174,"column":51}},{"start":{"line":174,"column":51},"end":{"line":174,"column":68}}],"line":174},"20":{"loc":{"start":{"line":186,"column":4},"end":{"line":186,"column":null}},"type":"if","locations":[{"start":{"line":186,"column":4},"end":{"line":186,"column":null}},{"start":{},"end":{}}],"line":186},"21":{"loc":{"start":{"line":200,"column":6},"end":{"line":202,"column":null}},"type":"if","locations":[{"start":{"line":200,"column":6},"end":{"line":202,"column":null}},{"start":{},"end":{}}],"line":200},"22":{"loc":{"start":{"line":200,"column":10},"end":{"line":200,"column":40}},"type":"binary-expr","locations":[{"start":{"line":200,"column":10},"end":{"line":200,"column":18}},{"start":{"line":200,"column":18},"end":{"line":200,"column":40}}],"line":200},"23":{"loc":{"start":{"line":212,"column":6},"end":{"line":212,"column":null}},"type":"if","locations":[{"start":{"line":212,"column":6},"end":{"line":212,"column":null}},{"start":{},"end":{}}],"line":212},"24":{"loc":{"start":{"line":219,"column":8},"end":{"line":219,"column":null}},"type":"if","locations":[{"start":{"line":219,"column":8},"end":{"line":219,"column":null}},{"start":{},"end":{}}],"line":219},"25":{"loc":{"start":{"line":220,"column":8},"end":{"line":220,"column":null}},"type":"if","locations":[{"start":{"line":220,"column":8},"end":{"line":220,"column":null}},{"start":{},"end":{}}],"line":220},"26":{"loc":{"start":{"line":221,"column":8},"end":{"line":221,"column":null}},"type":"if","locations":[{"start":{"line":221,"column":8},"end":{"line":221,"column":null}},{"start":{},"end":{}}],"line":221},"27":{"loc":{"start":{"line":233,"column":10},"end":{"line":233,"column":null}},"type":"binary-expr","locations":[{"start":{"line":233,"column":10},"end":{"line":233,"column":20}},{"start":{"line":233,"column":20},"end":{"line":233,"column":null}}],"line":233},"28":{"loc":{"start":{"line":233,"column":47},"end":{"line":233,"column":75}},"type":"binary-expr","locations":[{"start":{"line":233,"column":47},"end":{"line":233,"column":73}},{"start":{"line":233,"column":73},"end":{"line":233,"column":75}}],"line":233},"29":{"loc":{"start":{"line":245,"column":10},"end":{"line":245,"column":null}},"type":"binary-expr","locations":[{"start":{"line":245,"column":10},"end":{"line":245,"column":20}},{"start":{"line":245,"column":20},"end":{"line":245,"column":null}}],"line":245},"30":{"loc":{"start":{"line":245,"column":47},"end":{"line":245,"column":75}},"type":"binary-expr","locations":[{"start":{"line":245,"column":47},"end":{"line":245,"column":73}},{"start":{"line":245,"column":73},"end":{"line":245,"column":75}}],"line":245},"31":{"loc":{"start":{"line":256,"column":6},"end":{"line":256,"column":null}},"type":"cond-expr","locations":[{"start":{"line":256,"column":26},"end":{"line":256,"column":65}},{"start":{"line":256,"column":65},"end":{"line":256,"column":null}}],"line":256},"32":{"loc":{"start":{"line":283,"column":4},"end":{"line":285,"column":null}},"type":"if","locations":[{"start":{"line":283,"column":4},"end":{"line":285,"column":null}},{"start":{},"end":{}}],"line":283},"33":{"loc":{"start":{"line":284,"column":35},"end":{"line":284,"column":72}},"type":"binary-expr","locations":[{"start":{"line":284,"column":35},"end":{"line":284,"column":50}},{"start":{"line":284,"column":50},"end":{"line":284,"column":72}}],"line":284},"34":{"loc":{"start":{"line":287,"column":4},"end":{"line":292,"column":null}},"type":"if","locations":[{"start":{"line":287,"column":4},"end":{"line":292,"column":null}},{"start":{},"end":{}}],"line":287},"35":{"loc":{"start":{"line":289,"column":42},"end":{"line":289,"column":59}},"type":"binary-expr","locations":[{"start":{"line":289,"column":42},"end":{"line":289,"column":57}},{"start":{"line":289,"column":57},"end":{"line":289,"column":59}}],"line":289},"36":{"loc":{"start":{"line":290,"column":15},"end":{"line":290,"column":null}},"type":"binary-expr","locations":[{"start":{"line":290,"column":15},"end":{"line":290,"column":26}},{"start":{"line":290,"column":26},"end":{"line":290,"column":null}}],"line":290},"37":{"loc":{"start":{"line":302,"column":4},"end":{"line":306,"column":null}},"type":"if","locations":[{"start":{"line":302,"column":4},"end":{"line":306,"column":null}},{"start":{},"end":{}}],"line":302},"38":{"loc":{"start":{"line":302,"column":8},"end":{"line":302,"column":56}},"type":"binary-expr","locations":[{"start":{"line":302,"column":8},"end":{"line":302,"column":26}},{"start":{"line":302,"column":26},"end":{"line":302,"column":56}}],"line":302},"39":{"loc":{"start":{"line":320,"column":23},"end":{"line":320,"column":null}},"type":"binary-expr","locations":[{"start":{"line":320,"column":23},"end":{"line":320,"column":46}},{"start":{"line":320,"column":46},"end":{"line":320,"column":null}}],"line":320},"40":{"loc":{"start":{"line":327,"column":6},"end":{"line":331,"column":null}},"type":"if","locations":[{"start":{"line":327,"column":6},"end":{"line":331,"column":null}},{"start":{},"end":{}}],"line":327},"41":{"loc":{"start":{"line":341,"column":54},"end":{"line":341,"column":102}},"type":"cond-expr","locations":[{"start":{"line":341,"column":77},"end":{"line":341,"column":91}},{"start":{"line":341,"column":91},"end":{"line":341,"column":102}}],"line":341},"42":{"loc":{"start":{"line":351,"column":4},"end":{"line":355,"column":null}},"type":"if","locations":[{"start":{"line":351,"column":4},"end":{"line":355,"column":null}},{"start":{},"end":{}}],"line":351},"43":{"loc":{"start":{"line":351,"column":8},"end":{"line":351,"column":56}},"type":"binary-expr","locations":[{"start":{"line":351,"column":8},"end":{"line":351,"column":26}},{"start":{"line":351,"column":26},"end":{"line":351,"column":56}}],"line":351},"44":{"loc":{"start":{"line":368,"column":23},"end":{"line":368,"column":null}},"type":"binary-expr","locations":[{"start":{"line":368,"column":23},"end":{"line":368,"column":43}},{"start":{"line":368,"column":43},"end":{"line":368,"column":null}}],"line":368},"45":{"loc":{"start":{"line":370,"column":21},"end":{"line":370,"column":null}},"type":"binary-expr","locations":[{"start":{"line":370,"column":21},"end":{"line":370,"column":39}},{"start":{"line":370,"column":39},"end":{"line":370,"column":null}}],"line":370},"46":{"loc":{"start":{"line":371,"column":20},"end":{"line":371,"column":null}},"type":"binary-expr","locations":[{"start":{"line":371,"column":20},"end":{"line":371,"column":37}},{"start":{"line":371,"column":37},"end":{"line":371,"column":null}}],"line":371},"47":{"loc":{"start":{"line":372,"column":19},"end":{"line":372,"column":null}},"type":"binary-expr","locations":[{"start":{"line":372,"column":19},"end":{"line":372,"column":35}},{"start":{"line":372,"column":35},"end":{"line":372,"column":null}}],"line":372},"48":{"loc":{"start":{"line":377,"column":6},"end":{"line":381,"column":null}},"type":"if","locations":[{"start":{"line":377,"column":6},"end":{"line":381,"column":null}},{"start":{},"end":{}}],"line":377},"49":{"loc":{"start":{"line":389,"column":51},"end":{"line":389,"column":99}},"type":"cond-expr","locations":[{"start":{"line":389,"column":74},"end":{"line":389,"column":88}},{"start":{"line":389,"column":88},"end":{"line":389,"column":99}}],"line":389},"50":{"loc":{"start":{"line":401,"column":4},"end":{"line":403,"column":null}},"type":"if","locations":[{"start":{"line":401,"column":4},"end":{"line":403,"column":null}},{"start":{},"end":{}}],"line":401},"51":{"loc":{"start":{"line":401,"column":8},"end":{"line":401,"column":56}},"type":"binary-expr","locations":[{"start":{"line":401,"column":8},"end":{"line":401,"column":26}},{"start":{"line":401,"column":26},"end":{"line":401,"column":56}}],"line":401},"52":{"loc":{"start":{"line":411,"column":16},"end":{"line":411,"column":75}},"type":"cond-expr","locations":[{"start":{"line":411,"column":38},"end":{"line":411,"column":73}},{"start":{"line":411,"column":73},"end":{"line":411,"column":75}}],"line":411},"53":{"loc":{"start":{"line":412,"column":16},"end":{"line":412,"column":69}},"type":"cond-expr","locations":[{"start":{"line":412,"column":36},"end":{"line":412,"column":67}},{"start":{"line":412,"column":67},"end":{"line":412,"column":69}}],"line":412},"54":{"loc":{"start":{"line":413,"column":16},"end":{"line":413,"column":75}},"type":"cond-expr","locations":[{"start":{"line":413,"column":38},"end":{"line":413,"column":73}},{"start":{"line":413,"column":73},"end":{"line":413,"column":75}}],"line":413},"55":{"loc":{"start":{"line":442,"column":4},"end":{"line":444,"column":null}},"type":"if","locations":[{"start":{"line":442,"column":4},"end":{"line":444,"column":null}},{"start":{},"end":{}}],"line":442},"56":{"loc":{"start":{"line":442,"column":8},"end":{"line":442,"column":56}},"type":"binary-expr","locations":[{"start":{"line":442,"column":8},"end":{"line":442,"column":26}},{"start":{"line":442,"column":26},"end":{"line":442,"column":56}}],"line":442},"57":{"loc":{"start":{"line":452,"column":16},"end":{"line":452,"column":75}},"type":"cond-expr","locations":[{"start":{"line":452,"column":38},"end":{"line":452,"column":73}},{"start":{"line":452,"column":73},"end":{"line":452,"column":75}}],"line":452},"58":{"loc":{"start":{"line":453,"column":16},"end":{"line":453,"column":69}},"type":"cond-expr","locations":[{"start":{"line":453,"column":36},"end":{"line":453,"column":67}},{"start":{"line":453,"column":67},"end":{"line":453,"column":69}}],"line":453},"59":{"loc":{"start":{"line":454,"column":16},"end":{"line":454,"column":75}},"type":"cond-expr","locations":[{"start":{"line":454,"column":38},"end":{"line":454,"column":73}},{"start":{"line":454,"column":73},"end":{"line":454,"column":75}}],"line":454},"60":{"loc":{"start":{"line":492,"column":4},"end":{"line":504,"column":null}},"type":"if","locations":[{"start":{"line":492,"column":4},"end":{"line":504,"column":null}},{"start":{},"end":{}}],"line":492},"61":{"loc":{"start":{"line":494,"column":8},"end":{"line":496,"column":null}},"type":"if","locations":[{"start":{"line":494,"column":8},"end":{"line":496,"column":null}},{"start":{},"end":{}}],"line":494},"62":{"loc":{"start":{"line":500,"column":8},"end":{"line":502,"column":null}},"type":"if","locations":[{"start":{"line":500,"column":8},"end":{"line":502,"column":null}},{"start":{},"end":{}}],"line":500}},"s":{"0":62,"1":62,"2":62,"3":62,"4":62,"5":72,"6":72,"7":8,"8":72,"9":72,"10":14,"11":72,"12":14,"13":14,"14":14,"15":0,"16":2,"17":2,"18":1,"19":1,"20":0,"21":1,"22":1,"23":1,"24":2,"25":0,"26":2,"27":0,"28":2,"29":0,"30":2,"31":2,"32":3,"33":2,"34":3,"35":2,"36":3,"37":2,"38":2,"39":2,"40":0,"41":2,"42":2,"43":1,"44":1,"45":1,"46":2,"47":1,"48":1,"49":0,"50":1,"51":2,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"61":1,"62":1,"63":1,"64":1,"65":1,"66":0,"67":1,"68":2,"69":1,"70":2,"71":2,"72":0,"73":2,"74":1,"75":2,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1,"89":1,"90":2,"91":1,"92":2,"93":1,"94":1,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":1,"106":1,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":1,"127":0,"128":1,"129":1,"130":1,"131":1,"132":0,"133":0,"134":0,"135":0,"136":0,"137":0,"138":0,"139":0,"140":0,"141":0,"142":10,"143":10,"144":10,"145":10,"146":10,"147":10,"148":10,"149":2,"150":1,"151":10,"152":3,"153":1,"154":10,"155":10,"156":10,"157":0,"158":0,"159":0,"160":0},"f":{"0":62,"1":72,"2":2,"3":3,"4":3,"5":3,"6":2,"7":1,"8":2,"9":1,"10":1,"11":2,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":2,"19":2,"20":0,"21":0,"22":0,"23":0,"24":1,"25":0,"26":1,"27":0,"28":10,"29":0,"30":0,"31":0,"32":0},"b":{"0":[8,0],"1":[14,0],"2":[14,8],"3":[14,0],"4":[0,14],"5":[14,14],"6":[1,1],"7":[0,1],"8":[1,0],"9":[1,0],"10":[0,2],"11":[2,0],"12":[0,2],"13":[2,0],"14":[0,2],"15":[2,0],"16":[0,2],"17":[1,1],"18":[1,0],"19":[1,1],"20":[0,1],"21":[1,0],"22":[1,1],"23":[0,1],"24":[0,2],"25":[1,1],"26":[1,1],"27":[1,1],"28":[1,0],"29":[1,1],"30":[1,0],"31":[1,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[1,0],"38":[1,1],"39":[0,0],"40":[0,0],"41":[0,0],"42":[0,0],"43":[0,0],"44":[0,0],"45":[0,0],"46":[0,0],"47":[0,0],"48":[0,0],"49":[0,0],"50":[0,1],"51":[1,1],"52":[0,1],"53":[0,1],"54":[0,1],"55":[0,0],"56":[0,0],"57":[0,0],"58":[0,0],"59":[0,0],"60":[10,0],"61":[1,1],"62":[1,2]},"meta":{"lastBranch":63,"lastFunction":33,"lastStatement":161,"seen":{"f:66:2:66:14":0,"s:67:4:67:Infinity":0,"s:68:4:68:Infinity":1,"s:69:4:69:Infinity":2,"s:70:4:70:Infinity":3,"s:71:4:71:Infinity":4,"f:77:10:77:32":1,"s:79:25:79:Infinity":5,"s:80:4:92:Infinity":6,"s:81:6:91:Infinity":7,"b:84:16:84:42:84:42:84:Infinity":0,"s:95:22:95:Infinity":8,"s:96:4:109:Infinity":9,"s:97:6:108:Infinity":10,"b:101:16:101:42:101:42:101:Infinity":1,"b:107:19:107:48:107:48:107:Infinity":2,"s:112:4:119:Infinity":11,"b:113:6:118:Infinity:undefined:undefined:undefined:undefined":3,"s:113:6:118:Infinity":12,"s:114:24:114:Infinity":13,"b:115:8:117:Infinity:undefined:undefined:undefined:undefined":4,"s:115:8:117:Infinity":14,"b:115:12:115:23:115:23:115:64":5,"s:116:11:116:Infinity":15,"f:125:2:125:Infinity":2,"s:133:38:133:Infinity":16,"b:135:4:147:Infinity:140:4:147:Infinity":6,"s:135:4:147:Infinity":17,"s:136:6:139:Infinity":18,"b:137:8:137:Infinity:undefined:undefined:undefined:undefined":7,"s:137:8:137:Infinity":19,"b:137:12:137:30:137:30:137:64":8,"s:137:64:137:Infinity":20,"s:138:8:138:Infinity":21,"b:140:4:147:Infinity:undefined:undefined:undefined:undefined":9,"s:140:4:147:Infinity":22,"s:141:6:146:Infinity":23,"b:142:8:142:Infinity:undefined:undefined:undefined:undefined":10,"s:142:8:142:Infinity":24,"b:142:12:142:30:142:30:142:61":11,"s:142:61:142:Infinity":25,"b:143:8:143:Infinity:undefined:undefined:undefined:undefined":12,"s:143:8:143:Infinity":26,"b:143:12:143:32:143:32:143:67":13,"s:143:67:143:Infinity":27,"b:144:8:144:Infinity:undefined:undefined:undefined:undefined":14,"s:144:8:144:Infinity":28,"b:144:12:144:33:144:33:144:70":15,"s:144:70:144:Infinity":29,"s:145:8:145:Infinity":30,"s:150:22:150:Infinity":31,"f:150:35:150:36":3,"s:150:42:150:66":32,"s:151:23:151:Infinity":33,"f:151:36:151:37":4,"s:151:43:151:69":34,"s:152:20:152:Infinity":35,"f:152:33:152:34":5,"s:152:40:152:62":36,"s:154:4:160:Infinity":37,"f:166:2:166:13":6,"s:167:17:167:Infinity":38,"b:168:4:168:Infinity:undefined:undefined:undefined:undefined":16,"s:168:4:168:Infinity":39,"s:168:15:168:Infinity":40,"s:170:4:170:Infinity":41,"b:172:4:176:Infinity:174:4:176:Infinity":17,"s:172:4:176:Infinity":42,"s:173:6:173:Infinity":43,"b:174:4:176:Infinity:undefined:undefined:undefined:undefined":18,"s:174:4:176:Infinity":44,"b:174:15:174:51:174:51:174:68":19,"s:175:6:175:Infinity":45,"s:178:4:178:Infinity":46,"f:184:2:184:19":7,"s:185:20:185:Infinity":47,"b:186:4:186:Infinity:undefined:undefined:undefined:undefined":20,"s:186:4:186:Infinity":48,"s:186:18:186:Infinity":49,"s:189:18:191:Infinity":50,"f:190:6:190:7":8,"s:190:13:190:Infinity":51,"s:194:40:194:Infinity":52,"s:195:21:197:Infinity":53,"f:197:14:197:15":9,"s:197:21:197:44":54,"s:198:4:203:Infinity":55,"s:199:19:199:Infinity":56,"b:200:6:202:Infinity:undefined:undefined:undefined:undefined":21,"s:200:6:202:Infinity":57,"b:200:10:200:18:200:18:200:40":22,"s:201:8:201:Infinity":58,"s:206:24:206:Infinity":59,"s:207:21:207:Infinity":60,"s:209:4:223:Infinity":61,"s:210:24:210:Infinity":62,"s:211:23:211:Infinity":63,"f:211:38:211:39":10,"s:211:45:211:75":64,"b:212:6:212:Infinity:undefined:undefined:undefined:undefined":23,"s:212:6:212:Infinity":65,"s:212:21:212:Infinity":66,"s:214:23:216:Infinity":67,"f:216:16:216:17":11,"s:216:23:216:44":68,"s:217:6:222:Infinity":69,"s:218:21:218:Infinity":70,"b:219:8:219:Infinity:undefined:undefined:undefined:undefined":24,"s:219:8:219:Infinity":71,"s:219:19:219:Infinity":72,"b:220:8:220:Infinity:undefined:undefined:undefined:undefined":25,"s:220:8:220:Infinity":73,"s:220:38:220:Infinity":74,"b:221:8:221:Infinity:undefined:undefined:undefined:undefined":26,"s:221:8:221:Infinity":75,"s:221:35:221:Infinity":76,"s:226:23:236:Infinity":77,"f:226:70:226:71":12,"s:227:24:229:Infinity":78,"f:229:16:229:17":13,"s:229:23:229:41":79,"s:230:6:235:Infinity":80,"f:230:28:230:29":14,"s:231:23:231:Infinity":81,"s:232:8:233:Infinity":82,"b:233:10:233:20:233:20:233:Infinity":27,"b:233:47:233:73:233:73:233:75":28,"s:238:22:248:Infinity":83,"f:238:68:238:69":15,"s:239:23:241:Infinity":84,"f:241:16:241:17":16,"s:241:23:241:41":85,"s:242:6:247:Infinity":86,"f:242:27:242:28":17,"s:243:23:243:Infinity":87,"s:244:8:245:Infinity":88,"b:245:10:245:20:245:20:245:Infinity":29,"b:245:47:245:73:245:73:245:75":30,"s:251:27:251:Infinity":89,"f:251:40:251:41":18,"s:251:47:251:69":90,"s:254:27:254:Infinity":91,"f:254:40:254:41":19,"s:254:47:254:71":92,"s:256:6:256:Infinity":93,"b:256:26:256:65:256:65:256:Infinity":31,"s:258:4:272:Infinity":94,"f:278:2:278:20":20,"s:279:20:281:Infinity":95,"f:280:6:280:7":21,"s:280:13:280:Infinity":96,"b:283:4:285:Infinity:undefined:undefined:undefined:undefined":32,"s:283:4:285:Infinity":97,"s:284:6:284:Infinity":98,"f:284:28:284:29":22,"s:284:35:284:72":99,"b:284:35:284:50:284:50:284:72":33,"b:287:4:292:Infinity:undefined:undefined:undefined:undefined":34,"s:287:4:292:Infinity":100,"s:288:6:291:Infinity":101,"f:288:28:288:29":23,"s:289:24:289:Infinity":102,"b:289:42:289:57:289:57:289:59":35,"s:290:8:290:Infinity":103,"b:290:15:290:26:290:26:290:Infinity":36,"s:294:4:294:Infinity":104,"f:301:8:301:22":24,"b:302:4:306:Infinity:undefined:undefined:undefined:undefined":37,"s:302:4:306:Infinity":105,"b:302:8:302:26:302:26:302:56":38,"s:303:6:305:Infinity":106,"s:308:4:308:Infinity":107,"s:310:4:343:Infinity":108,"s:311:21:325:Infinity":109,"b:320:23:320:46:320:46:320:Infinity":39,"b:327:6:331:Infinity:undefined:undefined:undefined:undefined":40,"s:327:6:331:Infinity":110,"s:328:8:330:Infinity":111,"s:334:6:334:Infinity":112,"s:335:6:337:Infinity":113,"s:338:6:338:Infinity":114,"s:340:6:342:Infinity":115,"b:341:77:341:91:341:91:341:102":41,"f:350:8:350:19":25,"b:351:4:355:Infinity:undefined:undefined:undefined:undefined":42,"s:351:4:355:Infinity":116,"b:351:8:351:26:351:26:351:56":43,"s:352:6:354:Infinity":117,"s:357:4:391:Infinity":118,"s:358:21:375:Infinity":119,"b:368:23:368:43:368:43:368:Infinity":44,"b:370:21:370:39:370:39:370:Infinity":45,"b:371:20:371:37:371:37:371:Infinity":46,"b:372:19:372:35:372:35:372:Infinity":47,"b:377:6:381:Infinity:undefined:undefined:undefined:undefined":48,"s:377:6:381:Infinity":120,"s:378:8:380:Infinity":121,"s:384:6:384:Infinity":122,"s:385:6:385:Infinity":123,"s:386:6:386:Infinity":124,"s:388:6:390:Infinity":125,"b:389:74:389:88:389:88:389:99":49,"f:397:8:397:Infinity":26,"b:401:4:403:Infinity:undefined:undefined:undefined:undefined":50,"s:401:4:403:Infinity":126,"b:401:8:401:26:401:26:401:56":51,"s:402:6:402:Infinity":127,"s:405:4:432:Infinity":128,"s:406:41:422:Infinity":129,"b:411:38:411:73:411:73:411:75":52,"b:412:36:412:67:412:67:412:69":53,"b:413:38:413:73:413:73:413:75":54,"s:424:21:427:Infinity":130,"s:428:6:428:Infinity":131,"s:430:6:430:Infinity":132,"s:431:6:431:Infinity":133,"f:438:8:438:Infinity":27,"b:442:4:444:Infinity:undefined:undefined:undefined:undefined":55,"s:442:4:444:Infinity":134,"b:442:8:442:26:442:26:442:56":56,"s:443:6:443:Infinity":135,"s:446:4:476:Infinity":136,"s:447:41:463:Infinity":137,"b:452:38:452:73:452:73:452:75":57,"b:453:36:453:67:453:67:453:69":58,"b:454:38:454:73:454:73:454:75":59,"s:465:21:468:Infinity":138,"s:469:6:469:Infinity":139,"s:471:6:474:Infinity":140,"s:475:6:475:Infinity":141,"f:483:2:483:9":28,"s:484:4:484:Infinity":142,"s:486:4:486:Infinity":143,"s:487:4:487:Infinity":144,"s:488:4:488:Infinity":145,"s:489:4:489:Infinity":146,"b:492:4:504:Infinity:undefined:undefined:undefined:undefined":60,"s:492:4:504:Infinity":147,"s:493:6:497:Infinity":148,"b:494:8:496:Infinity:undefined:undefined:undefined:undefined":61,"s:494:8:496:Infinity":149,"s:495:10:495:Infinity":150,"s:499:6:503:Infinity":151,"b:500:8:502:Infinity:undefined:undefined:undefined:undefined":62,"s:500:8:502:Infinity":152,"s:501:10:501:Infinity":153,"s:506:25:506:Infinity":154,"s:507:22:507:Infinity":155,"s:508:4:508:Infinity":156,"f:514:2:514:19":29,"s:515:4:535:Infinity":157,"f:522:12:522:13":30,"s:522:19:522:Infinity":158,"f:526:12:526:13":31,"s:526:19:526:Infinity":159,"f:529:12:529:13":32,"s:529:19:529:Infinity":160}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/engines/test-engine.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/engines/test-engine.ts","statementMap":{"0":{"start":{"line":42,"column":4},"end":{"line":42,"column":null}},"1":{"start":{"line":43,"column":4},"end":{"line":43,"column":null}},"2":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"3":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"4":{"start":{"line":52,"column":23},"end":{"line":52,"column":null}},"5":{"start":{"line":54,"column":4},"end":{"line":121,"column":null}},"6":{"start":{"line":55,"column":23},"end":{"line":55,"column":null}},"7":{"start":{"line":56,"column":31},"end":{"line":56,"column":null}},"8":{"start":{"line":57,"column":33},"end":{"line":57,"column":null}},"9":{"start":{"line":58,"column":33},"end":{"line":58,"column":null}},"10":{"start":{"line":61,"column":24},"end":{"line":63,"column":null}},"11":{"start":{"line":63,"column":24},"end":{"line":63,"column":55}},"12":{"start":{"line":66,"column":6},"end":{"line":91,"column":null}},"13":{"start":{"line":67,"column":26},"end":{"line":69,"column":null}},"14":{"start":{"line":69,"column":25},"end":{"line":69,"column":43}},"15":{"start":{"line":71,"column":8},"end":{"line":90,"column":null}},"16":{"start":{"line":72,"column":32},"end":{"line":72,"column":null}},"17":{"start":{"line":73,"column":10},"end":{"line":73,"column":null}},"18":{"start":{"line":73,"column":30},"end":{"line":73,"column":null}},"19":{"start":{"line":76,"column":10},"end":{"line":78,"column":null}},"20":{"start":{"line":77,"column":12},"end":{"line":77,"column":null}},"21":{"start":{"line":81,"column":29},"end":{"line":83,"column":null}},"22":{"start":{"line":83,"column":27},"end":{"line":83,"column":47}},"23":{"start":{"line":84,"column":10},"end":{"line":89,"column":null}},"24":{"start":{"line":85,"column":29},"end":{"line":85,"column":null}},"25":{"start":{"line":86,"column":12},"end":{"line":88,"column":null}},"26":{"start":{"line":87,"column":14},"end":{"line":87,"column":null}},"27":{"start":{"line":95,"column":20},"end":{"line":103,"column":null}},"28":{"start":{"line":96,"column":21},"end":{"line":98,"column":null}},"29":{"start":{"line":98,"column":25},"end":{"line":98,"column":45}},"30":{"start":{"line":99,"column":8},"end":{"line":102,"column":null}},"31":{"start":{"line":100,"column":22},"end":{"line":100,"column":null}},"32":{"start":{"line":101,"column":10},"end":{"line":101,"column":null}},"33":{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},"34":{"start":{"line":105,"column":36},"end":{"line":105,"column":53}},"35":{"start":{"line":107,"column":6},"end":{"line":111,"column":null}},"36":{"start":{"line":114,"column":23},"end":{"line":114,"column":null}},"37":{"start":{"line":115,"column":6},"end":{"line":120,"column":null}},"38":{"start":{"line":130,"column":4},"end":{"line":130,"column":null}},"39":{"start":{"line":130,"column":49},"end":{"line":130,"column":null}},"40":{"start":{"line":131,"column":4},"end":{"line":131,"column":null}},"41":{"start":{"line":131,"column":49},"end":{"line":131,"column":null}},"42":{"start":{"line":132,"column":4},"end":{"line":132,"column":null}},"43":{"start":{"line":132,"column":36},"end":{"line":132,"column":null}},"44":{"start":{"line":133,"column":4},"end":{"line":133,"column":null}},"45":{"start":{"line":144,"column":21},"end":{"line":144,"column":null}},"46":{"start":{"line":145,"column":28},"end":{"line":145,"column":null}},"47":{"start":{"line":148,"column":30},"end":{"line":148,"column":null}},"48":{"start":{"line":148,"column":54},"end":{"line":148,"column":75}},"49":{"start":{"line":151,"column":4},"end":{"line":177,"column":null}},"50":{"start":{"line":152,"column":6},"end":{"line":176,"column":null}},"51":{"start":{"line":153,"column":25},"end":{"line":153,"column":null}},"52":{"start":{"line":154,"column":8},"end":{"line":154,"column":null}},"53":{"start":{"line":154,"column":23},"end":{"line":154,"column":null}},"54":{"start":{"line":157,"column":8},"end":{"line":158,"column":null}},"55":{"start":{"line":158,"column":10},"end":{"line":158,"column":null}},"56":{"start":{"line":161,"column":8},"end":{"line":165,"column":null}},"57":{"start":{"line":162,"column":10},"end":{"line":162,"column":null}},"58":{"start":{"line":163,"column":10},"end":{"line":163,"column":null}},"59":{"start":{"line":164,"column":10},"end":{"line":164,"column":null}},"60":{"start":{"line":168,"column":8},"end":{"line":175,"column":null}},"61":{"start":{"line":172,"column":10},"end":{"line":172,"column":null}},"62":{"start":{"line":173,"column":10},"end":{"line":173,"column":null}},"63":{"start":{"line":174,"column":10},"end":{"line":174,"column":null}},"64":{"start":{"line":181,"column":4},"end":{"line":186,"column":null}},"65":{"start":{"line":182,"column":6},"end":{"line":185,"column":null}},"66":{"start":{"line":183,"column":29},"end":{"line":183,"column":null}},"67":{"start":{"line":184,"column":8},"end":{"line":184,"column":null}},"68":{"start":{"line":184,"column":36},"end":{"line":184,"column":51}},"69":{"start":{"line":189,"column":23},"end":{"line":189,"column":null}},"70":{"start":{"line":190,"column":26},"end":{"line":190,"column":null}},"71":{"start":{"line":191,"column":21},"end":{"line":191,"column":null}},"72":{"start":{"line":194,"column":24},"end":{"line":194,"column":null}},"73":{"start":{"line":195,"column":4},"end":{"line":198,"column":null}},"74":{"start":{"line":196,"column":19},"end":{"line":196,"column":null}},"75":{"start":{"line":197,"column":6},"end":{"line":197,"column":null}},"76":{"start":{"line":197,"column":16},"end":{"line":197,"column":null}},"77":{"start":{"line":200,"column":4},"end":{"line":210,"column":null}},"78":{"start":{"line":221,"column":17},"end":{"line":221,"column":null}},"79":{"start":{"line":222,"column":4},"end":{"line":222,"column":null}},"80":{"start":{"line":222,"column":15},"end":{"line":222,"column":null}},"81":{"start":{"line":225,"column":4},"end":{"line":233,"column":null}},"82":{"start":{"line":226,"column":6},"end":{"line":226,"column":null}},"83":{"start":{"line":226,"column":34},"end":{"line":226,"column":null}},"84":{"start":{"line":230,"column":6},"end":{"line":232,"column":null}},"85":{"start":{"line":231,"column":8},"end":{"line":231,"column":null}},"86":{"start":{"line":235,"column":4},"end":{"line":235,"column":null}},"87":{"start":{"line":247,"column":4},"end":{"line":268,"column":null}},"88":{"start":{"line":249,"column":6},"end":{"line":267,"column":null}},"89":{"start":{"line":254,"column":8},"end":{"line":259,"column":null}},"90":{"start":{"line":258,"column":10},"end":{"line":258,"column":null}},"91":{"start":{"line":262,"column":8},"end":{"line":266,"column":null}},"92":{"start":{"line":263,"column":10},"end":{"line":265,"column":null}},"93":{"start":{"line":264,"column":12},"end":{"line":264,"column":null}},"94":{"start":{"line":270,"column":4},"end":{"line":270,"column":null}},"95":{"start":{"line":277,"column":30},"end":{"line":277,"column":null}},"96":{"start":{"line":281,"column":27},"end":{"line":281,"column":null}},"97":{"start":{"line":282,"column":4},"end":{"line":284,"column":null}},"98":{"start":{"line":283,"column":6},"end":{"line":283,"column":null}},"99":{"start":{"line":287,"column":19},"end":{"line":287,"column":null}},"100":{"start":{"line":288,"column":4},"end":{"line":292,"column":null}},"101":{"start":{"line":289,"column":6},"end":{"line":291,"column":null}},"102":{"start":{"line":290,"column":8},"end":{"line":290,"column":null}},"103":{"start":{"line":294,"column":4},"end":{"line":294,"column":null}},"104":{"start":{"line":302,"column":16},"end":{"line":302,"column":null}},"105":{"start":{"line":303,"column":17},"end":{"line":303,"column":null}},"106":{"start":{"line":304,"column":4},"end":{"line":304,"column":null}},"107":{"start":{"line":313,"column":18},"end":{"line":313,"column":null}},"108":{"start":{"line":314,"column":25},"end":{"line":314,"column":null}},"109":{"start":{"line":315,"column":25},"end":{"line":315,"column":null}},"110":{"start":{"line":317,"column":4},"end":{"line":324,"column":null}},"111":{"start":{"line":318,"column":19},"end":{"line":318,"column":null}},"112":{"start":{"line":319,"column":6},"end":{"line":319,"column":null}},"113":{"start":{"line":319,"column":17},"end":{"line":319,"column":null}},"114":{"start":{"line":321,"column":6},"end":{"line":321,"column":null}},"115":{"start":{"line":321,"column":36},"end":{"line":321,"column":null}},"116":{"start":{"line":322,"column":6},"end":{"line":322,"column":null}},"117":{"start":{"line":322,"column":43},"end":{"line":322,"column":null}},"118":{"start":{"line":323,"column":6},"end":{"line":323,"column":null}},"119":{"start":{"line":323,"column":43},"end":{"line":323,"column":null}},"120":{"start":{"line":326,"column":4},"end":{"line":332,"column":null}},"121":{"start":{"line":331,"column":6},"end":{"line":331,"column":null}},"122":{"start":{"line":334,"column":4},"end":{"line":334,"column":null}},"123":{"start":{"line":341,"column":4},"end":{"line":341,"column":null}},"124":{"start":{"line":349,"column":4},"end":{"line":349,"column":null}},"125":{"start":{"line":351,"column":4},"end":{"line":351,"column":null}},"126":{"start":{"line":352,"column":4},"end":{"line":352,"column":null}},"127":{"start":{"line":353,"column":4},"end":{"line":353,"column":null}},"128":{"start":{"line":354,"column":4},"end":{"line":354,"column":null}},"129":{"start":{"line":356,"column":22},"end":{"line":356,"column":null}},"130":{"start":{"line":357,"column":4},"end":{"line":357,"column":null}},"131":{"start":{"line":371,"column":20},"end":{"line":371,"column":null}},"132":{"start":{"line":372,"column":27},"end":{"line":372,"column":null}},"133":{"start":{"line":373,"column":27},"end":{"line":373,"column":null}},"134":{"start":{"line":374,"column":19},"end":{"line":374,"column":null}},"135":{"start":{"line":375,"column":24},"end":{"line":375,"column":null}},"136":{"start":{"line":377,"column":4},"end":{"line":393,"column":null}},"137":{"start":{"line":378,"column":6},"end":{"line":391,"column":null}},"138":{"start":{"line":380,"column":10},"end":{"line":380,"column":null}},"139":{"start":{"line":381,"column":10},"end":{"line":381,"column":null}},"140":{"start":{"line":383,"column":10},"end":{"line":383,"column":null}},"141":{"start":{"line":384,"column":10},"end":{"line":384,"column":null}},"142":{"start":{"line":386,"column":10},"end":{"line":386,"column":null}},"143":{"start":{"line":387,"column":10},"end":{"line":387,"column":null}},"144":{"start":{"line":389,"column":10},"end":{"line":389,"column":null}},"145":{"start":{"line":390,"column":10},"end":{"line":390,"column":null}},"146":{"start":{"line":392,"column":6},"end":{"line":392,"column":null}},"147":{"start":{"line":395,"column":4},"end":{"line":403,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":41,"column":2},"end":{"line":41,"column":14}},"loc":{"start":{"line":41,"column":40},"end":{"line":46,"column":null}},"line":41},"1":{"name":"(anonymous_1)","decl":{"start":{"line":51,"column":10},"end":{"line":51,"column":40}},"loc":{"start":{"line":51,"column":40},"end":{"line":122,"column":null}},"line":51},"2":{"name":"(anonymous_2)","decl":{"start":{"line":63,"column":16},"end":{"line":63,"column":17}},"loc":{"start":{"line":63,"column":24},"end":{"line":63,"column":55}},"line":63},"3":{"name":"(anonymous_3)","decl":{"start":{"line":69,"column":18},"end":{"line":69,"column":19}},"loc":{"start":{"line":69,"column":25},"end":{"line":69,"column":43}},"line":69},"4":{"name":"(anonymous_4)","decl":{"start":{"line":83,"column":20},"end":{"line":83,"column":21}},"loc":{"start":{"line":83,"column":27},"end":{"line":83,"column":47}},"line":83},"5":{"name":"(anonymous_5)","decl":{"start":{"line":95,"column":61},"end":{"line":95,"column":62}},"loc":{"start":{"line":95,"column":68},"end":{"line":103,"column":7}},"line":95},"6":{"name":"(anonymous_6)","decl":{"start":{"line":98,"column":18},"end":{"line":98,"column":19}},"loc":{"start":{"line":98,"column":25},"end":{"line":98,"column":45}},"line":98},"7":{"name":"(anonymous_7)","decl":{"start":{"line":99,"column":25},"end":{"line":99,"column":26}},"loc":{"start":{"line":99,"column":32},"end":{"line":102,"column":9}},"line":99},"8":{"name":"(anonymous_8)","decl":{"start":{"line":105,"column":29},"end":{"line":105,"column":30}},"loc":{"start":{"line":105,"column":36},"end":{"line":105,"column":53}},"line":105},"9":{"name":"(anonymous_9)","decl":{"start":{"line":127,"column":10},"end":{"line":127,"column":null}},"loc":{"start":{"line":129,"column":52},"end":{"line":134,"column":null}},"line":129},"10":{"name":"(anonymous_10)","decl":{"start":{"line":139,"column":2},"end":{"line":139,"column":null}},"loc":{"start":{"line":143,"column":25},"end":{"line":211,"column":null}},"line":143},"11":{"name":"(anonymous_11)","decl":{"start":{"line":148,"column":47},"end":{"line":148,"column":48}},"loc":{"start":{"line":148,"column":54},"end":{"line":148,"column":75}},"line":148},"12":{"name":"(anonymous_12)","decl":{"start":{"line":184,"column":29},"end":{"line":184,"column":30}},"loc":{"start":{"line":184,"column":36},"end":{"line":184,"column":51}},"line":184},"13":{"name":"(anonymous_13)","decl":{"start":{"line":195,"column":21},"end":{"line":195,"column":22}},"loc":{"start":{"line":195,"column":31},"end":{"line":198,"column":5}},"line":195},"14":{"name":"(anonymous_14)","decl":{"start":{"line":216,"column":10},"end":{"line":216,"column":null}},"loc":{"start":{"line":220,"column":13},"end":{"line":236,"column":null}},"line":220},"15":{"name":"(anonymous_15)","decl":{"start":{"line":241,"column":10},"end":{"line":241,"column":null}},"loc":{"start":{"line":245,"column":13},"end":{"line":271,"column":null}},"line":245},"16":{"name":"(anonymous_16)","decl":{"start":{"line":276,"column":10},"end":{"line":276,"column":27}},"loc":{"start":{"line":276,"column":55},"end":{"line":295,"column":null}},"line":276},"17":{"name":"(anonymous_17)","decl":{"start":{"line":300,"column":10},"end":{"line":300,"column":28}},"loc":{"start":{"line":300,"column":56},"end":{"line":305,"column":null}},"line":300},"18":{"name":"(anonymous_18)","decl":{"start":{"line":310,"column":10},"end":{"line":310,"column":null}},"loc":{"start":{"line":312,"column":38},"end":{"line":335,"column":null}},"line":312},"19":{"name":"(anonymous_19)","decl":{"start":{"line":340,"column":10},"end":{"line":340,"column":24}},"loc":{"start":{"line":340,"column":50},"end":{"line":342,"column":null}},"line":340},"20":{"name":"(anonymous_20)","decl":{"start":{"line":348,"column":2},"end":{"line":348,"column":9}},"loc":{"start":{"line":348,"column":61},"end":{"line":358,"column":null}},"line":348},"21":{"name":"(anonymous_21)","decl":{"start":{"line":363,"column":2},"end":{"line":363,"column":null}},"loc":{"start":{"line":370,"column":4},"end":{"line":404,"column":null}},"line":370}},"branchMap":{"0":{"loc":{"start":{"line":73,"column":10},"end":{"line":73,"column":null}},"type":"if","locations":[{"start":{"line":73,"column":10},"end":{"line":73,"column":null}},{"start":{},"end":{}}],"line":73},"1":{"loc":{"start":{"line":76,"column":10},"end":{"line":78,"column":null}},"type":"if","locations":[{"start":{"line":76,"column":10},"end":{"line":78,"column":null}},{"start":{},"end":{}}],"line":76},"2":{"loc":{"start":{"line":86,"column":12},"end":{"line":88,"column":null}},"type":"if","locations":[{"start":{"line":86,"column":12},"end":{"line":88,"column":null}},{"start":{},"end":{}}],"line":86},"3":{"loc":{"start":{"line":86,"column":16},"end":{"line":86,"column":56}},"type":"binary-expr","locations":[{"start":{"line":86,"column":16},"end":{"line":86,"column":28}},{"start":{"line":86,"column":28},"end":{"line":86,"column":56}}],"line":86},"4":{"loc":{"start":{"line":101,"column":17},"end":{"line":101,"column":null}},"type":"binary-expr","locations":[{"start":{"line":101,"column":17},"end":{"line":101,"column":24}},{"start":{"line":101,"column":24},"end":{"line":101,"column":null}}],"line":101},"5":{"loc":{"start":{"line":118,"column":18},"end":{"line":118,"column":null}},"type":"binary-expr","locations":[{"start":{"line":118,"column":18},"end":{"line":118,"column":50}},{"start":{"line":118,"column":50},"end":{"line":118,"column":null}}],"line":118},"6":{"loc":{"start":{"line":119,"column":16},"end":{"line":119,"column":null}},"type":"binary-expr","locations":[{"start":{"line":119,"column":16},"end":{"line":119,"column":47}},{"start":{"line":119,"column":47},"end":{"line":119,"column":null}}],"line":119},"7":{"loc":{"start":{"line":130,"column":4},"end":{"line":130,"column":null}},"type":"if","locations":[{"start":{"line":130,"column":4},"end":{"line":130,"column":null}},{"start":{},"end":{}}],"line":130},"8":{"loc":{"start":{"line":131,"column":4},"end":{"line":131,"column":null}},"type":"if","locations":[{"start":{"line":131,"column":4},"end":{"line":131,"column":null}},{"start":{},"end":{}}],"line":131},"9":{"loc":{"start":{"line":132,"column":4},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":132,"column":4},"end":{"line":132,"column":null}},{"start":{},"end":{}}],"line":132},"10":{"loc":{"start":{"line":141,"column":4},"end":{"line":141,"column":null}},"type":"default-arg","locations":[{"start":{"line":141,"column":25},"end":{"line":141,"column":null}}],"line":141},"11":{"loc":{"start":{"line":142,"column":4},"end":{"line":142,"column":null}},"type":"default-arg","locations":[{"start":{"line":142,"column":12},"end":{"line":142,"column":null}}],"line":142},"12":{"loc":{"start":{"line":154,"column":8},"end":{"line":154,"column":null}},"type":"if","locations":[{"start":{"line":154,"column":8},"end":{"line":154,"column":null}},{"start":{},"end":{}}],"line":154},"13":{"loc":{"start":{"line":157,"column":8},"end":{"line":158,"column":null}},"type":"if","locations":[{"start":{"line":157,"column":8},"end":{"line":158,"column":null}},{"start":{},"end":{}}],"line":157},"14":{"loc":{"start":{"line":157,"column":12},"end":{"line":157,"column":null}},"type":"binary-expr","locations":[{"start":{"line":157,"column":12},"end":{"line":157,"column":35}},{"start":{"line":157,"column":35},"end":{"line":157,"column":null}}],"line":157},"15":{"loc":{"start":{"line":161,"column":8},"end":{"line":165,"column":null}},"type":"if","locations":[{"start":{"line":161,"column":8},"end":{"line":165,"column":null}},{"start":{},"end":{}}],"line":161},"16":{"loc":{"start":{"line":168,"column":8},"end":{"line":175,"column":null}},"type":"if","locations":[{"start":{"line":168,"column":8},"end":{"line":175,"column":null}},{"start":{},"end":{}}],"line":168},"17":{"loc":{"start":{"line":169,"column":10},"end":{"line":170,"column":null}},"type":"binary-expr","locations":[{"start":{"line":169,"column":10},"end":{"line":169,"column":null}},{"start":{"line":170,"column":10},"end":{"line":170,"column":null}}],"line":169},"18":{"loc":{"start":{"line":181,"column":4},"end":{"line":186,"column":null}},"type":"if","locations":[{"start":{"line":181,"column":4},"end":{"line":186,"column":null}},{"start":{},"end":{}}],"line":181},"19":{"loc":{"start":{"line":191,"column":21},"end":{"line":191,"column":null}},"type":"cond-expr","locations":[{"start":{"line":191,"column":39},"end":{"line":191,"column":75}},{"start":{"line":191,"column":75},"end":{"line":191,"column":null}}],"line":191},"20":{"loc":{"start":{"line":197,"column":6},"end":{"line":197,"column":null}},"type":"if","locations":[{"start":{"line":197,"column":6},"end":{"line":197,"column":null}},{"start":{},"end":{}}],"line":197},"21":{"loc":{"start":{"line":222,"column":4},"end":{"line":222,"column":null}},"type":"if","locations":[{"start":{"line":222,"column":4},"end":{"line":222,"column":null}},{"start":{},"end":{}}],"line":222},"22":{"loc":{"start":{"line":226,"column":6},"end":{"line":226,"column":null}},"type":"if","locations":[{"start":{"line":226,"column":6},"end":{"line":226,"column":null}},{"start":{},"end":{}}],"line":226},"23":{"loc":{"start":{"line":230,"column":6},"end":{"line":232,"column":null}},"type":"if","locations":[{"start":{"line":230,"column":6},"end":{"line":232,"column":null}},{"start":{},"end":{}}],"line":230},"24":{"loc":{"start":{"line":230,"column":10},"end":{"line":230,"column":98}},"type":"binary-expr","locations":[{"start":{"line":230,"column":10},"end":{"line":230,"column":32}},{"start":{"line":230,"column":32},"end":{"line":230,"column":98}}],"line":230},"25":{"loc":{"start":{"line":249,"column":6},"end":{"line":267,"column":null}},"type":"if","locations":[{"start":{"line":249,"column":6},"end":{"line":267,"column":null}},{"start":{},"end":{}}],"line":249},"26":{"loc":{"start":{"line":250,"column":8},"end":{"line":251,"column":null}},"type":"binary-expr","locations":[{"start":{"line":250,"column":8},"end":{"line":250,"column":null}},{"start":{"line":251,"column":8},"end":{"line":251,"column":null}}],"line":250},"27":{"loc":{"start":{"line":254,"column":8},"end":{"line":259,"column":null}},"type":"if","locations":[{"start":{"line":254,"column":8},"end":{"line":259,"column":null}},{"start":{},"end":{}}],"line":254},"28":{"loc":{"start":{"line":255,"column":10},"end":{"line":256,"column":null}},"type":"binary-expr","locations":[{"start":{"line":255,"column":10},"end":{"line":255,"column":null}},{"start":{"line":256,"column":10},"end":{"line":256,"column":null}}],"line":255},"29":{"loc":{"start":{"line":262,"column":8},"end":{"line":266,"column":null}},"type":"if","locations":[{"start":{"line":262,"column":8},"end":{"line":266,"column":null}},{"start":{},"end":{}}],"line":262},"30":{"loc":{"start":{"line":263,"column":10},"end":{"line":265,"column":null}},"type":"if","locations":[{"start":{"line":263,"column":10},"end":{"line":265,"column":null}},{"start":{},"end":{}}],"line":263},"31":{"loc":{"start":{"line":282,"column":4},"end":{"line":284,"column":null}},"type":"if","locations":[{"start":{"line":282,"column":4},"end":{"line":284,"column":null}},{"start":{},"end":{}}],"line":282},"32":{"loc":{"start":{"line":289,"column":6},"end":{"line":291,"column":null}},"type":"if","locations":[{"start":{"line":289,"column":6},"end":{"line":291,"column":null}},{"start":{},"end":{}}],"line":289},"33":{"loc":{"start":{"line":289,"column":10},"end":{"line":289,"column":68}},"type":"binary-expr","locations":[{"start":{"line":289,"column":10},"end":{"line":289,"column":39}},{"start":{"line":289,"column":39},"end":{"line":289,"column":68}}],"line":289},"34":{"loc":{"start":{"line":319,"column":6},"end":{"line":319,"column":null}},"type":"if","locations":[{"start":{"line":319,"column":6},"end":{"line":319,"column":null}},{"start":{},"end":{}}],"line":319},"35":{"loc":{"start":{"line":321,"column":6},"end":{"line":321,"column":null}},"type":"if","locations":[{"start":{"line":321,"column":6},"end":{"line":321,"column":null}},{"start":{},"end":{}}],"line":321},"36":{"loc":{"start":{"line":322,"column":6},"end":{"line":322,"column":null}},"type":"if","locations":[{"start":{"line":322,"column":6},"end":{"line":322,"column":null}},{"start":{},"end":{}}],"line":322},"37":{"loc":{"start":{"line":323,"column":6},"end":{"line":323,"column":null}},"type":"if","locations":[{"start":{"line":323,"column":6},"end":{"line":323,"column":null}},{"start":{},"end":{}}],"line":323},"38":{"loc":{"start":{"line":326,"column":4},"end":{"line":332,"column":null}},"type":"if","locations":[{"start":{"line":326,"column":4},"end":{"line":332,"column":null}},{"start":{},"end":{}}],"line":326},"39":{"loc":{"start":{"line":326,"column":4},"end":{"line":329,"column":null}},"type":"binary-expr","locations":[{"start":{"line":327,"column":7},"end":{"line":327,"column":18}},{"start":{"line":327,"column":18},"end":{"line":327,"column":36}},{"start":{"line":327,"column":36},"end":{"line":327,"column":null}},{"start":{"line":327,"column":36},"end":{"line":329,"column":null}}],"line":326},"40":{"loc":{"start":{"line":328,"column":7},"end":{"line":328,"column":27}},"type":"cond-expr","locations":[{"start":{"line":328,"column":17},"end":{"line":328,"column":21}},{"start":{"line":328,"column":21},"end":{"line":328,"column":27}}],"line":328},"41":{"loc":{"start":{"line":328,"column":27},"end":{"line":328,"column":54}},"type":"cond-expr","locations":[{"start":{"line":328,"column":44},"end":{"line":328,"column":48}},{"start":{"line":328,"column":48},"end":{"line":328,"column":54}}],"line":328},"42":{"loc":{"start":{"line":328,"column":54},"end":{"line":328,"column":null}},"type":"cond-expr","locations":[{"start":{"line":328,"column":71},"end":{"line":328,"column":75}},{"start":{"line":328,"column":75},"end":{"line":328,"column":null}}],"line":328},"43":{"loc":{"start":{"line":334,"column":11},"end":{"line":334,"column":null}},"type":"cond-expr","locations":[{"start":{"line":334,"column":28},"end":{"line":334,"column":44}},{"start":{"line":334,"column":44},"end":{"line":334,"column":null}}],"line":334},"44":{"loc":{"start":{"line":378,"column":6},"end":{"line":391,"column":null}},"type":"switch","locations":[{"start":{"line":379,"column":8},"end":{"line":381,"column":null}},{"start":{"line":382,"column":8},"end":{"line":384,"column":null}},{"start":{"line":385,"column":8},"end":{"line":387,"column":null}},{"start":{"line":388,"column":8},"end":{"line":390,"column":null}}],"line":378},"45":{"loc":{"start":{"line":402,"column":8},"end":{"line":402,"column":null}},"type":"cond-expr","locations":[{"start":{"line":402,"column":32},"end":{"line":402,"column":68}},{"start":{"line":402,"column":68},"end":{"line":402,"column":null}}],"line":402}},"s":{"0":57,"1":57,"2":57,"3":57,"4":66,"5":66,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":9,"125":9,"126":9,"127":9,"128":9,"129":9,"130":9,"131":0,"132":0,"133":0,"134":0,"135":0,"136":0,"137":0,"138":0,"139":0,"140":0,"141":0,"142":0,"143":0,"144":0,"145":0,"146":0,"147":0},"f":{"0":57,"1":66,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":9,"21":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0],"11":[0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[0,0,0,0],"40":[0,0],"41":[0,0],"42":[0,0],"43":[0,0],"44":[0,0,0,0],"45":[0,0]},"meta":{"lastBranch":46,"lastFunction":22,"lastStatement":148,"seen":{"f:41:2:41:14":0,"s:42:4:42:Infinity":0,"s:43:4:43:Infinity":1,"s:44:4:44:Infinity":2,"s:45:4:45:Infinity":3,"f:51:10:51:40":1,"s:52:23:52:Infinity":4,"s:54:4:121:Infinity":5,"s:55:23:55:Infinity":6,"s:56:31:56:Infinity":7,"s:57:33:57:Infinity":8,"s:58:33:58:Infinity":9,"s:61:24:63:Infinity":10,"f:63:16:63:17":2,"s:63:24:63:55":11,"s:66:6:91:Infinity":12,"s:67:26:69:Infinity":13,"f:69:18:69:19":3,"s:69:25:69:43":14,"s:71:8:90:Infinity":15,"s:72:32:72:Infinity":16,"b:73:10:73:Infinity:undefined:undefined:undefined:undefined":0,"s:73:10:73:Infinity":17,"s:73:30:73:Infinity":18,"b:76:10:78:Infinity:undefined:undefined:undefined:undefined":1,"s:76:10:78:Infinity":19,"s:77:12:77:Infinity":20,"s:81:29:83:Infinity":21,"f:83:20:83:21":4,"s:83:27:83:47":22,"s:84:10:89:Infinity":23,"s:85:29:85:Infinity":24,"b:86:12:88:Infinity:undefined:undefined:undefined:undefined":2,"s:86:12:88:Infinity":25,"b:86:16:86:28:86:28:86:56":3,"s:87:14:87:Infinity":26,"s:95:20:103:Infinity":27,"f:95:61:95:62":5,"s:96:21:98:Infinity":28,"f:98:18:98:19":6,"s:98:25:98:45":29,"s:99:8:102:Infinity":30,"f:99:25:99:26":7,"s:100:22:100:Infinity":31,"s:101:10:101:Infinity":32,"b:101:17:101:24:101:24:101:Infinity":4,"s:105:6:105:Infinity":33,"f:105:29:105:30":8,"s:105:36:105:53":34,"s:107:6:111:Infinity":35,"s:114:23:114:Infinity":36,"s:115:6:120:Infinity":37,"b:118:18:118:50:118:50:118:Infinity":5,"b:119:16:119:47:119:47:119:Infinity":6,"f:127:10:127:Infinity":9,"b:130:4:130:Infinity:undefined:undefined:undefined:undefined":7,"s:130:4:130:Infinity":38,"s:130:49:130:Infinity":39,"b:131:4:131:Infinity:undefined:undefined:undefined:undefined":8,"s:131:4:131:Infinity":40,"s:131:49:131:Infinity":41,"b:132:4:132:Infinity:undefined:undefined:undefined:undefined":9,"s:132:4:132:Infinity":42,"s:132:36:132:Infinity":43,"s:133:4:133:Infinity":44,"f:139:2:139:Infinity":10,"b:141:25:141:Infinity":10,"b:142:12:142:Infinity":11,"s:144:21:144:Infinity":45,"s:145:28:145:Infinity":46,"s:148:30:148:Infinity":47,"f:148:47:148:48":11,"s:148:54:148:75":48,"s:151:4:177:Infinity":49,"s:152:6:176:Infinity":50,"s:153:25:153:Infinity":51,"b:154:8:154:Infinity:undefined:undefined:undefined:undefined":12,"s:154:8:154:Infinity":52,"s:154:23:154:Infinity":53,"b:157:8:158:Infinity:undefined:undefined:undefined:undefined":13,"s:157:8:158:Infinity":54,"b:157:12:157:35:157:35:157:Infinity":14,"s:158:10:158:Infinity":55,"b:161:8:165:Infinity:undefined:undefined:undefined:undefined":15,"s:161:8:165:Infinity":56,"s:162:10:162:Infinity":57,"s:163:10:163:Infinity":58,"s:164:10:164:Infinity":59,"b:168:8:175:Infinity:undefined:undefined:undefined:undefined":16,"s:168:8:175:Infinity":60,"b:169:10:169:Infinity:170:10:170:Infinity":17,"s:172:10:172:Infinity":61,"s:173:10:173:Infinity":62,"s:174:10:174:Infinity":63,"b:181:4:186:Infinity:undefined:undefined:undefined:undefined":18,"s:181:4:186:Infinity":64,"s:182:6:185:Infinity":65,"s:183:29:183:Infinity":66,"s:184:8:184:Infinity":67,"f:184:29:184:30":12,"s:184:36:184:51":68,"s:189:23:189:Infinity":69,"s:190:26:190:Infinity":70,"s:191:21:191:Infinity":71,"b:191:39:191:75:191:75:191:Infinity":19,"s:194:24:194:Infinity":72,"s:195:4:198:Infinity":73,"f:195:21:195:22":13,"s:196:19:196:Infinity":74,"b:197:6:197:Infinity:undefined:undefined:undefined:undefined":20,"s:197:6:197:Infinity":75,"s:197:16:197:Infinity":76,"s:200:4:210:Infinity":77,"f:216:10:216:Infinity":14,"s:221:17:221:Infinity":78,"b:222:4:222:Infinity:undefined:undefined:undefined:undefined":21,"s:222:4:222:Infinity":79,"s:222:15:222:Infinity":80,"s:225:4:233:Infinity":81,"b:226:6:226:Infinity:undefined:undefined:undefined:undefined":22,"s:226:6:226:Infinity":82,"s:226:34:226:Infinity":83,"b:230:6:232:Infinity:undefined:undefined:undefined:undefined":23,"s:230:6:232:Infinity":84,"b:230:10:230:32:230:32:230:98":24,"s:231:8:231:Infinity":85,"s:235:4:235:Infinity":86,"f:241:10:241:Infinity":15,"s:247:4:268:Infinity":87,"b:249:6:267:Infinity:undefined:undefined:undefined:undefined":25,"s:249:6:267:Infinity":88,"b:250:8:250:Infinity:251:8:251:Infinity":26,"b:254:8:259:Infinity:undefined:undefined:undefined:undefined":27,"s:254:8:259:Infinity":89,"b:255:10:255:Infinity:256:10:256:Infinity":28,"s:258:10:258:Infinity":90,"b:262:8:266:Infinity:undefined:undefined:undefined:undefined":29,"s:262:8:266:Infinity":91,"b:263:10:265:Infinity:undefined:undefined:undefined:undefined":30,"s:263:10:265:Infinity":92,"s:264:12:264:Infinity":93,"s:270:4:270:Infinity":94,"f:276:10:276:27":16,"s:277:30:277:Infinity":95,"s:281:27:281:Infinity":96,"b:282:4:284:Infinity:undefined:undefined:undefined:undefined":31,"s:282:4:284:Infinity":97,"s:283:6:283:Infinity":98,"s:287:19:287:Infinity":99,"s:288:4:292:Infinity":100,"b:289:6:291:Infinity:undefined:undefined:undefined:undefined":32,"s:289:6:291:Infinity":101,"b:289:10:289:39:289:39:289:68":33,"s:290:8:290:Infinity":102,"s:294:4:294:Infinity":103,"f:300:10:300:28":17,"s:302:16:302:Infinity":104,"s:303:17:303:Infinity":105,"s:304:4:304:Infinity":106,"f:310:10:310:Infinity":18,"s:313:18:313:Infinity":107,"s:314:25:314:Infinity":108,"s:315:25:315:Infinity":109,"s:317:4:324:Infinity":110,"s:318:19:318:Infinity":111,"b:319:6:319:Infinity:undefined:undefined:undefined:undefined":34,"s:319:6:319:Infinity":112,"s:319:17:319:Infinity":113,"b:321:6:321:Infinity:undefined:undefined:undefined:undefined":35,"s:321:6:321:Infinity":114,"s:321:36:321:Infinity":115,"b:322:6:322:Infinity:undefined:undefined:undefined:undefined":36,"s:322:6:322:Infinity":116,"s:322:43:322:Infinity":117,"b:323:6:323:Infinity:undefined:undefined:undefined:undefined":37,"s:323:6:323:Infinity":118,"s:323:43:323:Infinity":119,"b:326:4:332:Infinity:undefined:undefined:undefined:undefined":38,"s:326:4:332:Infinity":120,"b:327:7:327:18:327:18:327:36:327:36:327:Infinity:327:36:329:Infinity":39,"b:328:17:328:21:328:21:328:27":40,"b:328:44:328:48:328:48:328:54":41,"b:328:71:328:75:328:75:328:Infinity":42,"s:331:6:331:Infinity":121,"s:334:4:334:Infinity":122,"b:334:28:334:44:334:44:334:Infinity":43,"f:340:10:340:24":19,"s:341:4:341:Infinity":123,"f:348:2:348:9":20,"s:349:4:349:Infinity":124,"s:351:4:351:Infinity":125,"s:352:4:352:Infinity":126,"s:353:4:353:Infinity":127,"s:354:4:354:Infinity":128,"s:356:22:356:Infinity":129,"s:357:4:357:Infinity":130,"f:363:2:363:Infinity":21,"s:371:20:371:Infinity":131,"s:372:27:372:Infinity":132,"s:373:27:373:Infinity":133,"s:374:19:374:Infinity":134,"s:375:24:375:Infinity":135,"s:377:4:393:Infinity":136,"b:379:8:381:Infinity:382:8:384:Infinity:385:8:387:Infinity:388:8:390:Infinity":44,"s:378:6:391:Infinity":137,"s:380:10:380:Infinity":138,"s:381:10:381:Infinity":139,"s:383:10:383:Infinity":140,"s:384:10:384:Infinity":141,"s:386:10:386:Infinity":142,"s:387:10:387:Infinity":143,"s:389:10:389:Infinity":144,"s:390:10:390:Infinity":145,"s:392:6:392:Infinity":146,"s:395:4:403:Infinity":147,"b:402:32:402:68:402:68:402:Infinity":45}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/graph/builder.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/graph/builder.ts","statementMap":{"0":{"start":{"line":74,"column":42},"end":{"line":74,"column":null}},"1":{"start":{"line":75,"column":27},"end":{"line":75,"column":null}},"2":{"start":{"line":87,"column":4},"end":{"line":88,"column":null}},"3":{"start":{"line":89,"column":4},"end":{"line":90,"column":null}},"4":{"start":{"line":91,"column":4},"end":{"line":91,"column":null}},"5":{"start":{"line":92,"column":4},"end":{"line":92,"column":null}},"6":{"start":{"line":96,"column":4},"end":{"line":96,"column":null}},"7":{"start":{"line":113,"column":18},"end":{"line":113,"column":null}},"8":{"start":{"line":114,"column":4},"end":{"line":114,"column":null}},"9":{"start":{"line":114,"column":25},"end":{"line":114,"column":null}},"10":{"start":{"line":115,"column":4},"end":{"line":115,"column":null}},"11":{"start":{"line":115,"column":26},"end":{"line":115,"column":null}},"12":{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},"13":{"start":{"line":117,"column":19},"end":{"line":117,"column":null}},"14":{"start":{"line":118,"column":4},"end":{"line":118,"column":null}},"15":{"start":{"line":123,"column":6},"end":{"line":124,"column":null}},"16":{"start":{"line":125,"column":4},"end":{"line":125,"column":null}},"17":{"start":{"line":129,"column":4},"end":{"line":129,"column":null}},"18":{"start":{"line":133,"column":4},"end":{"line":133,"column":null}},"19":{"start":{"line":137,"column":4},"end":{"line":137,"column":null}},"20":{"start":{"line":138,"column":4},"end":{"line":138,"column":null}},"21":{"start":{"line":141,"column":4},"end":{"line":141,"column":null}},"22":{"start":{"line":144,"column":4},"end":{"line":146,"column":null}},"23":{"start":{"line":145,"column":6},"end":{"line":145,"column":null}},"24":{"start":{"line":149,"column":4},"end":{"line":149,"column":null}},"25":{"start":{"line":149,"column":40},"end":{"line":149,"column":77}},"26":{"start":{"line":152,"column":4},"end":{"line":154,"column":null}},"27":{"start":{"line":153,"column":6},"end":{"line":153,"column":null}},"28":{"start":{"line":157,"column":4},"end":{"line":159,"column":null}},"29":{"start":{"line":158,"column":6},"end":{"line":158,"column":null}},"30":{"start":{"line":162,"column":4},"end":{"line":164,"column":null}},"31":{"start":{"line":163,"column":6},"end":{"line":163,"column":null}},"32":{"start":{"line":167,"column":4},"end":{"line":167,"column":null}},"33":{"start":{"line":169,"column":4},"end":{"line":169,"column":null}},"34":{"start":{"line":174,"column":6},"end":{"line":175,"column":null}},"35":{"start":{"line":176,"column":19},"end":{"line":176,"column":null}},"36":{"start":{"line":177,"column":4},"end":{"line":177,"column":null}},"37":{"start":{"line":177,"column":41},"end":{"line":177,"column":null}},"38":{"start":{"line":178,"column":4},"end":{"line":178,"column":null}},"39":{"start":{"line":180,"column":39},"end":{"line":214,"column":null}},"40":{"start":{"line":215,"column":4},"end":{"line":215,"column":null}},"41":{"start":{"line":218,"column":23},"end":{"line":218,"column":null}},"42":{"start":{"line":219,"column":4},"end":{"line":219,"column":null}},"43":{"start":{"line":222,"column":4},"end":{"line":236,"column":null}},"44":{"start":{"line":240,"column":19},"end":{"line":240,"column":null}},"45":{"start":{"line":241,"column":4},"end":{"line":241,"column":null}},"46":{"start":{"line":241,"column":41},"end":{"line":241,"column":null}},"47":{"start":{"line":242,"column":4},"end":{"line":242,"column":null}},"48":{"start":{"line":244,"column":4},"end":{"line":257,"column":null}},"49":{"start":{"line":259,"column":23},"end":{"line":259,"column":null}},"50":{"start":{"line":260,"column":4},"end":{"line":275,"column":null}},"51":{"start":{"line":261,"column":6},"end":{"line":261,"column":null}},"52":{"start":{"line":264,"column":6},"end":{"line":274,"column":null}},"53":{"start":{"line":279,"column":19},"end":{"line":281,"column":null}},"54":{"start":{"line":282,"column":4},"end":{"line":282,"column":null}},"55":{"start":{"line":282,"column":41},"end":{"line":282,"column":null}},"56":{"start":{"line":283,"column":4},"end":{"line":283,"column":null}},"57":{"start":{"line":285,"column":4},"end":{"line":324,"column":null}},"58":{"start":{"line":327,"column":4},"end":{"line":337,"column":null}},"59":{"start":{"line":340,"column":4},"end":{"line":348,"column":null}},"60":{"start":{"line":341,"column":6},"end":{"line":347,"column":null}},"61":{"start":{"line":352,"column":19},"end":{"line":352,"column":null}},"62":{"start":{"line":353,"column":4},"end":{"line":353,"column":null}},"63":{"start":{"line":353,"column":41},"end":{"line":353,"column":null}},"64":{"start":{"line":354,"column":4},"end":{"line":354,"column":null}},"65":{"start":{"line":356,"column":4},"end":{"line":387,"column":null}},"66":{"start":{"line":390,"column":4},"end":{"line":400,"column":null}},"67":{"start":{"line":403,"column":4},"end":{"line":419,"column":null}},"68":{"start":{"line":404,"column":6},"end":{"line":418,"column":null}},"69":{"start":{"line":422,"column":4},"end":{"line":440,"column":null}},"70":{"start":{"line":423,"column":6},"end":{"line":439,"column":null}},"71":{"start":{"line":424,"column":8},"end":{"line":438,"column":null}},"72":{"start":{"line":442,"column":4},"end":{"line":450,"column":null}},"73":{"start":{"line":443,"column":6},"end":{"line":449,"column":null}},"74":{"start":{"line":454,"column":19},"end":{"line":454,"column":null}},"75":{"start":{"line":455,"column":4},"end":{"line":455,"column":null}},"76":{"start":{"line":455,"column":41},"end":{"line":455,"column":null}},"77":{"start":{"line":456,"column":4},"end":{"line":456,"column":null}},"78":{"start":{"line":458,"column":4},"end":{"line":475,"column":null}},"79":{"start":{"line":478,"column":4},"end":{"line":488,"column":null}},"80":{"start":{"line":492,"column":19},"end":{"line":492,"column":null}},"81":{"start":{"line":493,"column":4},"end":{"line":493,"column":null}},"82":{"start":{"line":493,"column":41},"end":{"line":493,"column":null}},"83":{"start":{"line":494,"column":4},"end":{"line":494,"column":null}},"84":{"start":{"line":496,"column":4},"end":{"line":521,"column":null}},"85":{"start":{"line":524,"column":4},"end":{"line":534,"column":null}},"86":{"start":{"line":537,"column":25},"end":{"line":540,"column":null}},"87":{"start":{"line":541,"column":4},"end":{"line":558,"column":null}},"88":{"start":{"line":542,"column":6},"end":{"line":557,"column":null}},"89":{"start":{"line":562,"column":19},"end":{"line":562,"column":null}},"90":{"start":{"line":563,"column":4},"end":{"line":563,"column":null}},"91":{"start":{"line":563,"column":41},"end":{"line":563,"column":null}},"92":{"start":{"line":564,"column":4},"end":{"line":564,"column":null}},"93":{"start":{"line":566,"column":4},"end":{"line":581,"column":null}},"94":{"start":{"line":584,"column":4},"end":{"line":594,"column":null}},"95":{"start":{"line":598,"column":23},"end":{"line":598,"column":null}},"96":{"start":{"line":599,"column":22},"end":{"line":599,"column":null}},"97":{"start":{"line":600,"column":4},"end":{"line":600,"column":null}},"98":{"start":{"line":600,"column":59},"end":{"line":600,"column":null}},"99":{"start":{"line":603,"column":6},"end":{"line":604,"column":null}},"100":{"start":{"line":607,"column":4},"end":{"line":648,"column":null}},"101":{"start":{"line":608,"column":21},"end":{"line":608,"column":null}},"102":{"start":{"line":609,"column":6},"end":{"line":609,"column":null}},"103":{"start":{"line":609,"column":43},"end":{"line":609,"column":null}},"104":{"start":{"line":610,"column":6},"end":{"line":610,"column":null}},"105":{"start":{"line":613,"column":6},"end":{"line":634,"column":null}},"106":{"start":{"line":637,"column":6},"end":{"line":647,"column":null}},"107":{"start":{"line":651,"column":4},"end":{"line":704,"column":null}},"108":{"start":{"line":652,"column":21},"end":{"line":652,"column":null}},"109":{"start":{"line":653,"column":6},"end":{"line":653,"column":null}},"110":{"start":{"line":653,"column":43},"end":{"line":653,"column":null}},"111":{"start":{"line":654,"column":6},"end":{"line":654,"column":null}},"112":{"start":{"line":657,"column":6},"end":{"line":674,"column":null}},"113":{"start":{"line":677,"column":6},"end":{"line":690,"column":null}},"114":{"start":{"line":678,"column":29},"end":{"line":678,"column":null}},"115":{"start":{"line":679,"column":8},"end":{"line":689,"column":null}},"116":{"start":{"line":693,"column":6},"end":{"line":703,"column":null}},"117":{"start":{"line":708,"column":4},"end":{"line":708,"column":null}},"118":{"start":{"line":708,"column":33},"end":{"line":708,"column":null}},"119":{"start":{"line":709,"column":17},"end":{"line":709,"column":null}},"120":{"start":{"line":710,"column":23},"end":{"line":715,"column":null}},"121":{"start":{"line":716,"column":4},"end":{"line":720,"column":null}},"122":{"start":{"line":717,"column":6},"end":{"line":719,"column":null}},"123":{"start":{"line":718,"column":8},"end":{"line":718,"column":null}},"124":{"start":{"line":721,"column":4},"end":{"line":721,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":81,"column":2},"end":{"line":81,"column":null}},"loc":{"start":{"line":86,"column":4},"end":{"line":93,"column":null}},"line":86},"1":{"name":"(anonymous_1)","decl":{"start":{"line":95,"column":10},"end":{"line":95,"column":19}},"loc":{"start":{"line":95,"column":42},"end":{"line":97,"column":null}},"line":95},"2":{"name":"(anonymous_2)","decl":{"start":{"line":107,"column":10},"end":{"line":107,"column":null}},"loc":{"start":{"line":112,"column":12},"end":{"line":119,"column":null}},"line":112},"3":{"name":"(anonymous_3)","decl":{"start":{"line":121,"column":10},"end":{"line":121,"column":21}},"loc":{"start":{"line":121,"column":53},"end":{"line":126,"column":null}},"line":121},"4":{"name":"(anonymous_4)","decl":{"start":{"line":128,"column":10},"end":{"line":128,"column":33}},"loc":{"start":{"line":128,"column":63},"end":{"line":130,"column":null}},"line":128},"5":{"name":"(anonymous_5)","decl":{"start":{"line":132,"column":10},"end":{"line":132,"column":23}},"loc":{"start":{"line":132,"column":51},"end":{"line":134,"column":null}},"line":132},"6":{"name":"(anonymous_6)","decl":{"start":{"line":136,"column":2},"end":{"line":136,"column":22}},"loc":{"start":{"line":136,"column":65},"end":{"line":170,"column":null}},"line":136},"7":{"name":"(anonymous_7)","decl":{"start":{"line":144,"column":33},"end":{"line":144,"column":34}},"loc":{"start":{"line":145,"column":6},"end":{"line":145,"column":null}},"line":145},"8":{"name":"(anonymous_8)","decl":{"start":{"line":149,"column":31},"end":{"line":149,"column":32}},"loc":{"start":{"line":149,"column":40},"end":{"line":149,"column":77}},"line":149},"9":{"name":"(anonymous_9)","decl":{"start":{"line":152,"column":34},"end":{"line":152,"column":35}},"loc":{"start":{"line":153,"column":6},"end":{"line":153,"column":null}},"line":153},"10":{"name":"(anonymous_10)","decl":{"start":{"line":157,"column":32},"end":{"line":157,"column":33}},"loc":{"start":{"line":158,"column":6},"end":{"line":158,"column":null}},"line":158},"11":{"name":"(anonymous_11)","decl":{"start":{"line":162,"column":32},"end":{"line":162,"column":33}},"loc":{"start":{"line":163,"column":6},"end":{"line":163,"column":null}},"line":163},"12":{"name":"(anonymous_12)","decl":{"start":{"line":172,"column":10},"end":{"line":172,"column":25}},"loc":{"start":{"line":172,"column":55},"end":{"line":237,"column":null}},"line":172},"13":{"name":"(anonymous_13)","decl":{"start":{"line":239,"column":10},"end":{"line":239,"column":32}},"loc":{"start":{"line":239,"column":58},"end":{"line":276,"column":null}},"line":239},"14":{"name":"(anonymous_14)","decl":{"start":{"line":278,"column":10},"end":{"line":278,"column":29}},"loc":{"start":{"line":278,"column":77},"end":{"line":349,"column":null}},"line":278},"15":{"name":"(anonymous_15)","decl":{"start":{"line":351,"column":10},"end":{"line":351,"column":26}},"loc":{"start":{"line":351,"column":72},"end":{"line":451,"column":null}},"line":351},"16":{"name":"(anonymous_16)","decl":{"start":{"line":423,"column":29},"end":{"line":423,"column":30}},"loc":{"start":{"line":423,"column":39},"end":{"line":439,"column":7}},"line":423},"17":{"name":"(anonymous_17)","decl":{"start":{"line":453,"column":10},"end":{"line":453,"column":29}},"loc":{"start":{"line":453,"column":74},"end":{"line":489,"column":null}},"line":453},"18":{"name":"(anonymous_18)","decl":{"start":{"line":491,"column":10},"end":{"line":491,"column":27}},"loc":{"start":{"line":491,"column":67},"end":{"line":559,"column":null}},"line":491},"19":{"name":"(anonymous_19)","decl":{"start":{"line":561,"column":10},"end":{"line":561,"column":27}},"loc":{"start":{"line":561,"column":67},"end":{"line":595,"column":null}},"line":561},"20":{"name":"(anonymous_20)","decl":{"start":{"line":597,"column":10},"end":{"line":597,"column":25}},"loc":{"start":{"line":597,"column":55},"end":{"line":705,"column":null}},"line":597},"21":{"name":"(anonymous_21)","decl":{"start":{"line":607,"column":23},"end":{"line":607,"column":24}},"loc":{"start":{"line":607,"column":34},"end":{"line":648,"column":5}},"line":607},"22":{"name":"(anonymous_22)","decl":{"start":{"line":651,"column":22},"end":{"line":651,"column":23}},"loc":{"start":{"line":651,"column":41},"end":{"line":704,"column":5}},"line":651},"23":{"name":"(anonymous_23)","decl":{"start":{"line":707,"column":10},"end":{"line":707,"column":28}},"loc":{"start":{"line":707,"column":76},"end":{"line":722,"column":null}},"line":707}},"branchMap":{"0":{"loc":{"start":{"line":88,"column":6},"end":{"line":88,"column":null}},"type":"binary-expr","locations":[{"start":{"line":88,"column":6},"end":{"line":88,"column":23}},{"start":{"line":88,"column":23},"end":{"line":88,"column":51}},{"start":{"line":88,"column":51},"end":{"line":88,"column":null}}],"line":88},"1":{"loc":{"start":{"line":90,"column":6},"end":{"line":90,"column":null}},"type":"binary-expr","locations":[{"start":{"line":90,"column":6},"end":{"line":90,"column":19}},{"start":{"line":90,"column":19},"end":{"line":90,"column":43}},{"start":{"line":90,"column":43},"end":{"line":90,"column":null}}],"line":90},"2":{"loc":{"start":{"line":91,"column":16},"end":{"line":91,"column":null}},"type":"binary-expr","locations":[{"start":{"line":91,"column":16},"end":{"line":91,"column":24}},{"start":{"line":91,"column":24},"end":{"line":91,"column":43}},{"start":{"line":91,"column":43},"end":{"line":91,"column":null}}],"line":91},"3":{"loc":{"start":{"line":92,"column":23},"end":{"line":92,"column":null}},"type":"binary-expr","locations":[{"start":{"line":92,"column":23},"end":{"line":92,"column":38}},{"start":{"line":92,"column":38},"end":{"line":92,"column":null}}],"line":92},"4":{"loc":{"start":{"line":114,"column":4},"end":{"line":114,"column":null}},"type":"if","locations":[{"start":{"line":114,"column":4},"end":{"line":114,"column":null}},{"start":{},"end":{}}],"line":114},"5":{"loc":{"start":{"line":115,"column":4},"end":{"line":115,"column":null}},"type":"if","locations":[{"start":{"line":115,"column":4},"end":{"line":115,"column":null}},{"start":{},"end":{}}],"line":115},"6":{"loc":{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},"type":"if","locations":[{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},{"start":{},"end":{}}],"line":117},"7":{"loc":{"start":{"line":123,"column":6},"end":{"line":124,"column":null}},"type":"binary-expr","locations":[{"start":{"line":123,"column":6},"end":{"line":123,"column":null}},{"start":{"line":124,"column":6},"end":{"line":124,"column":null}}],"line":123},"8":{"loc":{"start":{"line":174,"column":6},"end":{"line":175,"column":null}},"type":"binary-expr","locations":[{"start":{"line":174,"column":6},"end":{"line":174,"column":null}},{"start":{"line":175,"column":6},"end":{"line":175,"column":null}}],"line":174},"9":{"loc":{"start":{"line":177,"column":4},"end":{"line":177,"column":null}},"type":"if","locations":[{"start":{"line":177,"column":4},"end":{"line":177,"column":null}},{"start":{},"end":{}}],"line":177},"10":{"loc":{"start":{"line":202,"column":18},"end":{"line":202,"column":null}},"type":"binary-expr","locations":[{"start":{"line":202,"column":18},"end":{"line":202,"column":41}},{"start":{"line":202,"column":41},"end":{"line":202,"column":null}}],"line":202},"11":{"loc":{"start":{"line":203,"column":13},"end":{"line":203,"column":null}},"type":"binary-expr","locations":[{"start":{"line":203,"column":13},"end":{"line":203,"column":31}},{"start":{"line":203,"column":31},"end":{"line":203,"column":null}}],"line":203},"12":{"loc":{"start":{"line":204,"column":17},"end":{"line":204,"column":null}},"type":"binary-expr","locations":[{"start":{"line":204,"column":17},"end":{"line":204,"column":39}},{"start":{"line":204,"column":39},"end":{"line":204,"column":null}}],"line":204},"13":{"loc":{"start":{"line":205,"column":14},"end":{"line":205,"column":null}},"type":"binary-expr","locations":[{"start":{"line":205,"column":14},"end":{"line":205,"column":33}},{"start":{"line":205,"column":33},"end":{"line":205,"column":null}}],"line":205},"14":{"loc":{"start":{"line":241,"column":4},"end":{"line":241,"column":null}},"type":"if","locations":[{"start":{"line":241,"column":4},"end":{"line":241,"column":null}},{"start":{},"end":{}}],"line":241},"15":{"loc":{"start":{"line":260,"column":4},"end":{"line":275,"column":null}},"type":"if","locations":[{"start":{"line":260,"column":4},"end":{"line":275,"column":null}},{"start":{},"end":{}}],"line":260},"16":{"loc":{"start":{"line":280,"column":6},"end":{"line":280,"column":null}},"type":"binary-expr","locations":[{"start":{"line":280,"column":6},"end":{"line":280,"column":15}},{"start":{"line":280,"column":15},"end":{"line":280,"column":null}}],"line":280},"17":{"loc":{"start":{"line":282,"column":4},"end":{"line":282,"column":null}},"type":"if","locations":[{"start":{"line":282,"column":4},"end":{"line":282,"column":null}},{"start":{},"end":{}}],"line":282},"18":{"loc":{"start":{"line":305,"column":14},"end":{"line":305,"column":null}},"type":"binary-expr","locations":[{"start":{"line":305,"column":14},"end":{"line":305,"column":25}},{"start":{"line":305,"column":25},"end":{"line":305,"column":null}}],"line":305},"19":{"loc":{"start":{"line":306,"column":19},"end":{"line":306,"column":null}},"type":"binary-expr","locations":[{"start":{"line":306,"column":19},"end":{"line":306,"column":35}},{"start":{"line":306,"column":35},"end":{"line":306,"column":46}},{"start":{"line":306,"column":46},"end":{"line":306,"column":null}}],"line":306},"20":{"loc":{"start":{"line":307,"column":17},"end":{"line":307,"column":null}},"type":"binary-expr","locations":[{"start":{"line":307,"column":17},"end":{"line":307,"column":31}},{"start":{"line":307,"column":31},"end":{"line":307,"column":42}},{"start":{"line":307,"column":42},"end":{"line":307,"column":null}}],"line":307},"21":{"loc":{"start":{"line":308,"column":13},"end":{"line":308,"column":null}},"type":"binary-expr","locations":[{"start":{"line":308,"column":13},"end":{"line":308,"column":23}},{"start":{"line":308,"column":23},"end":{"line":308,"column":null}}],"line":308},"22":{"loc":{"start":{"line":309,"column":17},"end":{"line":309,"column":null}},"type":"binary-expr","locations":[{"start":{"line":309,"column":17},"end":{"line":309,"column":31}},{"start":{"line":309,"column":31},"end":{"line":309,"column":null}}],"line":309},"23":{"loc":{"start":{"line":314,"column":10},"end":{"line":314,"column":null}},"type":"binary-expr","locations":[{"start":{"line":314,"column":10},"end":{"line":314,"column":37}},{"start":{"line":314,"column":37},"end":{"line":314,"column":null}}],"line":314},"24":{"loc":{"start":{"line":340,"column":4},"end":{"line":348,"column":null}},"type":"if","locations":[{"start":{"line":340,"column":4},"end":{"line":348,"column":null}},{"start":{},"end":{}}],"line":340},"25":{"loc":{"start":{"line":353,"column":4},"end":{"line":353,"column":null}},"type":"if","locations":[{"start":{"line":353,"column":4},"end":{"line":353,"column":null}},{"start":{},"end":{}}],"line":353},"26":{"loc":{"start":{"line":375,"column":14},"end":{"line":375,"column":null}},"type":"binary-expr","locations":[{"start":{"line":375,"column":14},"end":{"line":375,"column":26}},{"start":{"line":375,"column":26},"end":{"line":375,"column":null}}],"line":375},"27":{"loc":{"start":{"line":376,"column":19},"end":{"line":376,"column":null}},"type":"binary-expr","locations":[{"start":{"line":376,"column":19},"end":{"line":376,"column":36}},{"start":{"line":376,"column":36},"end":{"line":376,"column":null}}],"line":376},"28":{"loc":{"start":{"line":377,"column":17},"end":{"line":377,"column":null}},"type":"binary-expr","locations":[{"start":{"line":377,"column":17},"end":{"line":377,"column":32}},{"start":{"line":377,"column":32},"end":{"line":377,"column":null}}],"line":377},"29":{"loc":{"start":{"line":378,"column":13},"end":{"line":378,"column":null}},"type":"binary-expr","locations":[{"start":{"line":378,"column":13},"end":{"line":378,"column":24}},{"start":{"line":378,"column":24},"end":{"line":378,"column":null}}],"line":378},"30":{"loc":{"start":{"line":379,"column":17},"end":{"line":379,"column":null}},"type":"binary-expr","locations":[{"start":{"line":379,"column":17},"end":{"line":379,"column":32}},{"start":{"line":379,"column":32},"end":{"line":379,"column":null}}],"line":379},"31":{"loc":{"start":{"line":380,"column":39},"end":{"line":380,"column":70}},"type":"binary-expr","locations":[{"start":{"line":380,"column":39},"end":{"line":380,"column":66}},{"start":{"line":380,"column":66},"end":{"line":380,"column":70}}],"line":380},"32":{"loc":{"start":{"line":403,"column":4},"end":{"line":419,"column":null}},"type":"if","locations":[{"start":{"line":403,"column":4},"end":{"line":419,"column":null}},{"start":{},"end":{}}],"line":403},"33":{"loc":{"start":{"line":422,"column":4},"end":{"line":440,"column":null}},"type":"if","locations":[{"start":{"line":422,"column":4},"end":{"line":440,"column":null}},{"start":{},"end":{}}],"line":422},"34":{"loc":{"start":{"line":442,"column":4},"end":{"line":450,"column":null}},"type":"if","locations":[{"start":{"line":442,"column":4},"end":{"line":450,"column":null}},{"start":{},"end":{}}],"line":442},"35":{"loc":{"start":{"line":455,"column":4},"end":{"line":455,"column":null}},"type":"if","locations":[{"start":{"line":455,"column":4},"end":{"line":455,"column":null}},{"start":{},"end":{}}],"line":455},"36":{"loc":{"start":{"line":472,"column":14},"end":{"line":472,"column":null}},"type":"binary-expr","locations":[{"start":{"line":472,"column":14},"end":{"line":472,"column":31}},{"start":{"line":472,"column":31},"end":{"line":472,"column":null}}],"line":472},"37":{"loc":{"start":{"line":493,"column":4},"end":{"line":493,"column":null}},"type":"if","locations":[{"start":{"line":493,"column":4},"end":{"line":493,"column":null}},{"start":{},"end":{}}],"line":493},"38":{"loc":{"start":{"line":514,"column":17},"end":{"line":514,"column":null}},"type":"binary-expr","locations":[{"start":{"line":514,"column":17},"end":{"line":514,"column":32}},{"start":{"line":514,"column":32},"end":{"line":514,"column":null}}],"line":514},"39":{"loc":{"start":{"line":541,"column":4},"end":{"line":558,"column":null}},"type":"if","locations":[{"start":{"line":541,"column":4},"end":{"line":558,"column":null}},{"start":{},"end":{}}],"line":541},"40":{"loc":{"start":{"line":563,"column":4},"end":{"line":563,"column":null}},"type":"if","locations":[{"start":{"line":563,"column":4},"end":{"line":563,"column":null}},{"start":{},"end":{}}],"line":563},"41":{"loc":{"start":{"line":598,"column":23},"end":{"line":598,"column":null}},"type":"binary-expr","locations":[{"start":{"line":598,"column":23},"end":{"line":598,"column":48}},{"start":{"line":598,"column":48},"end":{"line":598,"column":null}}],"line":598},"42":{"loc":{"start":{"line":599,"column":22},"end":{"line":599,"column":null}},"type":"binary-expr","locations":[{"start":{"line":599,"column":22},"end":{"line":599,"column":46}},{"start":{"line":599,"column":46},"end":{"line":599,"column":null}}],"line":599},"43":{"loc":{"start":{"line":600,"column":4},"end":{"line":600,"column":null}},"type":"if","locations":[{"start":{"line":600,"column":4},"end":{"line":600,"column":null}},{"start":{},"end":{}}],"line":600},"44":{"loc":{"start":{"line":600,"column":8},"end":{"line":600,"column":59}},"type":"binary-expr","locations":[{"start":{"line":600,"column":8},"end":{"line":600,"column":35}},{"start":{"line":600,"column":35},"end":{"line":600,"column":59}}],"line":600},"45":{"loc":{"start":{"line":603,"column":6},"end":{"line":604,"column":null}},"type":"binary-expr","locations":[{"start":{"line":603,"column":6},"end":{"line":603,"column":null}},{"start":{"line":604,"column":6},"end":{"line":604,"column":null}}],"line":603},"46":{"loc":{"start":{"line":609,"column":6},"end":{"line":609,"column":null}},"type":"if","locations":[{"start":{"line":609,"column":6},"end":{"line":609,"column":null}},{"start":{},"end":{}}],"line":609},"47":{"loc":{"start":{"line":628,"column":20},"end":{"line":628,"column":null}},"type":"binary-expr","locations":[{"start":{"line":628,"column":20},"end":{"line":628,"column":38}},{"start":{"line":628,"column":38},"end":{"line":628,"column":null}}],"line":628},"48":{"loc":{"start":{"line":630,"column":19},"end":{"line":630,"column":null}},"type":"binary-expr","locations":[{"start":{"line":630,"column":19},"end":{"line":630,"column":36}},{"start":{"line":630,"column":36},"end":{"line":630,"column":null}}],"line":630},"49":{"loc":{"start":{"line":653,"column":6},"end":{"line":653,"column":null}},"type":"if","locations":[{"start":{"line":653,"column":6},"end":{"line":653,"column":null}},{"start":{},"end":{}}],"line":653},"50":{"loc":{"start":{"line":670,"column":19},"end":{"line":670,"column":null}},"type":"binary-expr","locations":[{"start":{"line":670,"column":19},"end":{"line":670,"column":39}},{"start":{"line":670,"column":39},"end":{"line":670,"column":null}}],"line":670},"51":{"loc":{"start":{"line":677,"column":6},"end":{"line":690,"column":null}},"type":"if","locations":[{"start":{"line":677,"column":6},"end":{"line":690,"column":null}},{"start":{},"end":{}}],"line":677},"52":{"loc":{"start":{"line":708,"column":4},"end":{"line":708,"column":null}},"type":"if","locations":[{"start":{"line":708,"column":4},"end":{"line":708,"column":null}},{"start":{},"end":{}}],"line":708},"53":{"loc":{"start":{"line":717,"column":6},"end":{"line":719,"column":null}},"type":"if","locations":[{"start":{"line":717,"column":6},"end":{"line":719,"column":null}},{"start":{},"end":{}}],"line":717}},"s":{"0":57,"1":57,"2":57,"3":57,"4":57,"5":57,"6":32,"7":3,"8":3,"9":2,"10":1,"11":1,"12":1,"13":1,"14":1,"15":6,"16":6,"17":0,"18":22,"19":2,"20":2,"21":2,"22":2,"23":1,"24":2,"25":0,"26":2,"27":1,"28":2,"29":0,"30":2,"31":2,"32":2,"33":2,"34":2,"35":2,"36":2,"37":0,"38":2,"39":2,"40":2,"41":2,"42":2,"43":2,"44":8,"45":8,"46":0,"47":8,"48":8,"49":8,"50":8,"51":6,"52":6,"53":1,"54":1,"55":0,"56":1,"57":1,"58":1,"59":1,"60":1,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":1,"75":1,"76":0,"77":1,"78":1,"79":1,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":2,"90":2,"91":0,"92":2,"93":2,"94":2,"95":2,"96":2,"97":2,"98":2,"99":0,"100":2,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":2,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0},"f":{"0":57,"1":32,"2":3,"3":6,"4":0,"5":22,"6":2,"7":1,"8":0,"9":1,"10":0,"11":2,"12":2,"13":8,"14":1,"15":0,"16":0,"17":1,"18":0,"19":2,"20":2,"21":0,"22":0,"23":0},"b":{"0":[57,55,0],"1":[57,55,0],"2":[57,57,57],"3":[57,57],"4":[2,1],"5":[0,1],"6":[0,1],"7":[6,0],"8":[2,0],"9":[0,2],"10":[2,0],"11":[2,0],"12":[2,0],"13":[2,0],"14":[0,8],"15":[6,2],"16":[1,0],"17":[0,1],"18":[1,0],"19":[1,0,0],"20":[1,0,0],"21":[1,0],"22":[1,0],"23":[1,0],"24":[1,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,1],"36":[1,1],"37":[0,0],"38":[0,0],"39":[0,0],"40":[0,2],"41":[2,2],"42":[2,2],"43":[2,0],"44":[2,2],"45":[0,0],"46":[0,0],"47":[0,0],"48":[0,0],"49":[0,0],"50":[0,0],"51":[0,0],"52":[0,0],"53":[0,0]},"meta":{"lastBranch":54,"lastFunction":24,"lastStatement":125,"seen":{"s:74:42:74:Infinity":0,"s:75:27:75:Infinity":1,"f:81:2:81:Infinity":0,"s:87:4:88:Infinity":2,"b:88:6:88:23:88:23:88:51:88:51:88:Infinity":0,"s:89:4:90:Infinity":3,"b:90:6:90:19:90:19:90:43:90:43:90:Infinity":1,"s:91:4:91:Infinity":4,"b:91:16:91:24:91:24:91:43:91:43:91:Infinity":2,"s:92:4:92:Infinity":5,"b:92:23:92:38:92:38:92:Infinity":3,"f:95:10:95:19":1,"s:96:4:96:Infinity":6,"f:107:10:107:Infinity":2,"s:113:18:113:Infinity":7,"b:114:4:114:Infinity:undefined:undefined:undefined:undefined":4,"s:114:4:114:Infinity":8,"s:114:25:114:Infinity":9,"b:115:4:115:Infinity:undefined:undefined:undefined:undefined":5,"s:115:4:115:Infinity":10,"s:115:26:115:Infinity":11,"b:117:4:117:Infinity:undefined:undefined:undefined:undefined":6,"s:117:4:117:Infinity":12,"s:117:19:117:Infinity":13,"s:118:4:118:Infinity":14,"f:121:10:121:21":3,"s:123:6:124:Infinity":15,"b:123:6:123:Infinity:124:6:124:Infinity":7,"s:125:4:125:Infinity":16,"f:128:10:128:33":4,"s:129:4:129:Infinity":17,"f:132:10:132:23":5,"s:133:4:133:Infinity":18,"f:136:2:136:22":6,"s:137:4:137:Infinity":19,"s:138:4:138:Infinity":20,"s:141:4:141:Infinity":21,"s:144:4:146:Infinity":22,"f:144:33:144:34":7,"s:145:6:145:Infinity":23,"s:149:4:149:Infinity":24,"f:149:31:149:32":8,"s:149:40:149:77":25,"s:152:4:154:Infinity":26,"f:152:34:152:35":9,"s:153:6:153:Infinity":27,"s:157:4:159:Infinity":28,"f:157:32:157:33":10,"s:158:6:158:Infinity":29,"s:162:4:164:Infinity":30,"f:162:32:162:33":11,"s:163:6:163:Infinity":31,"s:167:4:167:Infinity":32,"s:169:4:169:Infinity":33,"f:172:10:172:25":12,"s:174:6:175:Infinity":34,"b:174:6:174:Infinity:175:6:175:Infinity":8,"s:176:19:176:Infinity":35,"b:177:4:177:Infinity:undefined:undefined:undefined:undefined":9,"s:177:4:177:Infinity":36,"s:177:41:177:Infinity":37,"s:178:4:178:Infinity":38,"s:180:39:214:Infinity":39,"b:202:18:202:41:202:41:202:Infinity":10,"b:203:13:203:31:203:31:203:Infinity":11,"b:204:17:204:39:204:39:204:Infinity":12,"b:205:14:205:33:205:33:205:Infinity":13,"s:215:4:215:Infinity":40,"s:218:23:218:Infinity":41,"s:219:4:219:Infinity":42,"s:222:4:236:Infinity":43,"f:239:10:239:32":13,"s:240:19:240:Infinity":44,"b:241:4:241:Infinity:undefined:undefined:undefined:undefined":14,"s:241:4:241:Infinity":45,"s:241:41:241:Infinity":46,"s:242:4:242:Infinity":47,"s:244:4:257:Infinity":48,"s:259:23:259:Infinity":49,"b:260:4:275:Infinity:undefined:undefined:undefined:undefined":15,"s:260:4:275:Infinity":50,"s:261:6:261:Infinity":51,"s:264:6:274:Infinity":52,"f:278:10:278:29":14,"s:279:19:281:Infinity":53,"b:280:6:280:15:280:15:280:Infinity":16,"b:282:4:282:Infinity:undefined:undefined:undefined:undefined":17,"s:282:4:282:Infinity":54,"s:282:41:282:Infinity":55,"s:283:4:283:Infinity":56,"s:285:4:324:Infinity":57,"b:305:14:305:25:305:25:305:Infinity":18,"b:306:19:306:35:306:35:306:46:306:46:306:Infinity":19,"b:307:17:307:31:307:31:307:42:307:42:307:Infinity":20,"b:308:13:308:23:308:23:308:Infinity":21,"b:309:17:309:31:309:31:309:Infinity":22,"b:314:10:314:37:314:37:314:Infinity":23,"s:327:4:337:Infinity":58,"b:340:4:348:Infinity:undefined:undefined:undefined:undefined":24,"s:340:4:348:Infinity":59,"s:341:6:347:Infinity":60,"f:351:10:351:26":15,"s:352:19:352:Infinity":61,"b:353:4:353:Infinity:undefined:undefined:undefined:undefined":25,"s:353:4:353:Infinity":62,"s:353:41:353:Infinity":63,"s:354:4:354:Infinity":64,"s:356:4:387:Infinity":65,"b:375:14:375:26:375:26:375:Infinity":26,"b:376:19:376:36:376:36:376:Infinity":27,"b:377:17:377:32:377:32:377:Infinity":28,"b:378:13:378:24:378:24:378:Infinity":29,"b:379:17:379:32:379:32:379:Infinity":30,"b:380:39:380:66:380:66:380:70":31,"s:390:4:400:Infinity":66,"b:403:4:419:Infinity:undefined:undefined:undefined:undefined":32,"s:403:4:419:Infinity":67,"s:404:6:418:Infinity":68,"b:422:4:440:Infinity:undefined:undefined:undefined:undefined":33,"s:422:4:440:Infinity":69,"s:423:6:439:Infinity":70,"f:423:29:423:30":16,"s:424:8:438:Infinity":71,"b:442:4:450:Infinity:undefined:undefined:undefined:undefined":34,"s:442:4:450:Infinity":72,"s:443:6:449:Infinity":73,"f:453:10:453:29":17,"s:454:19:454:Infinity":74,"b:455:4:455:Infinity:undefined:undefined:undefined:undefined":35,"s:455:4:455:Infinity":75,"s:455:41:455:Infinity":76,"s:456:4:456:Infinity":77,"s:458:4:475:Infinity":78,"b:472:14:472:31:472:31:472:Infinity":36,"s:478:4:488:Infinity":79,"f:491:10:491:27":18,"s:492:19:492:Infinity":80,"b:493:4:493:Infinity:undefined:undefined:undefined:undefined":37,"s:493:4:493:Infinity":81,"s:493:41:493:Infinity":82,"s:494:4:494:Infinity":83,"s:496:4:521:Infinity":84,"b:514:17:514:32:514:32:514:Infinity":38,"s:524:4:534:Infinity":85,"s:537:25:540:Infinity":86,"b:541:4:558:Infinity:undefined:undefined:undefined:undefined":39,"s:541:4:558:Infinity":87,"s:542:6:557:Infinity":88,"f:561:10:561:27":19,"s:562:19:562:Infinity":89,"b:563:4:563:Infinity:undefined:undefined:undefined:undefined":40,"s:563:4:563:Infinity":90,"s:563:41:563:Infinity":91,"s:564:4:564:Infinity":92,"s:566:4:581:Infinity":93,"s:584:4:594:Infinity":94,"f:597:10:597:25":20,"s:598:23:598:Infinity":95,"b:598:23:598:48:598:48:598:Infinity":41,"s:599:22:599:Infinity":96,"b:599:22:599:46:599:46:599:Infinity":42,"b:600:4:600:Infinity:undefined:undefined:undefined:undefined":43,"s:600:4:600:Infinity":97,"b:600:8:600:35:600:35:600:59":44,"s:600:59:600:Infinity":98,"s:603:6:604:Infinity":99,"b:603:6:603:Infinity:604:6:604:Infinity":45,"s:607:4:648:Infinity":100,"f:607:23:607:24":21,"s:608:21:608:Infinity":101,"b:609:6:609:Infinity:undefined:undefined:undefined:undefined":46,"s:609:6:609:Infinity":102,"s:609:43:609:Infinity":103,"s:610:6:610:Infinity":104,"s:613:6:634:Infinity":105,"b:628:20:628:38:628:38:628:Infinity":47,"b:630:19:630:36:630:36:630:Infinity":48,"s:637:6:647:Infinity":106,"s:651:4:704:Infinity":107,"f:651:22:651:23":22,"s:652:21:652:Infinity":108,"b:653:6:653:Infinity:undefined:undefined:undefined:undefined":49,"s:653:6:653:Infinity":109,"s:653:43:653:Infinity":110,"s:654:6:654:Infinity":111,"s:657:6:674:Infinity":112,"b:670:19:670:39:670:39:670:Infinity":50,"b:677:6:690:Infinity:undefined:undefined:undefined:undefined":51,"s:677:6:690:Infinity":113,"s:678:29:678:Infinity":114,"s:679:8:689:Infinity":115,"s:693:6:703:Infinity":116,"f:707:10:707:28":23,"b:708:4:708:Infinity:undefined:undefined:undefined:undefined":52,"s:708:4:708:Infinity":117,"s:708:33:708:Infinity":118,"s:709:17:709:Infinity":119,"s:710:23:715:Infinity":120,"s:716:4:720:Infinity":121,"b:717:6:719:Infinity:undefined:undefined:undefined:undefined":53,"s:717:6:719:Infinity":122,"s:718:8:718:Infinity":123,"s:721:4:721:Infinity":124}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/graph/cache.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/graph/cache.ts","statementMap":{"0":{"start":{"line":26,"column":4},"end":{"line":26,"column":null}},"1":{"start":{"line":27,"column":4},"end":{"line":27,"column":null}},"2":{"start":{"line":31,"column":4},"end":{"line":38,"column":null}},"3":{"start":{"line":32,"column":6},"end":{"line":35,"column":null}},"4":{"start":{"line":33,"column":21},"end":{"line":33,"column":null}},"5":{"start":{"line":34,"column":8},"end":{"line":34,"column":null}},"6":{"start":{"line":37,"column":6},"end":{"line":37,"column":null}},"7":{"start":{"line":40,"column":4},"end":{"line":44,"column":null}},"8":{"start":{"line":51,"column":4},"end":{"line":60,"column":null}},"9":{"start":{"line":52,"column":18},"end":{"line":52,"column":null}},"10":{"start":{"line":53,"column":6},"end":{"line":55,"column":null}},"11":{"start":{"line":54,"column":8},"end":{"line":54,"column":null}},"12":{"start":{"line":56,"column":6},"end":{"line":56,"column":null}},"13":{"start":{"line":57,"column":6},"end":{"line":57,"column":null}},"14":{"start":{"line":59,"column":6},"end":{"line":59,"column":null}},"15":{"start":{"line":67,"column":20},"end":{"line":67,"column":null}},"16":{"start":{"line":68,"column":4},"end":{"line":73,"column":null}},"17":{"start":{"line":80,"column":20},"end":{"line":80,"column":null}},"18":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"19":{"start":{"line":88,"column":18},"end":{"line":88,"column":null}},"20":{"start":{"line":89,"column":4},"end":{"line":89,"column":null}},"21":{"start":{"line":98,"column":30},"end":{"line":98,"column":null}},"22":{"start":{"line":100,"column":16},"end":{"line":100,"column":null}},"23":{"start":{"line":102,"column":4},"end":{"line":107,"column":null}},"24":{"start":{"line":103,"column":20},"end":{"line":103,"column":null}},"25":{"start":{"line":104,"column":6},"end":{"line":106,"column":null}},"26":{"start":{"line":105,"column":8},"end":{"line":105,"column":null}},"27":{"start":{"line":109,"column":4},"end":{"line":109,"column":null}},"28":{"start":{"line":116,"column":4},"end":{"line":120,"column":null}},"29":{"start":{"line":131,"column":4},"end":{"line":135,"column":null}},"30":{"start":{"line":142,"column":4},"end":{"line":142,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":25,"column":2},"end":{"line":25,"column":14}},"loc":{"start":{"line":25,"column":49},"end":{"line":28,"column":null}},"line":25},"1":{"name":"(anonymous_1)","decl":{"start":{"line":30,"column":10},"end":{"line":30,"column":33}},"loc":{"start":{"line":30,"column":33},"end":{"line":45,"column":null}},"line":30},"2":{"name":"(anonymous_2)","decl":{"start":{"line":50,"column":2},"end":{"line":50,"column":15}},"loc":{"start":{"line":50,"column":15},"end":{"line":61,"column":null}},"line":50},"3":{"name":"(anonymous_3)","decl":{"start":{"line":66,"column":2},"end":{"line":66,"column":6}},"loc":{"start":{"line":66,"column":57},"end":{"line":74,"column":null}},"line":66},"4":{"name":"(anonymous_4)","decl":{"start":{"line":79,"column":2},"end":{"line":79,"column":6}},"loc":{"start":{"line":79,"column":48},"end":{"line":82,"column":null}},"line":79},"5":{"name":"(anonymous_5)","decl":{"start":{"line":87,"column":2},"end":{"line":87,"column":13}},"loc":{"start":{"line":87,"column":61},"end":{"line":90,"column":null}},"line":87},"6":{"name":"(anonymous_6)","decl":{"start":{"line":95,"column":2},"end":{"line":95,"column":null}},"loc":{"start":{"line":97,"column":14},"end":{"line":110,"column":null}},"line":97},"7":{"name":"(anonymous_7)","decl":{"start":{"line":115,"column":2},"end":{"line":115,"column":16}},"loc":{"start":{"line":115,"column":16},"end":{"line":121,"column":null}},"line":115},"8":{"name":"(anonymous_8)","decl":{"start":{"line":126,"column":2},"end":{"line":126,"column":null}},"loc":{"start":{"line":130,"column":4},"end":{"line":136,"column":null}},"line":130},"9":{"name":"(anonymous_9)","decl":{"start":{"line":141,"column":2},"end":{"line":141,"column":19}},"loc":{"start":{"line":141,"column":19},"end":{"line":143,"column":null}},"line":141}},"branchMap":{"0":{"loc":{"start":{"line":25,"column":14},"end":{"line":25,"column":49}},"type":"default-arg","locations":[{"start":{"line":25,"column":33},"end":{"line":25,"column":49}}],"line":25},"1":{"loc":{"start":{"line":32,"column":6},"end":{"line":35,"column":null}},"type":"if","locations":[{"start":{"line":32,"column":6},"end":{"line":35,"column":null}},{"start":{},"end":{}}],"line":32},"2":{"loc":{"start":{"line":53,"column":6},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":53,"column":6},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":53},"3":{"loc":{"start":{"line":89,"column":11},"end":{"line":89,"column":null}},"type":"binary-expr","locations":[{"start":{"line":89,"column":11},"end":{"line":89,"column":21}},{"start":{"line":89,"column":21},"end":{"line":89,"column":null}}],"line":89},"4":{"loc":{"start":{"line":104,"column":6},"end":{"line":106,"column":null}},"type":"if","locations":[{"start":{"line":104,"column":6},"end":{"line":106,"column":null}},{"start":{},"end":{}}],"line":104},"5":{"loc":{"start":{"line":104,"column":10},"end":{"line":104,"column":46}},"type":"binary-expr","locations":[{"start":{"line":104,"column":10},"end":{"line":104,"column":20}},{"start":{"line":104,"column":20},"end":{"line":104,"column":46}}],"line":104}},"s":{"0":55,"1":55,"2":55,"3":55,"4":55,"5":55,"6":0,"7":0,"8":2,"9":2,"10":2,"11":0,"12":2,"13":2,"14":0,"15":2,"16":2,"17":2,"18":2,"19":2,"20":2,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0},"f":{"0":55,"1":55,"2":2,"3":2,"4":2,"5":2,"6":0,"7":0,"8":0,"9":0},"b":{"0":[55],"1":[55,0],"2":[0,2],"3":[2,0],"4":[0,0],"5":[0,0]},"meta":{"lastBranch":6,"lastFunction":10,"lastStatement":31,"seen":{"f:25:2:25:14":0,"b:25:33:25:49":0,"s:26:4:26:Infinity":0,"s:27:4:27:Infinity":1,"f:30:10:30:33":1,"s:31:4:38:Infinity":2,"b:32:6:35:Infinity:undefined:undefined:undefined:undefined":1,"s:32:6:35:Infinity":3,"s:33:21:33:Infinity":4,"s:34:8:34:Infinity":5,"s:37:6:37:Infinity":6,"s:40:4:44:Infinity":7,"f:50:2:50:15":2,"s:51:4:60:Infinity":8,"s:52:18:52:Infinity":9,"b:53:6:55:Infinity:undefined:undefined:undefined:undefined":2,"s:53:6:55:Infinity":10,"s:54:8:54:Infinity":11,"s:56:6:56:Infinity":12,"s:57:6:57:Infinity":13,"s:59:6:59:Infinity":14,"f:66:2:66:6":3,"s:67:20:67:Infinity":15,"s:68:4:73:Infinity":16,"f:79:2:79:6":4,"s:80:20:80:Infinity":17,"s:81:4:81:Infinity":18,"f:87:2:87:13":5,"s:88:18:88:Infinity":19,"s:89:4:89:Infinity":20,"b:89:11:89:21:89:21:89:Infinity":3,"f:95:2:95:Infinity":6,"s:98:30:98:Infinity":21,"s:100:16:100:Infinity":22,"s:102:4:107:Infinity":23,"s:103:20:103:Infinity":24,"b:104:6:106:Infinity:undefined:undefined:undefined:undefined":4,"s:104:6:106:Infinity":25,"b:104:10:104:20:104:20:104:46":5,"s:105:8:105:Infinity":26,"s:109:4:109:Infinity":27,"f:115:2:115:16":7,"s:116:4:120:Infinity":28,"f:126:2:126:Infinity":8,"s:131:4:135:Infinity":29,"f:141:2:141:19":9,"s:142:4:142:Infinity":30}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/graph/client.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/graph/client.ts","statementMap":{"0":{"start":{"line":24,"column":22},"end":{"line":24,"column":null}},"1":{"start":{"line":25,"column":40},"end":{"line":25,"column":null}},"2":{"start":{"line":28,"column":4},"end":{"line":33,"column":null}},"3":{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},"4":{"start":{"line":37,"column":20},"end":{"line":37,"column":null}},"5":{"start":{"line":39,"column":4},"end":{"line":39,"column":null}},"6":{"start":{"line":43,"column":4},"end":{"line":71,"column":null}},"7":{"start":{"line":45,"column":22},"end":{"line":45,"column":null}},"8":{"start":{"line":46,"column":6},"end":{"line":46,"column":null}},"9":{"start":{"line":47,"column":6},"end":{"line":47,"column":null}},"10":{"start":{"line":48,"column":6},"end":{"line":48,"column":null}},"11":{"start":{"line":49,"column":6},"end":{"line":49,"column":null}},"12":{"start":{"line":51,"column":6},"end":{"line":66,"column":null}},"13":{"start":{"line":52,"column":8},"end":{"line":54,"column":null}},"14":{"start":{"line":56,"column":8},"end":{"line":56,"column":null}},"15":{"start":{"line":57,"column":8},"end":{"line":57,"column":null}},"16":{"start":{"line":58,"column":8},"end":{"line":58,"column":null}},"17":{"start":{"line":60,"column":24},"end":{"line":60,"column":null}},"18":{"start":{"line":61,"column":8},"end":{"line":61,"column":null}},"19":{"start":{"line":62,"column":8},"end":{"line":62,"column":null}},"20":{"start":{"line":63,"column":8},"end":{"line":63,"column":null}},"21":{"start":{"line":64,"column":8},"end":{"line":64,"column":null}},"22":{"start":{"line":65,"column":8},"end":{"line":65,"column":null}},"23":{"start":{"line":68,"column":6},"end":{"line":68,"column":null}},"24":{"start":{"line":69,"column":6},"end":{"line":69,"column":null}},"25":{"start":{"line":70,"column":6},"end":{"line":70,"column":null}},"26":{"start":{"line":75,"column":20},"end":{"line":75,"column":null}},"27":{"start":{"line":76,"column":22},"end":{"line":79,"column":null}},"28":{"start":{"line":82,"column":4},"end":{"line":86,"column":null}},"29":{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},"30":{"start":{"line":91,"column":6},"end":{"line":91,"column":null}},"31":{"start":{"line":94,"column":20},"end":{"line":94,"column":null}},"32":{"start":{"line":95,"column":4},"end":{"line":95,"column":null}},"33":{"start":{"line":99,"column":4},"end":{"line":103,"column":null}},"34":{"start":{"line":100,"column":6},"end":{"line":100,"column":null}},"35":{"start":{"line":101,"column":6},"end":{"line":101,"column":null}},"36":{"start":{"line":102,"column":6},"end":{"line":102,"column":null}},"37":{"start":{"line":110,"column":4},"end":{"line":122,"column":null}},"38":{"start":{"line":111,"column":6},"end":{"line":113,"column":null}},"39":{"start":{"line":114,"column":6},"end":{"line":121,"column":null}},"40":{"start":{"line":115,"column":8},"end":{"line":115,"column":null}},"41":{"start":{"line":117,"column":8},"end":{"line":120,"column":null}},"42":{"start":{"line":125,"column":28},"end":{"line":127,"column":null}},"43":{"start":{"line":126,"column":45},"end":{"line":126,"column":76}},"44":{"start":{"line":129,"column":4},"end":{"line":160,"column":null}},"45":{"start":{"line":129,"column":23},"end":{"line":129,"column":26}},"46":{"start":{"line":130,"column":22},"end":{"line":130,"column":null}},"47":{"start":{"line":131,"column":6},"end":{"line":159,"column":null}},"48":{"start":{"line":132,"column":23},"end":{"line":132,"column":null}},"49":{"start":{"line":133,"column":21},"end":{"line":133,"column":null}},"50":{"start":{"line":133,"column":57},"end":{"line":133,"column":74}},"51":{"start":{"line":135,"column":8},"end":{"line":138,"column":null}},"52":{"start":{"line":140,"column":25},"end":{"line":140,"column":null}},"53":{"start":{"line":142,"column":10},"end":{"line":142,"column":null}},"54":{"start":{"line":144,"column":8},"end":{"line":149,"column":null}},"55":{"start":{"line":145,"column":10},"end":{"line":147,"column":null}},"56":{"start":{"line":148,"column":10},"end":{"line":148,"column":null}},"57":{"start":{"line":151,"column":8},"end":{"line":151,"column":null}},"58":{"start":{"line":152,"column":8},"end":{"line":152,"column":null}},"59":{"start":{"line":153,"column":8},"end":{"line":156,"column":null}},"60":{"start":{"line":158,"column":8},"end":{"line":158,"column":null}},"61":{"start":{"line":162,"column":4},"end":{"line":165,"column":null}},"62":{"start":{"line":169,"column":20},"end":{"line":169,"column":null}},"63":{"start":{"line":170,"column":23},"end":{"line":170,"column":null}},"64":{"start":{"line":171,"column":4},"end":{"line":175,"column":null}},"65":{"start":{"line":180,"column":35},"end":{"line":180,"column":null}},"66":{"start":{"line":182,"column":4},"end":{"line":193,"column":null}},"67":{"start":{"line":183,"column":21},"end":{"line":186,"column":null}},"68":{"start":{"line":187,"column":6},"end":{"line":187,"column":null}},"69":{"start":{"line":190,"column":6},"end":{"line":192,"column":null}},"70":{"start":{"line":191,"column":8},"end":{"line":191,"column":null}},"71":{"start":{"line":195,"column":4},"end":{"line":195,"column":null}},"72":{"start":{"line":203,"column":19},"end":{"line":203,"column":null}},"73":{"start":{"line":204,"column":4},"end":{"line":204,"column":null}},"74":{"start":{"line":211,"column":18},"end":{"line":211,"column":null}},"75":{"start":{"line":214,"column":4},"end":{"line":216,"column":null}},"76":{"start":{"line":215,"column":6},"end":{"line":215,"column":null}},"77":{"start":{"line":219,"column":4},"end":{"line":223,"column":null}},"78":{"start":{"line":220,"column":25},"end":{"line":220,"column":null}},"79":{"start":{"line":221,"column":22},"end":{"line":221,"column":null}},"80":{"start":{"line":222,"column":6},"end":{"line":222,"column":null}},"81":{"start":{"line":226,"column":4},"end":{"line":230,"column":null}},"82":{"start":{"line":227,"column":24},"end":{"line":227,"column":null}},"83":{"start":{"line":228,"column":23},"end":{"line":228,"column":null}},"84":{"start":{"line":229,"column":6},"end":{"line":229,"column":null}},"85":{"start":{"line":233,"column":4},"end":{"line":235,"column":null}},"86":{"start":{"line":234,"column":6},"end":{"line":234,"column":null}},"87":{"start":{"line":238,"column":4},"end":{"line":240,"column":null}},"88":{"start":{"line":239,"column":6},"end":{"line":239,"column":null}},"89":{"start":{"line":243,"column":4},"end":{"line":243,"column":null}},"90":{"start":{"line":254,"column":4},"end":{"line":256,"column":null}},"91":{"start":{"line":255,"column":6},"end":{"line":255,"column":null}},"92":{"start":{"line":258,"column":4},"end":{"line":294,"column":null}},"93":{"start":{"line":260,"column":26},"end":{"line":264,"column":null}},"94":{"start":{"line":266,"column":20},"end":{"line":270,"column":null}},"95":{"start":{"line":266,"column":56},"end":{"line":270,"column":8}},"96":{"start":{"line":273,"column":25},"end":{"line":277,"column":null}},"97":{"start":{"line":279,"column":28},"end":{"line":285,"column":null}},"98":{"start":{"line":279,"column":63},"end":{"line":285,"column":8}},"99":{"start":{"line":287,"column":6},"end":{"line":287,"column":null}},"100":{"start":{"line":289,"column":6},"end":{"line":292,"column":null}},"101":{"start":{"line":293,"column":6},"end":{"line":293,"column":null}},"102":{"start":{"line":301,"column":4},"end":{"line":301,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":27,"column":2},"end":{"line":27,"column":14}},"loc":{"start":{"line":27,"column":52},"end":{"line":40,"column":null}},"line":27},"1":{"name":"(anonymous_1)","decl":{"start":{"line":42,"column":8},"end":{"line":42,"column":33}},"loc":{"start":{"line":42,"column":33},"end":{"line":72,"column":null}},"line":42},"2":{"name":"(anonymous_2)","decl":{"start":{"line":74,"column":10},"end":{"line":74,"column":23}},"loc":{"start":{"line":74,"column":42},"end":{"line":87,"column":null}},"line":74},"3":{"name":"(anonymous_3)","decl":{"start":{"line":89,"column":10},"end":{"line":89,"column":36}},"loc":{"start":{"line":89,"column":61},"end":{"line":96,"column":null}},"line":89},"4":{"name":"(anonymous_4)","decl":{"start":{"line":98,"column":8},"end":{"line":98,"column":36}},"loc":{"start":{"line":98,"column":36},"end":{"line":104,"column":null}},"line":98},"5":{"name":"(anonymous_5)","decl":{"start":{"line":106,"column":8},"end":{"line":106,"column":null}},"loc":{"start":{"line":109,"column":26},"end":{"line":166,"column":null}},"line":109},"6":{"name":"(anonymous_6)","decl":{"start":{"line":126,"column":33},"end":{"line":126,"column":34}},"loc":{"start":{"line":126,"column":45},"end":{"line":126,"column":76}},"line":126},"7":{"name":"(anonymous_7)","decl":{"start":{"line":133,"column":40},"end":{"line":133,"column":41}},"loc":{"start":{"line":133,"column":57},"end":{"line":133,"column":74}},"line":133},"8":{"name":"(anonymous_8)","decl":{"start":{"line":168,"column":10},"end":{"line":168,"column":32}},"loc":{"start":{"line":168,"column":57},"end":{"line":177,"column":null}},"line":168},"9":{"name":"(anonymous_9)","decl":{"start":{"line":179,"column":8},"end":{"line":179,"column":21}},"loc":{"start":{"line":179,"column":76},"end":{"line":196,"column":null}},"line":179},"10":{"name":"(anonymous_10)","decl":{"start":{"line":202,"column":8},"end":{"line":202,"column":29}},"loc":{"start":{"line":202,"column":66},"end":{"line":205,"column":null}},"line":202},"11":{"name":"(anonymous_11)","decl":{"start":{"line":210,"column":10},"end":{"line":210,"column":34}},"loc":{"start":{"line":210,"column":57},"end":{"line":244,"column":null}},"line":210},"12":{"name":"(anonymous_12)","decl":{"start":{"line":250,"column":8},"end":{"line":250,"column":25}},"loc":{"start":{"line":253,"column":5},"end":{"line":295,"column":null}},"line":253},"13":{"name":"(anonymous_13)","decl":{"start":{"line":266,"column":41},"end":{"line":266,"column":42}},"loc":{"start":{"line":266,"column":56},"end":{"line":270,"column":8}},"line":266},"14":{"name":"(anonymous_14)","decl":{"start":{"line":279,"column":48},"end":{"line":279,"column":49}},"loc":{"start":{"line":279,"column":63},"end":{"line":285,"column":8}},"line":279},"15":{"name":"(anonymous_15)","decl":{"start":{"line":300,"column":2},"end":{"line":300,"column":25}},"loc":{"start":{"line":300,"column":25},"end":{"line":302,"column":null}},"line":300}},"branchMap":{"0":{"loc":{"start":{"line":27,"column":14},"end":{"line":27,"column":52}},"type":"default-arg","locations":[{"start":{"line":27,"column":48},"end":{"line":27,"column":52}}],"line":27},"1":{"loc":{"start":{"line":29,"column":12},"end":{"line":29,"column":null}},"type":"binary-expr","locations":[{"start":{"line":29,"column":12},"end":{"line":29,"column":27}},{"start":{"line":29,"column":27},"end":{"line":29,"column":null}}],"line":29},"2":{"loc":{"start":{"line":30,"column":12},"end":{"line":30,"column":null}},"type":"binary-expr","locations":[{"start":{"line":30,"column":12},"end":{"line":30,"column":27}},{"start":{"line":30,"column":27},"end":{"line":30,"column":null}}],"line":30},"3":{"loc":{"start":{"line":31,"column":16},"end":{"line":31,"column":null}},"type":"binary-expr","locations":[{"start":{"line":31,"column":16},"end":{"line":31,"column":35}},{"start":{"line":31,"column":35},"end":{"line":31,"column":null}}],"line":31},"4":{"loc":{"start":{"line":32,"column":16},"end":{"line":32,"column":null}},"type":"binary-expr","locations":[{"start":{"line":32,"column":16},"end":{"line":32,"column":35}},{"start":{"line":32,"column":35},"end":{"line":32,"column":null}}],"line":32},"5":{"loc":{"start":{"line":51,"column":6},"end":{"line":66,"column":null}},"type":"if","locations":[{"start":{"line":51,"column":6},"end":{"line":66,"column":null}},{"start":{},"end":{}}],"line":51},"6":{"loc":{"start":{"line":77,"column":6},"end":{"line":77,"column":null}},"type":"binary-expr","locations":[{"start":{"line":77,"column":6},"end":{"line":77,"column":30}},{"start":{"line":77,"column":30},"end":{"line":77,"column":null}}],"line":77},"7":{"loc":{"start":{"line":78,"column":6},"end":{"line":78,"column":null}},"type":"binary-expr","locations":[{"start":{"line":78,"column":6},"end":{"line":78,"column":30}},{"start":{"line":78,"column":30},"end":{"line":78,"column":null}}],"line":78},"8":{"loc":{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},"type":"if","locations":[{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},{"start":{},"end":{}}],"line":90},"9":{"loc":{"start":{"line":90,"column":8},"end":{"line":90,"column":78}},"type":"binary-expr","locations":[{"start":{"line":90,"column":8},"end":{"line":90,"column":44}},{"start":{"line":90,"column":44},"end":{"line":90,"column":78}}],"line":90},"10":{"loc":{"start":{"line":94,"column":20},"end":{"line":94,"column":null}},"type":"cond-expr","locations":[{"start":{"line":94,"column":45},"end":{"line":94,"column":61}},{"start":{"line":94,"column":61},"end":{"line":94,"column":null}}],"line":94},"11":{"loc":{"start":{"line":99,"column":4},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":99,"column":4},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":99},"12":{"loc":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"type":"default-arg","locations":[{"start":{"line":108,"column":34},"end":{"line":108,"column":null}}],"line":108},"13":{"loc":{"start":{"line":110,"column":4},"end":{"line":122,"column":null}},"type":"if","locations":[{"start":{"line":110,"column":4},"end":{"line":122,"column":null}},{"start":{},"end":{}}],"line":110},"14":{"loc":{"start":{"line":119,"column":39},"end":{"line":119,"column":93}},"type":"cond-expr","locations":[{"start":{"line":119,"column":64},"end":{"line":119,"column":80}},{"start":{"line":119,"column":80},"end":{"line":119,"column":93}}],"line":119},"15":{"loc":{"start":{"line":126,"column":49},"end":{"line":126,"column":75}},"type":"cond-expr","locations":[{"start":{"line":126,"column":67},"end":{"line":126,"column":74}},{"start":{"line":126,"column":74},"end":{"line":126,"column":75}}],"line":126},"16":{"loc":{"start":{"line":140,"column":25},"end":{"line":140,"column":null}},"type":"cond-expr","locations":[{"start":{"line":140,"column":50},"end":{"line":140,"column":66}},{"start":{"line":140,"column":66},"end":{"line":140,"column":null}}],"line":140},"17":{"loc":{"start":{"line":142,"column":10},"end":{"line":142,"column":null}},"type":"binary-expr","locations":[{"start":{"line":142,"column":10},"end":{"line":142,"column":47}},{"start":{"line":142,"column":47},"end":{"line":142,"column":null}}],"line":142},"18":{"loc":{"start":{"line":144,"column":8},"end":{"line":149,"column":null}},"type":"if","locations":[{"start":{"line":144,"column":8},"end":{"line":149,"column":null}},{"start":{},"end":{}}],"line":144},"19":{"loc":{"start":{"line":169,"column":20},"end":{"line":169,"column":null}},"type":"cond-expr","locations":[{"start":{"line":169,"column":45},"end":{"line":169,"column":61}},{"start":{"line":169,"column":61},"end":{"line":169,"column":null}}],"line":169},"20":{"loc":{"start":{"line":172,"column":6},"end":{"line":175,"column":null}},"type":"binary-expr","locations":[{"start":{"line":172,"column":6},"end":{"line":172,"column":null}},{"start":{"line":173,"column":6},"end":{"line":173,"column":null}},{"start":{"line":174,"column":6},"end":{"line":174,"column":null}},{"start":{"line":175,"column":6},"end":{"line":175,"column":null}}],"line":172},"21":{"loc":{"start":{"line":190,"column":6},"end":{"line":192,"column":null}},"type":"if","locations":[{"start":{"line":190,"column":6},"end":{"line":192,"column":null}},{"start":{},"end":{}}],"line":190},"22":{"loc":{"start":{"line":214,"column":4},"end":{"line":216,"column":null}},"type":"if","locations":[{"start":{"line":214,"column":4},"end":{"line":216,"column":null}},{"start":{},"end":{}}],"line":214},"23":{"loc":{"start":{"line":214,"column":8},"end":{"line":214,"column":69}},"type":"binary-expr","locations":[{"start":{"line":214,"column":8},"end":{"line":214,"column":39}},{"start":{"line":214,"column":39},"end":{"line":214,"column":69}}],"line":214},"24":{"loc":{"start":{"line":219,"column":4},"end":{"line":223,"column":null}},"type":"if","locations":[{"start":{"line":219,"column":4},"end":{"line":223,"column":null}},{"start":{},"end":{}}],"line":219},"25":{"loc":{"start":{"line":219,"column":8},"end":{"line":219,"column":60}},"type":"binary-expr","locations":[{"start":{"line":219,"column":8},"end":{"line":219,"column":35}},{"start":{"line":219,"column":35},"end":{"line":219,"column":60}}],"line":219},"26":{"loc":{"start":{"line":221,"column":22},"end":{"line":221,"column":null}},"type":"cond-expr","locations":[{"start":{"line":221,"column":35},"end":{"line":221,"column":51}},{"start":{"line":221,"column":51},"end":{"line":221,"column":null}}],"line":221},"27":{"loc":{"start":{"line":226,"column":4},"end":{"line":230,"column":null}},"type":"if","locations":[{"start":{"line":226,"column":4},"end":{"line":230,"column":null}},{"start":{},"end":{}}],"line":226},"28":{"loc":{"start":{"line":228,"column":23},"end":{"line":228,"column":null}},"type":"cond-expr","locations":[{"start":{"line":228,"column":35},"end":{"line":228,"column":50}},{"start":{"line":228,"column":50},"end":{"line":228,"column":null}}],"line":228},"29":{"loc":{"start":{"line":233,"column":4},"end":{"line":235,"column":null}},"type":"if","locations":[{"start":{"line":233,"column":4},"end":{"line":235,"column":null}},{"start":{},"end":{}}],"line":233},"30":{"loc":{"start":{"line":233,"column":8},"end":{"line":233,"column":59}},"type":"binary-expr","locations":[{"start":{"line":233,"column":8},"end":{"line":233,"column":34}},{"start":{"line":233,"column":34},"end":{"line":233,"column":59}}],"line":233},"31":{"loc":{"start":{"line":238,"column":4},"end":{"line":240,"column":null}},"type":"if","locations":[{"start":{"line":238,"column":4},"end":{"line":240,"column":null}},{"start":{},"end":{}}],"line":238},"32":{"loc":{"start":{"line":254,"column":4},"end":{"line":256,"column":null}},"type":"if","locations":[{"start":{"line":254,"column":4},"end":{"line":256,"column":null}},{"start":{},"end":{}}],"line":254},"33":{"loc":{"start":{"line":269,"column":20},"end":{"line":269,"column":null}},"type":"binary-expr","locations":[{"start":{"line":269,"column":20},"end":{"line":269,"column":33}},{"start":{"line":269,"column":33},"end":{"line":269,"column":null}}],"line":269},"34":{"loc":{"start":{"line":284,"column":20},"end":{"line":284,"column":null}},"type":"binary-expr","locations":[{"start":{"line":284,"column":20},"end":{"line":284,"column":33}},{"start":{"line":284,"column":33},"end":{"line":284,"column":null}}],"line":284}},"s":{"0":7,"1":7,"2":7,"3":7,"4":7,"5":7,"6":1,"7":1,"8":1,"9":0,"10":0,"11":0,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":0,"24":0,"25":0,"26":7,"27":7,"28":7,"29":1,"30":0,"31":1,"32":1,"33":0,"34":0,"35":0,"36":0,"37":4,"38":1,"39":1,"40":1,"41":1,"42":3,"43":2,"44":3,"45":3,"46":4,"47":4,"48":4,"49":2,"50":2,"51":2,"52":2,"53":2,"54":2,"55":1,"56":1,"57":1,"58":1,"59":1,"60":4,"61":1,"62":2,"63":2,"64":2,"65":1,"66":1,"67":2,"68":2,"69":2,"70":1,"71":1,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":2,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":0,"101":0,"102":1},"f":{"0":7,"1":1,"2":7,"3":1,"4":0,"5":4,"6":2,"7":2,"8":2,"9":1,"10":0,"11":0,"12":2,"13":1,"14":1,"15":1},"b":{"0":[7],"1":[7,6],"2":[7,6],"3":[7,7],"4":[7,7],"5":[1,0],"6":[7,0],"7":[7,7],"8":[0,1],"9":[1,1],"10":[1,0],"11":[0,0],"12":[4],"13":[1,3],"14":[1,0],"15":[1,1],"16":[2,0],"17":[2,2],"18":[1,1],"19":[2,0],"20":[2,1,1,1],"21":[1,1],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[1,1],"33":[1,0],"34":[1,0]},"meta":{"lastBranch":35,"lastFunction":16,"lastStatement":103,"seen":{"s:24:22:24:Infinity":0,"s:25:40:25:Infinity":1,"f:27:2:27:14":0,"b:27:48:27:52":0,"s:28:4:33:Infinity":2,"b:29:12:29:27:29:27:29:Infinity":1,"b:30:12:30:27:30:27:30:Infinity":2,"b:31:16:31:35:31:35:31:Infinity":3,"b:32:16:32:35:32:35:32:Infinity":4,"s:35:4:35:Infinity":3,"s:37:20:37:Infinity":4,"s:39:4:39:Infinity":5,"f:42:8:42:33":1,"s:43:4:71:Infinity":6,"s:45:22:45:Infinity":7,"s:46:6:46:Infinity":8,"s:47:6:47:Infinity":9,"s:48:6:48:Infinity":10,"s:49:6:49:Infinity":11,"b:51:6:66:Infinity:undefined:undefined:undefined:undefined":5,"s:51:6:66:Infinity":12,"s:52:8:54:Infinity":13,"s:56:8:56:Infinity":14,"s:57:8:57:Infinity":15,"s:58:8:58:Infinity":16,"s:60:24:60:Infinity":17,"s:61:8:61:Infinity":18,"s:62:8:62:Infinity":19,"s:63:8:63:Infinity":20,"s:64:8:64:Infinity":21,"s:65:8:65:Infinity":22,"s:68:6:68:Infinity":23,"s:69:6:69:Infinity":24,"s:70:6:70:Infinity":25,"f:74:10:74:23":2,"s:75:20:75:Infinity":26,"s:76:22:79:Infinity":27,"b:77:6:77:30:77:30:77:Infinity":6,"b:78:6:78:30:78:30:78:Infinity":7,"s:82:4:86:Infinity":28,"f:89:10:89:36":3,"b:90:4:92:Infinity:undefined:undefined:undefined:undefined":8,"s:90:4:92:Infinity":29,"b:90:8:90:44:90:44:90:78":9,"s:91:6:91:Infinity":30,"s:94:20:94:Infinity":31,"b:94:45:94:61:94:61:94:Infinity":10,"s:95:4:95:Infinity":32,"f:98:8:98:36":4,"b:99:4:103:Infinity:undefined:undefined:undefined:undefined":11,"s:99:4:103:Infinity":33,"s:100:6:100:Infinity":34,"s:101:6:101:Infinity":35,"s:102:6:102:Infinity":36,"f:106:8:106:Infinity":5,"b:108:34:108:Infinity":12,"b:110:4:122:Infinity:undefined:undefined:undefined:undefined":13,"s:110:4:122:Infinity":37,"s:111:6:113:Infinity":38,"s:114:6:121:Infinity":39,"s:115:8:115:Infinity":40,"s:117:8:120:Infinity":41,"b:119:64:119:80:119:80:119:93":14,"s:125:28:127:Infinity":42,"f:126:33:126:34":6,"s:126:45:126:76":43,"b:126:67:126:74:126:74:126:75":15,"s:129:4:160:Infinity":44,"s:129:23:129:26":45,"s:130:22:130:Infinity":46,"s:131:6:159:Infinity":47,"s:132:23:132:Infinity":48,"s:133:21:133:Infinity":49,"f:133:40:133:41":7,"s:133:57:133:74":50,"s:135:8:138:Infinity":51,"s:140:25:140:Infinity":52,"b:140:50:140:66:140:66:140:Infinity":16,"s:142:10:142:Infinity":53,"b:142:10:142:47:142:47:142:Infinity":17,"b:144:8:149:Infinity:undefined:undefined:undefined:undefined":18,"s:144:8:149:Infinity":54,"s:145:10:147:Infinity":55,"s:148:10:148:Infinity":56,"s:151:8:151:Infinity":57,"s:152:8:152:Infinity":58,"s:153:8:156:Infinity":59,"s:158:8:158:Infinity":60,"s:162:4:165:Infinity":61,"f:168:10:168:32":8,"s:169:20:169:Infinity":62,"b:169:45:169:61:169:61:169:Infinity":19,"s:170:23:170:Infinity":63,"s:171:4:175:Infinity":64,"b:172:6:172:Infinity:173:6:173:Infinity:174:6:174:Infinity:175:6:175:Infinity":20,"f:179:8:179:21":9,"s:180:35:180:Infinity":65,"s:182:4:193:Infinity":66,"s:183:21:186:Infinity":67,"s:187:6:187:Infinity":68,"b:190:6:192:Infinity:undefined:undefined:undefined:undefined":21,"s:190:6:192:Infinity":69,"s:191:8:191:Infinity":70,"s:195:4:195:Infinity":71,"f:202:8:202:29":10,"s:203:19:203:Infinity":72,"s:204:4:204:Infinity":73,"f:210:10:210:34":11,"s:211:18:211:Infinity":74,"b:214:4:216:Infinity:undefined:undefined:undefined:undefined":22,"s:214:4:216:Infinity":75,"b:214:8:214:39:214:39:214:69":23,"s:215:6:215:Infinity":76,"b:219:4:223:Infinity:undefined:undefined:undefined:undefined":24,"s:219:4:223:Infinity":77,"b:219:8:219:35:219:35:219:60":25,"s:220:25:220:Infinity":78,"s:221:22:221:Infinity":79,"b:221:35:221:51:221:51:221:Infinity":26,"s:222:6:222:Infinity":80,"b:226:4:230:Infinity:undefined:undefined:undefined:undefined":27,"s:226:4:230:Infinity":81,"s:227:24:227:Infinity":82,"s:228:23:228:Infinity":83,"b:228:35:228:50:228:50:228:Infinity":28,"s:229:6:229:Infinity":84,"b:233:4:235:Infinity:undefined:undefined:undefined:undefined":29,"s:233:4:235:Infinity":85,"b:233:8:233:34:233:34:233:59":30,"s:234:6:234:Infinity":86,"b:238:4:240:Infinity:undefined:undefined:undefined:undefined":31,"s:238:4:240:Infinity":87,"s:239:6:239:Infinity":88,"s:243:4:243:Infinity":89,"f:250:8:250:25":12,"b:254:4:256:Infinity:undefined:undefined:undefined:undefined":32,"s:254:4:256:Infinity":90,"s:255:6:255:Infinity":91,"s:258:4:294:Infinity":92,"s:260:26:264:Infinity":93,"s:266:20:270:Infinity":94,"f:266:41:266:42":13,"s:266:56:270:8":95,"b:269:20:269:33:269:33:269:Infinity":33,"s:273:25:277:Infinity":96,"s:279:28:285:Infinity":97,"f:279:48:279:49":14,"s:279:63:285:8":98,"b:284:20:284:33:284:33:284:Infinity":34,"s:287:6:287:Infinity":99,"s:289:6:292:Infinity":100,"s:293:6:293:Infinity":101,"f:300:2:300:25":15,"s:301:4:301:Infinity":102}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/graph/docs-builder.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/graph/docs-builder.ts","statementMap":{"0":{"start":{"line":27,"column":4},"end":{"line":28,"column":null}},"1":{"start":{"line":29,"column":4},"end":{"line":30,"column":null}},"2":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"3":{"start":{"line":32,"column":4},"end":{"line":32,"column":null}},"4":{"start":{"line":51,"column":37},"end":{"line":51,"column":null}},"5":{"start":{"line":52,"column":18},"end":{"line":52,"column":null}},"6":{"start":{"line":54,"column":4},"end":{"line":54,"column":null}},"7":{"start":{"line":56,"column":33},"end":{"line":56,"column":null}},"8":{"start":{"line":57,"column":4},"end":{"line":62,"column":null}},"9":{"start":{"line":58,"column":20},"end":{"line":58,"column":null}},"10":{"start":{"line":59,"column":6},"end":{"line":59,"column":null}},"11":{"start":{"line":60,"column":6},"end":{"line":60,"column":null}},"12":{"start":{"line":61,"column":6},"end":{"line":61,"column":null}},"13":{"start":{"line":65,"column":4},"end":{"line":67,"column":null}},"14":{"start":{"line":65,"column":17},"end":{"line":65,"column":20}},"15":{"start":{"line":66,"column":6},"end":{"line":66,"column":null}},"16":{"start":{"line":70,"column":4},"end":{"line":75,"column":null}},"17":{"start":{"line":71,"column":20},"end":{"line":71,"column":null}},"18":{"start":{"line":72,"column":6},"end":{"line":74,"column":null}},"19":{"start":{"line":73,"column":8},"end":{"line":73,"column":null}},"20":{"start":{"line":77,"column":4},"end":{"line":77,"column":null}},"21":{"start":{"line":83,"column":4},"end":{"line":108,"column":null}},"22":{"start":{"line":116,"column":4},"end":{"line":139,"column":null}},"23":{"start":{"line":143,"column":4},"end":{"line":150,"column":null}},"24":{"start":{"line":154,"column":4},"end":{"line":161,"column":null}},"25":{"start":{"line":178,"column":37},"end":{"line":178,"column":null}},"26":{"start":{"line":181,"column":4},"end":{"line":195,"column":null}},"27":{"start":{"line":198,"column":4},"end":{"line":211,"column":null}},"28":{"start":{"line":213,"column":4},"end":{"line":213,"column":null}},"29":{"start":{"line":219,"column":4},"end":{"line":219,"column":null}},"30":{"start":{"line":223,"column":4},"end":{"line":223,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":21,"column":2},"end":{"line":21,"column":null}},"loc":{"start":{"line":26,"column":4},"end":{"line":33,"column":null}},"line":26},"1":{"name":"(anonymous_1)","decl":{"start":{"line":50,"column":2},"end":{"line":50,"column":21}},"loc":{"start":{"line":50,"column":56},"end":{"line":78,"column":null}},"line":50},"2":{"name":"(anonymous_2)","decl":{"start":{"line":82,"column":10},"end":{"line":82,"column":25}},"loc":{"start":{"line":82,"column":73},"end":{"line":109,"column":null}},"line":82},"3":{"name":"(anonymous_3)","decl":{"start":{"line":111,"column":10},"end":{"line":111,"column":null}},"loc":{"start":{"line":115,"column":21},"end":{"line":140,"column":null}},"line":115},"4":{"name":"(anonymous_4)","decl":{"start":{"line":142,"column":10},"end":{"line":142,"column":26}},"loc":{"start":{"line":142,"column":73},"end":{"line":151,"column":null}},"line":142},"5":{"name":"(anonymous_5)","decl":{"start":{"line":153,"column":10},"end":{"line":153,"column":28}},"loc":{"start":{"line":153,"column":75},"end":{"line":162,"column":null}},"line":153},"6":{"name":"(anonymous_6)","decl":{"start":{"line":173,"column":10},"end":{"line":173,"column":null}},"loc":{"start":{"line":177,"column":23},"end":{"line":214,"column":null}},"line":177},"7":{"name":"(anonymous_7)","decl":{"start":{"line":218,"column":10},"end":{"line":218,"column":16}},"loc":{"start":{"line":218,"column":46},"end":{"line":220,"column":null}},"line":218},"8":{"name":"(anonymous_8)","decl":{"start":{"line":222,"column":10},"end":{"line":222,"column":20}},"loc":{"start":{"line":222,"column":65},"end":{"line":224,"column":null}},"line":222}},"branchMap":{"0":{"loc":{"start":{"line":28,"column":6},"end":{"line":28,"column":null}},"type":"binary-expr","locations":[{"start":{"line":28,"column":6},"end":{"line":28,"column":23}},{"start":{"line":28,"column":23},"end":{"line":28,"column":51}},{"start":{"line":28,"column":51},"end":{"line":28,"column":null}}],"line":28},"1":{"loc":{"start":{"line":30,"column":6},"end":{"line":30,"column":null}},"type":"binary-expr","locations":[{"start":{"line":30,"column":6},"end":{"line":30,"column":19}},{"start":{"line":30,"column":19},"end":{"line":30,"column":43}},{"start":{"line":30,"column":43},"end":{"line":30,"column":null}}],"line":30},"2":{"loc":{"start":{"line":31,"column":16},"end":{"line":31,"column":null}},"type":"binary-expr","locations":[{"start":{"line":31,"column":16},"end":{"line":31,"column":24}},{"start":{"line":31,"column":24},"end":{"line":31,"column":43}},{"start":{"line":31,"column":43},"end":{"line":31,"column":null}}],"line":31},"3":{"loc":{"start":{"line":32,"column":23},"end":{"line":32,"column":null}},"type":"binary-expr","locations":[{"start":{"line":32,"column":23},"end":{"line":32,"column":38}},{"start":{"line":32,"column":38},"end":{"line":32,"column":null}}],"line":32}},"s":{"0":49,"1":49,"2":49,"3":49,"4":52,"5":52,"6":52,"7":52,"8":52,"9":202,"10":202,"11":202,"12":202,"13":52,"14":52,"15":151,"16":52,"17":202,"18":202,"19":313,"20":52,"21":52,"22":202,"23":202,"24":151,"25":313,"26":313,"27":313,"28":313,"29":52,"30":404},"f":{"0":49,"1":52,"2":52,"3":202,"4":202,"5":151,"6":313,"7":52,"8":404},"b":{"0":[49,21,0],"1":[49,0,0],"2":[49,0,0],"3":[49,0]},"meta":{"lastBranch":4,"lastFunction":9,"lastStatement":31,"seen":{"f:21:2:21:Infinity":0,"s:27:4:28:Infinity":0,"b:28:6:28:23:28:23:28:51:28:51:28:Infinity":0,"s:29:4:30:Infinity":1,"b:30:6:30:19:30:19:30:43:30:43:30:Infinity":1,"s:31:4:31:Infinity":2,"b:31:16:31:24:31:24:31:43:31:43:31:Infinity":2,"s:32:4:32:Infinity":3,"b:32:23:32:38:32:38:32:Infinity":3,"f:50:2:50:21":1,"s:51:37:51:Infinity":4,"s:52:18:52:Infinity":5,"s:54:4:54:Infinity":6,"s:56:33:56:Infinity":7,"s:57:4:62:Infinity":8,"s:58:20:58:Infinity":9,"s:59:6:59:Infinity":10,"s:60:6:60:Infinity":11,"s:61:6:61:Infinity":12,"s:65:4:67:Infinity":13,"s:65:17:65:20":14,"s:66:6:66:Infinity":15,"s:70:4:75:Infinity":16,"s:71:20:71:Infinity":17,"s:72:6:74:Infinity":18,"s:73:8:73:Infinity":19,"s:77:4:77:Infinity":20,"f:82:10:82:25":2,"s:83:4:108:Infinity":21,"f:111:10:111:Infinity":3,"s:116:4:139:Infinity":22,"f:142:10:142:26":4,"s:143:4:150:Infinity":23,"f:153:10:153:28":5,"s:154:4:161:Infinity":24,"f:173:10:173:Infinity":6,"s:178:37:178:Infinity":25,"s:181:4:195:Infinity":26,"s:198:4:211:Infinity":27,"s:213:4:213:Infinity":28,"f:218:10:218:16":7,"s:219:4:219:Infinity":29,"f:222:10:222:20":8,"s:223:4:223:Infinity":30}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/graph/hybrid-retriever.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/graph/hybrid-retriever.ts","statementMap":{"0":{"start":{"line":30,"column":53},"end":{"line":30,"column":null}},"1":{"start":{"line":37,"column":12},"end":{"line":37,"column":null}},"2":{"start":{"line":38,"column":12},"end":{"line":38,"column":null}},"3":{"start":{"line":39,"column":12},"end":{"line":39,"column":null}},"4":{"start":{"line":33,"column":4},"end":{"line":33,"column":null}},"5":{"start":{"line":43,"column":17},"end":{"line":43,"column":null}},"6":{"start":{"line":44,"column":18},"end":{"line":44,"column":null}},"7":{"start":{"line":45,"column":17},"end":{"line":45,"column":null}},"8":{"start":{"line":48,"column":6},"end":{"line":50,"column":null}},"9":{"start":{"line":52,"column":6},"end":{"line":54,"column":null}},"10":{"start":{"line":56,"column":20},"end":{"line":59,"column":null}},"11":{"start":{"line":57,"column":21},"end":{"line":57,"column":32}},"12":{"start":{"line":62,"column":6},"end":{"line":64,"column":null}},"13":{"start":{"line":66,"column":18},"end":{"line":66,"column":null}},"14":{"start":{"line":67,"column":26},"end":{"line":67,"column":null}},"15":{"start":{"line":68,"column":21},"end":{"line":68,"column":null}},"16":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"17":{"start":{"line":77,"column":18},"end":{"line":77,"column":null}},"18":{"start":{"line":78,"column":31},"end":{"line":78,"column":null}},"19":{"start":{"line":80,"column":4},"end":{"line":99,"column":null}},"20":{"start":{"line":81,"column":6},"end":{"line":98,"column":null}},"21":{"start":{"line":82,"column":44},"end":{"line":86,"column":null}},"22":{"start":{"line":88,"column":23},"end":{"line":88,"column":null}},"23":{"start":{"line":89,"column":8},"end":{"line":95,"column":null}},"24":{"start":{"line":90,"column":10},"end":{"line":94,"column":null}},"25":{"start":{"line":101,"column":4},"end":{"line":103,"column":null}},"26":{"start":{"line":102,"column":6},"end":{"line":102,"column":null}},"27":{"start":{"line":105,"column":4},"end":{"line":105,"column":null}},"28":{"start":{"line":112,"column":18},"end":{"line":112,"column":null}},"29":{"start":{"line":114,"column":4},"end":{"line":149,"column":null}},"30":{"start":{"line":115,"column":6},"end":{"line":148,"column":null}},"31":{"start":{"line":116,"column":25},"end":{"line":131,"column":null}},"32":{"start":{"line":133,"column":8},"end":{"line":145,"column":null}},"33":{"start":{"line":134,"column":10},"end":{"line":134,"column":null}},"34":{"start":{"line":135,"column":10},"end":{"line":144,"column":null}},"35":{"start":{"line":136,"column":52},"end":{"line":140,"column":14}},"36":{"start":{"line":142,"column":23},"end":{"line":142,"column":null}},"37":{"start":{"line":151,"column":4},"end":{"line":151,"column":null}},"38":{"start":{"line":152,"column":4},"end":{"line":152,"column":null}},"39":{"start":{"line":160,"column":4},"end":{"line":166,"column":null}},"40":{"start":{"line":161,"column":6},"end":{"line":165,"column":null}},"41":{"start":{"line":167,"column":4},"end":{"line":203,"column":null}},"42":{"start":{"line":168,"column":20},"end":{"line":171,"column":null}},"43":{"start":{"line":172,"column":12},"end":{"line":174,"column":null}},"44":{"start":{"line":173,"column":40},"end":{"line":173,"column":null}},"45":{"start":{"line":175,"column":6},"end":{"line":184,"column":null}},"46":{"start":{"line":177,"column":8},"end":{"line":182,"column":null}},"47":{"start":{"line":178,"column":10},"end":{"line":181,"column":null}},"48":{"start":{"line":183,"column":8},"end":{"line":183,"column":null}},"49":{"start":{"line":185,"column":6},"end":{"line":188,"column":null}},"50":{"start":{"line":190,"column":6},"end":{"line":195,"column":null}},"51":{"start":{"line":191,"column":8},"end":{"line":194,"column":null}},"52":{"start":{"line":196,"column":6},"end":{"line":196,"column":null}},"53":{"start":{"line":198,"column":6},"end":{"line":202,"column":null}},"54":{"start":{"line":210,"column":18},"end":{"line":210,"column":null}},"55":{"start":{"line":211,"column":4},"end":{"line":213,"column":null}},"56":{"start":{"line":212,"column":6},"end":{"line":212,"column":null}},"57":{"start":{"line":215,"column":43},"end":{"line":222,"column":null}},"58":{"start":{"line":224,"column":19},"end":{"line":224,"column":null}},"59":{"start":{"line":226,"column":4},"end":{"line":235,"column":null}},"60":{"start":{"line":227,"column":23},"end":{"line":227,"column":null}},"61":{"start":{"line":228,"column":23},"end":{"line":228,"column":null}},"62":{"start":{"line":230,"column":6},"end":{"line":234,"column":null}},"63":{"start":{"line":231,"column":23},"end":{"line":231,"column":null}},"64":{"start":{"line":232,"column":22},"end":{"line":232,"column":null}},"65":{"start":{"line":233,"column":8},"end":{"line":233,"column":null}},"66":{"start":{"line":237,"column":4},"end":{"line":239,"column":null}},"67":{"start":{"line":238,"column":6},"end":{"line":238,"column":null}},"68":{"start":{"line":241,"column":4},"end":{"line":248,"column":null}},"69":{"start":{"line":242,"column":22},"end":{"line":242,"column":33}},"70":{"start":{"line":244,"column":33},"end":{"line":248,"column":8}},"71":{"start":{"line":252,"column":19},"end":{"line":252,"column":null}},"72":{"start":{"line":253,"column":25},"end":{"line":256,"column":null}},"73":{"start":{"line":258,"column":4},"end":{"line":268,"column":null}},"74":{"start":{"line":259,"column":6},"end":{"line":267,"column":null}},"75":{"start":{"line":260,"column":21},"end":{"line":260,"column":null}},"76":{"start":{"line":261,"column":20},"end":{"line":261,"column":null}},"77":{"start":{"line":262,"column":8},"end":{"line":262,"column":null}},"78":{"start":{"line":264,"column":25},"end":{"line":264,"column":null}},"79":{"start":{"line":265,"column":8},"end":{"line":265,"column":null}},"80":{"start":{"line":266,"column":8},"end":{"line":266,"column":null}},"81":{"start":{"line":270,"column":4},"end":{"line":282,"column":null}},"82":{"start":{"line":271,"column":22},"end":{"line":271,"column":33}},"83":{"start":{"line":273,"column":21},"end":{"line":273,"column":null}},"84":{"start":{"line":274,"column":8},"end":{"line":281,"column":null}},"85":{"start":{"line":291,"column":19},"end":{"line":294,"column":null}},"86":{"start":{"line":294,"column":25},"end":{"line":294,"column":42}},"87":{"start":{"line":296,"column":18},"end":{"line":300,"column":null}},"88":{"start":{"line":302,"column":4},"end":{"line":313,"column":null}},"89":{"start":{"line":304,"column":18},"end":{"line":304,"column":null}},"90":{"start":{"line":306,"column":22},"end":{"line":310,"column":8}},"91":{"start":{"line":311,"column":23},"end":{"line":311,"column":36}},"92":{"start":{"line":312,"column":22},"end":{"line":312,"column":39}},"93":{"start":{"line":318,"column":6},"end":{"line":318,"column":null}},"94":{"start":{"line":319,"column":4},"end":{"line":322,"column":null}},"95":{"start":{"line":320,"column":22},"end":{"line":320,"column":null}},"96":{"start":{"line":330,"column":17},"end":{"line":330,"column":null}},"97":{"start":{"line":331,"column":4},"end":{"line":337,"column":null}},"98":{"start":{"line":332,"column":6},"end":{"line":336,"column":null}},"99":{"start":{"line":339,"column":4},"end":{"line":343,"column":null}},"100":{"start":{"line":350,"column":4},"end":{"line":352,"column":null}},"101":{"start":{"line":351,"column":6},"end":{"line":351,"column":null}},"102":{"start":{"line":354,"column":20},"end":{"line":354,"column":null}},"103":{"start":{"line":354,"column":48},"end":{"line":354,"column":66}},"104":{"start":{"line":355,"column":4},"end":{"line":355,"column":null}},"105":{"start":{"line":355,"column":35},"end":{"line":355,"column":70}},"106":{"start":{"line":362,"column":4},"end":{"line":365,"column":null}},"107":{"start":{"line":363,"column":19},"end":{"line":363,"column":null}},"108":{"start":{"line":364,"column":6},"end":{"line":364,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":36,"column":2},"end":{"line":36,"column":null}},"loc":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"line":40},"1":{"name":"(anonymous_1)","decl":{"start":{"line":32,"column":6},"end":{"line":32,"column":48}},"loc":{"start":{"line":32,"column":48},"end":{"line":34,"column":null}},"line":32},"2":{"name":"(anonymous_2)","decl":{"start":{"line":42,"column":8},"end":{"line":42,"column":17}},"loc":{"start":{"line":42,"column":69},"end":{"line":71,"column":null}},"line":42},"3":{"name":"(anonymous_3)","decl":{"start":{"line":57,"column":11},"end":{"line":57,"column":12}},"loc":{"start":{"line":57,"column":21},"end":{"line":57,"column":32}},"line":57},"4":{"name":"(anonymous_4)","decl":{"start":{"line":73,"column":16},"end":{"line":73,"column":null}},"loc":{"start":{"line":76,"column":27},"end":{"line":106,"column":null}},"line":76},"5":{"name":"(anonymous_5)","decl":{"start":{"line":89,"column":23},"end":{"line":89,"column":24}},"loc":{"start":{"line":89,"column":41},"end":{"line":95,"column":9}},"line":89},"6":{"name":"(anonymous_6)","decl":{"start":{"line":108,"column":16},"end":{"line":108,"column":null}},"loc":{"start":{"line":111,"column":27},"end":{"line":153,"column":null}},"line":111},"7":{"name":"(anonymous_7)","decl":{"start":{"line":136,"column":17},"end":{"line":136,"column":18}},"loc":{"start":{"line":136,"column":52},"end":{"line":140,"column":14}},"line":136},"8":{"name":"(anonymous_8)","decl":{"start":{"line":142,"column":14},"end":{"line":142,"column":15}},"loc":{"start":{"line":142,"column":23},"end":{"line":142,"column":null}},"line":142},"9":{"name":"(anonymous_9)","decl":{"start":{"line":155,"column":8},"end":{"line":155,"column":null}},"loc":{"start":{"line":159,"column":5},"end":{"line":204,"column":null}},"line":159},"10":{"name":"(anonymous_10)","decl":{"start":{"line":173,"column":8},"end":{"line":173,"column":9}},"loc":{"start":{"line":173,"column":40},"end":{"line":173,"column":null}},"line":173},"11":{"name":"(anonymous_11)","decl":{"start":{"line":206,"column":16},"end":{"line":206,"column":null}},"loc":{"start":{"line":209,"column":27},"end":{"line":249,"column":null}},"line":209},"12":{"name":"(anonymous_12)","decl":{"start":{"line":242,"column":12},"end":{"line":242,"column":13}},"loc":{"start":{"line":242,"column":22},"end":{"line":242,"column":33}},"line":242},"13":{"name":"(anonymous_13)","decl":{"start":{"line":244,"column":11},"end":{"line":244,"column":12}},"loc":{"start":{"line":244,"column":33},"end":{"line":248,"column":8}},"line":244},"14":{"name":"(anonymous_14)","decl":{"start":{"line":251,"column":10},"end":{"line":251,"column":20}},"loc":{"start":{"line":251,"column":73},"end":{"line":283,"column":null}},"line":251},"15":{"name":"(anonymous_15)","decl":{"start":{"line":258,"column":18},"end":{"line":258,"column":19}},"loc":{"start":{"line":258,"column":28},"end":{"line":268,"column":5}},"line":258},"16":{"name":"(anonymous_16)","decl":{"start":{"line":259,"column":19},"end":{"line":259,"column":20}},"loc":{"start":{"line":259,"column":34},"end":{"line":267,"column":7}},"line":259},"17":{"name":"(anonymous_17)","decl":{"start":{"line":271,"column":12},"end":{"line":271,"column":13}},"loc":{"start":{"line":271,"column":22},"end":{"line":271,"column":33}},"line":271},"18":{"name":"(anonymous_18)","decl":{"start":{"line":272,"column":11},"end":{"line":272,"column":12}},"loc":{"start":{"line":272,"column":35},"end":{"line":282,"column":7}},"line":272},"19":{"name":"(anonymous_19)","decl":{"start":{"line":285,"column":10},"end":{"line":285,"column":null}},"loc":{"start":{"line":290,"column":18},"end":{"line":314,"column":null}},"line":290},"20":{"name":"(anonymous_20)","decl":{"start":{"line":294,"column":14},"end":{"line":294,"column":15}},"loc":{"start":{"line":294,"column":25},"end":{"line":294,"column":42}},"line":294},"21":{"name":"(anonymous_21)","decl":{"start":{"line":304,"column":8},"end":{"line":304,"column":9}},"loc":{"start":{"line":304,"column":18},"end":{"line":304,"column":null}},"line":304},"22":{"name":"(anonymous_22)","decl":{"start":{"line":306,"column":11},"end":{"line":306,"column":12}},"loc":{"start":{"line":306,"column":22},"end":{"line":310,"column":8}},"line":306},"23":{"name":"(anonymous_23)","decl":{"start":{"line":311,"column":14},"end":{"line":311,"column":15}},"loc":{"start":{"line":311,"column":23},"end":{"line":311,"column":36}},"line":311},"24":{"name":"(anonymous_24)","decl":{"start":{"line":312,"column":12},"end":{"line":312,"column":13}},"loc":{"start":{"line":312,"column":22},"end":{"line":312,"column":39}},"line":312},"25":{"name":"(anonymous_25)","decl":{"start":{"line":316,"column":10},"end":{"line":316,"column":20}},"loc":{"start":{"line":316,"column":63},"end":{"line":323,"column":null}},"line":316},"26":{"name":"(anonymous_26)","decl":{"start":{"line":320,"column":6},"end":{"line":320,"column":7}},"loc":{"start":{"line":320,"column":22},"end":{"line":320,"column":null}},"line":320},"27":{"name":"(anonymous_27)","decl":{"start":{"line":325,"column":10},"end":{"line":325,"column":19}},"loc":{"start":{"line":329,"column":4},"end":{"line":344,"column":null}},"line":329},"28":{"name":"(anonymous_28)","decl":{"start":{"line":346,"column":10},"end":{"line":346,"column":null}},"loc":{"start":{"line":349,"column":23},"end":{"line":356,"column":null}},"line":349},"29":{"name":"(anonymous_29)","decl":{"start":{"line":354,"column":38},"end":{"line":354,"column":39}},"loc":{"start":{"line":354,"column":48},"end":{"line":354,"column":66}},"line":354},"30":{"name":"(anonymous_30)","decl":{"start":{"line":355,"column":26},"end":{"line":355,"column":27}},"loc":{"start":{"line":355,"column":35},"end":{"line":355,"column":70}},"line":355},"31":{"name":"(anonymous_31)","decl":{"start":{"line":358,"column":10},"end":{"line":358,"column":null}},"loc":{"start":{"line":361,"column":23},"end":{"line":366,"column":null}},"line":361},"32":{"name":"(anonymous_32)","decl":{"start":{"line":362,"column":26},"end":{"line":362,"column":27}},"loc":{"start":{"line":362,"column":35},"end":{"line":365,"column":5}},"line":362}},"branchMap":{"0":{"loc":{"start":{"line":43,"column":17},"end":{"line":43,"column":null}},"type":"binary-expr","locations":[{"start":{"line":43,"column":17},"end":{"line":43,"column":30}},{"start":{"line":43,"column":30},"end":{"line":43,"column":null}}],"line":43},"1":{"loc":{"start":{"line":44,"column":39},"end":{"line":44,"column":57}},"type":"binary-expr","locations":[{"start":{"line":44,"column":39},"end":{"line":44,"column":53}},{"start":{"line":44,"column":53},"end":{"line":44,"column":57}}],"line":44},"2":{"loc":{"start":{"line":45,"column":17},"end":{"line":45,"column":null}},"type":"binary-expr","locations":[{"start":{"line":45,"column":17},"end":{"line":45,"column":30}},{"start":{"line":45,"column":30},"end":{"line":45,"column":null}}],"line":45},"3":{"loc":{"start":{"line":48,"column":6},"end":{"line":50,"column":null}},"type":"cond-expr","locations":[{"start":{"line":49,"column":10},"end":{"line":49,"column":null}},{"start":{"line":50,"column":10},"end":{"line":50,"column":null}}],"line":48},"4":{"loc":{"start":{"line":48,"column":6},"end":{"line":48,"column":null}},"type":"binary-expr","locations":[{"start":{"line":48,"column":6},"end":{"line":48,"column":27}},{"start":{"line":48,"column":27},"end":{"line":48,"column":null}}],"line":48},"5":{"loc":{"start":{"line":52,"column":6},"end":{"line":54,"column":null}},"type":"cond-expr","locations":[{"start":{"line":53,"column":10},"end":{"line":53,"column":null}},{"start":{"line":54,"column":10},"end":{"line":54,"column":null}}],"line":52},"6":{"loc":{"start":{"line":52,"column":6},"end":{"line":52,"column":null}},"type":"binary-expr","locations":[{"start":{"line":52,"column":6},"end":{"line":52,"column":25}},{"start":{"line":52,"column":25},"end":{"line":52,"column":null}}],"line":52},"7":{"loc":{"start":{"line":62,"column":6},"end":{"line":64,"column":null}},"type":"cond-expr","locations":[{"start":{"line":63,"column":10},"end":{"line":63,"column":null}},{"start":{"line":64,"column":10},"end":{"line":64,"column":null}}],"line":62},"8":{"loc":{"start":{"line":62,"column":6},"end":{"line":62,"column":null}},"type":"binary-expr","locations":[{"start":{"line":62,"column":6},"end":{"line":62,"column":26}},{"start":{"line":62,"column":26},"end":{"line":62,"column":null}}],"line":62},"9":{"loc":{"start":{"line":77,"column":39},"end":{"line":77,"column":57}},"type":"binary-expr","locations":[{"start":{"line":77,"column":39},"end":{"line":77,"column":53}},{"start":{"line":77,"column":53},"end":{"line":77,"column":57}}],"line":77},"10":{"loc":{"start":{"line":80,"column":4},"end":{"line":99,"column":null}},"type":"if","locations":[{"start":{"line":80,"column":4},"end":{"line":99,"column":null}},{"start":{},"end":{}}],"line":80},"11":{"loc":{"start":{"line":101,"column":4},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":4},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":101},"12":{"loc":{"start":{"line":112,"column":39},"end":{"line":112,"column":57}},"type":"binary-expr","locations":[{"start":{"line":112,"column":39},"end":{"line":112,"column":53}},{"start":{"line":112,"column":53},"end":{"line":112,"column":57}}],"line":112},"13":{"loc":{"start":{"line":114,"column":4},"end":{"line":149,"column":null}},"type":"if","locations":[{"start":{"line":114,"column":4},"end":{"line":149,"column":null}},{"start":{},"end":{}}],"line":114},"14":{"loc":{"start":{"line":133,"column":8},"end":{"line":145,"column":null}},"type":"if","locations":[{"start":{"line":133,"column":8},"end":{"line":145,"column":null}},{"start":{},"end":{}}],"line":133},"15":{"loc":{"start":{"line":133,"column":12},"end":{"line":133,"column":57}},"type":"binary-expr","locations":[{"start":{"line":133,"column":12},"end":{"line":133,"column":31}},{"start":{"line":133,"column":31},"end":{"line":133,"column":57}}],"line":133},"16":{"loc":{"start":{"line":137,"column":29},"end":{"line":137,"column":45}},"type":"binary-expr","locations":[{"start":{"line":137,"column":29},"end":{"line":137,"column":43}},{"start":{"line":137,"column":43},"end":{"line":137,"column":45}}],"line":137},"17":{"loc":{"start":{"line":138,"column":28},"end":{"line":138,"column":42}},"type":"binary-expr","locations":[{"start":{"line":138,"column":28},"end":{"line":138,"column":41}},{"start":{"line":138,"column":41},"end":{"line":138,"column":42}}],"line":138},"18":{"loc":{"start":{"line":142,"column":23},"end":{"line":142,"column":null}},"type":"binary-expr","locations":[{"start":{"line":142,"column":23},"end":{"line":142,"column":48}},{"start":{"line":142,"column":48},"end":{"line":142,"column":null}}],"line":142},"19":{"loc":{"start":{"line":160,"column":4},"end":{"line":166,"column":null}},"type":"if","locations":[{"start":{"line":160,"column":4},"end":{"line":166,"column":null}},{"start":{},"end":{}}],"line":160},"20":{"loc":{"start":{"line":172,"column":31},"end":{"line":172,"column":49}},"type":"binary-expr","locations":[{"start":{"line":172,"column":31},"end":{"line":172,"column":45}},{"start":{"line":172,"column":45},"end":{"line":172,"column":49}}],"line":172},"21":{"loc":{"start":{"line":173,"column":47},"end":{"line":173,"column":62}},"type":"binary-expr","locations":[{"start":{"line":173,"column":47},"end":{"line":173,"column":60}},{"start":{"line":173,"column":60},"end":{"line":173,"column":62}}],"line":173},"22":{"loc":{"start":{"line":175,"column":6},"end":{"line":184,"column":null}},"type":"if","locations":[{"start":{"line":175,"column":6},"end":{"line":184,"column":null}},{"start":{},"end":{}}],"line":175},"23":{"loc":{"start":{"line":177,"column":8},"end":{"line":182,"column":null}},"type":"if","locations":[{"start":{"line":177,"column":8},"end":{"line":182,"column":null}},{"start":{},"end":{}}],"line":177},"24":{"loc":{"start":{"line":190,"column":6},"end":{"line":195,"column":null}},"type":"if","locations":[{"start":{"line":190,"column":6},"end":{"line":195,"column":null}},{"start":{},"end":{}}],"line":190},"25":{"loc":{"start":{"line":201,"column":15},"end":{"line":201,"column":null}},"type":"cond-expr","locations":[{"start":{"line":201,"column":38},"end":{"line":201,"column":52}},{"start":{"line":201,"column":52},"end":{"line":201,"column":null}}],"line":201},"26":{"loc":{"start":{"line":210,"column":39},"end":{"line":210,"column":57}},"type":"binary-expr","locations":[{"start":{"line":210,"column":39},"end":{"line":210,"column":53}},{"start":{"line":210,"column":53},"end":{"line":210,"column":57}}],"line":210},"27":{"loc":{"start":{"line":211,"column":4},"end":{"line":213,"column":null}},"type":"if","locations":[{"start":{"line":211,"column":4},"end":{"line":213,"column":null}},{"start":{},"end":{}}],"line":211},"28":{"loc":{"start":{"line":231,"column":23},"end":{"line":231,"column":null}},"type":"cond-expr","locations":[{"start":{"line":231,"column":45},"end":{"line":231,"column":54}},{"start":{"line":231,"column":54},"end":{"line":231,"column":null}}],"line":231},"29":{"loc":{"start":{"line":232,"column":22},"end":{"line":232,"column":null}},"type":"binary-expr","locations":[{"start":{"line":232,"column":22},"end":{"line":232,"column":42}},{"start":{"line":232,"column":42},"end":{"line":232,"column":null}}],"line":232},"30":{"loc":{"start":{"line":233,"column":28},"end":{"line":233,"column":55}},"type":"binary-expr","locations":[{"start":{"line":233,"column":28},"end":{"line":233,"column":50}},{"start":{"line":233,"column":50},"end":{"line":233,"column":55}}],"line":233},"31":{"loc":{"start":{"line":237,"column":4},"end":{"line":239,"column":null}},"type":"if","locations":[{"start":{"line":237,"column":4},"end":{"line":239,"column":null}},{"start":{},"end":{}}],"line":237},"32":{"loc":{"start":{"line":262,"column":33},"end":{"line":262,"column":65}},"type":"binary-expr","locations":[{"start":{"line":262,"column":33},"end":{"line":262,"column":60}},{"start":{"line":262,"column":60},"end":{"line":262,"column":65}}],"line":262},"33":{"loc":{"start":{"line":264,"column":25},"end":{"line":264,"column":null}},"type":"binary-expr","locations":[{"start":{"line":264,"column":25},"end":{"line":264,"column":58}},{"start":{"line":264,"column":58},"end":{"line":264,"column":null}}],"line":264},"34":{"loc":{"start":{"line":280,"column":18},"end":{"line":280,"column":null}},"type":"binary-expr","locations":[{"start":{"line":280,"column":18},"end":{"line":280,"column":46}},{"start":{"line":280,"column":46},"end":{"line":280,"column":null}}],"line":280},"35":{"loc":{"start":{"line":304,"column":25},"end":{"line":304,"column":56}},"type":"binary-expr","locations":[{"start":{"line":304,"column":25},"end":{"line":304,"column":54}},{"start":{"line":304,"column":54},"end":{"line":304,"column":56}}],"line":304},"36":{"loc":{"start":{"line":318,"column":20},"end":{"line":318,"column":46}},"type":"binary-expr","locations":[{"start":{"line":318,"column":20},"end":{"line":318,"column":44}},{"start":{"line":318,"column":44},"end":{"line":318,"column":46}}],"line":318},"37":{"loc":{"start":{"line":318,"column":50},"end":{"line":318,"column":76}},"type":"binary-expr","locations":[{"start":{"line":318,"column":50},"end":{"line":318,"column":74}},{"start":{"line":318,"column":74},"end":{"line":318,"column":76}}],"line":318},"38":{"loc":{"start":{"line":318,"column":80},"end":{"line":318,"column":109}},"type":"binary-expr","locations":[{"start":{"line":318,"column":80},"end":{"line":318,"column":107}},{"start":{"line":318,"column":107},"end":{"line":318,"column":109}}],"line":318},"39":{"loc":{"start":{"line":320,"column":29},"end":{"line":320,"column":null}},"type":"cond-expr","locations":[{"start":{"line":320,"column":56},"end":{"line":320,"column":60}},{"start":{"line":320,"column":60},"end":{"line":320,"column":null}}],"line":320},"40":{"loc":{"start":{"line":331,"column":4},"end":{"line":337,"column":null}},"type":"if","locations":[{"start":{"line":331,"column":4},"end":{"line":337,"column":null}},{"start":{},"end":{}}],"line":331},"41":{"loc":{"start":{"line":340,"column":19},"end":{"line":340,"column":74}},"type":"binary-expr","locations":[{"start":{"line":340,"column":19},"end":{"line":340,"column":43}},{"start":{"line":340,"column":43},"end":{"line":340,"column":67}},{"start":{"line":340,"column":67},"end":{"line":340,"column":74}}],"line":340},"42":{"loc":{"start":{"line":341,"column":23},"end":{"line":341,"column":77}},"type":"binary-expr","locations":[{"start":{"line":341,"column":23},"end":{"line":341,"column":47}},{"start":{"line":341,"column":47},"end":{"line":341,"column":75}},{"start":{"line":341,"column":75},"end":{"line":341,"column":77}}],"line":341},"43":{"loc":{"start":{"line":342,"column":19},"end":{"line":342,"column":41}},"type":"binary-expr","locations":[{"start":{"line":342,"column":19},"end":{"line":342,"column":32}},{"start":{"line":342,"column":32},"end":{"line":342,"column":41}}],"line":342},"44":{"loc":{"start":{"line":350,"column":4},"end":{"line":352,"column":null}},"type":"if","locations":[{"start":{"line":350,"column":4},"end":{"line":352,"column":null}},{"start":{},"end":{}}],"line":350},"45":{"loc":{"start":{"line":364,"column":20},"end":{"line":364,"column":53}},"type":"binary-expr","locations":[{"start":{"line":364,"column":20},"end":{"line":364,"column":51}},{"start":{"line":364,"column":51},"end":{"line":364,"column":53}}],"line":364}},"s":{"0":59,"1":59,"2":59,"3":59,"4":8,"5":2,"6":2,"7":2,"8":2,"9":2,"10":2,"11":3,"12":2,"13":2,"14":2,"15":2,"16":2,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":2,"29":2,"30":2,"31":2,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":2,"72":2,"73":2,"74":6,"75":3,"76":3,"77":3,"78":3,"79":3,"80":3,"81":2,"82":1,"83":3,"84":3,"85":1,"86":1,"87":1,"88":1,"89":3,"90":2,"91":2,"92":1,"93":2,"94":2,"95":2,"96":3,"97":3,"98":0,"99":3,"100":2,"101":2,"102":0,"103":0,"104":0,"105":0,"106":2,"107":3,"108":3},"f":{"0":59,"1":8,"2":2,"3":3,"4":0,"5":0,"6":2,"7":1,"8":1,"9":0,"10":0,"11":0,"12":0,"13":0,"14":2,"15":6,"16":3,"17":1,"18":3,"19":1,"20":1,"21":3,"22":2,"23":2,"24":1,"25":2,"26":2,"27":3,"28":2,"29":0,"30":0,"31":2,"32":3},"b":{"0":[2,0],"1":[2,0],"2":[2,2],"3":[0,2],"4":[2,2],"5":[2,0],"6":[2,0],"7":[0,2],"8":[2,2],"9":[0,0],"10":[0,0],"11":[0,0],"12":[2,0],"13":[2,0],"14":[1,0],"15":[1,1],"16":[1,0],"17":[1,0],"18":[1,1],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[3,3],"33":[3,3],"34":[3,0],"35":[3,0],"36":[2,0],"37":[2,0],"38":[2,0],"39":[2,0],"40":[0,3],"41":[3,0,0],"42":[3,0,0],"43":[3,0],"44":[2,0],"45":[3,0]},"meta":{"lastBranch":46,"lastFunction":33,"lastStatement":109,"seen":{"s:30:53:30:Infinity":0,"f:36:2:36:Infinity":0,"s:37:12:37:Infinity":1,"s:38:12:38:Infinity":2,"s:39:12:39:Infinity":3,"f:32:6:32:48":1,"s:33:4:33:Infinity":4,"f:42:8:42:17":2,"s:43:17:43:Infinity":5,"b:43:17:43:30:43:30:43:Infinity":0,"s:44:18:44:Infinity":6,"b:44:39:44:53:44:53:44:57":1,"s:45:17:45:Infinity":7,"b:45:17:45:30:45:30:45:Infinity":2,"s:48:6:50:Infinity":8,"b:49:10:49:Infinity:50:10:50:Infinity":3,"b:48:6:48:27:48:27:48:Infinity":4,"s:52:6:54:Infinity":9,"b:53:10:53:Infinity:54:10:54:Infinity":5,"b:52:6:52:25:52:25:52:Infinity":6,"s:56:20:59:Infinity":10,"f:57:11:57:12":3,"s:57:21:57:32":11,"s:62:6:64:Infinity":12,"b:63:10:63:Infinity:64:10:64:Infinity":7,"b:62:6:62:26:62:26:62:Infinity":8,"s:66:18:66:Infinity":13,"s:67:26:67:Infinity":14,"s:68:21:68:Infinity":15,"s:70:4:70:Infinity":16,"f:73:16:73:Infinity":4,"s:77:18:77:Infinity":17,"b:77:39:77:53:77:53:77:57":9,"s:78:31:78:Infinity":18,"b:80:4:99:Infinity:undefined:undefined:undefined:undefined":10,"s:80:4:99:Infinity":19,"s:81:6:98:Infinity":20,"s:82:44:86:Infinity":21,"s:88:23:88:Infinity":22,"s:89:8:95:Infinity":23,"f:89:23:89:24":5,"s:90:10:94:Infinity":24,"b:101:4:103:Infinity:undefined:undefined:undefined:undefined":11,"s:101:4:103:Infinity":25,"s:102:6:102:Infinity":26,"s:105:4:105:Infinity":27,"f:108:16:108:Infinity":6,"s:112:18:112:Infinity":28,"b:112:39:112:53:112:53:112:57":12,"b:114:4:149:Infinity:undefined:undefined:undefined:undefined":13,"s:114:4:149:Infinity":29,"s:115:6:148:Infinity":30,"s:116:25:131:Infinity":31,"b:133:8:145:Infinity:undefined:undefined:undefined:undefined":14,"s:133:8:145:Infinity":32,"b:133:12:133:31:133:31:133:57":15,"s:134:10:134:Infinity":33,"s:135:10:144:Infinity":34,"f:136:17:136:18":7,"s:136:52:140:14":35,"b:137:29:137:43:137:43:137:45":16,"b:138:28:138:41:138:41:138:42":17,"f:142:14:142:15":8,"s:142:23:142:Infinity":36,"b:142:23:142:48:142:48:142:Infinity":18,"s:151:4:151:Infinity":37,"s:152:4:152:Infinity":38,"f:155:8:155:Infinity":9,"b:160:4:166:Infinity:undefined:undefined:undefined:undefined":19,"s:160:4:166:Infinity":39,"s:161:6:165:Infinity":40,"s:167:4:203:Infinity":41,"s:168:20:171:Infinity":42,"s:172:12:174:Infinity":43,"b:172:31:172:45:172:45:172:49":20,"f:173:8:173:9":10,"s:173:40:173:Infinity":44,"b:173:47:173:60:173:60:173:62":21,"b:175:6:184:Infinity:undefined:undefined:undefined:undefined":22,"s:175:6:184:Infinity":45,"b:177:8:182:Infinity:undefined:undefined:undefined:undefined":23,"s:177:8:182:Infinity":46,"s:178:10:181:Infinity":47,"s:183:8:183:Infinity":48,"s:185:6:188:Infinity":49,"b:190:6:195:Infinity:undefined:undefined:undefined:undefined":24,"s:190:6:195:Infinity":50,"s:191:8:194:Infinity":51,"s:196:6:196:Infinity":52,"s:198:6:202:Infinity":53,"b:201:38:201:52:201:52:201:Infinity":25,"f:206:16:206:Infinity":11,"s:210:18:210:Infinity":54,"b:210:39:210:53:210:53:210:57":26,"b:211:4:213:Infinity:undefined:undefined:undefined:undefined":27,"s:211:4:213:Infinity":55,"s:212:6:212:Infinity":56,"s:215:43:222:Infinity":57,"s:224:19:224:Infinity":58,"s:226:4:235:Infinity":59,"s:227:23:227:Infinity":60,"s:228:23:228:Infinity":61,"s:230:6:234:Infinity":62,"s:231:23:231:Infinity":63,"b:231:45:231:54:231:54:231:Infinity":28,"s:232:22:232:Infinity":64,"b:232:22:232:42:232:42:232:Infinity":29,"s:233:8:233:Infinity":65,"b:233:28:233:50:233:50:233:55":30,"b:237:4:239:Infinity:undefined:undefined:undefined:undefined":31,"s:237:4:239:Infinity":66,"s:238:6:238:Infinity":67,"s:241:4:248:Infinity":68,"f:242:12:242:13":12,"s:242:22:242:33":69,"f:244:11:244:12":13,"s:244:33:248:8":70,"f:251:10:251:20":14,"s:252:19:252:Infinity":71,"s:253:25:256:Infinity":72,"s:258:4:268:Infinity":73,"f:258:18:258:19":15,"s:259:6:267:Infinity":74,"f:259:19:259:20":16,"s:260:21:260:Infinity":75,"s:261:20:261:Infinity":76,"s:262:8:262:Infinity":77,"b:262:33:262:60:262:60:262:65":32,"s:264:25:264:Infinity":78,"b:264:25:264:58:264:58:264:Infinity":33,"s:265:8:265:Infinity":79,"s:266:8:266:Infinity":80,"s:270:4:282:Infinity":81,"f:271:12:271:13":17,"s:271:22:271:33":82,"f:272:11:272:12":18,"s:273:21:273:Infinity":83,"s:274:8:281:Infinity":84,"b:280:18:280:46:280:46:280:Infinity":34,"f:285:10:285:Infinity":19,"s:291:19:294:Infinity":85,"f:294:14:294:15":20,"s:294:25:294:42":86,"s:296:18:300:Infinity":87,"s:302:4:313:Infinity":88,"f:304:8:304:9":21,"s:304:18:304:Infinity":89,"b:304:25:304:54:304:54:304:56":35,"f:306:11:306:12":22,"s:306:22:310:8":90,"f:311:14:311:15":23,"s:311:23:311:36":91,"f:312:12:312:13":24,"s:312:22:312:39":92,"f:316:10:316:20":25,"s:318:6:318:Infinity":93,"b:318:20:318:44:318:44:318:46":36,"b:318:50:318:74:318:74:318:76":37,"b:318:80:318:107:318:107:318:109":38,"s:319:4:322:Infinity":94,"f:320:6:320:7":26,"s:320:22:320:Infinity":95,"b:320:56:320:60:320:60:320:Infinity":39,"f:325:10:325:19":27,"s:330:17:330:Infinity":96,"b:331:4:337:Infinity:undefined:undefined:undefined:undefined":40,"s:331:4:337:Infinity":97,"s:332:6:336:Infinity":98,"s:339:4:343:Infinity":99,"b:340:19:340:43:340:43:340:67:340:67:340:74":41,"b:341:23:341:47:341:47:341:75:341:75:341:77":42,"b:342:19:342:32:342:32:342:41":43,"f:346:10:346:Infinity":28,"b:350:4:352:Infinity:undefined:undefined:undefined:undefined":44,"s:350:4:352:Infinity":100,"s:351:6:351:Infinity":101,"s:354:20:354:Infinity":102,"f:354:38:354:39":29,"s:354:48:354:66":103,"s:355:4:355:Infinity":104,"f:355:26:355:27":30,"s:355:35:355:70":105,"f:358:10:358:Infinity":31,"s:362:4:365:Infinity":106,"f:362:26:362:27":32,"s:363:19:363:Infinity":107,"s:364:6:364:Infinity":108,"b:364:20:364:51:364:51:364:53":45}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/graph/index.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/graph/index.ts","statementMap":{"0":{"start":{"line":36,"column":30},"end":{"line":48,"column":null}},"1":{"start":{"line":54,"column":4},"end":{"line":56,"column":null}},"2":{"start":{"line":55,"column":6},"end":{"line":55,"column":null}},"3":{"start":{"line":58,"column":28},"end":{"line":58,"column":null}},"4":{"start":{"line":60,"column":4},"end":{"line":60,"column":null}},"5":{"start":{"line":62,"column":4},"end":{"line":64,"column":null}},"6":{"start":{"line":63,"column":6},"end":{"line":63,"column":null}},"7":{"start":{"line":65,"column":4},"end":{"line":65,"column":null}},"8":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"9":{"start":{"line":68,"column":4},"end":{"line":68,"column":null}},"10":{"start":{"line":81,"column":35},"end":{"line":81,"column":null}},"11":{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},"12":{"start":{"line":84,"column":6},"end":{"line":84,"column":null}},"13":{"start":{"line":86,"column":4},"end":{"line":86,"column":null}},"14":{"start":{"line":88,"column":4},"end":{"line":90,"column":null}},"15":{"start":{"line":89,"column":6},"end":{"line":89,"column":null}},"16":{"start":{"line":91,"column":4},"end":{"line":91,"column":null}},"17":{"start":{"line":93,"column":4},"end":{"line":95,"column":null}},"18":{"start":{"line":94,"column":6},"end":{"line":94,"column":null}},"19":{"start":{"line":96,"column":4},"end":{"line":96,"column":null}},"20":{"start":{"line":98,"column":4},"end":{"line":98,"column":null}},"21":{"start":{"line":99,"column":4},"end":{"line":100,"column":null}},"22":{"start":{"line":107,"column":4},"end":{"line":107,"column":null}},"23":{"start":{"line":114,"column":4},"end":{"line":114,"column":null}},"24":{"start":{"line":121,"column":4},"end":{"line":121,"column":null}},"25":{"start":{"line":128,"column":4},"end":{"line":128,"column":null}},"26":{"start":{"line":135,"column":4},"end":{"line":135,"column":null}},"27":{"start":{"line":142,"column":4},"end":{"line":142,"column":null}},"28":{"start":{"line":149,"column":4},"end":{"line":149,"column":null}},"29":{"start":{"line":150,"column":4},"end":{"line":150,"column":null}},"30":{"start":{"line":151,"column":4},"end":{"line":151,"column":null}},"31":{"start":{"line":152,"column":4},"end":{"line":152,"column":null}},"32":{"start":{"line":153,"column":4},"end":{"line":153,"column":null}},"33":{"start":{"line":154,"column":4},"end":{"line":159,"column":null}},"34":{"start":{"line":166,"column":4},"end":{"line":166,"column":null}},"35":{"start":{"line":173,"column":4},"end":{"line":173,"column":null}},"36":{"start":{"line":181,"column":22},"end":{"line":181,"column":null}},"37":{"start":{"line":182,"column":30},"end":{"line":182,"column":null}},"38":{"start":{"line":185,"column":4},"end":{"line":192,"column":null}},"39":{"start":{"line":186,"column":6},"end":{"line":191,"column":null}},"40":{"start":{"line":187,"column":8},"end":{"line":187,"column":null}},"41":{"start":{"line":188,"column":8},"end":{"line":188,"column":null}},"42":{"start":{"line":195,"column":4},"end":{"line":202,"column":null}},"43":{"start":{"line":196,"column":6},"end":{"line":201,"column":null}},"44":{"start":{"line":197,"column":8},"end":{"line":197,"column":null}},"45":{"start":{"line":198,"column":8},"end":{"line":198,"column":null}},"46":{"start":{"line":204,"column":4},"end":{"line":204,"column":null}},"47":{"start":{"line":211,"column":4},"end":{"line":219,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":53,"column":2},"end":{"line":53,"column":10}},"loc":{"start":{"line":53,"column":75},"end":{"line":69,"column":null}},"line":53},"1":{"name":"(anonymous_1)","decl":{"start":{"line":74,"column":2},"end":{"line":74,"column":null}},"loc":{"start":{"line":80,"column":10},"end":{"line":101,"column":null}},"line":80},"2":{"name":"(anonymous_2)","decl":{"start":{"line":106,"column":2},"end":{"line":106,"column":17}},"loc":{"start":{"line":106,"column":44},"end":{"line":108,"column":null}},"line":106},"3":{"name":"(anonymous_3)","decl":{"start":{"line":113,"column":2},"end":{"line":113,"column":10}},"loc":{"start":{"line":113,"column":45},"end":{"line":115,"column":null}},"line":113},"4":{"name":"(anonymous_4)","decl":{"start":{"line":120,"column":2},"end":{"line":120,"column":23}},"loc":{"start":{"line":120,"column":60},"end":{"line":122,"column":null}},"line":120},"5":{"name":"(anonymous_5)","decl":{"start":{"line":127,"column":2},"end":{"line":127,"column":21}},"loc":{"start":{"line":127,"column":58},"end":{"line":129,"column":null}},"line":127},"6":{"name":"(anonymous_6)","decl":{"start":{"line":134,"column":2},"end":{"line":134,"column":25}},"loc":{"start":{"line":134,"column":60},"end":{"line":136,"column":null}},"line":134},"7":{"name":"(anonymous_7)","decl":{"start":{"line":141,"column":2},"end":{"line":141,"column":44}},"loc":{"start":{"line":141,"column":44},"end":{"line":143,"column":null}},"line":141},"8":{"name":"(anonymous_8)","decl":{"start":{"line":148,"column":2},"end":{"line":148,"column":16}},"loc":{"start":{"line":148,"column":16},"end":{"line":160,"column":null}},"line":148},"9":{"name":"(anonymous_9)","decl":{"start":{"line":165,"column":2},"end":{"line":165,"column":29}},"loc":{"start":{"line":165,"column":29},"end":{"line":167,"column":null}},"line":165},"10":{"name":"(anonymous_10)","decl":{"start":{"line":172,"column":2},"end":{"line":172,"column":45}},"loc":{"start":{"line":172,"column":45},"end":{"line":174,"column":null}},"line":172},"11":{"name":"(anonymous_11)","decl":{"start":{"line":180,"column":2},"end":{"line":180,"column":11}},"loc":{"start":{"line":180,"column":97},"end":{"line":205,"column":null}},"line":180},"12":{"name":"(anonymous_12)","decl":{"start":{"line":210,"column":2},"end":{"line":210,"column":19}},"loc":{"start":{"line":210,"column":19},"end":{"line":220,"column":null}},"line":210}},"branchMap":{"0":{"loc":{"start":{"line":54,"column":4},"end":{"line":56,"column":null}},"type":"if","locations":[{"start":{"line":54,"column":4},"end":{"line":56,"column":null}},{"start":{},"end":{}}],"line":54},"1":{"loc":{"start":{"line":62,"column":4},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":62,"column":4},"end":{"line":64,"column":null}},{"start":{},"end":{}}],"line":62},"2":{"loc":{"start":{"line":68,"column":47},"end":{"line":68,"column":95}},"type":"binary-expr","locations":[{"start":{"line":68,"column":47},"end":{"line":68,"column":90}},{"start":{"line":68,"column":90},"end":{"line":68,"column":95}}],"line":68},"3":{"loc":{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},"type":"if","locations":[{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},{"start":{},"end":{}}],"line":83},"4":{"loc":{"start":{"line":88,"column":4},"end":{"line":90,"column":null}},"type":"if","locations":[{"start":{"line":88,"column":4},"end":{"line":90,"column":null}},{"start":{},"end":{}}],"line":88},"5":{"loc":{"start":{"line":93,"column":4},"end":{"line":95,"column":null}},"type":"if","locations":[{"start":{"line":93,"column":4},"end":{"line":95,"column":null}},{"start":{},"end":{}}],"line":93},"6":{"loc":{"start":{"line":100,"column":7},"end":{"line":100,"column":63}},"type":"binary-expr","locations":[{"start":{"line":100,"column":7},"end":{"line":100,"column":58}},{"start":{"line":100,"column":58},"end":{"line":100,"column":63}}],"line":100},"7":{"loc":{"start":{"line":107,"column":11},"end":{"line":107,"column":null}},"type":"binary-expr","locations":[{"start":{"line":107,"column":11},"end":{"line":107,"column":47}},{"start":{"line":107,"column":47},"end":{"line":107,"column":null}}],"line":107},"8":{"loc":{"start":{"line":121,"column":11},"end":{"line":121,"column":null}},"type":"binary-expr","locations":[{"start":{"line":121,"column":11},"end":{"line":121,"column":57}},{"start":{"line":121,"column":57},"end":{"line":121,"column":null}}],"line":121},"9":{"loc":{"start":{"line":128,"column":11},"end":{"line":128,"column":null}},"type":"binary-expr","locations":[{"start":{"line":128,"column":11},"end":{"line":128,"column":55}},{"start":{"line":128,"column":55},"end":{"line":128,"column":null}}],"line":128},"10":{"loc":{"start":{"line":135,"column":11},"end":{"line":135,"column":null}},"type":"binary-expr","locations":[{"start":{"line":135,"column":11},"end":{"line":135,"column":55}},{"start":{"line":135,"column":55},"end":{"line":135,"column":null}}],"line":135}},"s":{"0":127,"1":74,"2":0,"3":74,"4":74,"5":74,"6":63,"7":74,"8":74,"9":74,"10":32,"11":32,"12":27,"13":32,"14":32,"15":22,"16":32,"17":32,"18":20,"19":32,"20":32,"21":32,"22":259,"23":21,"24":10,"25":0,"26":0,"27":3,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0},"f":{"0":74,"1":32,"2":259,"3":21,"4":10,"5":0,"6":0,"7":3,"8":0,"9":0,"10":0,"11":0,"12":0},"b":{"0":[0,74],"1":[63,11],"2":[74,63],"3":[27,5],"4":[22,10],"5":[20,12],"6":[32,20],"7":[259,220],"8":[10,1],"9":[0,0],"10":[0,0]},"meta":{"lastBranch":11,"lastFunction":13,"lastStatement":48,"seen":{"s:36:30:48:Infinity":0,"f:53:2:53:10":0,"b:54:4:56:Infinity:undefined:undefined:undefined:undefined":0,"s:54:4:56:Infinity":1,"s:55:6:55:Infinity":2,"s:58:28:58:Infinity":3,"s:60:4:60:Infinity":4,"b:62:4:64:Infinity:undefined:undefined:undefined:undefined":1,"s:62:4:64:Infinity":5,"s:63:6:63:Infinity":6,"s:65:4:65:Infinity":7,"s:67:4:67:Infinity":8,"s:68:4:68:Infinity":9,"b:68:47:68:90:68:90:68:95":2,"f:74:2:74:Infinity":1,"s:81:35:81:Infinity":10,"b:83:4:85:Infinity:undefined:undefined:undefined:undefined":3,"s:83:4:85:Infinity":11,"s:84:6:84:Infinity":12,"s:86:4:86:Infinity":13,"b:88:4:90:Infinity:undefined:undefined:undefined:undefined":4,"s:88:4:90:Infinity":14,"s:89:6:89:Infinity":15,"s:91:4:91:Infinity":16,"b:93:4:95:Infinity:undefined:undefined:undefined:undefined":5,"s:93:4:95:Infinity":17,"s:94:6:94:Infinity":18,"s:96:4:96:Infinity":19,"s:98:4:98:Infinity":20,"s:99:4:100:Infinity":21,"b:100:7:100:58:100:58:100:63":6,"f:106:2:106:17":2,"s:107:4:107:Infinity":22,"b:107:11:107:47:107:47:107:Infinity":7,"f:113:2:113:10":3,"s:114:4:114:Infinity":23,"f:120:2:120:23":4,"s:121:4:121:Infinity":24,"b:121:11:121:57:121:57:121:Infinity":8,"f:127:2:127:21":5,"s:128:4:128:Infinity":25,"b:128:11:128:55:128:55:128:Infinity":9,"f:134:2:134:25":6,"s:135:4:135:Infinity":26,"b:135:11:135:55:135:55:135:Infinity":10,"f:141:2:141:44":7,"s:142:4:142:Infinity":27,"f:148:2:148:16":8,"s:149:4:149:Infinity":28,"s:150:4:150:Infinity":29,"s:151:4:151:Infinity":30,"s:152:4:152:Infinity":31,"s:153:4:153:Infinity":32,"s:154:4:159:Infinity":33,"f:165:2:165:29":9,"s:166:4:166:Infinity":34,"f:172:2:172:45":10,"s:173:4:173:Infinity":35,"f:180:2:180:11":11,"s:181:22:181:Infinity":36,"s:182:30:182:Infinity":37,"s:185:4:192:Infinity":38,"s:186:6:191:Infinity":39,"s:187:8:187:Infinity":40,"s:188:8:188:Infinity":41,"s:195:4:202:Infinity":42,"s:196:6:201:Infinity":43,"s:197:8:197:Infinity":44,"s:198:8:198:Infinity":45,"s:204:4:204:Infinity":46,"f:210:2:210:19":12,"s:211:4:219:Infinity":47}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/graph/orchestrator.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/graph/orchestrator.ts","statementMap":{"0":{"start":{"line":72,"column":58},"end":{"line":72,"column":null}},"1":{"start":{"line":73,"column":52},"end":{"line":73,"column":null}},"2":{"start":{"line":74,"column":58},"end":{"line":74,"column":null}},"3":{"start":{"line":75,"column":52},"end":{"line":75,"column":null}},"4":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"5":{"start":{"line":89,"column":4},"end":{"line":89,"column":null}},"6":{"start":{"line":90,"column":4},"end":{"line":90,"column":null}},"7":{"start":{"line":94,"column":21},"end":{"line":94,"column":null}},"8":{"start":{"line":95,"column":10},"end":{"line":95,"column":null}},"9":{"start":{"line":96,"column":4},"end":{"line":96,"column":null}},"10":{"start":{"line":97,"column":4},"end":{"line":105,"column":null}},"11":{"start":{"line":98,"column":6},"end":{"line":100,"column":null}},"12":{"start":{"line":99,"column":8},"end":{"line":99,"column":null}},"13":{"start":{"line":101,"column":6},"end":{"line":103,"column":null}},"14":{"start":{"line":102,"column":8},"end":{"line":102,"column":null}},"15":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"16":{"start":{"line":109,"column":10},"end":{"line":109,"column":null}},"17":{"start":{"line":110,"column":4},"end":{"line":110,"column":null}},"18":{"start":{"line":111,"column":4},"end":{"line":119,"column":null}},"19":{"start":{"line":112,"column":6},"end":{"line":114,"column":null}},"20":{"start":{"line":113,"column":8},"end":{"line":113,"column":null}},"21":{"start":{"line":115,"column":6},"end":{"line":117,"column":null}},"22":{"start":{"line":116,"column":8},"end":{"line":116,"column":null}},"23":{"start":{"line":118,"column":6},"end":{"line":118,"column":null}},"24":{"start":{"line":124,"column":10},"end":{"line":124,"column":null}},"25":{"start":{"line":125,"column":10},"end":{"line":125,"column":null}},"26":{"start":{"line":126,"column":27},"end":{"line":131,"column":null}},"27":{"start":{"line":133,"column":21},"end":{"line":133,"column":null}},"28":{"start":{"line":133,"column":50},"end":{"line":133,"column":65}},"29":{"start":{"line":134,"column":4},"end":{"line":141,"column":null}},"30":{"start":{"line":135,"column":23},"end":{"line":135,"column":null}},"31":{"start":{"line":136,"column":6},"end":{"line":140,"column":null}},"32":{"start":{"line":137,"column":8},"end":{"line":137,"column":null}},"33":{"start":{"line":139,"column":8},"end":{"line":139,"column":null}},"34":{"start":{"line":144,"column":35},"end":{"line":144,"column":null}},"35":{"start":{"line":145,"column":34},"end":{"line":145,"column":null}},"36":{"start":{"line":146,"column":4},"end":{"line":156,"column":null}},"37":{"start":{"line":147,"column":6},"end":{"line":148,"column":null}},"38":{"start":{"line":147,"column":37},"end":{"line":147,"column":null}},"39":{"start":{"line":148,"column":11},"end":{"line":148,"column":null}},"40":{"start":{"line":149,"column":6},"end":{"line":150,"column":null}},"41":{"start":{"line":149,"column":30},"end":{"line":149,"column":null}},"42":{"start":{"line":150,"column":11},"end":{"line":150,"column":null}},"43":{"start":{"line":151,"column":6},"end":{"line":152,"column":null}},"44":{"start":{"line":151,"column":37},"end":{"line":151,"column":null}},"45":{"start":{"line":152,"column":11},"end":{"line":152,"column":null}},"46":{"start":{"line":155,"column":6},"end":{"line":155,"column":null}},"47":{"start":{"line":157,"column":4},"end":{"line":160,"column":null}},"48":{"start":{"line":158,"column":6},"end":{"line":159,"column":null}},"49":{"start":{"line":158,"column":14},"end":{"line":158,"column":null}},"50":{"start":{"line":159,"column":11},"end":{"line":159,"column":null}},"51":{"start":{"line":161,"column":4},"end":{"line":165,"column":null}},"52":{"start":{"line":162,"column":6},"end":{"line":164,"column":null}},"53":{"start":{"line":166,"column":4},"end":{"line":170,"column":null}},"54":{"start":{"line":167,"column":6},"end":{"line":169,"column":null}},"55":{"start":{"line":172,"column":4},"end":{"line":172,"column":null}},"56":{"start":{"line":173,"column":4},"end":{"line":173,"column":null}},"57":{"start":{"line":174,"column":4},"end":{"line":174,"column":null}},"58":{"start":{"line":175,"column":4},"end":{"line":175,"column":null}},"59":{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},"60":{"start":{"line":177,"column":4},"end":{"line":177,"column":null}},"61":{"start":{"line":184,"column":22},"end":{"line":184,"column":null}},"62":{"start":{"line":185,"column":31},"end":{"line":197,"column":null}},"63":{"start":{"line":199,"column":29},"end":{"line":199,"column":null}},"64":{"start":{"line":200,"column":31},"end":{"line":200,"column":null}},"65":{"start":{"line":202,"column":4},"end":{"line":440,"column":null}},"66":{"start":{"line":203,"column":6},"end":{"line":206,"column":null}},"67":{"start":{"line":204,"column":8},"end":{"line":204,"column":null}},"68":{"start":{"line":205,"column":8},"end":{"line":205,"column":null}},"69":{"start":{"line":209,"column":20},"end":{"line":213,"column":null}},"70":{"start":{"line":215,"column":6},"end":{"line":217,"column":null}},"71":{"start":{"line":216,"column":8},"end":{"line":216,"column":null}},"72":{"start":{"line":220,"column":27},"end":{"line":220,"column":null}},"73":{"start":{"line":221,"column":25},"end":{"line":221,"column":null}},"74":{"start":{"line":223,"column":6},"end":{"line":264,"column":null}},"75":{"start":{"line":224,"column":35},"end":{"line":227,"column":null}},"76":{"start":{"line":229,"column":8},"end":{"line":259,"column":null}},"77":{"start":{"line":230,"column":10},"end":{"line":232,"column":null}},"78":{"start":{"line":231,"column":26},"end":{"line":231,"column":null}},"79":{"start":{"line":233,"column":10},"end":{"line":233,"column":null}},"80":{"start":{"line":235,"column":10},"end":{"line":239,"column":null}},"81":{"start":{"line":236,"column":12},"end":{"line":238,"column":null}},"82":{"start":{"line":241,"column":25},"end":{"line":247,"column":null}},"83":{"start":{"line":242,"column":36},"end":{"line":246,"column":14}},"84":{"start":{"line":249,"column":10},"end":{"line":251,"column":null}},"85":{"start":{"line":250,"column":27},"end":{"line":250,"column":64}},"86":{"start":{"line":251,"column":24},"end":{"line":251,"column":30}},"87":{"start":{"line":252,"column":10},"end":{"line":252,"column":null}},"88":{"start":{"line":254,"column":10},"end":{"line":258,"column":null}},"89":{"start":{"line":255,"column":12},"end":{"line":257,"column":null}},"90":{"start":{"line":262,"column":8},"end":{"line":262,"column":null}},"91":{"start":{"line":263,"column":8},"end":{"line":263,"column":null}},"92":{"start":{"line":267,"column":25},"end":{"line":267,"column":null}},"93":{"start":{"line":268,"column":51},"end":{"line":268,"column":null}},"94":{"start":{"line":269,"column":75},"end":{"line":269,"column":null}},"95":{"start":{"line":270,"column":6},"end":{"line":275,"column":null}},"96":{"start":{"line":277,"column":6},"end":{"line":305,"column":null}},"97":{"start":{"line":278,"column":8},"end":{"line":304,"column":null}},"98":{"start":{"line":279,"column":25},"end":{"line":282,"column":null}},"99":{"start":{"line":283,"column":10},"end":{"line":283,"column":null}},"100":{"start":{"line":284,"column":10},"end":{"line":284,"column":null}},"101":{"start":{"line":285,"column":32},"end":{"line":285,"column":null}},"102":{"start":{"line":286,"column":29},"end":{"line":286,"column":null}},"103":{"start":{"line":288,"column":10},"end":{"line":288,"column":null}},"104":{"start":{"line":291,"column":10},"end":{"line":291,"column":null}},"105":{"start":{"line":294,"column":10},"end":{"line":294,"column":null}},"106":{"start":{"line":295,"column":10},"end":{"line":295,"column":null}},"107":{"start":{"line":297,"column":10},"end":{"line":301,"column":null}},"108":{"start":{"line":298,"column":12},"end":{"line":300,"column":null}},"109":{"start":{"line":303,"column":10},"end":{"line":303,"column":null}},"110":{"start":{"line":308,"column":32},"end":{"line":312,"column":null}},"111":{"start":{"line":313,"column":6},"end":{"line":313,"column":null}},"112":{"start":{"line":316,"column":6},"end":{"line":318,"column":null}},"113":{"start":{"line":317,"column":8},"end":{"line":317,"column":null}},"114":{"start":{"line":319,"column":33},"end":{"line":319,"column":null}},"115":{"start":{"line":320,"column":6},"end":{"line":320,"column":null}},"116":{"start":{"line":323,"column":35},"end":{"line":323,"column":null}},"117":{"start":{"line":325,"column":6},"end":{"line":342,"column":null}},"118":{"start":{"line":326,"column":8},"end":{"line":330,"column":null}},"119":{"start":{"line":327,"column":10},"end":{"line":329,"column":null}},"120":{"start":{"line":331,"column":24},"end":{"line":331,"column":null}},"121":{"start":{"line":332,"column":33},"end":{"line":332,"column":null}},"122":{"start":{"line":332,"column":55},"end":{"line":332,"column":62}},"123":{"start":{"line":333,"column":8},"end":{"line":335,"column":null}},"124":{"start":{"line":334,"column":10},"end":{"line":334,"column":null}},"125":{"start":{"line":337,"column":8},"end":{"line":341,"column":null}},"126":{"start":{"line":338,"column":10},"end":{"line":340,"column":null}},"127":{"start":{"line":345,"column":12},"end":{"line":348,"column":null}},"128":{"start":{"line":349,"column":6},"end":{"line":376,"column":null}},"129":{"start":{"line":350,"column":8},"end":{"line":352,"column":null}},"130":{"start":{"line":351,"column":10},"end":{"line":351,"column":null}},"131":{"start":{"line":353,"column":8},"end":{"line":375,"column":null}},"132":{"start":{"line":354,"column":29},"end":{"line":354,"column":null}},"133":{"start":{"line":355,"column":29},"end":{"line":359,"column":null}},"134":{"start":{"line":360,"column":10},"end":{"line":365,"column":null}},"135":{"start":{"line":361,"column":12},"end":{"line":364,"column":null}},"136":{"start":{"line":366,"column":10},"end":{"line":370,"column":null}},"137":{"start":{"line":367,"column":12},"end":{"line":369,"column":null}},"138":{"start":{"line":368,"column":14},"end":{"line":368,"column":null}},"139":{"start":{"line":372,"column":10},"end":{"line":374,"column":null}},"140":{"start":{"line":379,"column":6},"end":{"line":379,"column":null}},"141":{"start":{"line":382,"column":6},"end":{"line":395,"column":null}},"142":{"start":{"line":383,"column":8},"end":{"line":394,"column":null}},"143":{"start":{"line":384,"column":29},"end":{"line":384,"column":null}},"144":{"start":{"line":385,"column":10},"end":{"line":389,"column":null}},"145":{"start":{"line":386,"column":12},"end":{"line":388,"column":null}},"146":{"start":{"line":391,"column":10},"end":{"line":393,"column":null}},"147":{"start":{"line":397,"column":23},"end":{"line":397,"column":null}},"148":{"start":{"line":399,"column":6},"end":{"line":411,"column":null}},"149":{"start":{"line":400,"column":22},"end":{"line":400,"column":null}},"150":{"start":{"line":401,"column":8},"end":{"line":401,"column":null}},"151":{"start":{"line":402,"column":8},"end":{"line":402,"column":null}},"152":{"start":{"line":403,"column":8},"end":{"line":405,"column":null}},"153":{"start":{"line":406,"column":8},"end":{"line":406,"column":null}},"154":{"start":{"line":407,"column":8},"end":{"line":409,"column":null}},"155":{"start":{"line":410,"column":8},"end":{"line":410,"column":null}},"156":{"start":{"line":413,"column":6},"end":{"line":424,"column":null}},"157":{"start":{"line":426,"column":23},"end":{"line":426,"column":null}},"158":{"start":{"line":427,"column":6},"end":{"line":427,"column":null}},"159":{"start":{"line":428,"column":6},"end":{"line":439,"column":null}},"160":{"start":{"line":451,"column":28},"end":{"line":451,"column":null}},"161":{"start":{"line":453,"column":21},"end":{"line":455,"column":null}},"162":{"start":{"line":457,"column":4},"end":{"line":464,"column":null}},"163":{"start":{"line":458,"column":6},"end":{"line":458,"column":null}},"164":{"start":{"line":460,"column":6},"end":{"line":462,"column":null}},"165":{"start":{"line":463,"column":6},"end":{"line":463,"column":null}},"166":{"start":{"line":466,"column":26},"end":{"line":469,"column":null}},"167":{"start":{"line":467,"column":18},"end":{"line":467,"column":null}},"168":{"start":{"line":468,"column":6},"end":{"line":468,"column":null}},"169":{"start":{"line":468,"column":34},"end":{"line":468,"column":50}},"170":{"start":{"line":471,"column":17},"end":{"line":492,"column":null}},"171":{"start":{"line":472,"column":6},"end":{"line":491,"column":null}},"172":{"start":{"line":473,"column":24},"end":{"line":473,"column":null}},"173":{"start":{"line":474,"column":8},"end":{"line":486,"column":null}},"174":{"start":{"line":475,"column":27},"end":{"line":475,"column":null}},"175":{"start":{"line":476,"column":10},"end":{"line":476,"column":null}},"176":{"start":{"line":476,"column":39},"end":{"line":476,"column":null}},"177":{"start":{"line":478,"column":10},"end":{"line":485,"column":null}},"178":{"start":{"line":479,"column":12},"end":{"line":479,"column":null}},"179":{"start":{"line":480,"column":10},"end":{"line":485,"column":null}},"180":{"start":{"line":484,"column":12},"end":{"line":484,"column":null}},"181":{"start":{"line":488,"column":8},"end":{"line":490,"column":null}},"182":{"start":{"line":494,"column":4},"end":{"line":494,"column":null}},"183":{"start":{"line":495,"column":4},"end":{"line":495,"column":null}},"184":{"start":{"line":502,"column":4},"end":{"line":504,"column":null}},"185":{"start":{"line":503,"column":6},"end":{"line":503,"column":null}},"186":{"start":{"line":506,"column":36},"end":{"line":506,"column":null}},"187":{"start":{"line":507,"column":17},"end":{"line":507,"column":null}},"188":{"start":{"line":509,"column":4},"end":{"line":534,"column":null}},"189":{"start":{"line":510,"column":22},"end":{"line":510,"column":48}},"190":{"start":{"line":513,"column":8},"end":{"line":515,"column":null}},"191":{"start":{"line":518,"column":25},"end":{"line":518,"column":null}},"192":{"start":{"line":519,"column":8},"end":{"line":522,"column":null}},"193":{"start":{"line":526,"column":8},"end":{"line":526,"column":null}},"194":{"start":{"line":529,"column":8},"end":{"line":531,"column":null}},"195":{"start":{"line":530,"column":10},"end":{"line":530,"column":null}},"196":{"start":{"line":532,"column":8},"end":{"line":532,"column":null}},"197":{"start":{"line":533,"column":8},"end":{"line":533,"column":null}},"198":{"start":{"line":541,"column":22},"end":{"line":541,"column":null}},"199":{"start":{"line":542,"column":4},"end":{"line":561,"column":null}},"200":{"start":{"line":544,"column":6},"end":{"line":559,"column":null}},"201":{"start":{"line":546,"column":10},"end":{"line":546,"column":null}},"202":{"start":{"line":547,"column":8},"end":{"line":558,"column":null}},"203":{"start":{"line":548,"column":26},"end":{"line":548,"column":null}},"204":{"start":{"line":549,"column":25},"end":{"line":549,"column":null}},"205":{"start":{"line":550,"column":10},"end":{"line":557,"column":null}},"206":{"start":{"line":551,"column":12},"end":{"line":556,"column":null}},"207":{"start":{"line":560,"column":6},"end":{"line":560,"column":null}},"208":{"start":{"line":563,"column":4},"end":{"line":592,"column":null}},"209":{"start":{"line":569,"column":6},"end":{"line":584,"column":null}},"210":{"start":{"line":571,"column":10},"end":{"line":571,"column":null}},"211":{"start":{"line":572,"column":8},"end":{"line":583,"column":null}},"212":{"start":{"line":573,"column":26},"end":{"line":573,"column":null}},"213":{"start":{"line":574,"column":25},"end":{"line":574,"column":null}},"214":{"start":{"line":575,"column":10},"end":{"line":582,"column":null}},"215":{"start":{"line":576,"column":12},"end":{"line":581,"column":null}},"216":{"start":{"line":586,"column":22},"end":{"line":586,"column":null}},"217":{"start":{"line":587,"column":6},"end":{"line":591,"column":null}},"218":{"start":{"line":594,"column":20},"end":{"line":594,"column":null}},"219":{"start":{"line":595,"column":19},"end":{"line":595,"column":null}},"220":{"start":{"line":596,"column":4},"end":{"line":603,"column":null}},"221":{"start":{"line":597,"column":6},"end":{"line":602,"column":null}},"222":{"start":{"line":605,"column":4},"end":{"line":609,"column":null}},"223":{"start":{"line":613,"column":21},"end":{"line":613,"column":null}},"224":{"start":{"line":614,"column":25},"end":{"line":614,"column":null}},"225":{"start":{"line":616,"column":5},"end":{"line":629,"column":null}},"226":{"start":{"line":631,"column":4},"end":{"line":642,"column":null}},"227":{"start":{"line":632,"column":7},"end":{"line":641,"column":null}},"228":{"start":{"line":644,"column":4},"end":{"line":655,"column":null}},"229":{"start":{"line":645,"column":7},"end":{"line":654,"column":null}},"230":{"start":{"line":657,"column":4},"end":{"line":667,"column":null}},"231":{"start":{"line":658,"column":7},"end":{"line":666,"column":null}},"232":{"start":{"line":676,"column":25},"end":{"line":678,"column":null}},"233":{"start":{"line":679,"column":17},"end":{"line":679,"column":null}},"234":{"start":{"line":680,"column":16},"end":{"line":680,"column":null}},"235":{"start":{"line":682,"column":20},"end":{"line":695,"column":null}},"236":{"start":{"line":683,"column":26},"end":{"line":683,"column":50}},"237":{"start":{"line":684,"column":31},"end":{"line":695,"column":8}},"238":{"start":{"line":697,"column":22},"end":{"line":715,"column":null}},"239":{"start":{"line":699,"column":20},"end":{"line":699,"column":null}},"240":{"start":{"line":701,"column":31},"end":{"line":715,"column":8}},"241":{"start":{"line":717,"column":20},"end":{"line":737,"column":null}},"242":{"start":{"line":720,"column":10},"end":{"line":724,"column":null}},"243":{"start":{"line":726,"column":31},"end":{"line":737,"column":8}},"244":{"start":{"line":739,"column":4},"end":{"line":759,"column":null}},"245":{"start":{"line":763,"column":42},"end":{"line":774,"column":null}},"246":{"start":{"line":775,"column":4},"end":{"line":775,"column":null}},"247":{"start":{"line":782,"column":20},"end":{"line":782,"column":null}},"248":{"start":{"line":783,"column":4},"end":{"line":783,"column":null}},"249":{"start":{"line":787,"column":15},"end":{"line":787,"column":null}},"250":{"start":{"line":788,"column":4},"end":{"line":792,"column":null}},"251":{"start":{"line":788,"column":17},"end":{"line":788,"column":20}},"252":{"start":{"line":789,"column":19},"end":{"line":789,"column":null}},"253":{"start":{"line":790,"column":6},"end":{"line":790,"column":null}},"254":{"start":{"line":791,"column":6},"end":{"line":791,"column":null}},"255":{"start":{"line":793,"column":4},"end":{"line":793,"column":null}},"256":{"start":{"line":801,"column":4},"end":{"line":808,"column":null}},"257":{"start":{"line":811,"column":4},"end":{"line":828,"column":null}},"258":{"start":{"line":812,"column":6},"end":{"line":821,"column":null}},"259":{"start":{"line":822,"column":6},"end":{"line":827,"column":null}},"260":{"start":{"line":831,"column":4},"end":{"line":848,"column":null}},"261":{"start":{"line":832,"column":6},"end":{"line":841,"column":null}},"262":{"start":{"line":842,"column":6},"end":{"line":847,"column":null}},"263":{"start":{"line":851,"column":4},"end":{"line":863,"column":null}},"264":{"start":{"line":852,"column":6},"end":{"line":856,"column":null}},"265":{"start":{"line":857,"column":6},"end":{"line":862,"column":null}},"266":{"start":{"line":870,"column":16},"end":{"line":870,"column":null}},"267":{"start":{"line":871,"column":4},"end":{"line":876,"column":null}},"268":{"start":{"line":873,"column":6},"end":{"line":875,"column":null}},"269":{"start":{"line":874,"column":8},"end":{"line":874,"column":null}},"270":{"start":{"line":877,"column":4},"end":{"line":877,"column":null}},"271":{"start":{"line":884,"column":4},"end":{"line":935,"column":null}},"272":{"start":{"line":892,"column":44},"end":{"line":898,"column":8}},"273":{"start":{"line":895,"column":49},"end":{"line":895,"column":75}},"274":{"start":{"line":899,"column":44},"end":{"line":905,"column":8}},"275":{"start":{"line":906,"column":47},"end":{"line":919,"column":8}},"276":{"start":{"line":910,"column":46},"end":{"line":910,"column":75}},"277":{"start":{"line":920,"column":44},"end":{"line":933,"column":8}},"278":{"start":{"line":948,"column":42},"end":{"line":948,"column":null}},"279":{"start":{"line":951,"column":22},"end":{"line":951,"column":null}},"280":{"start":{"line":951,"column":48},"end":{"line":951,"column":75}},"281":{"start":{"line":953,"column":4},"end":{"line":985,"column":null}},"282":{"start":{"line":954,"column":25},"end":{"line":954,"column":null}},"283":{"start":{"line":955,"column":6},"end":{"line":955,"column":null}},"284":{"start":{"line":955,"column":35},"end":{"line":955,"column":null}},"285":{"start":{"line":958,"column":22},"end":{"line":958,"column":null}},"286":{"start":{"line":960,"column":6},"end":{"line":984,"column":null}},"287":{"start":{"line":962,"column":29},"end":{"line":967,"column":null}},"288":{"start":{"line":968,"column":8},"end":{"line":968,"column":null}},"289":{"start":{"line":968,"column":27},"end":{"line":968,"column":null}},"290":{"start":{"line":971,"column":8},"end":{"line":983,"column":null}},"291":{"start":{"line":972,"column":10},"end":{"line":982,"column":null}},"292":{"start":{"line":987,"column":4},"end":{"line":987,"column":null}},"293":{"start":{"line":994,"column":4},"end":{"line":998,"column":null}},"294":{"start":{"line":1012,"column":4},"end":{"line":1014,"column":null}},"295":{"start":{"line":1013,"column":6},"end":{"line":1013,"column":null}},"296":{"start":{"line":1018,"column":4},"end":{"line":1027,"column":null}},"297":{"start":{"line":1020,"column":18},"end":{"line":1020,"column":null}},"298":{"start":{"line":1021,"column":6},"end":{"line":1021,"column":null}},"299":{"start":{"line":1022,"column":4},"end":{"line":1027,"column":null}},"300":{"start":{"line":1024,"column":6},"end":{"line":1024,"column":null}},"301":{"start":{"line":1026,"column":6},"end":{"line":1026,"column":null}},"302":{"start":{"line":1030,"column":23},"end":{"line":1036,"column":null}},"303":{"start":{"line":1038,"column":4},"end":{"line":1043,"column":null}},"304":{"start":{"line":1039,"column":21},"end":{"line":1039,"column":null}},"305":{"start":{"line":1039,"column":45},"end":{"line":1039,"column":69}},"306":{"start":{"line":1040,"column":6},"end":{"line":1042,"column":null}},"307":{"start":{"line":1041,"column":8},"end":{"line":1041,"column":null}},"308":{"start":{"line":1045,"column":4},"end":{"line":1045,"column":null}},"309":{"start":{"line":1052,"column":42},"end":{"line":1052,"column":null}},"310":{"start":{"line":1055,"column":4},"end":{"line":1057,"column":null}},"311":{"start":{"line":1056,"column":6},"end":{"line":1056,"column":null}},"312":{"start":{"line":1061,"column":21},"end":{"line":1092,"column":null}},"313":{"start":{"line":1094,"column":4},"end":{"line":1114,"column":null}},"314":{"start":{"line":1095,"column":6},"end":{"line":1113,"column":null}},"315":{"start":{"line":1116,"column":4},"end":{"line":1116,"column":null}},"316":{"start":{"line":1123,"column":4},"end":{"line":1123,"column":null}},"317":{"start":{"line":1123,"column":17},"end":{"line":1123,"column":null}},"318":{"start":{"line":1130,"column":21},"end":{"line":1134,"column":null}},"319":{"start":{"line":1135,"column":4},"end":{"line":1135,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":87,"column":2},"end":{"line":87,"column":14}},"loc":{"start":{"line":87,"column":91},"end":{"line":178,"column":null}},"line":87},"1":{"name":"(anonymous_1)","decl":{"start":{"line":133,"column":43},"end":{"line":133,"column":44}},"loc":{"start":{"line":133,"column":50},"end":{"line":133,"column":65}},"line":133},"2":{"name":"(anonymous_2)","decl":{"start":{"line":183,"column":8},"end":{"line":183,"column":14}},"loc":{"start":{"line":183,"column":73},"end":{"line":441,"column":null}},"line":183},"3":{"name":"(anonymous_3)","decl":{"start":{"line":231,"column":12},"end":{"line":231,"column":13}},"loc":{"start":{"line":231,"column":26},"end":{"line":231,"column":null}},"line":231},"4":{"name":"(anonymous_4)","decl":{"start":{"line":242,"column":22},"end":{"line":242,"column":29}},"loc":{"start":{"line":242,"column":36},"end":{"line":246,"column":14}},"line":242},"5":{"name":"(anonymous_5)","decl":{"start":{"line":250,"column":20},"end":{"line":250,"column":21}},"loc":{"start":{"line":250,"column":27},"end":{"line":250,"column":64}},"line":250},"6":{"name":"(anonymous_6)","decl":{"start":{"line":251,"column":17},"end":{"line":251,"column":18}},"loc":{"start":{"line":251,"column":24},"end":{"line":251,"column":30}},"line":251},"7":{"name":"(anonymous_7)","decl":{"start":{"line":332,"column":48},"end":{"line":332,"column":49}},"loc":{"start":{"line":332,"column":55},"end":{"line":332,"column":62}},"line":332},"8":{"name":"(anonymous_8)","decl":{"start":{"line":446,"column":16},"end":{"line":446,"column":null}},"loc":{"start":{"line":450,"column":23},"end":{"line":496,"column":null}},"line":450},"9":{"name":"(anonymous_9)","decl":{"start":{"line":466,"column":26},"end":{"line":466,"column":27}},"loc":{"start":{"line":466,"column":57},"end":{"line":469,"column":null}},"line":466},"10":{"name":"(anonymous_10)","decl":{"start":{"line":468,"column":26},"end":{"line":468,"column":27}},"loc":{"start":{"line":468,"column":34},"end":{"line":468,"column":50}},"line":468},"11":{"name":"(anonymous_11)","decl":{"start":{"line":471,"column":17},"end":{"line":471,"column":18}},"loc":{"start":{"line":471,"column":40},"end":{"line":492,"column":null}},"line":471},"12":{"name":"(anonymous_12)","decl":{"start":{"line":498,"column":10},"end":{"line":498,"column":null}},"loc":{"start":{"line":501,"column":14},"end":{"line":535,"column":null}},"line":501},"13":{"name":"(anonymous_13)","decl":{"start":{"line":510,"column":11},"end":{"line":510,"column":12}},"loc":{"start":{"line":510,"column":22},"end":{"line":510,"column":48}},"line":510},"14":{"name":"(anonymous_14)","decl":{"start":{"line":512,"column":11},"end":{"line":512,"column":12}},"loc":{"start":{"line":513,"column":8},"end":{"line":515,"column":null}},"line":513},"15":{"name":"(anonymous_15)","decl":{"start":{"line":517,"column":14},"end":{"line":517,"column":15}},"loc":{"start":{"line":517,"column":28},"end":{"line":524,"column":7}},"line":517},"16":{"name":"(anonymous_16)","decl":{"start":{"line":525,"column":14},"end":{"line":525,"column":15}},"loc":{"start":{"line":526,"column":8},"end":{"line":526,"column":null}},"line":526},"17":{"name":"(anonymous_17)","decl":{"start":{"line":528,"column":14},"end":{"line":528,"column":15}},"loc":{"start":{"line":528,"column":28},"end":{"line":534,"column":7}},"line":528},"18":{"name":"(anonymous_18)","decl":{"start":{"line":537,"column":16},"end":{"line":537,"column":null}},"loc":{"start":{"line":540,"column":25},"end":{"line":610,"column":null}},"line":540},"19":{"name":"(anonymous_19)","decl":{"start":{"line":612,"column":16},"end":{"line":612,"column":32}},"loc":{"start":{"line":612,"column":67},"end":{"line":668,"column":null}},"line":612},"20":{"name":"(anonymous_20)","decl":{"start":{"line":670,"column":10},"end":{"line":670,"column":null}},"loc":{"start":{"line":675,"column":16},"end":{"line":760,"column":null}},"line":675},"21":{"name":"(anonymous_21)","decl":{"start":{"line":683,"column":14},"end":{"line":683,"column":15}},"loc":{"start":{"line":683,"column":26},"end":{"line":683,"column":50}},"line":683},"22":{"name":"(anonymous_22)","decl":{"start":{"line":684,"column":11},"end":{"line":684,"column":12}},"loc":{"start":{"line":684,"column":31},"end":{"line":695,"column":8}},"line":684},"23":{"name":"(anonymous_23)","decl":{"start":{"line":699,"column":8},"end":{"line":699,"column":9}},"loc":{"start":{"line":699,"column":20},"end":{"line":699,"column":null}},"line":699},"24":{"name":"(anonymous_24)","decl":{"start":{"line":701,"column":11},"end":{"line":701,"column":12}},"loc":{"start":{"line":701,"column":31},"end":{"line":715,"column":8}},"line":701},"25":{"name":"(anonymous_25)","decl":{"start":{"line":719,"column":8},"end":{"line":719,"column":9}},"loc":{"start":{"line":720,"column":10},"end":{"line":724,"column":null}},"line":720},"26":{"name":"(anonymous_26)","decl":{"start":{"line":726,"column":11},"end":{"line":726,"column":12}},"loc":{"start":{"line":726,"column":31},"end":{"line":737,"column":8}},"line":726},"27":{"name":"(anonymous_27)","decl":{"start":{"line":762,"column":10},"end":{"line":762,"column":32}},"loc":{"start":{"line":762,"column":59},"end":{"line":776,"column":null}},"line":762},"28":{"name":"(anonymous_28)","decl":{"start":{"line":781,"column":16},"end":{"line":781,"column":25}},"loc":{"start":{"line":781,"column":60},"end":{"line":784,"column":null}},"line":781},"29":{"name":"(anonymous_29)","decl":{"start":{"line":786,"column":10},"end":{"line":786,"column":21}},"loc":{"start":{"line":786,"column":46},"end":{"line":794,"column":null}},"line":786},"30":{"name":"(anonymous_30)","decl":{"start":{"line":799,"column":10},"end":{"line":799,"column":21}},"loc":{"start":{"line":799,"column":47},"end":{"line":864,"column":null}},"line":799},"31":{"name":"(anonymous_31)","decl":{"start":{"line":811,"column":29},"end":{"line":811,"column":30}},"loc":{"start":{"line":811,"column":37},"end":{"line":828,"column":5}},"line":811},"32":{"name":"(anonymous_32)","decl":{"start":{"line":831,"column":27},"end":{"line":831,"column":28}},"loc":{"start":{"line":831,"column":36},"end":{"line":848,"column":5}},"line":831},"33":{"name":"(anonymous_33)","decl":{"start":{"line":851,"column":27},"end":{"line":851,"column":28}},"loc":{"start":{"line":851,"column":36},"end":{"line":863,"column":5}},"line":851},"34":{"name":"(anonymous_34)","decl":{"start":{"line":869,"column":10},"end":{"line":869,"column":33}},"loc":{"start":{"line":869,"column":72},"end":{"line":878,"column":null}},"line":869},"35":{"name":"(anonymous_35)","decl":{"start":{"line":883,"column":10},"end":{"line":883,"column":26}},"loc":{"start":{"line":883,"column":51},"end":{"line":936,"column":null}},"line":883},"36":{"name":"(anonymous_36)","decl":{"start":{"line":892,"column":34},"end":{"line":892,"column":35}},"loc":{"start":{"line":892,"column":44},"end":{"line":898,"column":8}},"line":892},"37":{"name":"(anonymous_37)","decl":{"start":{"line":895,"column":39},"end":{"line":895,"column":40}},"loc":{"start":{"line":895,"column":49},"end":{"line":895,"column":75}},"line":895},"38":{"name":"(anonymous_38)","decl":{"start":{"line":899,"column":34},"end":{"line":899,"column":35}},"loc":{"start":{"line":899,"column":44},"end":{"line":905,"column":8}},"line":899},"39":{"name":"(anonymous_39)","decl":{"start":{"line":906,"column":38},"end":{"line":906,"column":39}},"loc":{"start":{"line":906,"column":47},"end":{"line":919,"column":8}},"line":906},"40":{"name":"(anonymous_40)","decl":{"start":{"line":910,"column":38},"end":{"line":910,"column":39}},"loc":{"start":{"line":910,"column":46},"end":{"line":910,"column":75}},"line":910},"41":{"name":"(anonymous_41)","decl":{"start":{"line":920,"column":34},"end":{"line":920,"column":35}},"loc":{"start":{"line":920,"column":44},"end":{"line":933,"column":8}},"line":920},"42":{"name":"(anonymous_42)","decl":{"start":{"line":943,"column":10},"end":{"line":943,"column":null}},"loc":{"start":{"line":947,"column":23},"end":{"line":988,"column":null}},"line":947},"43":{"name":"(anonymous_43)","decl":{"start":{"line":951,"column":41},"end":{"line":951,"column":42}},"loc":{"start":{"line":951,"column":48},"end":{"line":951,"column":75}},"line":951},"44":{"name":"(anonymous_44)","decl":{"start":{"line":993,"column":10},"end":{"line":993,"column":21}},"loc":{"start":{"line":993,"column":48},"end":{"line":1000,"column":null}},"line":993},"45":{"name":"(anonymous_45)","decl":{"start":{"line":1005,"column":10},"end":{"line":1005,"column":null}},"loc":{"start":{"line":1010,"column":19},"end":{"line":1046,"column":null}},"line":1010},"46":{"name":"(anonymous_46)","decl":{"start":{"line":1039,"column":38},"end":{"line":1039,"column":39}},"loc":{"start":{"line":1039,"column":45},"end":{"line":1039,"column":69}},"line":1039},"47":{"name":"(anonymous_47)","decl":{"start":{"line":1051,"column":10},"end":{"line":1051,"column":28}},"loc":{"start":{"line":1051,"column":66},"end":{"line":1117,"column":null}},"line":1051},"48":{"name":"(anonymous_48)","decl":{"start":{"line":1122,"column":2},"end":{"line":1122,"column":54}},"loc":{"start":{"line":1122,"column":54},"end":{"line":1124,"column":null}},"line":1122},"49":{"name":"(anonymous_49)","decl":{"start":{"line":1123,"column":11},"end":{"line":1123,"column":17}},"loc":{"start":{"line":1123,"column":17},"end":{"line":1123,"column":null}},"line":1123},"50":{"name":"(anonymous_50)","decl":{"start":{"line":1129,"column":2},"end":{"line":1129,"column":17}},"loc":{"start":{"line":1129,"column":43},"end":{"line":1136,"column":null}},"line":1129}},"branchMap":{"0":{"loc":{"start":{"line":87,"column":41},"end":{"line":87,"column":58}},"type":"default-arg","locations":[{"start":{"line":87,"column":51},"end":{"line":87,"column":58}}],"line":87},"1":{"loc":{"start":{"line":97,"column":4},"end":{"line":105,"column":null}},"type":"if","locations":[{"start":{"line":97,"column":4},"end":{"line":105,"column":null}},{"start":{},"end":{}}],"line":97},"2":{"loc":{"start":{"line":98,"column":6},"end":{"line":100,"column":null}},"type":"if","locations":[{"start":{"line":98,"column":6},"end":{"line":100,"column":null}},{"start":{},"end":{}}],"line":98},"3":{"loc":{"start":{"line":101,"column":6},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":6},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":101},"4":{"loc":{"start":{"line":104,"column":29},"end":{"line":104,"column":null}},"type":"binary-expr","locations":[{"start":{"line":104,"column":29},"end":{"line":104,"column":58}},{"start":{"line":104,"column":58},"end":{"line":104,"column":null}}],"line":104},"5":{"loc":{"start":{"line":111,"column":4},"end":{"line":119,"column":null}},"type":"if","locations":[{"start":{"line":111,"column":4},"end":{"line":119,"column":null}},{"start":{},"end":{}}],"line":111},"6":{"loc":{"start":{"line":112,"column":6},"end":{"line":114,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":6},"end":{"line":114,"column":null}},{"start":{},"end":{}}],"line":112},"7":{"loc":{"start":{"line":115,"column":6},"end":{"line":117,"column":null}},"type":"if","locations":[{"start":{"line":115,"column":6},"end":{"line":117,"column":null}},{"start":{},"end":{}}],"line":115},"8":{"loc":{"start":{"line":136,"column":6},"end":{"line":140,"column":null}},"type":"if","locations":[{"start":{"line":136,"column":6},"end":{"line":140,"column":null}},{"start":{"line":138,"column":13},"end":{"line":140,"column":null}}],"line":136},"9":{"loc":{"start":{"line":136,"column":10},"end":{"line":136,"column":55}},"type":"binary-expr","locations":[{"start":{"line":136,"column":10},"end":{"line":136,"column":22}},{"start":{"line":136,"column":22},"end":{"line":136,"column":55}}],"line":136},"10":{"loc":{"start":{"line":146,"column":4},"end":{"line":156,"column":null}},"type":"if","locations":[{"start":{"line":146,"column":4},"end":{"line":156,"column":null}},{"start":{"line":153,"column":11},"end":{"line":156,"column":null}}],"line":146},"11":{"loc":{"start":{"line":147,"column":6},"end":{"line":148,"column":null}},"type":"if","locations":[{"start":{"line":147,"column":6},"end":{"line":148,"column":null}},{"start":{"line":148,"column":11},"end":{"line":148,"column":null}}],"line":147},"12":{"loc":{"start":{"line":149,"column":6},"end":{"line":150,"column":null}},"type":"if","locations":[{"start":{"line":149,"column":6},"end":{"line":150,"column":null}},{"start":{"line":150,"column":11},"end":{"line":150,"column":null}}],"line":149},"13":{"loc":{"start":{"line":151,"column":6},"end":{"line":152,"column":null}},"type":"if","locations":[{"start":{"line":151,"column":6},"end":{"line":152,"column":null}},{"start":{"line":152,"column":11},"end":{"line":152,"column":null}}],"line":151},"14":{"loc":{"start":{"line":158,"column":6},"end":{"line":159,"column":null}},"type":"if","locations":[{"start":{"line":158,"column":6},"end":{"line":159,"column":null}},{"start":{"line":159,"column":11},"end":{"line":159,"column":null}}],"line":158},"15":{"loc":{"start":{"line":161,"column":4},"end":{"line":165,"column":null}},"type":"if","locations":[{"start":{"line":161,"column":4},"end":{"line":165,"column":null}},{"start":{},"end":{}}],"line":161},"16":{"loc":{"start":{"line":166,"column":4},"end":{"line":170,"column":null}},"type":"if","locations":[{"start":{"line":166,"column":4},"end":{"line":170,"column":null}},{"start":{},"end":{}}],"line":166},"17":{"loc":{"start":{"line":175,"column":20},"end":{"line":175,"column":null}},"type":"binary-expr","locations":[{"start":{"line":175,"column":20},"end":{"line":175,"column":32}},{"start":{"line":175,"column":32},"end":{"line":175,"column":null}}],"line":175},"18":{"loc":{"start":{"line":183,"column":14},"end":{"line":183,"column":73}},"type":"default-arg","locations":[{"start":{"line":183,"column":47},"end":{"line":183,"column":73}}],"line":183},"19":{"loc":{"start":{"line":186,"column":12},"end":{"line":186,"column":null}},"type":"binary-expr","locations":[{"start":{"line":186,"column":12},"end":{"line":186,"column":28}},{"start":{"line":186,"column":28},"end":{"line":186,"column":null}}],"line":186},"20":{"loc":{"start":{"line":187,"column":15},"end":{"line":187,"column":null}},"type":"binary-expr","locations":[{"start":{"line":187,"column":15},"end":{"line":187,"column":34}},{"start":{"line":187,"column":34},"end":{"line":187,"column":null}}],"line":187},"21":{"loc":{"start":{"line":188,"column":21},"end":{"line":188,"column":null}},"type":"binary-expr","locations":[{"start":{"line":188,"column":21},"end":{"line":188,"column":46}},{"start":{"line":188,"column":46},"end":{"line":188,"column":null}}],"line":188},"22":{"loc":{"start":{"line":190,"column":8},"end":{"line":192,"column":null}},"type":"binary-expr","locations":[{"start":{"line":190,"column":8},"end":{"line":190,"column":null}},{"start":{"line":191,"column":8},"end":{"line":191,"column":null}},{"start":{"line":192,"column":8},"end":{"line":192,"column":null}}],"line":190},"23":{"loc":{"start":{"line":192,"column":22},"end":{"line":192,"column":71}},"type":"binary-expr","locations":[{"start":{"line":192,"column":22},"end":{"line":192,"column":47}},{"start":{"line":192,"column":47},"end":{"line":192,"column":71}}],"line":192},"24":{"loc":{"start":{"line":193,"column":17},"end":{"line":193,"column":null}},"type":"binary-expr","locations":[{"start":{"line":193,"column":17},"end":{"line":193,"column":38}},{"start":{"line":193,"column":38},"end":{"line":193,"column":null}}],"line":193},"25":{"loc":{"start":{"line":194,"column":15},"end":{"line":194,"column":null}},"type":"binary-expr","locations":[{"start":{"line":194,"column":15},"end":{"line":194,"column":34}},{"start":{"line":194,"column":34},"end":{"line":194,"column":null}}],"line":194},"26":{"loc":{"start":{"line":203,"column":6},"end":{"line":206,"column":null}},"type":"if","locations":[{"start":{"line":203,"column":6},"end":{"line":206,"column":null}},{"start":{},"end":{}}],"line":203},"27":{"loc":{"start":{"line":215,"column":6},"end":{"line":217,"column":null}},"type":"if","locations":[{"start":{"line":215,"column":6},"end":{"line":217,"column":null}},{"start":{},"end":{}}],"line":215},"28":{"loc":{"start":{"line":223,"column":6},"end":{"line":264,"column":null}},"type":"if","locations":[{"start":{"line":223,"column":6},"end":{"line":264,"column":null}},{"start":{"line":260,"column":13},"end":{"line":264,"column":null}}],"line":223},"29":{"loc":{"start":{"line":229,"column":8},"end":{"line":259,"column":null}},"type":"if","locations":[{"start":{"line":229,"column":8},"end":{"line":259,"column":null}},{"start":{"line":240,"column":15},"end":{"line":259,"column":null}}],"line":229},"30":{"loc":{"start":{"line":231,"column":26},"end":{"line":231,"column":null}},"type":"binary-expr","locations":[{"start":{"line":231,"column":26},"end":{"line":231,"column":53}},{"start":{"line":231,"column":53},"end":{"line":231,"column":null}}],"line":231},"31":{"loc":{"start":{"line":235,"column":10},"end":{"line":239,"column":null}},"type":"if","locations":[{"start":{"line":235,"column":10},"end":{"line":239,"column":null}},{"start":{},"end":{}}],"line":235},"32":{"loc":{"start":{"line":245,"column":20},"end":{"line":245,"column":68}},"type":"binary-expr","locations":[{"start":{"line":245,"column":20},"end":{"line":245,"column":64}},{"start":{"line":245,"column":64},"end":{"line":245,"column":68}}],"line":245},"33":{"loc":{"start":{"line":254,"column":10},"end":{"line":258,"column":null}},"type":"if","locations":[{"start":{"line":254,"column":10},"end":{"line":258,"column":null}},{"start":{},"end":{}}],"line":254},"34":{"loc":{"start":{"line":297,"column":10},"end":{"line":301,"column":null}},"type":"if","locations":[{"start":{"line":297,"column":10},"end":{"line":301,"column":null}},{"start":{},"end":{}}],"line":297},"35":{"loc":{"start":{"line":297,"column":14},"end":{"line":297,"column":75}},"type":"binary-expr","locations":[{"start":{"line":297,"column":14},"end":{"line":297,"column":30}},{"start":{"line":297,"column":30},"end":{"line":297,"column":75}}],"line":297},"36":{"loc":{"start":{"line":316,"column":6},"end":{"line":318,"column":null}},"type":"if","locations":[{"start":{"line":316,"column":6},"end":{"line":318,"column":null}},{"start":{},"end":{}}],"line":316},"37":{"loc":{"start":{"line":325,"column":6},"end":{"line":342,"column":null}},"type":"if","locations":[{"start":{"line":325,"column":6},"end":{"line":342,"column":null}},{"start":{"line":336,"column":13},"end":{"line":342,"column":null}}],"line":325},"38":{"loc":{"start":{"line":326,"column":8},"end":{"line":330,"column":null}},"type":"if","locations":[{"start":{"line":326,"column":8},"end":{"line":330,"column":null}},{"start":{},"end":{}}],"line":326},"39":{"loc":{"start":{"line":333,"column":8},"end":{"line":335,"column":null}},"type":"if","locations":[{"start":{"line":333,"column":8},"end":{"line":335,"column":null}},{"start":{},"end":{}}],"line":333},"40":{"loc":{"start":{"line":337,"column":8},"end":{"line":341,"column":null}},"type":"if","locations":[{"start":{"line":337,"column":8},"end":{"line":341,"column":null}},{"start":{},"end":{}}],"line":337},"41":{"loc":{"start":{"line":345,"column":12},"end":{"line":348,"column":null}},"type":"binary-expr","locations":[{"start":{"line":346,"column":9},"end":{"line":346,"column":27}},{"start":{"line":346,"column":27},"end":{"line":346,"column":null}},{"start":{"line":347,"column":8},"end":{"line":347,"column":null}},{"start":{"line":348,"column":8},"end":{"line":348,"column":null}}],"line":345},"42":{"loc":{"start":{"line":349,"column":6},"end":{"line":376,"column":null}},"type":"if","locations":[{"start":{"line":349,"column":6},"end":{"line":376,"column":null}},{"start":{},"end":{}}],"line":349},"43":{"loc":{"start":{"line":350,"column":8},"end":{"line":352,"column":null}},"type":"if","locations":[{"start":{"line":350,"column":8},"end":{"line":352,"column":null}},{"start":{},"end":{}}],"line":350},"44":{"loc":{"start":{"line":360,"column":10},"end":{"line":365,"column":null}},"type":"if","locations":[{"start":{"line":360,"column":10},"end":{"line":365,"column":null}},{"start":{},"end":{}}],"line":360},"45":{"loc":{"start":{"line":366,"column":10},"end":{"line":370,"column":null}},"type":"if","locations":[{"start":{"line":366,"column":10},"end":{"line":370,"column":null}},{"start":{},"end":{}}],"line":366},"46":{"loc":{"start":{"line":373,"column":39},"end":{"line":373,"column":99}},"type":"cond-expr","locations":[{"start":{"line":373,"column":66},"end":{"line":373,"column":84}},{"start":{"line":373,"column":84},"end":{"line":373,"column":99}}],"line":373},"47":{"loc":{"start":{"line":382,"column":6},"end":{"line":395,"column":null}},"type":"if","locations":[{"start":{"line":382,"column":6},"end":{"line":395,"column":null}},{"start":{},"end":{}}],"line":382},"48":{"loc":{"start":{"line":385,"column":10},"end":{"line":389,"column":null}},"type":"if","locations":[{"start":{"line":385,"column":10},"end":{"line":389,"column":null}},{"start":{},"end":{}}],"line":385},"49":{"loc":{"start":{"line":392,"column":44},"end":{"line":392,"column":110}},"type":"cond-expr","locations":[{"start":{"line":392,"column":73},"end":{"line":392,"column":93}},{"start":{"line":392,"column":93},"end":{"line":392,"column":110}}],"line":392},"50":{"loc":{"start":{"line":399,"column":6},"end":{"line":411,"column":null}},"type":"if","locations":[{"start":{"line":399,"column":6},"end":{"line":411,"column":null}},{"start":{},"end":{}}],"line":399},"51":{"loc":{"start":{"line":453,"column":21},"end":{"line":455,"column":null}},"type":"cond-expr","locations":[{"start":{"line":454,"column":8},"end":{"line":454,"column":null}},{"start":{"line":455,"column":8},"end":{"line":455,"column":null}}],"line":453},"52":{"loc":{"start":{"line":457,"column":4},"end":{"line":464,"column":null}},"type":"if","locations":[{"start":{"line":457,"column":4},"end":{"line":464,"column":null}},{"start":{"line":459,"column":11},"end":{"line":464,"column":null}}],"line":457},"53":{"loc":{"start":{"line":476,"column":10},"end":{"line":476,"column":null}},"type":"if","locations":[{"start":{"line":476,"column":10},"end":{"line":476,"column":null}},{"start":{},"end":{}}],"line":476},"54":{"loc":{"start":{"line":478,"column":10},"end":{"line":485,"column":null}},"type":"if","locations":[{"start":{"line":478,"column":10},"end":{"line":485,"column":null}},{"start":{"line":480,"column":10},"end":{"line":485,"column":null}}],"line":478},"55":{"loc":{"start":{"line":480,"column":10},"end":{"line":485,"column":null}},"type":"if","locations":[{"start":{"line":480,"column":10},"end":{"line":485,"column":null}},{"start":{},"end":{}}],"line":480},"56":{"loc":{"start":{"line":481,"column":12},"end":{"line":482,"column":null}},"type":"binary-expr","locations":[{"start":{"line":481,"column":12},"end":{"line":481,"column":null}},{"start":{"line":482,"column":12},"end":{"line":482,"column":null}}],"line":481},"57":{"loc":{"start":{"line":502,"column":4},"end":{"line":504,"column":null}},"type":"if","locations":[{"start":{"line":502,"column":4},"end":{"line":504,"column":null}},{"start":{},"end":{}}],"line":502},"58":{"loc":{"start":{"line":502,"column":8},"end":{"line":502,"column":67}},"type":"binary-expr","locations":[{"start":{"line":502,"column":8},"end":{"line":502,"column":40}},{"start":{"line":502,"column":40},"end":{"line":502,"column":67}}],"line":502},"59":{"loc":{"start":{"line":510,"column":29},"end":{"line":510,"column":40}},"type":"binary-expr","locations":[{"start":{"line":510,"column":29},"end":{"line":510,"column":38}},{"start":{"line":510,"column":38},"end":{"line":510,"column":40}}],"line":510},"60":{"loc":{"start":{"line":513,"column":8},"end":{"line":515,"column":null}},"type":"cond-expr","locations":[{"start":{"line":514,"column":12},"end":{"line":514,"column":null}},{"start":{"line":515,"column":12},"end":{"line":515,"column":null}}],"line":513},"61":{"loc":{"start":{"line":520,"column":10},"end":{"line":522,"column":null}},"type":"binary-expr","locations":[{"start":{"line":520,"column":10},"end":{"line":520,"column":null}},{"start":{"line":521,"column":10},"end":{"line":521,"column":null}},{"start":{"line":522,"column":10},"end":{"line":522,"column":null}}],"line":520},"62":{"loc":{"start":{"line":529,"column":8},"end":{"line":531,"column":null}},"type":"if","locations":[{"start":{"line":529,"column":8},"end":{"line":531,"column":null}},{"start":{},"end":{}}],"line":529},"63":{"loc":{"start":{"line":542,"column":4},"end":{"line":561,"column":null}},"type":"if","locations":[{"start":{"line":542,"column":4},"end":{"line":561,"column":null}},{"start":{},"end":{}}],"line":542},"64":{"loc":{"start":{"line":542,"column":8},"end":{"line":542,"column":53}},"type":"binary-expr","locations":[{"start":{"line":542,"column":8},"end":{"line":542,"column":31}},{"start":{"line":542,"column":31},"end":{"line":542,"column":53}}],"line":542},"65":{"loc":{"start":{"line":544,"column":6},"end":{"line":559,"column":null}},"type":"if","locations":[{"start":{"line":544,"column":6},"end":{"line":559,"column":null}},{"start":{},"end":{}}],"line":544},"66":{"loc":{"start":{"line":546,"column":10},"end":{"line":546,"column":null}},"type":"cond-expr","locations":[{"start":{"line":546,"column":33},"end":{"line":546,"column":52}},{"start":{"line":546,"column":52},"end":{"line":546,"column":null}}],"line":546},"67":{"loc":{"start":{"line":547,"column":8},"end":{"line":558,"column":null}},"type":"if","locations":[{"start":{"line":547,"column":8},"end":{"line":558,"column":null}},{"start":{},"end":{}}],"line":547},"68":{"loc":{"start":{"line":550,"column":10},"end":{"line":557,"column":null}},"type":"if","locations":[{"start":{"line":550,"column":10},"end":{"line":557,"column":null}},{"start":{},"end":{}}],"line":550},"69":{"loc":{"start":{"line":563,"column":4},"end":{"line":592,"column":null}},"type":"if","locations":[{"start":{"line":563,"column":4},"end":{"line":592,"column":null}},{"start":{},"end":{}}],"line":563},"70":{"loc":{"start":{"line":564,"column":6},"end":{"line":567,"column":null}},"type":"binary-expr","locations":[{"start":{"line":564,"column":6},"end":{"line":564,"column":null}},{"start":{"line":565,"column":6},"end":{"line":565,"column":null}},{"start":{"line":566,"column":6},"end":{"line":566,"column":null}},{"start":{"line":567,"column":6},"end":{"line":567,"column":null}}],"line":564},"71":{"loc":{"start":{"line":569,"column":6},"end":{"line":584,"column":null}},"type":"if","locations":[{"start":{"line":569,"column":6},"end":{"line":584,"column":null}},{"start":{},"end":{}}],"line":569},"72":{"loc":{"start":{"line":571,"column":10},"end":{"line":571,"column":null}},"type":"cond-expr","locations":[{"start":{"line":571,"column":33},"end":{"line":571,"column":52}},{"start":{"line":571,"column":52},"end":{"line":571,"column":null}}],"line":571},"73":{"loc":{"start":{"line":572,"column":8},"end":{"line":583,"column":null}},"type":"if","locations":[{"start":{"line":572,"column":8},"end":{"line":583,"column":null}},{"start":{},"end":{}}],"line":572},"74":{"loc":{"start":{"line":575,"column":10},"end":{"line":582,"column":null}},"type":"if","locations":[{"start":{"line":575,"column":10},"end":{"line":582,"column":null}},{"start":{},"end":{}}],"line":575},"75":{"loc":{"start":{"line":596,"column":4},"end":{"line":603,"column":null}},"type":"if","locations":[{"start":{"line":596,"column":4},"end":{"line":603,"column":null}},{"start":{},"end":{}}],"line":596},"76":{"loc":{"start":{"line":613,"column":21},"end":{"line":613,"column":null}},"type":"binary-expr","locations":[{"start":{"line":613,"column":21},"end":{"line":613,"column":36}},{"start":{"line":613,"column":36},"end":{"line":613,"column":null}}],"line":613},"77":{"loc":{"start":{"line":614,"column":25},"end":{"line":614,"column":null}},"type":"binary-expr","locations":[{"start":{"line":614,"column":25},"end":{"line":614,"column":48}},{"start":{"line":614,"column":48},"end":{"line":614,"column":null}}],"line":614},"78":{"loc":{"start":{"line":699,"column":20},"end":{"line":699,"column":null}},"type":"binary-expr","locations":[{"start":{"line":699,"column":20},"end":{"line":699,"column":50}},{"start":{"line":699,"column":50},"end":{"line":699,"column":null}}],"line":699},"79":{"loc":{"start":{"line":706,"column":11},"end":{"line":707,"column":null}},"type":"binary-expr","locations":[{"start":{"line":706,"column":11},"end":{"line":706,"column":null}},{"start":{"line":707,"column":11},"end":{"line":707,"column":null}}],"line":706},"80":{"loc":{"start":{"line":720,"column":10},"end":{"line":724,"column":null}},"type":"binary-expr","locations":[{"start":{"line":720,"column":10},"end":{"line":720,"column":null}},{"start":{"line":721,"column":10},"end":{"line":721,"column":null}},{"start":{"line":722,"column":10},"end":{"line":722,"column":null}},{"start":{"line":723,"column":10},"end":{"line":723,"column":null}},{"start":{"line":724,"column":10},"end":{"line":724,"column":null}}],"line":720},"81":{"loc":{"start":{"line":730,"column":10},"end":{"line":732,"column":null}},"type":"cond-expr","locations":[{"start":{"line":731,"column":15},"end":{"line":731,"column":null}},{"start":{"line":732,"column":15},"end":{"line":732,"column":null}}],"line":730},"82":{"loc":{"start":{"line":730,"column":10},"end":{"line":730,"column":null}},"type":"binary-expr","locations":[{"start":{"line":730,"column":10},"end":{"line":730,"column":41}},{"start":{"line":730,"column":41},"end":{"line":730,"column":null}}],"line":730},"83":{"loc":{"start":{"line":775,"column":11},"end":{"line":775,"column":null}},"type":"binary-expr","locations":[{"start":{"line":775,"column":11},"end":{"line":775,"column":31}},{"start":{"line":775,"column":31},"end":{"line":775,"column":null}}],"line":775},"84":{"loc":{"start":{"line":873,"column":6},"end":{"line":875,"column":null}},"type":"if","locations":[{"start":{"line":873,"column":6},"end":{"line":875,"column":null}},{"start":{},"end":{}}],"line":873},"85":{"loc":{"start":{"line":873,"column":10},"end":{"line":873,"column":77}},"type":"binary-expr","locations":[{"start":{"line":873,"column":10},"end":{"line":873,"column":44}},{"start":{"line":873,"column":44},"end":{"line":873,"column":77}}],"line":873},"86":{"loc":{"start":{"line":895,"column":49},"end":{"line":895,"column":75}},"type":"binary-expr","locations":[{"start":{"line":895,"column":49},"end":{"line":895,"column":66}},{"start":{"line":895,"column":66},"end":{"line":895,"column":75}}],"line":895},"87":{"loc":{"start":{"line":902,"column":14},"end":{"line":902,"column":null}},"type":"cond-expr","locations":[{"start":{"line":902,"column":30},"end":{"line":902,"column":42}},{"start":{"line":902,"column":42},"end":{"line":902,"column":null}}],"line":902},"88":{"loc":{"start":{"line":934,"column":17},"end":{"line":934,"column":null}},"type":"binary-expr","locations":[{"start":{"line":934,"column":17},"end":{"line":934,"column":37}},{"start":{"line":934,"column":37},"end":{"line":934,"column":null}}],"line":934},"89":{"loc":{"start":{"line":954,"column":25},"end":{"line":954,"column":null}},"type":"binary-expr","locations":[{"start":{"line":954,"column":25},"end":{"line":954,"column":55}},{"start":{"line":954,"column":55},"end":{"line":954,"column":null}}],"line":954},"90":{"loc":{"start":{"line":955,"column":6},"end":{"line":955,"column":null}},"type":"if","locations":[{"start":{"line":955,"column":6},"end":{"line":955,"column":null}},{"start":{},"end":{}}],"line":955},"91":{"loc":{"start":{"line":958,"column":22},"end":{"line":958,"column":null}},"type":"binary-expr","locations":[{"start":{"line":958,"column":22},"end":{"line":958,"column":49}},{"start":{"line":958,"column":49},"end":{"line":958,"column":null}}],"line":958},"92":{"loc":{"start":{"line":968,"column":8},"end":{"line":968,"column":null}},"type":"if","locations":[{"start":{"line":968,"column":8},"end":{"line":968,"column":null}},{"start":{},"end":{}}],"line":968},"93":{"loc":{"start":{"line":995,"column":6},"end":{"line":998,"column":null}},"type":"binary-expr","locations":[{"start":{"line":995,"column":6},"end":{"line":995,"column":null}},{"start":{"line":996,"column":6},"end":{"line":996,"column":null}},{"start":{"line":997,"column":6},"end":{"line":997,"column":null}},{"start":{"line":998,"column":6},"end":{"line":998,"column":null}}],"line":995},"94":{"loc":{"start":{"line":1012,"column":4},"end":{"line":1014,"column":null}},"type":"if","locations":[{"start":{"line":1012,"column":4},"end":{"line":1014,"column":null}},{"start":{},"end":{}}],"line":1012},"95":{"loc":{"start":{"line":1012,"column":8},"end":{"line":1012,"column":63}},"type":"binary-expr","locations":[{"start":{"line":1012,"column":8},"end":{"line":1012,"column":35}},{"start":{"line":1012,"column":35},"end":{"line":1012,"column":63}}],"line":1012},"96":{"loc":{"start":{"line":1018,"column":4},"end":{"line":1027,"column":null}},"type":"if","locations":[{"start":{"line":1018,"column":4},"end":{"line":1027,"column":null}},{"start":{"line":1022,"column":4},"end":{"line":1027,"column":null}}],"line":1018},"97":{"loc":{"start":{"line":1022,"column":4},"end":{"line":1027,"column":null}},"type":"if","locations":[{"start":{"line":1022,"column":4},"end":{"line":1027,"column":null}},{"start":{"line":1025,"column":11},"end":{"line":1027,"column":null}}],"line":1022},"98":{"loc":{"start":{"line":1040,"column":6},"end":{"line":1042,"column":null}},"type":"if","locations":[{"start":{"line":1040,"column":6},"end":{"line":1042,"column":null}},{"start":{},"end":{}}],"line":1040},"99":{"loc":{"start":{"line":1055,"column":4},"end":{"line":1057,"column":null}},"type":"if","locations":[{"start":{"line":1055,"column":4},"end":{"line":1057,"column":null}},{"start":{},"end":{}}],"line":1055},"100":{"loc":{"start":{"line":1055,"column":8},"end":{"line":1055,"column":56}},"type":"binary-expr","locations":[{"start":{"line":1055,"column":8},"end":{"line":1055,"column":26}},{"start":{"line":1055,"column":26},"end":{"line":1055,"column":56}}],"line":1055}},"s":{"0":55,"1":55,"2":55,"3":55,"4":55,"5":55,"6":55,"7":55,"8":55,"9":55,"10":55,"11":0,"12":0,"13":0,"14":0,"15":0,"16":55,"17":55,"18":55,"19":0,"20":0,"21":0,"22":0,"23":0,"24":55,"25":55,"26":55,"27":55,"28":220,"29":55,"30":220,"31":220,"32":0,"33":220,"34":55,"35":55,"36":55,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":55,"47":55,"48":220,"49":0,"50":220,"51":55,"52":0,"53":55,"54":55,"55":55,"56":55,"57":55,"58":55,"59":55,"60":55,"61":2,"62":2,"63":2,"64":2,"65":2,"66":2,"67":0,"68":0,"69":2,"70":2,"71":0,"72":2,"73":2,"74":2,"75":2,"76":2,"77":0,"78":0,"79":0,"80":0,"81":0,"82":2,"83":2,"84":2,"85":2,"86":2,"87":2,"88":2,"89":0,"90":0,"91":0,"92":2,"93":2,"94":2,"95":2,"96":2,"97":2,"98":2,"99":2,"100":2,"101":2,"102":2,"103":2,"104":2,"105":2,"106":2,"107":2,"108":0,"109":0,"110":2,"111":2,"112":2,"113":0,"114":2,"115":2,"116":2,"117":2,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0,"125":2,"126":0,"127":2,"128":2,"129":0,"130":0,"131":0,"132":0,"133":0,"134":0,"135":0,"136":0,"137":0,"138":0,"139":0,"140":2,"141":2,"142":0,"143":0,"144":0,"145":0,"146":0,"147":2,"148":2,"149":0,"150":0,"151":0,"152":0,"153":0,"154":0,"155":0,"156":2,"157":0,"158":0,"159":0,"160":2,"161":2,"162":2,"163":2,"164":0,"165":0,"166":2,"167":3,"168":3,"169":12,"170":2,"171":2,"172":2,"173":2,"174":3,"175":3,"176":0,"177":3,"178":0,"179":3,"180":2,"181":0,"182":2,"183":2,"184":2,"185":2,"186":0,"187":0,"188":0,"189":0,"190":0,"191":0,"192":0,"193":0,"194":0,"195":0,"196":0,"197":0,"198":2,"199":2,"200":2,"201":0,"202":0,"203":0,"204":0,"205":0,"206":0,"207":2,"208":0,"209":0,"210":0,"211":0,"212":0,"213":0,"214":0,"215":0,"216":0,"217":0,"218":0,"219":0,"220":0,"221":0,"222":0,"223":2,"224":2,"225":2,"226":2,"227":1,"228":2,"229":0,"230":2,"231":0,"232":0,"233":0,"234":0,"235":0,"236":0,"237":0,"238":0,"239":0,"240":0,"241":0,"242":0,"243":0,"244":0,"245":0,"246":0,"247":2,"248":2,"249":2,"250":2,"251":2,"252":70,"253":70,"254":70,"255":2,"256":2,"257":2,"258":1,"259":1,"260":2,"261":0,"262":0,"263":2,"264":0,"265":0,"266":2,"267":2,"268":27,"269":26,"270":2,"271":2,"272":0,"273":0,"274":2,"275":1,"276":0,"277":0,"278":2,"279":2,"280":2,"281":2,"282":0,"283":0,"284":0,"285":0,"286":0,"287":0,"288":0,"289":0,"290":0,"291":0,"292":2,"293":2,"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"300":0,"301":0,"302":0,"303":0,"304":0,"305":0,"306":0,"307":0,"308":0,"309":2,"310":2,"311":2,"312":0,"313":0,"314":0,"315":0,"316":0,"317":0,"318":0,"319":0},"f":{"0":55,"1":220,"2":2,"3":0,"4":2,"5":2,"6":2,"7":0,"8":2,"9":3,"10":12,"11":2,"12":2,"13":0,"14":0,"15":0,"16":0,"17":0,"18":2,"19":2,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":2,"29":2,"30":2,"31":1,"32":0,"33":0,"34":2,"35":2,"36":0,"37":0,"38":2,"39":1,"40":0,"41":0,"42":2,"43":2,"44":2,"45":0,"46":0,"47":2,"48":0,"49":0,"50":0},"b":{"0":[55],"1":[0,55],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,55],"6":[0,0],"7":[0,0],"8":[0,220],"9":[220,220],"10":[0,55],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,220],"15":[0,55],"16":[55,0],"17":[55,0],"18":[2],"19":[2,0],"20":[2,2],"21":[2,0],"22":[2,0,0],"23":[0,0],"24":[2,0],"25":[2,2],"26":[0,2],"27":[0,2],"28":[2,0],"29":[0,2],"30":[0,0],"31":[0,0],"32":[2,0],"33":[0,2],"34":[0,2],"35":[2,0],"36":[0,2],"37":[0,2],"38":[0,0],"39":[0,0],"40":[0,2],"41":[2,2,2,0],"42":[0,2],"43":[0,0],"44":[0,0],"45":[0,0],"46":[0,0],"47":[0,2],"48":[0,0],"49":[0,0],"50":[0,2],"51":[0,2],"52":[2,0],"53":[0,3],"54":[0,3],"55":[2,1],"56":[3,3],"57":[2,0],"58":[2,0],"59":[0,0],"60":[0,0],"61":[0,0,0],"62":[0,0],"63":[2,0],"64":[2,0],"65":[0,2],"66":[0,0],"67":[0,0],"68":[0,0],"69":[0,0],"70":[0,0,0,0],"71":[0,0],"72":[0,0],"73":[0,0],"74":[0,0],"75":[0,0],"76":[2,0],"77":[2,0],"78":[0,0],"79":[0,0],"80":[0,0,0,0,0],"81":[0,0],"82":[0,0],"83":[0,0],"84":[26,1],"85":[27,1],"86":[0,0],"87":[0,2],"88":[2,0],"89":[0,0],"90":[0,0],"91":[0,0],"92":[0,0],"93":[2,2,2,2],"94":[0,0],"95":[0,0],"96":[0,0],"97":[0,0],"98":[0,0],"99":[2,0],"100":[2,2]},"meta":{"lastBranch":101,"lastFunction":51,"lastStatement":320,"seen":{"s:72:58:72:Infinity":0,"s:73:52:73:Infinity":1,"s:74:58:74:Infinity":2,"s:75:52:75:Infinity":3,"f:87:2:87:14":0,"b:87:51:87:58":0,"s:88:4:88:Infinity":4,"s:89:4:89:Infinity":5,"s:90:4:90:Infinity":6,"s:94:21:94:Infinity":7,"s:95:10:95:Infinity":8,"s:96:4:96:Infinity":9,"b:97:4:105:Infinity:undefined:undefined:undefined:undefined":1,"s:97:4:105:Infinity":10,"b:98:6:100:Infinity:undefined:undefined:undefined:undefined":2,"s:98:6:100:Infinity":11,"s:99:8:99:Infinity":12,"b:101:6:103:Infinity:undefined:undefined:undefined:undefined":3,"s:101:6:103:Infinity":13,"s:102:8:102:Infinity":14,"s:104:6:104:Infinity":15,"b:104:29:104:58:104:58:104:Infinity":4,"s:109:10:109:Infinity":16,"s:110:4:110:Infinity":17,"b:111:4:119:Infinity:undefined:undefined:undefined:undefined":5,"s:111:4:119:Infinity":18,"b:112:6:114:Infinity:undefined:undefined:undefined:undefined":6,"s:112:6:114:Infinity":19,"s:113:8:113:Infinity":20,"b:115:6:117:Infinity:undefined:undefined:undefined:undefined":7,"s:115:6:117:Infinity":21,"s:116:8:116:Infinity":22,"s:118:6:118:Infinity":23,"s:124:10:124:Infinity":24,"s:125:10:125:Infinity":25,"s:126:27:131:Infinity":26,"s:133:21:133:Infinity":27,"f:133:43:133:44":1,"s:133:50:133:65":28,"s:134:4:141:Infinity":29,"s:135:23:135:Infinity":30,"b:136:6:140:Infinity:138:13:140:Infinity":8,"s:136:6:140:Infinity":31,"b:136:10:136:22:136:22:136:55":9,"s:137:8:137:Infinity":32,"s:139:8:139:Infinity":33,"s:144:35:144:Infinity":34,"s:145:34:145:Infinity":35,"b:146:4:156:Infinity:153:11:156:Infinity":10,"s:146:4:156:Infinity":36,"b:147:6:148:Infinity:148:11:148:Infinity":11,"s:147:6:148:Infinity":37,"s:147:37:147:Infinity":38,"s:148:11:148:Infinity":39,"b:149:6:150:Infinity:150:11:150:Infinity":12,"s:149:6:150:Infinity":40,"s:149:30:149:Infinity":41,"s:150:11:150:Infinity":42,"b:151:6:152:Infinity:152:11:152:Infinity":13,"s:151:6:152:Infinity":43,"s:151:37:151:Infinity":44,"s:152:11:152:Infinity":45,"s:155:6:155:Infinity":46,"s:157:4:160:Infinity":47,"b:158:6:159:Infinity:159:11:159:Infinity":14,"s:158:6:159:Infinity":48,"s:158:14:158:Infinity":49,"s:159:11:159:Infinity":50,"b:161:4:165:Infinity:undefined:undefined:undefined:undefined":15,"s:161:4:165:Infinity":51,"s:162:6:164:Infinity":52,"b:166:4:170:Infinity:undefined:undefined:undefined:undefined":16,"s:166:4:170:Infinity":53,"s:167:6:169:Infinity":54,"s:172:4:172:Infinity":55,"s:173:4:173:Infinity":56,"s:174:4:174:Infinity":57,"s:175:4:175:Infinity":58,"b:175:20:175:32:175:32:175:Infinity":17,"s:176:4:176:Infinity":59,"s:177:4:177:Infinity":60,"f:183:8:183:14":2,"b:183:47:183:73":18,"s:184:22:184:Infinity":61,"s:185:31:197:Infinity":62,"b:186:12:186:28:186:28:186:Infinity":19,"b:187:15:187:34:187:34:187:Infinity":20,"b:188:21:188:46:188:46:188:Infinity":21,"b:190:8:190:Infinity:191:8:191:Infinity:192:8:192:Infinity":22,"b:192:22:192:47:192:47:192:71":23,"b:193:17:193:38:193:38:193:Infinity":24,"b:194:15:194:34:194:34:194:Infinity":25,"s:199:29:199:Infinity":63,"s:200:31:200:Infinity":64,"s:202:4:440:Infinity":65,"b:203:6:206:Infinity:undefined:undefined:undefined:undefined":26,"s:203:6:206:Infinity":66,"s:204:8:204:Infinity":67,"s:205:8:205:Infinity":68,"s:209:20:213:Infinity":69,"b:215:6:217:Infinity:undefined:undefined:undefined:undefined":27,"s:215:6:217:Infinity":70,"s:216:8:216:Infinity":71,"s:220:27:220:Infinity":72,"s:221:25:221:Infinity":73,"b:223:6:264:Infinity:260:13:264:Infinity":28,"s:223:6:264:Infinity":74,"s:224:35:227:Infinity":75,"b:229:8:259:Infinity:240:15:259:Infinity":29,"s:229:8:259:Infinity":76,"s:230:10:232:Infinity":77,"f:231:12:231:13":3,"s:231:26:231:Infinity":78,"b:231:26:231:53:231:53:231:Infinity":30,"s:233:10:233:Infinity":79,"b:235:10:239:Infinity:undefined:undefined:undefined:undefined":31,"s:235:10:239:Infinity":80,"s:236:12:238:Infinity":81,"s:241:25:247:Infinity":82,"f:242:22:242:29":4,"s:242:36:246:14":83,"b:245:20:245:64:245:64:245:68":32,"s:249:10:251:Infinity":84,"f:250:20:250:21":5,"s:250:27:250:64":85,"f:251:17:251:18":6,"s:251:24:251:30":86,"s:252:10:252:Infinity":87,"b:254:10:258:Infinity:undefined:undefined:undefined:undefined":33,"s:254:10:258:Infinity":88,"s:255:12:257:Infinity":89,"s:262:8:262:Infinity":90,"s:263:8:263:Infinity":91,"s:267:25:267:Infinity":92,"s:268:51:268:Infinity":93,"s:269:75:269:Infinity":94,"s:270:6:275:Infinity":95,"s:277:6:305:Infinity":96,"s:278:8:304:Infinity":97,"s:279:25:282:Infinity":98,"s:283:10:283:Infinity":99,"s:284:10:284:Infinity":100,"s:285:32:285:Infinity":101,"s:286:29:286:Infinity":102,"s:288:10:288:Infinity":103,"s:291:10:291:Infinity":104,"s:294:10:294:Infinity":105,"s:295:10:295:Infinity":106,"b:297:10:301:Infinity:undefined:undefined:undefined:undefined":34,"s:297:10:301:Infinity":107,"b:297:14:297:30:297:30:297:75":35,"s:298:12:300:Infinity":108,"s:303:10:303:Infinity":109,"s:308:32:312:Infinity":110,"s:313:6:313:Infinity":111,"b:316:6:318:Infinity:undefined:undefined:undefined:undefined":36,"s:316:6:318:Infinity":112,"s:317:8:317:Infinity":113,"s:319:33:319:Infinity":114,"s:320:6:320:Infinity":115,"s:323:35:323:Infinity":116,"b:325:6:342:Infinity:336:13:342:Infinity":37,"s:325:6:342:Infinity":117,"b:326:8:330:Infinity:undefined:undefined:undefined:undefined":38,"s:326:8:330:Infinity":118,"s:327:10:329:Infinity":119,"s:331:24:331:Infinity":120,"s:332:33:332:Infinity":121,"f:332:48:332:49":7,"s:332:55:332:62":122,"b:333:8:335:Infinity:undefined:undefined:undefined:undefined":39,"s:333:8:335:Infinity":123,"s:334:10:334:Infinity":124,"b:337:8:341:Infinity:undefined:undefined:undefined:undefined":40,"s:337:8:341:Infinity":125,"s:338:10:340:Infinity":126,"s:345:12:348:Infinity":127,"b:346:9:346:27:346:27:346:Infinity:347:8:347:Infinity:348:8:348:Infinity":41,"b:349:6:376:Infinity:undefined:undefined:undefined:undefined":42,"s:349:6:376:Infinity":128,"b:350:8:352:Infinity:undefined:undefined:undefined:undefined":43,"s:350:8:352:Infinity":129,"s:351:10:351:Infinity":130,"s:353:8:375:Infinity":131,"s:354:29:354:Infinity":132,"s:355:29:359:Infinity":133,"b:360:10:365:Infinity:undefined:undefined:undefined:undefined":44,"s:360:10:365:Infinity":134,"s:361:12:364:Infinity":135,"b:366:10:370:Infinity:undefined:undefined:undefined:undefined":45,"s:366:10:370:Infinity":136,"s:367:12:369:Infinity":137,"s:368:14:368:Infinity":138,"s:372:10:374:Infinity":139,"b:373:66:373:84:373:84:373:99":46,"s:379:6:379:Infinity":140,"b:382:6:395:Infinity:undefined:undefined:undefined:undefined":47,"s:382:6:395:Infinity":141,"s:383:8:394:Infinity":142,"s:384:29:384:Infinity":143,"b:385:10:389:Infinity:undefined:undefined:undefined:undefined":48,"s:385:10:389:Infinity":144,"s:386:12:388:Infinity":145,"s:391:10:393:Infinity":146,"b:392:73:392:93:392:93:392:110":49,"s:397:23:397:Infinity":147,"b:399:6:411:Infinity:undefined:undefined:undefined:undefined":50,"s:399:6:411:Infinity":148,"s:400:22:400:Infinity":149,"s:401:8:401:Infinity":150,"s:402:8:402:Infinity":151,"s:403:8:405:Infinity":152,"s:406:8:406:Infinity":153,"s:407:8:409:Infinity":154,"s:410:8:410:Infinity":155,"s:413:6:424:Infinity":156,"s:426:23:426:Infinity":157,"s:427:6:427:Infinity":158,"s:428:6:439:Infinity":159,"f:446:16:446:Infinity":8,"s:451:28:451:Infinity":160,"s:453:21:455:Infinity":161,"b:454:8:454:Infinity:455:8:455:Infinity":51,"b:457:4:464:Infinity:459:11:464:Infinity":52,"s:457:4:464:Infinity":162,"s:458:6:458:Infinity":163,"s:460:6:462:Infinity":164,"s:463:6:463:Infinity":165,"s:466:26:469:Infinity":166,"f:466:26:466:27":9,"s:467:18:467:Infinity":167,"s:468:6:468:Infinity":168,"f:468:26:468:27":10,"s:468:34:468:50":169,"s:471:17:492:Infinity":170,"f:471:17:471:18":11,"s:472:6:491:Infinity":171,"s:473:24:473:Infinity":172,"s:474:8:486:Infinity":173,"s:475:27:475:Infinity":174,"b:476:10:476:Infinity:undefined:undefined:undefined:undefined":53,"s:476:10:476:Infinity":175,"s:476:39:476:Infinity":176,"b:478:10:485:Infinity:480:10:485:Infinity":54,"s:478:10:485:Infinity":177,"s:479:12:479:Infinity":178,"b:480:10:485:Infinity:undefined:undefined:undefined:undefined":55,"s:480:10:485:Infinity":179,"b:481:12:481:Infinity:482:12:482:Infinity":56,"s:484:12:484:Infinity":180,"s:488:8:490:Infinity":181,"s:494:4:494:Infinity":182,"s:495:4:495:Infinity":183,"f:498:10:498:Infinity":12,"b:502:4:504:Infinity:undefined:undefined:undefined:undefined":57,"s:502:4:504:Infinity":184,"b:502:8:502:40:502:40:502:67":58,"s:503:6:503:Infinity":185,"s:506:36:506:Infinity":186,"s:507:17:507:Infinity":187,"s:509:4:534:Infinity":188,"f:510:11:510:12":13,"s:510:22:510:48":189,"b:510:29:510:38:510:38:510:40":59,"f:512:11:512:12":14,"s:513:8:515:Infinity":190,"b:514:12:514:Infinity:515:12:515:Infinity":60,"f:517:14:517:15":15,"s:518:25:518:Infinity":191,"s:519:8:522:Infinity":192,"b:520:10:520:Infinity:521:10:521:Infinity:522:10:522:Infinity":61,"f:525:14:525:15":16,"s:526:8:526:Infinity":193,"f:528:14:528:15":17,"b:529:8:531:Infinity:undefined:undefined:undefined:undefined":62,"s:529:8:531:Infinity":194,"s:530:10:530:Infinity":195,"s:532:8:532:Infinity":196,"s:533:8:533:Infinity":197,"f:537:16:537:Infinity":18,"s:541:22:541:Infinity":198,"b:542:4:561:Infinity:undefined:undefined:undefined:undefined":63,"s:542:4:561:Infinity":199,"b:542:8:542:31:542:31:542:53":64,"b:544:6:559:Infinity:undefined:undefined:undefined:undefined":65,"s:544:6:559:Infinity":200,"s:546:10:546:Infinity":201,"b:546:33:546:52:546:52:546:Infinity":66,"b:547:8:558:Infinity:undefined:undefined:undefined:undefined":67,"s:547:8:558:Infinity":202,"s:548:26:548:Infinity":203,"s:549:25:549:Infinity":204,"b:550:10:557:Infinity:undefined:undefined:undefined:undefined":68,"s:550:10:557:Infinity":205,"s:551:12:556:Infinity":206,"s:560:6:560:Infinity":207,"b:563:4:592:Infinity:undefined:undefined:undefined:undefined":69,"s:563:4:592:Infinity":208,"b:564:6:564:Infinity:565:6:565:Infinity:566:6:566:Infinity:567:6:567:Infinity":70,"b:569:6:584:Infinity:undefined:undefined:undefined:undefined":71,"s:569:6:584:Infinity":209,"s:571:10:571:Infinity":210,"b:571:33:571:52:571:52:571:Infinity":72,"b:572:8:583:Infinity:undefined:undefined:undefined:undefined":73,"s:572:8:583:Infinity":211,"s:573:26:573:Infinity":212,"s:574:25:574:Infinity":213,"b:575:10:582:Infinity:undefined:undefined:undefined:undefined":74,"s:575:10:582:Infinity":214,"s:576:12:581:Infinity":215,"s:586:22:586:Infinity":216,"s:587:6:591:Infinity":217,"s:594:20:594:Infinity":218,"s:595:19:595:Infinity":219,"b:596:4:603:Infinity:undefined:undefined:undefined:undefined":75,"s:596:4:603:Infinity":220,"s:597:6:602:Infinity":221,"s:605:4:609:Infinity":222,"f:612:16:612:32":19,"s:613:21:613:Infinity":223,"b:613:21:613:36:613:36:613:Infinity":76,"s:614:25:614:Infinity":224,"b:614:25:614:48:614:48:614:Infinity":77,"s:616:5:629:Infinity":225,"s:631:4:642:Infinity":226,"s:632:7:641:Infinity":227,"s:644:4:655:Infinity":228,"s:645:7:654:Infinity":229,"s:657:4:667:Infinity":230,"s:658:7:666:Infinity":231,"f:670:10:670:Infinity":20,"s:676:25:678:Infinity":232,"s:679:17:679:Infinity":233,"s:680:16:680:Infinity":234,"s:682:20:695:Infinity":235,"f:683:14:683:15":21,"s:683:26:683:50":236,"f:684:11:684:12":22,"s:684:31:695:8":237,"s:697:22:715:Infinity":238,"f:699:8:699:9":23,"s:699:20:699:Infinity":239,"b:699:20:699:50:699:50:699:Infinity":78,"f:701:11:701:12":24,"s:701:31:715:8":240,"b:706:11:706:Infinity:707:11:707:Infinity":79,"s:717:20:737:Infinity":241,"f:719:8:719:9":25,"s:720:10:724:Infinity":242,"b:720:10:720:Infinity:721:10:721:Infinity:722:10:722:Infinity:723:10:723:Infinity:724:10:724:Infinity":80,"f:726:11:726:12":26,"s:726:31:737:8":243,"b:731:15:731:Infinity:732:15:732:Infinity":81,"b:730:10:730:41:730:41:730:Infinity":82,"s:739:4:759:Infinity":244,"f:762:10:762:32":27,"s:763:42:774:Infinity":245,"s:775:4:775:Infinity":246,"b:775:11:775:31:775:31:775:Infinity":83,"f:781:16:781:25":28,"s:782:20:782:Infinity":247,"s:783:4:783:Infinity":248,"f:786:10:786:21":29,"s:787:15:787:Infinity":249,"s:788:4:792:Infinity":250,"s:788:17:788:20":251,"s:789:19:789:Infinity":252,"s:790:6:790:Infinity":253,"s:791:6:791:Infinity":254,"s:793:4:793:Infinity":255,"f:799:10:799:21":30,"s:801:4:808:Infinity":256,"s:811:4:828:Infinity":257,"f:811:29:811:30":31,"s:812:6:821:Infinity":258,"s:822:6:827:Infinity":259,"s:831:4:848:Infinity":260,"f:831:27:831:28":32,"s:832:6:841:Infinity":261,"s:842:6:847:Infinity":262,"s:851:4:863:Infinity":263,"f:851:27:851:28":33,"s:852:6:856:Infinity":264,"s:857:6:862:Infinity":265,"f:869:10:869:33":34,"s:870:16:870:Infinity":266,"s:871:4:876:Infinity":267,"b:873:6:875:Infinity:undefined:undefined:undefined:undefined":84,"s:873:6:875:Infinity":268,"b:873:10:873:44:873:44:873:77":85,"s:874:8:874:Infinity":269,"s:877:4:877:Infinity":270,"f:883:10:883:26":35,"s:884:4:935:Infinity":271,"f:892:34:892:35":36,"s:892:44:898:8":272,"f:895:39:895:40":37,"s:895:49:895:75":273,"b:895:49:895:66:895:66:895:75":86,"f:899:34:899:35":38,"s:899:44:905:8":274,"b:902:30:902:42:902:42:902:Infinity":87,"f:906:38:906:39":39,"s:906:47:919:8":275,"f:910:38:910:39":40,"s:910:46:910:75":276,"f:920:34:920:35":41,"s:920:44:933:8":277,"b:934:17:934:37:934:37:934:Infinity":88,"f:943:10:943:Infinity":42,"s:948:42:948:Infinity":278,"s:951:22:951:Infinity":279,"f:951:41:951:42":43,"s:951:48:951:75":280,"s:953:4:985:Infinity":281,"s:954:25:954:Infinity":282,"b:954:25:954:55:954:55:954:Infinity":89,"b:955:6:955:Infinity:undefined:undefined:undefined:undefined":90,"s:955:6:955:Infinity":283,"s:955:35:955:Infinity":284,"s:958:22:958:Infinity":285,"b:958:22:958:49:958:49:958:Infinity":91,"s:960:6:984:Infinity":286,"s:962:29:967:Infinity":287,"b:968:8:968:Infinity:undefined:undefined:undefined:undefined":92,"s:968:8:968:Infinity":288,"s:968:27:968:Infinity":289,"s:971:8:983:Infinity":290,"s:972:10:982:Infinity":291,"s:987:4:987:Infinity":292,"f:993:10:993:21":44,"s:994:4:998:Infinity":293,"b:995:6:995:Infinity:996:6:996:Infinity:997:6:997:Infinity:998:6:998:Infinity":93,"f:1005:10:1005:Infinity":45,"b:1012:4:1014:Infinity:undefined:undefined:undefined:undefined":94,"s:1012:4:1014:Infinity":294,"b:1012:8:1012:35:1012:35:1012:63":95,"s:1013:6:1013:Infinity":295,"b:1018:4:1027:Infinity:1022:4:1027:Infinity":96,"s:1018:4:1027:Infinity":296,"s:1020:18:1020:Infinity":297,"s:1021:6:1021:Infinity":298,"b:1022:4:1027:Infinity:1025:11:1027:Infinity":97,"s:1022:4:1027:Infinity":299,"s:1024:6:1024:Infinity":300,"s:1026:6:1026:Infinity":301,"s:1030:23:1036:Infinity":302,"s:1038:4:1043:Infinity":303,"s:1039:21:1039:Infinity":304,"f:1039:38:1039:39":46,"s:1039:45:1039:69":305,"b:1040:6:1042:Infinity:undefined:undefined:undefined:undefined":98,"s:1040:6:1042:Infinity":306,"s:1041:8:1041:Infinity":307,"s:1045:4:1045:Infinity":308,"f:1051:10:1051:28":47,"s:1052:42:1052:Infinity":309,"b:1055:4:1057:Infinity:undefined:undefined:undefined:undefined":99,"s:1055:4:1057:Infinity":310,"b:1055:8:1055:26:1055:26:1055:56":100,"s:1056:6:1056:Infinity":311,"s:1061:21:1092:Infinity":312,"s:1094:4:1114:Infinity":313,"s:1095:6:1113:Infinity":314,"s:1116:4:1116:Infinity":315,"f:1122:2:1122:54":48,"s:1123:4:1123:Infinity":316,"f:1123:11:1123:17":49,"s:1123:17:1123:Infinity":317,"f:1129:2:1129:17":50,"s:1130:21:1134:Infinity":318,"s:1135:4:1135:Infinity":319}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/graph/ppr.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/graph/ppr.ts","statementMap":{"0":{"start":{"line":21,"column":53},"end":{"line":29,"column":null}},"1":{"start":{"line":45,"column":18},"end":{"line":45,"column":null}},"2":{"start":{"line":46,"column":2},"end":{"line":46,"column":null}},"3":{"start":{"line":46,"column":23},"end":{"line":46,"column":null}},"4":{"start":{"line":48,"column":21},"end":{"line":48,"column":null}},"5":{"start":{"line":49,"column":18},"end":{"line":49,"column":null}},"6":{"start":{"line":50,"column":21},"end":{"line":50,"column":null}},"7":{"start":{"line":52,"column":21},"end":{"line":58,"column":null}},"8":{"start":{"line":59,"column":2},"end":{"line":59,"column":null}},"9":{"start":{"line":59,"column":18},"end":{"line":59,"column":null}},"10":{"start":{"line":61,"column":2},"end":{"line":61,"column":null}},"11":{"start":{"line":74,"column":2},"end":{"line":159,"column":null}},"12":{"start":{"line":76,"column":24},"end":{"line":87,"column":null}},"13":{"start":{"line":89,"column":4},"end":{"line":95,"column":null}},"14":{"start":{"line":94,"column":6},"end":{"line":94,"column":null}},"15":{"start":{"line":97,"column":21},"end":{"line":97,"column":null}},"16":{"start":{"line":98,"column":21},"end":{"line":101,"column":null}},"17":{"start":{"line":102,"column":4},"end":{"line":111,"column":null}},"18":{"start":{"line":103,"column":17},"end":{"line":103,"column":null}},"19":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"20":{"start":{"line":104,"column":15},"end":{"line":104,"column":null}},"21":{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},"22":{"start":{"line":106,"column":6},"end":{"line":110,"column":null}},"23":{"start":{"line":114,"column":25},"end":{"line":123,"column":null}},"24":{"start":{"line":126,"column":45},"end":{"line":126,"column":null}},"25":{"start":{"line":127,"column":22},"end":{"line":127,"column":null}},"26":{"start":{"line":128,"column":4},"end":{"line":128,"column":null}},"27":{"start":{"line":128,"column":31},"end":{"line":128,"column":null}},"28":{"start":{"line":129,"column":4},"end":{"line":135,"column":null}},"29":{"start":{"line":130,"column":17},"end":{"line":130,"column":null}},"30":{"start":{"line":131,"column":6},"end":{"line":131,"column":null}},"31":{"start":{"line":131,"column":15},"end":{"line":131,"column":null}},"32":{"start":{"line":132,"column":22},"end":{"line":132,"column":null}},"33":{"start":{"line":133,"column":16},"end":{"line":133,"column":null}},"34":{"start":{"line":134,"column":6},"end":{"line":134,"column":null}},"35":{"start":{"line":138,"column":32},"end":{"line":138,"column":null}},"36":{"start":{"line":139,"column":19},"end":{"line":139,"column":null}},"37":{"start":{"line":140,"column":4},"end":{"line":153,"column":null}},"38":{"start":{"line":141,"column":16},"end":{"line":141,"column":null}},"39":{"start":{"line":142,"column":19},"end":{"line":142,"column":null}},"40":{"start":{"line":143,"column":20},"end":{"line":143,"column":null}},"41":{"start":{"line":144,"column":19},"end":{"line":144,"column":null}},"42":{"start":{"line":145,"column":6},"end":{"line":152,"column":null}},"43":{"start":{"line":155,"column":4},"end":{"line":155,"column":null}},"44":{"start":{"line":155,"column":33},"end":{"line":155,"column":50}},"45":{"start":{"line":158,"column":4},"end":{"line":158,"column":null}},"46":{"start":{"line":173,"column":22},"end":{"line":173,"column":null}},"47":{"start":{"line":175,"column":21},"end":{"line":189,"column":null}},"48":{"start":{"line":191,"column":16},"end":{"line":191,"column":null}},"49":{"start":{"line":192,"column":19},"end":{"line":195,"column":null}},"50":{"start":{"line":196,"column":19},"end":{"line":196,"column":null}},"51":{"start":{"line":198,"column":2},"end":{"line":226,"column":null}},"52":{"start":{"line":199,"column":19},"end":{"line":199,"column":null}},"53":{"start":{"line":200,"column":17},"end":{"line":200,"column":null}},"54":{"start":{"line":201,"column":4},"end":{"line":201,"column":null}},"55":{"start":{"line":201,"column":26},"end":{"line":201,"column":null}},"56":{"start":{"line":203,"column":20},"end":{"line":203,"column":null}},"57":{"start":{"line":204,"column":19},"end":{"line":204,"column":null}},"58":{"start":{"line":206,"column":4},"end":{"line":206,"column":null}},"59":{"start":{"line":207,"column":4},"end":{"line":207,"column":null}},"60":{"start":{"line":209,"column":4},"end":{"line":215,"column":null}},"61":{"start":{"line":210,"column":6},"end":{"line":214,"column":null}},"62":{"start":{"line":216,"column":4},"end":{"line":222,"column":null}},"63":{"start":{"line":217,"column":6},"end":{"line":221,"column":null}},"64":{"start":{"line":224,"column":4},"end":{"line":224,"column":null}},"65":{"start":{"line":224,"column":31},"end":{"line":224,"column":null}},"66":{"start":{"line":225,"column":4},"end":{"line":225,"column":null}},"67":{"start":{"line":228,"column":2},"end":{"line":232,"column":null}},"68":{"start":{"line":229,"column":4},"end":{"line":231,"column":null}},"69":{"start":{"line":230,"column":6},"end":{"line":230,"column":null}},"70":{"start":{"line":234,"column":19},"end":{"line":234,"column":null}},"71":{"start":{"line":235,"column":20},"end":{"line":235,"column":null}},"72":{"start":{"line":236,"column":21},"end":{"line":236,"column":null}},"73":{"start":{"line":237,"column":26},"end":{"line":237,"column":null}},"74":{"start":{"line":238,"column":2},"end":{"line":240,"column":null}},"75":{"start":{"line":239,"column":4},"end":{"line":239,"column":null}},"76":{"start":{"line":242,"column":13},"end":{"line":242,"column":null}},"77":{"start":{"line":243,"column":18},"end":{"line":243,"column":null}},"78":{"start":{"line":244,"column":2},"end":{"line":244,"column":null}},"79":{"start":{"line":244,"column":33},"end":{"line":244,"column":null}},"80":{"start":{"line":246,"column":19},"end":{"line":246,"column":null}},"81":{"start":{"line":247,"column":2},"end":{"line":252,"column":null}},"82":{"start":{"line":248,"column":4},"end":{"line":251,"column":null}},"83":{"start":{"line":249,"column":6},"end":{"line":249,"column":null}},"84":{"start":{"line":249,"column":34},"end":{"line":249,"column":null}},"85":{"start":{"line":250,"column":6},"end":{"line":250,"column":null}},"86":{"start":{"line":254,"column":2},"end":{"line":269,"column":null}},"87":{"start":{"line":254,"column":15},"end":{"line":254,"column":18}},"88":{"start":{"line":255,"column":17},"end":{"line":255,"column":null}},"89":{"start":{"line":256,"column":4},"end":{"line":267,"column":null}},"90":{"start":{"line":257,"column":22},"end":{"line":257,"column":null}},"91":{"start":{"line":258,"column":23},"end":{"line":258,"column":null}},"92":{"start":{"line":259,"column":6},"end":{"line":264,"column":null}},"93":{"start":{"line":260,"column":25},"end":{"line":260,"column":null}},"94":{"start":{"line":261,"column":29},"end":{"line":261,"column":null}},"95":{"start":{"line":262,"column":27},"end":{"line":262,"column":null}},"96":{"start":{"line":262,"column":60},"end":{"line":262,"column":77}},"97":{"start":{"line":263,"column":8},"end":{"line":263,"column":null}},"98":{"start":{"line":263,"column":28},"end":{"line":263,"column":null}},"99":{"start":{"line":265,"column":16},"end":{"line":265,"column":null}},"100":{"start":{"line":266,"column":6},"end":{"line":266,"column":null}},"101":{"start":{"line":268,"column":4},"end":{"line":268,"column":null}},"102":{"start":{"line":271,"column":2},"end":{"line":288,"column":null}},"103":{"start":{"line":273,"column":19},"end":{"line":277,"column":null}},"104":{"start":{"line":278,"column":6},"end":{"line":285,"column":null}},"105":{"start":{"line":287,"column":20},"end":{"line":287,"column":37}}},"fnMap":{"0":{"name":"runPPR","decl":{"start":{"line":41,"column":22},"end":{"line":41,"column":null}},"loc":{"start":{"line":44,"column":24},"end":{"line":62,"column":null}},"line":44},"1":{"name":"tryMagePPR","decl":{"start":{"line":67,"column":15},"end":{"line":67,"column":null}},"loc":{"start":{"line":73,"column":31},"end":{"line":160,"column":null}},"line":73},"2":{"name":"(anonymous_2)","decl":{"start":{"line":155,"column":23},"end":{"line":155,"column":24}},"loc":{"start":{"line":155,"column":33},"end":{"line":155,"column":50}},"line":155},"3":{"name":"runJsPPR","decl":{"start":{"line":165,"column":15},"end":{"line":165,"column":null}},"loc":{"start":{"line":172,"column":24},"end":{"line":289,"column":null}},"line":172},"4":{"name":"(anonymous_4)","decl":{"start":{"line":262,"column":47},"end":{"line":262,"column":48}},"loc":{"start":{"line":262,"column":60},"end":{"line":262,"column":77}},"line":262},"5":{"name":"(anonymous_5)","decl":{"start":{"line":272,"column":9},"end":{"line":272,"column":10}},"loc":{"start":{"line":272,"column":21},"end":{"line":286,"column":5}},"line":272},"6":{"name":"(anonymous_6)","decl":{"start":{"line":287,"column":10},"end":{"line":287,"column":11}},"loc":{"start":{"line":287,"column":20},"end":{"line":287,"column":37}},"line":287}},"branchMap":{"0":{"loc":{"start":{"line":45,"column":31},"end":{"line":45,"column":51}},"type":"binary-expr","locations":[{"start":{"line":45,"column":31},"end":{"line":45,"column":47}},{"start":{"line":45,"column":47},"end":{"line":45,"column":51}}],"line":45},"1":{"loc":{"start":{"line":46,"column":2},"end":{"line":46,"column":null}},"type":"if","locations":[{"start":{"line":46,"column":2},"end":{"line":46,"column":null}},{"start":{},"end":{}}],"line":46},"2":{"loc":{"start":{"line":48,"column":42},"end":{"line":48,"column":65}},"type":"binary-expr","locations":[{"start":{"line":48,"column":42},"end":{"line":48,"column":61}},{"start":{"line":48,"column":61},"end":{"line":48,"column":65}}],"line":48},"3":{"loc":{"start":{"line":49,"column":18},"end":{"line":49,"column":null}},"type":"cond-expr","locations":[{"start":{"line":49,"column":50},"end":{"line":49,"column":73}},{"start":{"line":49,"column":73},"end":{"line":49,"column":null}}],"line":49},"4":{"loc":{"start":{"line":50,"column":42},"end":{"line":50,"column":65}},"type":"binary-expr","locations":[{"start":{"line":50,"column":42},"end":{"line":50,"column":61}},{"start":{"line":50,"column":61},"end":{"line":50,"column":65}}],"line":50},"5":{"loc":{"start":{"line":59,"column":2},"end":{"line":59,"column":null}},"type":"if","locations":[{"start":{"line":59,"column":2},"end":{"line":59,"column":null}},{"start":{},"end":{}}],"line":59},"6":{"loc":{"start":{"line":89,"column":4},"end":{"line":95,"column":null}},"type":"if","locations":[{"start":{"line":89,"column":4},"end":{"line":95,"column":null}},{"start":{},"end":{}}],"line":89},"7":{"loc":{"start":{"line":90,"column":6},"end":{"line":92,"column":null}},"type":"binary-expr","locations":[{"start":{"line":90,"column":6},"end":{"line":90,"column":null}},{"start":{"line":91,"column":6},"end":{"line":91,"column":null}},{"start":{"line":92,"column":6},"end":{"line":92,"column":null}}],"line":90},"8":{"loc":{"start":{"line":103,"column":24},"end":{"line":103,"column":40}},"type":"binary-expr","locations":[{"start":{"line":103,"column":24},"end":{"line":103,"column":38}},{"start":{"line":103,"column":38},"end":{"line":103,"column":40}}],"line":103},"9":{"loc":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"type":"if","locations":[{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},{"start":{},"end":{}}],"line":104},"10":{"loc":{"start":{"line":105,"column":30},"end":{"line":105,"column":43}},"type":"binary-expr","locations":[{"start":{"line":105,"column":30},"end":{"line":105,"column":42}},{"start":{"line":105,"column":42},"end":{"line":105,"column":43}}],"line":105},"11":{"loc":{"start":{"line":107,"column":21},"end":{"line":107,"column":42}},"type":"binary-expr","locations":[{"start":{"line":107,"column":21},"end":{"line":107,"column":33}},{"start":{"line":107,"column":33},"end":{"line":107,"column":42}}],"line":107},"12":{"loc":{"start":{"line":108,"column":25},"end":{"line":108,"column":43}},"type":"binary-expr","locations":[{"start":{"line":108,"column":25},"end":{"line":108,"column":41}},{"start":{"line":108,"column":41},"end":{"line":108,"column":43}}],"line":108},"13":{"loc":{"start":{"line":109,"column":21},"end":{"line":109,"column":35}},"type":"binary-expr","locations":[{"start":{"line":109,"column":21},"end":{"line":109,"column":33}},{"start":{"line":109,"column":33},"end":{"line":109,"column":35}}],"line":109},"14":{"loc":{"start":{"line":129,"column":22},"end":{"line":129,"column":47}},"type":"binary-expr","locations":[{"start":{"line":129,"column":22},"end":{"line":129,"column":43}},{"start":{"line":129,"column":43},"end":{"line":129,"column":47}}],"line":129},"15":{"loc":{"start":{"line":130,"column":24},"end":{"line":130,"column":40}},"type":"binary-expr","locations":[{"start":{"line":130,"column":24},"end":{"line":130,"column":38}},{"start":{"line":130,"column":38},"end":{"line":130,"column":40}}],"line":130},"16":{"loc":{"start":{"line":131,"column":6},"end":{"line":131,"column":null}},"type":"if","locations":[{"start":{"line":131,"column":6},"end":{"line":131,"column":null}},{"start":{},"end":{}}],"line":131},"17":{"loc":{"start":{"line":132,"column":22},"end":{"line":132,"column":null}},"type":"binary-expr","locations":[{"start":{"line":132,"column":22},"end":{"line":132,"column":43}},{"start":{"line":132,"column":43},"end":{"line":132,"column":null}}],"line":132},"18":{"loc":{"start":{"line":133,"column":23},"end":{"line":133,"column":36}},"type":"binary-expr","locations":[{"start":{"line":133,"column":23},"end":{"line":133,"column":35}},{"start":{"line":133,"column":35},"end":{"line":133,"column":36}}],"line":133},"19":{"loc":{"start":{"line":134,"column":42},"end":{"line":134,"column":60}},"type":"binary-expr","locations":[{"start":{"line":134,"column":42},"end":{"line":134,"column":57}},{"start":{"line":134,"column":57},"end":{"line":134,"column":60}}],"line":134},"20":{"loc":{"start":{"line":141,"column":16},"end":{"line":141,"column":null}},"type":"binary-expr","locations":[{"start":{"line":141,"column":16},"end":{"line":141,"column":40}},{"start":{"line":141,"column":40},"end":{"line":141,"column":null}}],"line":141},"21":{"loc":{"start":{"line":142,"column":19},"end":{"line":142,"column":null}},"type":"binary-expr","locations":[{"start":{"line":142,"column":19},"end":{"line":142,"column":44}},{"start":{"line":142,"column":44},"end":{"line":142,"column":null}}],"line":142},"22":{"loc":{"start":{"line":148,"column":14},"end":{"line":148,"column":null}},"type":"binary-expr","locations":[{"start":{"line":148,"column":14},"end":{"line":148,"column":28}},{"start":{"line":148,"column":28},"end":{"line":148,"column":null}}],"line":148},"23":{"loc":{"start":{"line":149,"column":18},"end":{"line":149,"column":null}},"type":"binary-expr","locations":[{"start":{"line":149,"column":18},"end":{"line":149,"column":36}},{"start":{"line":149,"column":36},"end":{"line":149,"column":null}}],"line":149},"24":{"loc":{"start":{"line":150,"column":14},"end":{"line":150,"column":null}},"type":"binary-expr","locations":[{"start":{"line":150,"column":14},"end":{"line":150,"column":28}},{"start":{"line":150,"column":28},"end":{"line":150,"column":null}}],"line":150},"25":{"loc":{"start":{"line":173,"column":53},"end":{"line":173,"column":77}},"type":"binary-expr","locations":[{"start":{"line":173,"column":53},"end":{"line":173,"column":73}},{"start":{"line":173,"column":73},"end":{"line":173,"column":77}}],"line":173},"26":{"loc":{"start":{"line":198,"column":20},"end":{"line":198,"column":43}},"type":"binary-expr","locations":[{"start":{"line":198,"column":20},"end":{"line":198,"column":39}},{"start":{"line":198,"column":39},"end":{"line":198,"column":43}}],"line":198},"27":{"loc":{"start":{"line":199,"column":26},"end":{"line":199,"column":42}},"type":"binary-expr","locations":[{"start":{"line":199,"column":26},"end":{"line":199,"column":40}},{"start":{"line":199,"column":40},"end":{"line":199,"column":42}}],"line":199},"28":{"loc":{"start":{"line":200,"column":24},"end":{"line":200,"column":38}},"type":"binary-expr","locations":[{"start":{"line":200,"column":24},"end":{"line":200,"column":36}},{"start":{"line":200,"column":36},"end":{"line":200,"column":38}}],"line":200},"29":{"loc":{"start":{"line":201,"column":4},"end":{"line":201,"column":null}},"type":"if","locations":[{"start":{"line":201,"column":4},"end":{"line":201,"column":null}},{"start":{},"end":{}}],"line":201},"30":{"loc":{"start":{"line":201,"column":8},"end":{"line":201,"column":26}},"type":"binary-expr","locations":[{"start":{"line":201,"column":8},"end":{"line":201,"column":19}},{"start":{"line":201,"column":19},"end":{"line":201,"column":26}}],"line":201},"31":{"loc":{"start":{"line":203,"column":27},"end":{"line":203,"column":44}},"type":"binary-expr","locations":[{"start":{"line":203,"column":27},"end":{"line":203,"column":42}},{"start":{"line":203,"column":42},"end":{"line":203,"column":44}}],"line":203},"32":{"loc":{"start":{"line":204,"column":26},"end":{"line":204,"column":53}},"type":"binary-expr","locations":[{"start":{"line":204,"column":26},"end":{"line":204,"column":50}},{"start":{"line":204,"column":50},"end":{"line":204,"column":53}}],"line":204},"33":{"loc":{"start":{"line":209,"column":4},"end":{"line":215,"column":null}},"type":"if","locations":[{"start":{"line":209,"column":4},"end":{"line":215,"column":null}},{"start":{},"end":{}}],"line":209},"34":{"loc":{"start":{"line":211,"column":21},"end":{"line":211,"column":46}},"type":"binary-expr","locations":[{"start":{"line":211,"column":21},"end":{"line":211,"column":37}},{"start":{"line":211,"column":37},"end":{"line":211,"column":46}}],"line":211},"35":{"loc":{"start":{"line":212,"column":25},"end":{"line":212,"column":43}},"type":"binary-expr","locations":[{"start":{"line":212,"column":25},"end":{"line":212,"column":41}},{"start":{"line":212,"column":41},"end":{"line":212,"column":43}}],"line":212},"36":{"loc":{"start":{"line":213,"column":21},"end":{"line":213,"column":43}},"type":"binary-expr","locations":[{"start":{"line":213,"column":21},"end":{"line":213,"column":37}},{"start":{"line":213,"column":37},"end":{"line":213,"column":43}}],"line":213},"37":{"loc":{"start":{"line":216,"column":4},"end":{"line":222,"column":null}},"type":"if","locations":[{"start":{"line":216,"column":4},"end":{"line":222,"column":null}},{"start":{},"end":{}}],"line":216},"38":{"loc":{"start":{"line":218,"column":21},"end":{"line":218,"column":44}},"type":"binary-expr","locations":[{"start":{"line":218,"column":21},"end":{"line":218,"column":35}},{"start":{"line":218,"column":35},"end":{"line":218,"column":44}}],"line":218},"39":{"loc":{"start":{"line":219,"column":25},"end":{"line":219,"column":41}},"type":"binary-expr","locations":[{"start":{"line":219,"column":25},"end":{"line":219,"column":39}},{"start":{"line":219,"column":39},"end":{"line":219,"column":41}}],"line":219},"40":{"loc":{"start":{"line":220,"column":21},"end":{"line":220,"column":39}},"type":"binary-expr","locations":[{"start":{"line":220,"column":21},"end":{"line":220,"column":35}},{"start":{"line":220,"column":35},"end":{"line":220,"column":39}}],"line":220},"41":{"loc":{"start":{"line":224,"column":4},"end":{"line":224,"column":null}},"type":"if","locations":[{"start":{"line":224,"column":4},"end":{"line":224,"column":null}},{"start":{},"end":{}}],"line":224},"42":{"loc":{"start":{"line":229,"column":4},"end":{"line":231,"column":null}},"type":"if","locations":[{"start":{"line":229,"column":4},"end":{"line":231,"column":null}},{"start":{},"end":{}}],"line":229},"43":{"loc":{"start":{"line":235,"column":20},"end":{"line":235,"column":null}},"type":"binary-expr","locations":[{"start":{"line":235,"column":20},"end":{"line":235,"column":39}},{"start":{"line":235,"column":39},"end":{"line":235,"column":null}}],"line":235},"44":{"loc":{"start":{"line":239,"column":32},"end":{"line":239,"column":73}},"type":"cond-expr","locations":[{"start":{"line":239,"column":59},"end":{"line":239,"column":72}},{"start":{"line":239,"column":72},"end":{"line":239,"column":73}}],"line":239},"45":{"loc":{"start":{"line":249,"column":6},"end":{"line":249,"column":null}},"type":"if","locations":[{"start":{"line":249,"column":6},"end":{"line":249,"column":null}},{"start":{},"end":{}}],"line":249},"46":{"loc":{"start":{"line":257,"column":22},"end":{"line":257,"column":null}},"type":"binary-expr","locations":[{"start":{"line":257,"column":22},"end":{"line":257,"column":46}},{"start":{"line":257,"column":46},"end":{"line":257,"column":null}}],"line":257},"47":{"loc":{"start":{"line":260,"column":25},"end":{"line":260,"column":null}},"type":"binary-expr","locations":[{"start":{"line":260,"column":25},"end":{"line":260,"column":48}},{"start":{"line":260,"column":48},"end":{"line":260,"column":null}}],"line":260},"48":{"loc":{"start":{"line":261,"column":29},"end":{"line":261,"column":null}},"type":"binary-expr","locations":[{"start":{"line":261,"column":29},"end":{"line":261,"column":56}},{"start":{"line":261,"column":56},"end":{"line":261,"column":null}}],"line":261},"49":{"loc":{"start":{"line":263,"column":8},"end":{"line":263,"column":null}},"type":"if","locations":[{"start":{"line":263,"column":8},"end":{"line":263,"column":null}},{"start":{},"end":{}}],"line":263},"50":{"loc":{"start":{"line":265,"column":16},"end":{"line":265,"column":null}},"type":"binary-expr","locations":[{"start":{"line":265,"column":16},"end":{"line":265,"column":47}},{"start":{"line":265,"column":47},"end":{"line":265,"column":null}}],"line":265},"51":{"loc":{"start":{"line":273,"column":19},"end":{"line":277,"column":null}},"type":"binary-expr","locations":[{"start":{"line":273,"column":19},"end":{"line":273,"column":43}},{"start":{"line":273,"column":43},"end":{"line":277,"column":null}}],"line":273},"52":{"loc":{"start":{"line":280,"column":23},"end":{"line":280,"column":46}},"type":"binary-expr","locations":[{"start":{"line":280,"column":23},"end":{"line":280,"column":43}},{"start":{"line":280,"column":43},"end":{"line":280,"column":46}}],"line":280}},"s":{"0":2,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[0,0],"41":[0,0],"42":[0,0],"43":[0,0],"44":[0,0],"45":[0,0],"46":[0,0],"47":[0,0],"48":[0,0],"49":[0,0],"50":[0,0],"51":[0,0],"52":[0,0]},"meta":{"lastBranch":53,"lastFunction":7,"lastStatement":106,"seen":{"s:21:53:29:Infinity":0,"f:41:22:41:Infinity":0,"s:45:18:45:Infinity":1,"b:45:31:45:47:45:47:45:51":0,"b:46:2:46:Infinity:undefined:undefined:undefined:undefined":1,"s:46:2:46:Infinity":2,"s:46:23:46:Infinity":3,"s:48:21:48:Infinity":4,"b:48:42:48:61:48:61:48:65":2,"s:49:18:49:Infinity":5,"b:49:50:49:73:49:73:49:Infinity":3,"s:50:21:50:Infinity":6,"b:50:42:50:61:50:61:50:65":4,"s:52:21:58:Infinity":7,"b:59:2:59:Infinity:undefined:undefined:undefined:undefined":5,"s:59:2:59:Infinity":8,"s:59:18:59:Infinity":9,"s:61:2:61:Infinity":10,"f:67:15:67:Infinity":1,"s:74:2:159:Infinity":11,"s:76:24:87:Infinity":12,"b:89:4:95:Infinity:undefined:undefined:undefined:undefined":6,"s:89:4:95:Infinity":13,"b:90:6:90:Infinity:91:6:91:Infinity:92:6:92:Infinity":7,"s:94:6:94:Infinity":14,"s:97:21:97:Infinity":15,"s:98:21:101:Infinity":16,"s:102:4:111:Infinity":17,"s:103:17:103:Infinity":18,"b:103:24:103:38:103:38:103:40":8,"b:104:6:104:Infinity:undefined:undefined:undefined:undefined":9,"s:104:6:104:Infinity":19,"s:104:15:104:Infinity":20,"s:105:6:105:Infinity":21,"b:105:30:105:42:105:42:105:43":10,"s:106:6:110:Infinity":22,"b:107:21:107:33:107:33:107:42":11,"b:108:25:108:41:108:41:108:43":12,"b:109:21:109:33:109:33:109:35":13,"s:114:25:123:Infinity":23,"s:126:45:126:Infinity":24,"s:127:22:127:Infinity":25,"s:128:4:128:Infinity":26,"s:128:31:128:Infinity":27,"s:129:4:135:Infinity":28,"b:129:22:129:43:129:43:129:47":14,"s:130:17:130:Infinity":29,"b:130:24:130:38:130:38:130:40":15,"b:131:6:131:Infinity:undefined:undefined:undefined:undefined":16,"s:131:6:131:Infinity":30,"s:131:15:131:Infinity":31,"s:132:22:132:Infinity":32,"b:132:22:132:43:132:43:132:Infinity":17,"s:133:16:133:Infinity":33,"b:133:23:133:35:133:35:133:36":18,"s:134:6:134:Infinity":34,"b:134:42:134:57:134:57:134:60":19,"s:138:32:138:Infinity":35,"s:139:19:139:Infinity":36,"s:140:4:153:Infinity":37,"s:141:16:141:Infinity":38,"b:141:16:141:40:141:40:141:Infinity":20,"s:142:19:142:Infinity":39,"b:142:19:142:44:142:44:142:Infinity":21,"s:143:20:143:Infinity":40,"s:144:19:144:Infinity":41,"s:145:6:152:Infinity":42,"b:148:14:148:28:148:28:148:Infinity":22,"b:149:18:149:36:149:36:149:Infinity":23,"b:150:14:150:28:150:28:150:Infinity":24,"s:155:4:155:Infinity":43,"f:155:23:155:24":2,"s:155:33:155:50":44,"s:158:4:158:Infinity":45,"f:165:15:165:Infinity":3,"s:173:22:173:Infinity":46,"b:173:53:173:73:173:73:173:77":25,"s:175:21:189:Infinity":47,"s:191:16:191:Infinity":48,"s:192:19:195:Infinity":49,"s:196:19:196:Infinity":50,"s:198:2:226:Infinity":51,"b:198:20:198:39:198:39:198:43":26,"s:199:19:199:Infinity":52,"b:199:26:199:40:199:40:199:42":27,"s:200:17:200:Infinity":53,"b:200:24:200:36:200:36:200:38":28,"b:201:4:201:Infinity:undefined:undefined:undefined:undefined":29,"s:201:4:201:Infinity":54,"b:201:8:201:19:201:19:201:26":30,"s:201:26:201:Infinity":55,"s:203:20:203:Infinity":56,"b:203:27:203:42:203:42:203:44":31,"s:204:19:204:Infinity":57,"b:204:26:204:50:204:50:204:53":32,"s:206:4:206:Infinity":58,"s:207:4:207:Infinity":59,"b:209:4:215:Infinity:undefined:undefined:undefined:undefined":33,"s:209:4:215:Infinity":60,"s:210:6:214:Infinity":61,"b:211:21:211:37:211:37:211:46":34,"b:212:25:212:41:212:41:212:43":35,"b:213:21:213:37:213:37:213:43":36,"b:216:4:222:Infinity:undefined:undefined:undefined:undefined":37,"s:216:4:222:Infinity":62,"s:217:6:221:Infinity":63,"b:218:21:218:35:218:35:218:44":38,"b:219:25:219:39:219:39:219:41":39,"b:220:21:220:35:220:35:220:39":40,"b:224:4:224:Infinity:undefined:undefined:undefined:undefined":41,"s:224:4:224:Infinity":64,"s:224:31:224:Infinity":65,"s:225:4:225:Infinity":66,"s:228:2:232:Infinity":67,"b:229:4:231:Infinity:undefined:undefined:undefined:undefined":42,"s:229:4:231:Infinity":68,"s:230:6:230:Infinity":69,"s:234:19:234:Infinity":70,"s:235:20:235:Infinity":71,"b:235:20:235:39:235:39:235:Infinity":43,"s:236:21:236:Infinity":72,"s:237:26:237:Infinity":73,"s:238:2:240:Infinity":74,"s:239:4:239:Infinity":75,"b:239:59:239:72:239:72:239:73":44,"s:242:13:242:Infinity":76,"s:243:18:243:Infinity":77,"s:244:2:244:Infinity":78,"s:244:33:244:Infinity":79,"s:246:19:246:Infinity":80,"s:247:2:252:Infinity":81,"s:248:4:251:Infinity":82,"b:249:6:249:Infinity:undefined:undefined:undefined:undefined":45,"s:249:6:249:Infinity":83,"s:249:34:249:Infinity":84,"s:250:6:250:Infinity":85,"s:254:2:269:Infinity":86,"s:254:15:254:18":87,"s:255:17:255:Infinity":88,"s:256:4:267:Infinity":89,"s:257:22:257:Infinity":90,"b:257:22:257:46:257:46:257:Infinity":46,"s:258:23:258:Infinity":91,"s:259:6:264:Infinity":92,"s:260:25:260:Infinity":93,"b:260:25:260:48:260:48:260:Infinity":47,"s:261:29:261:Infinity":94,"b:261:29:261:56:261:56:261:Infinity":48,"s:262:27:262:Infinity":95,"f:262:47:262:48":4,"s:262:60:262:77":96,"b:263:8:263:Infinity:undefined:undefined:undefined:undefined":49,"s:263:8:263:Infinity":97,"s:263:28:263:Infinity":98,"s:265:16:265:Infinity":99,"b:265:16:265:47:265:47:265:Infinity":50,"s:266:6:266:Infinity":100,"s:268:4:268:Infinity":101,"s:271:2:288:Infinity":102,"f:272:9:272:10":5,"s:273:19:277:Infinity":103,"b:273:19:273:43:273:43:277:Infinity":51,"s:278:6:285:Infinity":104,"b:280:23:280:43:280:43:280:46":52,"f:287:10:287:11":6,"s:287:20:287:37":105}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/graph/watcher.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/graph/watcher.ts","statementMap":{"0":{"start":{"line":22,"column":20},"end":{"line":22,"column":null}},"1":{"start":{"line":24,"column":23},"end":{"line":24,"column":null}},"2":{"start":{"line":25,"column":37},"end":{"line":25,"column":null}},"3":{"start":{"line":28,"column":12},"end":{"line":28,"column":null}},"4":{"start":{"line":29,"column":12},"end":{"line":29,"column":null}},"5":{"start":{"line":33,"column":4},"end":{"line":33,"column":null}},"6":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"7":{"start":{"line":41,"column":4},"end":{"line":43,"column":null}},"8":{"start":{"line":42,"column":6},"end":{"line":42,"column":null}},"9":{"start":{"line":45,"column":20},"end":{"line":51,"column":null}},"10":{"start":{"line":53,"column":4},"end":{"line":61,"column":null}},"11":{"start":{"line":63,"column":4},"end":{"line":66,"column":null}},"12":{"start":{"line":64,"column":39},"end":{"line":64,"column":59}},"13":{"start":{"line":65,"column":42},"end":{"line":65,"column":62}},"14":{"start":{"line":66,"column":42},"end":{"line":66,"column":62}},"15":{"start":{"line":70,"column":4},"end":{"line":73,"column":null}},"16":{"start":{"line":71,"column":6},"end":{"line":71,"column":null}},"17":{"start":{"line":72,"column":6},"end":{"line":72,"column":null}},"18":{"start":{"line":75,"column":4},"end":{"line":78,"column":null}},"19":{"start":{"line":76,"column":6},"end":{"line":76,"column":null}},"20":{"start":{"line":77,"column":6},"end":{"line":77,"column":null}},"21":{"start":{"line":80,"column":4},"end":{"line":80,"column":null}},"22":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"23":{"start":{"line":82,"column":4},"end":{"line":82,"column":null}},"24":{"start":{"line":86,"column":4},"end":{"line":86,"column":null}},"25":{"start":{"line":87,"column":4},"end":{"line":87,"column":null}},"26":{"start":{"line":89,"column":4},"end":{"line":91,"column":null}},"27":{"start":{"line":90,"column":6},"end":{"line":90,"column":null}},"28":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"29":{"start":{"line":94,"column":4},"end":{"line":97,"column":null}},"30":{"start":{"line":95,"column":6},"end":{"line":95,"column":null}},"31":{"start":{"line":96,"column":6},"end":{"line":96,"column":null}},"32":{"start":{"line":101,"column":4},"end":{"line":106,"column":null}},"33":{"start":{"line":102,"column":6},"end":{"line":104,"column":null}},"34":{"start":{"line":103,"column":8},"end":{"line":103,"column":null}},"35":{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},"36":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"37":{"start":{"line":109,"column":4},"end":{"line":109,"column":null}},"38":{"start":{"line":111,"column":25},"end":{"line":111,"column":null}},"39":{"start":{"line":112,"column":4},"end":{"line":112,"column":null}},"40":{"start":{"line":114,"column":4},"end":{"line":132,"column":null}},"41":{"start":{"line":115,"column":6},"end":{"line":120,"column":null}},"42":{"start":{"line":122,"column":6},"end":{"line":122,"column":null}},"43":{"start":{"line":123,"column":6},"end":{"line":131,"column":null}},"44":{"start":{"line":124,"column":8},"end":{"line":124,"column":null}},"45":{"start":{"line":125,"column":8},"end":{"line":128,"column":null}},"46":{"start":{"line":126,"column":10},"end":{"line":126,"column":null}},"47":{"start":{"line":127,"column":10},"end":{"line":127,"column":null}},"48":{"start":{"line":130,"column":8},"end":{"line":130,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":27,"column":2},"end":{"line":27,"column":null}},"loc":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"line":30},"1":{"name":"(anonymous_1)","decl":{"start":{"line":32,"column":6},"end":{"line":32,"column":31}},"loc":{"start":{"line":32,"column":31},"end":{"line":34,"column":null}},"line":32},"2":{"name":"(anonymous_2)","decl":{"start":{"line":36,"column":6},"end":{"line":36,"column":28}},"loc":{"start":{"line":36,"column":28},"end":{"line":38,"column":null}},"line":36},"3":{"name":"(anonymous_3)","decl":{"start":{"line":40,"column":2},"end":{"line":40,"column":16}},"loc":{"start":{"line":40,"column":16},"end":{"line":67,"column":null}},"line":40},"4":{"name":"(anonymous_4)","decl":{"start":{"line":64,"column":17},"end":{"line":64,"column":18}},"loc":{"start":{"line":64,"column":39},"end":{"line":64,"column":59}},"line":64},"5":{"name":"(anonymous_5)","decl":{"start":{"line":65,"column":20},"end":{"line":65,"column":21}},"loc":{"start":{"line":65,"column":42},"end":{"line":65,"column":62}},"line":65},"6":{"name":"(anonymous_6)","decl":{"start":{"line":66,"column":20},"end":{"line":66,"column":21}},"loc":{"start":{"line":66,"column":42},"end":{"line":66,"column":62}},"line":66},"7":{"name":"(anonymous_7)","decl":{"start":{"line":69,"column":8},"end":{"line":69,"column":30}},"loc":{"start":{"line":69,"column":30},"end":{"line":83,"column":null}},"line":69},"8":{"name":"(anonymous_8)","decl":{"start":{"line":85,"column":10},"end":{"line":85,"column":16}},"loc":{"start":{"line":85,"column":40},"end":{"line":98,"column":null}},"line":85},"9":{"name":"(anonymous_9)","decl":{"start":{"line":94,"column":28},"end":{"line":94,"column":34}},"loc":{"start":{"line":94,"column":34},"end":{"line":97,"column":7}},"line":94},"10":{"name":"(anonymous_10)","decl":{"start":{"line":100,"column":16},"end":{"line":100,"column":39}},"loc":{"start":{"line":100,"column":39},"end":{"line":133,"column":null}},"line":100},"11":{"name":"(anonymous_11)","decl":{"start":{"line":125,"column":32},"end":{"line":125,"column":38}},"loc":{"start":{"line":125,"column":38},"end":{"line":128,"column":11}},"line":125}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":4},"end":{"line":43,"column":null}},"type":"if","locations":[{"start":{"line":41,"column":4},"end":{"line":43,"column":null}},{"start":{},"end":{}}],"line":41},"1":{"loc":{"start":{"line":50,"column":10},"end":{"line":50,"column":null}},"type":"binary-expr","locations":[{"start":{"line":50,"column":10},"end":{"line":50,"column":38}},{"start":{"line":50,"column":38},"end":{"line":50,"column":null}}],"line":50},"2":{"loc":{"start":{"line":70,"column":4},"end":{"line":73,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":4},"end":{"line":73,"column":null}},{"start":{},"end":{}}],"line":70},"3":{"loc":{"start":{"line":75,"column":4},"end":{"line":78,"column":null}},"type":"if","locations":[{"start":{"line":75,"column":4},"end":{"line":78,"column":null}},{"start":{},"end":{}}],"line":75},"4":{"loc":{"start":{"line":89,"column":4},"end":{"line":91,"column":null}},"type":"if","locations":[{"start":{"line":89,"column":4},"end":{"line":91,"column":null}},{"start":{},"end":{}}],"line":89},"5":{"loc":{"start":{"line":97,"column":7},"end":{"line":97,"column":34}},"type":"binary-expr","locations":[{"start":{"line":97,"column":7},"end":{"line":97,"column":31}},{"start":{"line":97,"column":31},"end":{"line":97,"column":34}}],"line":97},"6":{"loc":{"start":{"line":101,"column":4},"end":{"line":106,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":4},"end":{"line":106,"column":null}},{"start":{},"end":{}}],"line":101},"7":{"loc":{"start":{"line":101,"column":8},"end":{"line":101,"column":52}},"type":"binary-expr","locations":[{"start":{"line":101,"column":8},"end":{"line":101,"column":27}},{"start":{"line":101,"column":27},"end":{"line":101,"column":52}}],"line":101},"8":{"loc":{"start":{"line":102,"column":6},"end":{"line":104,"column":null}},"type":"if","locations":[{"start":{"line":102,"column":6},"end":{"line":104,"column":null}},{"start":{},"end":{}}],"line":102},"9":{"loc":{"start":{"line":102,"column":10},"end":{"line":102,"column":55}},"type":"binary-expr","locations":[{"start":{"line":102,"column":10},"end":{"line":102,"column":30}},{"start":{"line":102,"column":30},"end":{"line":102,"column":55}}],"line":102},"10":{"loc":{"start":{"line":123,"column":6},"end":{"line":131,"column":null}},"type":"if","locations":[{"start":{"line":123,"column":6},"end":{"line":131,"column":null}},{"start":{"line":129,"column":13},"end":{"line":131,"column":null}}],"line":123},"11":{"loc":{"start":{"line":128,"column":11},"end":{"line":128,"column":38}},"type":"binary-expr","locations":[{"start":{"line":128,"column":11},"end":{"line":128,"column":35}},{"start":{"line":128,"column":35},"end":{"line":128,"column":38}}],"line":128}},"s":{"0":2,"1":2,"2":2,"3":2,"4":2,"5":3,"6":5,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":2,"16":0,"17":0,"18":2,"19":0,"20":0,"21":2,"22":2,"23":2,"24":5,"25":5,"26":5,"27":2,"28":5,"29":5,"30":3,"31":3,"32":4,"33":1,"34":1,"35":1,"36":3,"37":3,"38":3,"39":3,"40":3,"41":3,"42":3,"43":3,"44":1,"45":1,"46":1,"47":1,"48":2},"f":{"0":2,"1":3,"2":5,"3":0,"4":0,"5":0,"6":0,"7":2,"8":5,"9":3,"10":4,"11":1},"b":{"0":[0,0],"1":[0,0],"2":[0,2],"3":[0,2],"4":[2,3],"5":[5,0],"6":[1,3],"7":[4,4],"8":[1,0],"9":[1,1],"10":[1,2],"11":[1,0]},"meta":{"lastBranch":12,"lastFunction":12,"lastStatement":49,"seen":{"s:22:20:22:Infinity":0,"s:24:23:24:Infinity":1,"s:25:37:25:Infinity":2,"f:27:2:27:Infinity":0,"s:28:12:28:Infinity":3,"s:29:12:29:Infinity":4,"f:32:6:32:31":1,"s:33:4:33:Infinity":5,"f:36:6:36:28":2,"s:37:4:37:Infinity":6,"f:40:2:40:16":3,"b:41:4:43:Infinity:undefined:undefined:undefined:undefined":0,"s:41:4:43:Infinity":7,"s:42:6:42:Infinity":8,"s:45:20:51:Infinity":9,"b:50:10:50:38:50:38:50:Infinity":1,"s:53:4:61:Infinity":10,"s:63:4:66:Infinity":11,"f:64:17:64:18":4,"s:64:39:64:59":12,"f:65:20:65:21":5,"s:65:42:65:62":13,"f:66:20:66:21":6,"s:66:42:66:62":14,"f:69:8:69:30":7,"b:70:4:73:Infinity:undefined:undefined:undefined:undefined":2,"s:70:4:73:Infinity":15,"s:71:6:71:Infinity":16,"s:72:6:72:Infinity":17,"b:75:4:78:Infinity:undefined:undefined:undefined:undefined":3,"s:75:4:78:Infinity":18,"s:76:6:76:Infinity":19,"s:77:6:77:Infinity":20,"s:80:4:80:Infinity":21,"s:81:4:81:Infinity":22,"s:82:4:82:Infinity":23,"f:85:10:85:16":8,"s:86:4:86:Infinity":24,"s:87:4:87:Infinity":25,"b:89:4:91:Infinity:undefined:undefined:undefined:undefined":4,"s:89:4:91:Infinity":26,"s:90:6:90:Infinity":27,"s:93:4:93:Infinity":28,"s:94:4:97:Infinity":29,"f:94:28:94:34":9,"s:95:6:95:Infinity":30,"s:96:6:96:Infinity":31,"b:97:7:97:31:97:31:97:34":5,"f:100:16:100:39":10,"b:101:4:106:Infinity:undefined:undefined:undefined:undefined":6,"s:101:4:106:Infinity":32,"b:101:8:101:27:101:27:101:52":7,"b:102:6:104:Infinity:undefined:undefined:undefined:undefined":8,"s:102:6:104:Infinity":33,"b:102:10:102:30:102:30:102:55":9,"s:103:8:103:Infinity":34,"s:105:6:105:Infinity":35,"s:108:4:108:Infinity":36,"s:109:4:109:Infinity":37,"s:111:25:111:Infinity":38,"s:112:4:112:Infinity":39,"s:114:4:132:Infinity":40,"s:115:6:120:Infinity":41,"s:122:6:122:Infinity":42,"b:123:6:131:Infinity:129:13:131:Infinity":10,"s:123:6:131:Infinity":43,"s:124:8:124:Infinity":44,"s:125:8:128:Infinity":45,"f:125:32:125:38":11,"s:126:10:126:Infinity":46,"s:127:10:127:Infinity":47,"b:128:11:128:35:128:35:128:38":11,"s:130:8:130:Infinity":48}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/parsers/docs-parser.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/parsers/docs-parser.ts","statementMap":{"0":{"start":{"line":75,"column":20},"end":{"line":75,"column":null}},"1":{"start":{"line":76,"column":4},"end":{"line":76,"column":null}},"2":{"start":{"line":90,"column":25},"end":{"line":92,"column":null}},"3":{"start":{"line":94,"column":17},"end":{"line":97,"column":null}},"4":{"start":{"line":99,"column":18},"end":{"line":99,"column":null}},"5":{"start":{"line":100,"column":21},"end":{"line":100,"column":null}},"6":{"start":{"line":101,"column":18},"end":{"line":101,"column":null}},"7":{"start":{"line":102,"column":17},"end":{"line":102,"column":null}},"8":{"start":{"line":103,"column":22},"end":{"line":103,"column":null}},"9":{"start":{"line":103,"column":50},"end":{"line":103,"column":69}},"10":{"start":{"line":105,"column":4},"end":{"line":105,"column":null}},"11":{"start":{"line":112,"column":18},"end":{"line":112,"column":null}},"12":{"start":{"line":113,"column":21},"end":{"line":113,"column":null}},"13":{"start":{"line":115,"column":4},"end":{"line":115,"column":null}},"14":{"start":{"line":115,"column":34},"end":{"line":115,"column":null}},"15":{"start":{"line":116,"column":4},"end":{"line":116,"column":null}},"16":{"start":{"line":116,"column":46},"end":{"line":116,"column":null}},"17":{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},"18":{"start":{"line":117,"column":48},"end":{"line":117,"column":null}},"19":{"start":{"line":118,"column":4},"end":{"line":123,"column":null}},"20":{"start":{"line":123,"column":6},"end":{"line":123,"column":null}},"21":{"start":{"line":124,"column":4},"end":{"line":125,"column":null}},"22":{"start":{"line":125,"column":6},"end":{"line":125,"column":null}},"23":{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},"24":{"start":{"line":135,"column":17},"end":{"line":135,"column":null}},"25":{"start":{"line":136,"column":20},"end":{"line":136,"column":null}},"26":{"start":{"line":138,"column":4},"end":{"line":143,"column":null}},"27":{"start":{"line":139,"column":18},"end":{"line":139,"column":null}},"28":{"start":{"line":140,"column":6},"end":{"line":142,"column":null}},"29":{"start":{"line":141,"column":8},"end":{"line":141,"column":null}},"30":{"start":{"line":144,"column":4},"end":{"line":144,"column":null}},"31":{"start":{"line":155,"column":38},"end":{"line":155,"column":null}},"32":{"start":{"line":156,"column":25},"end":{"line":156,"column":null}},"33":{"start":{"line":157,"column":34},"end":{"line":157,"column":null}},"34":{"start":{"line":158,"column":27},"end":{"line":158,"column":null}},"35":{"start":{"line":159,"column":37},"end":{"line":159,"column":null}},"36":{"start":{"line":160,"column":22},"end":{"line":160,"column":null}},"37":{"start":{"line":161,"column":22},"end":{"line":161,"column":null}},"38":{"start":{"line":163,"column":18},"end":{"line":178,"column":null}},"39":{"start":{"line":164,"column":19},"end":{"line":164,"column":null}},"40":{"start":{"line":165,"column":6},"end":{"line":175,"column":null}},"41":{"start":{"line":166,"column":8},"end":{"line":174,"column":null}},"42":{"start":{"line":176,"column":6},"end":{"line":176,"column":null}},"43":{"start":{"line":177,"column":6},"end":{"line":177,"column":null}},"44":{"start":{"line":180,"column":4},"end":{"line":246,"column":null}},"45":{"start":{"line":180,"column":17},"end":{"line":180,"column":20}},"46":{"start":{"line":181,"column":19},"end":{"line":181,"column":null}},"47":{"start":{"line":182,"column":25},"end":{"line":182,"column":null}},"48":{"start":{"line":185,"column":25},"end":{"line":185,"column":null}},"49":{"start":{"line":186,"column":6},"end":{"line":196,"column":null}},"50":{"start":{"line":187,"column":8},"end":{"line":193,"column":null}},"51":{"start":{"line":188,"column":10},"end":{"line":188,"column":null}},"52":{"start":{"line":189,"column":10},"end":{"line":189,"column":null}},"53":{"start":{"line":190,"column":8},"end":{"line":193,"column":null}},"54":{"start":{"line":191,"column":10},"end":{"line":191,"column":null}},"55":{"start":{"line":192,"column":10},"end":{"line":192,"column":null}},"56":{"start":{"line":194,"column":8},"end":{"line":194,"column":null}},"57":{"start":{"line":195,"column":8},"end":{"line":195,"column":null}},"58":{"start":{"line":198,"column":6},"end":{"line":201,"column":null}},"59":{"start":{"line":199,"column":8},"end":{"line":199,"column":null}},"60":{"start":{"line":200,"column":8},"end":{"line":200,"column":null}},"61":{"start":{"line":204,"column":27},"end":{"line":204,"column":null}},"62":{"start":{"line":205,"column":6},"end":{"line":217,"column":null}},"63":{"start":{"line":206,"column":22},"end":{"line":206,"column":null}},"64":{"start":{"line":207,"column":28},"end":{"line":207,"column":null}},"65":{"start":{"line":210,"column":8},"end":{"line":216,"column":null}},"66":{"start":{"line":211,"column":10},"end":{"line":211,"column":null}},"67":{"start":{"line":212,"column":10},"end":{"line":212,"column":null}},"68":{"start":{"line":213,"column":10},"end":{"line":213,"column":null}},"69":{"start":{"line":214,"column":10},"end":{"line":214,"column":null}},"70":{"start":{"line":215,"column":10},"end":{"line":215,"column":null}},"71":{"start":{"line":220,"column":6},"end":{"line":243,"column":null}},"72":{"start":{"line":221,"column":25},"end":{"line":221,"column":null}},"73":{"start":{"line":222,"column":8},"end":{"line":230,"column":null}},"74":{"start":{"line":224,"column":30},"end":{"line":224,"column":null}},"75":{"start":{"line":225,"column":10},"end":{"line":225,"column":null}},"76":{"start":{"line":226,"column":10},"end":{"line":226,"column":null}},"77":{"start":{"line":227,"column":10},"end":{"line":227,"column":null}},"78":{"start":{"line":228,"column":10},"end":{"line":228,"column":null}},"79":{"start":{"line":229,"column":10},"end":{"line":229,"column":null}},"80":{"start":{"line":231,"column":8},"end":{"line":242,"column":null}},"81":{"start":{"line":236,"column":30},"end":{"line":236,"column":null}},"82":{"start":{"line":237,"column":10},"end":{"line":237,"column":null}},"83":{"start":{"line":238,"column":10},"end":{"line":238,"column":null}},"84":{"start":{"line":239,"column":10},"end":{"line":239,"column":null}},"85":{"start":{"line":240,"column":10},"end":{"line":240,"column":null}},"86":{"start":{"line":241,"column":10},"end":{"line":241,"column":null}},"87":{"start":{"line":245,"column":6},"end":{"line":245,"column":null}},"88":{"start":{"line":249,"column":4},"end":{"line":249,"column":null}},"89":{"start":{"line":252,"column":4},"end":{"line":254,"column":null}},"90":{"start":{"line":253,"column":6},"end":{"line":253,"column":null}},"91":{"start":{"line":256,"column":4},"end":{"line":256,"column":null}},"92":{"start":{"line":268,"column":23},"end":{"line":268,"column":null}},"93":{"start":{"line":270,"column":22},"end":{"line":270,"column":null}},"94":{"start":{"line":272,"column":4},"end":{"line":282,"column":null}},"95":{"start":{"line":291,"column":32},"end":{"line":291,"column":null}},"96":{"start":{"line":292,"column":18},"end":{"line":292,"column":null}},"97":{"start":{"line":293,"column":18},"end":{"line":293,"column":null}},"98":{"start":{"line":294,"column":22},"end":{"line":294,"column":null}},"99":{"start":{"line":295,"column":15},"end":{"line":295,"column":null}},"100":{"start":{"line":296,"column":31},"end":{"line":296,"column":null}},"101":{"start":{"line":297,"column":21},"end":{"line":297,"column":null}},"102":{"start":{"line":299,"column":4},"end":{"line":326,"column":null}},"103":{"start":{"line":299,"column":17},"end":{"line":299,"column":20}},"104":{"start":{"line":300,"column":19},"end":{"line":300,"column":null}},"105":{"start":{"line":301,"column":24},"end":{"line":301,"column":null}},"106":{"start":{"line":303,"column":6},"end":{"line":310,"column":null}},"107":{"start":{"line":304,"column":8},"end":{"line":304,"column":null}},"108":{"start":{"line":305,"column":8},"end":{"line":305,"column":null}},"109":{"start":{"line":306,"column":8},"end":{"line":306,"column":null}},"110":{"start":{"line":307,"column":8},"end":{"line":307,"column":null}},"111":{"start":{"line":308,"column":8},"end":{"line":308,"column":null}},"112":{"start":{"line":309,"column":8},"end":{"line":309,"column":null}},"113":{"start":{"line":312,"column":6},"end":{"line":325,"column":null}},"114":{"start":{"line":313,"column":8},"end":{"line":324,"column":null}},"115":{"start":{"line":314,"column":10},"end":{"line":318,"column":null}},"116":{"start":{"line":319,"column":10},"end":{"line":319,"column":null}},"117":{"start":{"line":320,"column":10},"end":{"line":320,"column":null}},"118":{"start":{"line":321,"column":10},"end":{"line":321,"column":null}},"119":{"start":{"line":323,"column":10},"end":{"line":323,"column":null}},"120":{"start":{"line":328,"column":4},"end":{"line":328,"column":null}},"121":{"start":{"line":332,"column":4},"end":{"line":332,"column":null}},"122":{"start":{"line":336,"column":29},"end":{"line":336,"column":null}},"123":{"start":{"line":338,"column":20},"end":{"line":338,"column":null}},"124":{"start":{"line":340,"column":4},"end":{"line":342,"column":null}},"125":{"start":{"line":341,"column":6},"end":{"line":341,"column":null}},"126":{"start":{"line":343,"column":4},"end":{"line":343,"column":null}},"127":{"start":{"line":347,"column":4},"end":{"line":347,"column":null}},"128":{"start":{"line":353,"column":15},"end":{"line":353,"column":null}},"129":{"start":{"line":353,"column":36},"end":{"line":353,"column":73}},"130":{"start":{"line":354,"column":4},"end":{"line":354,"column":null}},"131":{"start":{"line":354,"column":12},"end":{"line":354,"column":null}},"132":{"start":{"line":356,"column":4},"end":{"line":356,"column":null}},"133":{"start":{"line":368,"column":28},"end":{"line":368,"column":null}},"134":{"start":{"line":369,"column":19},"end":{"line":377,"column":null}},"135":{"start":{"line":379,"column":15},"end":{"line":413,"column":null}},"136":{"start":{"line":380,"column":4},"end":{"line":380,"column":null}},"137":{"start":{"line":380,"column":19},"end":{"line":380,"column":null}},"138":{"start":{"line":382,"column":4},"end":{"line":386,"column":null}},"139":{"start":{"line":383,"column":6},"end":{"line":383,"column":null}},"140":{"start":{"line":385,"column":6},"end":{"line":385,"column":null}},"141":{"start":{"line":388,"column":4},"end":{"line":412,"column":null}},"142":{"start":{"line":389,"column":6},"end":{"line":389,"column":null}},"143":{"start":{"line":389,"column":36},"end":{"line":389,"column":null}},"144":{"start":{"line":391,"column":23},"end":{"line":391,"column":null}},"145":{"start":{"line":393,"column":6},"end":{"line":411,"column":null}},"146":{"start":{"line":396,"column":26},"end":{"line":396,"column":null}},"147":{"start":{"line":398,"column":10},"end":{"line":405,"column":null}},"148":{"start":{"line":406,"column":8},"end":{"line":408,"column":null}},"149":{"start":{"line":407,"column":10},"end":{"line":407,"column":null}},"150":{"start":{"line":409,"column":6},"end":{"line":411,"column":null}},"151":{"start":{"line":410,"column":8},"end":{"line":410,"column":null}},"152":{"start":{"line":415,"column":2},"end":{"line":415,"column":null}},"153":{"start":{"line":416,"column":2},"end":{"line":416,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":74,"column":2},"end":{"line":74,"column":12}},"loc":{"start":{"line":74,"column":64},"end":{"line":77,"column":null}},"line":74},"1":{"name":"(anonymous_1)","decl":{"start":{"line":85,"column":2},"end":{"line":85,"column":null}},"loc":{"start":{"line":89,"column":15},"end":{"line":106,"column":null}},"line":89},"2":{"name":"(anonymous_2)","decl":{"start":{"line":103,"column":38},"end":{"line":103,"column":39}},"loc":{"start":{"line":103,"column":50},"end":{"line":103,"column":69}},"line":103},"3":{"name":"(anonymous_3)","decl":{"start":{"line":111,"column":2},"end":{"line":111,"column":12}},"loc":{"start":{"line":111,"column":43},"end":{"line":128,"column":null}},"line":111},"4":{"name":"(anonymous_4)","decl":{"start":{"line":134,"column":2},"end":{"line":134,"column":22}},"loc":{"start":{"line":134,"column":46},"end":{"line":145,"column":null}},"line":134},"5":{"name":"(anonymous_5)","decl":{"start":{"line":154,"column":10},"end":{"line":154,"column":24}},"loc":{"start":{"line":154,"column":58},"end":{"line":257,"column":null}},"line":154},"6":{"name":"(anonymous_6)","decl":{"start":{"line":163,"column":18},"end":{"line":163,"column":19}},"loc":{"start":{"line":163,"column":51},"end":{"line":178,"column":null}},"line":163},"7":{"name":"(anonymous_7)","decl":{"start":{"line":261,"column":10},"end":{"line":261,"column":null}},"loc":{"start":{"line":267,"column":19},"end":{"line":283,"column":null}},"line":267},"8":{"name":"(anonymous_8)","decl":{"start":{"line":287,"column":10},"end":{"line":287,"column":null}},"loc":{"start":{"line":290,"column":17},"end":{"line":329,"column":null}},"line":290},"9":{"name":"(anonymous_9)","decl":{"start":{"line":331,"column":10},"end":{"line":331,"column":26}},"loc":{"start":{"line":331,"column":48},"end":{"line":333,"column":null}},"line":331},"10":{"name":"(anonymous_10)","decl":{"start":{"line":335,"column":10},"end":{"line":335,"column":23}},"loc":{"start":{"line":335,"column":48},"end":{"line":344,"column":null}},"line":335},"11":{"name":"(anonymous_11)","decl":{"start":{"line":346,"column":10},"end":{"line":346,"column":21}},"loc":{"start":{"line":346,"column":43},"end":{"line":348,"column":null}},"line":346},"12":{"name":"(anonymous_12)","decl":{"start":{"line":352,"column":10},"end":{"line":352,"column":21}},"loc":{"start":{"line":352,"column":78},"end":{"line":357,"column":null}},"line":352},"13":{"name":"(anonymous_13)","decl":{"start":{"line":353,"column":29},"end":{"line":353,"column":30}},"loc":{"start":{"line":353,"column":36},"end":{"line":353,"column":73}},"line":353},"14":{"name":"findMarkdownFiles","decl":{"start":{"line":367,"column":16},"end":{"line":367,"column":34}},"loc":{"start":{"line":367,"column":67},"end":{"line":417,"column":null}},"line":367},"15":{"name":"(anonymous_15)","decl":{"start":{"line":379,"column":15},"end":{"line":379,"column":16}},"loc":{"start":{"line":379,"column":53},"end":{"line":413,"column":null}},"line":379}},"branchMap":{"0":{"loc":{"start":{"line":115,"column":4},"end":{"line":115,"column":null}},"type":"if","locations":[{"start":{"line":115,"column":4},"end":{"line":115,"column":null}},{"start":{},"end":{}}],"line":115},"1":{"loc":{"start":{"line":116,"column":4},"end":{"line":116,"column":null}},"type":"if","locations":[{"start":{"line":116,"column":4},"end":{"line":116,"column":null}},{"start":{},"end":{}}],"line":116},"2":{"loc":{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},"type":"if","locations":[{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},{"start":{},"end":{}}],"line":117},"3":{"loc":{"start":{"line":118,"column":4},"end":{"line":123,"column":null}},"type":"if","locations":[{"start":{"line":118,"column":4},"end":{"line":123,"column":null}},{"start":{},"end":{}}],"line":118},"4":{"loc":{"start":{"line":119,"column":6},"end":{"line":121,"column":null}},"type":"binary-expr","locations":[{"start":{"line":119,"column":6},"end":{"line":119,"column":null}},{"start":{"line":120,"column":6},"end":{"line":120,"column":null}},{"start":{"line":121,"column":6},"end":{"line":121,"column":null}}],"line":119},"5":{"loc":{"start":{"line":124,"column":4},"end":{"line":125,"column":null}},"type":"if","locations":[{"start":{"line":124,"column":4},"end":{"line":125,"column":null}},{"start":{},"end":{}}],"line":124},"6":{"loc":{"start":{"line":124,"column":8},"end":{"line":124,"column":null}},"type":"binary-expr","locations":[{"start":{"line":124,"column":8},"end":{"line":124,"column":41}},{"start":{"line":124,"column":41},"end":{"line":124,"column":null}}],"line":124},"7":{"loc":{"start":{"line":140,"column":6},"end":{"line":142,"column":null}},"type":"if","locations":[{"start":{"line":140,"column":6},"end":{"line":142,"column":null}},{"start":{},"end":{}}],"line":140},"8":{"loc":{"start":{"line":140,"column":10},"end":{"line":140,"column":47}},"type":"binary-expr","locations":[{"start":{"line":140,"column":10},"end":{"line":140,"column":28}},{"start":{"line":140,"column":28},"end":{"line":140,"column":47}}],"line":140},"9":{"loc":{"start":{"line":165,"column":6},"end":{"line":175,"column":null}},"type":"if","locations":[{"start":{"line":165,"column":6},"end":{"line":175,"column":null}},{"start":{},"end":{}}],"line":165},"10":{"loc":{"start":{"line":165,"column":10},"end":{"line":165,"column":63}},"type":"binary-expr","locations":[{"start":{"line":165,"column":10},"end":{"line":165,"column":39}},{"start":{"line":165,"column":39},"end":{"line":165,"column":63}}],"line":165},"11":{"loc":{"start":{"line":186,"column":6},"end":{"line":196,"column":null}},"type":"if","locations":[{"start":{"line":186,"column":6},"end":{"line":196,"column":null}},{"start":{},"end":{}}],"line":186},"12":{"loc":{"start":{"line":187,"column":8},"end":{"line":193,"column":null}},"type":"if","locations":[{"start":{"line":187,"column":8},"end":{"line":193,"column":null}},{"start":{"line":190,"column":8},"end":{"line":193,"column":null}}],"line":187},"13":{"loc":{"start":{"line":190,"column":8},"end":{"line":193,"column":null}},"type":"if","locations":[{"start":{"line":190,"column":8},"end":{"line":193,"column":null}},{"start":{},"end":{}}],"line":190},"14":{"loc":{"start":{"line":198,"column":6},"end":{"line":201,"column":null}},"type":"if","locations":[{"start":{"line":198,"column":6},"end":{"line":201,"column":null}},{"start":{},"end":{}}],"line":198},"15":{"loc":{"start":{"line":205,"column":6},"end":{"line":217,"column":null}},"type":"if","locations":[{"start":{"line":205,"column":6},"end":{"line":217,"column":null}},{"start":{},"end":{}}],"line":205},"16":{"loc":{"start":{"line":210,"column":8},"end":{"line":216,"column":null}},"type":"if","locations":[{"start":{"line":210,"column":8},"end":{"line":216,"column":null}},{"start":{},"end":{}}],"line":210},"17":{"loc":{"start":{"line":220,"column":6},"end":{"line":243,"column":null}},"type":"if","locations":[{"start":{"line":220,"column":6},"end":{"line":243,"column":null}},{"start":{},"end":{}}],"line":220},"18":{"loc":{"start":{"line":220,"column":10},"end":{"line":220,"column":33}},"type":"binary-expr","locations":[{"start":{"line":220,"column":10},"end":{"line":220,"column":19}},{"start":{"line":220,"column":19},"end":{"line":220,"column":33}}],"line":220},"19":{"loc":{"start":{"line":221,"column":25},"end":{"line":221,"column":null}},"type":"binary-expr","locations":[{"start":{"line":221,"column":25},"end":{"line":221,"column":74}},{"start":{"line":221,"column":74},"end":{"line":221,"column":null}}],"line":221},"20":{"loc":{"start":{"line":222,"column":8},"end":{"line":230,"column":null}},"type":"if","locations":[{"start":{"line":222,"column":8},"end":{"line":230,"column":null}},{"start":{},"end":{}}],"line":222},"21":{"loc":{"start":{"line":222,"column":12},"end":{"line":222,"column":67}},"type":"binary-expr","locations":[{"start":{"line":222,"column":12},"end":{"line":222,"column":39}},{"start":{"line":222,"column":39},"end":{"line":222,"column":67}}],"line":222},"22":{"loc":{"start":{"line":224,"column":30},"end":{"line":224,"column":null}},"type":"binary-expr","locations":[{"start":{"line":224,"column":30},"end":{"line":224,"column":64}},{"start":{"line":224,"column":64},"end":{"line":224,"column":null}}],"line":224},"23":{"loc":{"start":{"line":231,"column":8},"end":{"line":242,"column":null}},"type":"if","locations":[{"start":{"line":231,"column":8},"end":{"line":242,"column":null}},{"start":{},"end":{}}],"line":231},"24":{"loc":{"start":{"line":232,"column":10},"end":{"line":234,"column":null}},"type":"binary-expr","locations":[{"start":{"line":232,"column":10},"end":{"line":232,"column":null}},{"start":{"line":233,"column":10},"end":{"line":233,"column":null}},{"start":{"line":234,"column":10},"end":{"line":234,"column":null}}],"line":232},"25":{"loc":{"start":{"line":236,"column":30},"end":{"line":236,"column":null}},"type":"binary-expr","locations":[{"start":{"line":236,"column":30},"end":{"line":236,"column":64}},{"start":{"line":236,"column":64},"end":{"line":236,"column":null}}],"line":236},"26":{"loc":{"start":{"line":252,"column":4},"end":{"line":254,"column":null}},"type":"if","locations":[{"start":{"line":252,"column":4},"end":{"line":254,"column":null}},{"start":{},"end":{}}],"line":252},"27":{"loc":{"start":{"line":303,"column":6},"end":{"line":310,"column":null}},"type":"if","locations":[{"start":{"line":303,"column":6},"end":{"line":310,"column":null}},{"start":{},"end":{}}],"line":303},"28":{"loc":{"start":{"line":303,"column":10},"end":{"line":303,"column":33}},"type":"binary-expr","locations":[{"start":{"line":303,"column":10},"end":{"line":303,"column":22}},{"start":{"line":303,"column":22},"end":{"line":303,"column":33}}],"line":303},"29":{"loc":{"start":{"line":306,"column":15},"end":{"line":306,"column":null}},"type":"binary-expr","locations":[{"start":{"line":306,"column":15},"end":{"line":306,"column":31}},{"start":{"line":306,"column":31},"end":{"line":306,"column":null}}],"line":306},"30":{"loc":{"start":{"line":312,"column":6},"end":{"line":325,"column":null}},"type":"if","locations":[{"start":{"line":312,"column":6},"end":{"line":325,"column":null}},{"start":{},"end":{}}],"line":312},"31":{"loc":{"start":{"line":313,"column":8},"end":{"line":324,"column":null}},"type":"if","locations":[{"start":{"line":313,"column":8},"end":{"line":324,"column":null}},{"start":{"line":322,"column":15},"end":{"line":324,"column":null}}],"line":313},"32":{"loc":{"start":{"line":347,"column":12},"end":{"line":347,"column":38}},"type":"binary-expr","locations":[{"start":{"line":347,"column":12},"end":{"line":347,"column":34}},{"start":{"line":347,"column":34},"end":{"line":347,"column":38}}],"line":347},"33":{"loc":{"start":{"line":353,"column":36},"end":{"line":353,"column":73}},"type":"binary-expr","locations":[{"start":{"line":353,"column":36},"end":{"line":353,"column":53}},{"start":{"line":353,"column":53},"end":{"line":353,"column":73}}],"line":353},"34":{"loc":{"start":{"line":354,"column":4},"end":{"line":354,"column":null}},"type":"if","locations":[{"start":{"line":354,"column":4},"end":{"line":354,"column":null}},{"start":{},"end":{}}],"line":354},"35":{"loc":{"start":{"line":380,"column":4},"end":{"line":380,"column":null}},"type":"if","locations":[{"start":{"line":380,"column":4},"end":{"line":380,"column":null}},{"start":{},"end":{}}],"line":380},"36":{"loc":{"start":{"line":389,"column":6},"end":{"line":389,"column":null}},"type":"if","locations":[{"start":{"line":389,"column":6},"end":{"line":389,"column":null}},{"start":{},"end":{}}],"line":389},"37":{"loc":{"start":{"line":393,"column":6},"end":{"line":411,"column":null}},"type":"if","locations":[{"start":{"line":393,"column":6},"end":{"line":411,"column":null}},{"start":{"line":409,"column":6},"end":{"line":411,"column":null}}],"line":393},"38":{"loc":{"start":{"line":398,"column":10},"end":{"line":405,"column":null}},"type":"binary-expr","locations":[{"start":{"line":398,"column":10},"end":{"line":398,"column":null}},{"start":{"line":399,"column":10},"end":{"line":399,"column":null}},{"start":{"line":400,"column":10},"end":{"line":400,"column":null}},{"start":{"line":401,"column":10},"end":{"line":401,"column":null}},{"start":{"line":402,"column":10},"end":{"line":402,"column":null}},{"start":{"line":403,"column":10},"end":{"line":403,"column":null}},{"start":{"line":404,"column":10},"end":{"line":404,"column":null}},{"start":{"line":405,"column":10},"end":{"line":405,"column":null}}],"line":398},"39":{"loc":{"start":{"line":406,"column":8},"end":{"line":408,"column":null}},"type":"if","locations":[{"start":{"line":406,"column":8},"end":{"line":408,"column":null}},{"start":{},"end":{}}],"line":406},"40":{"loc":{"start":{"line":406,"column":12},"end":{"line":406,"column":37}},"type":"binary-expr","locations":[{"start":{"line":406,"column":12},"end":{"line":406,"column":27}},{"start":{"line":406,"column":27},"end":{"line":406,"column":37}}],"line":406},"41":{"loc":{"start":{"line":409,"column":6},"end":{"line":411,"column":null}},"type":"if","locations":[{"start":{"line":409,"column":6},"end":{"line":411,"column":null}},{"start":{},"end":{}}],"line":409},"42":{"loc":{"start":{"line":409,"column":17},"end":{"line":409,"column":68}},"type":"binary-expr","locations":[{"start":{"line":409,"column":17},"end":{"line":409,"column":35}},{"start":{"line":409,"column":35},"end":{"line":409,"column":68}}],"line":409}},"s":{"0":43,"1":43,"2":64,"3":64,"4":64,"5":64,"6":64,"7":64,"8":64,"9":358,"10":64,"11":81,"12":81,"13":81,"14":20,"15":61,"16":3,"17":58,"18":2,"19":56,"20":5,"21":51,"22":3,"23":48,"24":363,"25":363,"26":363,"27":550,"28":550,"29":549,"30":363,"31":64,"32":64,"33":64,"34":64,"35":64,"36":64,"37":64,"38":64,"39":414,"40":414,"41":357,"42":414,"43":414,"44":64,"45":64,"46":1973,"47":1973,"48":1973,"49":1973,"50":96,"51":48,"52":48,"53":48,"54":48,"55":48,"56":96,"57":96,"58":1877,"59":92,"60":92,"61":1785,"62":1785,"63":349,"64":349,"65":349,"66":348,"67":348,"68":348,"69":348,"70":348,"71":1437,"72":1429,"73":1429,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1428,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1435,"88":64,"89":64,"90":1,"91":64,"92":358,"93":358,"94":358,"95":358,"96":358,"97":358,"98":358,"99":358,"100":358,"101":358,"102":358,"103":358,"104":1622,"105":1622,"106":1622,"107":48,"108":48,"109":48,"110":48,"111":48,"112":48,"113":1574,"114":140,"115":48,"116":48,"117":48,"118":48,"119":92,"120":358,"121":358,"122":358,"123":358,"124":358,"125":32,"126":358,"127":358,"128":64,"129":64,"130":64,"131":51,"132":13,"133":13,"134":13,"135":13,"136":22,"137":0,"138":22,"139":22,"140":0,"141":22,"142":135,"143":5,"144":130,"145":130,"146":25,"147":25,"148":25,"149":9,"150":105,"151":69,"152":13,"153":13},"f":{"0":43,"1":64,"2":358,"3":81,"4":363,"5":64,"6":414,"7":358,"8":358,"9":358,"10":358,"11":358,"12":64,"13":64,"14":13,"15":22},"b":{"0":[20,61],"1":[3,58],"2":[2,56],"3":[5,51],"4":[56,53,52],"5":[3,48],"6":[51,48],"7":[549,1],"8":[550,550],"9":[357,57],"10":[414,64],"11":[96,1877],"12":[48,48],"13":[48,0],"14":[92,1785],"15":[349,1436],"16":[348,1],"17":[1429,8],"18":[1437,1429],"19":[1429,349],"20":[1,1428],"21":[1429,1],"22":[1,0],"23":[1,1427],"24":[1428,1,1],"25":[1,0],"26":[1,63],"27":[48,1574],"28":[1622,1482],"29":[48,0],"30":[140,1434],"31":[48,92],"32":[358,1],"33":[64,59],"34":[51,13],"35":[0,22],"36":[5,130],"37":[25,105],"38":[25,24,24,24,24,24,24,24],"39":[9,16],"40":[25,16],"41":[69,36],"42":[105,104]},"meta":{"lastBranch":43,"lastFunction":16,"lastStatement":154,"seen":{"f:74:2:74:12":0,"s:75:20:75:Infinity":0,"s:76:4:76:Infinity":1,"f:85:2:85:Infinity":1,"s:90:25:92:Infinity":2,"s:94:17:97:Infinity":3,"s:99:18:99:Infinity":4,"s:100:21:100:Infinity":5,"s:101:18:101:Infinity":6,"s:102:17:102:Infinity":7,"s:103:22:103:Infinity":8,"f:103:38:103:39":2,"s:103:50:103:69":9,"s:105:4:105:Infinity":10,"f:111:2:111:12":3,"s:112:18:112:Infinity":11,"s:113:21:113:Infinity":12,"b:115:4:115:Infinity:undefined:undefined:undefined:undefined":0,"s:115:4:115:Infinity":13,"s:115:34:115:Infinity":14,"b:116:4:116:Infinity:undefined:undefined:undefined:undefined":1,"s:116:4:116:Infinity":15,"s:116:46:116:Infinity":16,"b:117:4:117:Infinity:undefined:undefined:undefined:undefined":2,"s:117:4:117:Infinity":17,"s:117:48:117:Infinity":18,"b:118:4:123:Infinity:undefined:undefined:undefined:undefined":3,"s:118:4:123:Infinity":19,"b:119:6:119:Infinity:120:6:120:Infinity:121:6:121:Infinity":4,"s:123:6:123:Infinity":20,"b:124:4:125:Infinity:undefined:undefined:undefined:undefined":5,"s:124:4:125:Infinity":21,"b:124:8:124:41:124:41:124:Infinity":6,"s:125:6:125:Infinity":22,"s:127:4:127:Infinity":23,"f:134:2:134:22":4,"s:135:17:135:Infinity":24,"s:136:20:136:Infinity":25,"s:138:4:143:Infinity":26,"s:139:18:139:Infinity":27,"b:140:6:142:Infinity:undefined:undefined:undefined:undefined":7,"s:140:6:142:Infinity":28,"b:140:10:140:28:140:28:140:47":8,"s:141:8:141:Infinity":29,"s:144:4:144:Infinity":30,"f:154:10:154:24":5,"s:155:38:155:Infinity":31,"s:156:25:156:Infinity":32,"s:157:34:157:Infinity":33,"s:158:27:158:Infinity":34,"s:159:37:159:Infinity":35,"s:160:22:160:Infinity":36,"s:161:22:161:Infinity":37,"s:163:18:178:Infinity":38,"f:163:18:163:19":6,"s:164:19:164:Infinity":39,"b:165:6:175:Infinity:undefined:undefined:undefined:undefined":9,"s:165:6:175:Infinity":40,"b:165:10:165:39:165:39:165:63":10,"s:166:8:174:Infinity":41,"s:176:6:176:Infinity":42,"s:177:6:177:Infinity":43,"s:180:4:246:Infinity":44,"s:180:17:180:20":45,"s:181:19:181:Infinity":46,"s:182:25:182:Infinity":47,"s:185:25:185:Infinity":48,"b:186:6:196:Infinity:undefined:undefined:undefined:undefined":11,"s:186:6:196:Infinity":49,"b:187:8:193:Infinity:190:8:193:Infinity":12,"s:187:8:193:Infinity":50,"s:188:10:188:Infinity":51,"s:189:10:189:Infinity":52,"b:190:8:193:Infinity:undefined:undefined:undefined:undefined":13,"s:190:8:193:Infinity":53,"s:191:10:191:Infinity":54,"s:192:10:192:Infinity":55,"s:194:8:194:Infinity":56,"s:195:8:195:Infinity":57,"b:198:6:201:Infinity:undefined:undefined:undefined:undefined":14,"s:198:6:201:Infinity":58,"s:199:8:199:Infinity":59,"s:200:8:200:Infinity":60,"s:204:27:204:Infinity":61,"b:205:6:217:Infinity:undefined:undefined:undefined:undefined":15,"s:205:6:217:Infinity":62,"s:206:22:206:Infinity":63,"s:207:28:207:Infinity":64,"b:210:8:216:Infinity:undefined:undefined:undefined:undefined":16,"s:210:8:216:Infinity":65,"s:211:10:211:Infinity":66,"s:212:10:212:Infinity":67,"s:213:10:213:Infinity":68,"s:214:10:214:Infinity":69,"s:215:10:215:Infinity":70,"b:220:6:243:Infinity:undefined:undefined:undefined:undefined":17,"s:220:6:243:Infinity":71,"b:220:10:220:19:220:19:220:33":18,"s:221:25:221:Infinity":72,"b:221:25:221:74:221:74:221:Infinity":19,"b:222:8:230:Infinity:undefined:undefined:undefined:undefined":20,"s:222:8:230:Infinity":73,"b:222:12:222:39:222:39:222:67":21,"s:224:30:224:Infinity":74,"b:224:30:224:64:224:64:224:Infinity":22,"s:225:10:225:Infinity":75,"s:226:10:226:Infinity":76,"s:227:10:227:Infinity":77,"s:228:10:228:Infinity":78,"s:229:10:229:Infinity":79,"b:231:8:242:Infinity:undefined:undefined:undefined:undefined":23,"s:231:8:242:Infinity":80,"b:232:10:232:Infinity:233:10:233:Infinity:234:10:234:Infinity":24,"s:236:30:236:Infinity":81,"b:236:30:236:64:236:64:236:Infinity":25,"s:237:10:237:Infinity":82,"s:238:10:238:Infinity":83,"s:239:10:239:Infinity":84,"s:240:10:240:Infinity":85,"s:241:10:241:Infinity":86,"s:245:6:245:Infinity":87,"s:249:4:249:Infinity":88,"b:252:4:254:Infinity:undefined:undefined:undefined:undefined":26,"s:252:4:254:Infinity":89,"s:253:6:253:Infinity":90,"s:256:4:256:Infinity":91,"f:261:10:261:Infinity":7,"s:268:23:268:Infinity":92,"s:270:22:270:Infinity":93,"s:272:4:282:Infinity":94,"f:287:10:287:Infinity":8,"s:291:32:291:Infinity":95,"s:292:18:292:Infinity":96,"s:293:18:293:Infinity":97,"s:294:22:294:Infinity":98,"s:295:15:295:Infinity":99,"s:296:31:296:Infinity":100,"s:297:21:297:Infinity":101,"s:299:4:326:Infinity":102,"s:299:17:299:20":103,"s:300:19:300:Infinity":104,"s:301:24:301:Infinity":105,"b:303:6:310:Infinity:undefined:undefined:undefined:undefined":27,"s:303:6:310:Infinity":106,"b:303:10:303:22:303:22:303:33":28,"s:304:8:304:Infinity":107,"s:305:8:305:Infinity":108,"s:306:8:306:Infinity":109,"b:306:15:306:31:306:31:306:Infinity":29,"s:307:8:307:Infinity":110,"s:308:8:308:Infinity":111,"s:309:8:309:Infinity":112,"b:312:6:325:Infinity:undefined:undefined:undefined:undefined":30,"s:312:6:325:Infinity":113,"b:313:8:324:Infinity:322:15:324:Infinity":31,"s:313:8:324:Infinity":114,"s:314:10:318:Infinity":115,"s:319:10:319:Infinity":116,"s:320:10:320:Infinity":117,"s:321:10:321:Infinity":118,"s:323:10:323:Infinity":119,"s:328:4:328:Infinity":120,"f:331:10:331:26":9,"s:332:4:332:Infinity":121,"f:335:10:335:23":10,"s:336:29:336:Infinity":122,"s:338:20:338:Infinity":123,"s:340:4:342:Infinity":124,"s:341:6:341:Infinity":125,"s:343:4:343:Infinity":126,"f:346:10:346:21":11,"s:347:4:347:Infinity":127,"b:347:12:347:34:347:34:347:38":32,"f:352:10:352:21":12,"s:353:15:353:Infinity":128,"f:353:29:353:30":13,"s:353:36:353:73":129,"b:353:36:353:53:353:53:353:73":33,"b:354:4:354:Infinity:undefined:undefined:undefined:undefined":34,"s:354:4:354:Infinity":130,"s:354:12:354:Infinity":131,"s:356:4:356:Infinity":132,"f:367:16:367:34":14,"s:368:28:368:Infinity":133,"s:369:19:377:Infinity":134,"s:379:15:413:Infinity":135,"f:379:15:379:16":15,"b:380:4:380:Infinity:undefined:undefined:undefined:undefined":35,"s:380:4:380:Infinity":136,"s:380:19:380:Infinity":137,"s:382:4:386:Infinity":138,"s:383:6:383:Infinity":139,"s:385:6:385:Infinity":140,"s:388:4:412:Infinity":141,"b:389:6:389:Infinity:undefined:undefined:undefined:undefined":36,"s:389:6:389:Infinity":142,"s:389:36:389:Infinity":143,"s:391:23:391:Infinity":144,"b:393:6:411:Infinity:409:6:411:Infinity":37,"s:393:6:411:Infinity":145,"s:396:26:396:Infinity":146,"s:398:10:405:Infinity":147,"b:398:10:398:Infinity:399:10:399:Infinity:400:10:400:Infinity:401:10:401:Infinity:402:10:402:Infinity:403:10:403:Infinity:404:10:404:Infinity:405:10:405:Infinity":38,"b:406:8:408:Infinity:undefined:undefined:undefined:undefined":39,"s:406:8:408:Infinity":148,"b:406:12:406:27:406:27:406:37":40,"s:407:10:407:Infinity":149,"b:409:6:411:Infinity:undefined:undefined:undefined:undefined":41,"s:409:6:411:Infinity":150,"b:409:17:409:35:409:35:409:68":42,"s:410:8:410:Infinity":151,"s:415:2:415:Infinity":152,"s:416:2:416:Infinity":153}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/parsers/parser-registry.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/parsers/parser-registry.ts","statementMap":{"0":{"start":{"line":5,"column":20},"end":{"line":5,"column":null}},"1":{"start":{"line":8,"column":4},"end":{"line":10,"column":null}},"2":{"start":{"line":9,"column":6},"end":{"line":9,"column":null}},"3":{"start":{"line":14,"column":16},"end":{"line":14,"column":null}},"4":{"start":{"line":15,"column":4},"end":{"line":15,"column":null}},"5":{"start":{"line":19,"column":19},"end":{"line":19,"column":null}},"6":{"start":{"line":20,"column":4},"end":{"line":22,"column":null}},"7":{"start":{"line":21,"column":6},"end":{"line":21,"column":null}},"8":{"start":{"line":23,"column":4},"end":{"line":23,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":7,"column":2},"end":{"line":7,"column":11}},"loc":{"start":{"line":7,"column":41},"end":{"line":11,"column":null}},"line":7},"1":{"name":"(anonymous_1)","decl":{"start":{"line":13,"column":2},"end":{"line":13,"column":19}},"loc":{"start":{"line":13,"column":60},"end":{"line":16,"column":null}},"line":13},"2":{"name":"(anonymous_2)","decl":{"start":{"line":18,"column":8},"end":{"line":18,"column":14}},"loc":{"start":{"line":18,"column":78},"end":{"line":24,"column":null}},"line":18}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":11},"end":{"line":15,"column":null}},"type":"binary-expr","locations":[{"start":{"line":15,"column":11},"end":{"line":15,"column":36}},{"start":{"line":15,"column":36},"end":{"line":15,"column":null}}],"line":15},"1":{"loc":{"start":{"line":20,"column":4},"end":{"line":22,"column":null}},"type":"if","locations":[{"start":{"line":20,"column":4},"end":{"line":22,"column":null}},{"start":{},"end":{}}],"line":20}},"s":{"0":59,"1":222,"2":223,"3":5,"4":5,"5":2,"6":2,"7":1,"8":1},"f":{"0":222,"1":5,"2":2},"b":{"0":[5,2],"1":[1,1]},"meta":{"lastBranch":2,"lastFunction":3,"lastStatement":9,"seen":{"s:5:20:5:Infinity":0,"f:7:2:7:11":0,"s:8:4:10:Infinity":1,"s:9:6:9:Infinity":2,"f:13:2:13:19":1,"s:14:16:14:Infinity":3,"s:15:4:15:Infinity":4,"b:15:11:15:36:15:36:15:Infinity":0,"f:18:8:18:14":2,"s:19:19:19:Infinity":5,"b:20:4:22:Infinity:undefined:undefined:undefined:undefined":1,"s:20:4:22:Infinity":6,"s:21:6:21:Infinity":7,"s:23:4:23:Infinity":8}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/parsers/regex-language-parsers.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/parsers/regex-language-parsers.ts","statementMap":{"0":{"start":{"line":13,"column":18},"end":{"line":13,"column":null}},"1":{"start":{"line":14,"column":36},"end":{"line":18,"column":null}},"2":{"start":{"line":20,"column":4},"end":{"line":24,"column":null}},"3":{"start":{"line":32,"column":18},"end":{"line":32,"column":null}},"4":{"start":{"line":33,"column":22},"end":{"line":33,"column":null}},"5":{"start":{"line":35,"column":4},"end":{"line":48,"column":null}},"6":{"start":{"line":35,"column":17},"end":{"line":35,"column":33}},"7":{"start":{"line":36,"column":19},"end":{"line":36,"column":null}},"8":{"start":{"line":37,"column":6},"end":{"line":47,"column":null}},"9":{"start":{"line":38,"column":8},"end":{"line":46,"column":null}},"10":{"start":{"line":39,"column":10},"end":{"line":39,"column":null}},"11":{"start":{"line":40,"column":10},"end":{"line":40,"column":null}},"12":{"start":{"line":41,"column":8},"end":{"line":46,"column":null}},"13":{"start":{"line":42,"column":10},"end":{"line":42,"column":null}},"14":{"start":{"line":43,"column":10},"end":{"line":45,"column":null}},"15":{"start":{"line":44,"column":12},"end":{"line":44,"column":null}},"16":{"start":{"line":50,"column":4},"end":{"line":50,"column":null}},"17":{"start":{"line":57,"column":22},"end":{"line":57,"column":null}},"18":{"start":{"line":58,"column":19},"end":{"line":58,"column":null}},"19":{"start":{"line":60,"column":4},"end":{"line":69,"column":null}},"20":{"start":{"line":60,"column":17},"end":{"line":60,"column":37}},"21":{"start":{"line":61,"column":19},"end":{"line":61,"column":null}},"22":{"start":{"line":62,"column":6},"end":{"line":64,"column":null}},"23":{"start":{"line":63,"column":8},"end":{"line":63,"column":null}},"24":{"start":{"line":65,"column":28},"end":{"line":65,"column":null}},"25":{"start":{"line":66,"column":6},"end":{"line":68,"column":null}},"26":{"start":{"line":67,"column":8},"end":{"line":67,"column":null}},"27":{"start":{"line":71,"column":4},"end":{"line":71,"column":null}},"28":{"start":{"line":76,"column":22},"end":{"line":76,"column":null}},"29":{"start":{"line":77,"column":24},"end":{"line":77,"column":null}},"30":{"start":{"line":80,"column":36},"end":{"line":80,"column":null}},"31":{"start":{"line":82,"column":4},"end":{"line":102,"column":null}},"32":{"start":{"line":83,"column":26},"end":{"line":83,"column":null}},"33":{"start":{"line":84,"column":6},"end":{"line":91,"column":null}},"34":{"start":{"line":85,"column":8},"end":{"line":90,"column":null}},"35":{"start":{"line":93,"column":24},"end":{"line":93,"column":null}},"36":{"start":{"line":94,"column":6},"end":{"line":101,"column":null}},"37":{"start":{"line":95,"column":8},"end":{"line":100,"column":null}},"38":{"start":{"line":104,"column":4},"end":{"line":104,"column":null}},"39":{"start":{"line":108,"column":36},"end":{"line":108,"column":null}},"40":{"start":{"line":110,"column":4},"end":{"line":122,"column":null}},"41":{"start":{"line":111,"column":20},"end":{"line":111,"column":null}},"42":{"start":{"line":112,"column":6},"end":{"line":114,"column":null}},"43":{"start":{"line":113,"column":8},"end":{"line":113,"column":null}},"44":{"start":{"line":116,"column":6},"end":{"line":121,"column":null}},"45":{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},"46":{"start":{"line":128,"column":36},"end":{"line":128,"column":null}},"47":{"start":{"line":130,"column":4},"end":{"line":142,"column":null}},"48":{"start":{"line":131,"column":20},"end":{"line":131,"column":null}},"49":{"start":{"line":132,"column":6},"end":{"line":134,"column":null}},"50":{"start":{"line":133,"column":8},"end":{"line":133,"column":null}},"51":{"start":{"line":136,"column":6},"end":{"line":141,"column":null}},"52":{"start":{"line":144,"column":4},"end":{"line":144,"column":null}},"53":{"start":{"line":149,"column":22},"end":{"line":149,"column":null}},"54":{"start":{"line":150,"column":24},"end":{"line":150,"column":null}},"55":{"start":{"line":153,"column":36},"end":{"line":153,"column":null}},"56":{"start":{"line":155,"column":4},"end":{"line":175,"column":null}},"57":{"start":{"line":156,"column":21},"end":{"line":156,"column":null}},"58":{"start":{"line":157,"column":6},"end":{"line":164,"column":null}},"59":{"start":{"line":158,"column":8},"end":{"line":163,"column":null}},"60":{"start":{"line":166,"column":25},"end":{"line":166,"column":null}},"61":{"start":{"line":167,"column":6},"end":{"line":174,"column":null}},"62":{"start":{"line":168,"column":8},"end":{"line":173,"column":null}},"63":{"start":{"line":177,"column":4},"end":{"line":177,"column":null}},"64":{"start":{"line":181,"column":36},"end":{"line":181,"column":null}},"65":{"start":{"line":183,"column":4},"end":{"line":196,"column":null}},"66":{"start":{"line":185,"column":8},"end":{"line":185,"column":null}},"67":{"start":{"line":186,"column":6},"end":{"line":188,"column":null}},"68":{"start":{"line":187,"column":8},"end":{"line":187,"column":null}},"69":{"start":{"line":190,"column":6},"end":{"line":195,"column":null}},"70":{"start":{"line":198,"column":4},"end":{"line":198,"column":null}},"71":{"start":{"line":202,"column":36},"end":{"line":202,"column":null}},"72":{"start":{"line":204,"column":4},"end":{"line":217,"column":null}},"73":{"start":{"line":206,"column":8},"end":{"line":206,"column":null}},"74":{"start":{"line":207,"column":6},"end":{"line":209,"column":null}},"75":{"start":{"line":208,"column":8},"end":{"line":208,"column":null}},"76":{"start":{"line":211,"column":6},"end":{"line":216,"column":null}},"77":{"start":{"line":219,"column":4},"end":{"line":219,"column":null}},"78":{"start":{"line":224,"column":22},"end":{"line":224,"column":null}},"79":{"start":{"line":225,"column":24},"end":{"line":225,"column":null}},"80":{"start":{"line":228,"column":36},"end":{"line":228,"column":null}},"81":{"start":{"line":230,"column":4},"end":{"line":242,"column":null}},"82":{"start":{"line":231,"column":20},"end":{"line":231,"column":null}},"83":{"start":{"line":232,"column":6},"end":{"line":234,"column":null}},"84":{"start":{"line":233,"column":8},"end":{"line":233,"column":null}},"85":{"start":{"line":236,"column":6},"end":{"line":241,"column":null}},"86":{"start":{"line":244,"column":4},"end":{"line":244,"column":null}},"87":{"start":{"line":248,"column":36},"end":{"line":248,"column":null}},"88":{"start":{"line":250,"column":4},"end":{"line":265,"column":null}},"89":{"start":{"line":252,"column":8},"end":{"line":254,"column":null}},"90":{"start":{"line":255,"column":6},"end":{"line":257,"column":null}},"91":{"start":{"line":256,"column":8},"end":{"line":256,"column":null}},"92":{"start":{"line":259,"column":6},"end":{"line":264,"column":null}},"93":{"start":{"line":267,"column":4},"end":{"line":267,"column":null}},"94":{"start":{"line":271,"column":36},"end":{"line":271,"column":null}},"95":{"start":{"line":273,"column":4},"end":{"line":287,"column":null}},"96":{"start":{"line":274,"column":20},"end":{"line":276,"column":null}},"97":{"start":{"line":277,"column":6},"end":{"line":279,"column":null}},"98":{"start":{"line":278,"column":8},"end":{"line":278,"column":null}},"99":{"start":{"line":281,"column":6},"end":{"line":286,"column":null}},"100":{"start":{"line":289,"column":4},"end":{"line":289,"column":null}},"101":{"start":{"line":294,"column":22},"end":{"line":294,"column":null}},"102":{"start":{"line":295,"column":24},"end":{"line":295,"column":null}},"103":{"start":{"line":298,"column":36},"end":{"line":298,"column":null}},"104":{"start":{"line":300,"column":4},"end":{"line":312,"column":null}},"105":{"start":{"line":301,"column":20},"end":{"line":301,"column":null}},"106":{"start":{"line":302,"column":6},"end":{"line":304,"column":null}},"107":{"start":{"line":303,"column":8},"end":{"line":303,"column":null}},"108":{"start":{"line":306,"column":6},"end":{"line":311,"column":null}},"109":{"start":{"line":314,"column":4},"end":{"line":314,"column":null}},"110":{"start":{"line":318,"column":36},"end":{"line":318,"column":null}},"111":{"start":{"line":320,"column":4},"end":{"line":335,"column":null}},"112":{"start":{"line":322,"column":8},"end":{"line":324,"column":null}},"113":{"start":{"line":325,"column":6},"end":{"line":327,"column":null}},"114":{"start":{"line":326,"column":8},"end":{"line":326,"column":null}},"115":{"start":{"line":329,"column":6},"end":{"line":334,"column":null}},"116":{"start":{"line":337,"column":4},"end":{"line":337,"column":null}},"117":{"start":{"line":341,"column":36},"end":{"line":341,"column":null}},"118":{"start":{"line":342,"column":21},"end":{"line":342,"column":null}},"119":{"start":{"line":344,"column":4},"end":{"line":359,"column":null}},"120":{"start":{"line":346,"column":8},"end":{"line":348,"column":null}},"121":{"start":{"line":349,"column":6},"end":{"line":351,"column":null}},"122":{"start":{"line":350,"column":8},"end":{"line":350,"column":null}},"123":{"start":{"line":353,"column":6},"end":{"line":358,"column":null}},"124":{"start":{"line":361,"column":4},"end":{"line":361,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":12,"column":8},"end":{"line":12,"column":14}},"loc":{"start":{"line":12,"column":71},"end":{"line":25,"column":null}},"line":12},"1":{"name":"(anonymous_1)","decl":{"start":{"line":31,"column":12},"end":{"line":31,"column":30}},"loc":{"start":{"line":31,"column":79},"end":{"line":51,"column":null}},"line":31},"2":{"name":"(anonymous_2)","decl":{"start":{"line":53,"column":12},"end":{"line":53,"column":null}},"loc":{"start":{"line":56,"column":12},"end":{"line":72,"column":null}},"line":56},"3":{"name":"(anonymous_3)","decl":{"start":{"line":79,"column":12},"end":{"line":79,"column":27}},"loc":{"start":{"line":79,"column":60},"end":{"line":105,"column":null}},"line":79},"4":{"name":"(anonymous_4)","decl":{"start":{"line":82,"column":18},"end":{"line":82,"column":19}},"loc":{"start":{"line":82,"column":35},"end":{"line":102,"column":5}},"line":82},"5":{"name":"(anonymous_5)","decl":{"start":{"line":107,"column":12},"end":{"line":107,"column":27}},"loc":{"start":{"line":107,"column":60},"end":{"line":125,"column":null}},"line":107},"6":{"name":"(anonymous_6)","decl":{"start":{"line":110,"column":18},"end":{"line":110,"column":19}},"loc":{"start":{"line":110,"column":35},"end":{"line":122,"column":5}},"line":110},"7":{"name":"(anonymous_7)","decl":{"start":{"line":127,"column":12},"end":{"line":127,"column":29}},"loc":{"start":{"line":127,"column":62},"end":{"line":145,"column":null}},"line":127},"8":{"name":"(anonymous_8)","decl":{"start":{"line":130,"column":18},"end":{"line":130,"column":19}},"loc":{"start":{"line":130,"column":35},"end":{"line":142,"column":5}},"line":130},"9":{"name":"(anonymous_9)","decl":{"start":{"line":152,"column":12},"end":{"line":152,"column":27}},"loc":{"start":{"line":152,"column":60},"end":{"line":178,"column":null}},"line":152},"10":{"name":"(anonymous_10)","decl":{"start":{"line":155,"column":18},"end":{"line":155,"column":19}},"loc":{"start":{"line":155,"column":35},"end":{"line":175,"column":5}},"line":155},"11":{"name":"(anonymous_11)","decl":{"start":{"line":180,"column":12},"end":{"line":180,"column":27}},"loc":{"start":{"line":180,"column":60},"end":{"line":199,"column":null}},"line":180},"12":{"name":"(anonymous_12)","decl":{"start":{"line":183,"column":18},"end":{"line":183,"column":19}},"loc":{"start":{"line":183,"column":35},"end":{"line":196,"column":5}},"line":183},"13":{"name":"(anonymous_13)","decl":{"start":{"line":201,"column":12},"end":{"line":201,"column":29}},"loc":{"start":{"line":201,"column":62},"end":{"line":220,"column":null}},"line":201},"14":{"name":"(anonymous_14)","decl":{"start":{"line":204,"column":18},"end":{"line":204,"column":19}},"loc":{"start":{"line":204,"column":35},"end":{"line":217,"column":5}},"line":204},"15":{"name":"(anonymous_15)","decl":{"start":{"line":227,"column":12},"end":{"line":227,"column":27}},"loc":{"start":{"line":227,"column":60},"end":{"line":245,"column":null}},"line":227},"16":{"name":"(anonymous_16)","decl":{"start":{"line":230,"column":18},"end":{"line":230,"column":19}},"loc":{"start":{"line":230,"column":35},"end":{"line":242,"column":5}},"line":230},"17":{"name":"(anonymous_17)","decl":{"start":{"line":247,"column":12},"end":{"line":247,"column":27}},"loc":{"start":{"line":247,"column":60},"end":{"line":268,"column":null}},"line":247},"18":{"name":"(anonymous_18)","decl":{"start":{"line":250,"column":18},"end":{"line":250,"column":19}},"loc":{"start":{"line":250,"column":35},"end":{"line":265,"column":5}},"line":250},"19":{"name":"(anonymous_19)","decl":{"start":{"line":270,"column":12},"end":{"line":270,"column":29}},"loc":{"start":{"line":270,"column":62},"end":{"line":290,"column":null}},"line":270},"20":{"name":"(anonymous_20)","decl":{"start":{"line":273,"column":18},"end":{"line":273,"column":19}},"loc":{"start":{"line":273,"column":35},"end":{"line":287,"column":5}},"line":273},"21":{"name":"(anonymous_21)","decl":{"start":{"line":297,"column":12},"end":{"line":297,"column":27}},"loc":{"start":{"line":297,"column":60},"end":{"line":315,"column":null}},"line":297},"22":{"name":"(anonymous_22)","decl":{"start":{"line":300,"column":18},"end":{"line":300,"column":19}},"loc":{"start":{"line":300,"column":35},"end":{"line":312,"column":5}},"line":300},"23":{"name":"(anonymous_23)","decl":{"start":{"line":317,"column":12},"end":{"line":317,"column":27}},"loc":{"start":{"line":317,"column":60},"end":{"line":338,"column":null}},"line":317},"24":{"name":"(anonymous_24)","decl":{"start":{"line":320,"column":18},"end":{"line":320,"column":19}},"loc":{"start":{"line":320,"column":35},"end":{"line":335,"column":5}},"line":320},"25":{"name":"(anonymous_25)","decl":{"start":{"line":340,"column":12},"end":{"line":340,"column":29}},"loc":{"start":{"line":340,"column":62},"end":{"line":362,"column":null}},"line":340},"26":{"name":"(anonymous_26)","decl":{"start":{"line":344,"column":18},"end":{"line":344,"column":19}},"loc":{"start":{"line":344,"column":35},"end":{"line":359,"column":5}},"line":344}},"branchMap":{"0":{"loc":{"start":{"line":38,"column":8},"end":{"line":46,"column":null}},"type":"if","locations":[{"start":{"line":38,"column":8},"end":{"line":46,"column":null}},{"start":{"line":41,"column":8},"end":{"line":46,"column":null}}],"line":38},"1":{"loc":{"start":{"line":41,"column":8},"end":{"line":46,"column":null}},"type":"if","locations":[{"start":{"line":41,"column":8},"end":{"line":46,"column":null}},{"start":{},"end":{}}],"line":41},"2":{"loc":{"start":{"line":43,"column":10},"end":{"line":45,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":10},"end":{"line":45,"column":null}},{"start":{},"end":{}}],"line":43},"3":{"loc":{"start":{"line":43,"column":14},"end":{"line":43,"column":43}},"type":"binary-expr","locations":[{"start":{"line":43,"column":14},"end":{"line":43,"column":29}},{"start":{"line":43,"column":29},"end":{"line":43,"column":43}}],"line":43},"4":{"loc":{"start":{"line":57,"column":22},"end":{"line":57,"column":null}},"type":"binary-expr","locations":[{"start":{"line":57,"column":22},"end":{"line":57,"column":47}},{"start":{"line":57,"column":47},"end":{"line":57,"column":null}}],"line":57},"5":{"loc":{"start":{"line":58,"column":19},"end":{"line":58,"column":null}},"type":"binary-expr","locations":[{"start":{"line":58,"column":19},"end":{"line":58,"column":58}},{"start":{"line":58,"column":58},"end":{"line":58,"column":null}}],"line":58},"6":{"loc":{"start":{"line":62,"column":6},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":62,"column":6},"end":{"line":64,"column":null}},{"start":{},"end":{}}],"line":62},"7":{"loc":{"start":{"line":65,"column":28},"end":{"line":65,"column":null}},"type":"binary-expr","locations":[{"start":{"line":65,"column":28},"end":{"line":65,"column":62}},{"start":{"line":65,"column":62},"end":{"line":65,"column":null}}],"line":65},"8":{"loc":{"start":{"line":66,"column":6},"end":{"line":68,"column":null}},"type":"if","locations":[{"start":{"line":66,"column":6},"end":{"line":68,"column":null}},{"start":{},"end":{}}],"line":66},"9":{"loc":{"start":{"line":84,"column":6},"end":{"line":91,"column":null}},"type":"if","locations":[{"start":{"line":84,"column":6},"end":{"line":91,"column":null}},{"start":{},"end":{}}],"line":84},"10":{"loc":{"start":{"line":94,"column":6},"end":{"line":101,"column":null}},"type":"if","locations":[{"start":{"line":94,"column":6},"end":{"line":101,"column":null}},{"start":{},"end":{}}],"line":94},"11":{"loc":{"start":{"line":112,"column":6},"end":{"line":114,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":6},"end":{"line":114,"column":null}},{"start":{},"end":{}}],"line":112},"12":{"loc":{"start":{"line":132,"column":6},"end":{"line":134,"column":null}},"type":"if","locations":[{"start":{"line":132,"column":6},"end":{"line":134,"column":null}},{"start":{},"end":{}}],"line":132},"13":{"loc":{"start":{"line":157,"column":6},"end":{"line":164,"column":null}},"type":"if","locations":[{"start":{"line":157,"column":6},"end":{"line":164,"column":null}},{"start":{},"end":{}}],"line":157},"14":{"loc":{"start":{"line":167,"column":6},"end":{"line":174,"column":null}},"type":"if","locations":[{"start":{"line":167,"column":6},"end":{"line":174,"column":null}},{"start":{},"end":{}}],"line":167},"15":{"loc":{"start":{"line":167,"column":10},"end":{"line":167,"column":74}},"type":"binary-expr","locations":[{"start":{"line":167,"column":10},"end":{"line":167,"column":24}},{"start":{"line":167,"column":24},"end":{"line":167,"column":37}},{"start":{"line":167,"column":37},"end":{"line":167,"column":74}}],"line":167},"16":{"loc":{"start":{"line":186,"column":6},"end":{"line":188,"column":null}},"type":"if","locations":[{"start":{"line":186,"column":6},"end":{"line":188,"column":null}},{"start":{},"end":{}}],"line":186},"17":{"loc":{"start":{"line":191,"column":14},"end":{"line":191,"column":null}},"type":"cond-expr","locations":[{"start":{"line":191,"column":41},"end":{"line":191,"column":55}},{"start":{"line":191,"column":55},"end":{"line":191,"column":null}}],"line":191},"18":{"loc":{"start":{"line":207,"column":6},"end":{"line":209,"column":null}},"type":"if","locations":[{"start":{"line":207,"column":6},"end":{"line":209,"column":null}},{"start":{},"end":{}}],"line":207},"19":{"loc":{"start":{"line":232,"column":6},"end":{"line":234,"column":null}},"type":"if","locations":[{"start":{"line":232,"column":6},"end":{"line":234,"column":null}},{"start":{},"end":{}}],"line":232},"20":{"loc":{"start":{"line":255,"column":6},"end":{"line":257,"column":null}},"type":"if","locations":[{"start":{"line":255,"column":6},"end":{"line":257,"column":null}},{"start":{},"end":{}}],"line":255},"21":{"loc":{"start":{"line":260,"column":14},"end":{"line":260,"column":null}},"type":"cond-expr","locations":[{"start":{"line":260,"column":37},"end":{"line":260,"column":51}},{"start":{"line":260,"column":51},"end":{"line":260,"column":null}}],"line":260},"22":{"loc":{"start":{"line":277,"column":6},"end":{"line":279,"column":null}},"type":"if","locations":[{"start":{"line":277,"column":6},"end":{"line":279,"column":null}},{"start":{},"end":{}}],"line":277},"23":{"loc":{"start":{"line":302,"column":6},"end":{"line":304,"column":null}},"type":"if","locations":[{"start":{"line":302,"column":6},"end":{"line":304,"column":null}},{"start":{},"end":{}}],"line":302},"24":{"loc":{"start":{"line":325,"column":6},"end":{"line":327,"column":null}},"type":"if","locations":[{"start":{"line":325,"column":6},"end":{"line":327,"column":null}},{"start":{},"end":{}}],"line":325},"25":{"loc":{"start":{"line":330,"column":14},"end":{"line":330,"column":null}},"type":"cond-expr","locations":[{"start":{"line":330,"column":41},"end":{"line":330,"column":55}},{"start":{"line":330,"column":55},"end":{"line":330,"column":null}}],"line":330},"26":{"loc":{"start":{"line":349,"column":6},"end":{"line":351,"column":null}},"type":"if","locations":[{"start":{"line":349,"column":6},"end":{"line":351,"column":null}},{"start":{},"end":{}}],"line":349},"27":{"loc":{"start":{"line":349,"column":10},"end":{"line":349,"column":44}},"type":"binary-expr","locations":[{"start":{"line":349,"column":10},"end":{"line":349,"column":20}},{"start":{"line":349,"column":20},"end":{"line":349,"column":44}}],"line":349}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":55,"29":55,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":55,"54":55,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":55,"79":55,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":55,"102":55,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0]},"meta":{"lastBranch":28,"lastFunction":27,"lastStatement":125,"seen":{"f:12:8:12:14":0,"s:13:18:13:Infinity":0,"s:14:36:18:Infinity":1,"s:20:4:24:Infinity":2,"f:31:12:31:30":1,"s:32:18:32:Infinity":3,"s:33:22:33:Infinity":4,"s:35:4:48:Infinity":5,"s:35:17:35:33":6,"s:36:19:36:Infinity":7,"s:37:6:47:Infinity":8,"b:38:8:46:Infinity:41:8:46:Infinity":0,"s:38:8:46:Infinity":9,"s:39:10:39:Infinity":10,"s:40:10:40:Infinity":11,"b:41:8:46:Infinity:undefined:undefined:undefined:undefined":1,"s:41:8:46:Infinity":12,"s:42:10:42:Infinity":13,"b:43:10:45:Infinity:undefined:undefined:undefined:undefined":2,"s:43:10:45:Infinity":14,"b:43:14:43:29:43:29:43:43":3,"s:44:12:44:Infinity":15,"s:50:4:50:Infinity":16,"f:53:12:53:Infinity":2,"s:57:22:57:Infinity":17,"b:57:22:57:47:57:47:57:Infinity":4,"s:58:19:58:Infinity":18,"b:58:19:58:58:58:58:58:Infinity":5,"s:60:4:69:Infinity":19,"s:60:17:60:37":20,"s:61:19:61:Infinity":21,"b:62:6:64:Infinity:undefined:undefined:undefined:undefined":6,"s:62:6:64:Infinity":22,"s:63:8:63:Infinity":23,"s:65:28:65:Infinity":24,"b:65:28:65:62:65:62:65:Infinity":7,"b:66:6:68:Infinity:undefined:undefined:undefined:undefined":8,"s:66:6:68:Infinity":25,"s:67:8:67:Infinity":26,"s:71:4:71:Infinity":27,"s:76:22:76:Infinity":28,"s:77:24:77:Infinity":29,"f:79:12:79:27":3,"s:80:36:80:Infinity":30,"s:82:4:102:Infinity":31,"f:82:18:82:19":4,"s:83:26:83:Infinity":32,"b:84:6:91:Infinity:undefined:undefined:undefined:undefined":9,"s:84:6:91:Infinity":33,"s:85:8:90:Infinity":34,"s:93:24:93:Infinity":35,"b:94:6:101:Infinity:undefined:undefined:undefined:undefined":10,"s:94:6:101:Infinity":36,"s:95:8:100:Infinity":37,"s:104:4:104:Infinity":38,"f:107:12:107:27":5,"s:108:36:108:Infinity":39,"s:110:4:122:Infinity":40,"f:110:18:110:19":6,"s:111:20:111:Infinity":41,"b:112:6:114:Infinity:undefined:undefined:undefined:undefined":11,"s:112:6:114:Infinity":42,"s:113:8:113:Infinity":43,"s:116:6:121:Infinity":44,"s:124:4:124:Infinity":45,"f:127:12:127:29":7,"s:128:36:128:Infinity":46,"s:130:4:142:Infinity":47,"f:130:18:130:19":8,"s:131:20:131:Infinity":48,"b:132:6:134:Infinity:undefined:undefined:undefined:undefined":12,"s:132:6:134:Infinity":49,"s:133:8:133:Infinity":50,"s:136:6:141:Infinity":51,"s:144:4:144:Infinity":52,"s:149:22:149:Infinity":53,"s:150:24:150:Infinity":54,"f:152:12:152:27":9,"s:153:36:153:Infinity":55,"s:155:4:175:Infinity":56,"f:155:18:155:19":10,"s:156:21:156:Infinity":57,"b:157:6:164:Infinity:undefined:undefined:undefined:undefined":13,"s:157:6:164:Infinity":58,"s:158:8:163:Infinity":59,"s:166:25:166:Infinity":60,"b:167:6:174:Infinity:undefined:undefined:undefined:undefined":14,"s:167:6:174:Infinity":61,"b:167:10:167:24:167:24:167:37:167:37:167:74":15,"s:168:8:173:Infinity":62,"s:177:4:177:Infinity":63,"f:180:12:180:27":11,"s:181:36:181:Infinity":64,"s:183:4:196:Infinity":65,"f:183:18:183:19":12,"s:185:8:185:Infinity":66,"b:186:6:188:Infinity:undefined:undefined:undefined:undefined":16,"s:186:6:188:Infinity":67,"s:187:8:187:Infinity":68,"s:190:6:195:Infinity":69,"b:191:41:191:55:191:55:191:Infinity":17,"s:198:4:198:Infinity":70,"f:201:12:201:29":13,"s:202:36:202:Infinity":71,"s:204:4:217:Infinity":72,"f:204:18:204:19":14,"s:206:8:206:Infinity":73,"b:207:6:209:Infinity:undefined:undefined:undefined:undefined":18,"s:207:6:209:Infinity":74,"s:208:8:208:Infinity":75,"s:211:6:216:Infinity":76,"s:219:4:219:Infinity":77,"s:224:22:224:Infinity":78,"s:225:24:225:Infinity":79,"f:227:12:227:27":15,"s:228:36:228:Infinity":80,"s:230:4:242:Infinity":81,"f:230:18:230:19":16,"s:231:20:231:Infinity":82,"b:232:6:234:Infinity:undefined:undefined:undefined:undefined":19,"s:232:6:234:Infinity":83,"s:233:8:233:Infinity":84,"s:236:6:241:Infinity":85,"s:244:4:244:Infinity":86,"f:247:12:247:27":17,"s:248:36:248:Infinity":87,"s:250:4:265:Infinity":88,"f:250:18:250:19":18,"s:252:8:254:Infinity":89,"b:255:6:257:Infinity:undefined:undefined:undefined:undefined":20,"s:255:6:257:Infinity":90,"s:256:8:256:Infinity":91,"s:259:6:264:Infinity":92,"b:260:37:260:51:260:51:260:Infinity":21,"s:267:4:267:Infinity":93,"f:270:12:270:29":19,"s:271:36:271:Infinity":94,"s:273:4:287:Infinity":95,"f:273:18:273:19":20,"s:274:20:276:Infinity":96,"b:277:6:279:Infinity:undefined:undefined:undefined:undefined":22,"s:277:6:279:Infinity":97,"s:278:8:278:Infinity":98,"s:281:6:286:Infinity":99,"s:289:4:289:Infinity":100,"s:294:22:294:Infinity":101,"s:295:24:295:Infinity":102,"f:297:12:297:27":21,"s:298:36:298:Infinity":103,"s:300:4:312:Infinity":104,"f:300:18:300:19":22,"s:301:20:301:Infinity":105,"b:302:6:304:Infinity:undefined:undefined:undefined:undefined":23,"s:302:6:304:Infinity":106,"s:303:8:303:Infinity":107,"s:306:6:311:Infinity":108,"s:314:4:314:Infinity":109,"f:317:12:317:27":23,"s:318:36:318:Infinity":110,"s:320:4:335:Infinity":111,"f:320:18:320:19":24,"s:322:8:324:Infinity":112,"b:325:6:327:Infinity:undefined:undefined:undefined:undefined":24,"s:325:6:327:Infinity":113,"s:326:8:326:Infinity":114,"s:329:6:334:Infinity":115,"b:330:41:330:55:330:55:330:Infinity":25,"s:337:4:337:Infinity":116,"f:340:12:340:29":25,"s:341:36:341:Infinity":117,"s:342:21:342:Infinity":118,"s:344:4:359:Infinity":119,"f:344:18:344:19":26,"s:346:8:348:Infinity":120,"b:349:6:351:Infinity:undefined:undefined:undefined:undefined":26,"s:349:6:351:Infinity":121,"b:349:10:349:20:349:20:349:44":27,"s:350:8:350:Infinity":122,"s:353:6:358:Infinity":123,"s:361:4:361:Infinity":124}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/parsers/tree-sitter-parser.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/parsers/tree-sitter-parser.ts","statementMap":{"0":{"start":{"line":22,"column":6},"end":{"line":22,"column":null}},"1":{"start":{"line":28,"column":2},"end":{"line":32,"column":null}},"2":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"3":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"4":{"start":{"line":41,"column":2},"end":{"line":41,"column":null}},"5":{"start":{"line":41,"column":12},"end":{"line":41,"column":null}},"6":{"start":{"line":42,"column":2},"end":{"line":43,"column":null}},"7":{"start":{"line":43,"column":4},"end":{"line":43,"column":null}},"8":{"start":{"line":44,"column":2},"end":{"line":44,"column":null}},"9":{"start":{"line":66,"column":2},"end":{"line":66,"column":null}},"10":{"start":{"line":67,"column":2},"end":{"line":70,"column":null}},"11":{"start":{"line":67,"column":15},"end":{"line":67,"column":18}},"12":{"start":{"line":68,"column":18},"end":{"line":68,"column":null}},"13":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"14":{"start":{"line":69,"column":15},"end":{"line":69,"column":null}},"15":{"start":{"line":75,"column":2},"end":{"line":75,"column":null}},"16":{"start":{"line":89,"column":13},"end":{"line":89,"column":null}},"17":{"start":{"line":91,"column":25},"end":{"line":91,"column":null}},"18":{"start":{"line":95,"column":4},"end":{"line":95,"column":null}},"19":{"start":{"line":95,"column":27},"end":{"line":95,"column":null}},"20":{"start":{"line":96,"column":4},"end":{"line":96,"column":null}},"21":{"start":{"line":98,"column":23},"end":{"line":98,"column":null}},"22":{"start":{"line":99,"column":4},"end":{"line":99,"column":null}},"23":{"start":{"line":99,"column":21},"end":{"line":99,"column":null}},"24":{"start":{"line":101,"column":23},"end":{"line":101,"column":null}},"25":{"start":{"line":102,"column":17},"end":{"line":102,"column":null}},"26":{"start":{"line":103,"column":4},"end":{"line":103,"column":null}},"27":{"start":{"line":103,"column":15},"end":{"line":103,"column":null}},"28":{"start":{"line":105,"column":4},"end":{"line":112,"column":null}},"29":{"start":{"line":106,"column":16},"end":{"line":106,"column":null}},"30":{"start":{"line":107,"column":6},"end":{"line":107,"column":null}},"31":{"start":{"line":108,"column":6},"end":{"line":108,"column":null}},"32":{"start":{"line":109,"column":6},"end":{"line":109,"column":null}},"33":{"start":{"line":111,"column":6},"end":{"line":111,"column":null}},"34":{"start":{"line":116,"column":4},"end":{"line":116,"column":null}},"35":{"start":{"line":120,"column":4},"end":{"line":127,"column":null}},"36":{"start":{"line":122,"column":6},"end":{"line":126,"column":null}},"37":{"start":{"line":129,"column":4},"end":{"line":143,"column":null}},"38":{"start":{"line":130,"column":19},"end":{"line":130,"column":null}},"39":{"start":{"line":131,"column":22},"end":{"line":131,"column":null}},"40":{"start":{"line":132,"column":6},"end":{"line":136,"column":null}},"41":{"start":{"line":138,"column":6},"end":{"line":142,"column":null}},"42":{"start":{"line":153,"column":30},"end":{"line":153,"column":null}},"43":{"start":{"line":154,"column":4},"end":{"line":156,"column":null}},"44":{"start":{"line":155,"column":6},"end":{"line":155,"column":null}},"45":{"start":{"line":155,"column":29},"end":{"line":155,"column":null}},"46":{"start":{"line":157,"column":4},"end":{"line":157,"column":null}},"47":{"start":{"line":165,"column":22},"end":{"line":165,"column":null}},"48":{"start":{"line":166,"column":24},"end":{"line":166,"column":null}},"49":{"start":{"line":167,"column":34},"end":{"line":167,"column":null}},"50":{"start":{"line":170,"column":36},"end":{"line":170,"column":null}},"51":{"start":{"line":172,"column":4},"end":{"line":233,"column":null}},"52":{"start":{"line":173,"column":6},"end":{"line":232,"column":null}},"53":{"start":{"line":176,"column":23},"end":{"line":176,"column":null}},"54":{"start":{"line":177,"column":10},"end":{"line":177,"column":null}},"55":{"start":{"line":177,"column":21},"end":{"line":177,"column":null}},"56":{"start":{"line":178,"column":10},"end":{"line":183,"column":null}},"57":{"start":{"line":184,"column":10},"end":{"line":184,"column":null}},"58":{"start":{"line":187,"column":23},"end":{"line":187,"column":null}},"59":{"start":{"line":188,"column":10},"end":{"line":188,"column":null}},"60":{"start":{"line":188,"column":21},"end":{"line":188,"column":null}},"61":{"start":{"line":189,"column":10},"end":{"line":194,"column":null}},"62":{"start":{"line":195,"column":10},"end":{"line":195,"column":null}},"63":{"start":{"line":199,"column":10},"end":{"line":217,"column":null}},"64":{"start":{"line":200,"column":12},"end":{"line":216,"column":null}},"65":{"start":{"line":204,"column":27},"end":{"line":204,"column":null}},"66":{"start":{"line":205,"column":14},"end":{"line":215,"column":null}},"67":{"start":{"line":207,"column":37},"end":{"line":207,"column":75}},"68":{"start":{"line":209,"column":16},"end":{"line":214,"column":null}},"69":{"start":{"line":218,"column":10},"end":{"line":218,"column":null}},"70":{"start":{"line":221,"column":22},"end":{"line":221,"column":null}},"71":{"start":{"line":222,"column":10},"end":{"line":229,"column":null}},"72":{"start":{"line":223,"column":12},"end":{"line":228,"column":null}},"73":{"start":{"line":230,"column":10},"end":{"line":230,"column":null}},"74":{"start":{"line":235,"column":4},"end":{"line":235,"column":null}},"75":{"start":{"line":243,"column":22},"end":{"line":243,"column":null}},"76":{"start":{"line":244,"column":24},"end":{"line":244,"column":null}},"77":{"start":{"line":245,"column":34},"end":{"line":245,"column":null}},"78":{"start":{"line":248,"column":36},"end":{"line":248,"column":null}},"79":{"start":{"line":250,"column":4},"end":{"line":295,"column":null}},"80":{"start":{"line":251,"column":6},"end":{"line":294,"column":null}},"81":{"start":{"line":254,"column":27},"end":{"line":254,"column":null}},"82":{"start":{"line":255,"column":23},"end":{"line":255,"column":null}},"83":{"start":{"line":256,"column":10},"end":{"line":256,"column":null}},"84":{"start":{"line":256,"column":21},"end":{"line":256,"column":null}},"85":{"start":{"line":257,"column":10},"end":{"line":262,"column":null}},"86":{"start":{"line":263,"column":10},"end":{"line":263,"column":null}},"87":{"start":{"line":266,"column":27},"end":{"line":266,"column":null}},"88":{"start":{"line":267,"column":27},"end":{"line":267,"column":null}},"89":{"start":{"line":268,"column":10},"end":{"line":268,"column":null}},"90":{"start":{"line":268,"column":25},"end":{"line":268,"column":null}},"91":{"start":{"line":269,"column":23},"end":{"line":269,"column":null}},"92":{"start":{"line":270,"column":26},"end":{"line":270,"column":null}},"93":{"start":{"line":271,"column":10},"end":{"line":276,"column":null}},"94":{"start":{"line":277,"column":10},"end":{"line":277,"column":null}},"95":{"start":{"line":281,"column":27},"end":{"line":281,"column":null}},"96":{"start":{"line":282,"column":22},"end":{"line":282,"column":null}},"97":{"start":{"line":283,"column":23},"end":{"line":283,"column":null}},"98":{"start":{"line":284,"column":10},"end":{"line":291,"column":null}},"99":{"start":{"line":285,"column":12},"end":{"line":290,"column":null}},"100":{"start":{"line":292,"column":10},"end":{"line":292,"column":null}},"101":{"start":{"line":297,"column":4},"end":{"line":297,"column":null}},"102":{"start":{"line":305,"column":22},"end":{"line":305,"column":null}},"103":{"start":{"line":306,"column":24},"end":{"line":306,"column":null}},"104":{"start":{"line":307,"column":34},"end":{"line":307,"column":null}},"105":{"start":{"line":310,"column":36},"end":{"line":310,"column":null}},"106":{"start":{"line":312,"column":4},"end":{"line":365,"column":null}},"107":{"start":{"line":313,"column":6},"end":{"line":364,"column":null}},"108":{"start":{"line":315,"column":23},"end":{"line":315,"column":null}},"109":{"start":{"line":316,"column":10},"end":{"line":316,"column":null}},"110":{"start":{"line":316,"column":21},"end":{"line":316,"column":null}},"111":{"start":{"line":317,"column":10},"end":{"line":322,"column":null}},"112":{"start":{"line":323,"column":10},"end":{"line":323,"column":null}},"113":{"start":{"line":327,"column":23},"end":{"line":327,"column":null}},"114":{"start":{"line":328,"column":10},"end":{"line":328,"column":null}},"115":{"start":{"line":328,"column":21},"end":{"line":328,"column":null}},"116":{"start":{"line":329,"column":10},"end":{"line":334,"column":null}},"117":{"start":{"line":335,"column":10},"end":{"line":335,"column":null}},"118":{"start":{"line":338,"column":23},"end":{"line":338,"column":null}},"119":{"start":{"line":339,"column":10},"end":{"line":339,"column":null}},"120":{"start":{"line":339,"column":21},"end":{"line":339,"column":null}},"121":{"start":{"line":340,"column":10},"end":{"line":345,"column":null}},"122":{"start":{"line":346,"column":10},"end":{"line":346,"column":null}},"123":{"start":{"line":350,"column":22},"end":{"line":350,"column":null}},"124":{"start":{"line":351,"column":10},"end":{"line":361,"column":null}},"125":{"start":{"line":352,"column":25},"end":{"line":352,"column":null}},"126":{"start":{"line":353,"column":12},"end":{"line":360,"column":null}},"127":{"start":{"line":354,"column":14},"end":{"line":359,"column":null}},"128":{"start":{"line":362,"column":10},"end":{"line":362,"column":null}},"129":{"start":{"line":367,"column":4},"end":{"line":367,"column":null}},"130":{"start":{"line":375,"column":22},"end":{"line":375,"column":null}},"131":{"start":{"line":376,"column":24},"end":{"line":376,"column":null}},"132":{"start":{"line":377,"column":34},"end":{"line":377,"column":null}},"133":{"start":{"line":379,"column":37},"end":{"line":387,"column":null}},"134":{"start":{"line":390,"column":36},"end":{"line":390,"column":null}},"135":{"start":{"line":392,"column":4},"end":{"line":438,"column":null}},"136":{"start":{"line":393,"column":6},"end":{"line":437,"column":null}},"137":{"start":{"line":398,"column":27},"end":{"line":398,"column":null}},"138":{"start":{"line":399,"column":10},"end":{"line":399,"column":null}},"139":{"start":{"line":399,"column":25},"end":{"line":399,"column":null}},"140":{"start":{"line":400,"column":10},"end":{"line":405,"column":null}},"141":{"start":{"line":406,"column":10},"end":{"line":406,"column":null}},"142":{"start":{"line":410,"column":27},"end":{"line":410,"column":null}},"143":{"start":{"line":411,"column":10},"end":{"line":411,"column":null}},"144":{"start":{"line":411,"column":25},"end":{"line":411,"column":null}},"145":{"start":{"line":412,"column":10},"end":{"line":412,"column":null}},"146":{"start":{"line":412,"column":64},"end":{"line":412,"column":null}},"147":{"start":{"line":413,"column":10},"end":{"line":418,"column":null}},"148":{"start":{"line":419,"column":10},"end":{"line":419,"column":null}},"149":{"start":{"line":423,"column":23},"end":{"line":426,"column":null}},"150":{"start":{"line":427,"column":10},"end":{"line":434,"column":null}},"151":{"start":{"line":428,"column":12},"end":{"line":433,"column":null}},"152":{"start":{"line":435,"column":10},"end":{"line":435,"column":null}},"153":{"start":{"line":440,"column":4},"end":{"line":440,"column":null}},"154":{"start":{"line":449,"column":42},"end":{"line":449,"column":null}},"155":{"start":{"line":452,"column":2},"end":{"line":452,"column":null}},"156":{"start":{"line":452,"column":16},"end":{"line":452,"column":null}},"157":{"start":{"line":453,"column":2},"end":{"line":458,"column":null}},"158":{"start":{"line":459,"column":2},"end":{"line":459,"column":null}},"159":{"start":{"line":467,"column":18},"end":{"line":467,"column":null}},"160":{"start":{"line":468,"column":42},"end":{"line":468,"column":null}},"161":{"start":{"line":469,"column":2},"end":{"line":471,"column":null}},"162":{"start":{"line":470,"column":4},"end":{"line":470,"column":null}},"163":{"start":{"line":472,"column":2},"end":{"line":472,"column":null}}},"fnMap":{"0":{"name":"tryRequire","decl":{"start":{"line":27,"column":9},"end":{"line":27,"column":20}},"loc":{"start":{"line":27,"column":43},"end":{"line":33,"column":null}},"line":27},"1":{"name":"resolveLanguage","decl":{"start":{"line":40,"column":9},"end":{"line":40,"column":25}},"loc":{"start":{"line":40,"column":48},"end":{"line":45,"column":null}},"line":40},"2":{"name":"walk","decl":{"start":{"line":65,"column":9},"end":{"line":65,"column":14}},"loc":{"start":{"line":65,"column":64},"end":{"line":71,"column":null}},"line":65},"3":{"name":"fieldText","decl":{"start":{"line":74,"column":9},"end":{"line":74,"column":19}},"loc":{"start":{"line":74,"column":56},"end":{"line":76,"column":null}},"line":74},"4":{"name":"(anonymous_4)","decl":{"start":{"line":94,"column":12},"end":{"line":94,"column":34}},"loc":{"start":{"line":94,"column":34},"end":{"line":113,"column":null}},"line":94},"5":{"name":"(anonymous_5)","decl":{"start":{"line":115,"column":6},"end":{"line":115,"column":29}},"loc":{"start":{"line":115,"column":29},"end":{"line":117,"column":null}},"line":115},"6":{"name":"(anonymous_6)","decl":{"start":{"line":119,"column":8},"end":{"line":119,"column":14}},"loc":{"start":{"line":119,"column":71},"end":{"line":144,"column":null}},"line":119},"7":{"name":"(anonymous_7)","decl":{"start":{"line":152,"column":12},"end":{"line":152,"column":20}},"loc":{"start":{"line":152,"column":64},"end":{"line":158,"column":null}},"line":152},"8":{"name":"(anonymous_8)","decl":{"start":{"line":154,"column":15},"end":{"line":154,"column":16}},"loc":{"start":{"line":154,"column":22},"end":{"line":156,"column":5}},"line":154},"9":{"name":"(anonymous_9)","decl":{"start":{"line":169,"column":12},"end":{"line":169,"column":27}},"loc":{"start":{"line":169,"column":74},"end":{"line":236,"column":null}},"line":169},"10":{"name":"(anonymous_10)","decl":{"start":{"line":172,"column":15},"end":{"line":172,"column":16}},"loc":{"start":{"line":172,"column":25},"end":{"line":233,"column":5}},"line":172},"11":{"name":"(anonymous_11)","decl":{"start":{"line":199,"column":21},"end":{"line":199,"column":22}},"loc":{"start":{"line":199,"column":32},"end":{"line":217,"column":11}},"line":199},"12":{"name":"(anonymous_12)","decl":{"start":{"line":207,"column":30},"end":{"line":207,"column":31}},"loc":{"start":{"line":207,"column":37},"end":{"line":207,"column":75}},"line":207},"13":{"name":"(anonymous_13)","decl":{"start":{"line":247,"column":12},"end":{"line":247,"column":27}},"loc":{"start":{"line":247,"column":74},"end":{"line":298,"column":null}},"line":247},"14":{"name":"(anonymous_14)","decl":{"start":{"line":250,"column":15},"end":{"line":250,"column":16}},"loc":{"start":{"line":250,"column":25},"end":{"line":295,"column":5}},"line":250},"15":{"name":"(anonymous_15)","decl":{"start":{"line":309,"column":12},"end":{"line":309,"column":27}},"loc":{"start":{"line":309,"column":74},"end":{"line":368,"column":null}},"line":309},"16":{"name":"(anonymous_16)","decl":{"start":{"line":312,"column":15},"end":{"line":312,"column":16}},"loc":{"start":{"line":312,"column":25},"end":{"line":365,"column":5}},"line":312},"17":{"name":"(anonymous_17)","decl":{"start":{"line":389,"column":12},"end":{"line":389,"column":27}},"loc":{"start":{"line":389,"column":74},"end":{"line":441,"column":null}},"line":389},"18":{"name":"(anonymous_18)","decl":{"start":{"line":392,"column":15},"end":{"line":392,"column":16}},"loc":{"start":{"line":392,"column":25},"end":{"line":438,"column":5}},"line":392},"19":{"name":"getTreeSitterParsers","decl":{"start":{"line":451,"column":16},"end":{"line":451,"column":59}},"loc":{"start":{"line":451,"column":59},"end":{"line":460,"column":null}},"line":451},"20":{"name":"checkTreeSitterAvailability","decl":{"start":{"line":466,"column":16},"end":{"line":466,"column":71}},"loc":{"start":{"line":466,"column":71},"end":{"line":473,"column":null}},"line":466}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":2},"end":{"line":41,"column":null}},"type":"if","locations":[{"start":{"line":41,"column":2},"end":{"line":41,"column":null}},{"start":{},"end":{}}],"line":41},"1":{"loc":{"start":{"line":42,"column":2},"end":{"line":43,"column":null}},"type":"if","locations":[{"start":{"line":42,"column":2},"end":{"line":43,"column":null}},{"start":{},"end":{}}],"line":42},"2":{"loc":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"type":"if","locations":[{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},{"start":{},"end":{}}],"line":69},"3":{"loc":{"start":{"line":75,"column":9},"end":{"line":75,"column":null}},"type":"binary-expr","locations":[{"start":{"line":75,"column":9},"end":{"line":75,"column":48}},{"start":{"line":75,"column":48},"end":{"line":75,"column":null}}],"line":75},"4":{"loc":{"start":{"line":95,"column":4},"end":{"line":95,"column":null}},"type":"if","locations":[{"start":{"line":95,"column":4},"end":{"line":95,"column":null}},{"start":{},"end":{}}],"line":95},"5":{"loc":{"start":{"line":99,"column":4},"end":{"line":99,"column":null}},"type":"if","locations":[{"start":{"line":99,"column":4},"end":{"line":99,"column":null}},{"start":{},"end":{}}],"line":99},"6":{"loc":{"start":{"line":103,"column":4},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":4},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":103},"7":{"loc":{"start":{"line":120,"column":4},"end":{"line":127,"column":null}},"type":"if","locations":[{"start":{"line":120,"column":4},"end":{"line":127,"column":null}},{"start":{},"end":{}}],"line":120},"8":{"loc":{"start":{"line":120,"column":8},"end":{"line":120,"column":45}},"type":"binary-expr","locations":[{"start":{"line":120,"column":8},"end":{"line":120,"column":30}},{"start":{"line":120,"column":30},"end":{"line":120,"column":45}}],"line":120},"9":{"loc":{"start":{"line":155,"column":6},"end":{"line":155,"column":null}},"type":"if","locations":[{"start":{"line":155,"column":6},"end":{"line":155,"column":null}},{"start":{},"end":{}}],"line":155},"10":{"loc":{"start":{"line":173,"column":6},"end":{"line":232,"column":null}},"type":"switch","locations":[{"start":{"line":174,"column":8},"end":{"line":174,"column":null}},{"start":{"line":175,"column":8},"end":{"line":185,"column":null}},{"start":{"line":186,"column":8},"end":{"line":196,"column":null}},{"start":{"line":197,"column":8},"end":{"line":219,"column":null}},{"start":{"line":220,"column":8},"end":{"line":231,"column":null}}],"line":173},"11":{"loc":{"start":{"line":177,"column":10},"end":{"line":177,"column":null}},"type":"if","locations":[{"start":{"line":177,"column":10},"end":{"line":177,"column":null}},{"start":{},"end":{}}],"line":177},"12":{"loc":{"start":{"line":188,"column":10},"end":{"line":188,"column":null}},"type":"if","locations":[{"start":{"line":188,"column":10},"end":{"line":188,"column":null}},{"start":{},"end":{}}],"line":188},"13":{"loc":{"start":{"line":200,"column":12},"end":{"line":216,"column":null}},"type":"if","locations":[{"start":{"line":200,"column":12},"end":{"line":216,"column":null}},{"start":{},"end":{}}],"line":200},"14":{"loc":{"start":{"line":201,"column":14},"end":{"line":202,"column":null}},"type":"binary-expr","locations":[{"start":{"line":201,"column":14},"end":{"line":201,"column":null}},{"start":{"line":202,"column":14},"end":{"line":202,"column":null}}],"line":201},"15":{"loc":{"start":{"line":204,"column":27},"end":{"line":204,"column":null}},"type":"binary-expr","locations":[{"start":{"line":204,"column":27},"end":{"line":204,"column":68}},{"start":{"line":204,"column":68},"end":{"line":204,"column":null}}],"line":204},"16":{"loc":{"start":{"line":205,"column":14},"end":{"line":215,"column":null}},"type":"if","locations":[{"start":{"line":205,"column":14},"end":{"line":215,"column":null}},{"start":{},"end":{}}],"line":205},"17":{"loc":{"start":{"line":206,"column":16},"end":{"line":207,"column":null}},"type":"binary-expr","locations":[{"start":{"line":206,"column":16},"end":{"line":206,"column":null}},{"start":{"line":207,"column":16},"end":{"line":207,"column":null}}],"line":206},"18":{"loc":{"start":{"line":207,"column":37},"end":{"line":207,"column":75}},"type":"binary-expr","locations":[{"start":{"line":207,"column":37},"end":{"line":207,"column":56}},{"start":{"line":207,"column":56},"end":{"line":207,"column":75}}],"line":207},"19":{"loc":{"start":{"line":222,"column":10},"end":{"line":229,"column":null}},"type":"if","locations":[{"start":{"line":222,"column":10},"end":{"line":229,"column":null}},{"start":{},"end":{}}],"line":222},"20":{"loc":{"start":{"line":251,"column":6},"end":{"line":294,"column":null}},"type":"switch","locations":[{"start":{"line":252,"column":8},"end":{"line":252,"column":null}},{"start":{"line":253,"column":8},"end":{"line":264,"column":null}},{"start":{"line":265,"column":8},"end":{"line":278,"column":null}},{"start":{"line":279,"column":8},"end":{"line":293,"column":null}}],"line":251},"21":{"loc":{"start":{"line":255,"column":23},"end":{"line":255,"column":null}},"type":"binary-expr","locations":[{"start":{"line":255,"column":23},"end":{"line":255,"column":41}},{"start":{"line":255,"column":41},"end":{"line":255,"column":null}}],"line":255},"22":{"loc":{"start":{"line":256,"column":10},"end":{"line":256,"column":null}},"type":"if","locations":[{"start":{"line":256,"column":10},"end":{"line":256,"column":null}},{"start":{},"end":{}}],"line":256},"23":{"loc":{"start":{"line":268,"column":10},"end":{"line":268,"column":null}},"type":"if","locations":[{"start":{"line":268,"column":10},"end":{"line":268,"column":null}},{"start":{},"end":{}}],"line":268},"24":{"loc":{"start":{"line":270,"column":26},"end":{"line":270,"column":null}},"type":"cond-expr","locations":[{"start":{"line":270,"column":54},"end":{"line":270,"column":68}},{"start":{"line":270,"column":68},"end":{"line":270,"column":null}}],"line":270},"25":{"loc":{"start":{"line":281,"column":27},"end":{"line":281,"column":null}},"type":"binary-expr","locations":[{"start":{"line":281,"column":27},"end":{"line":281,"column":61}},{"start":{"line":281,"column":61},"end":{"line":281,"column":null}}],"line":281},"26":{"loc":{"start":{"line":282,"column":22},"end":{"line":282,"column":null}},"type":"binary-expr","locations":[{"start":{"line":282,"column":22},"end":{"line":282,"column":40}},{"start":{"line":282,"column":40},"end":{"line":282,"column":null}}],"line":282},"27":{"loc":{"start":{"line":284,"column":10},"end":{"line":291,"column":null}},"type":"if","locations":[{"start":{"line":284,"column":10},"end":{"line":291,"column":null}},{"start":{},"end":{}}],"line":284},"28":{"loc":{"start":{"line":313,"column":6},"end":{"line":364,"column":null}},"type":"switch","locations":[{"start":{"line":314,"column":8},"end":{"line":324,"column":null}},{"start":{"line":325,"column":8},"end":{"line":325,"column":null}},{"start":{"line":326,"column":8},"end":{"line":336,"column":null}},{"start":{"line":337,"column":8},"end":{"line":347,"column":null}},{"start":{"line":348,"column":8},"end":{"line":363,"column":null}}],"line":313},"29":{"loc":{"start":{"line":316,"column":10},"end":{"line":316,"column":null}},"type":"if","locations":[{"start":{"line":316,"column":10},"end":{"line":316,"column":null}},{"start":{},"end":{}}],"line":316},"30":{"loc":{"start":{"line":328,"column":10},"end":{"line":328,"column":null}},"type":"if","locations":[{"start":{"line":328,"column":10},"end":{"line":328,"column":null}},{"start":{},"end":{}}],"line":328},"31":{"loc":{"start":{"line":339,"column":10},"end":{"line":339,"column":null}},"type":"if","locations":[{"start":{"line":339,"column":10},"end":{"line":339,"column":null}},{"start":{},"end":{}}],"line":339},"32":{"loc":{"start":{"line":351,"column":10},"end":{"line":361,"column":null}},"type":"if","locations":[{"start":{"line":351,"column":10},"end":{"line":361,"column":null}},{"start":{},"end":{}}],"line":351},"33":{"loc":{"start":{"line":353,"column":12},"end":{"line":360,"column":null}},"type":"if","locations":[{"start":{"line":353,"column":12},"end":{"line":360,"column":null}},{"start":{},"end":{}}],"line":353},"34":{"loc":{"start":{"line":393,"column":6},"end":{"line":437,"column":null}},"type":"switch","locations":[{"start":{"line":394,"column":8},"end":{"line":394,"column":null}},{"start":{"line":395,"column":8},"end":{"line":395,"column":null}},{"start":{"line":396,"column":8},"end":{"line":396,"column":null}},{"start":{"line":397,"column":8},"end":{"line":407,"column":null}},{"start":{"line":408,"column":8},"end":{"line":408,"column":null}},{"start":{"line":409,"column":8},"end":{"line":420,"column":null}},{"start":{"line":421,"column":8},"end":{"line":436,"column":null}}],"line":393},"35":{"loc":{"start":{"line":399,"column":10},"end":{"line":399,"column":null}},"type":"if","locations":[{"start":{"line":399,"column":10},"end":{"line":399,"column":null}},{"start":{},"end":{}}],"line":399},"36":{"loc":{"start":{"line":401,"column":18},"end":{"line":401,"column":null}},"type":"cond-expr","locations":[{"start":{"line":401,"column":58},"end":{"line":401,"column":72}},{"start":{"line":401,"column":72},"end":{"line":401,"column":null}}],"line":401},"37":{"loc":{"start":{"line":411,"column":10},"end":{"line":411,"column":null}},"type":"if","locations":[{"start":{"line":411,"column":10},"end":{"line":411,"column":null}},{"start":{},"end":{}}],"line":411},"38":{"loc":{"start":{"line":412,"column":10},"end":{"line":412,"column":null}},"type":"if","locations":[{"start":{"line":412,"column":10},"end":{"line":412,"column":null}},{"start":{},"end":{}}],"line":412},"39":{"loc":{"start":{"line":427,"column":10},"end":{"line":434,"column":null}},"type":"if","locations":[{"start":{"line":427,"column":10},"end":{"line":434,"column":null}},{"start":{},"end":{}}],"line":427},"40":{"loc":{"start":{"line":452,"column":2},"end":{"line":452,"column":null}},"type":"if","locations":[{"start":{"line":452,"column":2},"end":{"line":452,"column":null}},{"start":{},"end":{}}],"line":452}},"s":{"0":3,"1":12,"2":12,"3":12,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":12,"17":12,"18":220,"19":208,"20":12,"21":12,"22":12,"23":12,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":220,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":3,"48":3,"49":3,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":3,"76":3,"77":3,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":3,"103":3,"104":3,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":0,"127":0,"128":0,"129":0,"130":6,"131":6,"132":6,"133":6,"134":0,"135":0,"136":0,"137":0,"138":0,"139":0,"140":0,"141":0,"142":0,"143":0,"144":0,"145":0,"146":0,"147":0,"148":0,"149":0,"150":0,"151":0,"152":0,"153":0,"154":3,"155":110,"156":107,"157":3,"158":3,"159":55,"160":55,"161":55,"162":220,"163":55},"f":{"0":12,"1":0,"2":0,"3":0,"4":220,"5":220,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":110,"20":55},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[208,12],"5":[12,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0,0,0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0,0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0,0,0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0,0,0,0,0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[107,3]},"meta":{"lastBranch":41,"lastFunction":21,"lastStatement":164,"seen":{"s:22:6:22:Infinity":0,"f:27:9:27:20":0,"s:28:2:32:Infinity":1,"s:29:4:29:Infinity":2,"s:31:4:31:Infinity":3,"f:40:9:40:25":1,"b:41:2:41:Infinity:undefined:undefined:undefined:undefined":0,"s:41:2:41:Infinity":4,"s:41:12:41:Infinity":5,"b:42:2:43:Infinity:undefined:undefined:undefined:undefined":1,"s:42:2:43:Infinity":6,"s:43:4:43:Infinity":7,"s:44:2:44:Infinity":8,"f:65:9:65:14":2,"s:66:2:66:Infinity":9,"s:67:2:70:Infinity":10,"s:67:15:67:18":11,"s:68:18:68:Infinity":12,"b:69:4:69:Infinity:undefined:undefined:undefined:undefined":2,"s:69:4:69:Infinity":13,"s:69:15:69:Infinity":14,"f:74:9:74:19":3,"s:75:2:75:Infinity":15,"b:75:9:75:48:75:48:75:Infinity":3,"s:89:13:89:Infinity":16,"s:91:25:91:Infinity":17,"f:94:12:94:34":4,"b:95:4:95:Infinity:undefined:undefined:undefined:undefined":4,"s:95:4:95:Infinity":18,"s:95:27:95:Infinity":19,"s:96:4:96:Infinity":20,"s:98:23:98:Infinity":21,"b:99:4:99:Infinity:undefined:undefined:undefined:undefined":5,"s:99:4:99:Infinity":22,"s:99:21:99:Infinity":23,"s:101:23:101:Infinity":24,"s:102:17:102:Infinity":25,"b:103:4:103:Infinity:undefined:undefined:undefined:undefined":6,"s:103:4:103:Infinity":26,"s:103:15:103:Infinity":27,"s:105:4:112:Infinity":28,"s:106:16:106:Infinity":29,"s:107:6:107:Infinity":30,"s:108:6:108:Infinity":31,"s:109:6:109:Infinity":32,"s:111:6:111:Infinity":33,"f:115:6:115:29":5,"s:116:4:116:Infinity":34,"f:119:8:119:14":6,"b:120:4:127:Infinity:undefined:undefined:undefined:undefined":7,"s:120:4:127:Infinity":35,"b:120:8:120:30:120:30:120:45":8,"s:122:6:126:Infinity":36,"s:129:4:143:Infinity":37,"s:130:19:130:Infinity":38,"s:131:22:131:Infinity":39,"s:132:6:136:Infinity":40,"s:138:6:142:Infinity":41,"f:152:12:152:20":7,"s:153:30:153:Infinity":42,"s:154:4:156:Infinity":43,"f:154:15:154:16":8,"b:155:6:155:Infinity:undefined:undefined:undefined:undefined":9,"s:155:6:155:Infinity":44,"s:155:29:155:Infinity":45,"s:157:4:157:Infinity":46,"s:165:22:165:Infinity":47,"s:166:24:166:Infinity":48,"s:167:34:167:Infinity":49,"f:169:12:169:27":9,"s:170:36:170:Infinity":50,"s:172:4:233:Infinity":51,"f:172:15:172:16":10,"b:174:8:174:Infinity:175:8:185:Infinity:186:8:196:Infinity:197:8:219:Infinity:220:8:231:Infinity":10,"s:173:6:232:Infinity":52,"s:176:23:176:Infinity":53,"b:177:10:177:Infinity:undefined:undefined:undefined:undefined":11,"s:177:10:177:Infinity":54,"s:177:21:177:Infinity":55,"s:178:10:183:Infinity":56,"s:184:10:184:Infinity":57,"s:187:23:187:Infinity":58,"b:188:10:188:Infinity:undefined:undefined:undefined:undefined":12,"s:188:10:188:Infinity":59,"s:188:21:188:Infinity":60,"s:189:10:194:Infinity":61,"s:195:10:195:Infinity":62,"s:199:10:217:Infinity":63,"f:199:21:199:22":11,"b:200:12:216:Infinity:undefined:undefined:undefined:undefined":13,"s:200:12:216:Infinity":64,"b:201:14:201:Infinity:202:14:202:Infinity":14,"s:204:27:204:Infinity":65,"b:204:27:204:68:204:68:204:Infinity":15,"b:205:14:215:Infinity:undefined:undefined:undefined:undefined":16,"s:205:14:215:Infinity":66,"b:206:16:206:Infinity:207:16:207:Infinity":17,"f:207:30:207:31":12,"s:207:37:207:75":67,"b:207:37:207:56:207:56:207:75":18,"s:209:16:214:Infinity":68,"s:218:10:218:Infinity":69,"s:221:22:221:Infinity":70,"b:222:10:229:Infinity:undefined:undefined:undefined:undefined":19,"s:222:10:229:Infinity":71,"s:223:12:228:Infinity":72,"s:230:10:230:Infinity":73,"s:235:4:235:Infinity":74,"s:243:22:243:Infinity":75,"s:244:24:244:Infinity":76,"s:245:34:245:Infinity":77,"f:247:12:247:27":13,"s:248:36:248:Infinity":78,"s:250:4:295:Infinity":79,"f:250:15:250:16":14,"b:252:8:252:Infinity:253:8:264:Infinity:265:8:278:Infinity:279:8:293:Infinity":20,"s:251:6:294:Infinity":80,"s:254:27:254:Infinity":81,"s:255:23:255:Infinity":82,"b:255:23:255:41:255:41:255:Infinity":21,"b:256:10:256:Infinity:undefined:undefined:undefined:undefined":22,"s:256:10:256:Infinity":83,"s:256:21:256:Infinity":84,"s:257:10:262:Infinity":85,"s:263:10:263:Infinity":86,"s:266:27:266:Infinity":87,"s:267:27:267:Infinity":88,"b:268:10:268:Infinity:undefined:undefined:undefined:undefined":23,"s:268:10:268:Infinity":89,"s:268:25:268:Infinity":90,"s:269:23:269:Infinity":91,"s:270:26:270:Infinity":92,"b:270:54:270:68:270:68:270:Infinity":24,"s:271:10:276:Infinity":93,"s:277:10:277:Infinity":94,"s:281:27:281:Infinity":95,"b:281:27:281:61:281:61:281:Infinity":25,"s:282:22:282:Infinity":96,"b:282:22:282:40:282:40:282:Infinity":26,"s:283:23:283:Infinity":97,"b:284:10:291:Infinity:undefined:undefined:undefined:undefined":27,"s:284:10:291:Infinity":98,"s:285:12:290:Infinity":99,"s:292:10:292:Infinity":100,"s:297:4:297:Infinity":101,"s:305:22:305:Infinity":102,"s:306:24:306:Infinity":103,"s:307:34:307:Infinity":104,"f:309:12:309:27":15,"s:310:36:310:Infinity":105,"s:312:4:365:Infinity":106,"f:312:15:312:16":16,"b:314:8:324:Infinity:325:8:325:Infinity:326:8:336:Infinity:337:8:347:Infinity:348:8:363:Infinity":28,"s:313:6:364:Infinity":107,"s:315:23:315:Infinity":108,"b:316:10:316:Infinity:undefined:undefined:undefined:undefined":29,"s:316:10:316:Infinity":109,"s:316:21:316:Infinity":110,"s:317:10:322:Infinity":111,"s:323:10:323:Infinity":112,"s:327:23:327:Infinity":113,"b:328:10:328:Infinity:undefined:undefined:undefined:undefined":30,"s:328:10:328:Infinity":114,"s:328:21:328:Infinity":115,"s:329:10:334:Infinity":116,"s:335:10:335:Infinity":117,"s:338:23:338:Infinity":118,"b:339:10:339:Infinity:undefined:undefined:undefined:undefined":31,"s:339:10:339:Infinity":119,"s:339:21:339:Infinity":120,"s:340:10:345:Infinity":121,"s:346:10:346:Infinity":122,"s:350:22:350:Infinity":123,"b:351:10:361:Infinity:undefined:undefined:undefined:undefined":32,"s:351:10:361:Infinity":124,"s:352:25:352:Infinity":125,"b:353:12:360:Infinity:undefined:undefined:undefined:undefined":33,"s:353:12:360:Infinity":126,"s:354:14:359:Infinity":127,"s:362:10:362:Infinity":128,"s:367:4:367:Infinity":129,"s:375:22:375:Infinity":130,"s:376:24:376:Infinity":131,"s:377:34:377:Infinity":132,"s:379:37:387:Infinity":133,"f:389:12:389:27":17,"s:390:36:390:Infinity":134,"s:392:4:438:Infinity":135,"f:392:15:392:16":18,"b:394:8:394:Infinity:395:8:395:Infinity:396:8:396:Infinity:397:8:407:Infinity:408:8:408:Infinity:409:8:420:Infinity:421:8:436:Infinity":34,"s:393:6:437:Infinity":136,"s:398:27:398:Infinity":137,"b:399:10:399:Infinity:undefined:undefined:undefined:undefined":35,"s:399:10:399:Infinity":138,"s:399:25:399:Infinity":139,"s:400:10:405:Infinity":140,"b:401:58:401:72:401:72:401:Infinity":36,"s:406:10:406:Infinity":141,"s:410:27:410:Infinity":142,"b:411:10:411:Infinity:undefined:undefined:undefined:undefined":37,"s:411:10:411:Infinity":143,"s:411:25:411:Infinity":144,"b:412:10:412:Infinity:undefined:undefined:undefined:undefined":38,"s:412:10:412:Infinity":145,"s:412:64:412:Infinity":146,"s:413:10:418:Infinity":147,"s:419:10:419:Infinity":148,"s:423:23:426:Infinity":149,"b:427:10:434:Infinity:undefined:undefined:undefined:undefined":39,"s:427:10:434:Infinity":150,"s:428:12:433:Infinity":151,"s:435:10:435:Infinity":152,"s:440:4:440:Infinity":153,"s:449:42:449:Infinity":154,"f:451:16:451:59":19,"b:452:2:452:Infinity:undefined:undefined:undefined:undefined":40,"s:452:2:452:Infinity":155,"s:452:16:452:Infinity":156,"s:453:2:458:Infinity":157,"s:459:2:459:Infinity":158,"f:466:16:466:71":20,"s:467:18:467:Infinity":159,"s:468:42:468:Infinity":160,"s:469:2:471:Infinity":161,"s:470:4:470:Infinity":162,"s:472:2:472:Infinity":163}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/parsers/tree-sitter-typescript-parser.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/parsers/tree-sitter-typescript-parser.ts","statementMap":{"0":{"start":{"line":32,"column":6},"end":{"line":32,"column":null}},"1":{"start":{"line":38,"column":2},"end":{"line":42,"column":null}},"2":{"start":{"line":39,"column":4},"end":{"line":39,"column":null}},"3":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"4":{"start":{"line":50,"column":14},"end":{"line":50,"column":null}},"5":{"start":{"line":51,"column":2},"end":{"line":51,"column":null}},"6":{"start":{"line":51,"column":12},"end":{"line":51,"column":null}},"7":{"start":{"line":52,"column":2},"end":{"line":52,"column":null}},"8":{"start":{"line":52,"column":43},"end":{"line":52,"column":null}},"9":{"start":{"line":54,"column":2},"end":{"line":54,"column":null}},"10":{"start":{"line":64,"column":16},"end":{"line":64,"column":null}},"11":{"start":{"line":65,"column":2},"end":{"line":67,"column":null}},"12":{"start":{"line":66,"column":4},"end":{"line":66,"column":null}},"13":{"start":{"line":69,"column":19},"end":{"line":69,"column":null}},"14":{"start":{"line":70,"column":2},"end":{"line":70,"column":null}},"15":{"start":{"line":70,"column":17},"end":{"line":70,"column":null}},"16":{"start":{"line":71,"column":15},"end":{"line":71,"column":null}},"17":{"start":{"line":72,"column":2},"end":{"line":72,"column":null}},"18":{"start":{"line":72,"column":13},"end":{"line":72,"column":null}},"19":{"start":{"line":73,"column":2},"end":{"line":73,"column":null}},"20":{"start":{"line":97,"column":17},"end":{"line":97,"column":null}},"21":{"start":{"line":98,"column":2},"end":{"line":107,"column":null}},"22":{"start":{"line":103,"column":21},"end":{"line":103,"column":null}},"23":{"start":{"line":104,"column":4},"end":{"line":106,"column":null}},"24":{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},"25":{"start":{"line":108,"column":2},"end":{"line":108,"column":null}},"26":{"start":{"line":109,"column":2},"end":{"line":112,"column":null}},"27":{"start":{"line":109,"column":15},"end":{"line":109,"column":18}},"28":{"start":{"line":110,"column":18},"end":{"line":110,"column":null}},"29":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},"30":{"start":{"line":111,"column":15},"end":{"line":111,"column":null}},"31":{"start":{"line":119,"column":34},"end":{"line":119,"column":null}},"32":{"start":{"line":121,"column":2},"end":{"line":263,"column":null}},"33":{"start":{"line":122,"column":4},"end":{"line":262,"column":null}},"34":{"start":{"line":126,"column":25},"end":{"line":126,"column":null}},"35":{"start":{"line":127,"column":8},"end":{"line":127,"column":null}},"36":{"start":{"line":127,"column":29},"end":{"line":127,"column":null}},"37":{"start":{"line":128,"column":8},"end":{"line":138,"column":null}},"38":{"start":{"line":139,"column":8},"end":{"line":139,"column":null}},"39":{"start":{"line":146,"column":8},"end":{"line":165,"column":null}},"40":{"start":{"line":147,"column":10},"end":{"line":147,"column":null}},"41":{"start":{"line":147,"column":57},"end":{"line":147,"column":null}},"42":{"start":{"line":148,"column":27},"end":{"line":148,"column":null}},"43":{"start":{"line":149,"column":24},"end":{"line":149,"column":null}},"44":{"start":{"line":150,"column":10},"end":{"line":150,"column":null}},"45":{"start":{"line":150,"column":41},"end":{"line":150,"column":null}},"46":{"start":{"line":151,"column":10},"end":{"line":164,"column":null}},"47":{"start":{"line":156,"column":12},"end":{"line":163,"column":null}},"48":{"start":{"line":166,"column":8},"end":{"line":166,"column":null}},"49":{"start":{"line":172,"column":25},"end":{"line":172,"column":null}},"50":{"start":{"line":173,"column":8},"end":{"line":173,"column":null}},"51":{"start":{"line":173,"column":29},"end":{"line":173,"column":null}},"52":{"start":{"line":174,"column":27},"end":{"line":174,"column":null}},"53":{"start":{"line":176,"column":8},"end":{"line":176,"column":null}},"54":{"start":{"line":176,"column":42},"end":{"line":176,"column":null}},"55":{"start":{"line":177,"column":8},"end":{"line":185,"column":null}},"56":{"start":{"line":186,"column":8},"end":{"line":186,"column":null}},"57":{"start":{"line":192,"column":25},"end":{"line":192,"column":null}},"58":{"start":{"line":193,"column":8},"end":{"line":193,"column":null}},"59":{"start":{"line":193,"column":29},"end":{"line":193,"column":null}},"60":{"start":{"line":194,"column":8},"end":{"line":201,"column":null}},"61":{"start":{"line":202,"column":8},"end":{"line":202,"column":null}},"62":{"start":{"line":207,"column":25},"end":{"line":207,"column":null}},"63":{"start":{"line":208,"column":8},"end":{"line":208,"column":null}},"64":{"start":{"line":208,"column":29},"end":{"line":208,"column":null}},"65":{"start":{"line":209,"column":8},"end":{"line":215,"column":null}},"66":{"start":{"line":216,"column":8},"end":{"line":216,"column":null}},"67":{"start":{"line":221,"column":25},"end":{"line":221,"column":null}},"68":{"start":{"line":222,"column":8},"end":{"line":222,"column":null}},"69":{"start":{"line":222,"column":29},"end":{"line":222,"column":null}},"70":{"start":{"line":223,"column":8},"end":{"line":229,"column":null}},"71":{"start":{"line":230,"column":8},"end":{"line":230,"column":null}},"72":{"start":{"line":235,"column":25},"end":{"line":235,"column":null}},"73":{"start":{"line":236,"column":8},"end":{"line":236,"column":null}},"74":{"start":{"line":236,"column":29},"end":{"line":236,"column":null}},"75":{"start":{"line":237,"column":8},"end":{"line":243,"column":null}},"76":{"start":{"line":244,"column":8},"end":{"line":244,"column":null}},"77":{"start":{"line":250,"column":23},"end":{"line":250,"column":null}},"78":{"start":{"line":251,"column":8},"end":{"line":251,"column":null}},"79":{"start":{"line":251,"column":21},"end":{"line":251,"column":null}},"80":{"start":{"line":252,"column":27},"end":{"line":252,"column":null}},"81":{"start":{"line":253,"column":8},"end":{"line":259,"column":null}},"82":{"start":{"line":260,"column":8},"end":{"line":260,"column":null}},"83":{"start":{"line":265,"column":2},"end":{"line":265,"column":null}},"84":{"start":{"line":279,"column":13},"end":{"line":279,"column":null}},"85":{"start":{"line":281,"column":25},"end":{"line":281,"column":null}},"86":{"start":{"line":284,"column":4},"end":{"line":284,"column":null}},"87":{"start":{"line":284,"column":27},"end":{"line":284,"column":null}},"88":{"start":{"line":285,"column":4},"end":{"line":285,"column":null}},"89":{"start":{"line":287,"column":23},"end":{"line":287,"column":null}},"90":{"start":{"line":288,"column":4},"end":{"line":288,"column":null}},"91":{"start":{"line":288,"column":21},"end":{"line":288,"column":null}},"92":{"start":{"line":290,"column":17},"end":{"line":290,"column":null}},"93":{"start":{"line":291,"column":4},"end":{"line":291,"column":null}},"94":{"start":{"line":291,"column":15},"end":{"line":291,"column":null}},"95":{"start":{"line":293,"column":4},"end":{"line":300,"column":null}},"96":{"start":{"line":294,"column":16},"end":{"line":294,"column":null}},"97":{"start":{"line":295,"column":6},"end":{"line":295,"column":null}},"98":{"start":{"line":296,"column":6},"end":{"line":296,"column":null}},"99":{"start":{"line":297,"column":6},"end":{"line":297,"column":null}},"100":{"start":{"line":299,"column":6},"end":{"line":299,"column":null}},"101":{"start":{"line":304,"column":4},"end":{"line":304,"column":null}},"102":{"start":{"line":308,"column":4},"end":{"line":314,"column":null}},"103":{"start":{"line":309,"column":6},"end":{"line":313,"column":null}},"104":{"start":{"line":315,"column":4},"end":{"line":328,"column":null}},"105":{"start":{"line":316,"column":19},"end":{"line":316,"column":null}},"106":{"start":{"line":317,"column":6},"end":{"line":321,"column":null}},"107":{"start":{"line":323,"column":6},"end":{"line":327,"column":null}},"108":{"start":{"line":336,"column":22},"end":{"line":336,"column":null}},"109":{"start":{"line":337,"column":24},"end":{"line":337,"column":null}},"110":{"start":{"line":338,"column":31},"end":{"line":338,"column":null}},"111":{"start":{"line":345,"column":22},"end":{"line":345,"column":null}},"112":{"start":{"line":346,"column":24},"end":{"line":346,"column":null}},"113":{"start":{"line":347,"column":31},"end":{"line":347,"column":null}},"114":{"start":{"line":354,"column":51},"end":{"line":354,"column":null}},"115":{"start":{"line":355,"column":45},"end":{"line":355,"column":null}},"116":{"start":{"line":358,"column":2},"end":{"line":358,"column":null}},"117":{"start":{"line":358,"column":18},"end":{"line":358,"column":null}},"118":{"start":{"line":359,"column":2},"end":{"line":359,"column":null}},"119":{"start":{"line":363,"column":2},"end":{"line":363,"column":null}},"120":{"start":{"line":363,"column":19},"end":{"line":363,"column":null}},"121":{"start":{"line":364,"column":2},"end":{"line":364,"column":null}},"122":{"start":{"line":372,"column":2},"end":{"line":375,"column":null}},"123":{"start":{"line":389,"column":13},"end":{"line":389,"column":null}},"124":{"start":{"line":391,"column":25},"end":{"line":391,"column":null}},"125":{"start":{"line":394,"column":4},"end":{"line":394,"column":null}},"126":{"start":{"line":394,"column":27},"end":{"line":394,"column":null}},"127":{"start":{"line":395,"column":4},"end":{"line":395,"column":null}},"128":{"start":{"line":397,"column":23},"end":{"line":397,"column":null}},"129":{"start":{"line":398,"column":4},"end":{"line":398,"column":null}},"130":{"start":{"line":398,"column":21},"end":{"line":398,"column":null}},"131":{"start":{"line":400,"column":17},"end":{"line":400,"column":null}},"132":{"start":{"line":401,"column":4},"end":{"line":401,"column":null}},"133":{"start":{"line":401,"column":15},"end":{"line":401,"column":null}},"134":{"start":{"line":403,"column":4},"end":{"line":410,"column":null}},"135":{"start":{"line":404,"column":16},"end":{"line":404,"column":null}},"136":{"start":{"line":405,"column":6},"end":{"line":405,"column":null}},"137":{"start":{"line":406,"column":6},"end":{"line":406,"column":null}},"138":{"start":{"line":407,"column":6},"end":{"line":407,"column":null}},"139":{"start":{"line":409,"column":6},"end":{"line":409,"column":null}},"140":{"start":{"line":414,"column":4},"end":{"line":414,"column":null}},"141":{"start":{"line":418,"column":4},"end":{"line":424,"column":null}},"142":{"start":{"line":419,"column":6},"end":{"line":423,"column":null}},"143":{"start":{"line":425,"column":4},"end":{"line":439,"column":null}},"144":{"start":{"line":426,"column":19},"end":{"line":426,"column":null}},"145":{"start":{"line":427,"column":6},"end":{"line":432,"column":null}},"146":{"start":{"line":434,"column":6},"end":{"line":438,"column":null}},"147":{"start":{"line":444,"column":22},"end":{"line":444,"column":null}},"148":{"start":{"line":445,"column":24},"end":{"line":445,"column":null}},"149":{"start":{"line":449,"column":22},"end":{"line":449,"column":null}},"150":{"start":{"line":450,"column":24},"end":{"line":450,"column":null}},"151":{"start":{"line":454,"column":51},"end":{"line":454,"column":null}},"152":{"start":{"line":455,"column":45},"end":{"line":455,"column":null}},"153":{"start":{"line":458,"column":2},"end":{"line":458,"column":null}},"154":{"start":{"line":458,"column":18},"end":{"line":458,"column":null}},"155":{"start":{"line":459,"column":2},"end":{"line":459,"column":null}},"156":{"start":{"line":463,"column":2},"end":{"line":463,"column":null}},"157":{"start":{"line":463,"column":19},"end":{"line":463,"column":null}},"158":{"start":{"line":464,"column":2},"end":{"line":464,"column":null}},"159":{"start":{"line":473,"column":20},"end":{"line":473,"column":null}},"160":{"start":{"line":474,"column":2},"end":{"line":474,"column":null}}},"fnMap":{"0":{"name":"tryRequire","decl":{"start":{"line":37,"column":9},"end":{"line":37,"column":20}},"loc":{"start":{"line":37,"column":43},"end":{"line":43,"column":null}},"line":37},"1":{"name":"loadJsGrammar","decl":{"start":{"line":49,"column":9},"end":{"line":49,"column":34}},"loc":{"start":{"line":49,"column":34},"end":{"line":55,"column":null}},"line":49},"2":{"name":"loadTsGrammar","decl":{"start":{"line":62,"column":9},"end":{"line":62,"column":23}},"loc":{"start":{"line":62,"column":63},"end":{"line":74,"column":null}},"line":62},"3":{"name":"walkWithScope","decl":{"start":{"line":91,"column":9},"end":{"line":91,"column":null}},"loc":{"start":{"line":95,"column":8},"end":{"line":113,"column":null}},"line":95},"4":{"name":"extractSymbols","decl":{"start":{"line":118,"column":9},"end":{"line":118,"column":24}},"loc":{"start":{"line":118,"column":54},"end":{"line":266,"column":null}},"line":118},"5":{"name":"(anonymous_5)","decl":{"start":{"line":121,"column":22},"end":{"line":121,"column":23}},"loc":{"start":{"line":121,"column":39},"end":{"line":263,"column":3}},"line":121},"6":{"name":"(anonymous_6)","decl":{"start":{"line":283,"column":12},"end":{"line":283,"column":28}},"loc":{"start":{"line":283,"column":28},"end":{"line":301,"column":null}},"line":283},"7":{"name":"(anonymous_7)","decl":{"start":{"line":303,"column":6},"end":{"line":303,"column":29}},"loc":{"start":{"line":303,"column":29},"end":{"line":305,"column":null}},"line":303},"8":{"name":"(anonymous_8)","decl":{"start":{"line":307,"column":8},"end":{"line":307,"column":14}},"loc":{"start":{"line":307,"column":71},"end":{"line":329,"column":null}},"line":307},"9":{"name":"getTreeSitterTypeScriptParser","decl":{"start":{"line":357,"column":16},"end":{"line":357,"column":76}},"loc":{"start":{"line":357,"column":76},"end":{"line":360,"column":null}},"line":357},"10":{"name":"getTreeSitterTSXParser","decl":{"start":{"line":362,"column":16},"end":{"line":362,"column":62}},"loc":{"start":{"line":362,"column":62},"end":{"line":365,"column":null}},"line":362},"11":{"name":"checkTsTreeSitterAvailability","decl":{"start":{"line":368,"column":16},"end":{"line":368,"column":null}},"loc":{"start":{"line":371,"column":2},"end":{"line":376,"column":null}},"line":371},"12":{"name":"(anonymous_12)","decl":{"start":{"line":393,"column":12},"end":{"line":393,"column":28}},"loc":{"start":{"line":393,"column":28},"end":{"line":411,"column":null}},"line":393},"13":{"name":"(anonymous_13)","decl":{"start":{"line":413,"column":6},"end":{"line":413,"column":29}},"loc":{"start":{"line":413,"column":29},"end":{"line":415,"column":null}},"line":413},"14":{"name":"(anonymous_14)","decl":{"start":{"line":417,"column":8},"end":{"line":417,"column":14}},"loc":{"start":{"line":417,"column":71},"end":{"line":440,"column":null}},"line":417},"15":{"name":"getTreeSitterJavaScriptParser","decl":{"start":{"line":457,"column":16},"end":{"line":457,"column":76}},"loc":{"start":{"line":457,"column":76},"end":{"line":460,"column":null}},"line":457},"16":{"name":"getTreeSitterJSXParser","decl":{"start":{"line":462,"column":16},"end":{"line":462,"column":62}},"loc":{"start":{"line":462,"column":62},"end":{"line":465,"column":null}},"line":462},"17":{"name":"checkJsTreeSitterAvailability","decl":{"start":{"line":468,"column":16},"end":{"line":468,"column":null}},"loc":{"start":{"line":471,"column":2},"end":{"line":475,"column":null}},"line":471}},"branchMap":{"0":{"loc":{"start":{"line":51,"column":2},"end":{"line":51,"column":null}},"type":"if","locations":[{"start":{"line":51,"column":2},"end":{"line":51,"column":null}},{"start":{},"end":{}}],"line":51},"1":{"loc":{"start":{"line":52,"column":2},"end":{"line":52,"column":null}},"type":"if","locations":[{"start":{"line":52,"column":2},"end":{"line":52,"column":null}},{"start":{},"end":{}}],"line":52},"2":{"loc":{"start":{"line":65,"column":2},"end":{"line":67,"column":null}},"type":"if","locations":[{"start":{"line":65,"column":2},"end":{"line":67,"column":null}},{"start":{},"end":{}}],"line":65},"3":{"loc":{"start":{"line":66,"column":11},"end":{"line":66,"column":null}},"type":"cond-expr","locations":[{"start":{"line":66,"column":51},"end":{"line":66,"column":68}},{"start":{"line":66,"column":68},"end":{"line":66,"column":null}}],"line":66},"4":{"loc":{"start":{"line":70,"column":2},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":2},"end":{"line":70,"column":null}},{"start":{},"end":{}}],"line":70},"5":{"loc":{"start":{"line":72,"column":2},"end":{"line":72,"column":null}},"type":"if","locations":[{"start":{"line":72,"column":2},"end":{"line":72,"column":null}},{"start":{},"end":{}}],"line":72},"6":{"loc":{"start":{"line":73,"column":9},"end":{"line":73,"column":null}},"type":"cond-expr","locations":[{"start":{"line":73,"column":48},"end":{"line":73,"column":64}},{"start":{"line":73,"column":64},"end":{"line":73,"column":null}}],"line":73},"7":{"loc":{"start":{"line":94,"column":2},"end":{"line":94,"column":null}},"type":"default-arg","locations":[{"start":{"line":94,"column":20},"end":{"line":94,"column":null}}],"line":94},"8":{"loc":{"start":{"line":98,"column":2},"end":{"line":107,"column":null}},"type":"if","locations":[{"start":{"line":98,"column":2},"end":{"line":107,"column":null}},{"start":{},"end":{}}],"line":98},"9":{"loc":{"start":{"line":99,"column":4},"end":{"line":101,"column":null}},"type":"binary-expr","locations":[{"start":{"line":99,"column":4},"end":{"line":99,"column":null}},{"start":{"line":100,"column":4},"end":{"line":100,"column":null}},{"start":{"line":101,"column":4},"end":{"line":101,"column":null}}],"line":99},"10":{"loc":{"start":{"line":104,"column":4},"end":{"line":106,"column":null}},"type":"if","locations":[{"start":{"line":104,"column":4},"end":{"line":106,"column":null}},{"start":{},"end":{}}],"line":104},"11":{"loc":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},"type":"if","locations":[{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},{"start":{},"end":{}}],"line":111},"12":{"loc":{"start":{"line":122,"column":4},"end":{"line":262,"column":null}},"type":"switch","locations":[{"start":{"line":124,"column":6},"end":{"line":124,"column":null}},{"start":{"line":125,"column":6},"end":{"line":140,"column":null}},{"start":{"line":143,"column":6},"end":{"line":143,"column":null}},{"start":{"line":144,"column":6},"end":{"line":167,"column":null}},{"start":{"line":170,"column":6},"end":{"line":170,"column":null}},{"start":{"line":171,"column":6},"end":{"line":187,"column":null}},{"start":{"line":190,"column":6},"end":{"line":190,"column":null}},{"start":{"line":191,"column":6},"end":{"line":203,"column":null}},{"start":{"line":206,"column":6},"end":{"line":217,"column":null}},{"start":{"line":220,"column":6},"end":{"line":231,"column":null}},{"start":{"line":234,"column":6},"end":{"line":245,"column":null}},{"start":{"line":248,"column":6},"end":{"line":261,"column":null}}],"line":122},"13":{"loc":{"start":{"line":127,"column":8},"end":{"line":127,"column":null}},"type":"if","locations":[{"start":{"line":127,"column":8},"end":{"line":127,"column":null}},{"start":{},"end":{}}],"line":127},"14":{"loc":{"start":{"line":132,"column":12},"end":{"line":134,"column":null}},"type":"cond-expr","locations":[{"start":{"line":133,"column":16},"end":{"line":133,"column":null}},{"start":{"line":134,"column":16},"end":{"line":134,"column":null}}],"line":132},"15":{"loc":{"start":{"line":147,"column":10},"end":{"line":147,"column":null}},"type":"if","locations":[{"start":{"line":147,"column":10},"end":{"line":147,"column":null}},{"start":{},"end":{}}],"line":147},"16":{"loc":{"start":{"line":150,"column":10},"end":{"line":150,"column":null}},"type":"if","locations":[{"start":{"line":150,"column":10},"end":{"line":150,"column":null}},{"start":{},"end":{}}],"line":150},"17":{"loc":{"start":{"line":150,"column":14},"end":{"line":150,"column":41}},"type":"binary-expr","locations":[{"start":{"line":150,"column":14},"end":{"line":150,"column":33}},{"start":{"line":150,"column":33},"end":{"line":150,"column":41}}],"line":150},"18":{"loc":{"start":{"line":151,"column":10},"end":{"line":164,"column":null}},"type":"if","locations":[{"start":{"line":151,"column":10},"end":{"line":164,"column":null}},{"start":{},"end":{}}],"line":151},"19":{"loc":{"start":{"line":152,"column":12},"end":{"line":154,"column":null}},"type":"binary-expr","locations":[{"start":{"line":152,"column":12},"end":{"line":152,"column":null}},{"start":{"line":153,"column":12},"end":{"line":153,"column":null}},{"start":{"line":154,"column":12},"end":{"line":154,"column":null}}],"line":152},"20":{"loc":{"start":{"line":173,"column":8},"end":{"line":173,"column":null}},"type":"if","locations":[{"start":{"line":173,"column":8},"end":{"line":173,"column":null}},{"start":{},"end":{}}],"line":173},"21":{"loc":{"start":{"line":176,"column":8},"end":{"line":176,"column":null}},"type":"if","locations":[{"start":{"line":176,"column":8},"end":{"line":176,"column":null}},{"start":{},"end":{}}],"line":176},"22":{"loc":{"start":{"line":193,"column":8},"end":{"line":193,"column":null}},"type":"if","locations":[{"start":{"line":193,"column":8},"end":{"line":193,"column":null}},{"start":{},"end":{}}],"line":193},"23":{"loc":{"start":{"line":198,"column":12},"end":{"line":198,"column":null}},"type":"cond-expr","locations":[{"start":{"line":198,"column":57},"end":{"line":198,"column":70}},{"start":{"line":198,"column":70},"end":{"line":198,"column":null}}],"line":198},"24":{"loc":{"start":{"line":208,"column":8},"end":{"line":208,"column":null}},"type":"if","locations":[{"start":{"line":208,"column":8},"end":{"line":208,"column":null}},{"start":{},"end":{}}],"line":208},"25":{"loc":{"start":{"line":222,"column":8},"end":{"line":222,"column":null}},"type":"if","locations":[{"start":{"line":222,"column":8},"end":{"line":222,"column":null}},{"start":{},"end":{}}],"line":222},"26":{"loc":{"start":{"line":236,"column":8},"end":{"line":236,"column":null}},"type":"if","locations":[{"start":{"line":236,"column":8},"end":{"line":236,"column":null}},{"start":{},"end":{}}],"line":236},"27":{"loc":{"start":{"line":251,"column":8},"end":{"line":251,"column":null}},"type":"if","locations":[{"start":{"line":251,"column":8},"end":{"line":251,"column":null}},{"start":{},"end":{}}],"line":251},"28":{"loc":{"start":{"line":284,"column":4},"end":{"line":284,"column":null}},"type":"if","locations":[{"start":{"line":284,"column":4},"end":{"line":284,"column":null}},{"start":{},"end":{}}],"line":284},"29":{"loc":{"start":{"line":288,"column":4},"end":{"line":288,"column":null}},"type":"if","locations":[{"start":{"line":288,"column":4},"end":{"line":288,"column":null}},{"start":{},"end":{}}],"line":288},"30":{"loc":{"start":{"line":291,"column":4},"end":{"line":291,"column":null}},"type":"if","locations":[{"start":{"line":291,"column":4},"end":{"line":291,"column":null}},{"start":{},"end":{}}],"line":291},"31":{"loc":{"start":{"line":308,"column":4},"end":{"line":314,"column":null}},"type":"if","locations":[{"start":{"line":308,"column":4},"end":{"line":314,"column":null}},{"start":{},"end":{}}],"line":308},"32":{"loc":{"start":{"line":308,"column":8},"end":{"line":308,"column":39}},"type":"binary-expr","locations":[{"start":{"line":308,"column":8},"end":{"line":308,"column":24}},{"start":{"line":308,"column":24},"end":{"line":308,"column":39}}],"line":308},"33":{"loc":{"start":{"line":358,"column":2},"end":{"line":358,"column":null}},"type":"if","locations":[{"start":{"line":358,"column":2},"end":{"line":358,"column":null}},{"start":{},"end":{}}],"line":358},"34":{"loc":{"start":{"line":363,"column":2},"end":{"line":363,"column":null}},"type":"if","locations":[{"start":{"line":363,"column":2},"end":{"line":363,"column":null}},{"start":{},"end":{}}],"line":363},"35":{"loc":{"start":{"line":394,"column":4},"end":{"line":394,"column":null}},"type":"if","locations":[{"start":{"line":394,"column":4},"end":{"line":394,"column":null}},{"start":{},"end":{}}],"line":394},"36":{"loc":{"start":{"line":398,"column":4},"end":{"line":398,"column":null}},"type":"if","locations":[{"start":{"line":398,"column":4},"end":{"line":398,"column":null}},{"start":{},"end":{}}],"line":398},"37":{"loc":{"start":{"line":401,"column":4},"end":{"line":401,"column":null}},"type":"if","locations":[{"start":{"line":401,"column":4},"end":{"line":401,"column":null}},{"start":{},"end":{}}],"line":401},"38":{"loc":{"start":{"line":418,"column":4},"end":{"line":424,"column":null}},"type":"if","locations":[{"start":{"line":418,"column":4},"end":{"line":424,"column":null}},{"start":{},"end":{}}],"line":418},"39":{"loc":{"start":{"line":418,"column":8},"end":{"line":418,"column":39}},"type":"binary-expr","locations":[{"start":{"line":418,"column":8},"end":{"line":418,"column":24}},{"start":{"line":418,"column":24},"end":{"line":418,"column":39}}],"line":418},"40":{"loc":{"start":{"line":458,"column":2},"end":{"line":458,"column":null}},"type":"if","locations":[{"start":{"line":458,"column":2},"end":{"line":458,"column":null}},{"start":{},"end":{}}],"line":458},"41":{"loc":{"start":{"line":463,"column":2},"end":{"line":463,"column":null}},"type":"if","locations":[{"start":{"line":463,"column":2},"end":{"line":463,"column":null}},{"start":{},"end":{}}],"line":463}},"s":{"0":3,"1":9,"2":9,"3":9,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":6,"85":6,"86":110,"87":104,"88":6,"89":6,"90":6,"91":6,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":110,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":3,"109":3,"110":3,"111":3,"112":3,"113":3,"114":3,"115":3,"116":55,"117":3,"118":55,"119":55,"120":3,"121":55,"122":55,"123":3,"124":3,"125":55,"126":52,"127":3,"128":3,"129":3,"130":3,"131":0,"132":0,"133":0,"134":0,"135":0,"136":0,"137":0,"138":0,"139":0,"140":55,"141":0,"142":0,"143":0,"144":0,"145":0,"146":0,"147":3,"148":3,"149":0,"150":0,"151":3,"152":3,"153":55,"154":3,"155":55,"156":0,"157":0,"158":0,"159":55,"160":55},"f":{"0":9,"1":0,"2":0,"3":0,"4":0,"5":0,"6":110,"7":110,"8":0,"9":55,"10":55,"11":55,"12":55,"13":55,"14":0,"15":55,"16":0,"17":55},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0],"8":[0,0],"9":[0,0,0],"10":[0,0],"11":[0,0],"12":[0,0,0,0,0,0,0,0,0,0,0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[104,6],"29":[6,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[3,52],"34":[3,52],"35":[52,3],"36":[3,0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[3,52],"41":[0,0]},"meta":{"lastBranch":42,"lastFunction":18,"lastStatement":161,"seen":{"s:32:6:32:Infinity":0,"f:37:9:37:20":0,"s:38:2:42:Infinity":1,"s:39:4:39:Infinity":2,"s:41:4:41:Infinity":3,"f:49:9:49:34":1,"s:50:14:50:Infinity":4,"b:51:2:51:Infinity:undefined:undefined:undefined:undefined":0,"s:51:2:51:Infinity":5,"s:51:12:51:Infinity":6,"b:52:2:52:Infinity:undefined:undefined:undefined:undefined":1,"s:52:2:52:Infinity":7,"s:52:43:52:Infinity":8,"s:54:2:54:Infinity":9,"f:62:9:62:23":2,"s:64:16:64:Infinity":10,"b:65:2:67:Infinity:undefined:undefined:undefined:undefined":2,"s:65:2:67:Infinity":11,"s:66:4:66:Infinity":12,"b:66:51:66:68:66:68:66:Infinity":3,"s:69:19:69:Infinity":13,"b:70:2:70:Infinity:undefined:undefined:undefined:undefined":4,"s:70:2:70:Infinity":14,"s:70:17:70:Infinity":15,"s:71:15:71:Infinity":16,"b:72:2:72:Infinity:undefined:undefined:undefined:undefined":5,"s:72:2:72:Infinity":17,"s:72:13:72:Infinity":18,"s:73:2:73:Infinity":19,"b:73:48:73:64:73:64:73:Infinity":6,"f:91:9:91:Infinity":3,"b:94:20:94:Infinity":7,"s:97:17:97:Infinity":20,"b:98:2:107:Infinity:undefined:undefined:undefined:undefined":8,"s:98:2:107:Infinity":21,"b:99:4:99:Infinity:100:4:100:Infinity:101:4:101:Infinity":9,"s:103:21:103:Infinity":22,"b:104:4:106:Infinity:undefined:undefined:undefined:undefined":10,"s:104:4:106:Infinity":23,"s:105:6:105:Infinity":24,"s:108:2:108:Infinity":25,"s:109:2:112:Infinity":26,"s:109:15:109:18":27,"s:110:18:110:Infinity":28,"b:111:4:111:Infinity:undefined:undefined:undefined:undefined":11,"s:111:4:111:Infinity":29,"s:111:15:111:Infinity":30,"f:118:9:118:24":4,"s:119:34:119:Infinity":31,"s:121:2:263:Infinity":32,"f:121:22:121:23":5,"b:124:6:124:Infinity:125:6:140:Infinity:143:6:143:Infinity:144:6:167:Infinity:170:6:170:Infinity:171:6:187:Infinity:190:6:190:Infinity:191:6:203:Infinity:206:6:217:Infinity:220:6:231:Infinity:234:6:245:Infinity:248:6:261:Infinity":12,"s:122:4:262:Infinity":33,"s:126:25:126:Infinity":34,"b:127:8:127:Infinity:undefined:undefined:undefined:undefined":13,"s:127:8:127:Infinity":35,"s:127:29:127:Infinity":36,"s:128:8:138:Infinity":37,"b:133:16:133:Infinity:134:16:134:Infinity":14,"s:139:8:139:Infinity":38,"s:146:8:165:Infinity":39,"b:147:10:147:Infinity:undefined:undefined:undefined:undefined":15,"s:147:10:147:Infinity":40,"s:147:57:147:Infinity":41,"s:148:27:148:Infinity":42,"s:149:24:149:Infinity":43,"b:150:10:150:Infinity:undefined:undefined:undefined:undefined":16,"s:150:10:150:Infinity":44,"b:150:14:150:33:150:33:150:41":17,"s:150:41:150:Infinity":45,"b:151:10:164:Infinity:undefined:undefined:undefined:undefined":18,"s:151:10:164:Infinity":46,"b:152:12:152:Infinity:153:12:153:Infinity:154:12:154:Infinity":19,"s:156:12:163:Infinity":47,"s:166:8:166:Infinity":48,"s:172:25:172:Infinity":49,"b:173:8:173:Infinity:undefined:undefined:undefined:undefined":20,"s:173:8:173:Infinity":50,"s:173:29:173:Infinity":51,"s:174:27:174:Infinity":52,"b:176:8:176:Infinity:undefined:undefined:undefined:undefined":21,"s:176:8:176:Infinity":53,"s:176:42:176:Infinity":54,"s:177:8:185:Infinity":55,"s:186:8:186:Infinity":56,"s:192:25:192:Infinity":57,"b:193:8:193:Infinity:undefined:undefined:undefined:undefined":22,"s:193:8:193:Infinity":58,"s:193:29:193:Infinity":59,"s:194:8:201:Infinity":60,"b:198:57:198:70:198:70:198:Infinity":23,"s:202:8:202:Infinity":61,"s:207:25:207:Infinity":62,"b:208:8:208:Infinity:undefined:undefined:undefined:undefined":24,"s:208:8:208:Infinity":63,"s:208:29:208:Infinity":64,"s:209:8:215:Infinity":65,"s:216:8:216:Infinity":66,"s:221:25:221:Infinity":67,"b:222:8:222:Infinity:undefined:undefined:undefined:undefined":25,"s:222:8:222:Infinity":68,"s:222:29:222:Infinity":69,"s:223:8:229:Infinity":70,"s:230:8:230:Infinity":71,"s:235:25:235:Infinity":72,"b:236:8:236:Infinity:undefined:undefined:undefined:undefined":26,"s:236:8:236:Infinity":73,"s:236:29:236:Infinity":74,"s:237:8:243:Infinity":75,"s:244:8:244:Infinity":76,"s:250:23:250:Infinity":77,"b:251:8:251:Infinity:undefined:undefined:undefined:undefined":27,"s:251:8:251:Infinity":78,"s:251:21:251:Infinity":79,"s:252:27:252:Infinity":80,"s:253:8:259:Infinity":81,"s:260:8:260:Infinity":82,"s:265:2:265:Infinity":83,"s:279:13:279:Infinity":84,"s:281:25:281:Infinity":85,"f:283:12:283:28":6,"b:284:4:284:Infinity:undefined:undefined:undefined:undefined":28,"s:284:4:284:Infinity":86,"s:284:27:284:Infinity":87,"s:285:4:285:Infinity":88,"s:287:23:287:Infinity":89,"b:288:4:288:Infinity:undefined:undefined:undefined:undefined":29,"s:288:4:288:Infinity":90,"s:288:21:288:Infinity":91,"s:290:17:290:Infinity":92,"b:291:4:291:Infinity:undefined:undefined:undefined:undefined":30,"s:291:4:291:Infinity":93,"s:291:15:291:Infinity":94,"s:293:4:300:Infinity":95,"s:294:16:294:Infinity":96,"s:295:6:295:Infinity":97,"s:296:6:296:Infinity":98,"s:297:6:297:Infinity":99,"s:299:6:299:Infinity":100,"f:303:6:303:29":7,"s:304:4:304:Infinity":101,"f:307:8:307:14":8,"b:308:4:314:Infinity:undefined:undefined:undefined:undefined":31,"s:308:4:314:Infinity":102,"b:308:8:308:24:308:24:308:39":32,"s:309:6:313:Infinity":103,"s:315:4:328:Infinity":104,"s:316:19:316:Infinity":105,"s:317:6:321:Infinity":106,"s:323:6:327:Infinity":107,"s:336:22:336:Infinity":108,"s:337:24:337:Infinity":109,"s:338:31:338:Infinity":110,"s:345:22:345:Infinity":111,"s:346:24:346:Infinity":112,"s:347:31:347:Infinity":113,"s:354:51:354:Infinity":114,"s:355:45:355:Infinity":115,"f:357:16:357:76":9,"b:358:2:358:Infinity:undefined:undefined:undefined:undefined":33,"s:358:2:358:Infinity":116,"s:358:18:358:Infinity":117,"s:359:2:359:Infinity":118,"f:362:16:362:62":10,"b:363:2:363:Infinity:undefined:undefined:undefined:undefined":34,"s:363:2:363:Infinity":119,"s:363:19:363:Infinity":120,"s:364:2:364:Infinity":121,"f:368:16:368:Infinity":11,"s:372:2:375:Infinity":122,"s:389:13:389:Infinity":123,"s:391:25:391:Infinity":124,"f:393:12:393:28":12,"b:394:4:394:Infinity:undefined:undefined:undefined:undefined":35,"s:394:4:394:Infinity":125,"s:394:27:394:Infinity":126,"s:395:4:395:Infinity":127,"s:397:23:397:Infinity":128,"b:398:4:398:Infinity:undefined:undefined:undefined:undefined":36,"s:398:4:398:Infinity":129,"s:398:21:398:Infinity":130,"s:400:17:400:Infinity":131,"b:401:4:401:Infinity:undefined:undefined:undefined:undefined":37,"s:401:4:401:Infinity":132,"s:401:15:401:Infinity":133,"s:403:4:410:Infinity":134,"s:404:16:404:Infinity":135,"s:405:6:405:Infinity":136,"s:406:6:406:Infinity":137,"s:407:6:407:Infinity":138,"s:409:6:409:Infinity":139,"f:413:6:413:29":13,"s:414:4:414:Infinity":140,"f:417:8:417:14":14,"b:418:4:424:Infinity:undefined:undefined:undefined:undefined":38,"s:418:4:424:Infinity":141,"b:418:8:418:24:418:24:418:39":39,"s:419:6:423:Infinity":142,"s:425:4:439:Infinity":143,"s:426:19:426:Infinity":144,"s:427:6:432:Infinity":145,"s:434:6:438:Infinity":146,"s:444:22:444:Infinity":147,"s:445:24:445:Infinity":148,"s:449:22:449:Infinity":149,"s:450:24:450:Infinity":150,"s:454:51:454:Infinity":151,"s:455:45:455:Infinity":152,"f:457:16:457:76":15,"b:458:2:458:Infinity:undefined:undefined:undefined:undefined":40,"s:458:2:458:Infinity":153,"s:458:18:458:Infinity":154,"s:459:2:459:Infinity":155,"f:462:16:462:62":16,"b:463:2:463:Infinity:undefined:undefined:undefined:undefined":41,"s:463:2:463:Infinity":156,"s:463:19:463:Infinity":157,"s:464:2:464:Infinity":158,"f:468:16:468:Infinity":17,"s:473:20:473:Infinity":159,"s:474:2:474:Infinity":160}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/parsers/typescript-parser.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/parsers/typescript-parser.ts","statementMap":{"0":{"start":{"line":114,"column":4},"end":{"line":114,"column":null}},"1":{"start":{"line":118,"column":20},"end":{"line":118,"column":null}},"2":{"start":{"line":119,"column":26},"end":{"line":119,"column":null}},"3":{"start":{"line":120,"column":25},"end":{"line":120,"column":null}},"4":{"start":{"line":121,"column":17},"end":{"line":121,"column":null}},"5":{"start":{"line":122,"column":18},"end":{"line":122,"column":null}},"6":{"start":{"line":123,"column":16},"end":{"line":123,"column":null}},"7":{"start":{"line":126,"column":22},"end":{"line":126,"column":null}},"8":{"start":{"line":127,"column":20},"end":{"line":127,"column":null}},"9":{"start":{"line":128,"column":22},"end":{"line":128,"column":null}},"10":{"start":{"line":129,"column":20},"end":{"line":129,"column":null}},"11":{"start":{"line":130,"column":20},"end":{"line":130,"column":null}},"12":{"start":{"line":131,"column":23},"end":{"line":131,"column":null}},"13":{"start":{"line":132,"column":22},"end":{"line":132,"column":null}},"14":{"start":{"line":134,"column":4},"end":{"line":155,"column":null}},"15":{"start":{"line":159,"column":38},"end":{"line":159,"column":null}},"16":{"start":{"line":160,"column":18},"end":{"line":160,"column":null}},"17":{"start":{"line":163,"column":32},"end":{"line":172,"column":null}},"18":{"start":{"line":175,"column":21},"end":{"line":179,"column":null}},"19":{"start":{"line":181,"column":4},"end":{"line":211,"column":null}},"20":{"start":{"line":182,"column":6},"end":{"line":210,"column":null}},"21":{"start":{"line":184,"column":8},"end":{"line":209,"column":null}},"22":{"start":{"line":185,"column":23},"end":{"line":185,"column":null}},"23":{"start":{"line":188,"column":10},"end":{"line":190,"column":null}},"24":{"start":{"line":189,"column":12},"end":{"line":189,"column":null}},"25":{"start":{"line":193,"column":12},"end":{"line":196,"column":null}},"26":{"start":{"line":195,"column":26},"end":{"line":195,"column":34}},"27":{"start":{"line":197,"column":29},"end":{"line":197,"column":null}},"28":{"start":{"line":199,"column":10},"end":{"line":208,"column":null}},"29":{"start":{"line":213,"column":4},"end":{"line":213,"column":null}},"30":{"start":{"line":217,"column":33},"end":{"line":217,"column":null}},"31":{"start":{"line":218,"column":18},"end":{"line":218,"column":null}},"32":{"start":{"line":220,"column":4},"end":{"line":269,"column":null}},"33":{"start":{"line":222,"column":8},"end":{"line":224,"column":null}},"34":{"start":{"line":225,"column":6},"end":{"line":238,"column":null}},"35":{"start":{"line":226,"column":8},"end":{"line":237,"column":null}},"36":{"start":{"line":241,"column":8},"end":{"line":243,"column":null}},"37":{"start":{"line":244,"column":6},"end":{"line":255,"column":null}},"38":{"start":{"line":245,"column":8},"end":{"line":254,"column":null}},"39":{"start":{"line":257,"column":24},"end":{"line":257,"column":null}},"40":{"start":{"line":258,"column":6},"end":{"line":268,"column":null}},"41":{"start":{"line":259,"column":8},"end":{"line":267,"column":null}},"42":{"start":{"line":271,"column":4},"end":{"line":271,"column":null}},"43":{"start":{"line":275,"column":38},"end":{"line":275,"column":null}},"44":{"start":{"line":276,"column":18},"end":{"line":276,"column":null}},"45":{"start":{"line":278,"column":4},"end":{"line":299,"column":null}},"46":{"start":{"line":280,"column":8},"end":{"line":282,"column":null}},"47":{"start":{"line":283,"column":6},"end":{"line":298,"column":null}},"48":{"start":{"line":285,"column":8},"end":{"line":297,"column":null}},"49":{"start":{"line":301,"column":4},"end":{"line":301,"column":null}},"50":{"start":{"line":305,"column":34},"end":{"line":305,"column":null}},"51":{"start":{"line":306,"column":18},"end":{"line":306,"column":null}},"52":{"start":{"line":308,"column":4},"end":{"line":341,"column":null}},"53":{"start":{"line":310,"column":8},"end":{"line":312,"column":null}},"54":{"start":{"line":313,"column":6},"end":{"line":340,"column":null}},"55":{"start":{"line":314,"column":23},"end":{"line":314,"column":null}},"56":{"start":{"line":315,"column":29},"end":{"line":315,"column":null}},"57":{"start":{"line":316,"column":30},"end":{"line":316,"column":null}},"58":{"start":{"line":318,"column":27},"end":{"line":332,"column":null}},"59":{"start":{"line":324,"column":24},"end":{"line":324,"column":32}},"60":{"start":{"line":327,"column":39},"end":{"line":329,"column":null}},"61":{"start":{"line":328,"column":45},"end":{"line":328,"column":53}},"62":{"start":{"line":330,"column":14},"end":{"line":330,"column":null}},"63":{"start":{"line":334,"column":8},"end":{"line":339,"column":null}},"64":{"start":{"line":343,"column":4},"end":{"line":343,"column":null}},"65":{"start":{"line":347,"column":34},"end":{"line":347,"column":null}},"66":{"start":{"line":348,"column":18},"end":{"line":348,"column":null}},"67":{"start":{"line":350,"column":4},"end":{"line":391,"column":null}},"68":{"start":{"line":352,"column":27},"end":{"line":352,"column":null}},"69":{"start":{"line":353,"column":6},"end":{"line":360,"column":null}},"70":{"start":{"line":354,"column":8},"end":{"line":359,"column":null}},"71":{"start":{"line":364,"column":8},"end":{"line":364,"column":null}},"72":{"start":{"line":365,"column":6},"end":{"line":372,"column":null}},"73":{"start":{"line":366,"column":8},"end":{"line":371,"column":null}},"74":{"start":{"line":376,"column":8},"end":{"line":376,"column":null}},"75":{"start":{"line":377,"column":6},"end":{"line":390,"column":null}},"76":{"start":{"line":378,"column":22},"end":{"line":380,"column":null}},"77":{"start":{"line":378,"column":62},"end":{"line":378,"column":70}},"78":{"start":{"line":381,"column":8},"end":{"line":389,"column":null}},"79":{"start":{"line":382,"column":10},"end":{"line":388,"column":null}},"80":{"start":{"line":393,"column":4},"end":{"line":393,"column":null}},"81":{"start":{"line":397,"column":21},"end":{"line":397,"column":null}},"82":{"start":{"line":398,"column":20},"end":{"line":398,"column":null}},"83":{"start":{"line":400,"column":4},"end":{"line":413,"column":null}},"84":{"start":{"line":400,"column":17},"end":{"line":400,"column":29}},"85":{"start":{"line":401,"column":19},"end":{"line":401,"column":null}},"86":{"start":{"line":402,"column":6},"end":{"line":412,"column":null}},"87":{"start":{"line":403,"column":8},"end":{"line":411,"column":null}},"88":{"start":{"line":404,"column":10},"end":{"line":404,"column":null}},"89":{"start":{"line":405,"column":10},"end":{"line":405,"column":null}},"90":{"start":{"line":406,"column":8},"end":{"line":411,"column":null}},"91":{"start":{"line":407,"column":10},"end":{"line":407,"column":null}},"92":{"start":{"line":408,"column":10},"end":{"line":410,"column":null}},"93":{"start":{"line":409,"column":12},"end":{"line":409,"column":null}},"94":{"start":{"line":415,"column":4},"end":{"line":415,"column":null}},"95":{"start":{"line":422,"column":40},"end":{"line":422,"column":null}},"96":{"start":{"line":423,"column":18},"end":{"line":423,"column":null}},"97":{"start":{"line":425,"column":4},"end":{"line":464,"column":null}},"98":{"start":{"line":428,"column":20},"end":{"line":430,"column":null}},"99":{"start":{"line":431,"column":6},"end":{"line":431,"column":null}},"100":{"start":{"line":433,"column":6},"end":{"line":463,"column":null}},"101":{"start":{"line":434,"column":21},"end":{"line":434,"column":null}},"102":{"start":{"line":435,"column":21},"end":{"line":435,"column":null}},"103":{"start":{"line":443,"column":24},"end":{"line":443,"column":null}},"104":{"start":{"line":444,"column":8},"end":{"line":452,"column":null}},"105":{"start":{"line":445,"column":10},"end":{"line":445,"column":null}},"106":{"start":{"line":446,"column":8},"end":{"line":452,"column":null}},"107":{"start":{"line":447,"column":10},"end":{"line":447,"column":null}},"108":{"start":{"line":448,"column":8},"end":{"line":452,"column":null}},"109":{"start":{"line":449,"column":10},"end":{"line":449,"column":null}},"110":{"start":{"line":450,"column":8},"end":{"line":452,"column":null}},"111":{"start":{"line":451,"column":10},"end":{"line":451,"column":null}},"112":{"start":{"line":454,"column":8},"end":{"line":462,"column":null}},"113":{"start":{"line":466,"column":4},"end":{"line":466,"column":null}},"114":{"start":{"line":473,"column":38},"end":{"line":473,"column":null}},"115":{"start":{"line":474,"column":18},"end":{"line":474,"column":null}},"116":{"start":{"line":477,"column":4},"end":{"line":507,"column":null}},"117":{"start":{"line":479,"column":20},"end":{"line":481,"column":null}},"118":{"start":{"line":482,"column":20},"end":{"line":482,"column":null}},"119":{"start":{"line":484,"column":6},"end":{"line":506,"column":null}},"120":{"start":{"line":485,"column":21},"end":{"line":485,"column":null}},"121":{"start":{"line":489,"column":8},"end":{"line":497,"column":null}},"122":{"start":{"line":489,"column":21},"end":{"line":489,"column":32}},"123":{"start":{"line":490,"column":32},"end":{"line":492,"column":null}},"124":{"start":{"line":493,"column":10},"end":{"line":496,"column":null}},"125":{"start":{"line":494,"column":12},"end":{"line":494,"column":null}},"126":{"start":{"line":495,"column":12},"end":{"line":495,"column":null}},"127":{"start":{"line":499,"column":8},"end":{"line":505,"column":null}},"128":{"start":{"line":509,"column":4},"end":{"line":509,"column":null}},"129":{"start":{"line":514,"column":15},"end":{"line":514,"column":null}},"130":{"start":{"line":515,"column":4},"end":{"line":519,"column":null}},"131":{"start":{"line":515,"column":17},"end":{"line":515,"column":20}},"132":{"start":{"line":516,"column":19},"end":{"line":516,"column":null}},"133":{"start":{"line":517,"column":6},"end":{"line":517,"column":null}},"134":{"start":{"line":518,"column":6},"end":{"line":518,"column":null}},"135":{"start":{"line":520,"column":4},"end":{"line":520,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":111,"column":8},"end":{"line":111,"column":36}},"loc":{"start":{"line":111,"column":36},"end":{"line":115,"column":null}},"line":111},"1":{"name":"(anonymous_1)","decl":{"start":{"line":117,"column":2},"end":{"line":117,"column":12}},"loc":{"start":{"line":117,"column":70},"end":{"line":156,"column":null}},"line":117},"2":{"name":"(anonymous_2)","decl":{"start":{"line":158,"column":10},"end":{"line":158,"column":27}},"loc":{"start":{"line":158,"column":78},"end":{"line":214,"column":null}},"line":158},"3":{"name":"(anonymous_3)","decl":{"start":{"line":181,"column":32},"end":{"line":181,"column":33}},"loc":{"start":{"line":181,"column":49},"end":{"line":211,"column":5}},"line":181},"4":{"name":"(anonymous_4)","decl":{"start":{"line":195,"column":19},"end":{"line":195,"column":20}},"loc":{"start":{"line":195,"column":26},"end":{"line":195,"column":34}},"line":195},"5":{"name":"(anonymous_5)","decl":{"start":{"line":216,"column":10},"end":{"line":216,"column":25}},"loc":{"start":{"line":216,"column":73},"end":{"line":272,"column":null}},"line":216},"6":{"name":"(anonymous_6)","decl":{"start":{"line":220,"column":18},"end":{"line":220,"column":19}},"loc":{"start":{"line":220,"column":35},"end":{"line":269,"column":5}},"line":220},"7":{"name":"(anonymous_7)","decl":{"start":{"line":274,"column":10},"end":{"line":274,"column":27}},"loc":{"start":{"line":274,"column":78},"end":{"line":302,"column":null}},"line":274},"8":{"name":"(anonymous_8)","decl":{"start":{"line":278,"column":18},"end":{"line":278,"column":19}},"loc":{"start":{"line":278,"column":35},"end":{"line":299,"column":5}},"line":278},"9":{"name":"(anonymous_9)","decl":{"start":{"line":304,"column":10},"end":{"line":304,"column":25}},"loc":{"start":{"line":304,"column":74},"end":{"line":344,"column":null}},"line":304},"10":{"name":"(anonymous_10)","decl":{"start":{"line":308,"column":18},"end":{"line":308,"column":19}},"loc":{"start":{"line":308,"column":35},"end":{"line":341,"column":5}},"line":308},"11":{"name":"(anonymous_11)","decl":{"start":{"line":324,"column":17},"end":{"line":324,"column":18}},"loc":{"start":{"line":324,"column":24},"end":{"line":324,"column":32}},"line":324},"12":{"name":"(anonymous_12)","decl":{"start":{"line":326,"column":17},"end":{"line":326,"column":18}},"loc":{"start":{"line":326,"column":24},"end":{"line":331,"column":13}},"line":326},"13":{"name":"(anonymous_13)","decl":{"start":{"line":328,"column":38},"end":{"line":328,"column":39}},"loc":{"start":{"line":328,"column":45},"end":{"line":328,"column":53}},"line":328},"14":{"name":"(anonymous_14)","decl":{"start":{"line":346,"column":10},"end":{"line":346,"column":25}},"loc":{"start":{"line":346,"column":74},"end":{"line":394,"column":null}},"line":346},"15":{"name":"(anonymous_15)","decl":{"start":{"line":350,"column":18},"end":{"line":350,"column":19}},"loc":{"start":{"line":350,"column":35},"end":{"line":391,"column":5}},"line":350},"16":{"name":"(anonymous_16)","decl":{"start":{"line":378,"column":55},"end":{"line":378,"column":56}},"loc":{"start":{"line":378,"column":62},"end":{"line":378,"column":70}},"line":378},"17":{"name":"(anonymous_17)","decl":{"start":{"line":381,"column":22},"end":{"line":381,"column":23}},"loc":{"start":{"line":381,"column":32},"end":{"line":389,"column":9}},"line":381},"18":{"name":"(anonymous_18)","decl":{"start":{"line":396,"column":10},"end":{"line":396,"column":23}},"loc":{"start":{"line":396,"column":68},"end":{"line":416,"column":null}},"line":396},"19":{"name":"(anonymous_19)","decl":{"start":{"line":418,"column":10},"end":{"line":418,"column":null}},"loc":{"start":{"line":421,"column":21},"end":{"line":467,"column":null}},"line":421},"20":{"name":"(anonymous_20)","decl":{"start":{"line":425,"column":18},"end":{"line":425,"column":19}},"loc":{"start":{"line":425,"column":35},"end":{"line":464,"column":5}},"line":425},"21":{"name":"(anonymous_21)","decl":{"start":{"line":472,"column":10},"end":{"line":472,"column":27}},"loc":{"start":{"line":472,"column":78},"end":{"line":510,"column":null}},"line":472},"22":{"name":"(anonymous_22)","decl":{"start":{"line":477,"column":18},"end":{"line":477,"column":19}},"loc":{"start":{"line":477,"column":35},"end":{"line":507,"column":5}},"line":477},"23":{"name":"(anonymous_23)","decl":{"start":{"line":512,"column":10},"end":{"line":512,"column":22}},"loc":{"start":{"line":512,"column":47},"end":{"line":521,"column":null}},"line":512}},"branchMap":{"0":{"loc":{"start":{"line":119,"column":26},"end":{"line":119,"column":null}},"type":"binary-expr","locations":[{"start":{"line":119,"column":26},"end":{"line":119,"column":52}},{"start":{"line":119,"column":52},"end":{"line":119,"column":null}}],"line":119},"1":{"loc":{"start":{"line":188,"column":10},"end":{"line":190,"column":null}},"type":"if","locations":[{"start":{"line":188,"column":10},"end":{"line":190,"column":null}},{"start":{},"end":{}}],"line":188},"2":{"loc":{"start":{"line":193,"column":12},"end":{"line":196,"column":null}},"type":"binary-expr","locations":[{"start":{"line":193,"column":12},"end":{"line":196,"column":34}},{"start":{"line":196,"column":34},"end":{"line":196,"column":null}}],"line":193},"3":{"loc":{"start":{"line":202,"column":18},"end":{"line":202,"column":null}},"type":"cond-expr","locations":[{"start":{"line":202,"column":40},"end":{"line":202,"column":50}},{"start":{"line":202,"column":50},"end":{"line":202,"column":null}}],"line":202},"4":{"loc":{"start":{"line":225,"column":6},"end":{"line":238,"column":null}},"type":"if","locations":[{"start":{"line":225,"column":6},"end":{"line":238,"column":null}},{"start":{},"end":{}}],"line":225},"5":{"loc":{"start":{"line":234,"column":19},"end":{"line":236,"column":null}},"type":"cond-expr","locations":[{"start":{"line":235,"column":14},"end":{"line":235,"column":null}},{"start":{"line":236,"column":14},"end":{"line":236,"column":null}}],"line":234},"6":{"loc":{"start":{"line":244,"column":6},"end":{"line":255,"column":null}},"type":"if","locations":[{"start":{"line":244,"column":6},"end":{"line":255,"column":null}},{"start":{},"end":{}}],"line":244},"7":{"loc":{"start":{"line":258,"column":6},"end":{"line":268,"column":null}},"type":"if","locations":[{"start":{"line":258,"column":6},"end":{"line":268,"column":null}},{"start":{},"end":{}}],"line":258},"8":{"loc":{"start":{"line":283,"column":6},"end":{"line":298,"column":null}},"type":"if","locations":[{"start":{"line":283,"column":6},"end":{"line":298,"column":null}},{"start":{},"end":{}}],"line":283},"9":{"loc":{"start":{"line":283,"column":10},"end":{"line":283,"column":40}},"type":"binary-expr","locations":[{"start":{"line":283,"column":10},"end":{"line":283,"column":19}},{"start":{"line":283,"column":19},"end":{"line":283,"column":40}}],"line":283},"10":{"loc":{"start":{"line":288,"column":16},"end":{"line":292,"column":null}},"type":"cond-expr","locations":[{"start":{"line":289,"column":14},"end":{"line":289,"column":null}},{"start":{"line":290,"column":14},"end":{"line":292,"column":null}}],"line":288},"11":{"loc":{"start":{"line":290,"column":14},"end":{"line":292,"column":null}},"type":"cond-expr","locations":[{"start":{"line":291,"column":16},"end":{"line":291,"column":null}},{"start":{"line":292,"column":16},"end":{"line":292,"column":null}}],"line":290},"12":{"loc":{"start":{"line":313,"column":6},"end":{"line":340,"column":null}},"type":"if","locations":[{"start":{"line":313,"column":6},"end":{"line":340,"column":null}},{"start":{},"end":{}}],"line":313},"13":{"loc":{"start":{"line":315,"column":29},"end":{"line":315,"column":null}},"type":"binary-expr","locations":[{"start":{"line":315,"column":29},"end":{"line":315,"column":41}},{"start":{"line":315,"column":41},"end":{"line":315,"column":53}},{"start":{"line":315,"column":53},"end":{"line":315,"column":null}}],"line":315},"14":{"loc":{"start":{"line":316,"column":30},"end":{"line":316,"column":null}},"type":"binary-expr","locations":[{"start":{"line":316,"column":30},"end":{"line":316,"column":43}},{"start":{"line":316,"column":43},"end":{"line":316,"column":null}}],"line":316},"15":{"loc":{"start":{"line":316,"column":43},"end":{"line":316,"column":null}},"type":"cond-expr","locations":[{"start":{"line":316,"column":54},"end":{"line":316,"column":65}},{"start":{"line":316,"column":65},"end":{"line":316,"column":null}}],"line":316},"16":{"loc":{"start":{"line":319,"column":14},"end":{"line":321,"column":null}},"type":"cond-expr","locations":[{"start":{"line":320,"column":14},"end":{"line":320,"column":null}},{"start":{"line":321,"column":14},"end":{"line":321,"column":null}}],"line":319},"17":{"loc":{"start":{"line":327,"column":39},"end":{"line":329,"column":null}},"type":"cond-expr","locations":[{"start":{"line":328,"column":18},"end":{"line":328,"column":null}},{"start":{"line":329,"column":18},"end":{"line":329,"column":null}}],"line":327},"18":{"loc":{"start":{"line":353,"column":6},"end":{"line":360,"column":null}},"type":"if","locations":[{"start":{"line":353,"column":6},"end":{"line":360,"column":null}},{"start":{},"end":{}}],"line":353},"19":{"loc":{"start":{"line":365,"column":6},"end":{"line":372,"column":null}},"type":"if","locations":[{"start":{"line":365,"column":6},"end":{"line":372,"column":null}},{"start":{},"end":{}}],"line":365},"20":{"loc":{"start":{"line":377,"column":6},"end":{"line":390,"column":null}},"type":"if","locations":[{"start":{"line":377,"column":6},"end":{"line":390,"column":null}},{"start":{},"end":{}}],"line":377},"21":{"loc":{"start":{"line":378,"column":22},"end":{"line":380,"column":null}},"type":"binary-expr","locations":[{"start":{"line":378,"column":22},"end":{"line":378,"column":75}},{"start":{"line":378,"column":75},"end":{"line":380,"column":null}}],"line":378},"22":{"loc":{"start":{"line":403,"column":8},"end":{"line":411,"column":null}},"type":"if","locations":[{"start":{"line":403,"column":8},"end":{"line":411,"column":null}},{"start":{"line":406,"column":8},"end":{"line":411,"column":null}}],"line":403},"23":{"loc":{"start":{"line":406,"column":8},"end":{"line":411,"column":null}},"type":"if","locations":[{"start":{"line":406,"column":8},"end":{"line":411,"column":null}},{"start":{},"end":{}}],"line":406},"24":{"loc":{"start":{"line":408,"column":10},"end":{"line":410,"column":null}},"type":"if","locations":[{"start":{"line":408,"column":10},"end":{"line":410,"column":null}},{"start":{},"end":{}}],"line":408},"25":{"loc":{"start":{"line":408,"column":14},"end":{"line":408,"column":45}},"type":"binary-expr","locations":[{"start":{"line":408,"column":14},"end":{"line":408,"column":27}},{"start":{"line":408,"column":27},"end":{"line":408,"column":45}}],"line":408},"26":{"loc":{"start":{"line":433,"column":6},"end":{"line":463,"column":null}},"type":"if","locations":[{"start":{"line":433,"column":6},"end":{"line":463,"column":null}},{"start":{},"end":{}}],"line":433},"27":{"loc":{"start":{"line":444,"column":8},"end":{"line":452,"column":null}},"type":"if","locations":[{"start":{"line":444,"column":8},"end":{"line":452,"column":null}},{"start":{"line":446,"column":8},"end":{"line":452,"column":null}}],"line":444},"28":{"loc":{"start":{"line":446,"column":8},"end":{"line":452,"column":null}},"type":"if","locations":[{"start":{"line":446,"column":8},"end":{"line":452,"column":null}},{"start":{"line":448,"column":8},"end":{"line":452,"column":null}}],"line":446},"29":{"loc":{"start":{"line":448,"column":8},"end":{"line":452,"column":null}},"type":"if","locations":[{"start":{"line":448,"column":8},"end":{"line":452,"column":null}},{"start":{"line":450,"column":8},"end":{"line":452,"column":null}}],"line":448},"30":{"loc":{"start":{"line":450,"column":8},"end":{"line":452,"column":null}},"type":"if","locations":[{"start":{"line":450,"column":8},"end":{"line":452,"column":null}},{"start":{},"end":{}}],"line":450},"31":{"loc":{"start":{"line":484,"column":6},"end":{"line":506,"column":null}},"type":"if","locations":[{"start":{"line":484,"column":6},"end":{"line":506,"column":null}},{"start":{},"end":{}}],"line":484},"32":{"loc":{"start":{"line":493,"column":10},"end":{"line":496,"column":null}},"type":"if","locations":[{"start":{"line":493,"column":10},"end":{"line":496,"column":null}},{"start":{},"end":{}}],"line":493}},"s":{"0":0,"1":2,"2":2,"3":2,"4":2,"5":2,"6":2,"7":2,"8":2,"9":2,"10":2,"11":2,"12":2,"13":2,"14":2,"15":2,"16":2,"17":2,"18":2,"19":2,"20":4,"21":12,"22":1,"23":1,"24":0,"25":1,"26":1,"27":1,"28":1,"29":2,"30":2,"31":2,"32":2,"33":4,"34":4,"35":0,"36":4,"37":4,"38":0,"39":4,"40":4,"41":0,"42":2,"43":2,"44":2,"45":2,"46":4,"47":4,"48":1,"49":2,"50":2,"51":2,"52":2,"53":4,"54":4,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":2,"65":2,"66":2,"67":2,"68":4,"69":4,"70":0,"71":4,"72":4,"73":2,"74":4,"75":4,"76":0,"77":0,"78":0,"79":0,"80":2,"81":2,"82":2,"83":2,"84":2,"85":2,"86":2,"87":90,"88":2,"89":2,"90":88,"91":2,"92":2,"93":2,"94":0,"95":2,"96":2,"97":2,"98":4,"99":4,"100":4,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":2,"114":2,"115":2,"116":2,"117":4,"118":4,"119":4,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":0,"127":0,"128":2,"129":2,"130":2,"131":2,"132":70,"133":70,"134":70,"135":2},"f":{"0":0,"1":2,"2":2,"3":4,"4":1,"5":2,"6":4,"7":2,"8":4,"9":2,"10":4,"11":0,"12":0,"13":0,"14":2,"15":4,"16":0,"17":0,"18":2,"19":2,"20":4,"21":2,"22":4,"23":2},"b":{"0":[2,0],"1":[0,1],"2":[1,0],"3":[0,1],"4":[0,4],"5":[0,0],"6":[0,4],"7":[0,4],"8":[1,3],"9":[4,1],"10":[1,0],"11":[0,0],"12":[0,4],"13":[0,0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,4],"19":[2,2],"20":[0,4],"21":[0,0],"22":[2,88],"23":[2,86],"24":[2,0],"25":[2,2],"26":[0,4],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,4],"32":[0,0]},"meta":{"lastBranch":33,"lastFunction":24,"lastStatement":136,"seen":{"f:111:8:111:36":0,"s:114:4:114:Infinity":0,"f:117:2:117:12":1,"s:118:20:118:Infinity":1,"s:119:26:119:Infinity":2,"b:119:26:119:52:119:52:119:Infinity":0,"s:120:25:120:Infinity":3,"s:121:17:121:Infinity":4,"s:122:18:122:Infinity":5,"s:123:16:123:Infinity":6,"s:126:22:126:Infinity":7,"s:127:20:127:Infinity":8,"s:128:22:128:Infinity":9,"s:129:20:129:Infinity":10,"s:130:20:130:Infinity":11,"s:131:23:131:Infinity":12,"s:132:22:132:Infinity":13,"s:134:4:155:Infinity":14,"f:158:10:158:27":2,"s:159:38:159:Infinity":15,"s:160:18:160:Infinity":16,"s:163:32:172:Infinity":17,"s:175:21:179:Infinity":18,"s:181:4:211:Infinity":19,"f:181:32:181:33":3,"s:182:6:210:Infinity":20,"s:184:8:209:Infinity":21,"s:185:23:185:Infinity":22,"b:188:10:190:Infinity:undefined:undefined:undefined:undefined":1,"s:188:10:190:Infinity":23,"s:189:12:189:Infinity":24,"s:193:12:196:Infinity":25,"b:193:12:196:34:196:34:196:Infinity":2,"f:195:19:195:20":4,"s:195:26:195:34":26,"s:197:29:197:Infinity":27,"s:199:10:208:Infinity":28,"b:202:40:202:50:202:50:202:Infinity":3,"s:213:4:213:Infinity":29,"f:216:10:216:25":5,"s:217:33:217:Infinity":30,"s:218:18:218:Infinity":31,"s:220:4:269:Infinity":32,"f:220:18:220:19":6,"s:222:8:224:Infinity":33,"b:225:6:238:Infinity:undefined:undefined:undefined:undefined":4,"s:225:6:238:Infinity":34,"s:226:8:237:Infinity":35,"b:235:14:235:Infinity:236:14:236:Infinity":5,"s:241:8:243:Infinity":36,"b:244:6:255:Infinity:undefined:undefined:undefined:undefined":6,"s:244:6:255:Infinity":37,"s:245:8:254:Infinity":38,"s:257:24:257:Infinity":39,"b:258:6:268:Infinity:undefined:undefined:undefined:undefined":7,"s:258:6:268:Infinity":40,"s:259:8:267:Infinity":41,"s:271:4:271:Infinity":42,"f:274:10:274:27":7,"s:275:38:275:Infinity":43,"s:276:18:276:Infinity":44,"s:278:4:299:Infinity":45,"f:278:18:278:19":8,"s:280:8:282:Infinity":46,"b:283:6:298:Infinity:undefined:undefined:undefined:undefined":8,"s:283:6:298:Infinity":47,"b:283:10:283:19:283:19:283:40":9,"s:285:8:297:Infinity":48,"b:289:14:289:Infinity:290:14:292:Infinity":10,"b:291:16:291:Infinity:292:16:292:Infinity":11,"s:301:4:301:Infinity":49,"f:304:10:304:25":9,"s:305:34:305:Infinity":50,"s:306:18:306:Infinity":51,"s:308:4:341:Infinity":52,"f:308:18:308:19":10,"s:310:8:312:Infinity":53,"b:313:6:340:Infinity:undefined:undefined:undefined:undefined":12,"s:313:6:340:Infinity":54,"s:314:23:314:Infinity":55,"s:315:29:315:Infinity":56,"b:315:29:315:41:315:41:315:53:315:53:315:Infinity":13,"s:316:30:316:Infinity":57,"b:316:30:316:43:316:43:316:Infinity":14,"b:316:54:316:65:316:65:316:Infinity":15,"s:318:27:332:Infinity":58,"b:320:14:320:Infinity:321:14:321:Infinity":16,"f:324:17:324:18":11,"s:324:24:324:32":59,"f:326:17:326:18":12,"s:327:39:329:Infinity":60,"b:328:18:328:Infinity:329:18:329:Infinity":17,"f:328:38:328:39":13,"s:328:45:328:53":61,"s:330:14:330:Infinity":62,"s:334:8:339:Infinity":63,"s:343:4:343:Infinity":64,"f:346:10:346:25":14,"s:347:34:347:Infinity":65,"s:348:18:348:Infinity":66,"s:350:4:391:Infinity":67,"f:350:18:350:19":15,"s:352:27:352:Infinity":68,"b:353:6:360:Infinity:undefined:undefined:undefined:undefined":18,"s:353:6:360:Infinity":69,"s:354:8:359:Infinity":70,"s:364:8:364:Infinity":71,"b:365:6:372:Infinity:undefined:undefined:undefined:undefined":19,"s:365:6:372:Infinity":72,"s:366:8:371:Infinity":73,"s:376:8:376:Infinity":74,"b:377:6:390:Infinity:undefined:undefined:undefined:undefined":20,"s:377:6:390:Infinity":75,"s:378:22:380:Infinity":76,"b:378:22:378:75:378:75:380:Infinity":21,"f:378:55:378:56":16,"s:378:62:378:70":77,"s:381:8:389:Infinity":78,"f:381:22:381:23":17,"s:382:10:388:Infinity":79,"s:393:4:393:Infinity":80,"f:396:10:396:23":18,"s:397:21:397:Infinity":81,"s:398:20:398:Infinity":82,"s:400:4:413:Infinity":83,"s:400:17:400:29":84,"s:401:19:401:Infinity":85,"s:402:6:412:Infinity":86,"b:403:8:411:Infinity:406:8:411:Infinity":22,"s:403:8:411:Infinity":87,"s:404:10:404:Infinity":88,"s:405:10:405:Infinity":89,"b:406:8:411:Infinity:undefined:undefined:undefined:undefined":23,"s:406:8:411:Infinity":90,"s:407:10:407:Infinity":91,"b:408:10:410:Infinity:undefined:undefined:undefined:undefined":24,"s:408:10:410:Infinity":92,"b:408:14:408:27:408:27:408:45":25,"s:409:12:409:Infinity":93,"s:415:4:415:Infinity":94,"f:418:10:418:Infinity":19,"s:422:40:422:Infinity":95,"s:423:18:423:Infinity":96,"s:425:4:464:Infinity":97,"f:425:18:425:19":20,"s:428:20:430:Infinity":98,"s:431:6:431:Infinity":99,"b:433:6:463:Infinity:undefined:undefined:undefined:undefined":26,"s:433:6:463:Infinity":100,"s:434:21:434:Infinity":101,"s:435:21:435:Infinity":102,"s:443:24:443:Infinity":103,"b:444:8:452:Infinity:446:8:452:Infinity":27,"s:444:8:452:Infinity":104,"s:445:10:445:Infinity":105,"b:446:8:452:Infinity:448:8:452:Infinity":28,"s:446:8:452:Infinity":106,"s:447:10:447:Infinity":107,"b:448:8:452:Infinity:450:8:452:Infinity":29,"s:448:8:452:Infinity":108,"s:449:10:449:Infinity":109,"b:450:8:452:Infinity:undefined:undefined:undefined:undefined":30,"s:450:8:452:Infinity":110,"s:451:10:451:Infinity":111,"s:454:8:462:Infinity":112,"s:466:4:466:Infinity":113,"f:472:10:472:27":21,"s:473:38:473:Infinity":114,"s:474:18:474:Infinity":115,"s:477:4:507:Infinity":116,"f:477:18:477:19":22,"s:479:20:481:Infinity":117,"s:482:20:482:Infinity":118,"b:484:6:506:Infinity:undefined:undefined:undefined:undefined":31,"s:484:6:506:Infinity":119,"s:485:21:485:Infinity":120,"s:489:8:497:Infinity":121,"s:489:21:489:32":122,"s:490:32:492:Infinity":123,"b:493:10:496:Infinity:undefined:undefined:undefined:undefined":32,"s:493:10:496:Infinity":124,"s:494:12:494:Infinity":125,"s:495:12:495:Infinity":126,"s:499:8:505:Infinity":127,"s:509:4:509:Infinity":128,"f:512:10:512:22":23,"s:514:15:514:Infinity":129,"s:515:4:519:Infinity":130,"s:515:17:515:20":131,"s:516:19:516:Infinity":132,"s:517:6:517:Infinity":133,"s:518:6:518:Infinity":134,"s:520:4:520:Infinity":135}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/response/budget.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/response/budget.ts","statementMap":{"0":{"start":{"line":3,"column":70},"end":{"line":7,"column":null}},"1":{"start":{"line":23,"column":45},"end":{"line":29,"column":null}},"2":{"start":{"line":35,"column":2},"end":{"line":39,"column":null}},"3":{"start":{"line":43,"column":15},"end":{"line":43,"column":null}},"4":{"start":{"line":44,"column":2},"end":{"line":44,"column":null}},"5":{"start":{"line":52,"column":19},"end":{"line":52,"column":null}},"6":{"start":{"line":53,"column":24},"end":{"line":53,"column":null}},"7":{"start":{"line":55,"column":2},"end":{"line":63,"column":null}},"8":{"start":{"line":56,"column":21},"end":{"line":56,"column":null}},"9":{"start":{"line":57,"column":4},"end":{"line":59,"column":null}},"10":{"start":{"line":58,"column":6},"end":{"line":58,"column":null}},"11":{"start":{"line":61,"column":4},"end":{"line":61,"column":null}},"12":{"start":{"line":62,"column":4},"end":{"line":62,"column":null}},"13":{"start":{"line":65,"column":2},"end":{"line":65,"column":null}}},"fnMap":{"0":{"name":"makeBudget","decl":{"start":{"line":31,"column":16},"end":{"line":31,"column":null}},"loc":{"start":{"line":34,"column":17},"end":{"line":40,"column":null}},"line":34},"1":{"name":"estimateTokens","decl":{"start":{"line":42,"column":16},"end":{"line":42,"column":31}},"loc":{"start":{"line":42,"column":55},"end":{"line":45,"column":null}},"line":42},"2":{"name":"fillSlot","decl":{"start":{"line":47,"column":16},"end":{"line":47,"column":null}},"loc":{"start":{"line":51,"column":41},"end":{"line":66,"column":null}},"line":51}},"branchMap":{"0":{"loc":{"start":{"line":36,"column":15},"end":{"line":36,"column":null}},"type":"binary-expr","locations":[{"start":{"line":36,"column":15},"end":{"line":36,"column":38}},{"start":{"line":36,"column":38},"end":{"line":36,"column":null}}],"line":36},"1":{"loc":{"start":{"line":38,"column":16},"end":{"line":38,"column":null}},"type":"binary-expr","locations":[{"start":{"line":38,"column":16},"end":{"line":38,"column":40}},{"start":{"line":38,"column":40},"end":{"line":38,"column":null}}],"line":38},"2":{"loc":{"start":{"line":43,"column":15},"end":{"line":43,"column":null}},"type":"cond-expr","locations":[{"start":{"line":43,"column":43},"end":{"line":43,"column":51}},{"start":{"line":43,"column":51},"end":{"line":43,"column":null}}],"line":43},"3":{"loc":{"start":{"line":57,"column":4},"end":{"line":59,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":4},"end":{"line":59,"column":null}},{"start":{},"end":{}}],"line":57}},"s":{"0":3,"1":3,"2":61,"3":75,"4":75,"5":3,"6":3,"7":3,"8":10,"9":10,"10":5,"11":5,"12":5,"13":3},"f":{"0":61,"1":75,"2":3},"b":{"0":[61,60],"1":[61,60],"2":[17,58],"3":[5,5]},"meta":{"lastBranch":4,"lastFunction":3,"lastStatement":14,"seen":{"s:3:70:7:Infinity":0,"s:23:45:29:Infinity":1,"f:31:16:31:Infinity":0,"s:35:2:39:Infinity":2,"b:36:15:36:38:36:38:36:Infinity":0,"b:38:16:38:40:38:40:38:Infinity":1,"f:42:16:42:31":1,"s:43:15:43:Infinity":3,"b:43:43:43:51:43:51:43:Infinity":2,"s:44:2:44:Infinity":4,"f:47:16:47:Infinity":2,"s:52:19:52:Infinity":5,"s:53:24:53:Infinity":6,"s:55:2:63:Infinity":7,"s:56:21:56:Infinity":8,"b:57:4:59:Infinity:undefined:undefined:undefined:undefined":3,"s:57:4:59:Infinity":9,"s:58:6:58:Infinity":10,"s:61:4:61:Infinity":11,"s:62:4:62:Infinity":12,"s:65:2:65:Infinity":13}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/response/schemas.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/response/schemas.ts","statementMap":{"0":{"start":{"line":9,"column":66},"end":{"line":370,"column":null}},"1":{"start":{"line":372,"column":40},"end":{"line":372,"column":null}},"2":{"start":{"line":379,"column":42},"end":{"line":379,"column":null}},"3":{"start":{"line":380,"column":19},"end":{"line":382,"column":null}},"4":{"start":{"line":381,"column":29},"end":{"line":381,"column":58}},"5":{"start":{"line":381,"column":71},"end":{"line":381,"column":76}},"6":{"start":{"line":384,"column":2},"end":{"line":404,"column":null}},"7":{"start":{"line":385,"column":4},"end":{"line":387,"column":null}},"8":{"start":{"line":386,"column":6},"end":{"line":386,"column":null}},"9":{"start":{"line":389,"column":23},"end":{"line":391,"column":null}},"10":{"start":{"line":390,"column":25},"end":{"line":390,"column":52}},"11":{"start":{"line":391,"column":22},"end":{"line":391,"column":31}},"12":{"start":{"line":393,"column":4},"end":{"line":403,"column":null}},"13":{"start":{"line":394,"column":6},"end":{"line":396,"column":null}},"14":{"start":{"line":395,"column":8},"end":{"line":395,"column":null}},"15":{"start":{"line":397,"column":6},"end":{"line":399,"column":null}},"16":{"start":{"line":398,"column":8},"end":{"line":398,"column":null}},"17":{"start":{"line":400,"column":6},"end":{"line":402,"column":null}},"18":{"start":{"line":401,"column":8},"end":{"line":401,"column":null}},"19":{"start":{"line":406,"column":2},"end":{"line":406,"column":null}}},"fnMap":{"0":{"name":"applyFieldPriority","decl":{"start":{"line":374,"column":16},"end":{"line":374,"column":null}},"loc":{"start":{"line":378,"column":27},"end":{"line":407,"column":null}},"line":378},"1":{"name":"(anonymous_1)","decl":{"start":{"line":381,"column":18},"end":{"line":381,"column":19}},"loc":{"start":{"line":381,"column":29},"end":{"line":381,"column":58}},"line":381},"2":{"name":"(anonymous_2)","decl":{"start":{"line":381,"column":64},"end":{"line":381,"column":65}},"loc":{"start":{"line":381,"column":71},"end":{"line":381,"column":76}},"line":381},"3":{"name":"(anonymous_3)","decl":{"start":{"line":390,"column":14},"end":{"line":390,"column":15}},"loc":{"start":{"line":390,"column":25},"end":{"line":390,"column":52}},"line":390},"4":{"name":"(anonymous_4)","decl":{"start":{"line":391,"column":11},"end":{"line":391,"column":12}},"loc":{"start":{"line":391,"column":22},"end":{"line":391,"column":31}},"line":391}},"branchMap":{"0":{"loc":{"start":{"line":385,"column":4},"end":{"line":387,"column":null}},"type":"if","locations":[{"start":{"line":385,"column":4},"end":{"line":387,"column":null}},{"start":{},"end":{}}],"line":385},"1":{"loc":{"start":{"line":394,"column":6},"end":{"line":396,"column":null}},"type":"if","locations":[{"start":{"line":394,"column":6},"end":{"line":396,"column":null}},{"start":{},"end":{}}],"line":394},"2":{"loc":{"start":{"line":397,"column":6},"end":{"line":399,"column":null}},"type":"if","locations":[{"start":{"line":397,"column":6},"end":{"line":399,"column":null}},{"start":{},"end":{}}],"line":397},"3":{"loc":{"start":{"line":400,"column":6},"end":{"line":402,"column":null}},"type":"if","locations":[{"start":{"line":400,"column":6},"end":{"line":402,"column":null}},{"start":{},"end":{}}],"line":400}},"s":{"0":3,"1":3,"2":7,"3":7,"4":26,"5":10,"6":7,"7":13,"8":5,"9":8,"10":23,"11":5,"12":8,"13":5,"14":0,"15":5,"16":0,"17":5,"18":4,"19":7},"f":{"0":7,"1":26,"2":10,"3":23,"4":5},"b":{"0":[5,8],"1":[0,5],"2":[0,5],"3":[4,1]},"meta":{"lastBranch":4,"lastFunction":5,"lastStatement":20,"seen":{"s:9:66:370:Infinity":0,"s:372:40:372:Infinity":1,"f:374:16:374:Infinity":0,"s:379:42:379:Infinity":2,"s:380:19:382:Infinity":3,"f:381:18:381:19":1,"s:381:29:381:58":4,"f:381:64:381:65":2,"s:381:71:381:76":5,"s:384:2:404:Infinity":6,"b:385:4:387:Infinity:undefined:undefined:undefined:undefined":0,"s:385:4:387:Infinity":7,"s:386:6:386:Infinity":8,"s:389:23:391:Infinity":9,"f:390:14:390:15":3,"s:390:25:390:52":10,"f:391:11:391:12":4,"s:391:22:391:31":11,"s:393:4:403:Infinity":12,"b:394:6:396:Infinity:undefined:undefined:undefined:undefined":1,"s:394:6:396:Infinity":13,"s:395:8:395:Infinity":14,"b:397:6:399:Infinity:undefined:undefined:undefined:undefined":2,"s:397:6:399:Infinity":15,"s:398:8:398:Infinity":16,"b:400:6:402:Infinity:undefined:undefined:undefined:undefined":3,"s:400:6:402:Infinity":17,"s:401:8:401:Infinity":18,"s:406:2:406:Infinity":19}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/response/shaper.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/response/shaper.ts","statementMap":{"0":{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},"1":{"start":{"line":16,"column":4},"end":{"line":16,"column":null}},"2":{"start":{"line":18,"column":2},"end":{"line":18,"column":null}},"3":{"start":{"line":26,"column":19},"end":{"line":26,"column":null}},"4":{"start":{"line":28,"column":4},"end":{"line":32,"column":null}},"5":{"start":{"line":34,"column":4},"end":{"line":38,"column":null}},"6":{"start":{"line":40,"column":4},"end":{"line":44,"column":null}},"7":{"start":{"line":46,"column":2},"end":{"line":48,"column":null}},"8":{"start":{"line":47,"column":4},"end":{"line":47,"column":null}},"9":{"start":{"line":50,"column":2},"end":{"line":52,"column":null}},"10":{"start":{"line":51,"column":4},"end":{"line":51,"column":null}},"11":{"start":{"line":54,"column":2},"end":{"line":61,"column":null}},"12":{"start":{"line":55,"column":20},"end":{"line":55,"column":null}},"13":{"start":{"line":56,"column":19},"end":{"line":56,"column":null}},"14":{"start":{"line":56,"column":41},"end":{"line":56,"column":77}},"15":{"start":{"line":57,"column":4},"end":{"line":59,"column":null}},"16":{"start":{"line":58,"column":6},"end":{"line":58,"column":null}},"17":{"start":{"line":60,"column":4},"end":{"line":60,"column":null}},"18":{"start":{"line":63,"column":2},"end":{"line":77,"column":null}},"19":{"start":{"line":64,"column":20},"end":{"line":67,"column":null}},"20":{"start":{"line":68,"column":19},"end":{"line":70,"column":null}},"21":{"start":{"line":69,"column":35},"end":{"line":69,"column":78}},"22":{"start":{"line":71,"column":22},"end":{"line":71,"column":null}},"23":{"start":{"line":72,"column":4},"end":{"line":75,"column":null}},"24":{"start":{"line":73,"column":7},"end":{"line":74,"column":null}},"25":{"start":{"line":76,"column":4},"end":{"line":76,"column":null}},"26":{"start":{"line":79,"column":2},"end":{"line":79,"column":null}},"27":{"start":{"line":89,"column":8},"end":{"line":89,"column":null}},"28":{"start":{"line":90,"column":15},"end":{"line":90,"column":null}},"29":{"start":{"line":92,"column":2},"end":{"line":107,"column":null}},"30":{"start":{"line":99,"column":19},"end":{"line":99,"column":null}},"31":{"start":{"line":100,"column":4},"end":{"line":106,"column":null}},"32":{"start":{"line":101,"column":6},"end":{"line":105,"column":null}},"33":{"start":{"line":109,"column":2},"end":{"line":116,"column":null}},"34":{"start":{"line":125,"column":2},"end":{"line":132,"column":null}}},"fnMap":{"0":{"name":"truncateString","decl":{"start":{"line":14,"column":9},"end":{"line":14,"column":24}},"loc":{"start":{"line":14,"column":66},"end":{"line":19,"column":null}},"line":14},"1":{"name":"shapeValue","decl":{"start":{"line":21,"column":9},"end":{"line":21,"column":null}},"loc":{"start":{"line":25,"column":11},"end":{"line":80,"column":null}},"line":25},"2":{"name":"(anonymous_2)","decl":{"start":{"line":56,"column":31},"end":{"line":56,"column":32}},"loc":{"start":{"line":56,"column":41},"end":{"line":56,"column":77}},"line":56},"3":{"name":"(anonymous_3)","decl":{"start":{"line":69,"column":18},"end":{"line":69,"column":19}},"loc":{"start":{"line":69,"column":35},"end":{"line":69,"column":78}},"line":69},"4":{"name":"formatResponse","decl":{"start":{"line":82,"column":16},"end":{"line":82,"column":null}},"loc":{"start":{"line":88,"column":16},"end":{"line":117,"column":null}},"line":88},"5":{"name":"errorResponse","decl":{"start":{"line":119,"column":16},"end":{"line":119,"column":null}},"loc":{"start":{"line":124,"column":16},"end":{"line":133,"column":null}},"line":124}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},"type":"if","locations":[{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},{"start":{},"end":{}}],"line":15},"1":{"loc":{"start":{"line":15,"column":6},"end":{"line":15,"column":64}},"type":"binary-expr","locations":[{"start":{"line":15,"column":6},"end":{"line":15,"column":37}},{"start":{"line":15,"column":37},"end":{"line":15,"column":64}}],"line":15},"2":{"loc":{"start":{"line":24,"column":2},"end":{"line":24,"column":null}},"type":"default-arg","locations":[{"start":{"line":24,"column":10},"end":{"line":24,"column":null}}],"line":24},"3":{"loc":{"start":{"line":26,"column":19},"end":{"line":26,"column":null}},"type":"cond-expr","locations":[{"start":{"line":26,"column":41},"end":{"line":26,"column":46}},{"start":{"line":26,"column":46},"end":{"line":26,"column":null}}],"line":26},"4":{"loc":{"start":{"line":28,"column":4},"end":{"line":32,"column":null}},"type":"cond-expr","locations":[{"start":{"line":29,"column":8},"end":{"line":29,"column":null}},{"start":{"line":30,"column":8},"end":{"line":32,"column":null}}],"line":28},"5":{"loc":{"start":{"line":30,"column":8},"end":{"line":32,"column":null}},"type":"cond-expr","locations":[{"start":{"line":31,"column":10},"end":{"line":31,"column":null}},{"start":{"line":32,"column":10},"end":{"line":32,"column":null}}],"line":30},"6":{"loc":{"start":{"line":34,"column":4},"end":{"line":38,"column":null}},"type":"cond-expr","locations":[{"start":{"line":35,"column":8},"end":{"line":35,"column":null}},{"start":{"line":36,"column":8},"end":{"line":38,"column":null}}],"line":34},"7":{"loc":{"start":{"line":36,"column":8},"end":{"line":38,"column":null}},"type":"cond-expr","locations":[{"start":{"line":37,"column":10},"end":{"line":37,"column":null}},{"start":{"line":38,"column":10},"end":{"line":38,"column":null}}],"line":36},"8":{"loc":{"start":{"line":40,"column":4},"end":{"line":44,"column":null}},"type":"cond-expr","locations":[{"start":{"line":41,"column":8},"end":{"line":41,"column":null}},{"start":{"line":42,"column":8},"end":{"line":44,"column":null}}],"line":40},"9":{"loc":{"start":{"line":42,"column":8},"end":{"line":44,"column":null}},"type":"cond-expr","locations":[{"start":{"line":43,"column":10},"end":{"line":43,"column":null}},{"start":{"line":44,"column":10},"end":{"line":44,"column":null}}],"line":42},"10":{"loc":{"start":{"line":46,"column":2},"end":{"line":48,"column":null}},"type":"if","locations":[{"start":{"line":46,"column":2},"end":{"line":48,"column":null}},{"start":{},"end":{}}],"line":46},"11":{"loc":{"start":{"line":50,"column":2},"end":{"line":52,"column":null}},"type":"if","locations":[{"start":{"line":50,"column":2},"end":{"line":52,"column":null}},{"start":{},"end":{}}],"line":50},"12":{"loc":{"start":{"line":54,"column":2},"end":{"line":61,"column":null}},"type":"if","locations":[{"start":{"line":54,"column":2},"end":{"line":61,"column":null}},{"start":{},"end":{}}],"line":54},"13":{"loc":{"start":{"line":57,"column":4},"end":{"line":59,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":4},"end":{"line":59,"column":null}},{"start":{},"end":{}}],"line":57},"14":{"loc":{"start":{"line":63,"column":2},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":63,"column":2},"end":{"line":77,"column":null}},{"start":{},"end":{}}],"line":63},"15":{"loc":{"start":{"line":63,"column":6},"end":{"line":63,"column":51}},"type":"binary-expr","locations":[{"start":{"line":63,"column":6},"end":{"line":63,"column":24}},{"start":{"line":63,"column":24},"end":{"line":63,"column":51}}],"line":63},"16":{"loc":{"start":{"line":72,"column":4},"end":{"line":75,"column":null}},"type":"if","locations":[{"start":{"line":72,"column":4},"end":{"line":75,"column":null}},{"start":{},"end":{}}],"line":72},"17":{"loc":{"start":{"line":85,"column":2},"end":{"line":85,"column":null}},"type":"default-arg","locations":[{"start":{"line":85,"column":29},"end":{"line":85,"column":null}}],"line":85},"18":{"loc":{"start":{"line":92,"column":2},"end":{"line":107,"column":null}},"type":"if","locations":[{"start":{"line":92,"column":2},"end":{"line":107,"column":null}},{"start":{},"end":{}}],"line":92},"19":{"loc":{"start":{"line":93,"column":4},"end":{"line":97,"column":null}},"type":"binary-expr","locations":[{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},{"start":{"line":94,"column":4},"end":{"line":94,"column":null}},{"start":{"line":95,"column":4},"end":{"line":95,"column":null}},{"start":{"line":96,"column":4},"end":{"line":96,"column":null}},{"start":{"line":97,"column":4},"end":{"line":97,"column":null}}],"line":93},"20":{"loc":{"start":{"line":100,"column":4},"end":{"line":106,"column":null}},"type":"if","locations":[{"start":{"line":100,"column":4},"end":{"line":106,"column":null}},{"start":{},"end":{}}],"line":100},"21":{"loc":{"start":{"line":115,"column":8},"end":{"line":115,"column":null}},"type":"cond-expr","locations":[{"start":{"line":115,"column":15},"end":{"line":115,"column":26}},{"start":{"line":115,"column":26},"end":{"line":115,"column":null}}],"line":115},"22":{"loc":{"start":{"line":123,"column":2},"end":{"line":123,"column":null}},"type":"default-arg","locations":[{"start":{"line":123,"column":29},"end":{"line":123,"column":null}}],"line":123}},"s":{"0":373,"1":373,"2":0,"3":857,"4":857,"5":857,"6":857,"7":857,"8":0,"9":857,"10":373,"11":484,"12":68,"13":68,"14":66,"15":68,"16":0,"17":68,"18":416,"19":163,"20":163,"21":734,"22":163,"23":163,"24":0,"25":163,"26":253,"27":57,"28":57,"29":57,"30":4,"31":4,"32":3,"33":57,"34":15},"f":{"0":373,"1":857,"2":66,"3":734,"4":57,"5":15},"b":{"0":[373,0],"1":[373,74],"2":[857],"3":[646,211],"4":[0,857],"5":[646,211],"6":[0,857],"7":[646,211],"8":[0,857],"9":[646,211],"10":[0,857],"11":[373,484],"12":[68,416],"13":[0,68],"14":[163,253],"15":[416,385],"16":[0,163],"17":[57],"18":[4,53],"19":[57,20,4,4,4],"20":[3,1],"21":[0,57],"22":[15]},"meta":{"lastBranch":23,"lastFunction":6,"lastStatement":35,"seen":{"f:14:9:14:24":0,"b:15:2:17:Infinity:undefined:undefined:undefined:undefined":0,"s:15:2:17:Infinity":0,"b:15:6:15:37:15:37:15:64":1,"s:16:4:16:Infinity":1,"s:18:2:18:Infinity":2,"f:21:9:21:Infinity":1,"b:24:10:24:Infinity":2,"s:26:19:26:Infinity":3,"b:26:41:26:46:26:46:26:Infinity":3,"s:28:4:32:Infinity":4,"b:29:8:29:Infinity:30:8:32:Infinity":4,"b:31:10:31:Infinity:32:10:32:Infinity":5,"s:34:4:38:Infinity":5,"b:35:8:35:Infinity:36:8:38:Infinity":6,"b:37:10:37:Infinity:38:10:38:Infinity":7,"s:40:4:44:Infinity":6,"b:41:8:41:Infinity:42:8:44:Infinity":8,"b:43:10:43:Infinity:44:10:44:Infinity":9,"b:46:2:48:Infinity:undefined:undefined:undefined:undefined":10,"s:46:2:48:Infinity":7,"s:47:4:47:Infinity":8,"b:50:2:52:Infinity:undefined:undefined:undefined:undefined":11,"s:50:2:52:Infinity":9,"s:51:4:51:Infinity":10,"b:54:2:61:Infinity:undefined:undefined:undefined:undefined":12,"s:54:2:61:Infinity":11,"s:55:20:55:Infinity":12,"s:56:19:56:Infinity":13,"f:56:31:56:32":2,"s:56:41:56:77":14,"b:57:4:59:Infinity:undefined:undefined:undefined:undefined":13,"s:57:4:59:Infinity":15,"s:58:6:58:Infinity":16,"s:60:4:60:Infinity":17,"b:63:2:77:Infinity:undefined:undefined:undefined:undefined":14,"s:63:2:77:Infinity":18,"b:63:6:63:24:63:24:63:51":15,"s:64:20:67:Infinity":19,"s:68:19:70:Infinity":20,"f:69:18:69:19":3,"s:69:35:69:78":21,"s:71:22:71:Infinity":22,"b:72:4:75:Infinity:undefined:undefined:undefined:undefined":16,"s:72:4:75:Infinity":23,"s:73:7:74:Infinity":24,"s:76:4:76:Infinity":25,"s:79:2:79:Infinity":26,"f:82:16:82:Infinity":4,"b:85:29:85:Infinity":17,"s:89:8:89:Infinity":27,"s:90:15:90:Infinity":28,"b:92:2:107:Infinity:undefined:undefined:undefined:undefined":18,"s:92:2:107:Infinity":29,"b:93:4:93:Infinity:94:4:94:Infinity:95:4:95:Infinity:96:4:96:Infinity:97:4:97:Infinity":19,"s:99:19:99:Infinity":30,"b:100:4:106:Infinity:undefined:undefined:undefined:undefined":20,"s:100:4:106:Infinity":31,"s:101:6:105:Infinity":32,"s:109:2:116:Infinity":33,"b:115:15:115:26:115:26:115:Infinity":21,"f:119:16:119:Infinity":5,"b:123:29:123:Infinity":22,"s:125:2:132:Infinity":34}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/response/summarizer.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/response/summarizer.ts","statementMap":{"0":{"start":{"line":14,"column":18},"end":{"line":14,"column":null}},"1":{"start":{"line":16,"column":22},"end":{"line":16,"column":44}},"2":{"start":{"line":19,"column":4},"end":{"line":19,"column":null}},"3":{"start":{"line":23,"column":21},"end":{"line":23,"column":null}},"4":{"start":{"line":24,"column":4},"end":{"line":26,"column":null}},"5":{"start":{"line":25,"column":6},"end":{"line":25,"column":null}},"6":{"start":{"line":28,"column":19},"end":{"line":28,"column":null}},"7":{"start":{"line":29,"column":20},"end":{"line":29,"column":null}},"8":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"9":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"10":{"start":{"line":35,"column":4},"end":{"line":37,"column":null}},"11":{"start":{"line":36,"column":6},"end":{"line":36,"column":null}},"12":{"start":{"line":39,"column":23},"end":{"line":39,"column":null}},"13":{"start":{"line":40,"column":20},"end":{"line":40,"column":null}},"14":{"start":{"line":40,"column":37},"end":{"line":40,"column":57}},"15":{"start":{"line":42,"column":4},"end":{"line":88,"column":null}},"16":{"start":{"line":43,"column":23},"end":{"line":55,"column":null}},"17":{"start":{"line":57,"column":6},"end":{"line":59,"column":null}},"18":{"start":{"line":58,"column":8},"end":{"line":58,"column":null}},"19":{"start":{"line":61,"column":23},"end":{"line":61,"column":null}},"20":{"start":{"line":62,"column":6},"end":{"line":64,"column":null}},"21":{"start":{"line":63,"column":8},"end":{"line":63,"column":null}},"22":{"start":{"line":66,"column":6},"end":{"line":81,"column":null}},"23":{"start":{"line":67,"column":20},"end":{"line":67,"column":null}},"24":{"start":{"line":68,"column":8},"end":{"line":70,"column":null}},"25":{"start":{"line":69,"column":10},"end":{"line":69,"column":null}},"26":{"start":{"line":71,"column":8},"end":{"line":80,"column":null}},"27":{"start":{"line":76,"column":10},"end":{"line":79,"column":null}},"28":{"start":{"line":83,"column":6},"end":{"line":83,"column":null}},"29":{"start":{"line":85,"column":6},"end":{"line":85,"column":null}},"30":{"start":{"line":87,"column":6},"end":{"line":87,"column":null}},"31":{"start":{"line":92,"column":17},"end":{"line":92,"column":null}},"32":{"start":{"line":93,"column":17},"end":{"line":93,"column":null}},"33":{"start":{"line":94,"column":16},"end":{"line":94,"column":null}},"34":{"start":{"line":96,"column":4},"end":{"line":101,"column":null}},"35":{"start":{"line":97,"column":24},"end":{"line":97,"column":null}},"36":{"start":{"line":98,"column":22},"end":{"line":98,"column":null}},"37":{"start":{"line":99,"column":22},"end":{"line":99,"column":null}},"38":{"start":{"line":100,"column":6},"end":{"line":100,"column":null}},"39":{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},"40":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"41":{"start":{"line":107,"column":4},"end":{"line":109,"column":null}},"42":{"start":{"line":108,"column":6},"end":{"line":108,"column":null}},"43":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":16,"column":2},"end":{"line":16,"column":22}},"loc":{"start":{"line":16,"column":44},"end":{"line":16,"column":null}},"line":16},"1":{"name":"(anonymous_1)","decl":{"start":{"line":18,"column":2},"end":{"line":18,"column":26}},"loc":{"start":{"line":18,"column":26},"end":{"line":20,"column":null}},"line":18},"2":{"name":"(anonymous_2)","decl":{"start":{"line":22,"column":8},"end":{"line":22,"column":18}},"loc":{"start":{"line":22,"column":56},"end":{"line":32,"column":null}},"line":22},"3":{"name":"(anonymous_3)","decl":{"start":{"line":34,"column":16},"end":{"line":34,"column":33}},"loc":{"start":{"line":34,"column":78},"end":{"line":89,"column":null}},"line":34},"4":{"name":"(anonymous_4)","decl":{"start":{"line":40,"column":31},"end":{"line":40,"column":37}},"loc":{"start":{"line":40,"column":37},"end":{"line":40,"column":57}},"line":40},"5":{"name":"(anonymous_5)","decl":{"start":{"line":91,"column":10},"end":{"line":91,"column":23}},"loc":{"start":{"line":91,"column":52},"end":{"line":112,"column":null}},"line":91}},"branchMap":{"0":{"loc":{"start":{"line":24,"column":4},"end":{"line":26,"column":null}},"type":"if","locations":[{"start":{"line":24,"column":4},"end":{"line":26,"column":null}},{"start":{},"end":{}}],"line":24},"1":{"loc":{"start":{"line":29,"column":20},"end":{"line":29,"column":null}},"type":"binary-expr","locations":[{"start":{"line":29,"column":20},"end":{"line":29,"column":30}},{"start":{"line":29,"column":30},"end":{"line":29,"column":null}}],"line":29},"2":{"loc":{"start":{"line":35,"column":4},"end":{"line":37,"column":null}},"type":"if","locations":[{"start":{"line":35,"column":4},"end":{"line":37,"column":null}},{"start":{},"end":{}}],"line":35},"3":{"loc":{"start":{"line":52,"column":20},"end":{"line":52,"column":null}},"type":"binary-expr","locations":[{"start":{"line":52,"column":20},"end":{"line":52,"column":38}},{"start":{"line":52,"column":38},"end":{"line":52,"column":null}}],"line":52},"4":{"loc":{"start":{"line":57,"column":6},"end":{"line":59,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":6},"end":{"line":59,"column":null}},{"start":{},"end":{}}],"line":57},"5":{"loc":{"start":{"line":62,"column":6},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":62,"column":6},"end":{"line":64,"column":null}},{"start":{},"end":{}}],"line":62},"6":{"loc":{"start":{"line":66,"column":6},"end":{"line":81,"column":null}},"type":"if","locations":[{"start":{"line":66,"column":6},"end":{"line":81,"column":null}},{"start":{},"end":{}}],"line":66},"7":{"loc":{"start":{"line":66,"column":10},"end":{"line":66,"column":50}},"type":"binary-expr","locations":[{"start":{"line":66,"column":10},"end":{"line":66,"column":21}},{"start":{"line":66,"column":21},"end":{"line":66,"column":50}}],"line":66},"8":{"loc":{"start":{"line":68,"column":8},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":68,"column":8},"end":{"line":70,"column":null}},{"start":{},"end":{}}],"line":68},"9":{"loc":{"start":{"line":71,"column":8},"end":{"line":80,"column":null}},"type":"if","locations":[{"start":{"line":71,"column":8},"end":{"line":80,"column":null}},{"start":{},"end":{}}],"line":71},"10":{"loc":{"start":{"line":72,"column":10},"end":{"line":74,"column":null}},"type":"binary-expr","locations":[{"start":{"line":72,"column":10},"end":{"line":72,"column":null}},{"start":{"line":73,"column":10},"end":{"line":73,"column":null}},{"start":{"line":74,"column":10},"end":{"line":74,"column":null}}],"line":72},"11":{"loc":{"start":{"line":92,"column":17},"end":{"line":92,"column":null}},"type":"binary-expr","locations":[{"start":{"line":92,"column":17},"end":{"line":92,"column":31}},{"start":{"line":92,"column":31},"end":{"line":92,"column":null}}],"line":92},"12":{"loc":{"start":{"line":93,"column":17},"end":{"line":93,"column":null}},"type":"binary-expr","locations":[{"start":{"line":93,"column":17},"end":{"line":93,"column":31}},{"start":{"line":93,"column":31},"end":{"line":93,"column":null}}],"line":93},"13":{"loc":{"start":{"line":94,"column":16},"end":{"line":94,"column":null}},"type":"cond-expr","locations":[{"start":{"line":94,"column":45},"end":{"line":94,"column":65}},{"start":{"line":94,"column":65},"end":{"line":94,"column":null}}],"line":94},"14":{"loc":{"start":{"line":96,"column":4},"end":{"line":101,"column":null}},"type":"if","locations":[{"start":{"line":96,"column":4},"end":{"line":101,"column":null}},{"start":{},"end":{}}],"line":96},"15":{"loc":{"start":{"line":97,"column":31},"end":{"line":97,"column":65}},"type":"binary-expr","locations":[{"start":{"line":97,"column":31},"end":{"line":97,"column":64}},{"start":{"line":97,"column":64},"end":{"line":97,"column":65}}],"line":97},"16":{"loc":{"start":{"line":98,"column":29},"end":{"line":98,"column":60}},"type":"binary-expr","locations":[{"start":{"line":98,"column":29},"end":{"line":98,"column":59}},{"start":{"line":98,"column":59},"end":{"line":98,"column":60}}],"line":98},"17":{"loc":{"start":{"line":99,"column":29},"end":{"line":99,"column":61}},"type":"binary-expr","locations":[{"start":{"line":99,"column":29},"end":{"line":99,"column":60}},{"start":{"line":99,"column":60},"end":{"line":99,"column":61}}],"line":99},"18":{"loc":{"start":{"line":100,"column":16},"end":{"line":100,"column":42}},"type":"binary-expr","locations":[{"start":{"line":100,"column":16},"end":{"line":100,"column":34}},{"start":{"line":100,"column":34},"end":{"line":100,"column":42}}],"line":100},"19":{"loc":{"start":{"line":100,"column":64},"end":{"line":100,"column":72}},"type":"binary-expr","locations":[{"start":{"line":100,"column":64},"end":{"line":100,"column":71}},{"start":{"line":100,"column":71},"end":{"line":100,"column":72}}],"line":100},"20":{"loc":{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},{"start":{},"end":{}}],"line":103},"21":{"loc":{"start":{"line":104,"column":43},"end":{"line":104,"column":69}},"type":"cond-expr","locations":[{"start":{"line":104,"column":49},"end":{"line":104,"column":67}},{"start":{"line":104,"column":67},"end":{"line":104,"column":69}}],"line":104},"22":{"loc":{"start":{"line":107,"column":4},"end":{"line":109,"column":null}},"type":"if","locations":[{"start":{"line":107,"column":4},"end":{"line":109,"column":null}},{"start":{},"end":{}}],"line":107},"23":{"loc":{"start":{"line":108,"column":50},"end":{"line":108,"column":76}},"type":"cond-expr","locations":[{"start":{"line":108,"column":56},"end":{"line":108,"column":74}},{"start":{"line":108,"column":74},"end":{"line":108,"column":76}}],"line":108}},"s":{"0":55,"1":55,"2":0,"3":3,"4":3,"5":0,"6":3,"7":3,"8":3,"9":3,"10":3,"11":3,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":3,"32":3,"33":3,"34":3,"35":2,"36":2,"37":2,"38":2,"39":1,"40":1,"41":0,"42":0,"43":0},"f":{"0":55,"1":0,"2":3,"3":3,"4":0,"5":3},"b":{"0":[0,3],"1":[3,3],"2":[3,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0,0],"11":[3,0],"12":[3,0],"13":[3,0],"14":[2,1],"15":[2,1],"16":[2,2],"17":[2,2],"18":[2,0],"19":[2,0],"20":[1,0],"21":[1,0],"22":[0,0],"23":[0,0]},"meta":{"lastBranch":24,"lastFunction":6,"lastStatement":44,"seen":{"s:14:18:14:Infinity":0,"f:16:2:16:22":0,"s:16:22:16:44":1,"f:18:2:18:26":1,"s:19:4:19:Infinity":2,"f:22:8:22:18":2,"s:23:21:23:Infinity":3,"b:24:4:26:Infinity:undefined:undefined:undefined:undefined":0,"s:24:4:26:Infinity":4,"s:25:6:25:Infinity":5,"s:28:19:28:Infinity":6,"s:29:20:29:Infinity":7,"b:29:20:29:30:29:30:29:Infinity":1,"s:30:4:30:Infinity":8,"s:31:4:31:Infinity":9,"f:34:16:34:33":3,"b:35:4:37:Infinity:undefined:undefined:undefined:undefined":2,"s:35:4:37:Infinity":10,"s:36:6:36:Infinity":11,"s:39:23:39:Infinity":12,"s:40:20:40:Infinity":13,"f:40:31:40:37":4,"s:40:37:40:57":14,"s:42:4:88:Infinity":15,"s:43:23:55:Infinity":16,"b:52:20:52:38:52:38:52:Infinity":3,"b:57:6:59:Infinity:undefined:undefined:undefined:undefined":4,"s:57:6:59:Infinity":17,"s:58:8:58:Infinity":18,"s:61:23:61:Infinity":19,"b:62:6:64:Infinity:undefined:undefined:undefined:undefined":5,"s:62:6:64:Infinity":20,"s:63:8:63:Infinity":21,"b:66:6:81:Infinity:undefined:undefined:undefined:undefined":6,"s:66:6:81:Infinity":22,"b:66:10:66:21:66:21:66:50":7,"s:67:20:67:Infinity":23,"b:68:8:70:Infinity:undefined:undefined:undefined:undefined":8,"s:68:8:70:Infinity":24,"s:69:10:69:Infinity":25,"b:71:8:80:Infinity:undefined:undefined:undefined:undefined":9,"s:71:8:80:Infinity":26,"b:72:10:72:Infinity:73:10:73:Infinity:74:10:74:Infinity":10,"s:76:10:79:Infinity":27,"s:83:6:83:Infinity":28,"s:85:6:85:Infinity":29,"s:87:6:87:Infinity":30,"f:91:10:91:23":5,"s:92:17:92:Infinity":31,"b:92:17:92:31:92:31:92:Infinity":11,"s:93:17:93:Infinity":32,"b:93:17:93:31:93:31:93:Infinity":12,"s:94:16:94:Infinity":33,"b:94:45:94:65:94:65:94:Infinity":13,"b:96:4:101:Infinity:undefined:undefined:undefined:undefined":14,"s:96:4:101:Infinity":34,"s:97:24:97:Infinity":35,"b:97:31:97:64:97:64:97:65":15,"s:98:22:98:Infinity":36,"b:98:29:98:59:98:59:98:60":16,"s:99:22:99:Infinity":37,"b:99:29:99:60:99:60:99:61":17,"s:100:6:100:Infinity":38,"b:100:16:100:34:100:34:100:42":18,"b:100:64:100:71:100:71:100:72":19,"b:103:4:105:Infinity:undefined:undefined:undefined:undefined":20,"s:103:4:105:Infinity":39,"s:104:6:104:Infinity":40,"b:104:49:104:67:104:67:104:69":21,"b:107:4:109:Infinity:undefined:undefined:undefined:undefined":22,"s:107:4:109:Infinity":41,"s:108:6:108:Infinity":42,"b:108:56:108:74:108:74:108:76":23,"s:111:4:111:Infinity":43}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/tools/tool-handler-base.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/tools/tool-handler-base.ts","statementMap":{"0":{"start":{"line":63,"column":37},"end":{"line":63,"column":null}},"1":{"start":{"line":68,"column":36},"end":{"line":71,"column":null}},"2":{"start":{"line":72,"column":48},"end":{"line":72,"column":null}},"3":{"start":{"line":75,"column":37},"end":{"line":75,"column":null}},"4":{"start":{"line":76,"column":30},"end":{"line":76,"column":null}},"5":{"start":{"line":78,"column":24},"end":{"line":78,"column":46}},"6":{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},"7":{"start":{"line":80,"column":4},"end":{"line":80,"column":null}},"8":{"start":{"line":82,"column":4},"end":{"line":82,"column":null}},"9":{"start":{"line":90,"column":10},"end":{"line":90,"column":null}},"10":{"start":{"line":91,"column":4},"end":{"line":93,"column":null}},"11":{"start":{"line":92,"column":6},"end":{"line":92,"column":null}},"12":{"start":{"line":95,"column":4},"end":{"line":95,"column":null}},"13":{"start":{"line":99,"column":22},"end":{"line":99,"column":null}},"14":{"start":{"line":100,"column":4},"end":{"line":102,"column":null}},"15":{"start":{"line":101,"column":6},"end":{"line":101,"column":null}},"16":{"start":{"line":104,"column":4},"end":{"line":106,"column":null}},"17":{"start":{"line":111,"column":22},"end":{"line":111,"column":null}},"18":{"start":{"line":112,"column":4},"end":{"line":116,"column":null}},"19":{"start":{"line":113,"column":6},"end":{"line":113,"column":null}},"20":{"start":{"line":115,"column":6},"end":{"line":115,"column":null}},"21":{"start":{"line":119,"column":4},"end":{"line":119,"column":null}},"22":{"start":{"line":123,"column":4},"end":{"line":125,"column":null}},"23":{"start":{"line":127,"column":4},"end":{"line":138,"column":null}},"24":{"start":{"line":128,"column":6},"end":{"line":128,"column":null}},"25":{"start":{"line":129,"column":6},"end":{"line":129,"column":null}},"26":{"start":{"line":130,"column":6},"end":{"line":132,"column":null}},"27":{"start":{"line":131,"column":8},"end":{"line":131,"column":null}},"28":{"start":{"line":135,"column":6},"end":{"line":135,"column":null}},"29":{"start":{"line":137,"column":6},"end":{"line":137,"column":null}},"30":{"start":{"line":142,"column":26},"end":{"line":142,"column":null}},"31":{"start":{"line":143,"column":22},"end":{"line":143,"column":null}},"32":{"start":{"line":144,"column":22},"end":{"line":144,"column":null}},"33":{"start":{"line":146,"column":4},"end":{"line":150,"column":null}},"34":{"start":{"line":154,"column":17},"end":{"line":154,"column":null}},"35":{"start":{"line":156,"column":6},"end":{"line":157,"column":null}},"36":{"start":{"line":158,"column":27},"end":{"line":160,"column":null}},"37":{"start":{"line":161,"column":26},"end":{"line":161,"column":null}},"38":{"start":{"line":162,"column":24},"end":{"line":162,"column":null}},"39":{"start":{"line":163,"column":22},"end":{"line":165,"column":null}},"40":{"start":{"line":167,"column":6},"end":{"line":171,"column":null}},"41":{"start":{"line":173,"column":4},"end":{"line":177,"column":null}},"42":{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},"43":{"start":{"line":186,"column":6},"end":{"line":186,"column":null}},"44":{"start":{"line":189,"column":25},"end":{"line":189,"column":null}},"45":{"start":{"line":190,"column":4},"end":{"line":192,"column":null}},"46":{"start":{"line":191,"column":6},"end":{"line":191,"column":null}},"47":{"start":{"line":194,"column":26},"end":{"line":194,"column":null}},"48":{"start":{"line":195,"column":4},"end":{"line":204,"column":null}},"49":{"start":{"line":199,"column":29},"end":{"line":202,"column":null}},"50":{"start":{"line":203,"column":6},"end":{"line":203,"column":null}},"51":{"start":{"line":206,"column":4},"end":{"line":215,"column":null}},"52":{"start":{"line":219,"column":4},"end":{"line":219,"column":null}},"53":{"start":{"line":223,"column":4},"end":{"line":223,"column":null}},"54":{"start":{"line":231,"column":4},"end":{"line":231,"column":null}},"55":{"start":{"line":235,"column":4},"end":{"line":235,"column":null}},"56":{"start":{"line":239,"column":16},"end":{"line":239,"column":null}},"57":{"start":{"line":240,"column":21},"end":{"line":240,"column":null}},"58":{"start":{"line":241,"column":4},"end":{"line":243,"column":null}},"59":{"start":{"line":242,"column":6},"end":{"line":242,"column":null}},"60":{"start":{"line":245,"column":4},"end":{"line":245,"column":null}},"61":{"start":{"line":246,"column":4},"end":{"line":246,"column":null}},"62":{"start":{"line":250,"column":4},"end":{"line":252,"column":null}},"63":{"start":{"line":251,"column":6},"end":{"line":251,"column":null}},"64":{"start":{"line":254,"column":4},"end":{"line":254,"column":null}},"65":{"start":{"line":256,"column":20},"end":{"line":272,"column":null}},"66":{"start":{"line":265,"column":8},"end":{"line":270,"column":null}},"67":{"start":{"line":274,"column":4},"end":{"line":274,"column":null}},"68":{"start":{"line":275,"column":4},"end":{"line":275,"column":null}},"69":{"start":{"line":287,"column":4},"end":{"line":287,"column":null}},"70":{"start":{"line":287,"column":20},"end":{"line":287,"column":null}},"71":{"start":{"line":289,"column":4},"end":{"line":313,"column":null}},"72":{"start":{"line":291,"column":25},"end":{"line":291,"column":null}},"73":{"start":{"line":292,"column":22},"end":{"line":292,"column":null}},"74":{"start":{"line":293,"column":6},"end":{"line":299,"column":null}},"75":{"start":{"line":294,"column":8},"end":{"line":294,"column":null}},"76":{"start":{"line":295,"column":8},"end":{"line":295,"column":null}},"77":{"start":{"line":296,"column":8},"end":{"line":298,"column":null}},"78":{"start":{"line":302,"column":6},"end":{"line":307,"column":null}},"79":{"start":{"line":303,"column":8},"end":{"line":303,"column":null}},"80":{"start":{"line":304,"column":8},"end":{"line":306,"column":null}},"81":{"start":{"line":309,"column":6},"end":{"line":312,"column":null}},"82":{"start":{"line":321,"column":23},"end":{"line":321,"column":null}},"83":{"start":{"line":322,"column":24},"end":{"line":322,"column":null}},"84":{"start":{"line":325,"column":4},"end":{"line":334,"column":null}},"85":{"start":{"line":326,"column":6},"end":{"line":333,"column":null}},"86":{"start":{"line":327,"column":24},"end":{"line":327,"column":null}},"87":{"start":{"line":328,"column":8},"end":{"line":330,"column":null}},"88":{"start":{"line":329,"column":10},"end":{"line":329,"column":null}},"89":{"start":{"line":332,"column":8},"end":{"line":332,"column":null}},"90":{"start":{"line":336,"column":4},"end":{"line":336,"column":null}},"91":{"start":{"line":337,"column":4},"end":{"line":337,"column":null}},"92":{"start":{"line":338,"column":4},"end":{"line":340,"column":null}},"93":{"start":{"line":348,"column":4},"end":{"line":354,"column":null}},"94":{"start":{"line":349,"column":6},"end":{"line":353,"column":null}},"95":{"start":{"line":356,"column":4},"end":{"line":356,"column":null}},"96":{"start":{"line":357,"column":4},"end":{"line":360,"column":null}},"97":{"start":{"line":361,"column":4},"end":{"line":361,"column":null}},"98":{"start":{"line":362,"column":4},"end":{"line":362,"column":null}},"99":{"start":{"line":363,"column":4},"end":{"line":363,"column":null}},"100":{"start":{"line":366,"column":4},"end":{"line":368,"column":null}},"101":{"start":{"line":370,"column":4},"end":{"line":370,"column":null}},"102":{"start":{"line":374,"column":17},"end":{"line":374,"column":null}},"103":{"start":{"line":375,"column":17},"end":{"line":375,"column":null}},"104":{"start":{"line":376,"column":4},"end":{"line":376,"column":null}},"105":{"start":{"line":377,"column":4},"end":{"line":377,"column":null}},"106":{"start":{"line":378,"column":4},"end":{"line":382,"column":null}},"107":{"start":{"line":383,"column":4},"end":{"line":385,"column":null}},"108":{"start":{"line":387,"column":4},"end":{"line":389,"column":null}},"109":{"start":{"line":388,"column":6},"end":{"line":388,"column":null}},"110":{"start":{"line":391,"column":4},"end":{"line":398,"column":null}},"111":{"start":{"line":392,"column":6},"end":{"line":397,"column":null}},"112":{"start":{"line":407,"column":4},"end":{"line":455,"column":null}},"113":{"start":{"line":408,"column":6},"end":{"line":413,"column":null}},"114":{"start":{"line":409,"column":8},"end":{"line":411,"column":null}},"115":{"start":{"line":412,"column":8},"end":{"line":412,"column":null}},"116":{"start":{"line":415,"column":24},"end":{"line":415,"column":null}},"117":{"start":{"line":416,"column":6},"end":{"line":418,"column":null}},"118":{"start":{"line":420,"column":24},"end":{"line":420,"column":null}},"119":{"start":{"line":421,"column":39},"end":{"line":421,"column":null}},"120":{"start":{"line":423,"column":6},"end":{"line":428,"column":null}},"121":{"start":{"line":424,"column":8},"end":{"line":426,"column":null}},"122":{"start":{"line":427,"column":8},"end":{"line":427,"column":null}},"123":{"start":{"line":431,"column":6},"end":{"line":433,"column":null}},"124":{"start":{"line":432,"column":8},"end":{"line":432,"column":null}},"125":{"start":{"line":436,"column":6},"end":{"line":444,"column":null}},"126":{"start":{"line":437,"column":8},"end":{"line":443,"column":null}},"127":{"start":{"line":446,"column":6},"end":{"line":448,"column":null}},"128":{"start":{"line":450,"column":6},"end":{"line":453,"column":null}},"129":{"start":{"line":468,"column":10},"end":{"line":472,"column":null}},"130":{"start":{"line":473,"column":4},"end":{"line":478,"column":null}},"131":{"start":{"line":479,"column":4},"end":{"line":479,"column":null}},"132":{"start":{"line":483,"column":4},"end":{"line":486,"column":null}},"133":{"start":{"line":490,"column":4},"end":{"line":495,"column":null}},"134":{"start":{"line":491,"column":25},"end":{"line":491,"column":null}},"135":{"start":{"line":492,"column":6},"end":{"line":494,"column":null}},"136":{"start":{"line":497,"column":4},"end":{"line":499,"column":null}},"137":{"start":{"line":498,"column":6},"end":{"line":498,"column":null}},"138":{"start":{"line":498,"column":46},"end":{"line":498,"column":69}},"139":{"start":{"line":501,"column":4},"end":{"line":509,"column":null}},"140":{"start":{"line":502,"column":22},"end":{"line":505,"column":null}},"141":{"start":{"line":506,"column":6},"end":{"line":508,"column":null}},"142":{"start":{"line":507,"column":36},"end":{"line":507,"column":65}},"143":{"start":{"line":511,"column":4},"end":{"line":511,"column":null}},"144":{"start":{"line":520,"column":19},"end":{"line":520,"column":null}},"145":{"start":{"line":522,"column":6},"end":{"line":522,"column":null}},"146":{"start":{"line":523,"column":4},"end":{"line":532,"column":null}},"147":{"start":{"line":542,"column":18},"end":{"line":542,"column":null}},"148":{"start":{"line":544,"column":4},"end":{"line":546,"column":null}},"149":{"start":{"line":545,"column":6},"end":{"line":545,"column":null}},"150":{"start":{"line":548,"column":4},"end":{"line":550,"column":null}},"151":{"start":{"line":549,"column":6},"end":{"line":549,"column":null}},"152":{"start":{"line":552,"column":4},"end":{"line":554,"column":null}},"153":{"start":{"line":553,"column":6},"end":{"line":553,"column":null}},"154":{"start":{"line":556,"column":4},"end":{"line":558,"column":null}},"155":{"start":{"line":557,"column":6},"end":{"line":557,"column":null}},"156":{"start":{"line":560,"column":4},"end":{"line":560,"column":null}},"157":{"start":{"line":567,"column":31},"end":{"line":567,"column":null}},"158":{"start":{"line":568,"column":23},"end":{"line":568,"column":null}},"159":{"start":{"line":570,"column":4},"end":{"line":586,"column":null}},"160":{"start":{"line":571,"column":20},"end":{"line":575,"column":null}},"161":{"start":{"line":577,"column":6},"end":{"line":582,"column":null}},"162":{"start":{"line":581,"column":8},"end":{"line":581,"column":null}},"163":{"start":{"line":584,"column":6},"end":{"line":584,"column":null}},"164":{"start":{"line":585,"column":6},"end":{"line":585,"column":null}},"165":{"start":{"line":588,"column":4},"end":{"line":604,"column":null}},"166":{"start":{"line":589,"column":6},"end":{"line":593,"column":null}},"167":{"start":{"line":590,"column":26},"end":{"line":590,"column":null}},"168":{"start":{"line":591,"column":8},"end":{"line":591,"column":null}},"169":{"start":{"line":592,"column":8},"end":{"line":592,"column":null}},"170":{"start":{"line":595,"column":6},"end":{"line":598,"column":null}},"171":{"start":{"line":596,"column":8},"end":{"line":596,"column":null}},"172":{"start":{"line":597,"column":8},"end":{"line":597,"column":null}},"173":{"start":{"line":600,"column":6},"end":{"line":603,"column":null}},"174":{"start":{"line":601,"column":8},"end":{"line":601,"column":null}},"175":{"start":{"line":602,"column":8},"end":{"line":602,"column":null}},"176":{"start":{"line":606,"column":4},"end":{"line":611,"column":null}},"177":{"start":{"line":607,"column":6},"end":{"line":610,"column":null}},"178":{"start":{"line":608,"column":8},"end":{"line":608,"column":null}},"179":{"start":{"line":609,"column":8},"end":{"line":609,"column":null}},"180":{"start":{"line":613,"column":4},"end":{"line":622,"column":null}},"181":{"start":{"line":614,"column":6},"end":{"line":620,"column":null}},"182":{"start":{"line":618,"column":8},"end":{"line":618,"column":null}},"183":{"start":{"line":619,"column":8},"end":{"line":619,"column":null}},"184":{"start":{"line":621,"column":6},"end":{"line":621,"column":null}},"185":{"start":{"line":624,"column":4},"end":{"line":624,"column":null}},"186":{"start":{"line":631,"column":4},"end":{"line":631,"column":null}},"187":{"start":{"line":635,"column":37},"end":{"line":635,"column":null}},"188":{"start":{"line":636,"column":20},"end":{"line":636,"column":null}},"189":{"start":{"line":638,"column":4},"end":{"line":644,"column":null}},"190":{"start":{"line":639,"column":6},"end":{"line":643,"column":null}},"191":{"start":{"line":646,"column":19},"end":{"line":646,"column":null}},"192":{"start":{"line":648,"column":4},"end":{"line":650,"column":null}},"193":{"start":{"line":649,"column":6},"end":{"line":649,"column":null}},"194":{"start":{"line":652,"column":4},"end":{"line":661,"column":null}},"195":{"start":{"line":653,"column":21},"end":{"line":653,"column":null}},"196":{"start":{"line":654,"column":6},"end":{"line":657,"column":null}},"197":{"start":{"line":655,"column":8},"end":{"line":655,"column":null}},"198":{"start":{"line":656,"column":8},"end":{"line":656,"column":null}},"199":{"start":{"line":658,"column":6},"end":{"line":658,"column":null}},"200":{"start":{"line":660,"column":6},"end":{"line":660,"column":null}},"201":{"start":{"line":669,"column":4},"end":{"line":671,"column":null}},"202":{"start":{"line":670,"column":6},"end":{"line":670,"column":null}},"203":{"start":{"line":673,"column":4},"end":{"line":676,"column":null}},"204":{"start":{"line":674,"column":22},"end":{"line":674,"column":null}},"205":{"start":{"line":675,"column":6},"end":{"line":675,"column":null}},"206":{"start":{"line":678,"column":19},"end":{"line":678,"column":null}},"207":{"start":{"line":679,"column":4},"end":{"line":679,"column":null}},"208":{"start":{"line":683,"column":4},"end":{"line":685,"column":null}},"209":{"start":{"line":684,"column":6},"end":{"line":684,"column":null}},"210":{"start":{"line":687,"column":4},"end":{"line":689,"column":null}},"211":{"start":{"line":688,"column":6},"end":{"line":688,"column":null}},"212":{"start":{"line":691,"column":4},"end":{"line":694,"column":null}},"213":{"start":{"line":692,"column":21},"end":{"line":692,"column":null}},"214":{"start":{"line":693,"column":6},"end":{"line":693,"column":null}},"215":{"start":{"line":696,"column":4},"end":{"line":708,"column":null}},"216":{"start":{"line":701,"column":18},"end":{"line":701,"column":null}},"217":{"start":{"line":702,"column":23},"end":{"line":702,"column":null}},"218":{"start":{"line":703,"column":19},"end":{"line":703,"column":null}},"219":{"start":{"line":705,"column":6},"end":{"line":707,"column":null}},"220":{"start":{"line":706,"column":8},"end":{"line":706,"column":null}},"221":{"start":{"line":710,"column":4},"end":{"line":710,"column":null}},"222":{"start":{"line":723,"column":17},"end":{"line":723,"column":null}},"223":{"start":{"line":724,"column":21},"end":{"line":724,"column":null}},"224":{"start":{"line":725,"column":21},"end":{"line":725,"column":null}},"225":{"start":{"line":727,"column":4},"end":{"line":738,"column":null}},"226":{"start":{"line":728,"column":22},"end":{"line":728,"column":null}},"227":{"start":{"line":729,"column":6},"end":{"line":731,"column":null}},"228":{"start":{"line":730,"column":8},"end":{"line":730,"column":null}},"229":{"start":{"line":732,"column":6},"end":{"line":737,"column":null}},"230":{"start":{"line":736,"column":8},"end":{"line":736,"column":null}},"231":{"start":{"line":740,"column":4},"end":{"line":744,"column":null}},"232":{"start":{"line":741,"column":6},"end":{"line":743,"column":null}},"233":{"start":{"line":742,"column":8},"end":{"line":742,"column":null}},"234":{"start":{"line":746,"column":4},"end":{"line":757,"column":null}},"235":{"start":{"line":747,"column":22},"end":{"line":747,"column":null}},"236":{"start":{"line":748,"column":6},"end":{"line":750,"column":null}},"237":{"start":{"line":749,"column":8},"end":{"line":749,"column":null}},"238":{"start":{"line":751,"column":6},"end":{"line":756,"column":null}},"239":{"start":{"line":755,"column":8},"end":{"line":755,"column":null}},"240":{"start":{"line":759,"column":4},"end":{"line":766,"column":null}},"241":{"start":{"line":760,"column":6},"end":{"line":765,"column":null}},"242":{"start":{"line":764,"column":8},"end":{"line":764,"column":null}},"243":{"start":{"line":768,"column":4},"end":{"line":768,"column":null}},"244":{"start":{"line":775,"column":4},"end":{"line":777,"column":null}},"245":{"start":{"line":776,"column":6},"end":{"line":776,"column":null}},"246":{"start":{"line":779,"column":4},"end":{"line":795,"column":null}},"247":{"start":{"line":780,"column":6},"end":{"line":780,"column":null}},"248":{"start":{"line":781,"column":28},"end":{"line":781,"column":null}},"249":{"start":{"line":782,"column":19},"end":{"line":782,"column":null}},"250":{"start":{"line":783,"column":42},"end":{"line":787,"column":null}},"251":{"start":{"line":789,"column":6},"end":{"line":792,"column":null}},"252":{"start":{"line":790,"column":23},"end":{"line":790,"column":44}},"253":{"start":{"line":794,"column":6},"end":{"line":794,"column":null}},"254":{"start":{"line":810,"column":20},"end":{"line":810,"column":null}},"255":{"start":{"line":811,"column":4},"end":{"line":813,"column":null}},"256":{"start":{"line":812,"column":6},"end":{"line":812,"column":null}},"257":{"start":{"line":816,"column":6},"end":{"line":816,"column":null}},"258":{"start":{"line":817,"column":4},"end":{"line":827,"column":null}},"259":{"start":{"line":818,"column":23},"end":{"line":821,"column":null}},"260":{"start":{"line":822,"column":17},"end":{"line":822,"column":null}},"261":{"start":{"line":823,"column":6},"end":{"line":825,"column":null}},"262":{"start":{"line":824,"column":8},"end":{"line":824,"column":null}},"263":{"start":{"line":826,"column":6},"end":{"line":826,"column":null}},"264":{"start":{"line":829,"column":22},"end":{"line":829,"column":null}},"265":{"start":{"line":830,"column":4},"end":{"line":832,"column":null}},"266":{"start":{"line":831,"column":6},"end":{"line":831,"column":null}},"267":{"start":{"line":834,"column":4},"end":{"line":844,"column":null}},"268":{"start":{"line":835,"column":27},"end":{"line":838,"column":null}},"269":{"start":{"line":839,"column":17},"end":{"line":839,"column":null}},"270":{"start":{"line":840,"column":6},"end":{"line":842,"column":null}},"271":{"start":{"line":841,"column":8},"end":{"line":841,"column":null}},"272":{"start":{"line":843,"column":6},"end":{"line":843,"column":null}},"273":{"start":{"line":846,"column":24},"end":{"line":849,"column":null}},"274":{"start":{"line":850,"column":20},"end":{"line":850,"column":null}},"275":{"start":{"line":851,"column":4},"end":{"line":853,"column":null}},"276":{"start":{"line":852,"column":6},"end":{"line":852,"column":null}},"277":{"start":{"line":855,"column":4},"end":{"line":855,"column":null}},"278":{"start":{"line":866,"column":6},"end":{"line":866,"column":null}},"279":{"start":{"line":868,"column":4},"end":{"line":873,"column":null}},"280":{"start":{"line":872,"column":6},"end":{"line":872,"column":null}},"281":{"start":{"line":875,"column":4},"end":{"line":905,"column":null}},"282":{"start":{"line":876,"column":24},"end":{"line":876,"column":null}},"283":{"start":{"line":877,"column":6},"end":{"line":879,"column":null}},"284":{"start":{"line":878,"column":8},"end":{"line":878,"column":null}},"285":{"start":{"line":881,"column":6},"end":{"line":896,"column":null}},"286":{"start":{"line":882,"column":8},"end":{"line":882,"column":null}},"287":{"start":{"line":885,"column":10},"end":{"line":887,"column":null}},"288":{"start":{"line":888,"column":8},"end":{"line":890,"column":null}},"289":{"start":{"line":893,"column":8},"end":{"line":895,"column":null}},"290":{"start":{"line":898,"column":6},"end":{"line":898,"column":null}},"291":{"start":{"line":900,"column":23},"end":{"line":900,"column":null}},"292":{"start":{"line":901,"column":6},"end":{"line":903,"column":null}},"293":{"start":{"line":904,"column":6},"end":{"line":904,"column":null}},"294":{"start":{"line":909,"column":4},"end":{"line":909,"column":null}},"295":{"start":{"line":913,"column":4},"end":{"line":913,"column":null}},"296":{"start":{"line":917,"column":4},"end":{"line":917,"column":null}},"297":{"start":{"line":929,"column":21},"end":{"line":929,"column":null}},"298":{"start":{"line":930,"column":19},"end":{"line":930,"column":null}},"299":{"start":{"line":932,"column":4},"end":{"line":936,"column":null}},"300":{"start":{"line":939,"column":4},"end":{"line":941,"column":null}},"301":{"start":{"line":940,"column":6},"end":{"line":940,"column":null}},"302":{"start":{"line":943,"column":4},"end":{"line":943,"column":null}},"303":{"start":{"line":950,"column":19},"end":{"line":950,"column":null}},"304":{"start":{"line":951,"column":4},"end":{"line":951,"column":null}},"305":{"start":{"line":959,"column":22},"end":{"line":959,"column":null}},"306":{"start":{"line":960,"column":4},"end":{"line":962,"column":null}},"307":{"start":{"line":961,"column":6},"end":{"line":961,"column":null}},"308":{"start":{"line":964,"column":18},"end":{"line":964,"column":null}},"309":{"start":{"line":965,"column":4},"end":{"line":967,"column":null}},"310":{"start":{"line":966,"column":6},"end":{"line":966,"column":null}},"311":{"start":{"line":969,"column":27},"end":{"line":969,"column":null}},"312":{"start":{"line":970,"column":21},"end":{"line":970,"column":null}},"313":{"start":{"line":971,"column":23},"end":{"line":973,"column":null}},"314":{"start":{"line":974,"column":23},"end":{"line":976,"column":null}},"315":{"start":{"line":978,"column":18},"end":{"line":978,"column":null}},"316":{"start":{"line":979,"column":22},"end":{"line":979,"column":null}},"317":{"start":{"line":980,"column":20},"end":{"line":980,"column":null}},"318":{"start":{"line":982,"column":4},"end":{"line":1018,"column":null}},"319":{"start":{"line":1010,"column":21},"end":{"line":1010,"column":null}},"320":{"start":{"line":1011,"column":8},"end":{"line":1016,"column":null}},"321":{"start":{"line":1027,"column":19},"end":{"line":1027,"column":null}},"322":{"start":{"line":1028,"column":4},"end":{"line":1033,"column":null}},"323":{"start":{"line":1031,"column":10},"end":{"line":1031,"column":null}},"324":{"start":{"line":1037,"column":27},"end":{"line":1037,"column":null}},"325":{"start":{"line":1038,"column":18},"end":{"line":1038,"column":null}},"326":{"start":{"line":1040,"column":4},"end":{"line":1042,"column":null}},"327":{"start":{"line":1041,"column":6},"end":{"line":1041,"column":null}},"328":{"start":{"line":1043,"column":4},"end":{"line":1043,"column":null}},"329":{"start":{"line":1048,"column":6},"end":{"line":1048,"column":null}},"330":{"start":{"line":1050,"column":18},"end":{"line":1050,"column":null}},"331":{"start":{"line":1051,"column":22},"end":{"line":1084,"column":null}},"332":{"start":{"line":1052,"column":19},"end":{"line":1052,"column":null}},"333":{"start":{"line":1053,"column":6},"end":{"line":1055,"column":null}},"334":{"start":{"line":1054,"column":8},"end":{"line":1054,"column":null}},"335":{"start":{"line":1057,"column":24},"end":{"line":1057,"column":null}},"336":{"start":{"line":1058,"column":6},"end":{"line":1060,"column":null}},"337":{"start":{"line":1059,"column":8},"end":{"line":1059,"column":null}},"338":{"start":{"line":1062,"column":6},"end":{"line":1062,"column":null}},"339":{"start":{"line":1064,"column":8},"end":{"line":1064,"column":null}},"340":{"start":{"line":1065,"column":28},"end":{"line":1065,"column":null}},"341":{"start":{"line":1066,"column":25},"end":{"line":1066,"column":null}},"342":{"start":{"line":1068,"column":6},"end":{"line":1075,"column":null}},"343":{"start":{"line":1069,"column":8},"end":{"line":1073,"column":null}},"344":{"start":{"line":1070,"column":23},"end":{"line":1070,"column":null}},"345":{"start":{"line":1071,"column":23},"end":{"line":1071,"column":null}},"346":{"start":{"line":1072,"column":10},"end":{"line":1072,"column":null}},"347":{"start":{"line":1074,"column":8},"end":{"line":1074,"column":null}},"348":{"start":{"line":1077,"column":6},"end":{"line":1081,"column":null}},"349":{"start":{"line":1078,"column":21},"end":{"line":1078,"column":null}},"350":{"start":{"line":1079,"column":21},"end":{"line":1079,"column":null}},"351":{"start":{"line":1080,"column":8},"end":{"line":1080,"column":null}},"352":{"start":{"line":1083,"column":6},"end":{"line":1083,"column":null}},"353":{"start":{"line":1086,"column":4},"end":{"line":1086,"column":null}},"354":{"start":{"line":1096,"column":4},"end":{"line":1098,"column":null}},"355":{"start":{"line":1097,"column":6},"end":{"line":1097,"column":null}},"356":{"start":{"line":1101,"column":24},"end":{"line":1101,"column":null}},"357":{"start":{"line":1102,"column":10},"end":{"line":1102,"column":null}},"358":{"start":{"line":1104,"column":4},"end":{"line":1116,"column":null}},"359":{"start":{"line":1105,"column":6},"end":{"line":1115,"column":null}},"360":{"start":{"line":1118,"column":4},"end":{"line":1136,"column":null}},"361":{"start":{"line":1139,"column":4},"end":{"line":1139,"column":null}},"362":{"start":{"line":1140,"column":4},"end":{"line":1142,"column":null}},"363":{"start":{"line":1144,"column":4},"end":{"line":1144,"column":null}},"364":{"start":{"line":1145,"column":4},"end":{"line":1145,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":78,"column":2},"end":{"line":78,"column":24}},"loc":{"start":{"line":78,"column":46},"end":{"line":83,"column":null}},"line":78},"1":{"name":"(anonymous_1)","decl":{"start":{"line":89,"column":12},"end":{"line":89,"column":54}},"loc":{"start":{"line":89,"column":54},"end":{"line":96,"column":null}},"line":89},"2":{"name":"(anonymous_2)","decl":{"start":{"line":98,"column":12},"end":{"line":98,"column":54}},"loc":{"start":{"line":98,"column":54},"end":{"line":108,"column":null}},"line":98},"3":{"name":"(anonymous_3)","decl":{"start":{"line":110,"column":12},"end":{"line":110,"column":36}},"loc":{"start":{"line":110,"column":67},"end":{"line":120,"column":null}},"line":110},"4":{"name":"(anonymous_4)","decl":{"start":{"line":122,"column":12},"end":{"line":122,"column":36}},"loc":{"start":{"line":122,"column":67},"end":{"line":139,"column":null}},"line":122},"5":{"name":"(anonymous_5)","decl":{"start":{"line":141,"column":12},"end":{"line":141,"column":52}},"loc":{"start":{"line":141,"column":52},"end":{"line":151,"column":null}},"line":141},"6":{"name":"(anonymous_6)","decl":{"start":{"line":153,"column":12},"end":{"line":153,"column":34}},"loc":{"start":{"line":153,"column":71},"end":{"line":178,"column":null}},"line":153},"7":{"name":"(anonymous_7)","decl":{"start":{"line":180,"column":12},"end":{"line":180,"column":37}},"loc":{"start":{"line":184,"column":4},"end":{"line":216,"column":null}},"line":184},"8":{"name":"(anonymous_8)","decl":{"start":{"line":218,"column":12},"end":{"line":218,"column":50}},"loc":{"start":{"line":218,"column":50},"end":{"line":220,"column":null}},"line":218},"9":{"name":"(anonymous_9)","decl":{"start":{"line":222,"column":12},"end":{"line":222,"column":48}},"loc":{"start":{"line":222,"column":48},"end":{"line":224,"column":null}},"line":222},"10":{"name":"(anonymous_10)","decl":{"start":{"line":230,"column":12},"end":{"line":230,"column":33}},"loc":{"start":{"line":230,"column":33},"end":{"line":232,"column":null}},"line":230},"11":{"name":"(anonymous_11)","decl":{"start":{"line":234,"column":12},"end":{"line":234,"column":56}},"loc":{"start":{"line":234,"column":56},"end":{"line":236,"column":null}},"line":234},"12":{"name":"(anonymous_12)","decl":{"start":{"line":238,"column":18},"end":{"line":238,"column":53}},"loc":{"start":{"line":238,"column":53},"end":{"line":247,"column":null}},"line":238},"13":{"name":"(anonymous_13)","decl":{"start":{"line":249,"column":18},"end":{"line":249,"column":37}},"loc":{"start":{"line":249,"column":77},"end":{"line":276,"column":null}},"line":249},"14":{"name":"(anonymous_14)","decl":{"start":{"line":264,"column":6},"end":{"line":264,"column":13}},"loc":{"start":{"line":264,"column":71},"end":{"line":271,"column":null}},"line":264},"15":{"name":"(anonymous_15)","decl":{"start":{"line":286,"column":8},"end":{"line":286,"column":23}},"loc":{"start":{"line":286,"column":57},"end":{"line":314,"column":null}},"line":286},"16":{"name":"(anonymous_16)","decl":{"start":{"line":320,"column":8},"end":{"line":320,"column":44}},"loc":{"start":{"line":320,"column":44},"end":{"line":341,"column":null}},"line":320},"17":{"name":"(anonymous_17)","decl":{"start":{"line":347,"column":12},"end":{"line":347,"column":38}},"loc":{"start":{"line":347,"column":38},"end":{"line":371,"column":null}},"line":347},"18":{"name":"(anonymous_18)","decl":{"start":{"line":373,"column":12},"end":{"line":373,"column":43}},"loc":{"start":{"line":373,"column":43},"end":{"line":399,"column":null}},"line":373},"19":{"name":"(anonymous_19)","decl":{"start":{"line":387,"column":37},"end":{"line":387,"column":38}},"loc":{"start":{"line":387,"column":48},"end":{"line":389,"column":5}},"line":387},"20":{"name":"(anonymous_20)","decl":{"start":{"line":406,"column":18},"end":{"line":406,"column":63}},"loc":{"start":{"line":406,"column":63},"end":{"line":456,"column":null}},"line":406},"21":{"name":"(anonymous_21)","decl":{"start":{"line":462,"column":12},"end":{"line":462,"column":null}},"loc":{"start":{"line":467,"column":12},"end":{"line":480,"column":null}},"line":467},"22":{"name":"(anonymous_22)","decl":{"start":{"line":482,"column":12},"end":{"line":482,"column":30}},"loc":{"start":{"line":482,"column":52},"end":{"line":487,"column":null}},"line":482},"23":{"name":"(anonymous_23)","decl":{"start":{"line":489,"column":12},"end":{"line":489,"column":25}},"loc":{"start":{"line":489,"column":50},"end":{"line":512,"column":null}},"line":489},"24":{"name":"(anonymous_24)","decl":{"start":{"line":498,"column":36},"end":{"line":498,"column":37}},"loc":{"start":{"line":498,"column":46},"end":{"line":498,"column":69}},"line":498},"25":{"name":"(anonymous_25)","decl":{"start":{"line":507,"column":20},"end":{"line":507,"column":21}},"loc":{"start":{"line":507,"column":36},"end":{"line":507,"column":65}},"line":507},"26":{"name":"(anonymous_26)","decl":{"start":{"line":514,"column":12},"end":{"line":514,"column":null}},"loc":{"start":{"line":519,"column":12},"end":{"line":533,"column":null}},"line":519},"27":{"name":"(anonymous_27)","decl":{"start":{"line":539,"column":12},"end":{"line":539,"column":null}},"loc":{"start":{"line":541,"column":73},"end":{"line":561,"column":null}},"line":541},"28":{"name":"(anonymous_28)","decl":{"start":{"line":563,"column":12},"end":{"line":563,"column":null}},"loc":{"start":{"line":566,"column":45},"end":{"line":625,"column":null}},"line":566},"29":{"name":"(anonymous_29)","decl":{"start":{"line":627,"column":2},"end":{"line":627,"column":null}},"loc":{"start":{"line":630,"column":45},"end":{"line":632,"column":null}},"line":630},"30":{"name":"(anonymous_30)","decl":{"start":{"line":634,"column":8},"end":{"line":634,"column":17}},"loc":{"start":{"line":634,"column":66},"end":{"line":662,"column":null}},"line":634},"31":{"name":"(anonymous_31)","decl":{"start":{"line":668,"column":12},"end":{"line":668,"column":26}},"loc":{"start":{"line":668,"column":56},"end":{"line":680,"column":null}},"line":668},"32":{"name":"(anonymous_32)","decl":{"start":{"line":682,"column":12},"end":{"line":682,"column":25}},"loc":{"start":{"line":682,"column":56},"end":{"line":711,"column":null}},"line":682},"33":{"name":"(anonymous_33)","decl":{"start":{"line":717,"column":12},"end":{"line":717,"column":33}},"loc":{"start":{"line":722,"column":20},"end":{"line":769,"column":null}},"line":722},"34":{"name":"(anonymous_34)","decl":{"start":{"line":771,"column":18},"end":{"line":771,"column":null}},"loc":{"start":{"line":774,"column":23},"end":{"line":796,"column":null}},"line":774},"35":{"name":"(anonymous_35)","decl":{"start":{"line":790,"column":13},"end":{"line":790,"column":14}},"loc":{"start":{"line":790,"column":23},"end":{"line":790,"column":44}},"line":790},"36":{"name":"(anonymous_36)","decl":{"start":{"line":802,"column":18},"end":{"line":802,"column":null}},"loc":{"start":{"line":809,"column":12},"end":{"line":856,"column":null}},"line":809},"37":{"name":"(anonymous_37)","decl":{"start":{"line":864,"column":18},"end":{"line":864,"column":35}},"loc":{"start":{"line":864,"column":70},"end":{"line":906,"column":null}},"line":864},"38":{"name":"(anonymous_38)","decl":{"start":{"line":908,"column":12},"end":{"line":908,"column":37}},"loc":{"start":{"line":908,"column":65},"end":{"line":910,"column":null}},"line":908},"39":{"name":"(anonymous_39)","decl":{"start":{"line":912,"column":12},"end":{"line":912,"column":38}},"loc":{"start":{"line":912,"column":79},"end":{"line":914,"column":null}},"line":912},"40":{"name":"(anonymous_40)","decl":{"start":{"line":916,"column":12},"end":{"line":916,"column":40}},"loc":{"start":{"line":916,"column":65},"end":{"line":918,"column":null}},"line":916},"41":{"name":"(anonymous_41)","decl":{"start":{"line":924,"column":12},"end":{"line":924,"column":null}},"loc":{"start":{"line":928,"column":10},"end":{"line":944,"column":null}},"line":928},"42":{"name":"(anonymous_42)","decl":{"start":{"line":946,"column":12},"end":{"line":946,"column":null}},"loc":{"start":{"line":949,"column":67},"end":{"line":952,"column":null}},"line":949},"43":{"name":"(anonymous_43)","decl":{"start":{"line":958,"column":12},"end":{"line":958,"column":27}},"loc":{"start":{"line":958,"column":69},"end":{"line":1020,"column":null}},"line":958},"44":{"name":"(anonymous_44)","decl":{"start":{"line":1009,"column":19},"end":{"line":1009,"column":20}},"loc":{"start":{"line":1009,"column":29},"end":{"line":1018,"column":7}},"line":1009},"45":{"name":"(anonymous_45)","decl":{"start":{"line":1026,"column":12},"end":{"line":1026,"column":42}},"loc":{"start":{"line":1026,"column":71},"end":{"line":1034,"column":null}},"line":1026},"46":{"name":"(anonymous_46)","decl":{"start":{"line":1030,"column":8},"end":{"line":1030,"column":9}},"loc":{"start":{"line":1031,"column":10},"end":{"line":1031,"column":null}},"line":1031},"47":{"name":"(anonymous_47)","decl":{"start":{"line":1036,"column":12},"end":{"line":1036,"column":34}},"loc":{"start":{"line":1036,"column":61},"end":{"line":1044,"column":null}},"line":1036},"48":{"name":"(anonymous_48)","decl":{"start":{"line":1046,"column":12},"end":{"line":1046,"column":40}},"loc":{"start":{"line":1046,"column":63},"end":{"line":1087,"column":null}},"line":1046},"49":{"name":"(anonymous_49)","decl":{"start":{"line":1051,"column":55},"end":{"line":1051,"column":56}},"loc":{"start":{"line":1051,"column":68},"end":{"line":1084,"column":5}},"line":1051},"50":{"name":"(anonymous_50)","decl":{"start":{"line":1093,"column":18},"end":{"line":1093,"column":null}},"loc":{"start":{"line":1095,"column":19},"end":{"line":1146,"column":null}},"line":1095}},"branchMap":{"0":{"loc":{"start":{"line":91,"column":4},"end":{"line":93,"column":null}},"type":"if","locations":[{"start":{"line":91,"column":4},"end":{"line":93,"column":null}},{"start":{},"end":{}}],"line":91},"1":{"loc":{"start":{"line":91,"column":8},"end":{"line":91,"column":72}},"type":"binary-expr","locations":[{"start":{"line":91,"column":8},"end":{"line":91,"column":41}},{"start":{"line":91,"column":41},"end":{"line":91,"column":72}}],"line":91},"2":{"loc":{"start":{"line":100,"column":4},"end":{"line":102,"column":null}},"type":"if","locations":[{"start":{"line":100,"column":4},"end":{"line":102,"column":null}},{"start":{},"end":{}}],"line":100},"3":{"loc":{"start":{"line":105,"column":6},"end":{"line":106,"column":null}},"type":"binary-expr","locations":[{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},{"start":{"line":106,"column":6},"end":{"line":106,"column":null}}],"line":105},"4":{"loc":{"start":{"line":112,"column":4},"end":{"line":116,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":4},"end":{"line":116,"column":null}},{"start":{"line":114,"column":11},"end":{"line":116,"column":null}}],"line":112},"5":{"loc":{"start":{"line":130,"column":6},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":130,"column":6},"end":{"line":132,"column":null}},{"start":{},"end":{}}],"line":130},"6":{"loc":{"start":{"line":153,"column":34},"end":{"line":153,"column":71}},"type":"default-arg","locations":[{"start":{"line":153,"column":51},"end":{"line":153,"column":71}}],"line":153},"7":{"loc":{"start":{"line":154,"column":17},"end":{"line":154,"column":null}},"type":"binary-expr","locations":[{"start":{"line":154,"column":17},"end":{"line":154,"column":51}},{"start":{"line":154,"column":51},"end":{"line":154,"column":null}}],"line":154},"8":{"loc":{"start":{"line":156,"column":6},"end":{"line":157,"column":null}},"type":"binary-expr","locations":[{"start":{"line":156,"column":6},"end":{"line":156,"column":null}},{"start":{"line":157,"column":6},"end":{"line":157,"column":null}}],"line":156},"9":{"loc":{"start":{"line":158,"column":27},"end":{"line":160,"column":null}},"type":"cond-expr","locations":[{"start":{"line":159,"column":8},"end":{"line":159,"column":null}},{"start":{"line":160,"column":8},"end":{"line":160,"column":null}}],"line":158},"10":{"loc":{"start":{"line":162,"column":24},"end":{"line":162,"column":null}},"type":"binary-expr","locations":[{"start":{"line":162,"column":24},"end":{"line":162,"column":47}},{"start":{"line":162,"column":47},"end":{"line":162,"column":null}}],"line":162},"11":{"loc":{"start":{"line":163,"column":22},"end":{"line":165,"column":null}},"type":"cond-expr","locations":[{"start":{"line":164,"column":8},"end":{"line":164,"column":null}},{"start":{"line":165,"column":8},"end":{"line":165,"column":null}}],"line":163},"12":{"loc":{"start":{"line":167,"column":6},"end":{"line":171,"column":null}},"type":"binary-expr","locations":[{"start":{"line":167,"column":6},"end":{"line":167,"column":null}},{"start":{"line":168,"column":7},"end":{"line":170,"column":null}},{"start":{"line":171,"column":6},"end":{"line":171,"column":null}}],"line":167},"13":{"loc":{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},"type":"if","locations":[{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},{"start":{},"end":{}}],"line":185},"14":{"loc":{"start":{"line":190,"column":4},"end":{"line":192,"column":null}},"type":"if","locations":[{"start":{"line":190,"column":4},"end":{"line":192,"column":null}},{"start":{},"end":{}}],"line":190},"15":{"loc":{"start":{"line":190,"column":8},"end":{"line":190,"column":55}},"type":"binary-expr","locations":[{"start":{"line":190,"column":8},"end":{"line":190,"column":25}},{"start":{"line":190,"column":25},"end":{"line":190,"column":55}}],"line":190},"16":{"loc":{"start":{"line":195,"column":4},"end":{"line":204,"column":null}},"type":"if","locations":[{"start":{"line":195,"column":4},"end":{"line":204,"column":null}},{"start":{},"end":{}}],"line":195},"17":{"loc":{"start":{"line":196,"column":6},"end":{"line":197,"column":null}},"type":"binary-expr","locations":[{"start":{"line":196,"column":6},"end":{"line":196,"column":null}},{"start":{"line":197,"column":6},"end":{"line":197,"column":null}}],"line":196},"18":{"loc":{"start":{"line":223,"column":11},"end":{"line":223,"column":null}},"type":"binary-expr","locations":[{"start":{"line":223,"column":11},"end":{"line":223,"column":43}},{"start":{"line":223,"column":43},"end":{"line":223,"column":null}}],"line":223},"19":{"loc":{"start":{"line":231,"column":11},"end":{"line":231,"column":null}},"type":"binary-expr","locations":[{"start":{"line":231,"column":11},"end":{"line":231,"column":41}},{"start":{"line":231,"column":41},"end":{"line":231,"column":null}}],"line":231},"20":{"loc":{"start":{"line":241,"column":4},"end":{"line":243,"column":null}},"type":"if","locations":[{"start":{"line":241,"column":4},"end":{"line":243,"column":null}},{"start":{},"end":{}}],"line":241},"21":{"loc":{"start":{"line":250,"column":4},"end":{"line":252,"column":null}},"type":"if","locations":[{"start":{"line":250,"column":4},"end":{"line":252,"column":null}},{"start":{},"end":{}}],"line":250},"22":{"loc":{"start":{"line":287,"column":4},"end":{"line":287,"column":null}},"type":"if","locations":[{"start":{"line":287,"column":4},"end":{"line":287,"column":null}},{"start":{},"end":{}}],"line":287},"23":{"loc":{"start":{"line":293,"column":6},"end":{"line":299,"column":null}},"type":"if","locations":[{"start":{"line":293,"column":6},"end":{"line":299,"column":null}},{"start":{},"end":{}}],"line":293},"24":{"loc":{"start":{"line":302,"column":6},"end":{"line":307,"column":null}},"type":"if","locations":[{"start":{"line":302,"column":6},"end":{"line":307,"column":null}},{"start":{},"end":{}}],"line":302},"25":{"loc":{"start":{"line":328,"column":8},"end":{"line":330,"column":null}},"type":"if","locations":[{"start":{"line":328,"column":8},"end":{"line":330,"column":null}},{"start":{},"end":{}}],"line":328},"26":{"loc":{"start":{"line":348,"column":4},"end":{"line":354,"column":null}},"type":"if","locations":[{"start":{"line":348,"column":4},"end":{"line":354,"column":null}},{"start":{},"end":{}}],"line":348},"27":{"loc":{"start":{"line":367,"column":6},"end":{"line":368,"column":null}},"type":"binary-expr","locations":[{"start":{"line":367,"column":6},"end":{"line":367,"column":null}},{"start":{"line":368,"column":6},"end":{"line":368,"column":null}}],"line":367},"28":{"loc":{"start":{"line":391,"column":4},"end":{"line":398,"column":null}},"type":"if","locations":[{"start":{"line":391,"column":4},"end":{"line":398,"column":null}},{"start":{},"end":{}}],"line":391},"29":{"loc":{"start":{"line":408,"column":6},"end":{"line":413,"column":null}},"type":"if","locations":[{"start":{"line":408,"column":6},"end":{"line":413,"column":null}},{"start":{},"end":{}}],"line":408},"30":{"loc":{"start":{"line":423,"column":6},"end":{"line":428,"column":null}},"type":"if","locations":[{"start":{"line":423,"column":6},"end":{"line":428,"column":null}},{"start":{},"end":{}}],"line":423},"31":{"loc":{"start":{"line":423,"column":10},"end":{"line":423,"column":60}},"type":"binary-expr","locations":[{"start":{"line":423,"column":10},"end":{"line":423,"column":32}},{"start":{"line":423,"column":32},"end":{"line":423,"column":60}}],"line":423},"32":{"loc":{"start":{"line":465,"column":4},"end":{"line":465,"column":null}},"type":"default-arg","locations":[{"start":{"line":465,"column":18},"end":{"line":465,"column":null}}],"line":465},"33":{"loc":{"start":{"line":471,"column":6},"end":{"line":471,"column":null}},"type":"binary-expr","locations":[{"start":{"line":471,"column":6},"end":{"line":471,"column":14}},{"start":{"line":471,"column":14},"end":{"line":471,"column":null}}],"line":471},"34":{"loc":{"start":{"line":490,"column":4},"end":{"line":495,"column":null}},"type":"if","locations":[{"start":{"line":490,"column":4},"end":{"line":495,"column":null}},{"start":{},"end":{}}],"line":490},"35":{"loc":{"start":{"line":492,"column":13},"end":{"line":494,"column":null}},"type":"cond-expr","locations":[{"start":{"line":493,"column":10},"end":{"line":493,"column":null}},{"start":{"line":494,"column":10},"end":{"line":494,"column":null}}],"line":492},"36":{"loc":{"start":{"line":497,"column":4},"end":{"line":499,"column":null}},"type":"if","locations":[{"start":{"line":497,"column":4},"end":{"line":499,"column":null}},{"start":{},"end":{}}],"line":497},"37":{"loc":{"start":{"line":501,"column":4},"end":{"line":509,"column":null}},"type":"if","locations":[{"start":{"line":501,"column":4},"end":{"line":509,"column":null}},{"start":{},"end":{}}],"line":501},"38":{"loc":{"start":{"line":501,"column":8},"end":{"line":501,"column":44}},"type":"binary-expr","locations":[{"start":{"line":501,"column":8},"end":{"line":501,"column":17}},{"start":{"line":501,"column":17},"end":{"line":501,"column":44}}],"line":501},"39":{"loc":{"start":{"line":516,"column":4},"end":{"line":516,"column":null}},"type":"default-arg","locations":[{"start":{"line":516,"column":22},"end":{"line":516,"column":null}}],"line":516},"40":{"loc":{"start":{"line":520,"column":19},"end":{"line":520,"column":null}},"type":"cond-expr","locations":[{"start":{"line":520,"column":41},"end":{"line":520,"column":48}},{"start":{"line":520,"column":48},"end":{"line":520,"column":null}}],"line":520},"41":{"loc":{"start":{"line":522,"column":6},"end":{"line":522,"column":null}},"type":"cond-expr","locations":[{"start":{"line":522,"column":54},"end":{"line":522,"column":64}},{"start":{"line":522,"column":64},"end":{"line":522,"column":null}}],"line":522},"42":{"loc":{"start":{"line":522,"column":6},"end":{"line":522,"column":54}},"type":"binary-expr","locations":[{"start":{"line":522,"column":6},"end":{"line":522,"column":32}},{"start":{"line":522,"column":32},"end":{"line":522,"column":54}}],"line":522},"43":{"loc":{"start":{"line":525,"column":8},"end":{"line":525,"column":null}},"type":"binary-expr","locations":[{"start":{"line":525,"column":8},"end":{"line":525,"column":19}},{"start":{"line":525,"column":19},"end":{"line":525,"column":null}}],"line":525},"44":{"loc":{"start":{"line":544,"column":4},"end":{"line":546,"column":null}},"type":"if","locations":[{"start":{"line":544,"column":4},"end":{"line":546,"column":null}},{"start":{},"end":{}}],"line":544},"45":{"loc":{"start":{"line":548,"column":4},"end":{"line":550,"column":null}},"type":"if","locations":[{"start":{"line":548,"column":4},"end":{"line":550,"column":null}},{"start":{},"end":{}}],"line":548},"46":{"loc":{"start":{"line":552,"column":4},"end":{"line":554,"column":null}},"type":"if","locations":[{"start":{"line":552,"column":4},"end":{"line":554,"column":null}},{"start":{},"end":{}}],"line":552},"47":{"loc":{"start":{"line":556,"column":4},"end":{"line":558,"column":null}},"type":"if","locations":[{"start":{"line":556,"column":4},"end":{"line":558,"column":null}},{"start":{},"end":{}}],"line":556},"48":{"loc":{"start":{"line":568,"column":29},"end":{"line":568,"column":44}},"type":"binary-expr","locations":[{"start":{"line":568,"column":29},"end":{"line":568,"column":40}},{"start":{"line":568,"column":40},"end":{"line":568,"column":44}}],"line":568},"49":{"loc":{"start":{"line":570,"column":4},"end":{"line":586,"column":null}},"type":"if","locations":[{"start":{"line":570,"column":4},"end":{"line":586,"column":null}},{"start":{},"end":{}}],"line":570},"50":{"loc":{"start":{"line":571,"column":20},"end":{"line":575,"column":null}},"type":"cond-expr","locations":[{"start":{"line":572,"column":10},"end":{"line":572,"column":null}},{"start":{"line":573,"column":10},"end":{"line":575,"column":null}}],"line":571},"51":{"loc":{"start":{"line":573,"column":10},"end":{"line":575,"column":null}},"type":"cond-expr","locations":[{"start":{"line":574,"column":12},"end":{"line":574,"column":null}},{"start":{"line":575,"column":12},"end":{"line":575,"column":null}}],"line":573},"52":{"loc":{"start":{"line":577,"column":6},"end":{"line":582,"column":null}},"type":"if","locations":[{"start":{"line":577,"column":6},"end":{"line":582,"column":null}},{"start":{},"end":{}}],"line":577},"53":{"loc":{"start":{"line":578,"column":8},"end":{"line":579,"column":null}},"type":"binary-expr","locations":[{"start":{"line":578,"column":8},"end":{"line":578,"column":null}},{"start":{"line":579,"column":8},"end":{"line":579,"column":null}}],"line":578},"54":{"loc":{"start":{"line":588,"column":4},"end":{"line":604,"column":null}},"type":"if","locations":[{"start":{"line":588,"column":4},"end":{"line":604,"column":null}},{"start":{},"end":{}}],"line":588},"55":{"loc":{"start":{"line":589,"column":6},"end":{"line":593,"column":null}},"type":"if","locations":[{"start":{"line":589,"column":6},"end":{"line":593,"column":null}},{"start":{},"end":{}}],"line":589},"56":{"loc":{"start":{"line":590,"column":33},"end":{"line":590,"column":59}},"type":"binary-expr","locations":[{"start":{"line":590,"column":33},"end":{"line":590,"column":53}},{"start":{"line":590,"column":53},"end":{"line":590,"column":59}}],"line":590},"57":{"loc":{"start":{"line":591,"column":26},"end":{"line":591,"column":null}},"type":"cond-expr","locations":[{"start":{"line":591,"column":58},"end":{"line":591,"column":70}},{"start":{"line":591,"column":70},"end":{"line":591,"column":null}}],"line":591},"58":{"loc":{"start":{"line":595,"column":6},"end":{"line":598,"column":null}},"type":"if","locations":[{"start":{"line":595,"column":6},"end":{"line":598,"column":null}},{"start":{},"end":{}}],"line":595},"59":{"loc":{"start":{"line":600,"column":6},"end":{"line":603,"column":null}},"type":"if","locations":[{"start":{"line":600,"column":6},"end":{"line":603,"column":null}},{"start":{},"end":{}}],"line":600},"60":{"loc":{"start":{"line":606,"column":4},"end":{"line":611,"column":null}},"type":"if","locations":[{"start":{"line":606,"column":4},"end":{"line":611,"column":null}},{"start":{},"end":{}}],"line":606},"61":{"loc":{"start":{"line":607,"column":6},"end":{"line":610,"column":null}},"type":"if","locations":[{"start":{"line":607,"column":6},"end":{"line":610,"column":null}},{"start":{},"end":{}}],"line":607},"62":{"loc":{"start":{"line":613,"column":4},"end":{"line":622,"column":null}},"type":"if","locations":[{"start":{"line":613,"column":4},"end":{"line":622,"column":null}},{"start":{},"end":{}}],"line":613},"63":{"loc":{"start":{"line":613,"column":8},"end":{"line":613,"column":76}},"type":"binary-expr","locations":[{"start":{"line":613,"column":8},"end":{"line":613,"column":46}},{"start":{"line":613,"column":46},"end":{"line":613,"column":76}}],"line":613},"64":{"loc":{"start":{"line":614,"column":6},"end":{"line":620,"column":null}},"type":"if","locations":[{"start":{"line":614,"column":6},"end":{"line":620,"column":null}},{"start":{},"end":{}}],"line":614},"65":{"loc":{"start":{"line":615,"column":8},"end":{"line":616,"column":null}},"type":"binary-expr","locations":[{"start":{"line":615,"column":8},"end":{"line":615,"column":null}},{"start":{"line":616,"column":8},"end":{"line":616,"column":null}}],"line":615},"66":{"loc":{"start":{"line":638,"column":4},"end":{"line":644,"column":null}},"type":"if","locations":[{"start":{"line":638,"column":4},"end":{"line":644,"column":null}},{"start":{},"end":{}}],"line":638},"67":{"loc":{"start":{"line":648,"column":4},"end":{"line":650,"column":null}},"type":"if","locations":[{"start":{"line":648,"column":4},"end":{"line":650,"column":null}},{"start":{},"end":{}}],"line":648},"68":{"loc":{"start":{"line":654,"column":6},"end":{"line":657,"column":null}},"type":"if","locations":[{"start":{"line":654,"column":6},"end":{"line":657,"column":null}},{"start":{},"end":{}}],"line":654},"69":{"loc":{"start":{"line":654,"column":10},"end":{"line":654,"column":48}},"type":"binary-expr","locations":[{"start":{"line":654,"column":10},"end":{"line":654,"column":20}},{"start":{"line":654,"column":20},"end":{"line":654,"column":48}}],"line":654},"70":{"loc":{"start":{"line":669,"column":4},"end":{"line":671,"column":null}},"type":"if","locations":[{"start":{"line":669,"column":4},"end":{"line":671,"column":null}},{"start":{},"end":{}}],"line":669},"71":{"loc":{"start":{"line":669,"column":8},"end":{"line":669,"column":43}},"type":"binary-expr","locations":[{"start":{"line":669,"column":8},"end":{"line":669,"column":17}},{"start":{"line":669,"column":17},"end":{"line":669,"column":43}}],"line":669},"72":{"loc":{"start":{"line":673,"column":4},"end":{"line":676,"column":null}},"type":"if","locations":[{"start":{"line":673,"column":4},"end":{"line":676,"column":null}},{"start":{},"end":{}}],"line":673},"73":{"loc":{"start":{"line":675,"column":13},"end":{"line":675,"column":null}},"type":"cond-expr","locations":[{"start":{"line":675,"column":40},"end":{"line":675,"column":50}},{"start":{"line":675,"column":50},"end":{"line":675,"column":null}}],"line":675},"74":{"loc":{"start":{"line":679,"column":11},"end":{"line":679,"column":null}},"type":"cond-expr","locations":[{"start":{"line":679,"column":34},"end":{"line":679,"column":41}},{"start":{"line":679,"column":41},"end":{"line":679,"column":null}}],"line":679},"75":{"loc":{"start":{"line":683,"column":4},"end":{"line":685,"column":null}},"type":"if","locations":[{"start":{"line":683,"column":4},"end":{"line":685,"column":null}},{"start":{},"end":{}}],"line":683},"76":{"loc":{"start":{"line":684,"column":13},"end":{"line":684,"column":null}},"type":"cond-expr","locations":[{"start":{"line":684,"column":38},"end":{"line":684,"column":46}},{"start":{"line":684,"column":46},"end":{"line":684,"column":null}}],"line":684},"77":{"loc":{"start":{"line":687,"column":4},"end":{"line":689,"column":null}},"type":"if","locations":[{"start":{"line":687,"column":4},"end":{"line":689,"column":null}},{"start":{},"end":{}}],"line":687},"78":{"loc":{"start":{"line":691,"column":4},"end":{"line":694,"column":null}},"type":"if","locations":[{"start":{"line":691,"column":4},"end":{"line":694,"column":null}},{"start":{},"end":{}}],"line":691},"79":{"loc":{"start":{"line":691,"column":8},"end":{"line":691,"column":70}},"type":"binary-expr","locations":[{"start":{"line":691,"column":8},"end":{"line":691,"column":37}},{"start":{"line":691,"column":37},"end":{"line":691,"column":70}}],"line":691},"80":{"loc":{"start":{"line":693,"column":13},"end":{"line":693,"column":null}},"type":"cond-expr","locations":[{"start":{"line":693,"column":39},"end":{"line":693,"column":48}},{"start":{"line":693,"column":48},"end":{"line":693,"column":null}}],"line":693},"81":{"loc":{"start":{"line":696,"column":4},"end":{"line":708,"column":null}},"type":"if","locations":[{"start":{"line":696,"column":4},"end":{"line":708,"column":null}},{"start":{},"end":{}}],"line":696},"82":{"loc":{"start":{"line":697,"column":6},"end":{"line":699,"column":null}},"type":"binary-expr","locations":[{"start":{"line":697,"column":6},"end":{"line":697,"column":null}},{"start":{"line":698,"column":6},"end":{"line":698,"column":null}},{"start":{"line":699,"column":6},"end":{"line":699,"column":null}}],"line":697},"83":{"loc":{"start":{"line":703,"column":19},"end":{"line":703,"column":null}},"type":"cond-expr","locations":[{"start":{"line":703,"column":49},"end":{"line":703,"column":59}},{"start":{"line":703,"column":59},"end":{"line":703,"column":null}}],"line":703},"84":{"loc":{"start":{"line":703,"column":66},"end":{"line":703,"column":78}},"type":"binary-expr","locations":[{"start":{"line":703,"column":66},"end":{"line":703,"column":77}},{"start":{"line":703,"column":77},"end":{"line":703,"column":78}}],"line":703},"85":{"loc":{"start":{"line":705,"column":6},"end":{"line":707,"column":null}},"type":"if","locations":[{"start":{"line":705,"column":6},"end":{"line":707,"column":null}},{"start":{},"end":{}}],"line":705},"86":{"loc":{"start":{"line":705,"column":10},"end":{"line":705,"column":57}},"type":"binary-expr","locations":[{"start":{"line":705,"column":10},"end":{"line":705,"column":34}},{"start":{"line":705,"column":34},"end":{"line":705,"column":57}}],"line":705},"87":{"loc":{"start":{"line":723,"column":24},"end":{"line":723,"column":39}},"type":"binary-expr","locations":[{"start":{"line":723,"column":24},"end":{"line":723,"column":37}},{"start":{"line":723,"column":37},"end":{"line":723,"column":39}}],"line":723},"88":{"loc":{"start":{"line":724,"column":21},"end":{"line":724,"column":null}},"type":"cond-expr","locations":[{"start":{"line":724,"column":52},"end":{"line":724,"column":68}},{"start":{"line":724,"column":68},"end":{"line":724,"column":null}}],"line":724},"89":{"loc":{"start":{"line":725,"column":21},"end":{"line":725,"column":null}},"type":"binary-expr","locations":[{"start":{"line":725,"column":21},"end":{"line":725,"column":38}},{"start":{"line":725,"column":38},"end":{"line":725,"column":null}}],"line":725},"90":{"loc":{"start":{"line":727,"column":4},"end":{"line":738,"column":null}},"type":"if","locations":[{"start":{"line":727,"column":4},"end":{"line":738,"column":null}},{"start":{},"end":{}}],"line":727},"91":{"loc":{"start":{"line":728,"column":29},"end":{"line":728,"column":47}},"type":"binary-expr","locations":[{"start":{"line":728,"column":29},"end":{"line":728,"column":45}},{"start":{"line":728,"column":45},"end":{"line":728,"column":47}}],"line":728},"92":{"loc":{"start":{"line":729,"column":6},"end":{"line":731,"column":null}},"type":"if","locations":[{"start":{"line":729,"column":6},"end":{"line":731,"column":null}},{"start":{},"end":{}}],"line":729},"93":{"loc":{"start":{"line":729,"column":10},"end":{"line":729,"column":76}},"type":"binary-expr","locations":[{"start":{"line":729,"column":10},"end":{"line":729,"column":22}},{"start":{"line":729,"column":22},"end":{"line":729,"column":76}}],"line":729},"94":{"loc":{"start":{"line":732,"column":6},"end":{"line":737,"column":null}},"type":"if","locations":[{"start":{"line":732,"column":6},"end":{"line":737,"column":null}},{"start":{},"end":{}}],"line":732},"95":{"loc":{"start":{"line":733,"column":8},"end":{"line":734,"column":null}},"type":"binary-expr","locations":[{"start":{"line":733,"column":8},"end":{"line":733,"column":null}},{"start":{"line":734,"column":8},"end":{"line":734,"column":null}}],"line":733},"96":{"loc":{"start":{"line":740,"column":4},"end":{"line":744,"column":null}},"type":"if","locations":[{"start":{"line":740,"column":4},"end":{"line":744,"column":null}},{"start":{},"end":{}}],"line":740},"97":{"loc":{"start":{"line":741,"column":6},"end":{"line":743,"column":null}},"type":"if","locations":[{"start":{"line":741,"column":6},"end":{"line":743,"column":null}},{"start":{},"end":{}}],"line":741},"98":{"loc":{"start":{"line":746,"column":4},"end":{"line":757,"column":null}},"type":"if","locations":[{"start":{"line":746,"column":4},"end":{"line":757,"column":null}},{"start":{},"end":{}}],"line":746},"99":{"loc":{"start":{"line":747,"column":29},"end":{"line":747,"column":47}},"type":"binary-expr","locations":[{"start":{"line":747,"column":29},"end":{"line":747,"column":45}},{"start":{"line":747,"column":45},"end":{"line":747,"column":47}}],"line":747},"100":{"loc":{"start":{"line":748,"column":6},"end":{"line":750,"column":null}},"type":"if","locations":[{"start":{"line":748,"column":6},"end":{"line":750,"column":null}},{"start":{},"end":{}}],"line":748},"101":{"loc":{"start":{"line":748,"column":10},"end":{"line":748,"column":76}},"type":"binary-expr","locations":[{"start":{"line":748,"column":10},"end":{"line":748,"column":22}},{"start":{"line":748,"column":22},"end":{"line":748,"column":76}}],"line":748},"102":{"loc":{"start":{"line":751,"column":6},"end":{"line":756,"column":null}},"type":"if","locations":[{"start":{"line":751,"column":6},"end":{"line":756,"column":null}},{"start":{},"end":{}}],"line":751},"103":{"loc":{"start":{"line":752,"column":8},"end":{"line":753,"column":null}},"type":"binary-expr","locations":[{"start":{"line":752,"column":8},"end":{"line":752,"column":null}},{"start":{"line":753,"column":8},"end":{"line":753,"column":null}}],"line":752},"104":{"loc":{"start":{"line":759,"column":4},"end":{"line":766,"column":null}},"type":"if","locations":[{"start":{"line":759,"column":4},"end":{"line":766,"column":null}},{"start":{},"end":{}}],"line":759},"105":{"loc":{"start":{"line":760,"column":6},"end":{"line":765,"column":null}},"type":"if","locations":[{"start":{"line":760,"column":6},"end":{"line":765,"column":null}},{"start":{},"end":{}}],"line":760},"106":{"loc":{"start":{"line":761,"column":8},"end":{"line":762,"column":null}},"type":"binary-expr","locations":[{"start":{"line":761,"column":8},"end":{"line":761,"column":null}},{"start":{"line":762,"column":8},"end":{"line":762,"column":null}}],"line":761},"107":{"loc":{"start":{"line":775,"column":4},"end":{"line":777,"column":null}},"type":"if","locations":[{"start":{"line":775,"column":4},"end":{"line":777,"column":null}},{"start":{},"end":{}}],"line":775},"108":{"loc":{"start":{"line":775,"column":8},"end":{"line":775,"column":48}},"type":"binary-expr","locations":[{"start":{"line":775,"column":8},"end":{"line":775,"column":33}},{"start":{"line":775,"column":33},"end":{"line":775,"column":48}}],"line":775},"109":{"loc":{"start":{"line":790,"column":30},"end":{"line":790,"column":43}},"type":"binary-expr","locations":[{"start":{"line":790,"column":30},"end":{"line":790,"column":41}},{"start":{"line":790,"column":41},"end":{"line":790,"column":43}}],"line":790},"110":{"loc":{"start":{"line":811,"column":4},"end":{"line":813,"column":null}},"type":"if","locations":[{"start":{"line":811,"column":4},"end":{"line":813,"column":null}},{"start":{},"end":{}}],"line":811},"111":{"loc":{"start":{"line":817,"column":4},"end":{"line":827,"column":null}},"type":"if","locations":[{"start":{"line":817,"column":4},"end":{"line":827,"column":null}},{"start":{},"end":{}}],"line":817},"112":{"loc":{"start":{"line":817,"column":8},"end":{"line":817,"column":64}},"type":"binary-expr","locations":[{"start":{"line":817,"column":8},"end":{"line":817,"column":37}},{"start":{"line":817,"column":37},"end":{"line":817,"column":64}}],"line":817},"113":{"loc":{"start":{"line":823,"column":6},"end":{"line":825,"column":null}},"type":"if","locations":[{"start":{"line":823,"column":6},"end":{"line":825,"column":null}},{"start":{},"end":{}}],"line":823},"114":{"loc":{"start":{"line":830,"column":4},"end":{"line":832,"column":null}},"type":"if","locations":[{"start":{"line":830,"column":4},"end":{"line":832,"column":null}},{"start":{},"end":{}}],"line":830},"115":{"loc":{"start":{"line":834,"column":4},"end":{"line":844,"column":null}},"type":"if","locations":[{"start":{"line":834,"column":4},"end":{"line":844,"column":null}},{"start":{},"end":{}}],"line":834},"116":{"loc":{"start":{"line":840,"column":6},"end":{"line":842,"column":null}},"type":"if","locations":[{"start":{"line":840,"column":6},"end":{"line":842,"column":null}},{"start":{},"end":{}}],"line":840},"117":{"loc":{"start":{"line":851,"column":4},"end":{"line":853,"column":null}},"type":"if","locations":[{"start":{"line":851,"column":4},"end":{"line":853,"column":null}},{"start":{},"end":{}}],"line":851},"118":{"loc":{"start":{"line":866,"column":6},"end":{"line":866,"column":null}},"type":"binary-expr","locations":[{"start":{"line":866,"column":6},"end":{"line":866,"column":19}},{"start":{"line":866,"column":19},"end":{"line":866,"column":null}}],"line":866},"119":{"loc":{"start":{"line":868,"column":4},"end":{"line":873,"column":null}},"type":"if","locations":[{"start":{"line":868,"column":4},"end":{"line":873,"column":null}},{"start":{},"end":{}}],"line":868},"120":{"loc":{"start":{"line":869,"column":6},"end":{"line":870,"column":null}},"type":"binary-expr","locations":[{"start":{"line":869,"column":6},"end":{"line":869,"column":null}},{"start":{"line":870,"column":6},"end":{"line":870,"column":null}}],"line":869},"121":{"loc":{"start":{"line":877,"column":6},"end":{"line":879,"column":null}},"type":"if","locations":[{"start":{"line":877,"column":6},"end":{"line":879,"column":null}},{"start":{},"end":{}}],"line":877},"122":{"loc":{"start":{"line":885,"column":10},"end":{"line":887,"column":null}},"type":"cond-expr","locations":[{"start":{"line":886,"column":14},"end":{"line":886,"column":null}},{"start":{"line":887,"column":14},"end":{"line":887,"column":null}}],"line":885},"123":{"loc":{"start":{"line":900,"column":23},"end":{"line":900,"column":null}},"type":"cond-expr","locations":[{"start":{"line":900,"column":48},"end":{"line":900,"column":64}},{"start":{"line":900,"column":64},"end":{"line":900,"column":null}}],"line":900},"124":{"loc":{"start":{"line":909,"column":11},"end":{"line":909,"column":null}},"type":"binary-expr","locations":[{"start":{"line":909,"column":11},"end":{"line":909,"column":57}},{"start":{"line":909,"column":57},"end":{"line":909,"column":null}}],"line":909},"125":{"loc":{"start":{"line":929,"column":21},"end":{"line":929,"column":null}},"type":"cond-expr","locations":[{"start":{"line":929,"column":46},"end":{"line":929,"column":62}},{"start":{"line":929,"column":62},"end":{"line":929,"column":null}}],"line":929},"126":{"loc":{"start":{"line":930,"column":19},"end":{"line":930,"column":null}},"type":"binary-expr","locations":[{"start":{"line":930,"column":19},"end":{"line":930,"column":64}},{"start":{"line":930,"column":64},"end":{"line":930,"column":null}}],"line":930},"127":{"loc":{"start":{"line":939,"column":4},"end":{"line":941,"column":null}},"type":"if","locations":[{"start":{"line":939,"column":4},"end":{"line":941,"column":null}},{"start":{},"end":{}}],"line":939},"128":{"loc":{"start":{"line":948,"column":4},"end":{"line":948,"column":null}},"type":"default-arg","locations":[{"start":{"line":948,"column":20},"end":{"line":948,"column":null}}],"line":948},"129":{"loc":{"start":{"line":950,"column":19},"end":{"line":950,"column":null}},"type":"binary-expr","locations":[{"start":{"line":950,"column":19},"end":{"line":950,"column":64}},{"start":{"line":950,"column":64},"end":{"line":950,"column":null}}],"line":950},"130":{"loc":{"start":{"line":959,"column":29},"end":{"line":959,"column":44}},"type":"binary-expr","locations":[{"start":{"line":959,"column":29},"end":{"line":959,"column":42}},{"start":{"line":959,"column":42},"end":{"line":959,"column":44}}],"line":959},"131":{"loc":{"start":{"line":960,"column":4},"end":{"line":962,"column":null}},"type":"if","locations":[{"start":{"line":960,"column":4},"end":{"line":962,"column":null}},{"start":{},"end":{}}],"line":960},"132":{"loc":{"start":{"line":965,"column":4},"end":{"line":967,"column":null}},"type":"if","locations":[{"start":{"line":965,"column":4},"end":{"line":967,"column":null}},{"start":{},"end":{}}],"line":965},"133":{"loc":{"start":{"line":971,"column":23},"end":{"line":973,"column":null}},"type":"cond-expr","locations":[{"start":{"line":972,"column":8},"end":{"line":972,"column":null}},{"start":{"line":973,"column":8},"end":{"line":973,"column":null}}],"line":971},"134":{"loc":{"start":{"line":974,"column":23},"end":{"line":976,"column":null}},"type":"cond-expr","locations":[{"start":{"line":975,"column":8},"end":{"line":975,"column":null}},{"start":{"line":976,"column":8},"end":{"line":976,"column":null}}],"line":974},"135":{"loc":{"start":{"line":983,"column":6},"end":{"line":1018,"column":null}},"type":"binary-expr","locations":[{"start":{"line":983,"column":6},"end":{"line":998,"column":null}},{"start":{"line":999,"column":6},"end":{"line":1008,"column":null}},{"start":{"line":1009,"column":6},"end":{"line":1018,"column":null}}],"line":983},"136":{"loc":{"start":{"line":1010,"column":28},"end":{"line":1010,"column":54}},"type":"binary-expr","locations":[{"start":{"line":1010,"column":28},"end":{"line":1010,"column":52}},{"start":{"line":1010,"column":52},"end":{"line":1010,"column":54}}],"line":1010},"137":{"loc":{"start":{"line":1012,"column":10},"end":{"line":1016,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1012,"column":10},"end":{"line":1012,"column":null}},{"start":{"line":1013,"column":10},"end":{"line":1013,"column":null}},{"start":{"line":1014,"column":10},"end":{"line":1014,"column":null}},{"start":{"line":1015,"column":10},"end":{"line":1015,"column":null}},{"start":{"line":1016,"column":10},"end":{"line":1016,"column":null}}],"line":1012},"138":{"loc":{"start":{"line":1053,"column":6},"end":{"line":1055,"column":null}},"type":"if","locations":[{"start":{"line":1053,"column":6},"end":{"line":1055,"column":null}},{"start":{},"end":{}}],"line":1053},"139":{"loc":{"start":{"line":1058,"column":6},"end":{"line":1060,"column":null}},"type":"if","locations":[{"start":{"line":1058,"column":6},"end":{"line":1060,"column":null}},{"start":{},"end":{}}],"line":1058},"140":{"loc":{"start":{"line":1068,"column":6},"end":{"line":1075,"column":null}},"type":"if","locations":[{"start":{"line":1068,"column":6},"end":{"line":1075,"column":null}},{"start":{},"end":{}}],"line":1068},"141":{"loc":{"start":{"line":1069,"column":8},"end":{"line":1073,"column":null}},"type":"if","locations":[{"start":{"line":1069,"column":8},"end":{"line":1073,"column":null}},{"start":{},"end":{}}],"line":1069},"142":{"loc":{"start":{"line":1077,"column":6},"end":{"line":1081,"column":null}},"type":"if","locations":[{"start":{"line":1077,"column":6},"end":{"line":1081,"column":null}},{"start":{},"end":{}}],"line":1077},"143":{"loc":{"start":{"line":1086,"column":11},"end":{"line":1086,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1086,"column":21},"end":{"line":1086,"column":33}},{"start":{"line":1086,"column":33},"end":{"line":1086,"column":null}}],"line":1086},"144":{"loc":{"start":{"line":1096,"column":4},"end":{"line":1098,"column":null}},"type":"if","locations":[{"start":{"line":1096,"column":4},"end":{"line":1098,"column":null}},{"start":{},"end":{}}],"line":1096},"145":{"loc":{"start":{"line":1104,"column":4},"end":{"line":1116,"column":null}},"type":"if","locations":[{"start":{"line":1104,"column":4},"end":{"line":1116,"column":null}},{"start":{},"end":{}}],"line":1104}},"s":{"0":57,"1":57,"2":57,"3":57,"4":57,"5":57,"6":57,"7":57,"8":57,"9":72,"10":72,"11":50,"12":22,"13":50,"14":50,"15":38,"16":12,"17":9,"18":9,"19":5,"20":4,"21":9,"22":9,"23":9,"24":9,"25":9,"26":9,"27":0,"28":9,"29":0,"30":57,"31":57,"32":57,"33":57,"34":21,"35":21,"36":21,"37":21,"38":21,"39":21,"40":21,"41":21,"42":9,"43":8,"44":1,"45":1,"46":0,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":12,"54":9,"55":9,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":6,"63":6,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":57,"94":0,"95":57,"96":57,"97":57,"98":57,"99":57,"100":57,"101":57,"102":57,"103":57,"104":57,"105":57,"106":57,"107":57,"108":57,"109":0,"110":57,"111":57,"112":57,"113":57,"114":18,"115":18,"116":7,"117":7,"118":7,"119":5,"120":5,"121":5,"122":5,"123":0,"124":0,"125":0,"126":0,"127":0,"128":34,"129":15,"130":15,"131":15,"132":74,"133":211,"134":74,"135":74,"136":137,"137":18,"138":10,"139":119,"140":37,"141":37,"142":181,"143":82,"144":57,"145":57,"146":57,"147":3,"148":3,"149":0,"150":3,"151":0,"152":3,"153":0,"154":3,"155":2,"156":1,"157":42,"158":42,"159":42,"160":2,"161":2,"162":1,"163":2,"164":2,"165":42,"166":0,"167":0,"168":0,"169":0,"170":0,"171":0,"172":0,"173":0,"174":0,"175":0,"176":42,"177":0,"178":0,"179":0,"180":42,"181":5,"182":2,"183":2,"184":5,"185":42,"186":1,"187":41,"188":41,"189":41,"190":0,"191":41,"192":41,"193":39,"194":2,"195":2,"196":2,"197":2,"198":2,"199":0,"200":0,"201":6,"202":4,"203":2,"204":2,"205":2,"206":0,"207":0,"208":27,"209":0,"210":27,"211":7,"212":20,"213":4,"214":4,"215":16,"216":0,"217":0,"218":0,"219":0,"220":0,"221":16,"222":3,"223":3,"224":3,"225":3,"226":2,"227":2,"228":0,"229":2,"230":1,"231":2,"232":0,"233":0,"234":2,"235":0,"236":0,"237":0,"238":0,"239":0,"240":2,"241":0,"242":0,"243":2,"244":1,"245":0,"246":1,"247":1,"248":0,"249":0,"250":0,"251":0,"252":0,"253":1,"254":1,"255":1,"256":0,"257":1,"258":1,"259":0,"260":0,"261":0,"262":0,"263":0,"264":1,"265":1,"266":1,"267":0,"268":0,"269":0,"270":0,"271":0,"272":0,"273":0,"274":0,"275":1,"276":0,"277":0,"278":2,"279":2,"280":1,"281":1,"282":1,"283":1,"284":1,"285":0,"286":0,"287":0,"288":0,"289":0,"290":0,"291":1,"292":1,"293":1,"294":6,"295":6,"296":9,"297":0,"298":0,"299":0,"300":0,"301":0,"302":0,"303":3,"304":3,"305":1,"306":1,"307":0,"308":1,"309":1,"310":0,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":0,"320":0,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":0,"335":1,"336":1,"337":0,"338":1,"339":1,"340":1,"341":1,"342":1,"343":0,"344":0,"345":0,"346":0,"347":0,"348":1,"349":1,"350":1,"351":1,"352":0,"353":1,"354":2,"355":0,"356":2,"357":2,"358":2,"359":1,"360":2,"361":2,"362":2,"363":2,"364":2},"f":{"0":57,"1":72,"2":50,"3":9,"4":9,"5":57,"6":21,"7":9,"8":1,"9":12,"10":9,"11":9,"12":0,"13":6,"14":0,"15":0,"16":0,"17":57,"18":57,"19":0,"20":57,"21":15,"22":74,"23":211,"24":10,"25":181,"26":57,"27":3,"28":42,"29":1,"30":41,"31":6,"32":27,"33":3,"34":1,"35":0,"36":1,"37":2,"38":6,"39":6,"40":9,"41":0,"42":3,"43":1,"44":0,"45":1,"46":1,"47":1,"48":1,"49":1,"50":2},"b":{"0":[50,22],"1":[72,22],"2":[38,12],"3":[12,4],"4":[5,4],"5":[0,9],"6":[21],"7":[21,0],"8":[21,10],"9":[10,11],"10":[21,11],"11":[11,10],"12":[21,15,0],"13":[8,1],"14":[0,1],"15":[1,1],"16":[1,0],"17":[1,1],"18":[12,12],"19":[9,3],"20":[0,0],"21":[6,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,57],"27":[57,53],"28":[57,0],"29":[18,39],"30":[5,0],"31":[5,5],"32":[15],"33":[15,9],"34":[74,137],"35":[0,74],"36":[18,119],"37":[37,82],"38":[119,87],"39":[57],"40":[37,20],"41":[37,20],"42":[57,57],"43":[57,31],"44":[0,3],"45":[0,3],"46":[0,3],"47":[2,1],"48":[42,0],"49":[2,40],"50":[0,2],"51":[1,1],"52":[1,1],"53":[2,1],"54":[0,42],"55":[0,0],"56":[0,0],"57":[0,0],"58":[0,0],"59":[0,0],"60":[0,42],"61":[0,0],"62":[5,37],"63":[42,38],"64":[2,3],"65":[5,2],"66":[0,41],"67":[39,2],"68":[2,0],"69":[2,2],"70":[4,2],"71":[6,2],"72":[2,0],"73":[2,0],"74":[0,0],"75":[0,27],"76":[0,0],"77":[7,20],"78":[4,16],"79":[20,4],"80":[4,0],"81":[0,16],"82":[16,0,0],"83":[0,0],"84":[0,0],"85":[0,0],"86":[0,0],"87":[3,0],"88":[3,0],"89":[3,2],"90":[2,1],"91":[2,0],"92":[0,2],"93":[2,2],"94":[1,1],"95":[2,1],"96":[0,2],"97":[0,0],"98":[0,2],"99":[0,0],"100":[0,0],"101":[0,0],"102":[0,0],"103":[0,0],"104":[0,2],"105":[0,0],"106":[0,0],"107":[0,1],"108":[1,1],"109":[0,0],"110":[0,1],"111":[0,1],"112":[1,1],"113":[0,0],"114":[1,0],"115":[0,0],"116":[0,0],"117":[0,1],"118":[2,2],"119":[1,1],"120":[2,1],"121":[1,0],"122":[0,0],"123":[1,0],"124":[6,4],"125":[0,0],"126":[0,0],"127":[0,0],"128":[3],"129":[3,3],"130":[1,0],"131":[0,1],"132":[0,1],"133":[0,1],"134":[0,1],"135":[1,1,1],"136":[0,0],"137":[0,0,0,0,0],"138":[0,1],"139":[0,1],"140":[0,1],"141":[0,0],"142":[1,0],"143":[1,0],"144":[0,2],"145":[1,1]},"meta":{"lastBranch":146,"lastFunction":51,"lastStatement":365,"seen":{"s:63:37:63:Infinity":0,"s:68:36:71:Infinity":1,"s:72:48:72:Infinity":2,"s:75:37:75:Infinity":3,"s:76:30:76:Infinity":4,"f:78:2:78:24":0,"s:78:24:78:46":5,"s:79:4:79:Infinity":6,"s:80:4:80:Infinity":7,"s:82:4:82:Infinity":8,"f:89:12:89:54":1,"s:90:10:90:Infinity":9,"b:91:4:93:Infinity:undefined:undefined:undefined:undefined":0,"s:91:4:93:Infinity":10,"b:91:8:91:41:91:41:91:72":1,"s:92:6:92:Infinity":11,"s:95:4:95:Infinity":12,"f:98:12:98:54":2,"s:99:22:99:Infinity":13,"b:100:4:102:Infinity:undefined:undefined:undefined:undefined":2,"s:100:4:102:Infinity":14,"s:101:6:101:Infinity":15,"s:104:4:106:Infinity":16,"b:105:6:105:Infinity:106:6:106:Infinity":3,"f:110:12:110:36":3,"s:111:22:111:Infinity":17,"b:112:4:116:Infinity:114:11:116:Infinity":4,"s:112:4:116:Infinity":18,"s:113:6:113:Infinity":19,"s:115:6:115:Infinity":20,"s:119:4:119:Infinity":21,"f:122:12:122:36":4,"s:123:4:125:Infinity":22,"s:127:4:138:Infinity":23,"s:128:6:128:Infinity":24,"s:129:6:129:Infinity":25,"b:130:6:132:Infinity:undefined:undefined:undefined:undefined":5,"s:130:6:132:Infinity":26,"s:131:8:131:Infinity":27,"s:135:6:135:Infinity":28,"s:137:6:137:Infinity":29,"f:141:12:141:52":5,"s:142:26:142:Infinity":30,"s:143:22:143:Infinity":31,"s:144:22:144:Infinity":32,"s:146:4:150:Infinity":33,"f:153:12:153:34":6,"b:153:51:153:71":6,"s:154:17:154:Infinity":34,"b:154:17:154:51:154:51:154:Infinity":7,"s:156:6:157:Infinity":35,"b:156:6:156:Infinity:157:6:157:Infinity":8,"s:158:27:160:Infinity":36,"b:159:8:159:Infinity:160:8:160:Infinity":9,"s:161:26:161:Infinity":37,"s:162:24:162:Infinity":38,"b:162:24:162:47:162:47:162:Infinity":10,"s:163:22:165:Infinity":39,"b:164:8:164:Infinity:165:8:165:Infinity":11,"s:167:6:171:Infinity":40,"b:167:6:167:Infinity:168:7:170:Infinity:171:6:171:Infinity":12,"s:173:4:177:Infinity":41,"f:180:12:180:37":7,"b:185:4:187:Infinity:undefined:undefined:undefined:undefined":13,"s:185:4:187:Infinity":42,"s:186:6:186:Infinity":43,"s:189:25:189:Infinity":44,"b:190:4:192:Infinity:undefined:undefined:undefined:undefined":14,"s:190:4:192:Infinity":45,"b:190:8:190:25:190:25:190:55":15,"s:191:6:191:Infinity":46,"s:194:26:194:Infinity":47,"b:195:4:204:Infinity:undefined:undefined:undefined:undefined":16,"s:195:4:204:Infinity":48,"b:196:6:196:Infinity:197:6:197:Infinity":17,"s:199:29:202:Infinity":49,"s:203:6:203:Infinity":50,"s:206:4:215:Infinity":51,"f:218:12:218:50":8,"s:219:4:219:Infinity":52,"f:222:12:222:48":9,"s:223:4:223:Infinity":53,"b:223:11:223:43:223:43:223:Infinity":18,"f:230:12:230:33":10,"s:231:4:231:Infinity":54,"b:231:11:231:41:231:41:231:Infinity":19,"f:234:12:234:56":11,"s:235:4:235:Infinity":55,"f:238:18:238:53":12,"s:239:16:239:Infinity":56,"s:240:21:240:Infinity":57,"b:241:4:243:Infinity:undefined:undefined:undefined:undefined":20,"s:241:4:243:Infinity":58,"s:242:6:242:Infinity":59,"s:245:4:245:Infinity":60,"s:246:4:246:Infinity":61,"f:249:18:249:37":13,"b:250:4:252:Infinity:undefined:undefined:undefined:undefined":21,"s:250:4:252:Infinity":62,"s:251:6:251:Infinity":63,"s:254:4:254:Infinity":64,"s:256:20:272:Infinity":65,"f:264:6:264:13":14,"s:265:8:270:Infinity":66,"s:274:4:274:Infinity":67,"s:275:4:275:Infinity":68,"f:286:8:286:23":15,"b:287:4:287:Infinity:undefined:undefined:undefined:undefined":22,"s:287:4:287:Infinity":69,"s:287:20:287:Infinity":70,"s:289:4:313:Infinity":71,"s:291:25:291:Infinity":72,"s:292:22:292:Infinity":73,"b:293:6:299:Infinity:undefined:undefined:undefined:undefined":23,"s:293:6:299:Infinity":74,"s:294:8:294:Infinity":75,"s:295:8:295:Infinity":76,"s:296:8:298:Infinity":77,"b:302:6:307:Infinity:undefined:undefined:undefined:undefined":24,"s:302:6:307:Infinity":78,"s:303:8:303:Infinity":79,"s:304:8:306:Infinity":80,"s:309:6:312:Infinity":81,"f:320:8:320:44":16,"s:321:23:321:Infinity":82,"s:322:24:322:Infinity":83,"s:325:4:334:Infinity":84,"s:326:6:333:Infinity":85,"s:327:24:327:Infinity":86,"b:328:8:330:Infinity:undefined:undefined:undefined:undefined":25,"s:328:8:330:Infinity":87,"s:329:10:329:Infinity":88,"s:332:8:332:Infinity":89,"s:336:4:336:Infinity":90,"s:337:4:337:Infinity":91,"s:338:4:340:Infinity":92,"f:347:12:347:38":17,"b:348:4:354:Infinity:undefined:undefined:undefined:undefined":26,"s:348:4:354:Infinity":93,"s:349:6:353:Infinity":94,"s:356:4:356:Infinity":95,"s:357:4:360:Infinity":96,"s:361:4:361:Infinity":97,"s:362:4:362:Infinity":98,"s:363:4:363:Infinity":99,"s:366:4:368:Infinity":100,"b:367:6:367:Infinity:368:6:368:Infinity":27,"s:370:4:370:Infinity":101,"f:373:12:373:43":18,"s:374:17:374:Infinity":102,"s:375:17:375:Infinity":103,"s:376:4:376:Infinity":104,"s:377:4:377:Infinity":105,"s:378:4:382:Infinity":106,"s:383:4:385:Infinity":107,"s:387:4:389:Infinity":108,"f:387:37:387:38":19,"s:388:6:388:Infinity":109,"b:391:4:398:Infinity:undefined:undefined:undefined:undefined":28,"s:391:4:398:Infinity":110,"s:392:6:397:Infinity":111,"f:406:18:406:63":20,"s:407:4:455:Infinity":112,"b:408:6:413:Infinity:undefined:undefined:undefined:undefined":29,"s:408:6:413:Infinity":113,"s:409:8:411:Infinity":114,"s:412:8:412:Infinity":115,"s:415:24:415:Infinity":116,"s:416:6:418:Infinity":117,"s:420:24:420:Infinity":118,"s:421:39:421:Infinity":119,"b:423:6:428:Infinity:undefined:undefined:undefined:undefined":30,"s:423:6:428:Infinity":120,"b:423:10:423:32:423:32:423:60":31,"s:424:8:426:Infinity":121,"s:427:8:427:Infinity":122,"s:431:6:433:Infinity":123,"s:432:8:432:Infinity":124,"s:436:6:444:Infinity":125,"s:437:8:443:Infinity":126,"s:446:6:448:Infinity":127,"s:450:6:453:Infinity":128,"f:462:12:462:Infinity":21,"b:465:18:465:Infinity":32,"s:468:10:472:Infinity":129,"b:471:6:471:14:471:14:471:Infinity":33,"s:473:4:478:Infinity":130,"s:479:4:479:Infinity":131,"f:482:12:482:30":22,"s:483:4:486:Infinity":132,"f:489:12:489:25":23,"b:490:4:495:Infinity:undefined:undefined:undefined:undefined":34,"s:490:4:495:Infinity":133,"s:491:25:491:Infinity":134,"s:492:6:494:Infinity":135,"b:493:10:493:Infinity:494:10:494:Infinity":35,"b:497:4:499:Infinity:undefined:undefined:undefined:undefined":36,"s:497:4:499:Infinity":136,"s:498:6:498:Infinity":137,"f:498:36:498:37":24,"s:498:46:498:69":138,"b:501:4:509:Infinity:undefined:undefined:undefined:undefined":37,"s:501:4:509:Infinity":139,"b:501:8:501:17:501:17:501:44":38,"s:502:22:505:Infinity":140,"s:506:6:508:Infinity":141,"f:507:20:507:21":25,"s:507:36:507:65":142,"s:511:4:511:Infinity":143,"f:514:12:514:Infinity":26,"b:516:22:516:Infinity":39,"s:520:19:520:Infinity":144,"b:520:41:520:48:520:48:520:Infinity":40,"s:522:6:522:Infinity":145,"b:522:54:522:64:522:64:522:Infinity":41,"b:522:6:522:32:522:32:522:54":42,"s:523:4:532:Infinity":146,"b:525:8:525:19:525:19:525:Infinity":43,"f:539:12:539:Infinity":27,"s:542:18:542:Infinity":147,"b:544:4:546:Infinity:undefined:undefined:undefined:undefined":44,"s:544:4:546:Infinity":148,"s:545:6:545:Infinity":149,"b:548:4:550:Infinity:undefined:undefined:undefined:undefined":45,"s:548:4:550:Infinity":150,"s:549:6:549:Infinity":151,"b:552:4:554:Infinity:undefined:undefined:undefined:undefined":46,"s:552:4:554:Infinity":152,"s:553:6:553:Infinity":153,"b:556:4:558:Infinity:undefined:undefined:undefined:undefined":47,"s:556:4:558:Infinity":154,"s:557:6:557:Infinity":155,"s:560:4:560:Infinity":156,"f:563:12:563:Infinity":28,"s:567:31:567:Infinity":157,"s:568:23:568:Infinity":158,"b:568:29:568:40:568:40:568:44":48,"b:570:4:586:Infinity:undefined:undefined:undefined:undefined":49,"s:570:4:586:Infinity":159,"s:571:20:575:Infinity":160,"b:572:10:572:Infinity:573:10:575:Infinity":50,"b:574:12:574:Infinity:575:12:575:Infinity":51,"b:577:6:582:Infinity:undefined:undefined:undefined:undefined":52,"s:577:6:582:Infinity":161,"b:578:8:578:Infinity:579:8:579:Infinity":53,"s:581:8:581:Infinity":162,"s:584:6:584:Infinity":163,"s:585:6:585:Infinity":164,"b:588:4:604:Infinity:undefined:undefined:undefined:undefined":54,"s:588:4:604:Infinity":165,"b:589:6:593:Infinity:undefined:undefined:undefined:undefined":55,"s:589:6:593:Infinity":166,"s:590:26:590:Infinity":167,"b:590:33:590:53:590:53:590:59":56,"s:591:8:591:Infinity":168,"b:591:58:591:70:591:70:591:Infinity":57,"s:592:8:592:Infinity":169,"b:595:6:598:Infinity:undefined:undefined:undefined:undefined":58,"s:595:6:598:Infinity":170,"s:596:8:596:Infinity":171,"s:597:8:597:Infinity":172,"b:600:6:603:Infinity:undefined:undefined:undefined:undefined":59,"s:600:6:603:Infinity":173,"s:601:8:601:Infinity":174,"s:602:8:602:Infinity":175,"b:606:4:611:Infinity:undefined:undefined:undefined:undefined":60,"s:606:4:611:Infinity":176,"b:607:6:610:Infinity:undefined:undefined:undefined:undefined":61,"s:607:6:610:Infinity":177,"s:608:8:608:Infinity":178,"s:609:8:609:Infinity":179,"b:613:4:622:Infinity:undefined:undefined:undefined:undefined":62,"s:613:4:622:Infinity":180,"b:613:8:613:46:613:46:613:76":63,"b:614:6:620:Infinity:undefined:undefined:undefined:undefined":64,"s:614:6:620:Infinity":181,"b:615:8:615:Infinity:616:8:616:Infinity":65,"s:618:8:618:Infinity":182,"s:619:8:619:Infinity":183,"s:621:6:621:Infinity":184,"s:624:4:624:Infinity":185,"f:627:2:627:Infinity":29,"s:631:4:631:Infinity":186,"f:634:8:634:17":30,"s:635:37:635:Infinity":187,"s:636:20:636:Infinity":188,"b:638:4:644:Infinity:undefined:undefined:undefined:undefined":66,"s:638:4:644:Infinity":189,"s:639:6:643:Infinity":190,"s:646:19:646:Infinity":191,"b:648:4:650:Infinity:undefined:undefined:undefined:undefined":67,"s:648:4:650:Infinity":192,"s:649:6:649:Infinity":193,"s:652:4:661:Infinity":194,"s:653:21:653:Infinity":195,"b:654:6:657:Infinity:undefined:undefined:undefined:undefined":68,"s:654:6:657:Infinity":196,"b:654:10:654:20:654:20:654:48":69,"s:655:8:655:Infinity":197,"s:656:8:656:Infinity":198,"s:658:6:658:Infinity":199,"s:660:6:660:Infinity":200,"f:668:12:668:26":31,"b:669:4:671:Infinity:undefined:undefined:undefined:undefined":70,"s:669:4:671:Infinity":201,"b:669:8:669:17:669:17:669:43":71,"s:670:6:670:Infinity":202,"b:673:4:676:Infinity:undefined:undefined:undefined:undefined":72,"s:673:4:676:Infinity":203,"s:674:22:674:Infinity":204,"s:675:6:675:Infinity":205,"b:675:40:675:50:675:50:675:Infinity":73,"s:678:19:678:Infinity":206,"s:679:4:679:Infinity":207,"b:679:34:679:41:679:41:679:Infinity":74,"f:682:12:682:25":32,"b:683:4:685:Infinity:undefined:undefined:undefined:undefined":75,"s:683:4:685:Infinity":208,"s:684:6:684:Infinity":209,"b:684:38:684:46:684:46:684:Infinity":76,"b:687:4:689:Infinity:undefined:undefined:undefined:undefined":77,"s:687:4:689:Infinity":210,"s:688:6:688:Infinity":211,"b:691:4:694:Infinity:undefined:undefined:undefined:undefined":78,"s:691:4:694:Infinity":212,"b:691:8:691:37:691:37:691:70":79,"s:692:21:692:Infinity":213,"s:693:6:693:Infinity":214,"b:693:39:693:48:693:48:693:Infinity":80,"b:696:4:708:Infinity:undefined:undefined:undefined:undefined":81,"s:696:4:708:Infinity":215,"b:697:6:697:Infinity:698:6:698:Infinity:699:6:699:Infinity":82,"s:701:18:701:Infinity":216,"s:702:23:702:Infinity":217,"s:703:19:703:Infinity":218,"b:703:49:703:59:703:59:703:Infinity":83,"b:703:66:703:77:703:77:703:78":84,"b:705:6:707:Infinity:undefined:undefined:undefined:undefined":85,"s:705:6:707:Infinity":219,"b:705:10:705:34:705:34:705:57":86,"s:706:8:706:Infinity":220,"s:710:4:710:Infinity":221,"f:717:12:717:33":33,"s:723:17:723:Infinity":222,"b:723:24:723:37:723:37:723:39":87,"s:724:21:724:Infinity":223,"b:724:52:724:68:724:68:724:Infinity":88,"s:725:21:725:Infinity":224,"b:725:21:725:38:725:38:725:Infinity":89,"b:727:4:738:Infinity:undefined:undefined:undefined:undefined":90,"s:727:4:738:Infinity":225,"s:728:22:728:Infinity":226,"b:728:29:728:45:728:45:728:47":91,"b:729:6:731:Infinity:undefined:undefined:undefined:undefined":92,"s:729:6:731:Infinity":227,"b:729:10:729:22:729:22:729:76":93,"s:730:8:730:Infinity":228,"b:732:6:737:Infinity:undefined:undefined:undefined:undefined":94,"s:732:6:737:Infinity":229,"b:733:8:733:Infinity:734:8:734:Infinity":95,"s:736:8:736:Infinity":230,"b:740:4:744:Infinity:undefined:undefined:undefined:undefined":96,"s:740:4:744:Infinity":231,"b:741:6:743:Infinity:undefined:undefined:undefined:undefined":97,"s:741:6:743:Infinity":232,"s:742:8:742:Infinity":233,"b:746:4:757:Infinity:undefined:undefined:undefined:undefined":98,"s:746:4:757:Infinity":234,"s:747:22:747:Infinity":235,"b:747:29:747:45:747:45:747:47":99,"b:748:6:750:Infinity:undefined:undefined:undefined:undefined":100,"s:748:6:750:Infinity":236,"b:748:10:748:22:748:22:748:76":101,"s:749:8:749:Infinity":237,"b:751:6:756:Infinity:undefined:undefined:undefined:undefined":102,"s:751:6:756:Infinity":238,"b:752:8:752:Infinity:753:8:753:Infinity":103,"s:755:8:755:Infinity":239,"b:759:4:766:Infinity:undefined:undefined:undefined:undefined":104,"s:759:4:766:Infinity":240,"b:760:6:765:Infinity:undefined:undefined:undefined:undefined":105,"s:760:6:765:Infinity":241,"b:761:8:761:Infinity:762:8:762:Infinity":106,"s:764:8:764:Infinity":242,"s:768:4:768:Infinity":243,"f:771:18:771:Infinity":34,"b:775:4:777:Infinity:undefined:undefined:undefined:undefined":107,"s:775:4:777:Infinity":244,"b:775:8:775:33:775:33:775:48":108,"s:776:6:776:Infinity":245,"s:779:4:795:Infinity":246,"s:780:6:780:Infinity":247,"s:781:28:781:Infinity":248,"s:782:19:782:Infinity":249,"s:783:42:787:Infinity":250,"s:789:6:792:Infinity":251,"f:790:13:790:14":35,"s:790:23:790:44":252,"b:790:30:790:41:790:41:790:43":109,"s:794:6:794:Infinity":253,"f:802:18:802:Infinity":36,"s:810:20:810:Infinity":254,"b:811:4:813:Infinity:undefined:undefined:undefined:undefined":110,"s:811:4:813:Infinity":255,"s:812:6:812:Infinity":256,"s:816:6:816:Infinity":257,"b:817:4:827:Infinity:undefined:undefined:undefined:undefined":111,"s:817:4:827:Infinity":258,"b:817:8:817:37:817:37:817:64":112,"s:818:23:821:Infinity":259,"s:822:17:822:Infinity":260,"b:823:6:825:Infinity:undefined:undefined:undefined:undefined":113,"s:823:6:825:Infinity":261,"s:824:8:824:Infinity":262,"s:826:6:826:Infinity":263,"s:829:22:829:Infinity":264,"b:830:4:832:Infinity:undefined:undefined:undefined:undefined":114,"s:830:4:832:Infinity":265,"s:831:6:831:Infinity":266,"b:834:4:844:Infinity:undefined:undefined:undefined:undefined":115,"s:834:4:844:Infinity":267,"s:835:27:838:Infinity":268,"s:839:17:839:Infinity":269,"b:840:6:842:Infinity:undefined:undefined:undefined:undefined":116,"s:840:6:842:Infinity":270,"s:841:8:841:Infinity":271,"s:843:6:843:Infinity":272,"s:846:24:849:Infinity":273,"s:850:20:850:Infinity":274,"b:851:4:853:Infinity:undefined:undefined:undefined:undefined":117,"s:851:4:853:Infinity":275,"s:852:6:852:Infinity":276,"s:855:4:855:Infinity":277,"f:864:18:864:35":37,"s:866:6:866:Infinity":278,"b:866:6:866:19:866:19:866:Infinity":118,"b:868:4:873:Infinity:undefined:undefined:undefined:undefined":119,"s:868:4:873:Infinity":279,"b:869:6:869:Infinity:870:6:870:Infinity":120,"s:872:6:872:Infinity":280,"s:875:4:905:Infinity":281,"s:876:24:876:Infinity":282,"b:877:6:879:Infinity:undefined:undefined:undefined:undefined":121,"s:877:6:879:Infinity":283,"s:878:8:878:Infinity":284,"s:881:6:896:Infinity":285,"s:882:8:882:Infinity":286,"s:885:10:887:Infinity":287,"b:886:14:886:Infinity:887:14:887:Infinity":122,"s:888:8:890:Infinity":288,"s:893:8:895:Infinity":289,"s:898:6:898:Infinity":290,"s:900:23:900:Infinity":291,"b:900:48:900:64:900:64:900:Infinity":123,"s:901:6:903:Infinity":292,"s:904:6:904:Infinity":293,"f:908:12:908:37":38,"s:909:4:909:Infinity":294,"b:909:11:909:57:909:57:909:Infinity":124,"f:912:12:912:38":39,"s:913:4:913:Infinity":295,"f:916:12:916:40":40,"s:917:4:917:Infinity":296,"f:924:12:924:Infinity":41,"s:929:21:929:Infinity":297,"b:929:46:929:62:929:62:929:Infinity":125,"s:930:19:930:Infinity":298,"b:930:19:930:64:930:64:930:Infinity":126,"s:932:4:936:Infinity":299,"b:939:4:941:Infinity:undefined:undefined:undefined:undefined":127,"s:939:4:941:Infinity":300,"s:940:6:940:Infinity":301,"s:943:4:943:Infinity":302,"f:946:12:946:Infinity":42,"b:948:20:948:Infinity":128,"s:950:19:950:Infinity":303,"b:950:19:950:64:950:64:950:Infinity":129,"s:951:4:951:Infinity":304,"f:958:12:958:27":43,"s:959:22:959:Infinity":305,"b:959:29:959:42:959:42:959:44":130,"b:960:4:962:Infinity:undefined:undefined:undefined:undefined":131,"s:960:4:962:Infinity":306,"s:961:6:961:Infinity":307,"s:964:18:964:Infinity":308,"b:965:4:967:Infinity:undefined:undefined:undefined:undefined":132,"s:965:4:967:Infinity":309,"s:966:6:966:Infinity":310,"s:969:27:969:Infinity":311,"s:970:21:970:Infinity":312,"s:971:23:973:Infinity":313,"b:972:8:972:Infinity:973:8:973:Infinity":133,"s:974:23:976:Infinity":314,"b:975:8:975:Infinity:976:8:976:Infinity":134,"s:978:18:978:Infinity":315,"s:979:22:979:Infinity":316,"s:980:20:980:Infinity":317,"s:982:4:1018:Infinity":318,"b:983:6:998:Infinity:999:6:1008:Infinity:1009:6:1018:Infinity":135,"f:1009:19:1009:20":44,"s:1010:21:1010:Infinity":319,"b:1010:28:1010:52:1010:52:1010:54":136,"s:1011:8:1016:Infinity":320,"b:1012:10:1012:Infinity:1013:10:1013:Infinity:1014:10:1014:Infinity:1015:10:1015:Infinity:1016:10:1016:Infinity":137,"f:1026:12:1026:42":45,"s:1027:19:1027:Infinity":321,"s:1028:4:1033:Infinity":322,"f:1030:8:1030:9":46,"s:1031:10:1031:Infinity":323,"f:1036:12:1036:34":47,"s:1037:27:1037:Infinity":324,"s:1038:18:1038:Infinity":325,"s:1040:4:1042:Infinity":326,"s:1041:6:1041:Infinity":327,"s:1043:4:1043:Infinity":328,"f:1046:12:1046:40":48,"s:1048:6:1048:Infinity":329,"s:1050:18:1050:Infinity":330,"s:1051:22:1084:Infinity":331,"f:1051:55:1051:56":49,"s:1052:19:1052:Infinity":332,"b:1053:6:1055:Infinity:undefined:undefined:undefined:undefined":138,"s:1053:6:1055:Infinity":333,"s:1054:8:1054:Infinity":334,"s:1057:24:1057:Infinity":335,"b:1058:6:1060:Infinity:undefined:undefined:undefined:undefined":139,"s:1058:6:1060:Infinity":336,"s:1059:8:1059:Infinity":337,"s:1062:6:1062:Infinity":338,"s:1064:8:1064:Infinity":339,"s:1065:28:1065:Infinity":340,"s:1066:25:1066:Infinity":341,"b:1068:6:1075:Infinity:undefined:undefined:undefined:undefined":140,"s:1068:6:1075:Infinity":342,"b:1069:8:1073:Infinity:undefined:undefined:undefined:undefined":141,"s:1069:8:1073:Infinity":343,"s:1070:23:1070:Infinity":344,"s:1071:23:1071:Infinity":345,"s:1072:10:1072:Infinity":346,"s:1074:8:1074:Infinity":347,"b:1077:6:1081:Infinity:undefined:undefined:undefined:undefined":142,"s:1077:6:1081:Infinity":348,"s:1078:21:1078:Infinity":349,"s:1079:21:1079:Infinity":350,"s:1080:8:1080:Infinity":351,"s:1083:6:1083:Infinity":352,"s:1086:4:1086:Infinity":353,"b:1086:21:1086:33:1086:33:1086:Infinity":143,"f:1093:18:1093:Infinity":50,"b:1096:4:1098:Infinity:undefined:undefined:undefined:undefined":144,"s:1096:4:1098:Infinity":354,"s:1097:6:1097:Infinity":355,"s:1101:24:1101:Infinity":356,"s:1102:10:1102:Infinity":357,"b:1104:4:1116:Infinity:undefined:undefined:undefined:undefined":145,"s:1104:4:1116:Infinity":358,"s:1105:6:1115:Infinity":359,"s:1118:4:1136:Infinity":360,"s:1139:4:1139:Infinity":361,"s:1140:4:1142:Infinity":362,"s:1144:4:1144:Infinity":363,"s:1145:4:1145:Infinity":364}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/tools/tool-handlers.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/tools/tool-handlers.ts","statementMap":{"0":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"1":{"start":{"line":42,"column":4},"end":{"line":42,"column":null}},"2":{"start":{"line":43,"column":4},"end":{"line":43,"column":null}},"3":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"4":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"5":{"start":{"line":52,"column":10},"end":{"line":52,"column":null}},"6":{"start":{"line":53,"column":5},"end":{"line":53,"column":null}},"7":{"start":{"line":60,"column":10},"end":{"line":60,"column":null}},"8":{"start":{"line":61,"column":5},"end":{"line":61,"column":null}},"9":{"start":{"line":62,"column":5},"end":{"line":62,"column":null}},"10":{"start":{"line":69,"column":10},"end":{"line":69,"column":null}},"11":{"start":{"line":70,"column":5},"end":{"line":70,"column":null}},"12":{"start":{"line":71,"column":5},"end":{"line":71,"column":null}},"13":{"start":{"line":78,"column":10},"end":{"line":78,"column":null}},"14":{"start":{"line":79,"column":5},"end":{"line":79,"column":null}},"15":{"start":{"line":80,"column":5},"end":{"line":80,"column":null}},"16":{"start":{"line":81,"column":5},"end":{"line":81,"column":null}},"17":{"start":{"line":82,"column":5},"end":{"line":82,"column":null}},"18":{"start":{"line":93,"column":8},"end":{"line":93,"column":null}},"19":{"start":{"line":95,"column":4},"end":{"line":187,"column":null}},"20":{"start":{"line":97,"column":43},"end":{"line":97,"column":null}},"21":{"start":{"line":98,"column":21},"end":{"line":98,"column":null}},"22":{"start":{"line":99,"column":24},"end":{"line":99,"column":null}},"23":{"start":{"line":101,"column":6},"end":{"line":158,"column":null}},"24":{"start":{"line":103,"column":10},"end":{"line":103,"column":null}},"25":{"start":{"line":105,"column":8},"end":{"line":110,"column":null}},"26":{"start":{"line":112,"column":8},"end":{"line":157,"column":null}},"27":{"start":{"line":113,"column":29},"end":{"line":117,"column":null}},"28":{"start":{"line":119,"column":10},"end":{"line":144,"column":null}},"29":{"start":{"line":120,"column":12},"end":{"line":120,"column":null}},"30":{"start":{"line":122,"column":33},"end":{"line":127,"column":null}},"31":{"start":{"line":128,"column":34},"end":{"line":131,"column":null}},"32":{"start":{"line":132,"column":12},"end":{"line":143,"column":null}},"33":{"start":{"line":146,"column":31},"end":{"line":151,"column":null}},"34":{"start":{"line":152,"column":32},"end":{"line":155,"column":null}},"35":{"start":{"line":156,"column":10},"end":{"line":156,"column":null}},"36":{"start":{"line":160,"column":6},"end":{"line":167,"column":null}},"37":{"start":{"line":161,"column":8},"end":{"line":166,"column":null}},"38":{"start":{"line":169,"column":22},"end":{"line":169,"column":null}},"39":{"start":{"line":170,"column":6},"end":{"line":184,"column":null}},"40":{"start":{"line":186,"column":6},"end":{"line":186,"column":null}},"41":{"start":{"line":194,"column":4},"end":{"line":196,"column":null}},"42":{"start":{"line":195,"column":6},"end":{"line":195,"column":null}},"43":{"start":{"line":198,"column":4},"end":{"line":220,"column":null}},"44":{"start":{"line":199,"column":6},"end":{"line":201,"column":null}},"45":{"start":{"line":200,"column":8},"end":{"line":200,"column":null}},"46":{"start":{"line":203,"column":19},"end":{"line":203,"column":null}},"47":{"start":{"line":204,"column":24},"end":{"line":204,"column":null}},"48":{"start":{"line":205,"column":25},"end":{"line":205,"column":null}},"49":{"start":{"line":207,"column":8},"end":{"line":209,"column":null}},"50":{"start":{"line":211,"column":6},"end":{"line":213,"column":null}},"51":{"start":{"line":212,"column":8},"end":{"line":212,"column":null}},"52":{"start":{"line":215,"column":6},"end":{"line":218,"column":null}},"53":{"start":{"line":228,"column":24},"end":{"line":231,"column":null}},"54":{"start":{"line":231,"column":23},"end":{"line":231,"column":40}},"55":{"start":{"line":233,"column":44},"end":{"line":238,"column":null}},"56":{"start":{"line":240,"column":19},"end":{"line":248,"column":null}},"57":{"start":{"line":250,"column":4},"end":{"line":252,"column":null}},"58":{"start":{"line":251,"column":6},"end":{"line":251,"column":null}},"59":{"start":{"line":254,"column":21},"end":{"line":260,"column":null}},"60":{"start":{"line":262,"column":4},"end":{"line":262,"column":null}},"61":{"start":{"line":266,"column":16},"end":{"line":266,"column":null}},"62":{"start":{"line":267,"column":18},"end":{"line":267,"column":null}},"63":{"start":{"line":268,"column":4},"end":{"line":268,"column":null}},"64":{"start":{"line":268,"column":34},"end":{"line":268,"column":52}},"65":{"start":{"line":272,"column":56},"end":{"line":272,"column":null}},"66":{"start":{"line":274,"column":4},"end":{"line":319,"column":null}},"67":{"start":{"line":276,"column":20},"end":{"line":276,"column":null}},"68":{"start":{"line":277,"column":20},"end":{"line":277,"column":null}},"69":{"start":{"line":278,"column":22},"end":{"line":278,"column":null}},"70":{"start":{"line":281,"column":8},"end":{"line":283,"column":null}},"71":{"start":{"line":283,"column":28},"end":{"line":283,"column":57}},"72":{"start":{"line":285,"column":6},"end":{"line":292,"column":null}},"73":{"start":{"line":286,"column":8},"end":{"line":291,"column":null}},"74":{"start":{"line":295,"column":31},"end":{"line":301,"column":null}},"75":{"start":{"line":304,"column":23},"end":{"line":304,"column":null}},"76":{"start":{"line":305,"column":6},"end":{"line":314,"column":null}},"77":{"start":{"line":306,"column":23},"end":{"line":306,"column":null}},"78":{"start":{"line":307,"column":8},"end":{"line":313,"column":null}},"79":{"start":{"line":308,"column":10},"end":{"line":312,"column":null}},"80":{"start":{"line":316,"column":6},"end":{"line":316,"column":null}},"81":{"start":{"line":318,"column":6},"end":{"line":318,"column":null}},"82":{"start":{"line":323,"column":63},"end":{"line":323,"column":null}},"83":{"start":{"line":325,"column":4},"end":{"line":486,"column":null}},"84":{"start":{"line":326,"column":27},"end":{"line":330,"column":null}},"85":{"start":{"line":332,"column":6},"end":{"line":481,"column":null}},"86":{"start":{"line":333,"column":8},"end":{"line":335,"column":null}},"87":{"start":{"line":334,"column":10},"end":{"line":334,"column":null}},"88":{"start":{"line":336,"column":23},"end":{"line":336,"column":null}},"89":{"start":{"line":337,"column":8},"end":{"line":337,"column":null}},"90":{"start":{"line":338,"column":6},"end":{"line":481,"column":null}},"91":{"start":{"line":340,"column":22},"end":{"line":340,"column":null}},"92":{"start":{"line":341,"column":8},"end":{"line":349,"column":null}},"93":{"start":{"line":342,"column":23},"end":{"line":342,"column":null}},"94":{"start":{"line":343,"column":10},"end":{"line":348,"column":null}},"95":{"start":{"line":344,"column":12},"end":{"line":347,"column":null}},"96":{"start":{"line":350,"column":6},"end":{"line":481,"column":null}},"97":{"start":{"line":351,"column":30},"end":{"line":351,"column":null}},"98":{"start":{"line":352,"column":25},"end":{"line":352,"column":null}},"99":{"start":{"line":353,"column":20},"end":{"line":363,"column":null}},"100":{"start":{"line":354,"column":32},"end":{"line":354,"column":null}},"101":{"start":{"line":355,"column":10},"end":{"line":355,"column":null}},"102":{"start":{"line":355,"column":26},"end":{"line":355,"column":null}},"103":{"start":{"line":356,"column":10},"end":{"line":361,"column":null}},"104":{"start":{"line":357,"column":12},"end":{"line":359,"column":null}},"105":{"start":{"line":358,"column":14},"end":{"line":358,"column":null}},"106":{"start":{"line":360,"column":12},"end":{"line":360,"column":null}},"107":{"start":{"line":362,"column":10},"end":{"line":362,"column":null}},"108":{"start":{"line":365,"column":8},"end":{"line":367,"column":null}},"109":{"start":{"line":366,"column":10},"end":{"line":366,"column":null}},"110":{"start":{"line":369,"column":24},"end":{"line":369,"column":null}},"111":{"start":{"line":369,"column":49},"end":{"line":369,"column":53}},"112":{"start":{"line":370,"column":26},"end":{"line":370,"column":null}},"113":{"start":{"line":372,"column":8},"end":{"line":404,"column":null}},"114":{"start":{"line":373,"column":26},"end":{"line":373,"column":null}},"115":{"start":{"line":374,"column":29},"end":{"line":376,"column":null}},"116":{"start":{"line":376,"column":29},"end":{"line":376,"column":51}},"117":{"start":{"line":378,"column":10},"end":{"line":401,"column":null}},"118":{"start":{"line":379,"column":33},"end":{"line":379,"column":null}},"119":{"start":{"line":380,"column":12},"end":{"line":386,"column":null}},"120":{"start":{"line":385,"column":14},"end":{"line":385,"column":null}},"121":{"start":{"line":388,"column":25},"end":{"line":390,"column":null}},"122":{"start":{"line":390,"column":31},"end":{"line":390,"column":56}},"123":{"start":{"line":391,"column":12},"end":{"line":400,"column":null}},"124":{"start":{"line":392,"column":33},"end":{"line":392,"column":null}},"125":{"start":{"line":393,"column":14},"end":{"line":399,"column":null}},"126":{"start":{"line":398,"column":16},"end":{"line":398,"column":null}},"127":{"start":{"line":403,"column":10},"end":{"line":403,"column":null}},"128":{"start":{"line":406,"column":35},"end":{"line":406,"column":null}},"129":{"start":{"line":407,"column":27},"end":{"line":407,"column":null}},"130":{"start":{"line":408,"column":28},"end":{"line":408,"column":null}},"131":{"start":{"line":409,"column":28},"end":{"line":409,"column":null}},"132":{"start":{"line":410,"column":32},"end":{"line":410,"column":null}},"133":{"start":{"line":412,"column":34},"end":{"line":423,"column":null}},"134":{"start":{"line":413,"column":29},"end":{"line":413,"column":null}},"135":{"start":{"line":414,"column":10},"end":{"line":414,"column":null}},"136":{"start":{"line":414,"column":34},"end":{"line":414,"column":null}},"137":{"start":{"line":415,"column":21},"end":{"line":415,"column":null}},"138":{"start":{"line":416,"column":10},"end":{"line":421,"column":null}},"139":{"start":{"line":416,"column":23},"end":{"line":416,"column":26}},"140":{"start":{"line":417,"column":28},"end":{"line":417,"column":null}},"141":{"start":{"line":418,"column":12},"end":{"line":420,"column":null}},"142":{"start":{"line":419,"column":14},"end":{"line":419,"column":null}},"143":{"start":{"line":422,"column":10},"end":{"line":422,"column":null}},"144":{"start":{"line":425,"column":22},"end":{"line":453,"column":null}},"145":{"start":{"line":426,"column":10},"end":{"line":426,"column":null}},"146":{"start":{"line":426,"column":39},"end":{"line":426,"column":null}},"147":{"start":{"line":427,"column":10},"end":{"line":427,"column":null}},"148":{"start":{"line":428,"column":10},"end":{"line":428,"column":null}},"149":{"start":{"line":430,"column":28},"end":{"line":430,"column":null}},"150":{"start":{"line":431,"column":10},"end":{"line":448,"column":null}},"151":{"start":{"line":432,"column":12},"end":{"line":435,"column":null}},"152":{"start":{"line":433,"column":14},"end":{"line":433,"column":null}},"153":{"start":{"line":434,"column":14},"end":{"line":434,"column":null}},"154":{"start":{"line":437,"column":12},"end":{"line":447,"column":null}},"155":{"start":{"line":438,"column":28},"end":{"line":438,"column":null}},"156":{"start":{"line":439,"column":14},"end":{"line":446,"column":null}},"157":{"start":{"line":440,"column":30},"end":{"line":440,"column":null}},"158":{"start":{"line":441,"column":28},"end":{"line":441,"column":null}},"159":{"start":{"line":442,"column":16},"end":{"line":445,"column":null}},"160":{"start":{"line":443,"column":18},"end":{"line":443,"column":null}},"161":{"start":{"line":444,"column":18},"end":{"line":444,"column":null}},"162":{"start":{"line":450,"column":10},"end":{"line":450,"column":null}},"163":{"start":{"line":451,"column":10},"end":{"line":451,"column":null}},"164":{"start":{"line":452,"column":10},"end":{"line":452,"column":null}},"165":{"start":{"line":455,"column":8},"end":{"line":459,"column":null}},"166":{"start":{"line":456,"column":10},"end":{"line":458,"column":null}},"167":{"start":{"line":457,"column":12},"end":{"line":457,"column":null}},"168":{"start":{"line":461,"column":8},"end":{"line":467,"column":null}},"169":{"start":{"line":461,"column":62},"end":{"line":467,"column":10}},"170":{"start":{"line":463,"column":25},"end":{"line":463,"column":null}},"171":{"start":{"line":464,"column":12},"end":{"line":464,"column":null}},"172":{"start":{"line":469,"column":8},"end":{"line":474,"column":null}},"173":{"start":{"line":470,"column":10},"end":{"line":473,"column":null}},"174":{"start":{"line":477,"column":8},"end":{"line":480,"column":null}},"175":{"start":{"line":483,"column":6},"end":{"line":483,"column":null}},"176":{"start":{"line":485,"column":6},"end":{"line":485,"column":null}},"177":{"start":{"line":496,"column":20},"end":{"line":496,"column":null}},"178":{"start":{"line":497,"column":19},"end":{"line":497,"column":null}},"179":{"start":{"line":498,"column":22},"end":{"line":498,"column":null}},"180":{"start":{"line":499,"column":37},"end":{"line":501,"column":null}},"181":{"start":{"line":504,"column":6},"end":{"line":508,"column":null}},"182":{"start":{"line":510,"column":19},"end":{"line":513,"column":null}},"183":{"start":{"line":515,"column":4},"end":{"line":521,"column":null}},"184":{"start":{"line":516,"column":21},"end":{"line":516,"column":null}},"185":{"start":{"line":518,"column":6},"end":{"line":518,"column":null}},"186":{"start":{"line":520,"column":6},"end":{"line":520,"column":null}},"187":{"start":{"line":532,"column":8},"end":{"line":532,"column":null}},"188":{"start":{"line":534,"column":4},"end":{"line":627,"column":null}},"189":{"start":{"line":535,"column":22},"end":{"line":539,"column":null}},"190":{"start":{"line":541,"column":6},"end":{"line":546,"column":null}},"191":{"start":{"line":542,"column":8},"end":{"line":545,"column":null}},"192":{"start":{"line":549,"column":6},"end":{"line":561,"column":null}},"193":{"start":{"line":551,"column":10},"end":{"line":555,"column":null}},"194":{"start":{"line":556,"column":8},"end":{"line":560,"column":null}},"195":{"start":{"line":557,"column":10},"end":{"line":559,"column":null}},"196":{"start":{"line":563,"column":51},"end":{"line":563,"column":null}},"197":{"start":{"line":564,"column":6},"end":{"line":619,"column":null}},"198":{"start":{"line":565,"column":26},"end":{"line":565,"column":null}},"199":{"start":{"line":566,"column":31},"end":{"line":568,"column":null}},"200":{"start":{"line":569,"column":30},"end":{"line":569,"column":null}},"201":{"start":{"line":571,"column":8},"end":{"line":581,"column":null}},"202":{"start":{"line":572,"column":10},"end":{"line":576,"column":null}},"203":{"start":{"line":577,"column":10},"end":{"line":577,"column":null}},"204":{"start":{"line":579,"column":10},"end":{"line":579,"column":null}},"205":{"start":{"line":580,"column":10},"end":{"line":580,"column":null}},"206":{"start":{"line":583,"column":8},"end":{"line":596,"column":null}},"207":{"start":{"line":584,"column":29},"end":{"line":589,"column":null}},"208":{"start":{"line":590,"column":10},"end":{"line":593,"column":null}},"209":{"start":{"line":595,"column":10},"end":{"line":595,"column":null}},"210":{"start":{"line":598,"column":8},"end":{"line":618,"column":null}},"211":{"start":{"line":599,"column":36},"end":{"line":614,"column":null}},"212":{"start":{"line":615,"column":10},"end":{"line":615,"column":null}},"213":{"start":{"line":617,"column":10},"end":{"line":617,"column":null}},"214":{"start":{"line":621,"column":6},"end":{"line":624,"column":null}},"215":{"start":{"line":626,"column":6},"end":{"line":626,"column":null}},"216":{"start":{"line":631,"column":47},"end":{"line":631,"column":null}},"217":{"start":{"line":633,"column":4},"end":{"line":704,"column":null}},"218":{"start":{"line":634,"column":26},"end":{"line":634,"column":null}},"219":{"start":{"line":640,"column":24},"end":{"line":640,"column":null}},"220":{"start":{"line":641,"column":6},"end":{"line":658,"column":null}},"221":{"start":{"line":646,"column":8},"end":{"line":657,"column":null}},"222":{"start":{"line":650,"column":66},"end":{"line":654,"column":14}},"223":{"start":{"line":660,"column":30},"end":{"line":660,"column":null}},"224":{"start":{"line":661,"column":19},"end":{"line":661,"column":null}},"225":{"start":{"line":663,"column":6},"end":{"line":679,"column":null}},"226":{"start":{"line":664,"column":24},"end":{"line":664,"column":null}},"227":{"start":{"line":665,"column":24},"end":{"line":673,"column":null}},"228":{"start":{"line":666,"column":23},"end":{"line":666,"column":null}},"229":{"start":{"line":667,"column":10},"end":{"line":671,"column":null}},"230":{"start":{"line":675,"column":8},"end":{"line":678,"column":null}},"231":{"start":{"line":676,"column":10},"end":{"line":676,"column":null}},"232":{"start":{"line":677,"column":10},"end":{"line":677,"column":null}},"233":{"start":{"line":681,"column":6},"end":{"line":693,"column":null}},"234":{"start":{"line":682,"column":8},"end":{"line":692,"column":null}},"235":{"start":{"line":687,"column":32},"end":{"line":687,"column":42}},"236":{"start":{"line":695,"column":6},"end":{"line":701,"column":null}},"237":{"start":{"line":703,"column":6},"end":{"line":703,"column":null}},"238":{"start":{"line":708,"column":17},"end":{"line":708,"column":null}},"239":{"start":{"line":709,"column":20},"end":{"line":709,"column":null}},"240":{"start":{"line":711,"column":4},"end":{"line":728,"column":null}},"241":{"start":{"line":712,"column":21},"end":{"line":712,"column":null}},"242":{"start":{"line":714,"column":6},"end":{"line":725,"column":null}},"243":{"start":{"line":727,"column":6},"end":{"line":727,"column":null}},"244":{"start":{"line":736,"column":36},"end":{"line":736,"column":null}},"245":{"start":{"line":738,"column":4},"end":{"line":806,"column":null}},"246":{"start":{"line":739,"column":24},"end":{"line":739,"column":null}},"247":{"start":{"line":740,"column":22},"end":{"line":740,"column":null}},"248":{"start":{"line":742,"column":8},"end":{"line":743,"column":null}},"249":{"start":{"line":745,"column":6},"end":{"line":756,"column":null}},"250":{"start":{"line":750,"column":8},"end":{"line":755,"column":null}},"251":{"start":{"line":758,"column":6},"end":{"line":758,"column":null}},"252":{"start":{"line":760,"column":6},"end":{"line":767,"column":null}},"253":{"start":{"line":761,"column":8},"end":{"line":766,"column":null}},"254":{"start":{"line":769,"column":6},"end":{"line":776,"column":null}},"255":{"start":{"line":770,"column":8},"end":{"line":775,"column":null}},"256":{"start":{"line":778,"column":6},"end":{"line":778,"column":null}},"257":{"start":{"line":779,"column":6},"end":{"line":779,"column":null}},"258":{"start":{"line":781,"column":22},"end":{"line":781,"column":null}},"259":{"start":{"line":783,"column":6},"end":{"line":798,"column":null}},"260":{"start":{"line":800,"column":6},"end":{"line":805,"column":null}},"261":{"start":{"line":815,"column":8},"end":{"line":815,"column":null}},"262":{"start":{"line":817,"column":4},"end":{"line":1010,"column":null}},"263":{"start":{"line":818,"column":6},"end":{"line":824,"column":null}},"264":{"start":{"line":819,"column":8},"end":{"line":823,"column":null}},"265":{"start":{"line":826,"column":28},"end":{"line":826,"column":null}},"266":{"start":{"line":827,"column":22},"end":{"line":827,"column":null}},"267":{"start":{"line":829,"column":8},"end":{"line":830,"column":null}},"268":{"start":{"line":832,"column":6},"end":{"line":843,"column":null}},"269":{"start":{"line":837,"column":8},"end":{"line":842,"column":null}},"270":{"start":{"line":845,"column":6},"end":{"line":845,"column":null}},"271":{"start":{"line":846,"column":6},"end":{"line":846,"column":null}},"272":{"start":{"line":847,"column":54},"end":{"line":847,"column":null}},"273":{"start":{"line":848,"column":26},"end":{"line":848,"column":null}},"274":{"start":{"line":850,"column":12},"end":{"line":850,"column":null}},"275":{"start":{"line":852,"column":6},"end":{"line":864,"column":null}},"276":{"start":{"line":853,"column":8},"end":{"line":863,"column":null}},"277":{"start":{"line":866,"column":6},"end":{"line":873,"column":null}},"278":{"start":{"line":867,"column":8},"end":{"line":872,"column":null}},"279":{"start":{"line":875,"column":6},"end":{"line":882,"column":null}},"280":{"start":{"line":876,"column":8},"end":{"line":881,"column":null}},"281":{"start":{"line":887,"column":6},"end":{"line":978,"column":null}},"282":{"start":{"line":909,"column":12},"end":{"line":909,"column":null}},"283":{"start":{"line":910,"column":10},"end":{"line":914,"column":null}},"284":{"start":{"line":911,"column":12},"end":{"line":913,"column":null}},"285":{"start":{"line":916,"column":10},"end":{"line":963,"column":null}},"286":{"start":{"line":919,"column":12},"end":{"line":919,"column":null}},"287":{"start":{"line":920,"column":12},"end":{"line":922,"column":null}},"288":{"start":{"line":923,"column":10},"end":{"line":963,"column":null}},"289":{"start":{"line":926,"column":12},"end":{"line":946,"column":null}},"290":{"start":{"line":928,"column":16},"end":{"line":928,"column":null}},"291":{"start":{"line":929,"column":14},"end":{"line":939,"column":null}},"292":{"start":{"line":933,"column":16},"end":{"line":933,"column":null}},"293":{"start":{"line":935,"column":16},"end":{"line":935,"column":null}},"294":{"start":{"line":936,"column":16},"end":{"line":938,"column":null}},"295":{"start":{"line":941,"column":14},"end":{"line":944,"column":null}},"296":{"start":{"line":948,"column":31},"end":{"line":948,"column":null}},"297":{"start":{"line":949,"column":12},"end":{"line":957,"column":null}},"298":{"start":{"line":950,"column":14},"end":{"line":952,"column":null}},"299":{"start":{"line":953,"column":12},"end":{"line":957,"column":null}},"300":{"start":{"line":954,"column":14},"end":{"line":956,"column":null}},"301":{"start":{"line":959,"column":33},"end":{"line":959,"column":null}},"302":{"start":{"line":960,"column":12},"end":{"line":962,"column":null}},"303":{"start":{"line":967,"column":26},"end":{"line":967,"column":null}},"304":{"start":{"line":968,"column":10},"end":{"line":968,"column":null}},"305":{"start":{"line":970,"column":27},"end":{"line":970,"column":null}},"306":{"start":{"line":971,"column":24},"end":{"line":971,"column":null}},"307":{"start":{"line":972,"column":10},"end":{"line":974,"column":null}},"308":{"start":{"line":975,"column":10},"end":{"line":977,"column":null}},"309":{"start":{"line":976,"column":12},"end":{"line":976,"column":null}},"310":{"start":{"line":980,"column":6},"end":{"line":980,"column":null}},"311":{"start":{"line":981,"column":6},"end":{"line":981,"column":null}},"312":{"start":{"line":984,"column":6},"end":{"line":1003,"column":null}},"313":{"start":{"line":1005,"column":6},"end":{"line":1009,"column":null}},"314":{"start":{"line":1014,"column":20},"end":{"line":1014,"column":null}},"315":{"start":{"line":1016,"column":4},"end":{"line":1171,"column":null}},"316":{"start":{"line":1018,"column":8},"end":{"line":1018,"column":null}},"317":{"start":{"line":1022,"column":32},"end":{"line":1034,"column":null}},"318":{"start":{"line":1037,"column":20},"end":{"line":1037,"column":null}},"319":{"start":{"line":1038,"column":32},"end":{"line":1038,"column":null}},"320":{"start":{"line":1039,"column":31},"end":{"line":1039,"column":null}},"321":{"start":{"line":1040,"column":32},"end":{"line":1040,"column":null}},"322":{"start":{"line":1041,"column":32},"end":{"line":1041,"column":null}},"323":{"start":{"line":1042,"column":33},"end":{"line":1042,"column":null}},"324":{"start":{"line":1045,"column":25},"end":{"line":1045,"column":null}},"325":{"start":{"line":1046,"column":29},"end":{"line":1046,"column":null}},"326":{"start":{"line":1048,"column":8},"end":{"line":1048,"column":null}},"327":{"start":{"line":1049,"column":30},"end":{"line":1049,"column":null}},"328":{"start":{"line":1050,"column":29},"end":{"line":1050,"column":null}},"329":{"start":{"line":1054,"column":8},"end":{"line":1056,"column":null}},"330":{"start":{"line":1056,"column":25},"end":{"line":1056,"column":50}},"331":{"start":{"line":1058,"column":8},"end":{"line":1065,"column":null}},"332":{"start":{"line":1068,"column":25},"end":{"line":1068,"column":null}},"333":{"start":{"line":1069,"column":29},"end":{"line":1069,"column":null}},"334":{"start":{"line":1072,"column":31},"end":{"line":1078,"column":null}},"335":{"start":{"line":1079,"column":25},"end":{"line":1079,"column":null}},"336":{"start":{"line":1080,"column":26},"end":{"line":1080,"column":null}},"337":{"start":{"line":1081,"column":25},"end":{"line":1083,"column":null}},"338":{"start":{"line":1084,"column":22},"end":{"line":1084,"column":null}},"339":{"start":{"line":1087,"column":40},"end":{"line":1087,"column":null}},"340":{"start":{"line":1088,"column":6},"end":{"line":1092,"column":null}},"341":{"start":{"line":1089,"column":8},"end":{"line":1091,"column":null}},"342":{"start":{"line":1094,"column":6},"end":{"line":1098,"column":null}},"343":{"start":{"line":1095,"column":8},"end":{"line":1097,"column":null}},"344":{"start":{"line":1100,"column":6},"end":{"line":1168,"column":null}},"345":{"start":{"line":1170,"column":6},"end":{"line":1170,"column":null}},"346":{"start":{"line":1179,"column":8},"end":{"line":1179,"column":null}},"347":{"start":{"line":1181,"column":4},"end":{"line":1188,"column":null}},"348":{"start":{"line":1182,"column":6},"end":{"line":1187,"column":null}},"349":{"start":{"line":1190,"column":4},"end":{"line":1325,"column":null}},"350":{"start":{"line":1191,"column":21},"end":{"line":1191,"column":null}},"351":{"start":{"line":1193,"column":8},"end":{"line":1195,"column":null}},"352":{"start":{"line":1197,"column":30},"end":{"line":1201,"column":null}},"353":{"start":{"line":1199,"column":27},"end":{"line":1199,"column":53}},"354":{"start":{"line":1200,"column":30},"end":{"line":1200,"column":74}},"355":{"start":{"line":1203,"column":6},"end":{"line":1209,"column":null}},"356":{"start":{"line":1204,"column":8},"end":{"line":1208,"column":null}},"357":{"start":{"line":1211,"column":21},"end":{"line":1211,"column":null}},"358":{"start":{"line":1212,"column":6},"end":{"line":1219,"column":null}},"359":{"start":{"line":1213,"column":8},"end":{"line":1218,"column":null}},"360":{"start":{"line":1221,"column":23},"end":{"line":1227,"column":null}},"361":{"start":{"line":1228,"column":12},"end":{"line":1230,"column":null}},"362":{"start":{"line":1229,"column":22},"end":{"line":1229,"column":42}},"363":{"start":{"line":1232,"column":26},"end":{"line":1247,"column":null}},"364":{"start":{"line":1249,"column":28},"end":{"line":1264,"column":null}},"365":{"start":{"line":1266,"column":29},"end":{"line":1287,"column":null}},"366":{"start":{"line":1289,"column":23},"end":{"line":1297,"column":null}},"367":{"start":{"line":1289,"column":24},"end":{"line":1297,"column":null}},"368":{"start":{"line":1290,"column":35},"end":{"line":1297,"column":10}},"369":{"start":{"line":1299,"column":20},"end":{"line":1299,"column":null}},"370":{"start":{"line":1300,"column":22},"end":{"line":1300,"column":null}},"371":{"start":{"line":1301,"column":23},"end":{"line":1301,"column":null}},"372":{"start":{"line":1303,"column":22},"end":{"line":1303,"column":null}},"373":{"start":{"line":1305,"column":6},"end":{"line":1322,"column":null}},"374":{"start":{"line":1324,"column":6},"end":{"line":1324,"column":null}},"375":{"start":{"line":1329,"column":69},"end":{"line":1329,"column":null}},"376":{"start":{"line":1331,"column":4},"end":{"line":1337,"column":null}},"377":{"start":{"line":1332,"column":6},"end":{"line":1336,"column":null}},"378":{"start":{"line":1339,"column":4},"end":{"line":1357,"column":null}},"379":{"start":{"line":1340,"column":39},"end":{"line":1340,"column":null}},"380":{"start":{"line":1341,"column":6},"end":{"line":1350,"column":null}},"381":{"start":{"line":1352,"column":6},"end":{"line":1356,"column":null}},"382":{"start":{"line":1361,"column":73},"end":{"line":1361,"column":null}},"383":{"start":{"line":1363,"column":4},"end":{"line":1389,"column":null}},"384":{"start":{"line":1364,"column":6},"end":{"line":1364,"column":null}},"385":{"start":{"line":1365,"column":28},"end":{"line":1365,"column":null}},"386":{"start":{"line":1366,"column":22},"end":{"line":1371,"column":null}},"387":{"start":{"line":1373,"column":6},"end":{"line":1386,"column":null}},"388":{"start":{"line":1378,"column":42},"end":{"line":1383,"column":12}},"389":{"start":{"line":1388,"column":6},"end":{"line":1388,"column":null}},"390":{"start":{"line":1398,"column":8},"end":{"line":1398,"column":null}},"391":{"start":{"line":1400,"column":4},"end":{"line":1431,"column":null}},"392":{"start":{"line":1401,"column":6},"end":{"line":1401,"column":null}},"393":{"start":{"line":1402,"column":28},"end":{"line":1402,"column":null}},"394":{"start":{"line":1403,"column":22},"end":{"line":1408,"column":null}},"395":{"start":{"line":1409,"column":23},"end":{"line":1409,"column":null}},"396":{"start":{"line":1411,"column":6},"end":{"line":1424,"column":null}},"397":{"start":{"line":1416,"column":43},"end":{"line":1421,"column":12}},"398":{"start":{"line":1426,"column":6},"end":{"line":1430,"column":null}},"399":{"start":{"line":1435,"column":53},"end":{"line":1435,"column":null}},"400":{"start":{"line":1437,"column":4},"end":{"line":1469,"column":null}},"401":{"start":{"line":1438,"column":6},"end":{"line":1438,"column":null}},"402":{"start":{"line":1439,"column":28},"end":{"line":1439,"column":null}},"403":{"start":{"line":1440,"column":25},"end":{"line":1442,"column":null}},"404":{"start":{"line":1441,"column":26},"end":{"line":1441,"column":76}},"405":{"start":{"line":1444,"column":49},"end":{"line":1444,"column":null}},"406":{"start":{"line":1445,"column":6},"end":{"line":1452,"column":null}},"407":{"start":{"line":1446,"column":21},"end":{"line":1446,"column":null}},"408":{"start":{"line":1447,"column":20},"end":{"line":1447,"column":null}},"409":{"start":{"line":1448,"column":8},"end":{"line":1450,"column":null}},"410":{"start":{"line":1449,"column":10},"end":{"line":1449,"column":null}},"411":{"start":{"line":1451,"column":8},"end":{"line":1451,"column":null}},"412":{"start":{"line":1454,"column":26},"end":{"line":1461,"column":null}},"413":{"start":{"line":1455,"column":38},"end":{"line":1459,"column":10}},"414":{"start":{"line":1460,"column":24},"end":{"line":1460,"column":39}},"415":{"start":{"line":1463,"column":6},"end":{"line":1466,"column":null}},"416":{"start":{"line":1468,"column":6},"end":{"line":1468,"column":null}},"417":{"start":{"line":1473,"column":60},"end":{"line":1473,"column":null}},"418":{"start":{"line":1475,"column":4},"end":{"line":1512,"column":null}},"419":{"start":{"line":1476,"column":19},"end":{"line":1476,"column":null}},"420":{"start":{"line":1477,"column":20},"end":{"line":1477,"column":null}},"421":{"start":{"line":1479,"column":6},"end":{"line":1485,"column":null}},"422":{"start":{"line":1480,"column":8},"end":{"line":1484,"column":null}},"423":{"start":{"line":1487,"column":24},"end":{"line":1487,"column":null}},"424":{"start":{"line":1488,"column":25},"end":{"line":1488,"column":null}},"425":{"start":{"line":1489,"column":23},"end":{"line":1489,"column":null}},"426":{"start":{"line":1490,"column":24},"end":{"line":1490,"column":null}},"427":{"start":{"line":1491,"column":25},"end":{"line":1491,"column":null}},"428":{"start":{"line":1491,"column":55},"end":{"line":1491,"column":73}},"429":{"start":{"line":1493,"column":26},"end":{"line":1496,"column":null}},"430":{"start":{"line":1495,"column":10},"end":{"line":1495,"column":null}},"431":{"start":{"line":1498,"column":6},"end":{"line":1509,"column":null}},"432":{"start":{"line":1505,"column":54},"end":{"line":1505,"column":73}},"433":{"start":{"line":1506,"column":56},"end":{"line":1506,"column":74}},"434":{"start":{"line":1511,"column":6},"end":{"line":1511,"column":null}},"435":{"start":{"line":1516,"column":58},"end":{"line":1516,"column":null}},"436":{"start":{"line":1518,"column":4},"end":{"line":1555,"column":null}},"437":{"start":{"line":1519,"column":23},"end":{"line":1519,"column":null}},"438":{"start":{"line":1521,"column":8},"end":{"line":1526,"column":null}},"439":{"start":{"line":1528,"column":6},"end":{"line":1534,"column":null}},"440":{"start":{"line":1529,"column":8},"end":{"line":1533,"column":null}},"441":{"start":{"line":1536,"column":24},"end":{"line":1540,"column":null}},"442":{"start":{"line":1541,"column":24},"end":{"line":1541,"column":null}},"443":{"start":{"line":1543,"column":6},"end":{"line":1552,"column":null}},"444":{"start":{"line":1554,"column":6},"end":{"line":1554,"column":null}},"445":{"start":{"line":1574,"column":8},"end":{"line":1574,"column":null}},"446":{"start":{"line":1576,"column":4},"end":{"line":1583,"column":null}},"447":{"start":{"line":1577,"column":6},"end":{"line":1582,"column":null}},"448":{"start":{"line":1585,"column":27},"end":{"line":1585,"column":null}},"449":{"start":{"line":1586,"column":31},"end":{"line":1588,"column":null}},"450":{"start":{"line":1587,"column":31},"end":{"line":1587,"column":43}},"451":{"start":{"line":1590,"column":6},"end":{"line":1590,"column":null}},"452":{"start":{"line":1591,"column":28},"end":{"line":1596,"column":null}},"453":{"start":{"line":1597,"column":4},"end":{"line":1603,"column":null}},"454":{"start":{"line":1598,"column":6},"end":{"line":1602,"column":null}},"455":{"start":{"line":1605,"column":4},"end":{"line":1637,"column":null}},"456":{"start":{"line":1606,"column":31},"end":{"line":1606,"column":null}},"457":{"start":{"line":1607,"column":29},"end":{"line":1607,"column":null}},"458":{"start":{"line":1608,"column":28},"end":{"line":1608,"column":null}},"459":{"start":{"line":1610,"column":24},"end":{"line":1623,"column":null}},"460":{"start":{"line":1625,"column":6},"end":{"line":1634,"column":null}},"461":{"start":{"line":1636,"column":6},"end":{"line":1636,"column":null}},"462":{"start":{"line":1650,"column":8},"end":{"line":1650,"column":null}},"463":{"start":{"line":1652,"column":4},"end":{"line":1658,"column":null}},"464":{"start":{"line":1653,"column":6},"end":{"line":1657,"column":null}},"465":{"start":{"line":1660,"column":4},"end":{"line":1699,"column":null}},"466":{"start":{"line":1661,"column":22},"end":{"line":1661,"column":null}},"467":{"start":{"line":1662,"column":28},"end":{"line":1662,"column":null}},"468":{"start":{"line":1663,"column":31},"end":{"line":1665,"column":null}},"469":{"start":{"line":1664,"column":33},"end":{"line":1664,"column":45}},"470":{"start":{"line":1666,"column":35},"end":{"line":1669,"column":null}},"471":{"start":{"line":1670,"column":29},"end":{"line":1672,"column":null}},"472":{"start":{"line":1673,"column":23},"end":{"line":1684,"column":null}},"473":{"start":{"line":1679,"column":32},"end":{"line":1679,"column":73}},"474":{"start":{"line":1686,"column":6},"end":{"line":1696,"column":null}},"475":{"start":{"line":1698,"column":6},"end":{"line":1698,"column":null}},"476":{"start":{"line":1710,"column":8},"end":{"line":1710,"column":null}},"477":{"start":{"line":1712,"column":4},"end":{"line":1718,"column":null}},"478":{"start":{"line":1713,"column":6},"end":{"line":1717,"column":null}},"479":{"start":{"line":1720,"column":4},"end":{"line":1745,"column":null}},"480":{"start":{"line":1721,"column":28},"end":{"line":1721,"column":null}},"481":{"start":{"line":1722,"column":24},"end":{"line":1731,"column":null}},"482":{"start":{"line":1728,"column":40},"end":{"line":1728,"column":52}},"483":{"start":{"line":1733,"column":6},"end":{"line":1742,"column":null}},"484":{"start":{"line":1744,"column":6},"end":{"line":1744,"column":null}},"485":{"start":{"line":1749,"column":65},"end":{"line":1749,"column":null}},"486":{"start":{"line":1751,"column":4},"end":{"line":1767,"column":null}},"487":{"start":{"line":1752,"column":28},"end":{"line":1752,"column":null}},"488":{"start":{"line":1753,"column":21},"end":{"line":1758,"column":null}},"489":{"start":{"line":1760,"column":6},"end":{"line":1764,"column":null}},"490":{"start":{"line":1766,"column":6},"end":{"line":1766,"column":null}},"491":{"start":{"line":1783,"column":8},"end":{"line":1783,"column":null}},"492":{"start":{"line":1785,"column":4},"end":{"line":1791,"column":null}},"493":{"start":{"line":1786,"column":6},"end":{"line":1790,"column":null}},"494":{"start":{"line":1793,"column":4},"end":{"line":1820,"column":null}},"495":{"start":{"line":1794,"column":31},"end":{"line":1794,"column":null}},"496":{"start":{"line":1795,"column":29},"end":{"line":1795,"column":null}},"497":{"start":{"line":1796,"column":28},"end":{"line":1796,"column":null}},"498":{"start":{"line":1798,"column":21},"end":{"line":1806,"column":null}},"499":{"start":{"line":1808,"column":6},"end":{"line":1817,"column":null}},"500":{"start":{"line":1819,"column":6},"end":{"line":1819,"column":null}},"501":{"start":{"line":1824,"column":54},"end":{"line":1824,"column":null}},"502":{"start":{"line":1826,"column":4},"end":{"line":1832,"column":null}},"503":{"start":{"line":1827,"column":6},"end":{"line":1831,"column":null}},"504":{"start":{"line":1834,"column":4},"end":{"line":1848,"column":null}},"505":{"start":{"line":1835,"column":6},"end":{"line":1835,"column":null}},"506":{"start":{"line":1837,"column":6},"end":{"line":1845,"column":null}},"507":{"start":{"line":1847,"column":6},"end":{"line":1847,"column":null}},"508":{"start":{"line":1852,"column":45},"end":{"line":1852,"column":null}},"509":{"start":{"line":1854,"column":4},"end":{"line":1860,"column":null}},"510":{"start":{"line":1855,"column":6},"end":{"line":1859,"column":null}},"511":{"start":{"line":1862,"column":4},"end":{"line":1876,"column":null}},"512":{"start":{"line":1863,"column":28},"end":{"line":1863,"column":null}},"513":{"start":{"line":1864,"column":21},"end":{"line":1864,"column":null}},"514":{"start":{"line":1866,"column":6},"end":{"line":1873,"column":null}},"515":{"start":{"line":1875,"column":6},"end":{"line":1875,"column":null}},"516":{"start":{"line":1880,"column":36},"end":{"line":1880,"column":null}},"517":{"start":{"line":1882,"column":4},"end":{"line":1900,"column":null}},"518":{"start":{"line":1883,"column":28},"end":{"line":1883,"column":null}},"519":{"start":{"line":1884,"column":23},"end":{"line":1884,"column":null}},"520":{"start":{"line":1886,"column":6},"end":{"line":1893,"column":null}},"521":{"start":{"line":1895,"column":6},"end":{"line":1899,"column":null}},"522":{"start":{"line":1912,"column":8},"end":{"line":1912,"column":null}},"523":{"start":{"line":1914,"column":4},"end":{"line":1920,"column":null}},"524":{"start":{"line":1915,"column":6},"end":{"line":1919,"column":null}},"525":{"start":{"line":1922,"column":4},"end":{"line":2019,"column":null}},"526":{"start":{"line":1923,"column":29},"end":{"line":1923,"column":null}},"527":{"start":{"line":1924,"column":43},"end":{"line":1924,"column":null}},"528":{"start":{"line":1926,"column":22},"end":{"line":1926,"column":null}},"529":{"start":{"line":1927,"column":30},"end":{"line":1930,"column":null}},"530":{"start":{"line":1931,"column":25},"end":{"line":1938,"column":null}},"531":{"start":{"line":1940,"column":29},"end":{"line":1944,"column":null}},"532":{"start":{"line":1941,"column":8},"end":{"line":1943,"column":null}},"533":{"start":{"line":1945,"column":26},"end":{"line":1948,"column":null}},"534":{"start":{"line":1950,"column":26},"end":{"line":1950,"column":null}},"535":{"start":{"line":1950,"column":52},"end":{"line":1950,"column":63}},"536":{"start":{"line":1951,"column":29},"end":{"line":1955,"column":null}},"537":{"start":{"line":1956,"column":24},"end":{"line":1958,"column":null}},"538":{"start":{"line":1959,"column":24},"end":{"line":1961,"column":null}},"539":{"start":{"line":1962,"column":23},"end":{"line":1964,"column":null}},"540":{"start":{"line":1967,"column":8},"end":{"line":1969,"column":null}},"541":{"start":{"line":1970,"column":22},"end":{"line":1970,"column":null}},"542":{"start":{"line":1972,"column":44},"end":{"line":2008,"column":null}},"543":{"start":{"line":1979,"column":52},"end":{"line":1990,"column":9}},"544":{"start":{"line":1980,"column":56},"end":{"line":1984,"column":12}},"545":{"start":{"line":1985,"column":54},"end":{"line":1989,"column":12}},"546":{"start":{"line":2005,"column":41},"end":{"line":2005,"column":66}},"547":{"start":{"line":2011,"column":8},"end":{"line":2011,"column":null}},"548":{"start":{"line":2012,"column":12},"end":{"line":2012,"column":null}},"549":{"start":{"line":2013,"column":6},"end":{"line":2013,"column":null}},"550":{"start":{"line":2014,"column":6},"end":{"line":2014,"column":null}},"551":{"start":{"line":2016,"column":6},"end":{"line":2016,"column":null}},"552":{"start":{"line":2018,"column":6},"end":{"line":2018,"column":null}},"553":{"start":{"line":2030,"column":8},"end":{"line":2030,"column":null}},"554":{"start":{"line":2032,"column":4},"end":{"line":2038,"column":null}},"555":{"start":{"line":2033,"column":6},"end":{"line":2037,"column":null}},"556":{"start":{"line":2040,"column":4},"end":{"line":2129,"column":null}},"557":{"start":{"line":2041,"column":43},"end":{"line":2041,"column":null}},"558":{"start":{"line":2042,"column":23},"end":{"line":2042,"column":null}},"559":{"start":{"line":2043,"column":6},"end":{"line":2050,"column":null}},"560":{"start":{"line":2044,"column":8},"end":{"line":2049,"column":null}},"561":{"start":{"line":2052,"column":53},"end":{"line":2052,"column":null}},"562":{"start":{"line":2053,"column":27},"end":{"line":2055,"column":null}},"563":{"start":{"line":2058,"column":8},"end":{"line":2063,"column":null}},"564":{"start":{"line":2065,"column":37},"end":{"line":2069,"column":null}},"565":{"start":{"line":2070,"column":19},"end":{"line":2070,"column":null}},"566":{"start":{"line":2073,"column":8},"end":{"line":2084,"column":null}},"567":{"start":{"line":2076,"column":31},"end":{"line":2076,"column":51}},"568":{"start":{"line":2078,"column":29},"end":{"line":2083,"column":16}},"569":{"start":{"line":2087,"column":8},"end":{"line":2098,"column":null}},"570":{"start":{"line":2090,"column":31},"end":{"line":2090,"column":51}},"571":{"start":{"line":2092,"column":29},"end":{"line":2097,"column":16}},"572":{"start":{"line":2100,"column":31},"end":{"line":2100,"column":null}},"573":{"start":{"line":2101,"column":24},"end":{"line":2103,"column":null}},"574":{"start":{"line":2104,"column":24},"end":{"line":2106,"column":null}},"575":{"start":{"line":2108,"column":23},"end":{"line":2122,"column":null}},"576":{"start":{"line":2124,"column":22},"end":{"line":2124,"column":null}},"577":{"start":{"line":2126,"column":6},"end":{"line":2126,"column":null}},"578":{"start":{"line":2128,"column":6},"end":{"line":2128,"column":null}},"579":{"start":{"line":2133,"column":19},"end":{"line":2136,"column":null}},"580":{"start":{"line":2136,"column":25},"end":{"line":2136,"column":42}},"581":{"start":{"line":2138,"column":23},"end":{"line":2142,"column":null}},"582":{"start":{"line":2144,"column":19},"end":{"line":2154,"column":null}},"583":{"start":{"line":2147,"column":10},"end":{"line":2147,"column":null}},"584":{"start":{"line":2148,"column":22},"end":{"line":2151,"column":null}},"585":{"start":{"line":2149,"column":26},"end":{"line":2149,"column":null}},"586":{"start":{"line":2152,"column":8},"end":{"line":2152,"column":null}},"587":{"start":{"line":2154,"column":22},"end":{"line":2154,"column":39}},"588":{"start":{"line":2156,"column":21},"end":{"line":2156,"column":null}},"589":{"start":{"line":2156,"column":45},"end":{"line":2156,"column":59}},"590":{"start":{"line":2157,"column":4},"end":{"line":2159,"column":null}},"591":{"start":{"line":2158,"column":6},"end":{"line":2158,"column":null}},"592":{"start":{"line":2158,"column":36},"end":{"line":2158,"column":47}},"593":{"start":{"line":2161,"column":4},"end":{"line":2161,"column":null}},"594":{"start":{"line":2161,"column":52},"end":{"line":2161,"column":59}},"595":{"start":{"line":2168,"column":4},"end":{"line":2170,"column":null}},"596":{"start":{"line":2169,"column":6},"end":{"line":2169,"column":null}},"597":{"start":{"line":2172,"column":21},"end":{"line":2172,"column":null}},"598":{"start":{"line":2173,"column":30},"end":{"line":2180,"column":null}},"599":{"start":{"line":2182,"column":20},"end":{"line":2182,"column":null}},"600":{"start":{"line":2183,"column":4},"end":{"line":2189,"column":null}},"601":{"start":{"line":2184,"column":6},"end":{"line":2188,"column":null}},"602":{"start":{"line":2185,"column":8},"end":{"line":2187,"column":null}},"603":{"start":{"line":2186,"column":10},"end":{"line":2186,"column":null}},"604":{"start":{"line":2191,"column":4},"end":{"line":2191,"column":null}},"605":{"start":{"line":2198,"column":23},"end":{"line":2198,"column":null}},"606":{"start":{"line":2199,"column":21},"end":{"line":2199,"column":null}},"607":{"start":{"line":2200,"column":26},"end":{"line":2200,"column":null}},"608":{"start":{"line":2202,"column":4},"end":{"line":2239,"column":null}},"609":{"start":{"line":2203,"column":23},"end":{"line":2203,"column":null}},"610":{"start":{"line":2204,"column":6},"end":{"line":2206,"column":null}},"611":{"start":{"line":2205,"column":8},"end":{"line":2205,"column":null}},"612":{"start":{"line":2208,"column":53},"end":{"line":2208,"column":null}},"613":{"start":{"line":2209,"column":27},"end":{"line":2211,"column":null}},"614":{"start":{"line":2213,"column":19},"end":{"line":2213,"column":null}},"615":{"start":{"line":2214,"column":30},"end":{"line":2218,"column":null}},"616":{"start":{"line":2216,"column":25},"end":{"line":2216,"column":45}},"617":{"start":{"line":2218,"column":23},"end":{"line":2218,"column":40}},"618":{"start":{"line":2219,"column":28},"end":{"line":2223,"column":null}},"619":{"start":{"line":2221,"column":25},"end":{"line":2221,"column":45}},"620":{"start":{"line":2223,"column":23},"end":{"line":2223,"column":38}},"621":{"start":{"line":2225,"column":6},"end":{"line":2238,"column":null}},"622":{"start":{"line":2241,"column":4},"end":{"line":2241,"column":null}},"623":{"start":{"line":2250,"column":17},"end":{"line":2250,"column":null}},"624":{"start":{"line":2251,"column":4},"end":{"line":2253,"column":null}},"625":{"start":{"line":2252,"column":6},"end":{"line":2252,"column":null}},"626":{"start":{"line":2255,"column":19},"end":{"line":2257,"column":null}},"627":{"start":{"line":2258,"column":4},"end":{"line":2268,"column":null}},"628":{"start":{"line":2259,"column":22},"end":{"line":2261,"column":null}},"629":{"start":{"line":2261,"column":25},"end":{"line":2261,"column":48}},"630":{"start":{"line":2262,"column":23},"end":{"line":2264,"column":null}},"631":{"start":{"line":2263,"column":22},"end":{"line":2263,"column":58}},"632":{"start":{"line":2264,"column":29},"end":{"line":2264,"column":55}},"633":{"start":{"line":2265,"column":6},"end":{"line":2267,"column":null}},"634":{"start":{"line":2270,"column":4},"end":{"line":2272,"column":null}},"635":{"start":{"line":2271,"column":6},"end":{"line":2271,"column":null}},"636":{"start":{"line":2274,"column":22},"end":{"line":2276,"column":null}},"637":{"start":{"line":2277,"column":20},"end":{"line":2277,"column":null}},"638":{"start":{"line":2279,"column":4},"end":{"line":2284,"column":null}},"639":{"start":{"line":2293,"column":4},"end":{"line":2306,"column":null}},"640":{"start":{"line":2294,"column":6},"end":{"line":2296,"column":null}},"641":{"start":{"line":2295,"column":8},"end":{"line":2295,"column":null}},"642":{"start":{"line":2297,"column":20},"end":{"line":2297,"column":null}},"643":{"start":{"line":2298,"column":22},"end":{"line":2300,"column":null}},"644":{"start":{"line":2301,"column":6},"end":{"line":2303,"column":null}},"645":{"start":{"line":2305,"column":6},"end":{"line":2305,"column":null}},"646":{"start":{"line":2314,"column":4},"end":{"line":2316,"column":null}},"647":{"start":{"line":2315,"column":6},"end":{"line":2315,"column":null}},"648":{"start":{"line":2318,"column":21},"end":{"line":2329,"column":null}},"649":{"start":{"line":2331,"column":4},"end":{"line":2337,"column":null}},"650":{"start":{"line":2331,"column":47},"end":{"line":2337,"column":6}},"651":{"start":{"line":2344,"column":4},"end":{"line":2346,"column":null}},"652":{"start":{"line":2345,"column":6},"end":{"line":2345,"column":null}},"653":{"start":{"line":2348,"column":19},"end":{"line":2355,"column":null}},"654":{"start":{"line":2357,"column":4},"end":{"line":2361,"column":null}},"655":{"start":{"line":2357,"column":45},"end":{"line":2361,"column":6}},"656":{"start":{"line":2368,"column":4},"end":{"line":2370,"column":null}},"657":{"start":{"line":2369,"column":6},"end":{"line":2369,"column":null}},"658":{"start":{"line":2372,"column":19},"end":{"line":2379,"column":null}},"659":{"start":{"line":2381,"column":4},"end":{"line":2385,"column":null}},"660":{"start":{"line":2381,"column":45},"end":{"line":2385,"column":6}},"661":{"start":{"line":2393,"column":33},"end":{"line":2393,"column":null}},"662":{"start":{"line":2394,"column":44},"end":{"line":2394,"column":null}},"663":{"start":{"line":2396,"column":4},"end":{"line":2402,"column":null}},"664":{"start":{"line":2397,"column":6},"end":{"line":2397,"column":null}},"665":{"start":{"line":2398,"column":6},"end":{"line":2398,"column":null}},"666":{"start":{"line":2400,"column":6},"end":{"line":2400,"column":null}},"667":{"start":{"line":2401,"column":6},"end":{"line":2401,"column":null}},"668":{"start":{"line":2404,"column":19},"end":{"line":2411,"column":null}},"669":{"start":{"line":2413,"column":4},"end":{"line":2418,"column":null}},"670":{"start":{"line":2413,"column":45},"end":{"line":2418,"column":6}},"671":{"start":{"line":2425,"column":4},"end":{"line":2427,"column":null}},"672":{"start":{"line":2426,"column":6},"end":{"line":2426,"column":null}},"673":{"start":{"line":2429,"column":22},"end":{"line":2455,"column":null}},"674":{"start":{"line":2430,"column":6},"end":{"line":2433,"column":null}},"675":{"start":{"line":2431,"column":8},"end":{"line":2431,"column":null}},"676":{"start":{"line":2432,"column":8},"end":{"line":2432,"column":null}},"677":{"start":{"line":2434,"column":6},"end":{"line":2437,"column":null}},"678":{"start":{"line":2435,"column":8},"end":{"line":2435,"column":null}},"679":{"start":{"line":2436,"column":8},"end":{"line":2436,"column":null}},"680":{"start":{"line":2438,"column":6},"end":{"line":2441,"column":null}},"681":{"start":{"line":2439,"column":8},"end":{"line":2439,"column":null}},"682":{"start":{"line":2440,"column":8},"end":{"line":2440,"column":null}},"683":{"start":{"line":2442,"column":6},"end":{"line":2445,"column":null}},"684":{"start":{"line":2443,"column":8},"end":{"line":2443,"column":null}},"685":{"start":{"line":2444,"column":8},"end":{"line":2444,"column":null}},"686":{"start":{"line":2446,"column":6},"end":{"line":2453,"column":null}},"687":{"start":{"line":2447,"column":8},"end":{"line":2452,"column":null}},"688":{"start":{"line":2448,"column":10},"end":{"line":2451,"column":null}},"689":{"start":{"line":2449,"column":12},"end":{"line":2449,"column":null}},"690":{"start":{"line":2450,"column":12},"end":{"line":2450,"column":null}},"691":{"start":{"line":2454,"column":6},"end":{"line":2454,"column":null}},"692":{"start":{"line":2457,"column":8},"end":{"line":2457,"column":null}},"693":{"start":{"line":2458,"column":16},"end":{"line":2458,"column":null}},"694":{"start":{"line":2459,"column":4},"end":{"line":2466,"column":null}},"695":{"start":{"line":2460,"column":22},"end":{"line":2460,"column":null}},"696":{"start":{"line":2461,"column":6},"end":{"line":2463,"column":null}},"697":{"start":{"line":2462,"column":8},"end":{"line":2462,"column":null}},"698":{"start":{"line":2464,"column":6},"end":{"line":2464,"column":null}},"699":{"start":{"line":2465,"column":6},"end":{"line":2465,"column":null}},"700":{"start":{"line":2479,"column":27},"end":{"line":2479,"column":null}},"701":{"start":{"line":2480,"column":29},"end":{"line":2480,"column":null}},"702":{"start":{"line":2482,"column":4},"end":{"line":2487,"column":null}},"703":{"start":{"line":2483,"column":20},"end":{"line":2483,"column":null}},"704":{"start":{"line":2484,"column":6},"end":{"line":2486,"column":null}},"705":{"start":{"line":2485,"column":8},"end":{"line":2485,"column":null}},"706":{"start":{"line":2489,"column":4},"end":{"line":2517,"column":null}},"707":{"start":{"line":2490,"column":23},"end":{"line":2501,"column":null}},"708":{"start":{"line":2493,"column":32},"end":{"line":2495,"column":null}},"709":{"start":{"line":2496,"column":10},"end":{"line":2499,"column":null}},"710":{"start":{"line":2503,"column":6},"end":{"line":2516,"column":null}},"711":{"start":{"line":2504,"column":25},"end":{"line":2507,"column":null}},"712":{"start":{"line":2506,"column":27},"end":{"line":2506,"column":50}},"713":{"start":{"line":2507,"column":24},"end":{"line":2507,"column":30}},"714":{"start":{"line":2509,"column":10},"end":{"line":2509,"column":null}},"715":{"start":{"line":2510,"column":22},"end":{"line":2512,"column":null}},"716":{"start":{"line":2511,"column":23},"end":{"line":2511,"column":53}},"717":{"start":{"line":2512,"column":26},"end":{"line":2512,"column":63}},"718":{"start":{"line":2513,"column":8},"end":{"line":2515,"column":null}},"719":{"start":{"line":2514,"column":10},"end":{"line":2514,"column":null}},"720":{"start":{"line":2519,"column":4},"end":{"line":2533,"column":null}},"721":{"start":{"line":2520,"column":25},"end":{"line":2520,"column":null}},"722":{"start":{"line":2521,"column":21},"end":{"line":2528,"column":null}},"723":{"start":{"line":2526,"column":21},"end":{"line":2526,"column":null}},"724":{"start":{"line":2527,"column":8},"end":{"line":2527,"column":null}},"725":{"start":{"line":2530,"column":6},"end":{"line":2532,"column":null}},"726":{"start":{"line":2531,"column":8},"end":{"line":2531,"column":null}},"727":{"start":{"line":2535,"column":4},"end":{"line":2540,"column":null}},"728":{"start":{"line":2536,"column":25},"end":{"line":2536,"column":null}},"729":{"start":{"line":2537,"column":6},"end":{"line":2539,"column":null}},"730":{"start":{"line":2538,"column":8},"end":{"line":2538,"column":null}},"731":{"start":{"line":2542,"column":4},"end":{"line":2558,"column":null}},"732":{"start":{"line":2543,"column":23},"end":{"line":2554,"column":null}},"733":{"start":{"line":2546,"column":32},"end":{"line":2548,"column":null}},"734":{"start":{"line":2549,"column":10},"end":{"line":2552,"column":null}},"735":{"start":{"line":2555,"column":6},"end":{"line":2557,"column":null}},"736":{"start":{"line":2556,"column":8},"end":{"line":2556,"column":null}},"737":{"start":{"line":2560,"column":4},"end":{"line":2560,"column":null}},"738":{"start":{"line":2568,"column":4},"end":{"line":2570,"column":null}},"739":{"start":{"line":2569,"column":6},"end":{"line":2569,"column":null}},"740":{"start":{"line":2571,"column":4},"end":{"line":2571,"column":null}},"741":{"start":{"line":2579,"column":4},"end":{"line":2581,"column":null}},"742":{"start":{"line":2580,"column":6},"end":{"line":2580,"column":null}},"743":{"start":{"line":2582,"column":18},"end":{"line":2582,"column":null}},"744":{"start":{"line":2583,"column":4},"end":{"line":2585,"column":null}},"745":{"start":{"line":2598,"column":8},"end":{"line":2598,"column":null}},"746":{"start":{"line":2600,"column":4},"end":{"line":2607,"column":null}},"747":{"start":{"line":2601,"column":6},"end":{"line":2606,"column":null}},"748":{"start":{"line":2609,"column":25},"end":{"line":2609,"column":null}},"749":{"start":{"line":2610,"column":4},"end":{"line":2617,"column":null}},"750":{"start":{"line":2611,"column":6},"end":{"line":2616,"column":null}},"751":{"start":{"line":2619,"column":76},"end":{"line":2619,"column":null}},"752":{"start":{"line":2621,"column":4},"end":{"line":2757,"column":null}},"753":{"start":{"line":2623,"column":27},"end":{"line":2623,"column":null}},"754":{"start":{"line":2624,"column":6},"end":{"line":2624,"column":null}},"755":{"start":{"line":2624,"column":21},"end":{"line":2624,"column":null}},"756":{"start":{"line":2625,"column":6},"end":{"line":2625,"column":null}},"757":{"start":{"line":2625,"column":21},"end":{"line":2625,"column":null}},"758":{"start":{"line":2628,"column":6},"end":{"line":2662,"column":null}},"759":{"start":{"line":2629,"column":8},"end":{"line":2629,"column":null}},"760":{"start":{"line":2630,"column":24},"end":{"line":2630,"column":null}},"761":{"start":{"line":2631,"column":8},"end":{"line":2643,"column":null}},"762":{"start":{"line":2632,"column":10},"end":{"line":2636,"column":null}},"763":{"start":{"line":2637,"column":10},"end":{"line":2642,"column":null}},"764":{"start":{"line":2644,"column":20},"end":{"line":2644,"column":null}},"765":{"start":{"line":2645,"column":8},"end":{"line":2649,"column":null}},"766":{"start":{"line":2651,"column":8},"end":{"line":2655,"column":null}},"767":{"start":{"line":2656,"column":8},"end":{"line":2661,"column":null}},"768":{"start":{"line":2665,"column":31},"end":{"line":2670,"column":null}},"769":{"start":{"line":2671,"column":6},"end":{"line":2671,"column":null}},"770":{"start":{"line":2671,"column":21},"end":{"line":2671,"column":null}},"771":{"start":{"line":2672,"column":6},"end":{"line":2672,"column":null}},"772":{"start":{"line":2672,"column":21},"end":{"line":2672,"column":null}},"773":{"start":{"line":2674,"column":6},"end":{"line":2696,"column":null}},"774":{"start":{"line":2675,"column":30},"end":{"line":2675,"column":null}},"775":{"start":{"line":2676,"column":28},"end":{"line":2676,"column":null}},"776":{"start":{"line":2677,"column":8},"end":{"line":2689,"column":null}},"777":{"start":{"line":2678,"column":10},"end":{"line":2682,"column":null}},"778":{"start":{"line":2684,"column":10},"end":{"line":2688,"column":null}},"779":{"start":{"line":2691,"column":8},"end":{"line":2695,"column":null}},"780":{"start":{"line":2699,"column":26},"end":{"line":2703,"column":null}},"781":{"start":{"line":2704,"column":6},"end":{"line":2730,"column":null}},"782":{"start":{"line":2705,"column":8},"end":{"line":2723,"column":null}},"783":{"start":{"line":2706,"column":10},"end":{"line":2711,"column":null}},"784":{"start":{"line":2712,"column":10},"end":{"line":2716,"column":null}},"785":{"start":{"line":2718,"column":10},"end":{"line":2722,"column":null}},"786":{"start":{"line":2725,"column":8},"end":{"line":2729,"column":null}},"787":{"start":{"line":2732,"column":18},"end":{"line":2736,"column":null}},"788":{"start":{"line":2738,"column":6},"end":{"line":2750,"column":null}},"789":{"start":{"line":2752,"column":6},"end":{"line":2756,"column":null}},"790":{"start":{"line":2771,"column":8},"end":{"line":2771,"column":null}},"791":{"start":{"line":2775,"column":4},"end":{"line":2780,"column":null}},"792":{"start":{"line":2776,"column":6},"end":{"line":2776,"column":null}},"793":{"start":{"line":2778,"column":18},"end":{"line":2778,"column":null}},"794":{"start":{"line":2779,"column":6},"end":{"line":2779,"column":null}},"795":{"start":{"line":2782,"column":4},"end":{"line":2789,"column":null}},"796":{"start":{"line":2783,"column":6},"end":{"line":2788,"column":null}},"797":{"start":{"line":2791,"column":21},"end":{"line":2795,"column":null}},"798":{"start":{"line":2796,"column":4},"end":{"line":2807,"column":null}},"799":{"start":{"line":2797,"column":6},"end":{"line":2806,"column":null}},"800":{"start":{"line":2809,"column":4},"end":{"line":3013,"column":null}},"801":{"start":{"line":2811,"column":23},"end":{"line":2811,"column":null}},"802":{"start":{"line":2812,"column":22},"end":{"line":2812,"column":null}},"803":{"start":{"line":2813,"column":27},"end":{"line":2815,"column":null}},"804":{"start":{"line":2817,"column":19},"end":{"line":2817,"column":null}},"805":{"start":{"line":2818,"column":26},"end":{"line":2818,"column":null}},"806":{"start":{"line":2819,"column":43},"end":{"line":2822,"column":null}},"807":{"start":{"line":2825,"column":30},"end":{"line":2825,"column":null}},"808":{"start":{"line":2827,"column":8},"end":{"line":2828,"column":null}},"809":{"start":{"line":2830,"column":8},"end":{"line":2830,"column":null}},"810":{"start":{"line":2832,"column":8},"end":{"line":2834,"column":null}},"811":{"start":{"line":2835,"column":19},"end":{"line":2835,"column":null}},"812":{"start":{"line":2836,"column":21},"end":{"line":2836,"column":null}},"813":{"start":{"line":2838,"column":8},"end":{"line":2839,"column":null}},"814":{"start":{"line":2840,"column":22},"end":{"line":2840,"column":null}},"815":{"start":{"line":2841,"column":23},"end":{"line":2841,"column":null}},"816":{"start":{"line":2843,"column":8},"end":{"line":2844,"column":null}},"817":{"start":{"line":2846,"column":6},"end":{"line":2847,"column":null}},"818":{"start":{"line":2846,"column":24},"end":{"line":2846,"column":null}},"819":{"start":{"line":2846,"column":47},"end":{"line":2847,"column":null}},"820":{"start":{"line":2847,"column":23},"end":{"line":2847,"column":null}},"821":{"start":{"line":2848,"column":6},"end":{"line":2848,"column":null}},"822":{"start":{"line":2848,"column":20},"end":{"line":2848,"column":null}},"823":{"start":{"line":2849,"column":6},"end":{"line":2849,"column":null}},"824":{"start":{"line":2849,"column":16},"end":{"line":2849,"column":null}},"825":{"start":{"line":2850,"column":6},"end":{"line":2850,"column":null}},"826":{"start":{"line":2850,"column":18},"end":{"line":2850,"column":null}},"827":{"start":{"line":2851,"column":6},"end":{"line":2851,"column":null}},"828":{"start":{"line":2851,"column":18},"end":{"line":2851,"column":null}},"829":{"start":{"line":2852,"column":6},"end":{"line":2853,"column":null}},"830":{"start":{"line":2852,"column":20},"end":{"line":2852,"column":null}},"831":{"start":{"line":2852,"column":40},"end":{"line":2853,"column":null}},"832":{"start":{"line":2853,"column":24},"end":{"line":2853,"column":null}},"833":{"start":{"line":2854,"column":6},"end":{"line":2854,"column":null}},"834":{"start":{"line":2854,"column":20},"end":{"line":2854,"column":null}},"835":{"start":{"line":2857,"column":22},"end":{"line":2862,"column":null}},"836":{"start":{"line":2860,"column":29},"end":{"line":2860,"column":51}},"837":{"start":{"line":2865,"column":31},"end":{"line":2865,"column":null}},"838":{"start":{"line":2867,"column":8},"end":{"line":2869,"column":null}},"839":{"start":{"line":2868,"column":10},"end":{"line":2868,"column":null}},"840":{"start":{"line":2872,"column":22},"end":{"line":2872,"column":null}},"841":{"start":{"line":2873,"column":30},"end":{"line":2873,"column":null}},"842":{"start":{"line":2874,"column":6},"end":{"line":2884,"column":null}},"843":{"start":{"line":2875,"column":8},"end":{"line":2883,"column":null}},"844":{"start":{"line":2876,"column":10},"end":{"line":2880,"column":null}},"845":{"start":{"line":2878,"column":27},"end":{"line":2878,"column":42}},"846":{"start":{"line":2879,"column":24},"end":{"line":2879,"column":30}},"847":{"start":{"line":2888,"column":8},"end":{"line":2890,"column":null}},"848":{"start":{"line":2893,"column":30},"end":{"line":2893,"column":null}},"849":{"start":{"line":2894,"column":6},"end":{"line":2896,"column":null}},"850":{"start":{"line":2895,"column":8},"end":{"line":2895,"column":null}},"851":{"start":{"line":2898,"column":6},"end":{"line":2898,"column":null}},"852":{"start":{"line":2899,"column":6},"end":{"line":2902,"column":null}},"853":{"start":{"line":2904,"column":6},"end":{"line":2913,"column":null}},"854":{"start":{"line":2905,"column":8},"end":{"line":2905,"column":null}},"855":{"start":{"line":2906,"column":8},"end":{"line":2906,"column":null}},"856":{"start":{"line":2907,"column":8},"end":{"line":2907,"column":null}},"857":{"start":{"line":2908,"column":8},"end":{"line":2912,"column":null}},"858":{"start":{"line":2909,"column":10},"end":{"line":2911,"column":null}},"859":{"start":{"line":2910,"column":57},"end":{"line":2910,"column":77}},"860":{"start":{"line":2914,"column":6},"end":{"line":2916,"column":null}},"861":{"start":{"line":2915,"column":8},"end":{"line":2915,"column":null}},"862":{"start":{"line":2918,"column":6},"end":{"line":2939,"column":null}},"863":{"start":{"line":2919,"column":8},"end":{"line":2929,"column":null}},"864":{"start":{"line":2931,"column":8},"end":{"line":2938,"column":null}},"865":{"start":{"line":2941,"column":6},"end":{"line":2953,"column":null}},"866":{"start":{"line":2955,"column":6},"end":{"line":2964,"column":null}},"867":{"start":{"line":2966,"column":6},"end":{"line":2971,"column":null}},"868":{"start":{"line":2973,"column":22},"end":{"line":2973,"column":null}},"869":{"start":{"line":2975,"column":6},"end":{"line":2986,"column":null}},"870":{"start":{"line":2976,"column":8},"end":{"line":2985,"column":null}},"871":{"start":{"line":2989,"column":24},"end":{"line":2989,"column":null}},"872":{"start":{"line":2990,"column":6},"end":{"line":2992,"column":null}},"873":{"start":{"line":2991,"column":8},"end":{"line":2991,"column":null}},"874":{"start":{"line":2993,"column":6},"end":{"line":2993,"column":null}},"875":{"start":{"line":2995,"column":6},"end":{"line":3006,"column":null}},"876":{"start":{"line":3008,"column":6},"end":{"line":3012,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":39,"column":2},"end":{"line":39,"column":14}},"loc":{"start":{"line":39,"column":36},"end":{"line":46,"column":null}},"line":39},"1":{"name":"(anonymous_1)","decl":{"start":{"line":51,"column":10},"end":{"line":51,"column":37}},"loc":{"start":{"line":51,"column":37},"end":{"line":54,"column":null}},"line":51},"2":{"name":"(anonymous_2)","decl":{"start":{"line":59,"column":10},"end":{"line":59,"column":38}},"loc":{"start":{"line":59,"column":38},"end":{"line":63,"column":null}},"line":59},"3":{"name":"(anonymous_3)","decl":{"start":{"line":68,"column":10},"end":{"line":68,"column":38}},"loc":{"start":{"line":68,"column":38},"end":{"line":72,"column":null}},"line":68},"4":{"name":"(anonymous_4)","decl":{"start":{"line":77,"column":10},"end":{"line":77,"column":38}},"loc":{"start":{"line":77,"column":38},"end":{"line":83,"column":null}},"line":77},"5":{"name":"(anonymous_5)","decl":{"start":{"line":85,"column":8},"end":{"line":85,"column":20}},"loc":{"start":{"line":85,"column":48},"end":{"line":188,"column":null}},"line":85},"6":{"name":"(anonymous_6)","decl":{"start":{"line":190,"column":10},"end":{"line":190,"column":null}},"loc":{"start":{"line":193,"column":32},"end":{"line":221,"column":null}},"line":193},"7":{"name":"(anonymous_7)","decl":{"start":{"line":198,"column":23},"end":{"line":198,"column":24}},"loc":{"start":{"line":198,"column":32},"end":{"line":220,"column":5}},"line":198},"8":{"name":"(anonymous_8)","decl":{"start":{"line":223,"column":16},"end":{"line":223,"column":null}},"loc":{"start":{"line":227,"column":20},"end":{"line":263,"column":null}},"line":227},"9":{"name":"(anonymous_9)","decl":{"start":{"line":231,"column":12},"end":{"line":231,"column":13}},"loc":{"start":{"line":231,"column":23},"end":{"line":231,"column":40}},"line":231},"10":{"name":"(anonymous_10)","decl":{"start":{"line":265,"column":10},"end":{"line":265,"column":27}},"loc":{"start":{"line":265,"column":52},"end":{"line":269,"column":null}},"line":265},"11":{"name":"(anonymous_11)","decl":{"start":{"line":268,"column":24},"end":{"line":268,"column":25}},"loc":{"start":{"line":268,"column":34},"end":{"line":268,"column":52}},"line":268},"12":{"name":"(anonymous_12)","decl":{"start":{"line":271,"column":8},"end":{"line":271,"column":21}},"loc":{"start":{"line":271,"column":49},"end":{"line":320,"column":null}},"line":271},"13":{"name":"(anonymous_13)","decl":{"start":{"line":283,"column":21},"end":{"line":283,"column":22}},"loc":{"start":{"line":283,"column":28},"end":{"line":283,"column":57}},"line":283},"14":{"name":"(anonymous_14)","decl":{"start":{"line":322,"column":8},"end":{"line":322,"column":21}},"loc":{"start":{"line":322,"column":49},"end":{"line":487,"column":null}},"line":322},"15":{"name":"(anonymous_15)","decl":{"start":{"line":353,"column":36},"end":{"line":353,"column":37}},"loc":{"start":{"line":353,"column":46},"end":{"line":363,"column":9}},"line":353},"16":{"name":"(anonymous_16)","decl":{"start":{"line":369,"column":42},"end":{"line":369,"column":43}},"loc":{"start":{"line":369,"column":49},"end":{"line":369,"column":53}},"line":369},"17":{"name":"(anonymous_17)","decl":{"start":{"line":376,"column":20},"end":{"line":376,"column":21}},"loc":{"start":{"line":376,"column":29},"end":{"line":376,"column":51}},"line":376},"18":{"name":"(anonymous_18)","decl":{"start":{"line":390,"column":22},"end":{"line":390,"column":23}},"loc":{"start":{"line":390,"column":31},"end":{"line":390,"column":56}},"line":390},"19":{"name":"(anonymous_19)","decl":{"start":{"line":412,"column":34},"end":{"line":412,"column":35}},"loc":{"start":{"line":412,"column":63},"end":{"line":423,"column":null}},"line":412},"20":{"name":"(anonymous_20)","decl":{"start":{"line":425,"column":22},"end":{"line":425,"column":23}},"loc":{"start":{"line":425,"column":48},"end":{"line":453,"column":null}},"line":425},"21":{"name":"(anonymous_21)","decl":{"start":{"line":461,"column":50},"end":{"line":461,"column":51}},"loc":{"start":{"line":461,"column":62},"end":{"line":467,"column":10}},"line":461},"22":{"name":"(anonymous_22)","decl":{"start":{"line":462,"column":27},"end":{"line":462,"column":28}},"loc":{"start":{"line":462,"column":35},"end":{"line":465,"column":11}},"line":462},"23":{"name":"(anonymous_23)","decl":{"start":{"line":495,"column":8},"end":{"line":495,"column":23}},"loc":{"start":{"line":495,"column":51},"end":{"line":522,"column":null}},"line":495},"24":{"name":"(anonymous_24)","decl":{"start":{"line":524,"column":8},"end":{"line":524,"column":20}},"loc":{"start":{"line":524,"column":48},"end":{"line":628,"column":null}},"line":524},"25":{"name":"(anonymous_25)","decl":{"start":{"line":630,"column":8},"end":{"line":630,"column":23}},"loc":{"start":{"line":630,"column":51},"end":{"line":705,"column":null}},"line":630},"26":{"name":"(anonymous_26)","decl":{"start":{"line":650,"column":52},"end":{"line":650,"column":53}},"loc":{"start":{"line":650,"column":66},"end":{"line":654,"column":14}},"line":650},"27":{"name":"(anonymous_27)","decl":{"start":{"line":665,"column":41},"end":{"line":665,"column":42}},"loc":{"start":{"line":665,"column":54},"end":{"line":673,"column":9}},"line":665},"28":{"name":"(anonymous_28)","decl":{"start":{"line":687,"column":19},"end":{"line":687,"column":20}},"loc":{"start":{"line":687,"column":32},"end":{"line":687,"column":42}},"line":687},"29":{"name":"(anonymous_29)","decl":{"start":{"line":707,"column":8},"end":{"line":707,"column":24}},"loc":{"start":{"line":707,"column":52},"end":{"line":729,"column":null}},"line":707},"30":{"name":"(anonymous_30)","decl":{"start":{"line":735,"column":8},"end":{"line":735,"column":28}},"loc":{"start":{"line":735,"column":56},"end":{"line":807,"column":null}},"line":735},"31":{"name":"(anonymous_31)","decl":{"start":{"line":809,"column":8},"end":{"line":809,"column":22}},"loc":{"start":{"line":809,"column":50},"end":{"line":1011,"column":null}},"line":809},"32":{"name":"(anonymous_32)","decl":{"start":{"line":907,"column":14},"end":{"line":907,"column":26}},"loc":{"start":{"line":907,"column":26},"end":{"line":964,"column":9}},"line":907},"33":{"name":"(anonymous_33)","decl":{"start":{"line":965,"column":15},"end":{"line":965,"column":16}},"loc":{"start":{"line":965,"column":24},"end":{"line":978,"column":9}},"line":965},"34":{"name":"(anonymous_34)","decl":{"start":{"line":1013,"column":8},"end":{"line":1013,"column":21}},"loc":{"start":{"line":1013,"column":49},"end":{"line":1172,"column":null}},"line":1013},"35":{"name":"(anonymous_35)","decl":{"start":{"line":1056,"column":18},"end":{"line":1056,"column":19}},"loc":{"start":{"line":1056,"column":25},"end":{"line":1056,"column":50}},"line":1056},"36":{"name":"(anonymous_36)","decl":{"start":{"line":1174,"column":8},"end":{"line":1174,"column":19}},"loc":{"start":{"line":1174,"column":47},"end":{"line":1326,"column":null}},"line":1174},"37":{"name":"(anonymous_37)","decl":{"start":{"line":1199,"column":17},"end":{"line":1199,"column":18}},"loc":{"start":{"line":1199,"column":27},"end":{"line":1199,"column":53}},"line":1199},"38":{"name":"(anonymous_38)","decl":{"start":{"line":1200,"column":20},"end":{"line":1200,"column":21}},"loc":{"start":{"line":1200,"column":30},"end":{"line":1200,"column":74}},"line":1200},"39":{"name":"(anonymous_39)","decl":{"start":{"line":1229,"column":13},"end":{"line":1229,"column":14}},"loc":{"start":{"line":1229,"column":22},"end":{"line":1229,"column":42}},"line":1229},"40":{"name":"(anonymous_40)","decl":{"start":{"line":1289,"column":23},"end":{"line":1289,"column":24}},"loc":{"start":{"line":1289,"column":24},"end":{"line":1297,"column":null}},"line":1289},"41":{"name":"(anonymous_41)","decl":{"start":{"line":1290,"column":25},"end":{"line":1290,"column":26}},"loc":{"start":{"line":1290,"column":35},"end":{"line":1297,"column":10}},"line":1290},"42":{"name":"(anonymous_42)","decl":{"start":{"line":1328,"column":8},"end":{"line":1328,"column":26}},"loc":{"start":{"line":1328,"column":54},"end":{"line":1358,"column":null}},"line":1328},"43":{"name":"(anonymous_43)","decl":{"start":{"line":1360,"column":8},"end":{"line":1360,"column":24}},"loc":{"start":{"line":1360,"column":52},"end":{"line":1390,"column":null}},"line":1360},"44":{"name":"(anonymous_44)","decl":{"start":{"line":1378,"column":31},"end":{"line":1378,"column":32}},"loc":{"start":{"line":1378,"column":42},"end":{"line":1383,"column":12}},"line":1378},"45":{"name":"(anonymous_45)","decl":{"start":{"line":1392,"column":8},"end":{"line":1392,"column":26}},"loc":{"start":{"line":1392,"column":54},"end":{"line":1432,"column":null}},"line":1392},"46":{"name":"(anonymous_46)","decl":{"start":{"line":1416,"column":32},"end":{"line":1416,"column":33}},"loc":{"start":{"line":1416,"column":43},"end":{"line":1421,"column":12}},"line":1416},"47":{"name":"(anonymous_47)","decl":{"start":{"line":1434,"column":8},"end":{"line":1434,"column":22}},"loc":{"start":{"line":1434,"column":50},"end":{"line":1470,"column":null}},"line":1434},"48":{"name":"(anonymous_48)","decl":{"start":{"line":1441,"column":16},"end":{"line":1441,"column":17}},"loc":{"start":{"line":1441,"column":26},"end":{"line":1441,"column":76}},"line":1441},"49":{"name":"(anonymous_49)","decl":{"start":{"line":1455,"column":13},"end":{"line":1455,"column":14}},"loc":{"start":{"line":1455,"column":38},"end":{"line":1459,"column":10}},"line":1455},"50":{"name":"(anonymous_50)","decl":{"start":{"line":1460,"column":14},"end":{"line":1460,"column":15}},"loc":{"start":{"line":1460,"column":24},"end":{"line":1460,"column":39}},"line":1460},"51":{"name":"(anonymous_51)","decl":{"start":{"line":1472,"column":8},"end":{"line":1472,"column":22}},"loc":{"start":{"line":1472,"column":50},"end":{"line":1513,"column":null}},"line":1472},"52":{"name":"(anonymous_52)","decl":{"start":{"line":1491,"column":46},"end":{"line":1491,"column":47}},"loc":{"start":{"line":1491,"column":55},"end":{"line":1491,"column":73}},"line":1491},"53":{"name":"(anonymous_53)","decl":{"start":{"line":1494,"column":8},"end":{"line":1494,"column":9}},"loc":{"start":{"line":1495,"column":10},"end":{"line":1495,"column":null}},"line":1495},"54":{"name":"(anonymous_54)","decl":{"start":{"line":1505,"column":45},"end":{"line":1505,"column":46}},"loc":{"start":{"line":1505,"column":54},"end":{"line":1505,"column":73}},"line":1505},"55":{"name":"(anonymous_55)","decl":{"start":{"line":1506,"column":47},"end":{"line":1506,"column":48}},"loc":{"start":{"line":1506,"column":56},"end":{"line":1506,"column":74}},"line":1506},"56":{"name":"(anonymous_56)","decl":{"start":{"line":1515,"column":8},"end":{"line":1515,"column":22}},"loc":{"start":{"line":1515,"column":50},"end":{"line":1556,"column":null}},"line":1515},"57":{"name":"(anonymous_57)","decl":{"start":{"line":1562,"column":8},"end":{"line":1562,"column":20}},"loc":{"start":{"line":1562,"column":48},"end":{"line":1638,"column":null}},"line":1562},"58":{"name":"(anonymous_58)","decl":{"start":{"line":1587,"column":21},"end":{"line":1587,"column":22}},"loc":{"start":{"line":1587,"column":31},"end":{"line":1587,"column":43}},"line":1587},"59":{"name":"(anonymous_59)","decl":{"start":{"line":1640,"column":8},"end":{"line":1640,"column":23}},"loc":{"start":{"line":1640,"column":51},"end":{"line":1700,"column":null}},"line":1640},"60":{"name":"(anonymous_60)","decl":{"start":{"line":1664,"column":23},"end":{"line":1664,"column":24}},"loc":{"start":{"line":1664,"column":33},"end":{"line":1664,"column":45}},"line":1664},"61":{"name":"(anonymous_61)","decl":{"start":{"line":1679,"column":22},"end":{"line":1679,"column":23}},"loc":{"start":{"line":1679,"column":32},"end":{"line":1679,"column":73}},"line":1679},"62":{"name":"(anonymous_62)","decl":{"start":{"line":1702,"column":8},"end":{"line":1702,"column":23}},"loc":{"start":{"line":1702,"column":51},"end":{"line":1746,"column":null}},"line":1702},"63":{"name":"(anonymous_63)","decl":{"start":{"line":1728,"column":30},"end":{"line":1728,"column":31}},"loc":{"start":{"line":1728,"column":40},"end":{"line":1728,"column":52}},"line":1728},"64":{"name":"(anonymous_64)","decl":{"start":{"line":1748,"column":8},"end":{"line":1748,"column":16}},"loc":{"start":{"line":1748,"column":44},"end":{"line":1768,"column":null}},"line":1748},"65":{"name":"(anonymous_65)","decl":{"start":{"line":1774,"column":8},"end":{"line":1774,"column":20}},"loc":{"start":{"line":1774,"column":48},"end":{"line":1821,"column":null}},"line":1774},"66":{"name":"(anonymous_66)","decl":{"start":{"line":1823,"column":8},"end":{"line":1823,"column":22}},"loc":{"start":{"line":1823,"column":50},"end":{"line":1849,"column":null}},"line":1823},"67":{"name":"(anonymous_67)","decl":{"start":{"line":1851,"column":8},"end":{"line":1851,"column":21}},"loc":{"start":{"line":1851,"column":49},"end":{"line":1877,"column":null}},"line":1851},"68":{"name":"(anonymous_68)","decl":{"start":{"line":1879,"column":8},"end":{"line":1879,"column":30}},"loc":{"start":{"line":1879,"column":58},"end":{"line":1901,"column":null}},"line":1879},"69":{"name":"(anonymous_69)","decl":{"start":{"line":1903,"column":8},"end":{"line":1903,"column":21}},"loc":{"start":{"line":1903,"column":49},"end":{"line":2020,"column":null}},"line":1903},"70":{"name":"(anonymous_70)","decl":{"start":{"line":1940,"column":47},"end":{"line":1940,"column":48}},"loc":{"start":{"line":1941,"column":8},"end":{"line":1943,"column":null}},"line":1941},"71":{"name":"(anonymous_71)","decl":{"start":{"line":1950,"column":42},"end":{"line":1950,"column":43}},"loc":{"start":{"line":1950,"column":52},"end":{"line":1950,"column":63}},"line":1950},"72":{"name":"(anonymous_72)","decl":{"start":{"line":1979,"column":42},"end":{"line":1979,"column":43}},"loc":{"start":{"line":1979,"column":52},"end":{"line":1990,"column":9}},"line":1979},"73":{"name":"(anonymous_73)","decl":{"start":{"line":1980,"column":38},"end":{"line":1980,"column":39}},"loc":{"start":{"line":1980,"column":56},"end":{"line":1984,"column":12}},"line":1980},"74":{"name":"(anonymous_74)","decl":{"start":{"line":1985,"column":36},"end":{"line":1985,"column":37}},"loc":{"start":{"line":1985,"column":54},"end":{"line":1989,"column":12}},"line":1985},"75":{"name":"(anonymous_75)","decl":{"start":{"line":2005,"column":31},"end":{"line":2005,"column":32}},"loc":{"start":{"line":2005,"column":41},"end":{"line":2005,"column":66}},"line":2005},"76":{"name":"(anonymous_76)","decl":{"start":{"line":2022,"column":8},"end":{"line":2022,"column":23}},"loc":{"start":{"line":2022,"column":51},"end":{"line":2130,"column":null}},"line":2022},"77":{"name":"(anonymous_77)","decl":{"start":{"line":2076,"column":22},"end":{"line":2076,"column":23}},"loc":{"start":{"line":2076,"column":31},"end":{"line":2076,"column":51}},"line":2076},"78":{"name":"(anonymous_78)","decl":{"start":{"line":2078,"column":19},"end":{"line":2078,"column":20}},"loc":{"start":{"line":2078,"column":29},"end":{"line":2083,"column":16}},"line":2078},"79":{"name":"(anonymous_79)","decl":{"start":{"line":2090,"column":22},"end":{"line":2090,"column":23}},"loc":{"start":{"line":2090,"column":31},"end":{"line":2090,"column":51}},"line":2090},"80":{"name":"(anonymous_80)","decl":{"start":{"line":2092,"column":19},"end":{"line":2092,"column":20}},"loc":{"start":{"line":2092,"column":29},"end":{"line":2097,"column":16}},"line":2092},"81":{"name":"(anonymous_81)","decl":{"start":{"line":2132,"column":10},"end":{"line":2132,"column":26}},"loc":{"start":{"line":2132,"column":65},"end":{"line":2162,"column":null}},"line":2132},"82":{"name":"(anonymous_82)","decl":{"start":{"line":2136,"column":14},"end":{"line":2136,"column":15}},"loc":{"start":{"line":2136,"column":25},"end":{"line":2136,"column":42}},"line":2136},"83":{"name":"(anonymous_83)","decl":{"start":{"line":2145,"column":11},"end":{"line":2145,"column":12}},"loc":{"start":{"line":2145,"column":21},"end":{"line":2153,"column":7}},"line":2145},"84":{"name":"(anonymous_84)","decl":{"start":{"line":2149,"column":10},"end":{"line":2149,"column":11}},"loc":{"start":{"line":2149,"column":26},"end":{"line":2149,"column":null}},"line":2149},"85":{"name":"(anonymous_85)","decl":{"start":{"line":2154,"column":12},"end":{"line":2154,"column":13}},"loc":{"start":{"line":2154,"column":22},"end":{"line":2154,"column":39}},"line":2154},"86":{"name":"(anonymous_86)","decl":{"start":{"line":2156,"column":35},"end":{"line":2156,"column":36}},"loc":{"start":{"line":2156,"column":45},"end":{"line":2156,"column":59}},"line":2156},"87":{"name":"(anonymous_87)","decl":{"start":{"line":2158,"column":26},"end":{"line":2158,"column":27}},"loc":{"start":{"line":2158,"column":36},"end":{"line":2158,"column":47}},"line":2158},"88":{"name":"(anonymous_88)","decl":{"start":{"line":2161,"column":42},"end":{"line":2161,"column":43}},"loc":{"start":{"line":2161,"column":52},"end":{"line":2161,"column":59}},"line":2161},"89":{"name":"(anonymous_89)","decl":{"start":{"line":2164,"column":16},"end":{"line":2164,"column":null}},"loc":{"start":{"line":2167,"column":23},"end":{"line":2192,"column":null}},"line":2167},"90":{"name":"(anonymous_90)","decl":{"start":{"line":2194,"column":16},"end":{"line":2194,"column":null}},"loc":{"start":{"line":2197,"column":20},"end":{"line":2242,"column":null}},"line":2197},"91":{"name":"(anonymous_91)","decl":{"start":{"line":2216,"column":16},"end":{"line":2216,"column":17}},"loc":{"start":{"line":2216,"column":25},"end":{"line":2216,"column":45}},"line":2216},"92":{"name":"(anonymous_92)","decl":{"start":{"line":2218,"column":13},"end":{"line":2218,"column":14}},"loc":{"start":{"line":2218,"column":23},"end":{"line":2218,"column":40}},"line":2218},"93":{"name":"(anonymous_93)","decl":{"start":{"line":2221,"column":16},"end":{"line":2221,"column":17}},"loc":{"start":{"line":2221,"column":25},"end":{"line":2221,"column":45}},"line":2221},"94":{"name":"(anonymous_94)","decl":{"start":{"line":2223,"column":13},"end":{"line":2223,"column":14}},"loc":{"start":{"line":2223,"column":23},"end":{"line":2223,"column":38}},"line":2223},"95":{"name":"(anonymous_95)","decl":{"start":{"line":2244,"column":10},"end":{"line":2244,"column":30}},"loc":{"start":{"line":2249,"column":11},"end":{"line":2285,"column":null}},"line":2249},"96":{"name":"(anonymous_96)","decl":{"start":{"line":2261,"column":16},"end":{"line":2261,"column":17}},"loc":{"start":{"line":2261,"column":25},"end":{"line":2261,"column":48}},"line":2261},"97":{"name":"(anonymous_97)","decl":{"start":{"line":2263,"column":13},"end":{"line":2263,"column":14}},"loc":{"start":{"line":2263,"column":22},"end":{"line":2263,"column":58}},"line":2263},"98":{"name":"(anonymous_98)","decl":{"start":{"line":2264,"column":14},"end":{"line":2264,"column":15}},"loc":{"start":{"line":2264,"column":29},"end":{"line":2264,"column":55}},"line":2264},"99":{"name":"(anonymous_99)","decl":{"start":{"line":2287,"column":10},"end":{"line":2287,"column":null}},"loc":{"start":{"line":2292,"column":12},"end":{"line":2307,"column":null}},"line":2292},"100":{"name":"(anonymous_100)","decl":{"start":{"line":2309,"column":16},"end":{"line":2309,"column":null}},"loc":{"start":{"line":2313,"column":20},"end":{"line":2338,"column":null}},"line":2313},"101":{"name":"(anonymous_101)","decl":{"start":{"line":2331,"column":37},"end":{"line":2331,"column":38}},"loc":{"start":{"line":2331,"column":47},"end":{"line":2337,"column":6}},"line":2331},"102":{"name":"(anonymous_102)","decl":{"start":{"line":2340,"column":16},"end":{"line":2340,"column":null}},"loc":{"start":{"line":2343,"column":20},"end":{"line":2362,"column":null}},"line":2343},"103":{"name":"(anonymous_103)","decl":{"start":{"line":2357,"column":35},"end":{"line":2357,"column":36}},"loc":{"start":{"line":2357,"column":45},"end":{"line":2361,"column":6}},"line":2357},"104":{"name":"(anonymous_104)","decl":{"start":{"line":2364,"column":16},"end":{"line":2364,"column":null}},"loc":{"start":{"line":2367,"column":20},"end":{"line":2386,"column":null}},"line":2367},"105":{"name":"(anonymous_105)","decl":{"start":{"line":2381,"column":35},"end":{"line":2381,"column":36}},"loc":{"start":{"line":2381,"column":45},"end":{"line":2385,"column":6}},"line":2381},"106":{"name":"(anonymous_106)","decl":{"start":{"line":2388,"column":16},"end":{"line":2388,"column":null}},"loc":{"start":{"line":2392,"column":20},"end":{"line":2419,"column":null}},"line":2392},"107":{"name":"(anonymous_107)","decl":{"start":{"line":2413,"column":35},"end":{"line":2413,"column":36}},"loc":{"start":{"line":2413,"column":45},"end":{"line":2418,"column":6}},"line":2413},"108":{"name":"(anonymous_108)","decl":{"start":{"line":2421,"column":10},"end":{"line":2421,"column":null}},"loc":{"start":{"line":2424,"column":10},"end":{"line":2467,"column":null}},"line":2424},"109":{"name":"(anonymous_109)","decl":{"start":{"line":2429,"column":22},"end":{"line":2429,"column":28}},"loc":{"start":{"line":2429,"column":28},"end":{"line":2455,"column":null}},"line":2429},"110":{"name":"(anonymous_110)","decl":{"start":{"line":2469,"column":10},"end":{"line":2469,"column":37}},"loc":{"start":{"line":2478,"column":11},"end":{"line":2561,"column":null}},"line":2478},"111":{"name":"(anonymous_111)","decl":{"start":{"line":2492,"column":14},"end":{"line":2492,"column":15}},"loc":{"start":{"line":2492,"column":29},"end":{"line":2501,"column":9}},"line":2492},"112":{"name":"(anonymous_112)","decl":{"start":{"line":2506,"column":18},"end":{"line":2506,"column":19}},"loc":{"start":{"line":2506,"column":27},"end":{"line":2506,"column":50}},"line":2506},"113":{"name":"(anonymous_113)","decl":{"start":{"line":2507,"column":15},"end":{"line":2507,"column":16}},"loc":{"start":{"line":2507,"column":24},"end":{"line":2507,"column":30}},"line":2507},"114":{"name":"(anonymous_114)","decl":{"start":{"line":2511,"column":15},"end":{"line":2511,"column":16}},"loc":{"start":{"line":2511,"column":23},"end":{"line":2511,"column":53}},"line":2511},"115":{"name":"(anonymous_115)","decl":{"start":{"line":2512,"column":16},"end":{"line":2512,"column":17}},"loc":{"start":{"line":2512,"column":26},"end":{"line":2512,"column":63}},"line":2512},"116":{"name":"(anonymous_116)","decl":{"start":{"line":2525,"column":13},"end":{"line":2525,"column":14}},"loc":{"start":{"line":2525,"column":23},"end":{"line":2528,"column":7}},"line":2525},"117":{"name":"(anonymous_117)","decl":{"start":{"line":2545,"column":14},"end":{"line":2545,"column":15}},"loc":{"start":{"line":2545,"column":29},"end":{"line":2554,"column":9}},"line":2545},"118":{"name":"(anonymous_118)","decl":{"start":{"line":2563,"column":10},"end":{"line":2563,"column":null}},"loc":{"start":{"line":2567,"column":22},"end":{"line":2572,"column":null}},"line":2567},"119":{"name":"(anonymous_119)","decl":{"start":{"line":2574,"column":10},"end":{"line":2574,"column":null}},"loc":{"start":{"line":2578,"column":12},"end":{"line":2586,"column":null}},"line":2578},"120":{"name":"(anonymous_120)","decl":{"start":{"line":2590,"column":8},"end":{"line":2590,"column":27}},"loc":{"start":{"line":2590,"column":55},"end":{"line":2758,"column":null}},"line":2590},"121":{"name":"(anonymous_121)","decl":{"start":{"line":2764,"column":8},"end":{"line":2764,"column":35}},"loc":{"start":{"line":2764,"column":63},"end":{"line":3014,"column":null}},"line":2764},"122":{"name":"(anonymous_122)","decl":{"start":{"line":2860,"column":17},"end":{"line":2860,"column":18}},"loc":{"start":{"line":2860,"column":29},"end":{"line":2860,"column":51}},"line":2860},"123":{"name":"(anonymous_123)","decl":{"start":{"line":2867,"column":30},"end":{"line":2867,"column":31}},"loc":{"start":{"line":2868,"column":10},"end":{"line":2868,"column":null}},"line":2868},"124":{"name":"(anonymous_124)","decl":{"start":{"line":2878,"column":20},"end":{"line":2878,"column":21}},"loc":{"start":{"line":2878,"column":27},"end":{"line":2878,"column":42}},"line":2878},"125":{"name":"(anonymous_125)","decl":{"start":{"line":2879,"column":17},"end":{"line":2879,"column":18}},"loc":{"start":{"line":2879,"column":24},"end":{"line":2879,"column":30}},"line":2879},"126":{"name":"(anonymous_126)","decl":{"start":{"line":2910,"column":50},"end":{"line":2910,"column":51}},"loc":{"start":{"line":2910,"column":57},"end":{"line":2910,"column":77}},"line":2910}},"branchMap":{"0":{"loc":{"start":{"line":88,"column":6},"end":{"line":88,"column":null}},"type":"default-arg","locations":[{"start":{"line":88,"column":17},"end":{"line":88,"column":null}}],"line":88},"1":{"loc":{"start":{"line":89,"column":6},"end":{"line":89,"column":null}},"type":"default-arg","locations":[{"start":{"line":89,"column":14},"end":{"line":89,"column":null}}],"line":89},"2":{"loc":{"start":{"line":90,"column":6},"end":{"line":90,"column":null}},"type":"default-arg","locations":[{"start":{"line":90,"column":16},"end":{"line":90,"column":null}}],"line":90},"3":{"loc":{"start":{"line":92,"column":6},"end":{"line":92,"column":null}},"type":"default-arg","locations":[{"start":{"line":92,"column":13},"end":{"line":92,"column":null}}],"line":92},"4":{"loc":{"start":{"line":99,"column":24},"end":{"line":99,"column":null}},"type":"cond-expr","locations":[{"start":{"line":99,"column":65},"end":{"line":99,"column":72}},{"start":{"line":99,"column":72},"end":{"line":99,"column":null}}],"line":99},"5":{"loc":{"start":{"line":99,"column":24},"end":{"line":99,"column":65}},"type":"binary-expr","locations":[{"start":{"line":99,"column":24},"end":{"line":99,"column":45}},{"start":{"line":99,"column":45},"end":{"line":99,"column":65}}],"line":99},"6":{"loc":{"start":{"line":101,"column":6},"end":{"line":158,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":6},"end":{"line":158,"column":null}},{"start":{"line":111,"column":13},"end":{"line":158,"column":null}}],"line":101},"7":{"loc":{"start":{"line":103,"column":10},"end":{"line":103,"column":null}},"type":"cond-expr","locations":[{"start":{"line":103,"column":28},"end":{"line":103,"column":70}},{"start":{"line":103,"column":70},"end":{"line":103,"column":null}}],"line":103},"8":{"loc":{"start":{"line":106,"column":10},"end":{"line":110,"column":null}},"type":"cond-expr","locations":[{"start":{"line":107,"column":14},"end":{"line":109,"column":null}},{"start":{"line":110,"column":14},"end":{"line":110,"column":null}}],"line":106},"9":{"loc":{"start":{"line":112,"column":8},"end":{"line":157,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":8},"end":{"line":157,"column":null}},{"start":{"line":145,"column":15},"end":{"line":157,"column":null}}],"line":112},"10":{"loc":{"start":{"line":112,"column":12},"end":{"line":112,"column":62}},"type":"binary-expr","locations":[{"start":{"line":112,"column":12},"end":{"line":112,"column":38}},{"start":{"line":112,"column":38},"end":{"line":112,"column":62}}],"line":112},"11":{"loc":{"start":{"line":119,"column":10},"end":{"line":144,"column":null}},"type":"if","locations":[{"start":{"line":119,"column":10},"end":{"line":144,"column":null}},{"start":{"line":121,"column":17},"end":{"line":144,"column":null}}],"line":119},"12":{"loc":{"start":{"line":160,"column":6},"end":{"line":167,"column":null}},"type":"if","locations":[{"start":{"line":160,"column":6},"end":{"line":167,"column":null}},{"start":{},"end":{}}],"line":160},"13":{"loc":{"start":{"line":173,"column":12},"end":{"line":173,"column":null}},"type":"cond-expr","locations":[{"start":{"line":173,"column":37},"end":{"line":173,"column":66}},{"start":{"line":173,"column":66},"end":{"line":173,"column":null}}],"line":173},"14":{"loc":{"start":{"line":194,"column":4},"end":{"line":196,"column":null}},"type":"if","locations":[{"start":{"line":194,"column":4},"end":{"line":196,"column":null}},{"start":{},"end":{}}],"line":194},"15":{"loc":{"start":{"line":194,"column":8},"end":{"line":194,"column":49}},"type":"binary-expr","locations":[{"start":{"line":194,"column":8},"end":{"line":194,"column":27}},{"start":{"line":194,"column":27},"end":{"line":194,"column":49}}],"line":194},"16":{"loc":{"start":{"line":199,"column":6},"end":{"line":201,"column":null}},"type":"if","locations":[{"start":{"line":199,"column":6},"end":{"line":201,"column":null}},{"start":{},"end":{}}],"line":199},"17":{"loc":{"start":{"line":207,"column":8},"end":{"line":209,"column":null}},"type":"cond-expr","locations":[{"start":{"line":208,"column":12},"end":{"line":208,"column":null}},{"start":{"line":209,"column":12},"end":{"line":209,"column":null}}],"line":207},"18":{"loc":{"start":{"line":207,"column":8},"end":{"line":207,"column":null}},"type":"binary-expr","locations":[{"start":{"line":207,"column":8},"end":{"line":207,"column":31}},{"start":{"line":207,"column":31},"end":{"line":207,"column":null}}],"line":207},"19":{"loc":{"start":{"line":211,"column":6},"end":{"line":213,"column":null}},"type":"if","locations":[{"start":{"line":211,"column":6},"end":{"line":213,"column":null}},{"start":{},"end":{}}],"line":211},"20":{"loc":{"start":{"line":216,"column":8},"end":{"line":218,"column":null}},"type":"binary-expr","locations":[{"start":{"line":216,"column":8},"end":{"line":216,"column":null}},{"start":{"line":217,"column":9},"end":{"line":217,"column":null}},{"start":{"line":218,"column":11},"end":{"line":218,"column":36}},{"start":{"line":218,"column":36},"end":{"line":218,"column":null}}],"line":216},"21":{"loc":{"start":{"line":236,"column":19},"end":{"line":236,"column":null}},"type":"binary-expr","locations":[{"start":{"line":236,"column":19},"end":{"line":236,"column":34}},{"start":{"line":236,"column":34},"end":{"line":236,"column":null}}],"line":236},"22":{"loc":{"start":{"line":250,"column":4},"end":{"line":252,"column":null}},"type":"if","locations":[{"start":{"line":250,"column":4},"end":{"line":252,"column":null}},{"start":{},"end":{}}],"line":250},"23":{"loc":{"start":{"line":272,"column":21},"end":{"line":272,"column":32}},"type":"default-arg","locations":[{"start":{"line":272,"column":29},"end":{"line":272,"column":32}}],"line":272},"24":{"loc":{"start":{"line":272,"column":32},"end":{"line":272,"column":52}},"type":"default-arg","locations":[{"start":{"line":272,"column":42},"end":{"line":272,"column":52}}],"line":272},"25":{"loc":{"start":{"line":281,"column":8},"end":{"line":283,"column":null}},"type":"binary-expr","locations":[{"start":{"line":281,"column":8},"end":{"line":281,"column":null}},{"start":{"line":282,"column":8},"end":{"line":282,"column":null}},{"start":{"line":283,"column":8},"end":{"line":283,"column":null}}],"line":281},"26":{"loc":{"start":{"line":285,"column":6},"end":{"line":292,"column":null}},"type":"if","locations":[{"start":{"line":285,"column":6},"end":{"line":292,"column":null}},{"start":{},"end":{}}],"line":285},"27":{"loc":{"start":{"line":296,"column":17},"end":{"line":296,"column":null}},"type":"binary-expr","locations":[{"start":{"line":296,"column":17},"end":{"line":296,"column":47}},{"start":{"line":296,"column":47},"end":{"line":296,"column":null}}],"line":296},"28":{"loc":{"start":{"line":307,"column":8},"end":{"line":313,"column":null}},"type":"if","locations":[{"start":{"line":307,"column":8},"end":{"line":313,"column":null}},{"start":{},"end":{}}],"line":307},"29":{"loc":{"start":{"line":311,"column":14},"end":{"line":311,"column":null}},"type":"binary-expr","locations":[{"start":{"line":311,"column":14},"end":{"line":311,"column":40}},{"start":{"line":311,"column":40},"end":{"line":311,"column":66}},{"start":{"line":311,"column":66},"end":{"line":311,"column":null}}],"line":311},"30":{"loc":{"start":{"line":323,"column":21},"end":{"line":323,"column":39}},"type":"default-arg","locations":[{"start":{"line":323,"column":28},"end":{"line":323,"column":39}}],"line":323},"31":{"loc":{"start":{"line":323,"column":39},"end":{"line":323,"column":59}},"type":"default-arg","locations":[{"start":{"line":323,"column":49},"end":{"line":323,"column":59}}],"line":323},"32":{"loc":{"start":{"line":332,"column":6},"end":{"line":481,"column":null}},"type":"if","locations":[{"start":{"line":332,"column":6},"end":{"line":481,"column":null}},{"start":{"line":338,"column":6},"end":{"line":481,"column":null}}],"line":332},"33":{"loc":{"start":{"line":333,"column":8},"end":{"line":335,"column":null}},"type":"if","locations":[{"start":{"line":333,"column":8},"end":{"line":335,"column":null}},{"start":{},"end":{}}],"line":333},"34":{"loc":{"start":{"line":338,"column":6},"end":{"line":481,"column":null}},"type":"if","locations":[{"start":{"line":338,"column":6},"end":{"line":481,"column":null}},{"start":{"line":350,"column":6},"end":{"line":481,"column":null}}],"line":338},"35":{"loc":{"start":{"line":343,"column":10},"end":{"line":348,"column":null}},"type":"if","locations":[{"start":{"line":343,"column":10},"end":{"line":348,"column":null}},{"start":{},"end":{}}],"line":343},"36":{"loc":{"start":{"line":350,"column":6},"end":{"line":481,"column":null}},"type":"if","locations":[{"start":{"line":350,"column":6},"end":{"line":481,"column":null}},{"start":{"line":475,"column":13},"end":{"line":481,"column":null}}],"line":350},"37":{"loc":{"start":{"line":354,"column":39},"end":{"line":354,"column":70}},"type":"binary-expr","locations":[{"start":{"line":354,"column":39},"end":{"line":354,"column":68}},{"start":{"line":354,"column":68},"end":{"line":354,"column":70}}],"line":354},"38":{"loc":{"start":{"line":355,"column":10},"end":{"line":355,"column":null}},"type":"if","locations":[{"start":{"line":355,"column":10},"end":{"line":355,"column":null}},{"start":{},"end":{}}],"line":355},"39":{"loc":{"start":{"line":356,"column":10},"end":{"line":361,"column":null}},"type":"if","locations":[{"start":{"line":356,"column":10},"end":{"line":361,"column":null}},{"start":{},"end":{}}],"line":356},"40":{"loc":{"start":{"line":357,"column":12},"end":{"line":359,"column":null}},"type":"if","locations":[{"start":{"line":357,"column":12},"end":{"line":359,"column":null}},{"start":{},"end":{}}],"line":357},"41":{"loc":{"start":{"line":365,"column":8},"end":{"line":367,"column":null}},"type":"if","locations":[{"start":{"line":365,"column":8},"end":{"line":367,"column":null}},{"start":{},"end":{}}],"line":365},"42":{"loc":{"start":{"line":380,"column":12},"end":{"line":386,"column":null}},"type":"if","locations":[{"start":{"line":380,"column":12},"end":{"line":386,"column":null}},{"start":{},"end":{}}],"line":380},"43":{"loc":{"start":{"line":381,"column":14},"end":{"line":383,"column":null}},"type":"binary-expr","locations":[{"start":{"line":381,"column":14},"end":{"line":381,"column":null}},{"start":{"line":382,"column":14},"end":{"line":382,"column":null}},{"start":{"line":383,"column":14},"end":{"line":383,"column":null}}],"line":381},"44":{"loc":{"start":{"line":393,"column":14},"end":{"line":399,"column":null}},"type":"if","locations":[{"start":{"line":393,"column":14},"end":{"line":399,"column":null}},{"start":{},"end":{}}],"line":393},"45":{"loc":{"start":{"line":394,"column":16},"end":{"line":396,"column":null}},"type":"binary-expr","locations":[{"start":{"line":394,"column":16},"end":{"line":394,"column":null}},{"start":{"line":395,"column":16},"end":{"line":395,"column":null}},{"start":{"line":396,"column":16},"end":{"line":396,"column":null}}],"line":394},"46":{"loc":{"start":{"line":414,"column":10},"end":{"line":414,"column":null}},"type":"if","locations":[{"start":{"line":414,"column":10},"end":{"line":414,"column":null}},{"start":{},"end":{}}],"line":414},"47":{"loc":{"start":{"line":418,"column":12},"end":{"line":420,"column":null}},"type":"if","locations":[{"start":{"line":418,"column":12},"end":{"line":420,"column":null}},{"start":{},"end":{}}],"line":418},"48":{"loc":{"start":{"line":426,"column":10},"end":{"line":426,"column":null}},"type":"if","locations":[{"start":{"line":426,"column":10},"end":{"line":426,"column":null}},{"start":{},"end":{}}],"line":426},"49":{"loc":{"start":{"line":430,"column":28},"end":{"line":430,"column":null}},"type":"binary-expr","locations":[{"start":{"line":430,"column":28},"end":{"line":430,"column":53}},{"start":{"line":430,"column":53},"end":{"line":430,"column":null}}],"line":430},"50":{"loc":{"start":{"line":432,"column":12},"end":{"line":435,"column":null}},"type":"if","locations":[{"start":{"line":432,"column":12},"end":{"line":435,"column":null}},{"start":{},"end":{}}],"line":432},"51":{"loc":{"start":{"line":432,"column":16},"end":{"line":432,"column":70}},"type":"binary-expr","locations":[{"start":{"line":432,"column":16},"end":{"line":432,"column":44}},{"start":{"line":432,"column":44},"end":{"line":432,"column":70}}],"line":432},"52":{"loc":{"start":{"line":437,"column":12},"end":{"line":447,"column":null}},"type":"if","locations":[{"start":{"line":437,"column":12},"end":{"line":447,"column":null}},{"start":{},"end":{}}],"line":437},"53":{"loc":{"start":{"line":439,"column":14},"end":{"line":446,"column":null}},"type":"if","locations":[{"start":{"line":439,"column":14},"end":{"line":446,"column":null}},{"start":{},"end":{}}],"line":439},"54":{"loc":{"start":{"line":442,"column":16},"end":{"line":445,"column":null}},"type":"if","locations":[{"start":{"line":442,"column":16},"end":{"line":445,"column":null}},{"start":{},"end":{}}],"line":442},"55":{"loc":{"start":{"line":442,"column":20},"end":{"line":442,"column":49}},"type":"binary-expr","locations":[{"start":{"line":442,"column":20},"end":{"line":442,"column":27}},{"start":{"line":442,"column":27},"end":{"line":442,"column":49}}],"line":442},"56":{"loc":{"start":{"line":456,"column":10},"end":{"line":458,"column":null}},"type":"if","locations":[{"start":{"line":456,"column":10},"end":{"line":458,"column":null}},{"start":{},"end":{}}],"line":456},"57":{"loc":{"start":{"line":464,"column":26},"end":{"line":464,"column":53}},"type":"binary-expr","locations":[{"start":{"line":464,"column":26},"end":{"line":464,"column":51}},{"start":{"line":464,"column":51},"end":{"line":464,"column":53}}],"line":464},"58":{"loc":{"start":{"line":469,"column":8},"end":{"line":474,"column":null}},"type":"if","locations":[{"start":{"line":469,"column":8},"end":{"line":474,"column":null}},{"start":{},"end":{}}],"line":469},"59":{"loc":{"start":{"line":496,"column":20},"end":{"line":496,"column":null}},"type":"binary-expr","locations":[{"start":{"line":496,"column":20},"end":{"line":496,"column":37}},{"start":{"line":496,"column":37},"end":{"line":496,"column":null}}],"line":496},"60":{"loc":{"start":{"line":497,"column":19},"end":{"line":497,"column":null}},"type":"binary-expr","locations":[{"start":{"line":497,"column":19},"end":{"line":497,"column":35}},{"start":{"line":497,"column":35},"end":{"line":497,"column":null}}],"line":497},"61":{"loc":{"start":{"line":498,"column":29},"end":{"line":498,"column":64}},"type":"binary-expr","locations":[{"start":{"line":498,"column":29},"end":{"line":498,"column":44}},{"start":{"line":498,"column":44},"end":{"line":498,"column":58}},{"start":{"line":498,"column":58},"end":{"line":498,"column":64}}],"line":498},"62":{"loc":{"start":{"line":499,"column":37},"end":{"line":501,"column":null}},"type":"cond-expr","locations":[{"start":{"line":500,"column":8},"end":{"line":500,"column":null}},{"start":{"line":501,"column":8},"end":{"line":501,"column":null}}],"line":499},"63":{"loc":{"start":{"line":504,"column":6},"end":{"line":508,"column":null}},"type":"cond-expr","locations":[{"start":{"line":505,"column":10},"end":{"line":505,"column":null}},{"start":{"line":506,"column":10},"end":{"line":508,"column":null}}],"line":504},"64":{"loc":{"start":{"line":506,"column":10},"end":{"line":508,"column":null}},"type":"cond-expr","locations":[{"start":{"line":507,"column":12},"end":{"line":507,"column":null}},{"start":{"line":508,"column":12},"end":{"line":508,"column":null}}],"line":506},"65":{"loc":{"start":{"line":511,"column":10},"end":{"line":511,"column":null}},"type":"binary-expr","locations":[{"start":{"line":511,"column":10},"end":{"line":511,"column":26}},{"start":{"line":511,"column":26},"end":{"line":511,"column":null}}],"line":511},"66":{"loc":{"start":{"line":512,"column":10},"end":{"line":512,"column":null}},"type":"cond-expr","locations":[{"start":{"line":512,"column":29},"end":{"line":512,"column":60}},{"start":{"line":512,"column":60},"end":{"line":512,"column":null}}],"line":512},"67":{"loc":{"start":{"line":531,"column":6},"end":{"line":531,"column":null}},"type":"default-arg","locations":[{"start":{"line":531,"column":16},"end":{"line":531,"column":null}}],"line":531},"68":{"loc":{"start":{"line":541,"column":6},"end":{"line":546,"column":null}},"type":"if","locations":[{"start":{"line":541,"column":6},"end":{"line":546,"column":null}},{"start":{},"end":{}}],"line":541},"69":{"loc":{"start":{"line":549,"column":6},"end":{"line":561,"column":null}},"type":"if","locations":[{"start":{"line":549,"column":6},"end":{"line":561,"column":null}},{"start":{},"end":{}}],"line":549},"70":{"loc":{"start":{"line":549,"column":10},"end":{"line":549,"column":41}},"type":"binary-expr","locations":[{"start":{"line":549,"column":10},"end":{"line":549,"column":20}},{"start":{"line":549,"column":20},"end":{"line":549,"column":32}},{"start":{"line":549,"column":32},"end":{"line":549,"column":41}}],"line":549},"71":{"loc":{"start":{"line":556,"column":8},"end":{"line":560,"column":null}},"type":"if","locations":[{"start":{"line":556,"column":8},"end":{"line":560,"column":null}},{"start":{},"end":{}}],"line":556},"72":{"loc":{"start":{"line":564,"column":6},"end":{"line":619,"column":null}},"type":"if","locations":[{"start":{"line":564,"column":6},"end":{"line":619,"column":null}},{"start":{},"end":{}}],"line":564},"73":{"loc":{"start":{"line":564,"column":17},"end":{"line":564,"column":29}},"type":"binary-expr","locations":[{"start":{"line":564,"column":17},"end":{"line":564,"column":27}},{"start":{"line":564,"column":27},"end":{"line":564,"column":29}}],"line":564},"74":{"loc":{"start":{"line":565,"column":26},"end":{"line":565,"column":null}},"type":"binary-expr","locations":[{"start":{"line":565,"column":26},"end":{"line":565,"column":56}},{"start":{"line":565,"column":56},"end":{"line":565,"column":null}}],"line":565},"75":{"loc":{"start":{"line":567,"column":10},"end":{"line":567,"column":null}},"type":"binary-expr","locations":[{"start":{"line":567,"column":10},"end":{"line":567,"column":22}},{"start":{"line":567,"column":22},"end":{"line":567,"column":39}},{"start":{"line":567,"column":39},"end":{"line":567,"column":null}}],"line":567},"76":{"loc":{"start":{"line":603,"column":52},"end":{"line":603,"column":90}},"type":"cond-expr","locations":[{"start":{"line":603,"column":60},"end":{"line":603,"column":88}},{"start":{"line":603,"column":88},"end":{"line":603,"column":90}}],"line":603},"77":{"loc":{"start":{"line":631,"column":23},"end":{"line":631,"column":43}},"type":"default-arg","locations":[{"start":{"line":631,"column":33},"end":{"line":631,"column":43}}],"line":631},"78":{"loc":{"start":{"line":640,"column":31},"end":{"line":640,"column":46}},"type":"binary-expr","locations":[{"start":{"line":640,"column":31},"end":{"line":640,"column":44}},{"start":{"line":640,"column":44},"end":{"line":640,"column":46}}],"line":640},"79":{"loc":{"start":{"line":641,"column":6},"end":{"line":658,"column":null}},"type":"if","locations":[{"start":{"line":641,"column":6},"end":{"line":658,"column":null}},{"start":{},"end":{}}],"line":641},"80":{"loc":{"start":{"line":642,"column":8},"end":{"line":644,"column":null}},"type":"binary-expr","locations":[{"start":{"line":642,"column":8},"end":{"line":642,"column":null}},{"start":{"line":643,"column":8},"end":{"line":643,"column":null}},{"start":{"line":644,"column":8},"end":{"line":644,"column":null}}],"line":642},"81":{"loc":{"start":{"line":652,"column":20},"end":{"line":652,"column":null}},"type":"binary-expr","locations":[{"start":{"line":652,"column":20},"end":{"line":652,"column":36}},{"start":{"line":652,"column":36},"end":{"line":652,"column":null}}],"line":652},"82":{"loc":{"start":{"line":653,"column":22},"end":{"line":653,"column":null}},"type":"binary-expr","locations":[{"start":{"line":653,"column":22},"end":{"line":653,"column":40}},{"start":{"line":653,"column":40},"end":{"line":653,"column":null}}],"line":653},"83":{"loc":{"start":{"line":663,"column":6},"end":{"line":679,"column":null}},"type":"if","locations":[{"start":{"line":663,"column":6},"end":{"line":679,"column":null}},{"start":{},"end":{}}],"line":663},"84":{"loc":{"start":{"line":666,"column":30},"end":{"line":666,"column":48}},"type":"binary-expr","locations":[{"start":{"line":666,"column":30},"end":{"line":666,"column":46}},{"start":{"line":666,"column":46},"end":{"line":666,"column":48}}],"line":666},"85":{"loc":{"start":{"line":668,"column":12},"end":{"line":671,"column":null}},"type":"binary-expr","locations":[{"start":{"line":668,"column":12},"end":{"line":668,"column":null}},{"start":{"line":669,"column":12},"end":{"line":669,"column":null}},{"start":{"line":670,"column":12},"end":{"line":670,"column":null}},{"start":{"line":671,"column":12},"end":{"line":671,"column":null}}],"line":668},"86":{"loc":{"start":{"line":675,"column":8},"end":{"line":678,"column":null}},"type":"if","locations":[{"start":{"line":675,"column":8},"end":{"line":678,"column":null}},{"start":{},"end":{}}],"line":675},"87":{"loc":{"start":{"line":681,"column":6},"end":{"line":693,"column":null}},"type":"if","locations":[{"start":{"line":681,"column":6},"end":{"line":693,"column":null}},{"start":{},"end":{}}],"line":681},"88":{"loc":{"start":{"line":708,"column":17},"end":{"line":708,"column":null}},"type":"binary-expr","locations":[{"start":{"line":708,"column":17},"end":{"line":708,"column":32}},{"start":{"line":708,"column":32},"end":{"line":708,"column":null}}],"line":708},"89":{"loc":{"start":{"line":708,"column":32},"end":{"line":708,"column":null}},"type":"cond-expr","locations":[{"start":{"line":708,"column":48},"end":{"line":708,"column":56}},{"start":{"line":708,"column":56},"end":{"line":708,"column":null}}],"line":708},"90":{"loc":{"start":{"line":709,"column":20},"end":{"line":709,"column":null}},"type":"binary-expr","locations":[{"start":{"line":709,"column":20},"end":{"line":709,"column":37}},{"start":{"line":709,"column":37},"end":{"line":709,"column":null}}],"line":709},"91":{"loc":{"start":{"line":720,"column":12},"end":{"line":722,"column":null}},"type":"cond-expr","locations":[{"start":{"line":721,"column":16},"end":{"line":721,"column":null}},{"start":{"line":722,"column":16},"end":{"line":722,"column":null}}],"line":720},"92":{"loc":{"start":{"line":736,"column":12},"end":{"line":736,"column":32}},"type":"default-arg","locations":[{"start":{"line":736,"column":22},"end":{"line":736,"column":32}}],"line":736},"93":{"loc":{"start":{"line":736,"column":36},"end":{"line":736,"column":null}},"type":"binary-expr","locations":[{"start":{"line":736,"column":36},"end":{"line":736,"column":44}},{"start":{"line":736,"column":44},"end":{"line":736,"column":null}}],"line":736},"94":{"loc":{"start":{"line":739,"column":51},"end":{"line":739,"column":61}},"type":"binary-expr","locations":[{"start":{"line":739,"column":51},"end":{"line":739,"column":59}},{"start":{"line":739,"column":59},"end":{"line":739,"column":61}}],"line":739},"95":{"loc":{"start":{"line":742,"column":8},"end":{"line":743,"column":null}},"type":"binary-expr","locations":[{"start":{"line":742,"column":8},"end":{"line":742,"column":null}},{"start":{"line":743,"column":8},"end":{"line":743,"column":null}}],"line":742},"96":{"loc":{"start":{"line":745,"column":6},"end":{"line":756,"column":null}},"type":"if","locations":[{"start":{"line":745,"column":6},"end":{"line":756,"column":null}},{"start":{},"end":{}}],"line":745},"97":{"loc":{"start":{"line":746,"column":8},"end":{"line":748,"column":null}},"type":"binary-expr","locations":[{"start":{"line":746,"column":8},"end":{"line":746,"column":null}},{"start":{"line":747,"column":8},"end":{"line":747,"column":null}},{"start":{"line":748,"column":8},"end":{"line":748,"column":null}}],"line":746},"98":{"loc":{"start":{"line":760,"column":6},"end":{"line":767,"column":null}},"type":"if","locations":[{"start":{"line":760,"column":6},"end":{"line":767,"column":null}},{"start":{},"end":{}}],"line":760},"99":{"loc":{"start":{"line":769,"column":6},"end":{"line":776,"column":null}},"type":"if","locations":[{"start":{"line":769,"column":6},"end":{"line":776,"column":null}},{"start":{},"end":{}}],"line":769},"100":{"loc":{"start":{"line":788,"column":25},"end":{"line":788,"column":null}},"type":"binary-expr","locations":[{"start":{"line":788,"column":25},"end":{"line":788,"column":43}},{"start":{"line":788,"column":43},"end":{"line":788,"column":null}}],"line":788},"101":{"loc":{"start":{"line":791,"column":26},"end":{"line":791,"column":null}},"type":"binary-expr","locations":[{"start":{"line":791,"column":26},"end":{"line":791,"column":53}},{"start":{"line":791,"column":53},"end":{"line":791,"column":null}}],"line":791},"102":{"loc":{"start":{"line":793,"column":37},"end":{"line":793,"column":null}},"type":"binary-expr","locations":[{"start":{"line":793,"column":37},"end":{"line":793,"column":63}},{"start":{"line":793,"column":63},"end":{"line":793,"column":null}}],"line":793},"103":{"loc":{"start":{"line":811,"column":6},"end":{"line":811,"column":null}},"type":"default-arg","locations":[{"start":{"line":811,"column":13},"end":{"line":811,"column":null}}],"line":811},"104":{"loc":{"start":{"line":812,"column":6},"end":{"line":812,"column":null}},"type":"default-arg","locations":[{"start":{"line":812,"column":16},"end":{"line":812,"column":null}}],"line":812},"105":{"loc":{"start":{"line":813,"column":6},"end":{"line":813,"column":null}},"type":"default-arg","locations":[{"start":{"line":813,"column":16},"end":{"line":813,"column":null}}],"line":813},"106":{"loc":{"start":{"line":814,"column":6},"end":{"line":814,"column":null}},"type":"default-arg","locations":[{"start":{"line":814,"column":18},"end":{"line":814,"column":null}}],"line":814},"107":{"loc":{"start":{"line":818,"column":6},"end":{"line":824,"column":null}},"type":"if","locations":[{"start":{"line":818,"column":6},"end":{"line":824,"column":null}},{"start":{},"end":{}}],"line":818},"108":{"loc":{"start":{"line":826,"column":55},"end":{"line":826,"column":65}},"type":"binary-expr","locations":[{"start":{"line":826,"column":55},"end":{"line":826,"column":63}},{"start":{"line":826,"column":63},"end":{"line":826,"column":65}}],"line":826},"109":{"loc":{"start":{"line":829,"column":8},"end":{"line":830,"column":null}},"type":"binary-expr","locations":[{"start":{"line":829,"column":8},"end":{"line":829,"column":null}},{"start":{"line":830,"column":8},"end":{"line":830,"column":null}}],"line":829},"110":{"loc":{"start":{"line":832,"column":6},"end":{"line":843,"column":null}},"type":"if","locations":[{"start":{"line":832,"column":6},"end":{"line":843,"column":null}},{"start":{},"end":{}}],"line":832},"111":{"loc":{"start":{"line":833,"column":8},"end":{"line":835,"column":null}},"type":"binary-expr","locations":[{"start":{"line":833,"column":8},"end":{"line":833,"column":null}},{"start":{"line":834,"column":8},"end":{"line":834,"column":null}},{"start":{"line":835,"column":8},"end":{"line":835,"column":null}}],"line":833},"112":{"loc":{"start":{"line":852,"column":6},"end":{"line":864,"column":null}},"type":"if","locations":[{"start":{"line":852,"column":6},"end":{"line":864,"column":null}},{"start":{},"end":{}}],"line":852},"113":{"loc":{"start":{"line":858,"column":18},"end":{"line":858,"column":null}},"type":"cond-expr","locations":[{"start":{"line":858,"column":36},"end":{"line":858,"column":53}},{"start":{"line":858,"column":53},"end":{"line":858,"column":null}}],"line":858},"114":{"loc":{"start":{"line":866,"column":6},"end":{"line":873,"column":null}},"type":"if","locations":[{"start":{"line":866,"column":6},"end":{"line":873,"column":null}},{"start":{},"end":{}}],"line":866},"115":{"loc":{"start":{"line":875,"column":6},"end":{"line":882,"column":null}},"type":"if","locations":[{"start":{"line":875,"column":6},"end":{"line":882,"column":null}},{"start":{},"end":{}}],"line":875},"116":{"loc":{"start":{"line":910,"column":10},"end":{"line":914,"column":null}},"type":"if","locations":[{"start":{"line":910,"column":10},"end":{"line":914,"column":null}},{"start":{},"end":{}}],"line":910},"117":{"loc":{"start":{"line":916,"column":10},"end":{"line":963,"column":null}},"type":"if","locations":[{"start":{"line":916,"column":10},"end":{"line":963,"column":null}},{"start":{"line":923,"column":10},"end":{"line":963,"column":null}}],"line":916},"118":{"loc":{"start":{"line":923,"column":10},"end":{"line":963,"column":null}},"type":"if","locations":[{"start":{"line":923,"column":10},"end":{"line":963,"column":null}},{"start":{},"end":{}}],"line":923},"119":{"loc":{"start":{"line":929,"column":14},"end":{"line":939,"column":null}},"type":"if","locations":[{"start":{"line":929,"column":14},"end":{"line":939,"column":null}},{"start":{},"end":{}}],"line":929},"120":{"loc":{"start":{"line":930,"column":16},"end":{"line":931,"column":null}},"type":"binary-expr","locations":[{"start":{"line":930,"column":16},"end":{"line":930,"column":null}},{"start":{"line":931,"column":16},"end":{"line":931,"column":null}}],"line":930},"121":{"loc":{"start":{"line":949,"column":12},"end":{"line":957,"column":null}},"type":"if","locations":[{"start":{"line":949,"column":12},"end":{"line":957,"column":null}},{"start":{"line":953,"column":12},"end":{"line":957,"column":null}}],"line":949},"122":{"loc":{"start":{"line":953,"column":12},"end":{"line":957,"column":null}},"type":"if","locations":[{"start":{"line":953,"column":12},"end":{"line":957,"column":null}},{"start":{},"end":{}}],"line":953},"123":{"loc":{"start":{"line":970,"column":27},"end":{"line":970,"column":null}},"type":"cond-expr","locations":[{"start":{"line":970,"column":50},"end":{"line":970,"column":64}},{"start":{"line":970,"column":64},"end":{"line":970,"column":null}}],"line":970},"124":{"loc":{"start":{"line":971,"column":24},"end":{"line":971,"column":null}},"type":"cond-expr","locations":[{"start":{"line":971,"column":47},"end":{"line":971,"column":59}},{"start":{"line":971,"column":59},"end":{"line":971,"column":null}}],"line":971},"125":{"loc":{"start":{"line":975,"column":10},"end":{"line":977,"column":null}},"type":"if","locations":[{"start":{"line":975,"column":10},"end":{"line":977,"column":null}},{"start":{},"end":{}}],"line":975},"126":{"loc":{"start":{"line":996,"column":37},"end":{"line":996,"column":null}},"type":"binary-expr","locations":[{"start":{"line":996,"column":37},"end":{"line":996,"column":63}},{"start":{"line":996,"column":63},"end":{"line":996,"column":null}}],"line":996},"127":{"loc":{"start":{"line":997,"column":71},"end":{"line":997,"column":106}},"type":"cond-expr","locations":[{"start":{"line":997,"column":89},"end":{"line":997,"column":97}},{"start":{"line":997,"column":97},"end":{"line":997,"column":106}}],"line":997},"128":{"loc":{"start":{"line":1014,"column":20},"end":{"line":1014,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1014,"column":20},"end":{"line":1014,"column":37}},{"start":{"line":1014,"column":37},"end":{"line":1014,"column":null}}],"line":1014},"129":{"loc":{"start":{"line":1037,"column":20},"end":{"line":1037,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1037,"column":20},"end":{"line":1037,"column":51}},{"start":{"line":1037,"column":51},"end":{"line":1037,"column":null}}],"line":1037},"130":{"loc":{"start":{"line":1038,"column":32},"end":{"line":1038,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1038,"column":32},"end":{"line":1038,"column":71}},{"start":{"line":1038,"column":71},"end":{"line":1038,"column":null}}],"line":1038},"131":{"loc":{"start":{"line":1039,"column":31},"end":{"line":1039,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1039,"column":31},"end":{"line":1039,"column":69}},{"start":{"line":1039,"column":69},"end":{"line":1039,"column":null}}],"line":1039},"132":{"loc":{"start":{"line":1040,"column":32},"end":{"line":1040,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1040,"column":32},"end":{"line":1040,"column":70}},{"start":{"line":1040,"column":70},"end":{"line":1040,"column":null}}],"line":1040},"133":{"loc":{"start":{"line":1041,"column":32},"end":{"line":1041,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1041,"column":32},"end":{"line":1041,"column":70}},{"start":{"line":1041,"column":70},"end":{"line":1041,"column":null}}],"line":1041},"134":{"loc":{"start":{"line":1042,"column":33},"end":{"line":1042,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1042,"column":33},"end":{"line":1042,"column":72}},{"start":{"line":1042,"column":72},"end":{"line":1042,"column":null}}],"line":1042},"135":{"loc":{"start":{"line":1054,"column":8},"end":{"line":1056,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1054,"column":8},"end":{"line":1056,"column":62}},{"start":{"line":1056,"column":62},"end":{"line":1056,"column":null}}],"line":1054},"136":{"loc":{"start":{"line":1058,"column":8},"end":{"line":1065,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1059,"column":12},"end":{"line":1064,"column":null}},{"start":{"line":1065,"column":12},"end":{"line":1065,"column":null}}],"line":1058},"137":{"loc":{"start":{"line":1079,"column":25},"end":{"line":1079,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1079,"column":25},"end":{"line":1079,"column":55}},{"start":{"line":1079,"column":55},"end":{"line":1079,"column":null}}],"line":1079},"138":{"loc":{"start":{"line":1080,"column":26},"end":{"line":1080,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1080,"column":26},"end":{"line":1080,"column":49}},{"start":{"line":1080,"column":49},"end":{"line":1080,"column":null}}],"line":1080},"139":{"loc":{"start":{"line":1082,"column":17},"end":{"line":1082,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1082,"column":17},"end":{"line":1082,"column":58}},{"start":{"line":1082,"column":58},"end":{"line":1082,"column":null}}],"line":1082},"140":{"loc":{"start":{"line":1088,"column":6},"end":{"line":1092,"column":null}},"type":"if","locations":[{"start":{"line":1088,"column":6},"end":{"line":1092,"column":null}},{"start":{},"end":{}}],"line":1088},"141":{"loc":{"start":{"line":1094,"column":6},"end":{"line":1098,"column":null}},"type":"if","locations":[{"start":{"line":1094,"column":6},"end":{"line":1098,"column":null}},{"start":{},"end":{}}],"line":1094},"142":{"loc":{"start":{"line":1094,"column":10},"end":{"line":1094,"column":70}},"type":"binary-expr","locations":[{"start":{"line":1094,"column":10},"end":{"line":1094,"column":28}},{"start":{"line":1094,"column":28},"end":{"line":1094,"column":70}}],"line":1094},"143":{"loc":{"start":{"line":1102,"column":18},"end":{"line":1102,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1102,"column":31},"end":{"line":1102,"column":50}},{"start":{"line":1102,"column":50},"end":{"line":1102,"column":null}}],"line":1102},"144":{"loc":{"start":{"line":1107,"column":27},"end":{"line":1107,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1107,"column":27},"end":{"line":1107,"column":57}},{"start":{"line":1107,"column":57},"end":{"line":1107,"column":null}}],"line":1107},"145":{"loc":{"start":{"line":1121,"column":28},"end":{"line":1123,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1122,"column":16},"end":{"line":1122,"column":null}},{"start":{"line":1123,"column":16},"end":{"line":1123,"column":null}}],"line":1121},"146":{"loc":{"start":{"line":1131,"column":28},"end":{"line":1133,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1132,"column":16},"end":{"line":1132,"column":null}},{"start":{"line":1133,"column":16},"end":{"line":1133,"column":null}}],"line":1131},"147":{"loc":{"start":{"line":1137,"column":18},"end":{"line":1137,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1137,"column":18},"end":{"line":1137,"column":52}},{"start":{"line":1137,"column":52},"end":{"line":1137,"column":null}}],"line":1137},"148":{"loc":{"start":{"line":1141,"column":22},"end":{"line":1141,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1141,"column":49},"end":{"line":1141,"column":66}},{"start":{"line":1141,"column":66},"end":{"line":1141,"column":null}}],"line":1141},"149":{"loc":{"start":{"line":1144,"column":29},"end":{"line":1144,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1144,"column":29},"end":{"line":1144,"column":56}},{"start":{"line":1144,"column":56},"end":{"line":1144,"column":null}}],"line":1144},"150":{"loc":{"start":{"line":1145,"column":22},"end":{"line":1145,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1145,"column":22},"end":{"line":1145,"column":51}},{"start":{"line":1145,"column":51},"end":{"line":1145,"column":null}}],"line":1145},"151":{"loc":{"start":{"line":1146,"column":24},"end":{"line":1146,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1146,"column":24},"end":{"line":1146,"column":42}},{"start":{"line":1146,"column":42},"end":{"line":1146,"column":null}}],"line":1146},"152":{"loc":{"start":{"line":1148,"column":14},"end":{"line":1150,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1148,"column":14},"end":{"line":1148,"column":null}},{"start":{"line":1149,"column":14},"end":{"line":1149,"column":null}},{"start":{"line":1150,"column":14},"end":{"line":1150,"column":null}}],"line":1148},"153":{"loc":{"start":{"line":1151,"column":21},"end":{"line":1151,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1151,"column":21},"end":{"line":1151,"column":43}},{"start":{"line":1151,"column":43},"end":{"line":1151,"column":null}}],"line":1151},"154":{"loc":{"start":{"line":1159,"column":26},"end":{"line":1159,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1159,"column":26},"end":{"line":1159,"column":53}},{"start":{"line":1159,"column":53},"end":{"line":1159,"column":null}}],"line":1159},"155":{"loc":{"start":{"line":1160,"column":24},"end":{"line":1160,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1160,"column":24},"end":{"line":1160,"column":42}},{"start":{"line":1160,"column":42},"end":{"line":1160,"column":null}}],"line":1160},"156":{"loc":{"start":{"line":1164,"column":8},"end":{"line":1166,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1165,"column":12},"end":{"line":1165,"column":null}},{"start":{"line":1166,"column":12},"end":{"line":1166,"column":null}}],"line":1164},"157":{"loc":{"start":{"line":1177,"column":6},"end":{"line":1177,"column":null}},"type":"default-arg","locations":[{"start":{"line":1177,"column":14},"end":{"line":1177,"column":null}}],"line":1177},"158":{"loc":{"start":{"line":1178,"column":6},"end":{"line":1178,"column":null}},"type":"default-arg","locations":[{"start":{"line":1178,"column":16},"end":{"line":1178,"column":null}}],"line":1178},"159":{"loc":{"start":{"line":1179,"column":8},"end":{"line":1179,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1179,"column":8},"end":{"line":1179,"column":16}},{"start":{"line":1179,"column":16},"end":{"line":1179,"column":null}}],"line":1179},"160":{"loc":{"start":{"line":1181,"column":4},"end":{"line":1188,"column":null}},"type":"if","locations":[{"start":{"line":1181,"column":4},"end":{"line":1188,"column":null}},{"start":{},"end":{}}],"line":1181},"161":{"loc":{"start":{"line":1181,"column":8},"end":{"line":1181,"column":45}},"type":"binary-expr","locations":[{"start":{"line":1181,"column":8},"end":{"line":1181,"column":18}},{"start":{"line":1181,"column":18},"end":{"line":1181,"column":45}}],"line":1181},"162":{"loc":{"start":{"line":1193,"column":8},"end":{"line":1195,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1194,"column":12},"end":{"line":1194,"column":null}},{"start":{"line":1195,"column":12},"end":{"line":1195,"column":null}}],"line":1193},"163":{"loc":{"start":{"line":1193,"column":8},"end":{"line":1193,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1193,"column":8},"end":{"line":1193,"column":47}},{"start":{"line":1193,"column":47},"end":{"line":1193,"column":null}}],"line":1193},"164":{"loc":{"start":{"line":1197,"column":30},"end":{"line":1201,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1198,"column":10},"end":{"line":1200,"column":null}},{"start":{"line":1201,"column":10},"end":{"line":1201,"column":null}}],"line":1197},"165":{"loc":{"start":{"line":1203,"column":6},"end":{"line":1209,"column":null}},"type":"if","locations":[{"start":{"line":1203,"column":6},"end":{"line":1209,"column":null}},{"start":{},"end":{}}],"line":1203},"166":{"loc":{"start":{"line":1212,"column":6},"end":{"line":1219,"column":null}},"type":"if","locations":[{"start":{"line":1212,"column":6},"end":{"line":1219,"column":null}},{"start":{},"end":{}}],"line":1212},"167":{"loc":{"start":{"line":1228,"column":21},"end":{"line":1228,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1228,"column":21},"end":{"line":1228,"column":38}},{"start":{"line":1228,"column":38},"end":{"line":1228,"column":null}}],"line":1228},"168":{"loc":{"start":{"line":1229,"column":29},"end":{"line":1229,"column":41}},"type":"binary-expr","locations":[{"start":{"line":1229,"column":29},"end":{"line":1229,"column":39}},{"start":{"line":1229,"column":39},"end":{"line":1229,"column":41}}],"line":1229},"169":{"loc":{"start":{"line":1290,"column":9},"end":{"line":1290,"column":21}},"type":"binary-expr","locations":[{"start":{"line":1290,"column":9},"end":{"line":1290,"column":17}},{"start":{"line":1290,"column":17},"end":{"line":1290,"column":21}}],"line":1290},"170":{"loc":{"start":{"line":1291,"column":26},"end":{"line":1291,"column":43}},"type":"binary-expr","locations":[{"start":{"line":1291,"column":26},"end":{"line":1291,"column":41}},{"start":{"line":1291,"column":41},"end":{"line":1291,"column":43}}],"line":1291},"171":{"loc":{"start":{"line":1292,"column":23},"end":{"line":1292,"column":44}},"type":"binary-expr","locations":[{"start":{"line":1292,"column":23},"end":{"line":1292,"column":35}},{"start":{"line":1292,"column":35},"end":{"line":1292,"column":44}}],"line":1292},"172":{"loc":{"start":{"line":1293,"column":23},"end":{"line":1293,"column":37}},"type":"binary-expr","locations":[{"start":{"line":1293,"column":23},"end":{"line":1293,"column":35}},{"start":{"line":1293,"column":35},"end":{"line":1293,"column":37}}],"line":1293},"173":{"loc":{"start":{"line":1294,"column":22},"end":{"line":1294,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1294,"column":39},"end":{"line":1294,"column":64}},{"start":{"line":1294,"column":64},"end":{"line":1294,"column":null}}],"line":1294},"174":{"loc":{"start":{"line":1296,"column":19},"end":{"line":1296,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1296,"column":19},"end":{"line":1296,"column":53}},{"start":{"line":1296,"column":53},"end":{"line":1296,"column":null}}],"line":1296},"175":{"loc":{"start":{"line":1299,"column":29},"end":{"line":1299,"column":51}},"type":"binary-expr","locations":[{"start":{"line":1299,"column":29},"end":{"line":1299,"column":49}},{"start":{"line":1299,"column":49},"end":{"line":1299,"column":51}}],"line":1299},"176":{"loc":{"start":{"line":1300,"column":31},"end":{"line":1300,"column":55}},"type":"binary-expr","locations":[{"start":{"line":1300,"column":31},"end":{"line":1300,"column":53}},{"start":{"line":1300,"column":53},"end":{"line":1300,"column":55}}],"line":1300},"177":{"loc":{"start":{"line":1301,"column":32},"end":{"line":1301,"column":57}},"type":"binary-expr","locations":[{"start":{"line":1301,"column":32},"end":{"line":1301,"column":55}},{"start":{"line":1301,"column":55},"end":{"line":1301,"column":57}}],"line":1301},"178":{"loc":{"start":{"line":1329,"column":29},"end":{"line":1329,"column":45}},"type":"default-arg","locations":[{"start":{"line":1329,"column":41},"end":{"line":1329,"column":45}}],"line":1329},"179":{"loc":{"start":{"line":1329,"column":45},"end":{"line":1329,"column":65}},"type":"default-arg","locations":[{"start":{"line":1329,"column":55},"end":{"line":1329,"column":65}}],"line":1329},"180":{"loc":{"start":{"line":1329,"column":69},"end":{"line":1329,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1329,"column":69},"end":{"line":1329,"column":77}},{"start":{"line":1329,"column":77},"end":{"line":1329,"column":null}}],"line":1329},"181":{"loc":{"start":{"line":1331,"column":4},"end":{"line":1337,"column":null}},"type":"if","locations":[{"start":{"line":1331,"column":4},"end":{"line":1337,"column":null}},{"start":{},"end":{}}],"line":1331},"182":{"loc":{"start":{"line":1331,"column":8},"end":{"line":1331,"column":43}},"type":"binary-expr","locations":[{"start":{"line":1331,"column":8},"end":{"line":1331,"column":17}},{"start":{"line":1331,"column":17},"end":{"line":1331,"column":43}}],"line":1331},"183":{"loc":{"start":{"line":1361,"column":19},"end":{"line":1361,"column":38}},"type":"default-arg","locations":[{"start":{"line":1361,"column":26},"end":{"line":1361,"column":38}}],"line":1361},"184":{"loc":{"start":{"line":1361,"column":38},"end":{"line":1361,"column":49}},"type":"default-arg","locations":[{"start":{"line":1361,"column":46},"end":{"line":1361,"column":49}}],"line":1361},"185":{"loc":{"start":{"line":1361,"column":49},"end":{"line":1361,"column":69}},"type":"default-arg","locations":[{"start":{"line":1361,"column":59},"end":{"line":1361,"column":69}}],"line":1361},"186":{"loc":{"start":{"line":1395,"column":6},"end":{"line":1395,"column":null}},"type":"default-arg","locations":[{"start":{"line":1395,"column":18},"end":{"line":1395,"column":null}}],"line":1395},"187":{"loc":{"start":{"line":1396,"column":6},"end":{"line":1396,"column":null}},"type":"default-arg","locations":[{"start":{"line":1396,"column":14},"end":{"line":1396,"column":null}}],"line":1396},"188":{"loc":{"start":{"line":1397,"column":6},"end":{"line":1397,"column":null}},"type":"default-arg","locations":[{"start":{"line":1397,"column":16},"end":{"line":1397,"column":null}}],"line":1397},"189":{"loc":{"start":{"line":1435,"column":18},"end":{"line":1435,"column":29}},"type":"default-arg","locations":[{"start":{"line":1435,"column":26},"end":{"line":1435,"column":29}}],"line":1435},"190":{"loc":{"start":{"line":1435,"column":29},"end":{"line":1435,"column":49}},"type":"default-arg","locations":[{"start":{"line":1435,"column":39},"end":{"line":1435,"column":49}}],"line":1435},"191":{"loc":{"start":{"line":1441,"column":26},"end":{"line":1441,"column":76}},"type":"binary-expr","locations":[{"start":{"line":1441,"column":26},"end":{"line":1441,"column":48}},{"start":{"line":1441,"column":48},"end":{"line":1441,"column":76}}],"line":1441},"192":{"loc":{"start":{"line":1446,"column":21},"end":{"line":1446,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1446,"column":21},"end":{"line":1446,"column":43}},{"start":{"line":1446,"column":43},"end":{"line":1446,"column":null}}],"line":1446},"193":{"loc":{"start":{"line":1447,"column":20},"end":{"line":1447,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1447,"column":20},"end":{"line":1447,"column":61}},{"start":{"line":1447,"column":61},"end":{"line":1447,"column":null}}],"line":1447},"194":{"loc":{"start":{"line":1448,"column":8},"end":{"line":1450,"column":null}},"type":"if","locations":[{"start":{"line":1448,"column":8},"end":{"line":1450,"column":null}},{"start":{},"end":{}}],"line":1448},"195":{"loc":{"start":{"line":1473,"column":36},"end":{"line":1473,"column":56}},"type":"default-arg","locations":[{"start":{"line":1473,"column":46},"end":{"line":1473,"column":56}}],"line":1473},"196":{"loc":{"start":{"line":1479,"column":6},"end":{"line":1485,"column":null}},"type":"if","locations":[{"start":{"line":1479,"column":6},"end":{"line":1485,"column":null}},{"start":{},"end":{}}],"line":1479},"197":{"loc":{"start":{"line":1479,"column":10},"end":{"line":1479,"column":27}},"type":"binary-expr","locations":[{"start":{"line":1479,"column":10},"end":{"line":1479,"column":19}},{"start":{"line":1479,"column":19},"end":{"line":1479,"column":27}}],"line":1479},"198":{"loc":{"start":{"line":1487,"column":24},"end":{"line":1487,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1487,"column":24},"end":{"line":1487,"column":43}},{"start":{"line":1487,"column":43},"end":{"line":1487,"column":null}}],"line":1487},"199":{"loc":{"start":{"line":1488,"column":25},"end":{"line":1488,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1488,"column":25},"end":{"line":1488,"column":45}},{"start":{"line":1488,"column":45},"end":{"line":1488,"column":null}}],"line":1488},"200":{"loc":{"start":{"line":1500,"column":16},"end":{"line":1500,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1500,"column":16},"end":{"line":1500,"column":40}},{"start":{"line":1500,"column":40},"end":{"line":1500,"column":64}},{"start":{"line":1500,"column":64},"end":{"line":1500,"column":null}}],"line":1500},"201":{"loc":{"start":{"line":1501,"column":17},"end":{"line":1501,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1501,"column":17},"end":{"line":1501,"column":42}},{"start":{"line":1501,"column":42},"end":{"line":1501,"column":67}},{"start":{"line":1501,"column":67},"end":{"line":1501,"column":null}}],"line":1501},"202":{"loc":{"start":{"line":1516,"column":23},"end":{"line":1516,"column":34}},"type":"default-arg","locations":[{"start":{"line":1516,"column":31},"end":{"line":1516,"column":34}}],"line":1516},"203":{"loc":{"start":{"line":1516,"column":34},"end":{"line":1516,"column":54}},"type":"default-arg","locations":[{"start":{"line":1516,"column":44},"end":{"line":1516,"column":54}}],"line":1516},"204":{"loc":{"start":{"line":1521,"column":8},"end":{"line":1526,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1521,"column":8},"end":{"line":1521,"column":null}},{"start":{"line":1522,"column":8},"end":{"line":1522,"column":null}},{"start":{"line":1523,"column":8},"end":{"line":1523,"column":null}},{"start":{"line":1524,"column":9},"end":{"line":1526,"column":null}}],"line":1521},"205":{"loc":{"start":{"line":1524,"column":9},"end":{"line":1526,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1525,"column":12},"end":{"line":1525,"column":null}},{"start":{"line":1526,"column":12},"end":{"line":1526,"column":null}}],"line":1524},"206":{"loc":{"start":{"line":1524,"column":9},"end":{"line":1524,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1524,"column":9},"end":{"line":1524,"column":42}},{"start":{"line":1524,"column":42},"end":{"line":1524,"column":null}}],"line":1524},"207":{"loc":{"start":{"line":1528,"column":6},"end":{"line":1534,"column":null}},"type":"if","locations":[{"start":{"line":1528,"column":6},"end":{"line":1534,"column":null}},{"start":{},"end":{}}],"line":1528},"208":{"loc":{"start":{"line":1566,"column":6},"end":{"line":1566,"column":null}},"type":"default-arg","locations":[{"start":{"line":1566,"column":17},"end":{"line":1566,"column":null}}],"line":1566},"209":{"loc":{"start":{"line":1570,"column":6},"end":{"line":1570,"column":null}},"type":"default-arg","locations":[{"start":{"line":1570,"column":18},"end":{"line":1570,"column":null}}],"line":1570},"210":{"loc":{"start":{"line":1571,"column":6},"end":{"line":1571,"column":null}},"type":"default-arg","locations":[{"start":{"line":1571,"column":16},"end":{"line":1571,"column":null}}],"line":1571},"211":{"loc":{"start":{"line":1574,"column":8},"end":{"line":1574,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1574,"column":8},"end":{"line":1574,"column":16}},{"start":{"line":1574,"column":16},"end":{"line":1574,"column":null}}],"line":1574},"212":{"loc":{"start":{"line":1576,"column":4},"end":{"line":1583,"column":null}},"type":"if","locations":[{"start":{"line":1576,"column":4},"end":{"line":1583,"column":null}},{"start":{},"end":{}}],"line":1576},"213":{"loc":{"start":{"line":1576,"column":8},"end":{"line":1576,"column":27}},"type":"binary-expr","locations":[{"start":{"line":1576,"column":8},"end":{"line":1576,"column":17}},{"start":{"line":1576,"column":17},"end":{"line":1576,"column":27}}],"line":1576},"214":{"loc":{"start":{"line":1586,"column":31},"end":{"line":1588,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1587,"column":8},"end":{"line":1587,"column":null}},{"start":{"line":1588,"column":8},"end":{"line":1588,"column":null}}],"line":1586},"215":{"loc":{"start":{"line":1590,"column":6},"end":{"line":1590,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1590,"column":49},"end":{"line":1590,"column":60}},{"start":{"line":1590,"column":60},"end":{"line":1590,"column":null}}],"line":1590},"216":{"loc":{"start":{"line":1590,"column":6},"end":{"line":1590,"column":49}},"type":"binary-expr","locations":[{"start":{"line":1590,"column":6},"end":{"line":1590,"column":18}},{"start":{"line":1590,"column":18},"end":{"line":1590,"column":49}}],"line":1590},"217":{"loc":{"start":{"line":1597,"column":4},"end":{"line":1603,"column":null}},"type":"if","locations":[{"start":{"line":1597,"column":4},"end":{"line":1603,"column":null}},{"start":{},"end":{}}],"line":1597},"218":{"loc":{"start":{"line":1606,"column":31},"end":{"line":1606,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1606,"column":31},"end":{"line":1606,"column":61}},{"start":{"line":1606,"column":61},"end":{"line":1606,"column":null}}],"line":1606},"219":{"loc":{"start":{"line":1607,"column":36},"end":{"line":1607,"column":65}},"type":"binary-expr","locations":[{"start":{"line":1607,"column":36},"end":{"line":1607,"column":47}},{"start":{"line":1607,"column":47},"end":{"line":1607,"column":65}}],"line":1607},"220":{"loc":{"start":{"line":1615,"column":18},"end":{"line":1615,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1615,"column":27},"end":{"line":1615,"column":44}},{"start":{"line":1615,"column":44},"end":{"line":1615,"column":null}}],"line":1615},"221":{"loc":{"start":{"line":1620,"column":28},"end":{"line":1620,"column":57}},"type":"binary-expr","locations":[{"start":{"line":1620,"column":28},"end":{"line":1620,"column":41}},{"start":{"line":1620,"column":41},"end":{"line":1620,"column":57}}],"line":1620},"222":{"loc":{"start":{"line":1630,"column":18},"end":{"line":1630,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1630,"column":18},"end":{"line":1630,"column":28}},{"start":{"line":1630,"column":28},"end":{"line":1630,"column":null}}],"line":1630},"223":{"loc":{"start":{"line":1647,"column":6},"end":{"line":1647,"column":null}},"type":"default-arg","locations":[{"start":{"line":1647,"column":14},"end":{"line":1647,"column":null}}],"line":1647},"224":{"loc":{"start":{"line":1649,"column":6},"end":{"line":1649,"column":null}},"type":"default-arg","locations":[{"start":{"line":1649,"column":16},"end":{"line":1649,"column":null}}],"line":1649},"225":{"loc":{"start":{"line":1650,"column":8},"end":{"line":1650,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1650,"column":8},"end":{"line":1650,"column":16}},{"start":{"line":1650,"column":16},"end":{"line":1650,"column":null}}],"line":1650},"226":{"loc":{"start":{"line":1652,"column":4},"end":{"line":1658,"column":null}},"type":"if","locations":[{"start":{"line":1652,"column":4},"end":{"line":1658,"column":null}},{"start":{},"end":{}}],"line":1652},"227":{"loc":{"start":{"line":1652,"column":8},"end":{"line":1652,"column":45}},"type":"binary-expr","locations":[{"start":{"line":1652,"column":8},"end":{"line":1652,"column":18}},{"start":{"line":1652,"column":18},"end":{"line":1652,"column":45}}],"line":1652},"228":{"loc":{"start":{"line":1663,"column":31},"end":{"line":1665,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1664,"column":10},"end":{"line":1664,"column":null}},{"start":{"line":1665,"column":10},"end":{"line":1665,"column":null}}],"line":1663},"229":{"loc":{"start":{"line":1678,"column":15},"end":{"line":1680,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1679,"column":12},"end":{"line":1679,"column":null}},{"start":{"line":1680,"column":12},"end":{"line":1680,"column":null}}],"line":1678},"230":{"loc":{"start":{"line":1681,"column":18},"end":{"line":1681,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1681,"column":42},"end":{"line":1681,"column":59}},{"start":{"line":1681,"column":59},"end":{"line":1681,"column":null}}],"line":1681},"231":{"loc":{"start":{"line":1683,"column":15},"end":{"line":1683,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1683,"column":15},"end":{"line":1683,"column":26}},{"start":{"line":1683,"column":26},"end":{"line":1683,"column":null}}],"line":1683},"232":{"loc":{"start":{"line":1690,"column":23},"end":{"line":1690,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1690,"column":45},"end":{"line":1690,"column":68}},{"start":{"line":1690,"column":68},"end":{"line":1690,"column":null}}],"line":1690},"233":{"loc":{"start":{"line":1705,"column":6},"end":{"line":1705,"column":null}},"type":"default-arg","locations":[{"start":{"line":1705,"column":22},"end":{"line":1705,"column":null}}],"line":1705},"234":{"loc":{"start":{"line":1706,"column":6},"end":{"line":1706,"column":null}},"type":"default-arg","locations":[{"start":{"line":1706,"column":14},"end":{"line":1706,"column":null}}],"line":1706},"235":{"loc":{"start":{"line":1709,"column":6},"end":{"line":1709,"column":null}},"type":"default-arg","locations":[{"start":{"line":1709,"column":16},"end":{"line":1709,"column":null}}],"line":1709},"236":{"loc":{"start":{"line":1710,"column":8},"end":{"line":1710,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1710,"column":8},"end":{"line":1710,"column":16}},{"start":{"line":1710,"column":16},"end":{"line":1710,"column":null}}],"line":1710},"237":{"loc":{"start":{"line":1712,"column":4},"end":{"line":1718,"column":null}},"type":"if","locations":[{"start":{"line":1712,"column":4},"end":{"line":1718,"column":null}},{"start":{},"end":{}}],"line":1712},"238":{"loc":{"start":{"line":1712,"column":8},"end":{"line":1712,"column":45}},"type":"binary-expr","locations":[{"start":{"line":1712,"column":8},"end":{"line":1712,"column":18}},{"start":{"line":1712,"column":18},"end":{"line":1712,"column":45}}],"line":1712},"239":{"loc":{"start":{"line":1727,"column":18},"end":{"line":1729,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1728,"column":12},"end":{"line":1728,"column":null}},{"start":{"line":1729,"column":12},"end":{"line":1729,"column":null}}],"line":1727},"240":{"loc":{"start":{"line":1749,"column":29},"end":{"line":1749,"column":41}},"type":"default-arg","locations":[{"start":{"line":1749,"column":37},"end":{"line":1749,"column":41}}],"line":1749},"241":{"loc":{"start":{"line":1749,"column":41},"end":{"line":1749,"column":61}},"type":"default-arg","locations":[{"start":{"line":1749,"column":51},"end":{"line":1749,"column":61}}],"line":1749},"242":{"loc":{"start":{"line":1749,"column":65},"end":{"line":1749,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1749,"column":65},"end":{"line":1749,"column":73}},{"start":{"line":1749,"column":73},"end":{"line":1749,"column":null}}],"line":1749},"243":{"loc":{"start":{"line":1777,"column":6},"end":{"line":1777,"column":null}},"type":"default-arg","locations":[{"start":{"line":1777,"column":18},"end":{"line":1777,"column":null}}],"line":1777},"244":{"loc":{"start":{"line":1782,"column":6},"end":{"line":1782,"column":null}},"type":"default-arg","locations":[{"start":{"line":1782,"column":16},"end":{"line":1782,"column":null}}],"line":1782},"245":{"loc":{"start":{"line":1783,"column":8},"end":{"line":1783,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1783,"column":8},"end":{"line":1783,"column":16}},{"start":{"line":1783,"column":16},"end":{"line":1783,"column":null}}],"line":1783},"246":{"loc":{"start":{"line":1785,"column":4},"end":{"line":1791,"column":null}},"type":"if","locations":[{"start":{"line":1785,"column":4},"end":{"line":1791,"column":null}},{"start":{},"end":{}}],"line":1785},"247":{"loc":{"start":{"line":1785,"column":8},"end":{"line":1785,"column":30}},"type":"binary-expr","locations":[{"start":{"line":1785,"column":8},"end":{"line":1785,"column":21}},{"start":{"line":1785,"column":21},"end":{"line":1785,"column":30}}],"line":1785},"248":{"loc":{"start":{"line":1794,"column":31},"end":{"line":1794,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1794,"column":31},"end":{"line":1794,"column":61}},{"start":{"line":1794,"column":61},"end":{"line":1794,"column":null}}],"line":1794},"249":{"loc":{"start":{"line":1795,"column":36},"end":{"line":1795,"column":65}},"type":"binary-expr","locations":[{"start":{"line":1795,"column":36},"end":{"line":1795,"column":47}},{"start":{"line":1795,"column":47},"end":{"line":1795,"column":65}}],"line":1795},"250":{"loc":{"start":{"line":1802,"column":16},"end":{"line":1802,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1802,"column":25},"end":{"line":1802,"column":42}},{"start":{"line":1802,"column":42},"end":{"line":1802,"column":null}}],"line":1802},"251":{"loc":{"start":{"line":1804,"column":26},"end":{"line":1804,"column":55}},"type":"binary-expr","locations":[{"start":{"line":1804,"column":26},"end":{"line":1804,"column":39}},{"start":{"line":1804,"column":39},"end":{"line":1804,"column":55}}],"line":1804},"252":{"loc":{"start":{"line":1814,"column":8},"end":{"line":1816,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1815,"column":12},"end":{"line":1815,"column":null}},{"start":{"line":1816,"column":12},"end":{"line":1816,"column":null}}],"line":1814},"253":{"loc":{"start":{"line":1824,"column":30},"end":{"line":1824,"column":50}},"type":"default-arg","locations":[{"start":{"line":1824,"column":40},"end":{"line":1824,"column":50}}],"line":1824},"254":{"loc":{"start":{"line":1824,"column":54},"end":{"line":1824,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1824,"column":54},"end":{"line":1824,"column":62}},{"start":{"line":1824,"column":62},"end":{"line":1824,"column":null}}],"line":1824},"255":{"loc":{"start":{"line":1826,"column":4},"end":{"line":1832,"column":null}},"type":"if","locations":[{"start":{"line":1826,"column":4},"end":{"line":1832,"column":null}},{"start":{},"end":{}}],"line":1826},"256":{"loc":{"start":{"line":1841,"column":19},"end":{"line":1841,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1841,"column":19},"end":{"line":1841,"column":30}},{"start":{"line":1841,"column":30},"end":{"line":1841,"column":null}}],"line":1841},"257":{"loc":{"start":{"line":1852,"column":21},"end":{"line":1852,"column":41}},"type":"default-arg","locations":[{"start":{"line":1852,"column":31},"end":{"line":1852,"column":41}}],"line":1852},"258":{"loc":{"start":{"line":1852,"column":45},"end":{"line":1852,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1852,"column":45},"end":{"line":1852,"column":53}},{"start":{"line":1852,"column":53},"end":{"line":1852,"column":null}}],"line":1852},"259":{"loc":{"start":{"line":1854,"column":4},"end":{"line":1860,"column":null}},"type":"if","locations":[{"start":{"line":1854,"column":4},"end":{"line":1860,"column":null}},{"start":{},"end":{}}],"line":1854},"260":{"loc":{"start":{"line":1854,"column":8},"end":{"line":1854,"column":49}},"type":"binary-expr","locations":[{"start":{"line":1854,"column":8},"end":{"line":1854,"column":20}},{"start":{"line":1854,"column":20},"end":{"line":1854,"column":49}}],"line":1854},"261":{"loc":{"start":{"line":1880,"column":12},"end":{"line":1880,"column":32}},"type":"default-arg","locations":[{"start":{"line":1880,"column":22},"end":{"line":1880,"column":32}}],"line":1880},"262":{"loc":{"start":{"line":1880,"column":36},"end":{"line":1880,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1880,"column":36},"end":{"line":1880,"column":44}},{"start":{"line":1880,"column":44},"end":{"line":1880,"column":null}}],"line":1880},"263":{"loc":{"start":{"line":1908,"column":6},"end":{"line":1908,"column":null}},"type":"default-arg","locations":[{"start":{"line":1908,"column":16},"end":{"line":1908,"column":null}}],"line":1908},"264":{"loc":{"start":{"line":1909,"column":6},"end":{"line":1909,"column":null}},"type":"default-arg","locations":[{"start":{"line":1909,"column":25},"end":{"line":1909,"column":null}}],"line":1909},"265":{"loc":{"start":{"line":1910,"column":6},"end":{"line":1910,"column":null}},"type":"default-arg","locations":[{"start":{"line":1910,"column":25},"end":{"line":1910,"column":null}}],"line":1910},"266":{"loc":{"start":{"line":1911,"column":6},"end":{"line":1911,"column":null}},"type":"default-arg","locations":[{"start":{"line":1911,"column":24},"end":{"line":1911,"column":null}}],"line":1911},"267":{"loc":{"start":{"line":1912,"column":8},"end":{"line":1912,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1912,"column":8},"end":{"line":1912,"column":16}},{"start":{"line":1912,"column":16},"end":{"line":1912,"column":null}}],"line":1912},"268":{"loc":{"start":{"line":1914,"column":4},"end":{"line":1920,"column":null}},"type":"if","locations":[{"start":{"line":1914,"column":4},"end":{"line":1920,"column":null}},{"start":{},"end":{}}],"line":1914},"269":{"loc":{"start":{"line":1914,"column":8},"end":{"line":1914,"column":43}},"type":"binary-expr","locations":[{"start":{"line":1914,"column":8},"end":{"line":1914,"column":17}},{"start":{"line":1914,"column":17},"end":{"line":1914,"column":43}}],"line":1914},"270":{"loc":{"start":{"line":1923,"column":36},"end":{"line":1923,"column":65}},"type":"binary-expr","locations":[{"start":{"line":1923,"column":36},"end":{"line":1923,"column":47}},{"start":{"line":1923,"column":47},"end":{"line":1923,"column":65}}],"line":1923},"271":{"loc":{"start":{"line":1934,"column":19},"end":{"line":1934,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1934,"column":44},"end":{"line":1934,"column":62}},{"start":{"line":1934,"column":62},"end":{"line":1934,"column":null}}],"line":1934},"272":{"loc":{"start":{"line":1942,"column":17},"end":{"line":1942,"column":32}},"type":"binary-expr","locations":[{"start":{"line":1942,"column":17},"end":{"line":1942,"column":30}},{"start":{"line":1942,"column":30},"end":{"line":1942,"column":32}}],"line":1942},"273":{"loc":{"start":{"line":1956,"column":24},"end":{"line":1958,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1957,"column":10},"end":{"line":1957,"column":null}},{"start":{"line":1958,"column":10},"end":{"line":1958,"column":null}}],"line":1956},"274":{"loc":{"start":{"line":1959,"column":24},"end":{"line":1961,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1960,"column":10},"end":{"line":1960,"column":null}},{"start":{"line":1961,"column":10},"end":{"line":1961,"column":null}}],"line":1959},"275":{"loc":{"start":{"line":1962,"column":23},"end":{"line":1964,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1963,"column":10},"end":{"line":1963,"column":null}},{"start":{"line":1964,"column":10},"end":{"line":1964,"column":null}}],"line":1962},"276":{"loc":{"start":{"line":1967,"column":8},"end":{"line":1969,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1967,"column":8},"end":{"line":1967,"column":null}},{"start":{"line":1968,"column":8},"end":{"line":1968,"column":null}},{"start":{"line":1969,"column":8},"end":{"line":1969,"column":null}}],"line":1967},"277":{"loc":{"start":{"line":1976,"column":16},"end":{"line":1976,"column":null}},"type":"binary-expr","locations":[{"start":{"line":1976,"column":16},"end":{"line":1976,"column":26}},{"start":{"line":1976,"column":26},"end":{"line":1976,"column":null}}],"line":1976},"278":{"loc":{"start":{"line":1995,"column":14},"end":{"line":2001,"column":null}},"type":"cond-expr","locations":[{"start":{"line":1996,"column":12},"end":{"line":2000,"column":null}},{"start":{"line":2001,"column":12},"end":{"line":2001,"column":null}}],"line":1995},"279":{"loc":{"start":{"line":2003,"column":10},"end":{"line":2007,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2004,"column":14},"end":{"line":2006,"column":null}},{"start":{"line":2007,"column":14},"end":{"line":2007,"column":null}}],"line":2003},"280":{"loc":{"start":{"line":2011,"column":8},"end":{"line":2011,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2011,"column":56},"end":{"line":2011,"column":66}},{"start":{"line":2011,"column":66},"end":{"line":2011,"column":null}}],"line":2011},"281":{"loc":{"start":{"line":2011,"column":8},"end":{"line":2011,"column":56}},"type":"binary-expr","locations":[{"start":{"line":2011,"column":8},"end":{"line":2011,"column":34}},{"start":{"line":2011,"column":34},"end":{"line":2011,"column":56}}],"line":2011},"282":{"loc":{"start":{"line":2027,"column":6},"end":{"line":2027,"column":null}},"type":"default-arg","locations":[{"start":{"line":2027,"column":16},"end":{"line":2027,"column":null}}],"line":2027},"283":{"loc":{"start":{"line":2029,"column":6},"end":{"line":2029,"column":null}},"type":"default-arg","locations":[{"start":{"line":2029,"column":16},"end":{"line":2029,"column":null}}],"line":2029},"284":{"loc":{"start":{"line":2030,"column":8},"end":{"line":2030,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2030,"column":8},"end":{"line":2030,"column":16}},{"start":{"line":2030,"column":16},"end":{"line":2030,"column":null}}],"line":2030},"285":{"loc":{"start":{"line":2032,"column":4},"end":{"line":2038,"column":null}},"type":"if","locations":[{"start":{"line":2032,"column":4},"end":{"line":2038,"column":null}},{"start":{},"end":{}}],"line":2032},"286":{"loc":{"start":{"line":2032,"column":8},"end":{"line":2032,"column":36}},"type":"binary-expr","locations":[{"start":{"line":2032,"column":8},"end":{"line":2032,"column":19}},{"start":{"line":2032,"column":19},"end":{"line":2032,"column":29}},{"start":{"line":2032,"column":29},"end":{"line":2032,"column":36}}],"line":2032},"287":{"loc":{"start":{"line":2043,"column":6},"end":{"line":2050,"column":null}},"type":"if","locations":[{"start":{"line":2043,"column":6},"end":{"line":2050,"column":null}},{"start":{},"end":{}}],"line":2043},"288":{"loc":{"start":{"line":2053,"column":27},"end":{"line":2055,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2054,"column":10},"end":{"line":2054,"column":null}},{"start":{"line":2055,"column":10},"end":{"line":2055,"column":null}}],"line":2053},"289":{"loc":{"start":{"line":2058,"column":8},"end":{"line":2063,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2062,"column":12},"end":{"line":2062,"column":null}},{"start":{"line":2063,"column":12},"end":{"line":2063,"column":null}}],"line":2058},"290":{"loc":{"start":{"line":2058,"column":8},"end":{"line":2061,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2058,"column":8},"end":{"line":2058,"column":null}},{"start":{"line":2059,"column":8},"end":{"line":2059,"column":null}},{"start":{"line":2060,"column":8},"end":{"line":2060,"column":null}},{"start":{"line":2061,"column":8},"end":{"line":2061,"column":null}}],"line":2058},"291":{"loc":{"start":{"line":2073,"column":8},"end":{"line":2084,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2074,"column":12},"end":{"line":2083,"column":null}},{"start":{"line":2084,"column":12},"end":{"line":2084,"column":null}}],"line":2073},"292":{"loc":{"start":{"line":2073,"column":8},"end":{"line":2073,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2073,"column":8},"end":{"line":2073,"column":40}},{"start":{"line":2073,"column":40},"end":{"line":2073,"column":null}}],"line":2073},"293":{"loc":{"start":{"line":2081,"column":18},"end":{"line":2082,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2081,"column":18},"end":{"line":2081,"column":null}},{"start":{"line":2082,"column":18},"end":{"line":2082,"column":null}}],"line":2081},"294":{"loc":{"start":{"line":2087,"column":8},"end":{"line":2098,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2088,"column":12},"end":{"line":2097,"column":null}},{"start":{"line":2098,"column":12},"end":{"line":2098,"column":null}}],"line":2087},"295":{"loc":{"start":{"line":2087,"column":8},"end":{"line":2087,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2087,"column":8},"end":{"line":2087,"column":40}},{"start":{"line":2087,"column":40},"end":{"line":2087,"column":null}}],"line":2087},"296":{"loc":{"start":{"line":2095,"column":18},"end":{"line":2096,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2095,"column":18},"end":{"line":2095,"column":null}},{"start":{"line":2096,"column":18},"end":{"line":2096,"column":null}}],"line":2095},"297":{"loc":{"start":{"line":2101,"column":24},"end":{"line":2103,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2102,"column":10},"end":{"line":2102,"column":null}},{"start":{"line":2103,"column":10},"end":{"line":2103,"column":null}}],"line":2101},"298":{"loc":{"start":{"line":2104,"column":24},"end":{"line":2106,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2105,"column":10},"end":{"line":2105,"column":null}},{"start":{"line":2106,"column":10},"end":{"line":2106,"column":null}}],"line":2104},"299":{"loc":{"start":{"line":2113,"column":27},"end":{"line":2113,"column":74}},"type":"binary-expr","locations":[{"start":{"line":2113,"column":27},"end":{"line":2113,"column":51}},{"start":{"line":2113,"column":51},"end":{"line":2113,"column":74}}],"line":2113},"300":{"loc":{"start":{"line":2114,"column":18},"end":{"line":2114,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2114,"column":49},"end":{"line":2114,"column":60}},{"start":{"line":2114,"column":60},"end":{"line":2114,"column":null}}],"line":2114},"301":{"loc":{"start":{"line":2119,"column":19},"end":{"line":2119,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2119,"column":19},"end":{"line":2119,"column":48}},{"start":{"line":2119,"column":48},"end":{"line":2119,"column":null}}],"line":2119},"302":{"loc":{"start":{"line":2147,"column":24},"end":{"line":2147,"column":50}},"type":"binary-expr","locations":[{"start":{"line":2147,"column":24},"end":{"line":2147,"column":48}},{"start":{"line":2147,"column":48},"end":{"line":2147,"column":50}}],"line":2147},"303":{"loc":{"start":{"line":2147,"column":54},"end":{"line":2147,"column":80}},"type":"binary-expr","locations":[{"start":{"line":2147,"column":54},"end":{"line":2147,"column":78}},{"start":{"line":2147,"column":78},"end":{"line":2147,"column":80}}],"line":2147},"304":{"loc":{"start":{"line":2149,"column":33},"end":{"line":2149,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2149,"column":60},"end":{"line":2149,"column":64}},{"start":{"line":2149,"column":64},"end":{"line":2149,"column":null}}],"line":2149},"305":{"loc":{"start":{"line":2157,"column":4},"end":{"line":2159,"column":null}},"type":"if","locations":[{"start":{"line":2157,"column":4},"end":{"line":2159,"column":null}},{"start":{},"end":{}}],"line":2157},"306":{"loc":{"start":{"line":2168,"column":4},"end":{"line":2170,"column":null}},"type":"if","locations":[{"start":{"line":2168,"column":4},"end":{"line":2170,"column":null}},{"start":{},"end":{}}],"line":2168},"307":{"loc":{"start":{"line":2183,"column":4},"end":{"line":2189,"column":null}},"type":"if","locations":[{"start":{"line":2183,"column":4},"end":{"line":2189,"column":null}},{"start":{},"end":{}}],"line":2183},"308":{"loc":{"start":{"line":2185,"column":8},"end":{"line":2187,"column":null}},"type":"if","locations":[{"start":{"line":2185,"column":8},"end":{"line":2187,"column":null}},{"start":{},"end":{}}],"line":2185},"309":{"loc":{"start":{"line":2204,"column":6},"end":{"line":2206,"column":null}},"type":"if","locations":[{"start":{"line":2204,"column":6},"end":{"line":2206,"column":null}},{"start":{},"end":{}}],"line":2204},"310":{"loc":{"start":{"line":2209,"column":27},"end":{"line":2211,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2210,"column":10},"end":{"line":2210,"column":null}},{"start":{"line":2211,"column":10},"end":{"line":2211,"column":null}}],"line":2209},"311":{"loc":{"start":{"line":2231,"column":27},"end":{"line":2231,"column":74}},"type":"binary-expr","locations":[{"start":{"line":2231,"column":27},"end":{"line":2231,"column":51}},{"start":{"line":2231,"column":51},"end":{"line":2231,"column":74}}],"line":2231},"312":{"loc":{"start":{"line":2235,"column":19},"end":{"line":2235,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2235,"column":19},"end":{"line":2235,"column":48}},{"start":{"line":2235,"column":48},"end":{"line":2235,"column":null}}],"line":2235},"313":{"loc":{"start":{"line":2251,"column":4},"end":{"line":2253,"column":null}},"type":"if","locations":[{"start":{"line":2251,"column":4},"end":{"line":2253,"column":null}},{"start":{},"end":{}}],"line":2251},"314":{"loc":{"start":{"line":2256,"column":6},"end":{"line":2256,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2256,"column":6},"end":{"line":2256,"column":30}},{"start":{"line":2256,"column":30},"end":{"line":2256,"column":58}},{"start":{"line":2256,"column":58},"end":{"line":2256,"column":null}}],"line":2256},"315":{"loc":{"start":{"line":2258,"column":4},"end":{"line":2268,"column":null}},"type":"if","locations":[{"start":{"line":2258,"column":4},"end":{"line":2268,"column":null}},{"start":{},"end":{}}],"line":2258},"316":{"loc":{"start":{"line":2266,"column":8},"end":{"line":2266,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2266,"column":8},"end":{"line":2266,"column":37}},{"start":{"line":2266,"column":37},"end":{"line":2266,"column":70}},{"start":{"line":2266,"column":70},"end":{"line":2266,"column":null}}],"line":2266},"317":{"loc":{"start":{"line":2270,"column":4},"end":{"line":2272,"column":null}},"type":"if","locations":[{"start":{"line":2270,"column":4},"end":{"line":2272,"column":null}},{"start":{},"end":{}}],"line":2270},"318":{"loc":{"start":{"line":2275,"column":6},"end":{"line":2275,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2275,"column":6},"end":{"line":2275,"column":35}},{"start":{"line":2275,"column":35},"end":{"line":2275,"column":59}},{"start":{"line":2275,"column":59},"end":{"line":2275,"column":null}}],"line":2275},"319":{"loc":{"start":{"line":2277,"column":27},"end":{"line":2277,"column":68}},"type":"binary-expr","locations":[{"start":{"line":2277,"column":27},"end":{"line":2277,"column":54}},{"start":{"line":2277,"column":54},"end":{"line":2277,"column":68}}],"line":2277},"320":{"loc":{"start":{"line":2294,"column":6},"end":{"line":2296,"column":null}},"type":"if","locations":[{"start":{"line":2294,"column":6},"end":{"line":2296,"column":null}},{"start":{},"end":{}}],"line":2294},"321":{"loc":{"start":{"line":2301,"column":13},"end":{"line":2303,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2302,"column":10},"end":{"line":2302,"column":null}},{"start":{"line":2303,"column":10},"end":{"line":2303,"column":null}}],"line":2301},"322":{"loc":{"start":{"line":2314,"column":4},"end":{"line":2316,"column":null}},"type":"if","locations":[{"start":{"line":2314,"column":4},"end":{"line":2316,"column":null}},{"start":{},"end":{}}],"line":2314},"323":{"loc":{"start":{"line":2331,"column":12},"end":{"line":2331,"column":33}},"type":"binary-expr","locations":[{"start":{"line":2331,"column":12},"end":{"line":2331,"column":29}},{"start":{"line":2331,"column":29},"end":{"line":2331,"column":33}}],"line":2331},"324":{"loc":{"start":{"line":2332,"column":22},"end":{"line":2332,"column":39}},"type":"binary-expr","locations":[{"start":{"line":2332,"column":22},"end":{"line":2332,"column":37}},{"start":{"line":2332,"column":37},"end":{"line":2332,"column":39}}],"line":2332},"325":{"loc":{"start":{"line":2333,"column":22},"end":{"line":2333,"column":46}},"type":"binary-expr","locations":[{"start":{"line":2333,"column":22},"end":{"line":2333,"column":37}},{"start":{"line":2333,"column":37},"end":{"line":2333,"column":46}}],"line":2333},"326":{"loc":{"start":{"line":2334,"column":21},"end":{"line":2334,"column":37}},"type":"binary-expr","locations":[{"start":{"line":2334,"column":21},"end":{"line":2334,"column":35}},{"start":{"line":2334,"column":35},"end":{"line":2334,"column":37}}],"line":2334},"327":{"loc":{"start":{"line":2335,"column":23},"end":{"line":2335,"column":41}},"type":"binary-expr","locations":[{"start":{"line":2335,"column":23},"end":{"line":2335,"column":39}},{"start":{"line":2335,"column":39},"end":{"line":2335,"column":41}}],"line":2335},"328":{"loc":{"start":{"line":2336,"column":20},"end":{"line":2336,"column":43}},"type":"binary-expr","locations":[{"start":{"line":2336,"column":20},"end":{"line":2336,"column":33}},{"start":{"line":2336,"column":33},"end":{"line":2336,"column":43}}],"line":2336},"329":{"loc":{"start":{"line":2344,"column":4},"end":{"line":2346,"column":null}},"type":"if","locations":[{"start":{"line":2344,"column":4},"end":{"line":2346,"column":null}},{"start":{},"end":{}}],"line":2344},"330":{"loc":{"start":{"line":2357,"column":12},"end":{"line":2357,"column":31}},"type":"binary-expr","locations":[{"start":{"line":2357,"column":12},"end":{"line":2357,"column":27}},{"start":{"line":2357,"column":27},"end":{"line":2357,"column":31}}],"line":2357},"331":{"loc":{"start":{"line":2358,"column":17},"end":{"line":2358,"column":29}},"type":"binary-expr","locations":[{"start":{"line":2358,"column":17},"end":{"line":2358,"column":27}},{"start":{"line":2358,"column":27},"end":{"line":2358,"column":29}}],"line":2358},"332":{"loc":{"start":{"line":2359,"column":22},"end":{"line":2359,"column":39}},"type":"binary-expr","locations":[{"start":{"line":2359,"column":22},"end":{"line":2359,"column":37}},{"start":{"line":2359,"column":37},"end":{"line":2359,"column":39}}],"line":2359},"333":{"loc":{"start":{"line":2360,"column":24},"end":{"line":2360,"column":51}},"type":"binary-expr","locations":[{"start":{"line":2360,"column":24},"end":{"line":2360,"column":41}},{"start":{"line":2360,"column":41},"end":{"line":2360,"column":51}}],"line":2360},"334":{"loc":{"start":{"line":2368,"column":4},"end":{"line":2370,"column":null}},"type":"if","locations":[{"start":{"line":2368,"column":4},"end":{"line":2370,"column":null}},{"start":{},"end":{}}],"line":2368},"335":{"loc":{"start":{"line":2381,"column":12},"end":{"line":2381,"column":31}},"type":"binary-expr","locations":[{"start":{"line":2381,"column":12},"end":{"line":2381,"column":27}},{"start":{"line":2381,"column":27},"end":{"line":2381,"column":31}}],"line":2381},"336":{"loc":{"start":{"line":2382,"column":17},"end":{"line":2382,"column":29}},"type":"binary-expr","locations":[{"start":{"line":2382,"column":17},"end":{"line":2382,"column":27}},{"start":{"line":2382,"column":27},"end":{"line":2382,"column":29}}],"line":2382},"337":{"loc":{"start":{"line":2383,"column":22},"end":{"line":2383,"column":39}},"type":"binary-expr","locations":[{"start":{"line":2383,"column":22},"end":{"line":2383,"column":37}},{"start":{"line":2383,"column":37},"end":{"line":2383,"column":39}}],"line":2383},"338":{"loc":{"start":{"line":2384,"column":25},"end":{"line":2384,"column":44}},"type":"binary-expr","locations":[{"start":{"line":2384,"column":25},"end":{"line":2384,"column":43}},{"start":{"line":2384,"column":43},"end":{"line":2384,"column":44}}],"line":2384},"339":{"loc":{"start":{"line":2396,"column":4},"end":{"line":2402,"column":null}},"type":"if","locations":[{"start":{"line":2396,"column":4},"end":{"line":2402,"column":null}},{"start":{"line":2399,"column":11},"end":{"line":2402,"column":null}}],"line":2396},"340":{"loc":{"start":{"line":2413,"column":12},"end":{"line":2413,"column":31}},"type":"binary-expr","locations":[{"start":{"line":2413,"column":12},"end":{"line":2413,"column":27}},{"start":{"line":2413,"column":27},"end":{"line":2413,"column":31}}],"line":2413},"341":{"loc":{"start":{"line":2414,"column":17},"end":{"line":2414,"column":29}},"type":"binary-expr","locations":[{"start":{"line":2414,"column":17},"end":{"line":2414,"column":27}},{"start":{"line":2414,"column":27},"end":{"line":2414,"column":29}}],"line":2414},"342":{"loc":{"start":{"line":2415,"column":19},"end":{"line":2415,"column":44}},"type":"binary-expr","locations":[{"start":{"line":2415,"column":19},"end":{"line":2415,"column":31}},{"start":{"line":2415,"column":31},"end":{"line":2415,"column":44}}],"line":2415},"343":{"loc":{"start":{"line":2416,"column":22},"end":{"line":2416,"column":39}},"type":"binary-expr","locations":[{"start":{"line":2416,"column":22},"end":{"line":2416,"column":37}},{"start":{"line":2416,"column":37},"end":{"line":2416,"column":39}}],"line":2416},"344":{"loc":{"start":{"line":2417,"column":24},"end":{"line":2417,"column":51}},"type":"binary-expr","locations":[{"start":{"line":2417,"column":24},"end":{"line":2417,"column":41}},{"start":{"line":2417,"column":41},"end":{"line":2417,"column":51}}],"line":2417},"345":{"loc":{"start":{"line":2425,"column":4},"end":{"line":2427,"column":null}},"type":"if","locations":[{"start":{"line":2425,"column":4},"end":{"line":2427,"column":null}},{"start":{},"end":{}}],"line":2425},"346":{"loc":{"start":{"line":2430,"column":6},"end":{"line":2433,"column":null}},"type":"if","locations":[{"start":{"line":2430,"column":6},"end":{"line":2433,"column":null}},{"start":{},"end":{}}],"line":2430},"347":{"loc":{"start":{"line":2430,"column":10},"end":{"line":2430,"column":74}},"type":"binary-expr","locations":[{"start":{"line":2430,"column":10},"end":{"line":2430,"column":45}},{"start":{"line":2430,"column":45},"end":{"line":2430,"column":74}}],"line":2430},"348":{"loc":{"start":{"line":2434,"column":6},"end":{"line":2437,"column":null}},"type":"if","locations":[{"start":{"line":2434,"column":6},"end":{"line":2437,"column":null}},{"start":{},"end":{}}],"line":2434},"349":{"loc":{"start":{"line":2434,"column":10},"end":{"line":2434,"column":70}},"type":"binary-expr","locations":[{"start":{"line":2434,"column":10},"end":{"line":2434,"column":43}},{"start":{"line":2434,"column":43},"end":{"line":2434,"column":70}}],"line":2434},"350":{"loc":{"start":{"line":2438,"column":6},"end":{"line":2441,"column":null}},"type":"if","locations":[{"start":{"line":2438,"column":6},"end":{"line":2441,"column":null}},{"start":{},"end":{}}],"line":2438},"351":{"loc":{"start":{"line":2438,"column":10},"end":{"line":2438,"column":70}},"type":"binary-expr","locations":[{"start":{"line":2438,"column":10},"end":{"line":2438,"column":43}},{"start":{"line":2438,"column":43},"end":{"line":2438,"column":70}}],"line":2438},"352":{"loc":{"start":{"line":2442,"column":6},"end":{"line":2445,"column":null}},"type":"if","locations":[{"start":{"line":2442,"column":6},"end":{"line":2445,"column":null}},{"start":{},"end":{}}],"line":2442},"353":{"loc":{"start":{"line":2442,"column":10},"end":{"line":2442,"column":68}},"type":"binary-expr","locations":[{"start":{"line":2442,"column":10},"end":{"line":2442,"column":42}},{"start":{"line":2442,"column":42},"end":{"line":2442,"column":68}}],"line":2442},"354":{"loc":{"start":{"line":2446,"column":6},"end":{"line":2453,"column":null}},"type":"if","locations":[{"start":{"line":2446,"column":6},"end":{"line":2453,"column":null}},{"start":{},"end":{}}],"line":2446},"355":{"loc":{"start":{"line":2448,"column":10},"end":{"line":2451,"column":null}},"type":"if","locations":[{"start":{"line":2448,"column":10},"end":{"line":2451,"column":null}},{"start":{},"end":{}}],"line":2448},"356":{"loc":{"start":{"line":2448,"column":14},"end":{"line":2448,"column":75}},"type":"binary-expr","locations":[{"start":{"line":2448,"column":14},"end":{"line":2448,"column":49}},{"start":{"line":2448,"column":49},"end":{"line":2448,"column":75}}],"line":2448},"357":{"loc":{"start":{"line":2459,"column":11},"end":{"line":2459,"column":46}},"type":"binary-expr","locations":[{"start":{"line":2459,"column":11},"end":{"line":2459,"column":33}},{"start":{"line":2459,"column":33},"end":{"line":2459,"column":46}}],"line":2459},"358":{"loc":{"start":{"line":2461,"column":6},"end":{"line":2463,"column":null}},"type":"if","locations":[{"start":{"line":2461,"column":6},"end":{"line":2463,"column":null}},{"start":{},"end":{}}],"line":2461},"359":{"loc":{"start":{"line":2479,"column":27},"end":{"line":2479,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2479,"column":40},"end":{"line":2479,"column":61}},{"start":{"line":2479,"column":61},"end":{"line":2479,"column":null}}],"line":2479},"360":{"loc":{"start":{"line":2480,"column":29},"end":{"line":2480,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2480,"column":44},"end":{"line":2480,"column":67}},{"start":{"line":2480,"column":67},"end":{"line":2480,"column":null}}],"line":2480},"361":{"loc":{"start":{"line":2482,"column":4},"end":{"line":2487,"column":null}},"type":"if","locations":[{"start":{"line":2482,"column":4},"end":{"line":2487,"column":null}},{"start":{},"end":{}}],"line":2482},"362":{"loc":{"start":{"line":2484,"column":6},"end":{"line":2486,"column":null}},"type":"if","locations":[{"start":{"line":2484,"column":6},"end":{"line":2486,"column":null}},{"start":{},"end":{}}],"line":2484},"363":{"loc":{"start":{"line":2489,"column":4},"end":{"line":2517,"column":null}},"type":"if","locations":[{"start":{"line":2489,"column":4},"end":{"line":2517,"column":null}},{"start":{},"end":{}}],"line":2489},"364":{"loc":{"start":{"line":2489,"column":8},"end":{"line":2489,"column":44}},"type":"binary-expr","locations":[{"start":{"line":2489,"column":8},"end":{"line":2489,"column":28}},{"start":{"line":2489,"column":28},"end":{"line":2489,"column":44}}],"line":2489},"365":{"loc":{"start":{"line":2494,"column":12},"end":{"line":2494,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2494,"column":12},"end":{"line":2494,"column":41}},{"start":{"line":2494,"column":41},"end":{"line":2494,"column":74}},{"start":{"line":2494,"column":74},"end":{"line":2494,"column":null}}],"line":2494},"366":{"loc":{"start":{"line":2497,"column":12},"end":{"line":2499,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2497,"column":12},"end":{"line":2497,"column":null}},{"start":{"line":2498,"column":12},"end":{"line":2498,"column":null}},{"start":{"line":2499,"column":12},"end":{"line":2499,"column":null}}],"line":2497},"367":{"loc":{"start":{"line":2503,"column":6},"end":{"line":2516,"column":null}},"type":"if","locations":[{"start":{"line":2503,"column":6},"end":{"line":2516,"column":null}},{"start":{},"end":{}}],"line":2503},"368":{"loc":{"start":{"line":2509,"column":10},"end":{"line":2509,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2509,"column":10},"end":{"line":2509,"column":47}},{"start":{"line":2509,"column":47},"end":{"line":2509,"column":null}}],"line":2509},"369":{"loc":{"start":{"line":2513,"column":8},"end":{"line":2515,"column":null}},"type":"if","locations":[{"start":{"line":2513,"column":8},"end":{"line":2515,"column":null}},{"start":{},"end":{}}],"line":2513},"370":{"loc":{"start":{"line":2519,"column":4},"end":{"line":2533,"column":null}},"type":"if","locations":[{"start":{"line":2519,"column":4},"end":{"line":2533,"column":null}},{"start":{},"end":{}}],"line":2519},"371":{"loc":{"start":{"line":2520,"column":25},"end":{"line":2520,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2520,"column":25},"end":{"line":2520,"column":62}},{"start":{"line":2520,"column":62},"end":{"line":2520,"column":null}}],"line":2520},"372":{"loc":{"start":{"line":2526,"column":28},"end":{"line":2526,"column":78}},"type":"binary-expr","locations":[{"start":{"line":2526,"column":28},"end":{"line":2526,"column":52}},{"start":{"line":2526,"column":52},"end":{"line":2526,"column":76}},{"start":{"line":2526,"column":76},"end":{"line":2526,"column":78}}],"line":2526},"373":{"loc":{"start":{"line":2527,"column":15},"end":{"line":2527,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2527,"column":15},"end":{"line":2527,"column":38}},{"start":{"line":2527,"column":38},"end":{"line":2527,"column":null}}],"line":2527},"374":{"loc":{"start":{"line":2530,"column":6},"end":{"line":2532,"column":null}},"type":"if","locations":[{"start":{"line":2530,"column":6},"end":{"line":2532,"column":null}},{"start":{},"end":{}}],"line":2530},"375":{"loc":{"start":{"line":2535,"column":4},"end":{"line":2540,"column":null}},"type":"if","locations":[{"start":{"line":2535,"column":4},"end":{"line":2540,"column":null}},{"start":{},"end":{}}],"line":2535},"376":{"loc":{"start":{"line":2537,"column":6},"end":{"line":2539,"column":null}},"type":"if","locations":[{"start":{"line":2537,"column":6},"end":{"line":2539,"column":null}},{"start":{},"end":{}}],"line":2537},"377":{"loc":{"start":{"line":2542,"column":4},"end":{"line":2558,"column":null}},"type":"if","locations":[{"start":{"line":2542,"column":4},"end":{"line":2558,"column":null}},{"start":{},"end":{}}],"line":2542},"378":{"loc":{"start":{"line":2547,"column":12},"end":{"line":2547,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2547,"column":12},"end":{"line":2547,"column":41}},{"start":{"line":2547,"column":41},"end":{"line":2547,"column":74}},{"start":{"line":2547,"column":74},"end":{"line":2547,"column":null}}],"line":2547},"379":{"loc":{"start":{"line":2550,"column":12},"end":{"line":2552,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2550,"column":12},"end":{"line":2550,"column":null}},{"start":{"line":2551,"column":12},"end":{"line":2551,"column":null}},{"start":{"line":2552,"column":12},"end":{"line":2552,"column":null}}],"line":2550},"380":{"loc":{"start":{"line":2555,"column":6},"end":{"line":2557,"column":null}},"type":"if","locations":[{"start":{"line":2555,"column":6},"end":{"line":2557,"column":null}},{"start":{},"end":{}}],"line":2555},"381":{"loc":{"start":{"line":2568,"column":4},"end":{"line":2570,"column":null}},"type":"if","locations":[{"start":{"line":2568,"column":4},"end":{"line":2570,"column":null}},{"start":{},"end":{}}],"line":2568},"382":{"loc":{"start":{"line":2579,"column":4},"end":{"line":2581,"column":null}},"type":"if","locations":[{"start":{"line":2579,"column":4},"end":{"line":2581,"column":null}},{"start":{},"end":{}}],"line":2579},"383":{"loc":{"start":{"line":2595,"column":6},"end":{"line":2595,"column":null}},"type":"default-arg","locations":[{"start":{"line":2595,"column":20},"end":{"line":2595,"column":null}}],"line":2595},"384":{"loc":{"start":{"line":2596,"column":6},"end":{"line":2596,"column":null}},"type":"default-arg","locations":[{"start":{"line":2596,"column":17},"end":{"line":2596,"column":null}}],"line":2596},"385":{"loc":{"start":{"line":2597,"column":6},"end":{"line":2597,"column":null}},"type":"default-arg","locations":[{"start":{"line":2597,"column":16},"end":{"line":2597,"column":null}}],"line":2597},"386":{"loc":{"start":{"line":2598,"column":8},"end":{"line":2598,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2598,"column":8},"end":{"line":2598,"column":16}},{"start":{"line":2598,"column":16},"end":{"line":2598,"column":null}}],"line":2598},"387":{"loc":{"start":{"line":2600,"column":4},"end":{"line":2607,"column":null}},"type":"if","locations":[{"start":{"line":2600,"column":4},"end":{"line":2607,"column":null}},{"start":{},"end":{}}],"line":2600},"388":{"loc":{"start":{"line":2600,"column":8},"end":{"line":2600,"column":61}},"type":"binary-expr","locations":[{"start":{"line":2600,"column":8},"end":{"line":2600,"column":26}},{"start":{"line":2600,"column":26},"end":{"line":2600,"column":61}}],"line":2600},"389":{"loc":{"start":{"line":2610,"column":4},"end":{"line":2617,"column":null}},"type":"if","locations":[{"start":{"line":2610,"column":4},"end":{"line":2617,"column":null}},{"start":{},"end":{}}],"line":2610},"390":{"loc":{"start":{"line":2624,"column":6},"end":{"line":2624,"column":null}},"type":"if","locations":[{"start":{"line":2624,"column":6},"end":{"line":2624,"column":null}},{"start":{},"end":{}}],"line":2624},"391":{"loc":{"start":{"line":2625,"column":6},"end":{"line":2625,"column":null}},"type":"if","locations":[{"start":{"line":2625,"column":6},"end":{"line":2625,"column":null}},{"start":{},"end":{}}],"line":2625},"392":{"loc":{"start":{"line":2631,"column":8},"end":{"line":2643,"column":null}},"type":"if","locations":[{"start":{"line":2631,"column":8},"end":{"line":2643,"column":null}},{"start":{},"end":{}}],"line":2631},"393":{"loc":{"start":{"line":2644,"column":20},"end":{"line":2644,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2644,"column":20},"end":{"line":2644,"column":53}},{"start":{"line":2644,"column":53},"end":{"line":2644,"column":70}},{"start":{"line":2644,"column":70},"end":{"line":2644,"column":null}}],"line":2644},"394":{"loc":{"start":{"line":2648,"column":31},"end":{"line":2648,"column":51}},"type":"binary-expr","locations":[{"start":{"line":2648,"column":31},"end":{"line":2648,"column":48}},{"start":{"line":2648,"column":48},"end":{"line":2648,"column":51}}],"line":2648},"395":{"loc":{"start":{"line":2648,"column":66},"end":{"line":2648,"column":86}},"type":"binary-expr","locations":[{"start":{"line":2648,"column":66},"end":{"line":2648,"column":83}},{"start":{"line":2648,"column":83},"end":{"line":2648,"column":86}}],"line":2648},"396":{"loc":{"start":{"line":2671,"column":6},"end":{"line":2671,"column":null}},"type":"if","locations":[{"start":{"line":2671,"column":6},"end":{"line":2671,"column":null}},{"start":{},"end":{}}],"line":2671},"397":{"loc":{"start":{"line":2672,"column":6},"end":{"line":2672,"column":null}},"type":"if","locations":[{"start":{"line":2672,"column":6},"end":{"line":2672,"column":null}},{"start":{},"end":{}}],"line":2672},"398":{"loc":{"start":{"line":2677,"column":8},"end":{"line":2689,"column":null}},"type":"if","locations":[{"start":{"line":2677,"column":8},"end":{"line":2689,"column":null}},{"start":{"line":2683,"column":15},"end":{"line":2689,"column":null}}],"line":2677},"399":{"loc":{"start":{"line":2704,"column":6},"end":{"line":2730,"column":null}},"type":"if","locations":[{"start":{"line":2704,"column":6},"end":{"line":2730,"column":null}},{"start":{"line":2724,"column":13},"end":{"line":2730,"column":null}}],"line":2704},"400":{"loc":{"start":{"line":2734,"column":12},"end":{"line":2734,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2734,"column":24},"end":{"line":2734,"column":40}},{"start":{"line":2734,"column":40},"end":{"line":2734,"column":null}}],"line":2734},"401":{"loc":{"start":{"line":2735,"column":12},"end":{"line":2735,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2735,"column":24},"end":{"line":2735,"column":40}},{"start":{"line":2735,"column":40},"end":{"line":2735,"column":null}}],"line":2735},"402":{"loc":{"start":{"line":2754,"column":8},"end":{"line":2754,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2754,"column":33},"end":{"line":2754,"column":49}},{"start":{"line":2754,"column":49},"end":{"line":2754,"column":null}}],"line":2754},"403":{"loc":{"start":{"line":2768,"column":6},"end":{"line":2768,"column":null}},"type":"default-arg","locations":[{"start":{"line":2768,"column":15},"end":{"line":2768,"column":null}}],"line":2768},"404":{"loc":{"start":{"line":2769,"column":6},"end":{"line":2769,"column":null}},"type":"default-arg","locations":[{"start":{"line":2769,"column":18},"end":{"line":2769,"column":null}}],"line":2769},"405":{"loc":{"start":{"line":2770,"column":6},"end":{"line":2770,"column":null}},"type":"default-arg","locations":[{"start":{"line":2770,"column":16},"end":{"line":2770,"column":null}}],"line":2770},"406":{"loc":{"start":{"line":2771,"column":8},"end":{"line":2771,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2771,"column":8},"end":{"line":2771,"column":16}},{"start":{"line":2771,"column":16},"end":{"line":2771,"column":null}}],"line":2771},"407":{"loc":{"start":{"line":2775,"column":4},"end":{"line":2780,"column":null}},"type":"if","locations":[{"start":{"line":2775,"column":4},"end":{"line":2780,"column":null}},{"start":{"line":2777,"column":11},"end":{"line":2780,"column":null}}],"line":2775},"408":{"loc":{"start":{"line":2775,"column":8},"end":{"line":2775,"column":54}},"type":"binary-expr","locations":[{"start":{"line":2775,"column":8},"end":{"line":2775,"column":22}},{"start":{"line":2775,"column":22},"end":{"line":2775,"column":54}}],"line":2775},"409":{"loc":{"start":{"line":2782,"column":4},"end":{"line":2789,"column":null}},"type":"if","locations":[{"start":{"line":2782,"column":4},"end":{"line":2789,"column":null}},{"start":{},"end":{}}],"line":2782},"410":{"loc":{"start":{"line":2796,"column":4},"end":{"line":2807,"column":null}},"type":"if","locations":[{"start":{"line":2796,"column":4},"end":{"line":2807,"column":null}},{"start":{},"end":{}}],"line":2796},"411":{"loc":{"start":{"line":2796,"column":8},"end":{"line":2796,"column":58}},"type":"binary-expr","locations":[{"start":{"line":2796,"column":8},"end":{"line":2796,"column":35}},{"start":{"line":2796,"column":35},"end":{"line":2796,"column":49}},{"start":{"line":2796,"column":49},"end":{"line":2796,"column":58}}],"line":2796},"412":{"loc":{"start":{"line":2811,"column":23},"end":{"line":2811,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2811,"column":23},"end":{"line":2811,"column":43}},{"start":{"line":2811,"column":43},"end":{"line":2811,"column":null}}],"line":2811},"413":{"loc":{"start":{"line":2813,"column":27},"end":{"line":2815,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2814,"column":10},"end":{"line":2814,"column":null}},{"start":{"line":2815,"column":10},"end":{"line":2815,"column":null}}],"line":2813},"414":{"loc":{"start":{"line":2817,"column":19},"end":{"line":2817,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2817,"column":19},"end":{"line":2817,"column":39}},{"start":{"line":2817,"column":39},"end":{"line":2817,"column":56}},{"start":{"line":2817,"column":56},"end":{"line":2817,"column":null}}],"line":2817},"415":{"loc":{"start":{"line":2818,"column":26},"end":{"line":2818,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2818,"column":26},"end":{"line":2818,"column":50}},{"start":{"line":2818,"column":50},"end":{"line":2818,"column":null}}],"line":2818},"416":{"loc":{"start":{"line":2820,"column":12},"end":{"line":2820,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2820,"column":12},"end":{"line":2820,"column":37}},{"start":{"line":2820,"column":37},"end":{"line":2820,"column":null}}],"line":2820},"417":{"loc":{"start":{"line":2821,"column":12},"end":{"line":2821,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2821,"column":12},"end":{"line":2821,"column":40}},{"start":{"line":2821,"column":40},"end":{"line":2821,"column":null}}],"line":2821},"418":{"loc":{"start":{"line":2827,"column":8},"end":{"line":2828,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2827,"column":8},"end":{"line":2827,"column":null}},{"start":{"line":2828,"column":8},"end":{"line":2828,"column":null}}],"line":2827},"419":{"loc":{"start":{"line":2830,"column":8},"end":{"line":2830,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2830,"column":8},"end":{"line":2830,"column":21}},{"start":{"line":2830,"column":21},"end":{"line":2830,"column":null}}],"line":2830},"420":{"loc":{"start":{"line":2832,"column":8},"end":{"line":2834,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2832,"column":8},"end":{"line":2832,"column":null}},{"start":{"line":2833,"column":8},"end":{"line":2833,"column":null}},{"start":{"line":2834,"column":8},"end":{"line":2834,"column":null}}],"line":2832},"421":{"loc":{"start":{"line":2838,"column":8},"end":{"line":2839,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2838,"column":8},"end":{"line":2838,"column":null}},{"start":{"line":2839,"column":8},"end":{"line":2839,"column":null}}],"line":2838},"422":{"loc":{"start":{"line":2843,"column":8},"end":{"line":2844,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2843,"column":8},"end":{"line":2843,"column":null}},{"start":{"line":2844,"column":8},"end":{"line":2844,"column":null}}],"line":2843},"423":{"loc":{"start":{"line":2846,"column":6},"end":{"line":2847,"column":null}},"type":"if","locations":[{"start":{"line":2846,"column":6},"end":{"line":2847,"column":null}},{"start":{"line":2846,"column":47},"end":{"line":2847,"column":null}}],"line":2846},"424":{"loc":{"start":{"line":2846,"column":47},"end":{"line":2847,"column":null}},"type":"if","locations":[{"start":{"line":2846,"column":47},"end":{"line":2847,"column":null}},{"start":{},"end":{}}],"line":2846},"425":{"loc":{"start":{"line":2848,"column":6},"end":{"line":2848,"column":null}},"type":"if","locations":[{"start":{"line":2848,"column":6},"end":{"line":2848,"column":null}},{"start":{},"end":{}}],"line":2848},"426":{"loc":{"start":{"line":2849,"column":6},"end":{"line":2849,"column":null}},"type":"if","locations":[{"start":{"line":2849,"column":6},"end":{"line":2849,"column":null}},{"start":{},"end":{}}],"line":2849},"427":{"loc":{"start":{"line":2850,"column":6},"end":{"line":2850,"column":null}},"type":"if","locations":[{"start":{"line":2850,"column":6},"end":{"line":2850,"column":null}},{"start":{},"end":{}}],"line":2850},"428":{"loc":{"start":{"line":2851,"column":6},"end":{"line":2851,"column":null}},"type":"if","locations":[{"start":{"line":2851,"column":6},"end":{"line":2851,"column":null}},{"start":{},"end":{}}],"line":2851},"429":{"loc":{"start":{"line":2852,"column":6},"end":{"line":2853,"column":null}},"type":"if","locations":[{"start":{"line":2852,"column":6},"end":{"line":2853,"column":null}},{"start":{"line":2852,"column":40},"end":{"line":2853,"column":null}}],"line":2852},"430":{"loc":{"start":{"line":2852,"column":40},"end":{"line":2853,"column":null}},"type":"if","locations":[{"start":{"line":2852,"column":40},"end":{"line":2853,"column":null}},{"start":{},"end":{}}],"line":2852},"431":{"loc":{"start":{"line":2854,"column":6},"end":{"line":2854,"column":null}},"type":"if","locations":[{"start":{"line":2854,"column":6},"end":{"line":2854,"column":null}},{"start":{},"end":{}}],"line":2854},"432":{"loc":{"start":{"line":2857,"column":22},"end":{"line":2862,"column":null}},"type":"cond-expr","locations":[{"start":{"line":2858,"column":10},"end":{"line":2861,"column":null}},{"start":{"line":2862,"column":10},"end":{"line":2862,"column":null}}],"line":2857},"433":{"loc":{"start":{"line":2867,"column":8},"end":{"line":2869,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2867,"column":8},"end":{"line":2869,"column":13}},{"start":{"line":2869,"column":13},"end":{"line":2869,"column":null}}],"line":2867},"434":{"loc":{"start":{"line":2874,"column":6},"end":{"line":2884,"column":null}},"type":"if","locations":[{"start":{"line":2874,"column":6},"end":{"line":2884,"column":null}},{"start":{},"end":{}}],"line":2874},"435":{"loc":{"start":{"line":2888,"column":8},"end":{"line":2890,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2888,"column":8},"end":{"line":2888,"column":null}},{"start":{"line":2889,"column":8},"end":{"line":2889,"column":null}},{"start":{"line":2890,"column":8},"end":{"line":2890,"column":null}}],"line":2888},"436":{"loc":{"start":{"line":2894,"column":6},"end":{"line":2896,"column":null}},"type":"if","locations":[{"start":{"line":2894,"column":6},"end":{"line":2896,"column":null}},{"start":{},"end":{}}],"line":2894},"437":{"loc":{"start":{"line":2904,"column":6},"end":{"line":2913,"column":null}},"type":"if","locations":[{"start":{"line":2904,"column":6},"end":{"line":2913,"column":null}},{"start":{},"end":{}}],"line":2904},"438":{"loc":{"start":{"line":2908,"column":8},"end":{"line":2912,"column":null}},"type":"if","locations":[{"start":{"line":2908,"column":8},"end":{"line":2912,"column":null}},{"start":{},"end":{}}],"line":2908},"439":{"loc":{"start":{"line":2914,"column":6},"end":{"line":2916,"column":null}},"type":"if","locations":[{"start":{"line":2914,"column":6},"end":{"line":2916,"column":null}},{"start":{},"end":{}}],"line":2914},"440":{"loc":{"start":{"line":2918,"column":6},"end":{"line":2939,"column":null}},"type":"if","locations":[{"start":{"line":2918,"column":6},"end":{"line":2939,"column":null}},{"start":{"line":2930,"column":13},"end":{"line":2939,"column":null}}],"line":2918},"441":{"loc":{"start":{"line":2975,"column":6},"end":{"line":2986,"column":null}},"type":"if","locations":[{"start":{"line":2975,"column":6},"end":{"line":2986,"column":null}},{"start":{},"end":{}}],"line":2975},"442":{"loc":{"start":{"line":2990,"column":6},"end":{"line":2992,"column":null}},"type":"if","locations":[{"start":{"line":2990,"column":6},"end":{"line":2992,"column":null}},{"start":{},"end":{}}],"line":2990},"443":{"loc":{"start":{"line":3001,"column":23},"end":{"line":3001,"column":null}},"type":"binary-expr","locations":[{"start":{"line":3001,"column":23},"end":{"line":3001,"column":36}},{"start":{"line":3001,"column":36},"end":{"line":3001,"column":null}}],"line":3001},"444":{"loc":{"start":{"line":3010,"column":8},"end":{"line":3010,"column":null}},"type":"cond-expr","locations":[{"start":{"line":3010,"column":33},"end":{"line":3010,"column":49}},{"start":{"line":3010,"column":49},"end":{"line":3010,"column":null}}],"line":3010}},"s":{"0":57,"1":57,"2":57,"3":57,"4":57,"5":57,"6":57,"7":57,"8":57,"9":57,"10":57,"11":57,"12":57,"13":57,"14":57,"15":57,"16":57,"17":57,"18":4,"19":4,"20":4,"21":4,"22":4,"23":4,"24":1,"25":1,"26":3,"27":1,"28":1,"29":0,"30":1,"31":1,"32":1,"33":2,"34":2,"35":2,"36":4,"37":0,"38":4,"39":4,"40":0,"41":3,"42":3,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":0,"60":0,"61":1,"62":1,"63":1,"64":6,"65":3,"66":3,"67":3,"68":3,"69":3,"70":3,"71":0,"72":3,"73":1,"74":2,"75":3,"76":3,"77":1,"78":1,"79":1,"80":2,"81":0,"82":1,"83":1,"84":1,"85":1,"86":0,"87":0,"88":0,"89":0,"90":1,"91":0,"92":0,"93":0,"94":0,"95":0,"96":1,"97":1,"98":1,"99":1,"100":2,"101":2,"102":0,"103":2,"104":0,"105":0,"106":0,"107":2,"108":1,"109":1,"110":1,"111":2,"112":1,"113":1,"114":2,"115":2,"116":2,"117":2,"118":2,"119":2,"120":0,"121":2,"122":2,"123":2,"124":2,"125":2,"126":2,"127":2,"128":1,"129":1,"130":1,"131":1,"132":1,"133":1,"134":1,"135":1,"136":0,"137":1,"138":1,"139":1,"140":1,"141":1,"142":0,"143":1,"144":1,"145":2,"146":0,"147":2,"148":2,"149":2,"150":2,"151":2,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":2,"163":2,"164":2,"165":1,"166":2,"167":1,"168":1,"169":1,"170":3,"171":3,"172":1,"173":0,"174":0,"175":1,"176":0,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1,"183":1,"184":1,"185":1,"186":0,"187":0,"188":0,"189":0,"190":0,"191":0,"192":0,"193":0,"194":0,"195":0,"196":0,"197":0,"198":0,"199":0,"200":0,"201":0,"202":0,"203":0,"204":0,"205":0,"206":0,"207":0,"208":0,"209":0,"210":0,"211":0,"212":0,"213":0,"214":0,"215":0,"216":2,"217":2,"218":2,"219":2,"220":2,"221":1,"222":2,"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":0,"235":0,"236":1,"237":0,"238":0,"239":0,"240":0,"241":0,"242":0,"243":0,"244":7,"245":7,"246":7,"247":7,"248":7,"249":7,"250":1,"251":6,"252":6,"253":0,"254":6,"255":0,"256":6,"257":6,"258":6,"259":6,"260":0,"261":2,"262":2,"263":2,"264":0,"265":2,"266":2,"267":2,"268":2,"269":0,"270":2,"271":2,"272":2,"273":2,"274":2,"275":2,"276":1,"277":2,"278":0,"279":2,"280":0,"281":2,"282":2,"283":2,"284":0,"285":2,"286":2,"287":2,"288":0,"289":0,"290":0,"291":0,"292":0,"293":0,"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"300":0,"301":0,"302":0,"303":0,"304":0,"305":0,"306":0,"307":0,"308":0,"309":0,"310":2,"311":2,"312":2,"313":0,"314":3,"315":3,"316":3,"317":3,"318":3,"319":3,"320":3,"321":3,"322":3,"323":3,"324":3,"325":3,"326":3,"327":3,"328":3,"329":3,"330":0,"331":3,"332":3,"333":3,"334":3,"335":3,"336":3,"337":3,"338":3,"339":3,"340":3,"341":1,"342":3,"343":0,"344":3,"345":0,"346":1,"347":1,"348":0,"349":1,"350":1,"351":1,"352":1,"353":3,"354":3,"355":1,"356":0,"357":1,"358":1,"359":0,"360":1,"361":1,"362":2,"363":1,"364":1,"365":1,"366":1,"367":3,"368":3,"369":1,"370":1,"371":1,"372":1,"373":1,"374":0,"375":0,"376":0,"377":0,"378":0,"379":0,"380":0,"381":0,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":0,"390":0,"391":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"399":0,"400":0,"401":0,"402":0,"403":0,"404":0,"405":0,"406":0,"407":0,"408":0,"409":0,"410":0,"411":0,"412":0,"413":0,"414":0,"415":0,"416":0,"417":0,"418":0,"419":0,"420":0,"421":0,"422":0,"423":0,"424":0,"425":0,"426":0,"427":0,"428":0,"429":0,"430":0,"431":0,"432":0,"433":0,"434":0,"435":1,"436":1,"437":1,"438":1,"439":1,"440":0,"441":1,"442":1,"443":1,"444":0,"445":4,"446":4,"447":1,"448":3,"449":3,"450":1,"451":4,"452":4,"453":4,"454":1,"455":2,"456":2,"457":4,"458":4,"459":4,"460":2,"461":0,"462":2,"463":2,"464":1,"465":1,"466":1,"467":1,"468":1,"469":0,"470":2,"471":1,"472":1,"473":0,"474":1,"475":0,"476":1,"477":1,"478":0,"479":1,"480":1,"481":1,"482":0,"483":1,"484":0,"485":1,"486":1,"487":1,"488":1,"489":1,"490":0,"491":3,"492":3,"493":1,"494":2,"495":2,"496":3,"497":3,"498":3,"499":2,"500":0,"501":1,"502":1,"503":0,"504":1,"505":1,"506":1,"507":0,"508":2,"509":2,"510":1,"511":1,"512":1,"513":1,"514":1,"515":0,"516":1,"517":1,"518":1,"519":1,"520":1,"521":0,"522":1,"523":1,"524":1,"525":0,"526":0,"527":1,"528":1,"529":1,"530":0,"531":0,"532":0,"533":0,"534":0,"535":0,"536":0,"537":0,"538":1,"539":1,"540":1,"541":1,"542":1,"543":0,"544":0,"545":0,"546":0,"547":1,"548":1,"549":1,"550":1,"551":1,"552":0,"553":1,"554":1,"555":0,"556":1,"557":1,"558":1,"559":1,"560":0,"561":1,"562":1,"563":1,"564":1,"565":1,"566":1,"567":0,"568":0,"569":1,"570":0,"571":0,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":0,"579":0,"580":0,"581":0,"582":0,"583":0,"584":0,"585":0,"586":0,"587":0,"588":0,"589":0,"590":0,"591":0,"592":0,"593":0,"594":0,"595":0,"596":0,"597":0,"598":0,"599":0,"600":0,"601":0,"602":0,"603":0,"604":0,"605":0,"606":0,"607":0,"608":0,"609":0,"610":0,"611":0,"612":0,"613":0,"614":0,"615":0,"616":0,"617":0,"618":0,"619":0,"620":0,"621":0,"622":0,"623":1,"624":1,"625":0,"626":1,"627":1,"628":0,"629":0,"630":0,"631":0,"632":0,"633":0,"634":1,"635":0,"636":1,"637":1,"638":1,"639":0,"640":0,"641":0,"642":0,"643":0,"644":0,"645":0,"646":0,"647":0,"648":0,"649":0,"650":0,"651":0,"652":0,"653":0,"654":0,"655":0,"656":0,"657":0,"658":0,"659":0,"660":0,"661":0,"662":0,"663":0,"664":0,"665":0,"666":0,"667":0,"668":0,"669":0,"670":0,"671":0,"672":0,"673":0,"674":0,"675":0,"676":0,"677":0,"678":0,"679":0,"680":0,"681":0,"682":0,"683":0,"684":0,"685":0,"686":0,"687":0,"688":0,"689":0,"690":0,"691":0,"692":0,"693":0,"694":0,"695":0,"696":0,"697":0,"698":0,"699":0,"700":1,"701":1,"702":1,"703":0,"704":0,"705":0,"706":1,"707":0,"708":0,"709":0,"710":0,"711":0,"712":0,"713":0,"714":0,"715":0,"716":0,"717":0,"718":0,"719":0,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":0,"728":0,"729":0,"730":0,"731":0,"732":0,"733":0,"734":0,"735":0,"736":0,"737":0,"738":1,"739":0,"740":1,"741":1,"742":0,"743":1,"744":1,"745":2,"746":2,"747":1,"748":1,"749":1,"750":0,"751":1,"752":1,"753":1,"754":1,"755":1,"756":1,"757":0,"758":1,"759":1,"760":1,"761":1,"762":0,"763":0,"764":1,"765":2,"766":0,"767":0,"768":1,"769":1,"770":1,"771":1,"772":0,"773":1,"774":1,"775":1,"776":1,"777":0,"778":1,"779":0,"780":1,"781":1,"782":1,"783":1,"784":1,"785":0,"786":0,"787":1,"788":2,"789":0,"790":4,"791":4,"792":4,"793":0,"794":0,"795":4,"796":1,"797":3,"798":3,"799":0,"800":3,"801":3,"802":4,"803":4,"804":4,"805":4,"806":4,"807":4,"808":4,"809":4,"810":4,"811":4,"812":4,"813":4,"814":4,"815":4,"816":4,"817":4,"818":0,"819":3,"820":1,"821":3,"822":0,"823":3,"824":0,"825":3,"826":0,"827":3,"828":0,"829":3,"830":3,"831":3,"832":0,"833":3,"834":0,"835":3,"836":1,"837":4,"838":4,"839":7,"840":4,"841":4,"842":4,"843":2,"844":2,"845":0,"846":0,"847":3,"848":4,"849":4,"850":0,"851":3,"852":3,"853":3,"854":1,"855":1,"856":1,"857":1,"858":0,"859":0,"860":3,"861":1,"862":3,"863":0,"864":3,"865":3,"866":3,"867":3,"868":3,"869":3,"870":1,"871":2,"872":2,"873":2,"874":2,"875":2,"876":0},"f":{"0":57,"1":57,"2":57,"3":57,"4":57,"5":4,"6":3,"7":0,"8":1,"9":1,"10":1,"11":6,"12":3,"13":0,"14":1,"15":2,"16":2,"17":2,"18":2,"19":1,"20":2,"21":1,"22":3,"23":1,"24":0,"25":2,"26":2,"27":1,"28":0,"29":0,"30":7,"31":2,"32":2,"33":0,"34":3,"35":0,"36":1,"37":3,"38":3,"39":2,"40":3,"41":3,"42":0,"43":1,"44":1,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":1,"57":4,"58":1,"59":2,"60":0,"61":0,"62":1,"63":0,"64":1,"65":3,"66":1,"67":2,"68":1,"69":1,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":1,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":1,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":1,"111":0,"112":0,"113":0,"114":0,"115":0,"116":1,"117":0,"118":1,"119":1,"120":2,"121":4,"122":1,"123":7,"124":0,"125":0,"126":0},"b":{"0":[4],"1":[4],"2":[4],"3":[4],"4":[1,3],"5":[4,4],"6":[1,3],"7":[1,0],"8":[1,0],"9":[1,2],"10":[3,3],"11":[0,1],"12":[0,4],"13":[3,1],"14":[3,0],"15":[3,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0,0,0],"21":[1,0],"22":[1,0],"23":[3],"24":[3],"25":[3,2,1],"26":[1,2],"27":[2,1],"28":[1,0],"29":[1,0,0],"30":[1],"31":[1],"32":[0,1],"33":[0,0],"34":[0,1],"35":[0,0],"36":[1,0],"37":[2,0],"38":[0,2],"39":[0,2],"40":[0,0],"41":[1,0],"42":[0,2],"43":[2,0,0],"44":[2,0],"45":[2,2,2],"46":[0,1],"47":[0,1],"48":[0,2],"49":[2,0],"50":[1,1],"51":[2,1],"52":[1,0],"53":[1,0],"54":[1,0],"55":[1,1],"56":[1,1],"57":[3,0],"58":[0,1],"59":[1,1],"60":[1,0],"61":[1,0,0],"62":[0,1],"63":[1,0],"64":[0,0],"65":[1,1],"66":[1,0],"67":[0],"68":[0,0],"69":[0,0],"70":[0,0,0],"71":[0,0],"72":[0,0],"73":[0,0],"74":[0,0],"75":[0,0,0],"76":[0,0],"77":[2],"78":[2,0],"79":[1,1],"80":[2,2,2],"81":[2,0],"82":[2,0],"83":[1,0],"84":[1,0],"85":[1,1,0,0],"86":[1,0],"87":[0,1],"88":[0,0],"89":[0,0],"90":[0,0],"91":[0,0],"92":[7],"93":[7,0],"94":[7,0],"95":[7,7],"96":[1,6],"97":[7,1,1],"98":[0,6],"99":[0,6],"100":[6,6],"101":[7,6],"102":[7,6],"103":[2],"104":[2],"105":[2],"106":[2],"107":[0,2],"108":[2,0],"109":[2,2],"110":[0,2],"111":[2,0,0],"112":[1,1],"113":[0,1],"114":[0,2],"115":[0,2],"116":[0,2],"117":[2,0],"118":[0,0],"119":[0,0],"120":[0,0],"121":[0,0],"122":[0,0],"123":[0,0],"124":[0,0],"125":[0,0],"126":[2,2],"127":[0,2],"128":[3,0],"129":[3,2],"130":[3,2],"131":[3,2],"132":[3,2],"133":[3,2],"134":[3,2],"135":[3,3],"136":[1,2],"137":[3,2],"138":[3,2],"139":[3,2],"140":[1,2],"141":[0,3],"142":[3,0],"143":[1,2],"144":[3,3],"145":[1,2],"146":[0,3],"147":[3,0],"148":[0,3],"149":[3,3],"150":[3,3],"151":[3,2],"152":[3,2,2],"153":[3,0],"154":[3,3],"155":[3,3],"156":[1,2],"157":[1],"158":[1],"159":[1,0],"160":[0,1],"161":[1,1],"162":[0,1],"163":[1,0],"164":[1,0],"165":[0,1],"166":[0,1],"167":[1,0],"168":[2,0],"169":[3,0],"170":[3,0],"171":[3,0],"172":[3,0],"173":[2,1],"174":[3,2],"175":[1,0],"176":[1,0],"177":[1,0],"178":[0],"179":[0],"180":[0,0],"181":[0,0],"182":[0,0],"183":[1],"184":[1],"185":[1],"186":[0],"187":[0],"188":[0],"189":[0],"190":[0],"191":[0,0],"192":[0,0],"193":[0,0],"194":[0,0],"195":[0],"196":[0,0],"197":[0,0],"198":[0,0],"199":[0,0],"200":[0,0,0],"201":[0,0,0],"202":[1],"203":[1],"204":[1,1,1,1],"205":[1,0],"206":[1,1],"207":[0,1],"208":[4],"209":[4],"210":[4],"211":[4,0],"212":[1,3],"213":[4,4],"214":[3,0],"215":[1,2],"216":[4,1],"217":[1,3],"218":[2,2],"219":[4,1],"220":[0,2],"221":[4,1],"222":[2,2],"223":[2],"224":[2],"225":[2,0],"226":[1,1],"227":[2,1],"228":[0,1],"229":[0,1],"230":[0,1],"231":[2,1],"232":[1,0],"233":[1],"234":[1],"235":[1],"236":[1,0],"237":[0,1],"238":[1,1],"239":[1,0],"240":[1],"241":[1],"242":[1,0],"243":[3],"244":[3],"245":[3,0],"246":[1,2],"247":[3,3],"248":[2,2],"249":[3,1],"250":[0,2],"251":[3,1],"252":[1,1],"253":[1],"254":[1,0],"255":[0,1],"256":[1,0],"257":[2],"258":[2,0],"259":[1,1],"260":[2,1],"261":[1],"262":[1,0],"263":[1],"264":[1],"265":[1],"266":[1],"267":[1,0],"268":[1,0],"269":[1,0],"270":[0,0],"271":[0,0],"272":[0,0],"273":[0,0],"274":[0,0],"275":[0,0],"276":[1,0,0],"277":[1,0],"278":[0,0],"279":[0,0],"280":[0,0],"281":[1,0],"282":[1],"283":[1],"284":[1,0],"285":[0,1],"286":[1,0,0],"287":[0,1],"288":[0,1],"289":[1,0],"290":[1,1,0,0],"291":[0,1],"292":[1,1],"293":[0,0],"294":[0,1],"295":[1,1],"296":[0,0],"297":[0,1],"298":[0,1],"299":[1,0],"300":[0,1],"301":[1,1],"302":[0,0],"303":[0,0],"304":[0,0],"305":[0,0],"306":[0,0],"307":[0,0],"308":[0,0],"309":[0,0],"310":[0,0],"311":[0,0],"312":[0,0],"313":[0,1],"314":[1,0,0],"315":[0,1],"316":[0,0,0],"317":[0,1],"318":[1,0,0],"319":[1,0],"320":[0,0],"321":[0,0],"322":[0,0],"323":[0,0],"324":[0,0],"325":[0,0],"326":[0,0],"327":[0,0],"328":[0,0],"329":[0,0],"330":[0,0],"331":[0,0],"332":[0,0],"333":[0,0],"334":[0,0],"335":[0,0],"336":[0,0],"337":[0,0],"338":[0,0],"339":[0,0],"340":[0,0],"341":[0,0],"342":[0,0],"343":[0,0],"344":[0,0],"345":[0,0],"346":[0,0],"347":[0,0],"348":[0,0],"349":[0,0],"350":[0,0],"351":[0,0],"352":[0,0],"353":[0,0],"354":[0,0],"355":[0,0],"356":[0,0],"357":[0,0],"358":[0,0],"359":[0,1],"360":[1,0],"361":[0,1],"362":[0,0],"363":[0,1],"364":[1,1],"365":[0,0,0],"366":[0,0,0],"367":[0,0],"368":[0,0],"369":[0,0],"370":[1,0],"371":[1,0],"372":[1,0,0],"373":[1,0],"374":[1,0],"375":[0,0],"376":[0,0],"377":[0,0],"378":[0,0,0],"379":[0,0,0],"380":[0,0],"381":[0,1],"382":[0,1],"383":[2],"384":[2],"385":[2],"386":[2,0],"387":[1,1],"388":[2,1],"389":[0,1],"390":[1,0],"391":[0,1],"392":[0,1],"393":[1,0,0],"394":[2,0],"395":[2,0],"396":[1,0],"397":[0,1],"398":[0,1],"399":[1,0],"400":[1,0],"401":[0,1],"402":[0,0],"403":[4],"404":[4],"405":[4],"406":[4,0],"407":[4,0],"408":[4,4],"409":[1,3],"410":[0,3],"411":[3,0,0],"412":[3,3],"413":[1,2],"414":[4,3,2],"415":[4,3],"416":[4,3],"417":[4,3],"418":[4,3],"419":[4,2],"420":[4,3,3],"421":[4,3],"422":[4,3],"423":[0,3],"424":[1,2],"425":[0,3],"426":[0,3],"427":[0,3],"428":[0,3],"429":[0,3],"430":[0,3],"431":[0,3],"432":[1,2],"433":[4,1],"434":[2,2],"435":[3,3,3],"436":[0,4],"437":[1,2],"438":[0,1],"439":[1,2],"440":[0,3],"441":[1,2],"442":[2,0],"443":[2,0],"444":[0,0]},"meta":{"lastBranch":445,"lastFunction":127,"lastStatement":877,"seen":{"f:39:2:39:14":0,"s:40:4:40:Infinity":0,"s:42:4:42:Infinity":1,"s:43:4:43:Infinity":2,"s:44:4:44:Infinity":3,"s:45:4:45:Infinity":4,"f:51:10:51:37":1,"s:52:10:52:Infinity":5,"s:53:5:53:Infinity":6,"f:59:10:59:38":2,"s:60:10:60:Infinity":7,"s:61:5:61:Infinity":8,"s:62:5:62:Infinity":9,"f:68:10:68:38":3,"s:69:10:69:Infinity":10,"s:70:5:70:Infinity":11,"s:71:5:71:Infinity":12,"f:77:10:77:38":4,"s:78:10:78:Infinity":13,"s:79:5:79:Infinity":14,"s:80:5:80:Infinity":15,"s:81:5:81:Infinity":16,"s:82:5:82:Infinity":17,"f:85:8:85:20":5,"s:93:8:93:Infinity":18,"b:88:17:88:Infinity":0,"b:89:14:89:Infinity":1,"b:90:16:90:Infinity":2,"b:92:13:92:Infinity":3,"s:95:4:187:Infinity":19,"s:97:43:97:Infinity":20,"s:98:21:98:Infinity":21,"s:99:24:99:Infinity":22,"b:99:65:99:72:99:72:99:Infinity":4,"b:99:24:99:45:99:45:99:65":5,"b:101:6:158:Infinity:111:13:158:Infinity":6,"s:101:6:158:Infinity":23,"s:103:10:103:Infinity":24,"b:103:28:103:70:103:70:103:Infinity":7,"s:105:8:110:Infinity":25,"b:107:14:109:Infinity:110:14:110:Infinity":8,"b:112:8:157:Infinity:145:15:157:Infinity":9,"s:112:8:157:Infinity":26,"b:112:12:112:38:112:38:112:62":10,"s:113:29:117:Infinity":27,"b:119:10:144:Infinity:121:17:144:Infinity":11,"s:119:10:144:Infinity":28,"s:120:12:120:Infinity":29,"s:122:33:127:Infinity":30,"s:128:34:131:Infinity":31,"s:132:12:143:Infinity":32,"s:146:31:151:Infinity":33,"s:152:32:155:Infinity":34,"s:156:10:156:Infinity":35,"b:160:6:167:Infinity:undefined:undefined:undefined:undefined":12,"s:160:6:167:Infinity":36,"s:161:8:166:Infinity":37,"s:169:22:169:Infinity":38,"s:170:6:184:Infinity":39,"b:173:37:173:66:173:66:173:Infinity":13,"s:186:6:186:Infinity":40,"f:190:10:190:Infinity":6,"b:194:4:196:Infinity:undefined:undefined:undefined:undefined":14,"s:194:4:196:Infinity":41,"b:194:8:194:27:194:27:194:49":15,"s:195:6:195:Infinity":42,"s:198:4:220:Infinity":43,"f:198:23:198:24":7,"b:199:6:201:Infinity:undefined:undefined:undefined:undefined":16,"s:199:6:201:Infinity":44,"s:200:8:200:Infinity":45,"s:203:19:203:Infinity":46,"s:204:24:204:Infinity":47,"s:205:25:205:Infinity":48,"s:207:8:209:Infinity":49,"b:208:12:208:Infinity:209:12:209:Infinity":17,"b:207:8:207:31:207:31:207:Infinity":18,"b:211:6:213:Infinity:undefined:undefined:undefined:undefined":19,"s:211:6:213:Infinity":50,"s:212:8:212:Infinity":51,"s:215:6:218:Infinity":52,"b:216:8:216:Infinity:217:9:217:Infinity:218:11:218:36:218:36:218:Infinity":20,"f:223:16:223:Infinity":8,"s:228:24:231:Infinity":53,"f:231:12:231:13":9,"s:231:23:231:40":54,"s:233:44:238:Infinity":55,"b:236:19:236:34:236:34:236:Infinity":21,"s:240:19:248:Infinity":56,"b:250:4:252:Infinity:undefined:undefined:undefined:undefined":22,"s:250:4:252:Infinity":57,"s:251:6:251:Infinity":58,"s:254:21:260:Infinity":59,"s:262:4:262:Infinity":60,"f:265:10:265:27":10,"s:266:16:266:Infinity":61,"s:267:18:267:Infinity":62,"s:268:4:268:Infinity":63,"f:268:24:268:25":11,"s:268:34:268:52":64,"f:271:8:271:21":12,"s:272:56:272:Infinity":65,"b:272:29:272:32":23,"b:272:42:272:52":24,"s:274:4:319:Infinity":66,"s:276:20:276:Infinity":67,"s:277:20:277:Infinity":68,"s:278:22:278:Infinity":69,"s:281:8:283:Infinity":70,"b:281:8:281:Infinity:282:8:282:Infinity:283:8:283:Infinity":25,"f:283:21:283:22":13,"s:283:28:283:57":71,"b:285:6:292:Infinity:undefined:undefined:undefined:undefined":26,"s:285:6:292:Infinity":72,"s:286:8:291:Infinity":73,"s:295:31:301:Infinity":74,"b:296:17:296:47:296:47:296:Infinity":27,"s:304:23:304:Infinity":75,"s:305:6:314:Infinity":76,"s:306:23:306:Infinity":77,"b:307:8:313:Infinity:undefined:undefined:undefined:undefined":28,"s:307:8:313:Infinity":78,"s:308:10:312:Infinity":79,"b:311:14:311:40:311:40:311:66:311:66:311:Infinity":29,"s:316:6:316:Infinity":80,"s:318:6:318:Infinity":81,"f:322:8:322:21":14,"s:323:63:323:Infinity":82,"b:323:28:323:39":30,"b:323:49:323:59":31,"s:325:4:486:Infinity":83,"s:326:27:330:Infinity":84,"b:332:6:481:Infinity:338:6:481:Infinity":32,"s:332:6:481:Infinity":85,"b:333:8:335:Infinity:undefined:undefined:undefined:undefined":33,"s:333:8:335:Infinity":86,"s:334:10:334:Infinity":87,"s:336:23:336:Infinity":88,"s:337:8:337:Infinity":89,"b:338:6:481:Infinity:350:6:481:Infinity":34,"s:338:6:481:Infinity":90,"s:340:22:340:Infinity":91,"s:341:8:349:Infinity":92,"s:342:23:342:Infinity":93,"b:343:10:348:Infinity:undefined:undefined:undefined:undefined":35,"s:343:10:348:Infinity":94,"s:344:12:347:Infinity":95,"b:350:6:481:Infinity:475:13:481:Infinity":36,"s:350:6:481:Infinity":96,"s:351:30:351:Infinity":97,"s:352:25:352:Infinity":98,"s:353:20:363:Infinity":99,"f:353:36:353:37":15,"s:354:32:354:Infinity":100,"b:354:39:354:68:354:68:354:70":37,"b:355:10:355:Infinity:undefined:undefined:undefined:undefined":38,"s:355:10:355:Infinity":101,"s:355:26:355:Infinity":102,"b:356:10:361:Infinity:undefined:undefined:undefined:undefined":39,"s:356:10:361:Infinity":103,"b:357:12:359:Infinity:undefined:undefined:undefined:undefined":40,"s:357:12:359:Infinity":104,"s:358:14:358:Infinity":105,"s:360:12:360:Infinity":106,"s:362:10:362:Infinity":107,"b:365:8:367:Infinity:undefined:undefined:undefined:undefined":41,"s:365:8:367:Infinity":108,"s:366:10:366:Infinity":109,"s:369:24:369:Infinity":110,"f:369:42:369:43":16,"s:369:49:369:53":111,"s:370:26:370:Infinity":112,"s:372:8:404:Infinity":113,"s:373:26:373:Infinity":114,"s:374:29:376:Infinity":115,"f:376:20:376:21":17,"s:376:29:376:51":116,"s:378:10:401:Infinity":117,"s:379:33:379:Infinity":118,"b:380:12:386:Infinity:undefined:undefined:undefined:undefined":42,"s:380:12:386:Infinity":119,"b:381:14:381:Infinity:382:14:382:Infinity:383:14:383:Infinity":43,"s:385:14:385:Infinity":120,"s:388:25:390:Infinity":121,"f:390:22:390:23":18,"s:390:31:390:56":122,"s:391:12:400:Infinity":123,"s:392:33:392:Infinity":124,"b:393:14:399:Infinity:undefined:undefined:undefined:undefined":44,"s:393:14:399:Infinity":125,"b:394:16:394:Infinity:395:16:395:Infinity:396:16:396:Infinity":45,"s:398:16:398:Infinity":126,"s:403:10:403:Infinity":127,"s:406:35:406:Infinity":128,"s:407:27:407:Infinity":129,"s:408:28:408:Infinity":130,"s:409:28:409:Infinity":131,"s:410:32:410:Infinity":132,"s:412:34:423:Infinity":133,"f:412:34:412:35":19,"s:413:29:413:Infinity":134,"b:414:10:414:Infinity:undefined:undefined:undefined:undefined":46,"s:414:10:414:Infinity":135,"s:414:34:414:Infinity":136,"s:415:21:415:Infinity":137,"s:416:10:421:Infinity":138,"s:416:23:416:26":139,"s:417:28:417:Infinity":140,"b:418:12:420:Infinity:undefined:undefined:undefined:undefined":47,"s:418:12:420:Infinity":141,"s:419:14:419:Infinity":142,"s:422:10:422:Infinity":143,"s:425:22:453:Infinity":144,"f:425:22:425:23":20,"b:426:10:426:Infinity:undefined:undefined:undefined:undefined":48,"s:426:10:426:Infinity":145,"s:426:39:426:Infinity":146,"s:427:10:427:Infinity":147,"s:428:10:428:Infinity":148,"s:430:28:430:Infinity":149,"b:430:28:430:53:430:53:430:Infinity":49,"s:431:10:448:Infinity":150,"b:432:12:435:Infinity:undefined:undefined:undefined:undefined":50,"s:432:12:435:Infinity":151,"b:432:16:432:44:432:44:432:70":51,"s:433:14:433:Infinity":152,"s:434:14:434:Infinity":153,"b:437:12:447:Infinity:undefined:undefined:undefined:undefined":52,"s:437:12:447:Infinity":154,"s:438:28:438:Infinity":155,"b:439:14:446:Infinity:undefined:undefined:undefined:undefined":53,"s:439:14:446:Infinity":156,"s:440:30:440:Infinity":157,"s:441:28:441:Infinity":158,"b:442:16:445:Infinity:undefined:undefined:undefined:undefined":54,"s:442:16:445:Infinity":159,"b:442:20:442:27:442:27:442:49":55,"s:443:18:443:Infinity":160,"s:444:18:444:Infinity":161,"s:450:10:450:Infinity":162,"s:451:10:451:Infinity":163,"s:452:10:452:Infinity":164,"s:455:8:459:Infinity":165,"b:456:10:458:Infinity:undefined:undefined:undefined:undefined":56,"s:456:10:458:Infinity":166,"s:457:12:457:Infinity":167,"s:461:8:467:Infinity":168,"f:461:50:461:51":21,"s:461:62:467:10":169,"f:462:27:462:28":22,"s:463:25:463:Infinity":170,"s:464:12:464:Infinity":171,"b:464:26:464:51:464:51:464:53":57,"b:469:8:474:Infinity:undefined:undefined:undefined:undefined":58,"s:469:8:474:Infinity":172,"s:470:10:473:Infinity":173,"s:477:8:480:Infinity":174,"s:483:6:483:Infinity":175,"s:485:6:485:Infinity":176,"f:495:8:495:23":23,"s:496:20:496:Infinity":177,"b:496:20:496:37:496:37:496:Infinity":59,"s:497:19:497:Infinity":178,"b:497:19:497:35:497:35:497:Infinity":60,"s:498:22:498:Infinity":179,"b:498:29:498:44:498:44:498:58:498:58:498:64":61,"s:499:37:501:Infinity":180,"b:500:8:500:Infinity:501:8:501:Infinity":62,"s:504:6:508:Infinity":181,"b:505:10:505:Infinity:506:10:508:Infinity":63,"b:507:12:507:Infinity:508:12:508:Infinity":64,"s:510:19:513:Infinity":182,"b:511:10:511:26:511:26:511:Infinity":65,"b:512:29:512:60:512:60:512:Infinity":66,"s:515:4:521:Infinity":183,"s:516:21:516:Infinity":184,"s:518:6:518:Infinity":185,"s:520:6:520:Infinity":186,"f:524:8:524:20":24,"s:532:8:532:Infinity":187,"b:531:16:531:Infinity":67,"s:534:4:627:Infinity":188,"s:535:22:539:Infinity":189,"b:541:6:546:Infinity:undefined:undefined:undefined:undefined":68,"s:541:6:546:Infinity":190,"s:542:8:545:Infinity":191,"b:549:6:561:Infinity:undefined:undefined:undefined:undefined":69,"s:549:6:561:Infinity":192,"b:549:10:549:20:549:20:549:32:549:32:549:41":70,"s:551:10:555:Infinity":193,"b:556:8:560:Infinity:undefined:undefined:undefined:undefined":71,"s:556:8:560:Infinity":194,"s:557:10:559:Infinity":195,"s:563:51:563:Infinity":196,"b:564:6:619:Infinity:undefined:undefined:undefined:undefined":72,"s:564:6:619:Infinity":197,"b:564:17:564:27:564:27:564:29":73,"s:565:26:565:Infinity":198,"b:565:26:565:56:565:56:565:Infinity":74,"s:566:31:568:Infinity":199,"b:567:10:567:22:567:22:567:39:567:39:567:Infinity":75,"s:569:30:569:Infinity":200,"s:571:8:581:Infinity":201,"s:572:10:576:Infinity":202,"s:577:10:577:Infinity":203,"s:579:10:579:Infinity":204,"s:580:10:580:Infinity":205,"s:583:8:596:Infinity":206,"s:584:29:589:Infinity":207,"s:590:10:593:Infinity":208,"s:595:10:595:Infinity":209,"s:598:8:618:Infinity":210,"s:599:36:614:Infinity":211,"b:603:60:603:88:603:88:603:90":76,"s:615:10:615:Infinity":212,"s:617:10:617:Infinity":213,"s:621:6:624:Infinity":214,"s:626:6:626:Infinity":215,"f:630:8:630:23":25,"s:631:47:631:Infinity":216,"b:631:33:631:43":77,"s:633:4:704:Infinity":217,"s:634:26:634:Infinity":218,"s:640:24:640:Infinity":219,"b:640:31:640:44:640:44:640:46":78,"b:641:6:658:Infinity:undefined:undefined:undefined:undefined":79,"s:641:6:658:Infinity":220,"b:642:8:642:Infinity:643:8:643:Infinity:644:8:644:Infinity":80,"s:646:8:657:Infinity":221,"f:650:52:650:53":26,"s:650:66:654:14":222,"b:652:20:652:36:652:36:652:Infinity":81,"b:653:22:653:40:653:40:653:Infinity":82,"s:660:30:660:Infinity":223,"s:661:19:661:Infinity":224,"b:663:6:679:Infinity:undefined:undefined:undefined:undefined":83,"s:663:6:679:Infinity":225,"s:664:24:664:Infinity":226,"s:665:24:673:Infinity":227,"f:665:41:665:42":27,"s:666:23:666:Infinity":228,"b:666:30:666:46:666:46:666:48":84,"s:667:10:671:Infinity":229,"b:668:12:668:Infinity:669:12:669:Infinity:670:12:670:Infinity:671:12:671:Infinity":85,"b:675:8:678:Infinity:undefined:undefined:undefined:undefined":86,"s:675:8:678:Infinity":230,"s:676:10:676:Infinity":231,"s:677:10:677:Infinity":232,"b:681:6:693:Infinity:undefined:undefined:undefined:undefined":87,"s:681:6:693:Infinity":233,"s:682:8:692:Infinity":234,"f:687:19:687:20":28,"s:687:32:687:42":235,"s:695:6:701:Infinity":236,"s:703:6:703:Infinity":237,"f:707:8:707:24":29,"s:708:17:708:Infinity":238,"b:708:17:708:32:708:32:708:Infinity":88,"b:708:48:708:56:708:56:708:Infinity":89,"s:709:20:709:Infinity":239,"b:709:20:709:37:709:37:709:Infinity":90,"s:711:4:728:Infinity":240,"s:712:21:712:Infinity":241,"s:714:6:725:Infinity":242,"b:721:16:721:Infinity:722:16:722:Infinity":91,"s:727:6:727:Infinity":243,"f:735:8:735:28":30,"s:736:36:736:Infinity":244,"b:736:22:736:32":92,"b:736:36:736:44:736:44:736:Infinity":93,"s:738:4:806:Infinity":245,"s:739:24:739:Infinity":246,"b:739:51:739:59:739:59:739:61":94,"s:740:22:740:Infinity":247,"s:742:8:743:Infinity":248,"b:742:8:742:Infinity:743:8:743:Infinity":95,"b:745:6:756:Infinity:undefined:undefined:undefined:undefined":96,"s:745:6:756:Infinity":249,"b:746:8:746:Infinity:747:8:747:Infinity:748:8:748:Infinity":97,"s:750:8:755:Infinity":250,"s:758:6:758:Infinity":251,"b:760:6:767:Infinity:undefined:undefined:undefined:undefined":98,"s:760:6:767:Infinity":252,"s:761:8:766:Infinity":253,"b:769:6:776:Infinity:undefined:undefined:undefined:undefined":99,"s:769:6:776:Infinity":254,"s:770:8:775:Infinity":255,"s:778:6:778:Infinity":256,"s:779:6:779:Infinity":257,"s:781:22:781:Infinity":258,"s:783:6:798:Infinity":259,"b:788:25:788:43:788:43:788:Infinity":100,"b:791:26:791:53:791:53:791:Infinity":101,"b:793:37:793:63:793:63:793:Infinity":102,"s:800:6:805:Infinity":260,"f:809:8:809:22":31,"s:815:8:815:Infinity":261,"b:811:13:811:Infinity":103,"b:812:16:812:Infinity":104,"b:813:16:813:Infinity":105,"b:814:18:814:Infinity":106,"s:817:4:1010:Infinity":262,"b:818:6:824:Infinity:undefined:undefined:undefined:undefined":107,"s:818:6:824:Infinity":263,"s:819:8:823:Infinity":264,"s:826:28:826:Infinity":265,"b:826:55:826:63:826:63:826:65":108,"s:827:22:827:Infinity":266,"s:829:8:830:Infinity":267,"b:829:8:829:Infinity:830:8:830:Infinity":109,"b:832:6:843:Infinity:undefined:undefined:undefined:undefined":110,"s:832:6:843:Infinity":268,"b:833:8:833:Infinity:834:8:834:Infinity:835:8:835:Infinity":111,"s:837:8:842:Infinity":269,"s:845:6:845:Infinity":270,"s:846:6:846:Infinity":271,"s:847:54:847:Infinity":272,"s:848:26:848:Infinity":273,"s:850:12:850:Infinity":274,"b:852:6:864:Infinity:undefined:undefined:undefined:undefined":112,"s:852:6:864:Infinity":275,"s:853:8:863:Infinity":276,"b:858:36:858:53:858:53:858:Infinity":113,"b:866:6:873:Infinity:undefined:undefined:undefined:undefined":114,"s:866:6:873:Infinity":277,"s:867:8:872:Infinity":278,"b:875:6:882:Infinity:undefined:undefined:undefined:undefined":115,"s:875:6:882:Infinity":279,"s:876:8:881:Infinity":280,"s:887:6:978:Infinity":281,"f:907:14:907:26":32,"s:909:12:909:Infinity":282,"b:910:10:914:Infinity:undefined:undefined:undefined:undefined":116,"s:910:10:914:Infinity":283,"s:911:12:913:Infinity":284,"b:916:10:963:Infinity:923:10:963:Infinity":117,"s:916:10:963:Infinity":285,"s:919:12:919:Infinity":286,"s:920:12:922:Infinity":287,"b:923:10:963:Infinity:undefined:undefined:undefined:undefined":118,"s:923:10:963:Infinity":288,"s:926:12:946:Infinity":289,"s:928:16:928:Infinity":290,"b:929:14:939:Infinity:undefined:undefined:undefined:undefined":119,"s:929:14:939:Infinity":291,"b:930:16:930:Infinity:931:16:931:Infinity":120,"s:933:16:933:Infinity":292,"s:935:16:935:Infinity":293,"s:936:16:938:Infinity":294,"s:941:14:944:Infinity":295,"s:948:31:948:Infinity":296,"b:949:12:957:Infinity:953:12:957:Infinity":121,"s:949:12:957:Infinity":297,"s:950:14:952:Infinity":298,"b:953:12:957:Infinity:undefined:undefined:undefined:undefined":122,"s:953:12:957:Infinity":299,"s:954:14:956:Infinity":300,"s:959:33:959:Infinity":301,"s:960:12:962:Infinity":302,"f:965:15:965:16":33,"s:967:26:967:Infinity":303,"s:968:10:968:Infinity":304,"s:970:27:970:Infinity":305,"b:970:50:970:64:970:64:970:Infinity":123,"s:971:24:971:Infinity":306,"b:971:47:971:59:971:59:971:Infinity":124,"s:972:10:974:Infinity":307,"b:975:10:977:Infinity:undefined:undefined:undefined:undefined":125,"s:975:10:977:Infinity":308,"s:976:12:976:Infinity":309,"s:980:6:980:Infinity":310,"s:981:6:981:Infinity":311,"s:984:6:1003:Infinity":312,"b:996:37:996:63:996:63:996:Infinity":126,"b:997:89:997:97:997:97:997:106":127,"s:1005:6:1009:Infinity":313,"f:1013:8:1013:21":34,"s:1014:20:1014:Infinity":314,"b:1014:20:1014:37:1014:37:1014:Infinity":128,"s:1016:4:1171:Infinity":315,"s:1018:8:1018:Infinity":316,"s:1022:32:1034:Infinity":317,"s:1037:20:1037:Infinity":318,"b:1037:20:1037:51:1037:51:1037:Infinity":129,"s:1038:32:1038:Infinity":319,"b:1038:32:1038:71:1038:71:1038:Infinity":130,"s:1039:31:1039:Infinity":320,"b:1039:31:1039:69:1039:69:1039:Infinity":131,"s:1040:32:1040:Infinity":321,"b:1040:32:1040:70:1040:70:1040:Infinity":132,"s:1041:32:1041:Infinity":322,"b:1041:32:1041:70:1041:70:1041:Infinity":133,"s:1042:33:1042:Infinity":323,"b:1042:33:1042:72:1042:72:1042:Infinity":134,"s:1045:25:1045:Infinity":324,"s:1046:29:1046:Infinity":325,"s:1048:8:1048:Infinity":326,"s:1049:30:1049:Infinity":327,"s:1050:29:1050:Infinity":328,"s:1054:8:1056:Infinity":329,"b:1054:8:1056:62:1056:62:1056:Infinity":135,"f:1056:18:1056:19":35,"s:1056:25:1056:50":330,"s:1058:8:1065:Infinity":331,"b:1059:12:1064:Infinity:1065:12:1065:Infinity":136,"s:1068:25:1068:Infinity":332,"s:1069:29:1069:Infinity":333,"s:1072:31:1078:Infinity":334,"s:1079:25:1079:Infinity":335,"b:1079:25:1079:55:1079:55:1079:Infinity":137,"s:1080:26:1080:Infinity":336,"b:1080:26:1080:49:1080:49:1080:Infinity":138,"s:1081:25:1083:Infinity":337,"b:1082:17:1082:58:1082:58:1082:Infinity":139,"s:1084:22:1084:Infinity":338,"s:1087:40:1087:Infinity":339,"b:1088:6:1092:Infinity:undefined:undefined:undefined:undefined":140,"s:1088:6:1092:Infinity":340,"s:1089:8:1091:Infinity":341,"b:1094:6:1098:Infinity:undefined:undefined:undefined:undefined":141,"s:1094:6:1098:Infinity":342,"b:1094:10:1094:28:1094:28:1094:70":142,"s:1095:8:1097:Infinity":343,"s:1100:6:1168:Infinity":344,"b:1102:31:1102:50:1102:50:1102:Infinity":143,"b:1107:27:1107:57:1107:57:1107:Infinity":144,"b:1122:16:1122:Infinity:1123:16:1123:Infinity":145,"b:1132:16:1132:Infinity:1133:16:1133:Infinity":146,"b:1137:18:1137:52:1137:52:1137:Infinity":147,"b:1141:49:1141:66:1141:66:1141:Infinity":148,"b:1144:29:1144:56:1144:56:1144:Infinity":149,"b:1145:22:1145:51:1145:51:1145:Infinity":150,"b:1146:24:1146:42:1146:42:1146:Infinity":151,"b:1148:14:1148:Infinity:1149:14:1149:Infinity:1150:14:1150:Infinity":152,"b:1151:21:1151:43:1151:43:1151:Infinity":153,"b:1159:26:1159:53:1159:53:1159:Infinity":154,"b:1160:24:1160:42:1160:42:1160:Infinity":155,"b:1165:12:1165:Infinity:1166:12:1166:Infinity":156,"s:1170:6:1170:Infinity":345,"f:1174:8:1174:19":36,"s:1179:8:1179:Infinity":346,"b:1177:14:1177:Infinity":157,"b:1178:16:1178:Infinity":158,"b:1179:8:1179:16:1179:16:1179:Infinity":159,"b:1181:4:1188:Infinity:undefined:undefined:undefined:undefined":160,"s:1181:4:1188:Infinity":347,"b:1181:8:1181:18:1181:18:1181:45":161,"s:1182:6:1187:Infinity":348,"s:1190:4:1325:Infinity":349,"s:1191:21:1191:Infinity":350,"s:1193:8:1195:Infinity":351,"b:1194:12:1194:Infinity:1195:12:1195:Infinity":162,"b:1193:8:1193:47:1193:47:1193:Infinity":163,"s:1197:30:1201:Infinity":352,"b:1198:10:1200:Infinity:1201:10:1201:Infinity":164,"f:1199:17:1199:18":37,"s:1199:27:1199:53":353,"f:1200:20:1200:21":38,"s:1200:30:1200:74":354,"b:1203:6:1209:Infinity:undefined:undefined:undefined:undefined":165,"s:1203:6:1209:Infinity":355,"s:1204:8:1208:Infinity":356,"s:1211:21:1211:Infinity":357,"b:1212:6:1219:Infinity:undefined:undefined:undefined:undefined":166,"s:1212:6:1219:Infinity":358,"s:1213:8:1218:Infinity":359,"s:1221:23:1227:Infinity":360,"s:1228:12:1230:Infinity":361,"b:1228:21:1228:38:1228:38:1228:Infinity":167,"f:1229:13:1229:14":39,"s:1229:22:1229:42":362,"b:1229:29:1229:39:1229:39:1229:41":168,"s:1232:26:1247:Infinity":363,"s:1249:28:1264:Infinity":364,"s:1266:29:1287:Infinity":365,"s:1289:23:1297:Infinity":366,"f:1289:23:1289:24":40,"s:1289:24:1297:Infinity":367,"b:1290:9:1290:17:1290:17:1290:21":169,"f:1290:25:1290:26":41,"s:1290:35:1297:10":368,"b:1291:26:1291:41:1291:41:1291:43":170,"b:1292:23:1292:35:1292:35:1292:44":171,"b:1293:23:1293:35:1293:35:1293:37":172,"b:1294:39:1294:64:1294:64:1294:Infinity":173,"b:1296:19:1296:53:1296:53:1296:Infinity":174,"s:1299:20:1299:Infinity":369,"b:1299:29:1299:49:1299:49:1299:51":175,"s:1300:22:1300:Infinity":370,"b:1300:31:1300:53:1300:53:1300:55":176,"s:1301:23:1301:Infinity":371,"b:1301:32:1301:55:1301:55:1301:57":177,"s:1303:22:1303:Infinity":372,"s:1305:6:1322:Infinity":373,"s:1324:6:1324:Infinity":374,"f:1328:8:1328:26":42,"s:1329:69:1329:Infinity":375,"b:1329:41:1329:45":178,"b:1329:55:1329:65":179,"b:1329:69:1329:77:1329:77:1329:Infinity":180,"b:1331:4:1337:Infinity:undefined:undefined:undefined:undefined":181,"s:1331:4:1337:Infinity":376,"b:1331:8:1331:17:1331:17:1331:43":182,"s:1332:6:1336:Infinity":377,"s:1339:4:1357:Infinity":378,"s:1340:39:1340:Infinity":379,"s:1341:6:1350:Infinity":380,"s:1352:6:1356:Infinity":381,"f:1360:8:1360:24":43,"s:1361:73:1361:Infinity":382,"b:1361:26:1361:38":183,"b:1361:46:1361:49":184,"b:1361:59:1361:69":185,"s:1363:4:1389:Infinity":383,"s:1364:6:1364:Infinity":384,"s:1365:28:1365:Infinity":385,"s:1366:22:1371:Infinity":386,"s:1373:6:1386:Infinity":387,"f:1378:31:1378:32":44,"s:1378:42:1383:12":388,"s:1388:6:1388:Infinity":389,"f:1392:8:1392:26":45,"s:1398:8:1398:Infinity":390,"b:1395:18:1395:Infinity":186,"b:1396:14:1396:Infinity":187,"b:1397:16:1397:Infinity":188,"s:1400:4:1431:Infinity":391,"s:1401:6:1401:Infinity":392,"s:1402:28:1402:Infinity":393,"s:1403:22:1408:Infinity":394,"s:1409:23:1409:Infinity":395,"s:1411:6:1424:Infinity":396,"f:1416:32:1416:33":46,"s:1416:43:1421:12":397,"s:1426:6:1430:Infinity":398,"f:1434:8:1434:22":47,"s:1435:53:1435:Infinity":399,"b:1435:26:1435:29":189,"b:1435:39:1435:49":190,"s:1437:4:1469:Infinity":400,"s:1438:6:1438:Infinity":401,"s:1439:28:1439:Infinity":402,"s:1440:25:1442:Infinity":403,"f:1441:16:1441:17":48,"s:1441:26:1441:76":404,"b:1441:26:1441:48:1441:48:1441:76":191,"s:1444:49:1444:Infinity":405,"s:1445:6:1452:Infinity":406,"s:1446:21:1446:Infinity":407,"b:1446:21:1446:43:1446:43:1446:Infinity":192,"s:1447:20:1447:Infinity":408,"b:1447:20:1447:61:1447:61:1447:Infinity":193,"b:1448:8:1450:Infinity:undefined:undefined:undefined:undefined":194,"s:1448:8:1450:Infinity":409,"s:1449:10:1449:Infinity":410,"s:1451:8:1451:Infinity":411,"s:1454:26:1461:Infinity":412,"f:1455:13:1455:14":49,"s:1455:38:1459:10":413,"f:1460:14:1460:15":50,"s:1460:24:1460:39":414,"s:1463:6:1466:Infinity":415,"s:1468:6:1468:Infinity":416,"f:1472:8:1472:22":51,"s:1473:60:1473:Infinity":417,"b:1473:46:1473:56":195,"s:1475:4:1512:Infinity":418,"s:1476:19:1476:Infinity":419,"s:1477:20:1477:Infinity":420,"b:1479:6:1485:Infinity:undefined:undefined:undefined:undefined":196,"s:1479:6:1485:Infinity":421,"b:1479:10:1479:19:1479:19:1479:27":197,"s:1480:8:1484:Infinity":422,"s:1487:24:1487:Infinity":423,"b:1487:24:1487:43:1487:43:1487:Infinity":198,"s:1488:25:1488:Infinity":424,"b:1488:25:1488:45:1488:45:1488:Infinity":199,"s:1489:23:1489:Infinity":425,"s:1490:24:1490:Infinity":426,"s:1491:25:1491:Infinity":427,"f:1491:46:1491:47":52,"s:1491:55:1491:73":428,"s:1493:26:1496:Infinity":429,"f:1494:8:1494:9":53,"s:1495:10:1495:Infinity":430,"s:1498:6:1509:Infinity":431,"b:1500:16:1500:40:1500:40:1500:64:1500:64:1500:Infinity":200,"b:1501:17:1501:42:1501:42:1501:67:1501:67:1501:Infinity":201,"f:1505:45:1505:46":54,"s:1505:54:1505:73":432,"f:1506:47:1506:48":55,"s:1506:56:1506:74":433,"s:1511:6:1511:Infinity":434,"f:1515:8:1515:22":56,"s:1516:58:1516:Infinity":435,"b:1516:31:1516:34":202,"b:1516:44:1516:54":203,"s:1518:4:1555:Infinity":436,"s:1519:23:1519:Infinity":437,"s:1521:8:1526:Infinity":438,"b:1521:8:1521:Infinity:1522:8:1522:Infinity:1523:8:1523:Infinity:1524:9:1526:Infinity":204,"b:1525:12:1525:Infinity:1526:12:1526:Infinity":205,"b:1524:9:1524:42:1524:42:1524:Infinity":206,"b:1528:6:1534:Infinity:undefined:undefined:undefined:undefined":207,"s:1528:6:1534:Infinity":439,"s:1529:8:1533:Infinity":440,"s:1536:24:1540:Infinity":441,"s:1541:24:1541:Infinity":442,"s:1543:6:1552:Infinity":443,"s:1554:6:1554:Infinity":444,"f:1562:8:1562:20":57,"s:1574:8:1574:Infinity":445,"b:1566:17:1566:Infinity":208,"b:1570:18:1570:Infinity":209,"b:1571:16:1571:Infinity":210,"b:1574:8:1574:16:1574:16:1574:Infinity":211,"b:1576:4:1583:Infinity:undefined:undefined:undefined:undefined":212,"s:1576:4:1583:Infinity":446,"b:1576:8:1576:17:1576:17:1576:27":213,"s:1577:6:1582:Infinity":447,"s:1585:27:1585:Infinity":448,"s:1586:31:1588:Infinity":449,"b:1587:8:1587:Infinity:1588:8:1588:Infinity":214,"f:1587:21:1587:22":58,"s:1587:31:1587:43":450,"s:1590:6:1590:Infinity":451,"b:1590:49:1590:60:1590:60:1590:Infinity":215,"b:1590:6:1590:18:1590:18:1590:49":216,"s:1591:28:1596:Infinity":452,"b:1597:4:1603:Infinity:undefined:undefined:undefined:undefined":217,"s:1597:4:1603:Infinity":453,"s:1598:6:1602:Infinity":454,"s:1605:4:1637:Infinity":455,"s:1606:31:1606:Infinity":456,"b:1606:31:1606:61:1606:61:1606:Infinity":218,"s:1607:29:1607:Infinity":457,"b:1607:36:1607:47:1607:47:1607:65":219,"s:1608:28:1608:Infinity":458,"s:1610:24:1623:Infinity":459,"b:1615:27:1615:44:1615:44:1615:Infinity":220,"b:1620:28:1620:41:1620:41:1620:57":221,"s:1625:6:1634:Infinity":460,"b:1630:18:1630:28:1630:28:1630:Infinity":222,"s:1636:6:1636:Infinity":461,"f:1640:8:1640:23":59,"s:1650:8:1650:Infinity":462,"b:1647:14:1647:Infinity":223,"b:1649:16:1649:Infinity":224,"b:1650:8:1650:16:1650:16:1650:Infinity":225,"b:1652:4:1658:Infinity:undefined:undefined:undefined:undefined":226,"s:1652:4:1658:Infinity":463,"b:1652:8:1652:18:1652:18:1652:45":227,"s:1653:6:1657:Infinity":464,"s:1660:4:1699:Infinity":465,"s:1661:22:1661:Infinity":466,"s:1662:28:1662:Infinity":467,"s:1663:31:1665:Infinity":468,"b:1664:10:1664:Infinity:1665:10:1665:Infinity":228,"f:1664:23:1664:24":60,"s:1664:33:1664:45":469,"s:1666:35:1669:Infinity":470,"s:1670:29:1672:Infinity":471,"s:1673:23:1684:Infinity":472,"b:1679:12:1679:Infinity:1680:12:1680:Infinity":229,"f:1679:22:1679:23":61,"s:1679:32:1679:73":473,"b:1681:42:1681:59:1681:59:1681:Infinity":230,"b:1683:15:1683:26:1683:26:1683:Infinity":231,"s:1686:6:1696:Infinity":474,"b:1690:45:1690:68:1690:68:1690:Infinity":232,"s:1698:6:1698:Infinity":475,"f:1702:8:1702:23":62,"s:1710:8:1710:Infinity":476,"b:1705:22:1705:Infinity":233,"b:1706:14:1706:Infinity":234,"b:1709:16:1709:Infinity":235,"b:1710:8:1710:16:1710:16:1710:Infinity":236,"b:1712:4:1718:Infinity:undefined:undefined:undefined:undefined":237,"s:1712:4:1718:Infinity":477,"b:1712:8:1712:18:1712:18:1712:45":238,"s:1713:6:1717:Infinity":478,"s:1720:4:1745:Infinity":479,"s:1721:28:1721:Infinity":480,"s:1722:24:1731:Infinity":481,"b:1728:12:1728:Infinity:1729:12:1729:Infinity":239,"f:1728:30:1728:31":63,"s:1728:40:1728:52":482,"s:1733:6:1742:Infinity":483,"s:1744:6:1744:Infinity":484,"f:1748:8:1748:16":64,"s:1749:65:1749:Infinity":485,"b:1749:37:1749:41":240,"b:1749:51:1749:61":241,"b:1749:65:1749:73:1749:73:1749:Infinity":242,"s:1751:4:1767:Infinity":486,"s:1752:28:1752:Infinity":487,"s:1753:21:1758:Infinity":488,"s:1760:6:1764:Infinity":489,"s:1766:6:1766:Infinity":490,"f:1774:8:1774:20":65,"s:1783:8:1783:Infinity":491,"b:1777:18:1777:Infinity":243,"b:1782:16:1782:Infinity":244,"b:1783:8:1783:16:1783:16:1783:Infinity":245,"b:1785:4:1791:Infinity:undefined:undefined:undefined:undefined":246,"s:1785:4:1791:Infinity":492,"b:1785:8:1785:21:1785:21:1785:30":247,"s:1786:6:1790:Infinity":493,"s:1793:4:1820:Infinity":494,"s:1794:31:1794:Infinity":495,"b:1794:31:1794:61:1794:61:1794:Infinity":248,"s:1795:29:1795:Infinity":496,"b:1795:36:1795:47:1795:47:1795:65":249,"s:1796:28:1796:Infinity":497,"s:1798:21:1806:Infinity":498,"b:1802:25:1802:42:1802:42:1802:Infinity":250,"b:1804:26:1804:39:1804:39:1804:55":251,"s:1808:6:1817:Infinity":499,"b:1815:12:1815:Infinity:1816:12:1816:Infinity":252,"s:1819:6:1819:Infinity":500,"f:1823:8:1823:22":66,"s:1824:54:1824:Infinity":501,"b:1824:40:1824:50":253,"b:1824:54:1824:62:1824:62:1824:Infinity":254,"b:1826:4:1832:Infinity:undefined:undefined:undefined:undefined":255,"s:1826:4:1832:Infinity":502,"s:1827:6:1831:Infinity":503,"s:1834:4:1848:Infinity":504,"s:1835:6:1835:Infinity":505,"s:1837:6:1845:Infinity":506,"b:1841:19:1841:30:1841:30:1841:Infinity":256,"s:1847:6:1847:Infinity":507,"f:1851:8:1851:21":67,"s:1852:45:1852:Infinity":508,"b:1852:31:1852:41":257,"b:1852:45:1852:53:1852:53:1852:Infinity":258,"b:1854:4:1860:Infinity:undefined:undefined:undefined:undefined":259,"s:1854:4:1860:Infinity":509,"b:1854:8:1854:20:1854:20:1854:49":260,"s:1855:6:1859:Infinity":510,"s:1862:4:1876:Infinity":511,"s:1863:28:1863:Infinity":512,"s:1864:21:1864:Infinity":513,"s:1866:6:1873:Infinity":514,"s:1875:6:1875:Infinity":515,"f:1879:8:1879:30":68,"s:1880:36:1880:Infinity":516,"b:1880:22:1880:32":261,"b:1880:36:1880:44:1880:44:1880:Infinity":262,"s:1882:4:1900:Infinity":517,"s:1883:28:1883:Infinity":518,"s:1884:23:1884:Infinity":519,"s:1886:6:1893:Infinity":520,"s:1895:6:1899:Infinity":521,"f:1903:8:1903:21":69,"s:1912:8:1912:Infinity":522,"b:1908:16:1908:Infinity":263,"b:1909:25:1909:Infinity":264,"b:1910:25:1910:Infinity":265,"b:1911:24:1911:Infinity":266,"b:1912:8:1912:16:1912:16:1912:Infinity":267,"b:1914:4:1920:Infinity:undefined:undefined:undefined:undefined":268,"s:1914:4:1920:Infinity":523,"b:1914:8:1914:17:1914:17:1914:43":269,"s:1915:6:1919:Infinity":524,"s:1922:4:2019:Infinity":525,"s:1923:29:1923:Infinity":526,"b:1923:36:1923:47:1923:47:1923:65":270,"s:1924:43:1924:Infinity":527,"s:1926:22:1926:Infinity":528,"s:1927:30:1930:Infinity":529,"s:1931:25:1938:Infinity":530,"b:1934:44:1934:62:1934:62:1934:Infinity":271,"s:1940:29:1944:Infinity":531,"f:1940:47:1940:48":70,"s:1941:8:1943:Infinity":532,"b:1942:17:1942:30:1942:30:1942:32":272,"s:1945:26:1948:Infinity":533,"s:1950:26:1950:Infinity":534,"f:1950:42:1950:43":71,"s:1950:52:1950:63":535,"s:1951:29:1955:Infinity":536,"s:1956:24:1958:Infinity":537,"b:1957:10:1957:Infinity:1958:10:1958:Infinity":273,"s:1959:24:1961:Infinity":538,"b:1960:10:1960:Infinity:1961:10:1961:Infinity":274,"s:1962:23:1964:Infinity":539,"b:1963:10:1963:Infinity:1964:10:1964:Infinity":275,"s:1967:8:1969:Infinity":540,"b:1967:8:1967:Infinity:1968:8:1968:Infinity:1969:8:1969:Infinity":276,"s:1970:22:1970:Infinity":541,"s:1972:44:2008:Infinity":542,"b:1976:16:1976:26:1976:26:1976:Infinity":277,"f:1979:42:1979:43":72,"s:1979:52:1990:9":543,"f:1980:38:1980:39":73,"s:1980:56:1984:12":544,"f:1985:36:1985:37":74,"s:1985:54:1989:12":545,"b:1996:12:2000:Infinity:2001:12:2001:Infinity":278,"b:2004:14:2006:Infinity:2007:14:2007:Infinity":279,"f:2005:31:2005:32":75,"s:2005:41:2005:66":546,"s:2011:8:2011:Infinity":547,"b:2011:56:2011:66:2011:66:2011:Infinity":280,"b:2011:8:2011:34:2011:34:2011:56":281,"s:2012:12:2012:Infinity":548,"s:2013:6:2013:Infinity":549,"s:2014:6:2014:Infinity":550,"s:2016:6:2016:Infinity":551,"s:2018:6:2018:Infinity":552,"f:2022:8:2022:23":76,"s:2030:8:2030:Infinity":553,"b:2027:16:2027:Infinity":282,"b:2029:16:2029:Infinity":283,"b:2030:8:2030:16:2030:16:2030:Infinity":284,"b:2032:4:2038:Infinity:undefined:undefined:undefined:undefined":285,"s:2032:4:2038:Infinity":554,"b:2032:8:2032:19:2032:19:2032:29:2032:29:2032:36":286,"s:2033:6:2037:Infinity":555,"s:2040:4:2129:Infinity":556,"s:2041:43:2041:Infinity":557,"s:2042:23:2042:Infinity":558,"b:2043:6:2050:Infinity:undefined:undefined:undefined:undefined":287,"s:2043:6:2050:Infinity":559,"s:2044:8:2049:Infinity":560,"s:2052:53:2052:Infinity":561,"s:2053:27:2055:Infinity":562,"b:2054:10:2054:Infinity:2055:10:2055:Infinity":288,"s:2058:8:2063:Infinity":563,"b:2062:12:2062:Infinity:2063:12:2063:Infinity":289,"b:2058:8:2058:Infinity:2059:8:2059:Infinity:2060:8:2060:Infinity:2061:8:2061:Infinity":290,"s:2065:37:2069:Infinity":564,"s:2070:19:2070:Infinity":565,"s:2073:8:2084:Infinity":566,"b:2074:12:2083:Infinity:2084:12:2084:Infinity":291,"b:2073:8:2073:40:2073:40:2073:Infinity":292,"f:2076:22:2076:23":77,"s:2076:31:2076:51":567,"f:2078:19:2078:20":78,"s:2078:29:2083:16":568,"b:2081:18:2081:Infinity:2082:18:2082:Infinity":293,"s:2087:8:2098:Infinity":569,"b:2088:12:2097:Infinity:2098:12:2098:Infinity":294,"b:2087:8:2087:40:2087:40:2087:Infinity":295,"f:2090:22:2090:23":79,"s:2090:31:2090:51":570,"f:2092:19:2092:20":80,"s:2092:29:2097:16":571,"b:2095:18:2095:Infinity:2096:18:2096:Infinity":296,"s:2100:31:2100:Infinity":572,"s:2101:24:2103:Infinity":573,"b:2102:10:2102:Infinity:2103:10:2103:Infinity":297,"s:2104:24:2106:Infinity":574,"b:2105:10:2105:Infinity:2106:10:2106:Infinity":298,"s:2108:23:2122:Infinity":575,"b:2113:27:2113:51:2113:51:2113:74":299,"b:2114:49:2114:60:2114:60:2114:Infinity":300,"b:2119:19:2119:48:2119:48:2119:Infinity":301,"s:2124:22:2124:Infinity":576,"s:2126:6:2126:Infinity":577,"s:2128:6:2128:Infinity":578,"f:2132:10:2132:26":81,"s:2133:19:2136:Infinity":579,"f:2136:14:2136:15":82,"s:2136:25:2136:42":580,"s:2138:23:2142:Infinity":581,"s:2144:19:2154:Infinity":582,"f:2145:11:2145:12":83,"s:2147:10:2147:Infinity":583,"b:2147:24:2147:48:2147:48:2147:50":302,"b:2147:54:2147:78:2147:78:2147:80":303,"s:2148:22:2151:Infinity":584,"f:2149:10:2149:11":84,"s:2149:26:2149:Infinity":585,"b:2149:60:2149:64:2149:64:2149:Infinity":304,"s:2152:8:2152:Infinity":586,"f:2154:12:2154:13":85,"s:2154:22:2154:39":587,"s:2156:21:2156:Infinity":588,"f:2156:35:2156:36":86,"s:2156:45:2156:59":589,"b:2157:4:2159:Infinity:undefined:undefined:undefined:undefined":305,"s:2157:4:2159:Infinity":590,"s:2158:6:2158:Infinity":591,"f:2158:26:2158:27":87,"s:2158:36:2158:47":592,"s:2161:4:2161:Infinity":593,"f:2161:42:2161:43":88,"s:2161:52:2161:59":594,"f:2164:16:2164:Infinity":89,"b:2168:4:2170:Infinity:undefined:undefined:undefined:undefined":306,"s:2168:4:2170:Infinity":595,"s:2169:6:2169:Infinity":596,"s:2172:21:2172:Infinity":597,"s:2173:30:2180:Infinity":598,"s:2182:20:2182:Infinity":599,"b:2183:4:2189:Infinity:undefined:undefined:undefined:undefined":307,"s:2183:4:2189:Infinity":600,"s:2184:6:2188:Infinity":601,"b:2185:8:2187:Infinity:undefined:undefined:undefined:undefined":308,"s:2185:8:2187:Infinity":602,"s:2186:10:2186:Infinity":603,"s:2191:4:2191:Infinity":604,"f:2194:16:2194:Infinity":90,"s:2198:23:2198:Infinity":605,"s:2199:21:2199:Infinity":606,"s:2200:26:2200:Infinity":607,"s:2202:4:2239:Infinity":608,"s:2203:23:2203:Infinity":609,"b:2204:6:2206:Infinity:undefined:undefined:undefined:undefined":309,"s:2204:6:2206:Infinity":610,"s:2205:8:2205:Infinity":611,"s:2208:53:2208:Infinity":612,"s:2209:27:2211:Infinity":613,"b:2210:10:2210:Infinity:2211:10:2211:Infinity":310,"s:2213:19:2213:Infinity":614,"s:2214:30:2218:Infinity":615,"f:2216:16:2216:17":91,"s:2216:25:2216:45":616,"f:2218:13:2218:14":92,"s:2218:23:2218:40":617,"s:2219:28:2223:Infinity":618,"f:2221:16:2221:17":93,"s:2221:25:2221:45":619,"f:2223:13:2223:14":94,"s:2223:23:2223:38":620,"s:2225:6:2238:Infinity":621,"b:2231:27:2231:51:2231:51:2231:74":311,"b:2235:19:2235:48:2235:48:2235:Infinity":312,"s:2241:4:2241:Infinity":622,"f:2244:10:2244:30":95,"s:2250:17:2250:Infinity":623,"b:2251:4:2253:Infinity:undefined:undefined:undefined:undefined":313,"s:2251:4:2253:Infinity":624,"s:2252:6:2252:Infinity":625,"s:2255:19:2257:Infinity":626,"b:2256:6:2256:30:2256:30:2256:58:2256:58:2256:Infinity":314,"b:2258:4:2268:Infinity:undefined:undefined:undefined:undefined":315,"s:2258:4:2268:Infinity":627,"s:2259:22:2261:Infinity":628,"f:2261:16:2261:17":96,"s:2261:25:2261:48":629,"s:2262:23:2264:Infinity":630,"f:2263:13:2263:14":97,"s:2263:22:2263:58":631,"f:2264:14:2264:15":98,"s:2264:29:2264:55":632,"s:2265:6:2267:Infinity":633,"b:2266:8:2266:37:2266:37:2266:70:2266:70:2266:Infinity":316,"b:2270:4:2272:Infinity:undefined:undefined:undefined:undefined":317,"s:2270:4:2272:Infinity":634,"s:2271:6:2271:Infinity":635,"s:2274:22:2276:Infinity":636,"b:2275:6:2275:35:2275:35:2275:59:2275:59:2275:Infinity":318,"s:2277:20:2277:Infinity":637,"b:2277:27:2277:54:2277:54:2277:68":319,"s:2279:4:2284:Infinity":638,"f:2287:10:2287:Infinity":99,"s:2293:4:2306:Infinity":639,"b:2294:6:2296:Infinity:undefined:undefined:undefined:undefined":320,"s:2294:6:2296:Infinity":640,"s:2295:8:2295:Infinity":641,"s:2297:20:2297:Infinity":642,"s:2298:22:2300:Infinity":643,"s:2301:6:2303:Infinity":644,"b:2302:10:2302:Infinity:2303:10:2303:Infinity":321,"s:2305:6:2305:Infinity":645,"f:2309:16:2309:Infinity":100,"b:2314:4:2316:Infinity:undefined:undefined:undefined:undefined":322,"s:2314:4:2316:Infinity":646,"s:2315:6:2315:Infinity":647,"s:2318:21:2329:Infinity":648,"s:2331:4:2337:Infinity":649,"b:2331:12:2331:29:2331:29:2331:33":323,"f:2331:37:2331:38":101,"s:2331:47:2337:6":650,"b:2332:22:2332:37:2332:37:2332:39":324,"b:2333:22:2333:37:2333:37:2333:46":325,"b:2334:21:2334:35:2334:35:2334:37":326,"b:2335:23:2335:39:2335:39:2335:41":327,"b:2336:20:2336:33:2336:33:2336:43":328,"f:2340:16:2340:Infinity":102,"b:2344:4:2346:Infinity:undefined:undefined:undefined:undefined":329,"s:2344:4:2346:Infinity":651,"s:2345:6:2345:Infinity":652,"s:2348:19:2355:Infinity":653,"s:2357:4:2361:Infinity":654,"b:2357:12:2357:27:2357:27:2357:31":330,"f:2357:35:2357:36":103,"s:2357:45:2361:6":655,"b:2358:17:2358:27:2358:27:2358:29":331,"b:2359:22:2359:37:2359:37:2359:39":332,"b:2360:24:2360:41:2360:41:2360:51":333,"f:2364:16:2364:Infinity":104,"b:2368:4:2370:Infinity:undefined:undefined:undefined:undefined":334,"s:2368:4:2370:Infinity":656,"s:2369:6:2369:Infinity":657,"s:2372:19:2379:Infinity":658,"s:2381:4:2385:Infinity":659,"b:2381:12:2381:27:2381:27:2381:31":335,"f:2381:35:2381:36":105,"s:2381:45:2385:6":660,"b:2382:17:2382:27:2382:27:2382:29":336,"b:2383:22:2383:37:2383:37:2383:39":337,"b:2384:25:2384:43:2384:43:2384:44":338,"f:2388:16:2388:Infinity":106,"s:2393:33:2393:Infinity":661,"s:2394:44:2394:Infinity":662,"b:2396:4:2402:Infinity:2399:11:2402:Infinity":339,"s:2396:4:2402:Infinity":663,"s:2397:6:2397:Infinity":664,"s:2398:6:2398:Infinity":665,"s:2400:6:2400:Infinity":666,"s:2401:6:2401:Infinity":667,"s:2404:19:2411:Infinity":668,"s:2413:4:2418:Infinity":669,"b:2413:12:2413:27:2413:27:2413:31":340,"f:2413:35:2413:36":107,"s:2413:45:2418:6":670,"b:2414:17:2414:27:2414:27:2414:29":341,"b:2415:19:2415:31:2415:31:2415:44":342,"b:2416:22:2416:37:2416:37:2416:39":343,"b:2417:24:2417:41:2417:41:2417:51":344,"f:2421:10:2421:Infinity":108,"b:2425:4:2427:Infinity:undefined:undefined:undefined:undefined":345,"s:2425:4:2427:Infinity":671,"s:2426:6:2426:Infinity":672,"s:2429:22:2455:Infinity":673,"f:2429:22:2429:28":109,"b:2430:6:2433:Infinity:undefined:undefined:undefined:undefined":346,"s:2430:6:2433:Infinity":674,"b:2430:10:2430:45:2430:45:2430:74":347,"s:2431:8:2431:Infinity":675,"s:2432:8:2432:Infinity":676,"b:2434:6:2437:Infinity:undefined:undefined:undefined:undefined":348,"s:2434:6:2437:Infinity":677,"b:2434:10:2434:43:2434:43:2434:70":349,"s:2435:8:2435:Infinity":678,"s:2436:8:2436:Infinity":679,"b:2438:6:2441:Infinity:undefined:undefined:undefined:undefined":350,"s:2438:6:2441:Infinity":680,"b:2438:10:2438:43:2438:43:2438:70":351,"s:2439:8:2439:Infinity":681,"s:2440:8:2440:Infinity":682,"b:2442:6:2445:Infinity:undefined:undefined:undefined:undefined":352,"s:2442:6:2445:Infinity":683,"b:2442:10:2442:42:2442:42:2442:68":353,"s:2443:8:2443:Infinity":684,"s:2444:8:2444:Infinity":685,"b:2446:6:2453:Infinity:undefined:undefined:undefined:undefined":354,"s:2446:6:2453:Infinity":686,"s:2447:8:2452:Infinity":687,"b:2448:10:2451:Infinity:undefined:undefined:undefined:undefined":355,"s:2448:10:2451:Infinity":688,"b:2448:14:2448:49:2448:49:2448:75":356,"s:2449:12:2449:Infinity":689,"s:2450:12:2450:Infinity":690,"s:2454:6:2454:Infinity":691,"s:2457:8:2457:Infinity":692,"s:2458:16:2458:Infinity":693,"s:2459:4:2466:Infinity":694,"b:2459:11:2459:33:2459:33:2459:46":357,"s:2460:22:2460:Infinity":695,"b:2461:6:2463:Infinity:undefined:undefined:undefined:undefined":358,"s:2461:6:2463:Infinity":696,"s:2462:8:2462:Infinity":697,"s:2464:6:2464:Infinity":698,"s:2465:6:2465:Infinity":699,"f:2469:10:2469:37":110,"s:2479:27:2479:Infinity":700,"b:2479:40:2479:61:2479:61:2479:Infinity":359,"s:2480:29:2480:Infinity":701,"b:2480:44:2480:67:2480:67:2480:Infinity":360,"b:2482:4:2487:Infinity:undefined:undefined:undefined:undefined":361,"s:2482:4:2487:Infinity":702,"s:2483:20:2483:Infinity":703,"b:2484:6:2486:Infinity:undefined:undefined:undefined:undefined":362,"s:2484:6:2486:Infinity":704,"s:2485:8:2485:Infinity":705,"b:2489:4:2517:Infinity:undefined:undefined:undefined:undefined":363,"s:2489:4:2517:Infinity":706,"b:2489:8:2489:28:2489:28:2489:44":364,"s:2490:23:2501:Infinity":707,"f:2492:14:2492:15":111,"s:2493:32:2495:Infinity":708,"b:2494:12:2494:41:2494:41:2494:74:2494:74:2494:Infinity":365,"s:2496:10:2499:Infinity":709,"b:2497:12:2497:Infinity:2498:12:2498:Infinity:2499:12:2499:Infinity":366,"b:2503:6:2516:Infinity:undefined:undefined:undefined:undefined":367,"s:2503:6:2516:Infinity":710,"s:2504:25:2507:Infinity":711,"f:2506:18:2506:19":112,"s:2506:27:2506:50":712,"f:2507:15:2507:16":113,"s:2507:24:2507:30":713,"s:2509:10:2509:Infinity":714,"b:2509:10:2509:47:2509:47:2509:Infinity":368,"s:2510:22:2512:Infinity":715,"f:2511:15:2511:16":114,"s:2511:23:2511:53":716,"f:2512:16:2512:17":115,"s:2512:26:2512:63":717,"b:2513:8:2515:Infinity:undefined:undefined:undefined:undefined":369,"s:2513:8:2515:Infinity":718,"s:2514:10:2514:Infinity":719,"b:2519:4:2533:Infinity:undefined:undefined:undefined:undefined":370,"s:2519:4:2533:Infinity":720,"s:2520:25:2520:Infinity":721,"b:2520:25:2520:62:2520:62:2520:Infinity":371,"s:2521:21:2528:Infinity":722,"f:2525:13:2525:14":116,"s:2526:21:2526:Infinity":723,"b:2526:28:2526:52:2526:52:2526:76:2526:76:2526:78":372,"s:2527:8:2527:Infinity":724,"b:2527:15:2527:38:2527:38:2527:Infinity":373,"b:2530:6:2532:Infinity:undefined:undefined:undefined:undefined":374,"s:2530:6:2532:Infinity":725,"s:2531:8:2531:Infinity":726,"b:2535:4:2540:Infinity:undefined:undefined:undefined:undefined":375,"s:2535:4:2540:Infinity":727,"s:2536:25:2536:Infinity":728,"b:2537:6:2539:Infinity:undefined:undefined:undefined:undefined":376,"s:2537:6:2539:Infinity":729,"s:2538:8:2538:Infinity":730,"b:2542:4:2558:Infinity:undefined:undefined:undefined:undefined":377,"s:2542:4:2558:Infinity":731,"s:2543:23:2554:Infinity":732,"f:2545:14:2545:15":117,"s:2546:32:2548:Infinity":733,"b:2547:12:2547:41:2547:41:2547:74:2547:74:2547:Infinity":378,"s:2549:10:2552:Infinity":734,"b:2550:12:2550:Infinity:2551:12:2551:Infinity:2552:12:2552:Infinity":379,"b:2555:6:2557:Infinity:undefined:undefined:undefined:undefined":380,"s:2555:6:2557:Infinity":735,"s:2556:8:2556:Infinity":736,"s:2560:4:2560:Infinity":737,"f:2563:10:2563:Infinity":118,"b:2568:4:2570:Infinity:undefined:undefined:undefined:undefined":381,"s:2568:4:2570:Infinity":738,"s:2569:6:2569:Infinity":739,"s:2571:4:2571:Infinity":740,"f:2574:10:2574:Infinity":119,"b:2579:4:2581:Infinity:undefined:undefined:undefined:undefined":382,"s:2579:4:2581:Infinity":741,"s:2580:6:2580:Infinity":742,"s:2582:18:2582:Infinity":743,"s:2583:4:2585:Infinity":744,"f:2590:8:2590:27":120,"s:2598:8:2598:Infinity":745,"b:2595:20:2595:Infinity":383,"b:2596:17:2596:Infinity":384,"b:2597:16:2597:Infinity":385,"b:2598:8:2598:16:2598:16:2598:Infinity":386,"b:2600:4:2607:Infinity:undefined:undefined:undefined:undefined":387,"s:2600:4:2607:Infinity":746,"b:2600:8:2600:26:2600:26:2600:61":388,"s:2601:6:2606:Infinity":747,"s:2609:25:2609:Infinity":748,"b:2610:4:2617:Infinity:undefined:undefined:undefined:undefined":389,"s:2610:4:2617:Infinity":749,"s:2611:6:2616:Infinity":750,"s:2619:76:2619:Infinity":751,"s:2621:4:2757:Infinity":752,"s:2623:27:2623:Infinity":753,"b:2624:6:2624:Infinity:undefined:undefined:undefined:undefined":390,"s:2624:6:2624:Infinity":754,"s:2624:21:2624:Infinity":755,"b:2625:6:2625:Infinity:undefined:undefined:undefined:undefined":391,"s:2625:6:2625:Infinity":756,"s:2625:21:2625:Infinity":757,"s:2628:6:2662:Infinity":758,"s:2629:8:2629:Infinity":759,"s:2630:24:2630:Infinity":760,"b:2631:8:2643:Infinity:undefined:undefined:undefined:undefined":392,"s:2631:8:2643:Infinity":761,"s:2632:10:2636:Infinity":762,"s:2637:10:2642:Infinity":763,"s:2644:20:2644:Infinity":764,"b:2644:20:2644:53:2644:53:2644:70:2644:70:2644:Infinity":393,"s:2645:8:2649:Infinity":765,"b:2648:31:2648:48:2648:48:2648:51":394,"b:2648:66:2648:83:2648:83:2648:86":395,"s:2651:8:2655:Infinity":766,"s:2656:8:2661:Infinity":767,"s:2665:31:2670:Infinity":768,"b:2671:6:2671:Infinity:undefined:undefined:undefined:undefined":396,"s:2671:6:2671:Infinity":769,"s:2671:21:2671:Infinity":770,"b:2672:6:2672:Infinity:undefined:undefined:undefined:undefined":397,"s:2672:6:2672:Infinity":771,"s:2672:21:2672:Infinity":772,"s:2674:6:2696:Infinity":773,"s:2675:30:2675:Infinity":774,"s:2676:28:2676:Infinity":775,"b:2677:8:2689:Infinity:2683:15:2689:Infinity":398,"s:2677:8:2689:Infinity":776,"s:2678:10:2682:Infinity":777,"s:2684:10:2688:Infinity":778,"s:2691:8:2695:Infinity":779,"s:2699:26:2703:Infinity":780,"b:2704:6:2730:Infinity:2724:13:2730:Infinity":399,"s:2704:6:2730:Infinity":781,"s:2705:8:2723:Infinity":782,"s:2706:10:2711:Infinity":783,"s:2712:10:2716:Infinity":784,"s:2718:10:2722:Infinity":785,"s:2725:8:2729:Infinity":786,"s:2732:18:2736:Infinity":787,"b:2734:24:2734:40:2734:40:2734:Infinity":400,"b:2735:24:2735:40:2735:40:2735:Infinity":401,"s:2738:6:2750:Infinity":788,"s:2752:6:2756:Infinity":789,"b:2754:33:2754:49:2754:49:2754:Infinity":402,"f:2764:8:2764:35":121,"s:2771:8:2771:Infinity":790,"b:2768:15:2768:Infinity":403,"b:2769:18:2769:Infinity":404,"b:2770:16:2770:Infinity":405,"b:2771:8:2771:16:2771:16:2771:Infinity":406,"b:2775:4:2780:Infinity:2777:11:2780:Infinity":407,"s:2775:4:2780:Infinity":791,"b:2775:8:2775:22:2775:22:2775:54":408,"s:2776:6:2776:Infinity":792,"s:2778:18:2778:Infinity":793,"s:2779:6:2779:Infinity":794,"b:2782:4:2789:Infinity:undefined:undefined:undefined:undefined":409,"s:2782:4:2789:Infinity":795,"s:2783:6:2788:Infinity":796,"s:2791:21:2795:Infinity":797,"b:2796:4:2807:Infinity:undefined:undefined:undefined:undefined":410,"s:2796:4:2807:Infinity":798,"b:2796:8:2796:35:2796:35:2796:49:2796:49:2796:58":411,"s:2797:6:2806:Infinity":799,"s:2809:4:3013:Infinity":800,"s:2811:23:2811:Infinity":801,"b:2811:23:2811:43:2811:43:2811:Infinity":412,"s:2812:22:2812:Infinity":802,"s:2813:27:2815:Infinity":803,"b:2814:10:2814:Infinity:2815:10:2815:Infinity":413,"s:2817:19:2817:Infinity":804,"b:2817:19:2817:39:2817:39:2817:56:2817:56:2817:Infinity":414,"s:2818:26:2818:Infinity":805,"b:2818:26:2818:50:2818:50:2818:Infinity":415,"s:2819:43:2822:Infinity":806,"b:2820:12:2820:37:2820:37:2820:Infinity":416,"b:2821:12:2821:40:2821:40:2821:Infinity":417,"s:2825:30:2825:Infinity":807,"s:2827:8:2828:Infinity":808,"b:2827:8:2827:Infinity:2828:8:2828:Infinity":418,"s:2830:8:2830:Infinity":809,"b:2830:8:2830:21:2830:21:2830:Infinity":419,"s:2832:8:2834:Infinity":810,"b:2832:8:2832:Infinity:2833:8:2833:Infinity:2834:8:2834:Infinity":420,"s:2835:19:2835:Infinity":811,"s:2836:21:2836:Infinity":812,"s:2838:8:2839:Infinity":813,"b:2838:8:2838:Infinity:2839:8:2839:Infinity":421,"s:2840:22:2840:Infinity":814,"s:2841:23:2841:Infinity":815,"s:2843:8:2844:Infinity":816,"b:2843:8:2843:Infinity:2844:8:2844:Infinity":422,"b:2846:6:2847:Infinity:2846:47:2847:Infinity":423,"s:2846:6:2847:Infinity":817,"s:2846:24:2846:Infinity":818,"b:2846:47:2847:Infinity:undefined:undefined:undefined:undefined":424,"s:2846:47:2847:Infinity":819,"s:2847:23:2847:Infinity":820,"b:2848:6:2848:Infinity:undefined:undefined:undefined:undefined":425,"s:2848:6:2848:Infinity":821,"s:2848:20:2848:Infinity":822,"b:2849:6:2849:Infinity:undefined:undefined:undefined:undefined":426,"s:2849:6:2849:Infinity":823,"s:2849:16:2849:Infinity":824,"b:2850:6:2850:Infinity:undefined:undefined:undefined:undefined":427,"s:2850:6:2850:Infinity":825,"s:2850:18:2850:Infinity":826,"b:2851:6:2851:Infinity:undefined:undefined:undefined:undefined":428,"s:2851:6:2851:Infinity":827,"s:2851:18:2851:Infinity":828,"b:2852:6:2853:Infinity:2852:40:2853:Infinity":429,"s:2852:6:2853:Infinity":829,"s:2852:20:2852:Infinity":830,"b:2852:40:2853:Infinity:undefined:undefined:undefined:undefined":430,"s:2852:40:2853:Infinity":831,"s:2853:24:2853:Infinity":832,"b:2854:6:2854:Infinity:undefined:undefined:undefined:undefined":431,"s:2854:6:2854:Infinity":833,"s:2854:20:2854:Infinity":834,"s:2857:22:2862:Infinity":835,"b:2858:10:2861:Infinity:2862:10:2862:Infinity":432,"f:2860:17:2860:18":122,"s:2860:29:2860:51":836,"s:2865:31:2865:Infinity":837,"s:2867:8:2869:Infinity":838,"b:2867:8:2869:13:2869:13:2869:Infinity":433,"f:2867:30:2867:31":123,"s:2868:10:2868:Infinity":839,"s:2872:22:2872:Infinity":840,"s:2873:30:2873:Infinity":841,"b:2874:6:2884:Infinity:undefined:undefined:undefined:undefined":434,"s:2874:6:2884:Infinity":842,"s:2875:8:2883:Infinity":843,"s:2876:10:2880:Infinity":844,"f:2878:20:2878:21":124,"s:2878:27:2878:42":845,"f:2879:17:2879:18":125,"s:2879:24:2879:30":846,"s:2888:8:2890:Infinity":847,"b:2888:8:2888:Infinity:2889:8:2889:Infinity:2890:8:2890:Infinity":435,"s:2893:30:2893:Infinity":848,"b:2894:6:2896:Infinity:undefined:undefined:undefined:undefined":436,"s:2894:6:2896:Infinity":849,"s:2895:8:2895:Infinity":850,"s:2898:6:2898:Infinity":851,"s:2899:6:2902:Infinity":852,"b:2904:6:2913:Infinity:undefined:undefined:undefined:undefined":437,"s:2904:6:2913:Infinity":853,"s:2905:8:2905:Infinity":854,"s:2906:8:2906:Infinity":855,"s:2907:8:2907:Infinity":856,"b:2908:8:2912:Infinity:undefined:undefined:undefined:undefined":438,"s:2908:8:2912:Infinity":857,"s:2909:10:2911:Infinity":858,"f:2910:50:2910:51":126,"s:2910:57:2910:77":859,"b:2914:6:2916:Infinity:undefined:undefined:undefined:undefined":439,"s:2914:6:2916:Infinity":860,"s:2915:8:2915:Infinity":861,"b:2918:6:2939:Infinity:2930:13:2939:Infinity":440,"s:2918:6:2939:Infinity":862,"s:2919:8:2929:Infinity":863,"s:2931:8:2938:Infinity":864,"s:2941:6:2953:Infinity":865,"s:2955:6:2964:Infinity":866,"s:2966:6:2971:Infinity":867,"s:2973:22:2973:Infinity":868,"b:2975:6:2986:Infinity:undefined:undefined:undefined:undefined":441,"s:2975:6:2986:Infinity":869,"s:2976:8:2985:Infinity":870,"s:2989:24:2989:Infinity":871,"b:2990:6:2992:Infinity:undefined:undefined:undefined:undefined":442,"s:2990:6:2992:Infinity":872,"s:2991:8:2991:Infinity":873,"s:2993:6:2993:Infinity":874,"s:2995:6:3006:Infinity":875,"b:3001:23:3001:36:3001:36:3001:Infinity":443,"s:3008:6:3012:Infinity":876,"b:3010:33:3010:49:3010:49:3010:Infinity":444}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/tools/handlers/arch-tools.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/tools/handlers/arch-tools.ts","statementMap":{"0":{"start":{"line":36,"column":2},"end":{"line":116,"column":null}},"1":{"start":{"line":41,"column":61},"end":{"line":41,"column":null}},"2":{"start":{"line":43,"column":6},"end":{"line":49,"column":null}},"3":{"start":{"line":44,"column":8},"end":{"line":48,"column":null}},"4":{"start":{"line":51,"column":6},"end":{"line":68,"column":null}},"5":{"start":{"line":52,"column":23},"end":{"line":52,"column":null}},"6":{"start":{"line":54,"column":23},"end":{"line":59,"column":null}},"7":{"start":{"line":61,"column":8},"end":{"line":61,"column":null}},"8":{"start":{"line":63,"column":8},"end":{"line":67,"column":null}},"9":{"start":{"line":75,"column":69},"end":{"line":75,"column":null}},"10":{"start":{"line":77,"column":6},"end":{"line":83,"column":null}},"11":{"start":{"line":78,"column":8},"end":{"line":82,"column":null}},"12":{"start":{"line":85,"column":6},"end":{"line":114,"column":null}},"13":{"start":{"line":86,"column":27},"end":{"line":90,"column":null}},"14":{"start":{"line":92,"column":8},"end":{"line":101,"column":null}},"15":{"start":{"line":93,"column":10},"end":{"line":100,"column":null}},"16":{"start":{"line":103,"column":8},"end":{"line":111,"column":null}},"17":{"start":{"line":113,"column":8},"end":{"line":113,"column":null}}},"fnMap":{"0":{"name":"createArchTools","decl":{"start":{"line":35,"column":16},"end":{"line":35,"column":32}},"loc":{"start":{"line":35,"column":54},"end":{"line":117,"column":null}},"line":35},"1":{"name":"(anonymous_1)","decl":{"start":{"line":40,"column":10},"end":{"line":40,"column":24}},"loc":{"start":{"line":40,"column":52},"end":{"line":69,"column":null}},"line":40},"2":{"name":"(anonymous_2)","decl":{"start":{"line":74,"column":10},"end":{"line":74,"column":23}},"loc":{"start":{"line":74,"column":51},"end":{"line":115,"column":null}},"line":74}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":21},"end":{"line":41,"column":37}},"type":"default-arg","locations":[{"start":{"line":41,"column":30},"end":{"line":41,"column":37}}],"line":41},"1":{"loc":{"start":{"line":41,"column":37},"end":{"line":41,"column":57}},"type":"default-arg","locations":[{"start":{"line":41,"column":47},"end":{"line":41,"column":57}}],"line":41},"2":{"loc":{"start":{"line":43,"column":6},"end":{"line":49,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":6},"end":{"line":49,"column":null}},{"start":{},"end":{}}],"line":43},"3":{"loc":{"start":{"line":58,"column":20},"end":{"line":58,"column":null}},"type":"cond-expr","locations":[{"start":{"line":58,"column":29},"end":{"line":58,"column":39}},{"start":{"line":58,"column":39},"end":{"line":58,"column":null}}],"line":58},"4":{"loc":{"start":{"line":75,"column":26},"end":{"line":75,"column":45}},"type":"default-arg","locations":[{"start":{"line":75,"column":41},"end":{"line":75,"column":45}}],"line":75},"5":{"loc":{"start":{"line":75,"column":45},"end":{"line":75,"column":65}},"type":"default-arg","locations":[{"start":{"line":75,"column":55},"end":{"line":75,"column":65}}],"line":75},"6":{"loc":{"start":{"line":77,"column":6},"end":{"line":83,"column":null}},"type":"if","locations":[{"start":{"line":77,"column":6},"end":{"line":83,"column":null}},{"start":{},"end":{}}],"line":77},"7":{"loc":{"start":{"line":92,"column":8},"end":{"line":101,"column":null}},"type":"if","locations":[{"start":{"line":92,"column":8},"end":{"line":101,"column":null}},{"start":{},"end":{}}],"line":92}},"s":{"0":57,"1":2,"2":2,"3":1,"4":1,"5":1,"6":1,"7":2,"8":0,"9":1,"10":1,"11":0,"12":1,"13":1,"14":1,"15":1,"16":0,"17":0},"f":{"0":57,"1":2,"2":1},"b":{"0":[2],"1":[2],"2":[1,1],"3":[1,0],"4":[1],"5":[1],"6":[0,1],"7":[1,0]},"meta":{"lastBranch":8,"lastFunction":3,"lastStatement":18,"seen":{"f:35:16:35:32":0,"s:36:2:116:Infinity":0,"f:40:10:40:24":1,"s:41:61:41:Infinity":1,"b:41:30:41:37":0,"b:41:47:41:57":1,"b:43:6:49:Infinity:undefined:undefined:undefined:undefined":2,"s:43:6:49:Infinity":2,"s:44:8:48:Infinity":3,"s:51:6:68:Infinity":4,"s:52:23:52:Infinity":5,"s:54:23:59:Infinity":6,"b:58:29:58:39:58:39:58:Infinity":3,"s:61:8:61:Infinity":7,"s:63:8:67:Infinity":8,"f:74:10:74:23":2,"s:75:69:75:Infinity":9,"b:75:41:75:45":4,"b:75:55:75:65":5,"b:77:6:83:Infinity:undefined:undefined:undefined:undefined":6,"s:77:6:83:Infinity":10,"s:78:8:82:Infinity":11,"s:85:6:114:Infinity":12,"s:86:27:90:Infinity":13,"b:92:8:101:Infinity:undefined:undefined:undefined:undefined":7,"s:92:8:101:Infinity":14,"s:93:10:100:Infinity":15,"s:103:8:111:Infinity":16,"s:113:8:113:Infinity":17}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/tools/handlers/docs-tools.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/tools/handlers/docs-tools.ts","statementMap":{"0":{"start":{"line":37,"column":2},"end":{"line":157,"column":null}},"1":{"start":{"line":47,"column":10},"end":{"line":47,"column":null}},"2":{"start":{"line":48,"column":6},"end":{"line":87,"column":null}},"3":{"start":{"line":49,"column":45},"end":{"line":52,"column":null}},"4":{"start":{"line":53,"column":8},"end":{"line":59,"column":null}},"5":{"start":{"line":54,"column":10},"end":{"line":58,"column":null}},"6":{"start":{"line":60,"column":23},"end":{"line":67,"column":null}},"7":{"start":{"line":68,"column":8},"end":{"line":80,"column":null}},"8":{"start":{"line":82,"column":8},"end":{"line":86,"column":null}},"9":{"start":{"line":99,"column":10},"end":{"line":99,"column":null}},"10":{"start":{"line":100,"column":6},"end":{"line":155,"column":null}},"11":{"start":{"line":101,"column":30},"end":{"line":103,"column":null}},"12":{"start":{"line":104,"column":8},"end":{"line":110,"column":null}},"13":{"start":{"line":105,"column":10},"end":{"line":109,"column":null}},"14":{"start":{"line":112,"column":8},"end":{"line":132,"column":null}},"15":{"start":{"line":113,"column":10},"end":{"line":117,"column":null}},"16":{"start":{"line":118,"column":8},"end":{"line":132,"column":null}},"17":{"start":{"line":119,"column":10},"end":{"line":125,"column":null}},"18":{"start":{"line":127,"column":10},"end":{"line":131,"column":null}},"19":{"start":{"line":133,"column":8},"end":{"line":148,"column":null}},"20":{"start":{"line":137,"column":46},"end":{"line":144,"column":14}},"21":{"start":{"line":150,"column":8},"end":{"line":154,"column":null}}},"fnMap":{"0":{"name":"createDocsTools","decl":{"start":{"line":36,"column":16},"end":{"line":36,"column":32}},"loc":{"start":{"line":36,"column":54},"end":{"line":158,"column":null}},"line":36},"1":{"name":"(anonymous_1)","decl":{"start":{"line":41,"column":10},"end":{"line":41,"column":21}},"loc":{"start":{"line":41,"column":49},"end":{"line":88,"column":null}},"line":41},"2":{"name":"(anonymous_2)","decl":{"start":{"line":93,"column":10},"end":{"line":93,"column":22}},"loc":{"start":{"line":93,"column":50},"end":{"line":156,"column":null}},"line":93},"3":{"name":"(anonymous_3)","decl":{"start":{"line":137,"column":33},"end":{"line":137,"column":34}},"loc":{"start":{"line":137,"column":46},"end":{"line":144,"column":14}},"line":137}},"branchMap":{"0":{"loc":{"start":{"line":45,"column":8},"end":{"line":45,"column":null}},"type":"default-arg","locations":[{"start":{"line":45,"column":22},"end":{"line":45,"column":null}}],"line":45},"1":{"loc":{"start":{"line":46,"column":8},"end":{"line":46,"column":null}},"type":"default-arg","locations":[{"start":{"line":46,"column":25},"end":{"line":46,"column":null}}],"line":46},"2":{"loc":{"start":{"line":47,"column":10},"end":{"line":47,"column":null}},"type":"binary-expr","locations":[{"start":{"line":47,"column":10},"end":{"line":47,"column":18}},{"start":{"line":47,"column":18},"end":{"line":47,"column":null}}],"line":47},"3":{"loc":{"start":{"line":53,"column":8},"end":{"line":59,"column":null}},"type":"if","locations":[{"start":{"line":53,"column":8},"end":{"line":59,"column":null}},{"start":{},"end":{}}],"line":53},"4":{"loc":{"start":{"line":84,"column":10},"end":{"line":84,"column":null}},"type":"cond-expr","locations":[{"start":{"line":84,"column":33},"end":{"line":84,"column":47}},{"start":{"line":84,"column":47},"end":{"line":84,"column":null}}],"line":84},"5":{"loc":{"start":{"line":97,"column":8},"end":{"line":97,"column":null}},"type":"default-arg","locations":[{"start":{"line":97,"column":16},"end":{"line":97,"column":null}}],"line":97},"6":{"loc":{"start":{"line":99,"column":10},"end":{"line":99,"column":null}},"type":"binary-expr","locations":[{"start":{"line":99,"column":10},"end":{"line":99,"column":18}},{"start":{"line":99,"column":18},"end":{"line":99,"column":null}}],"line":99},"7":{"loc":{"start":{"line":104,"column":8},"end":{"line":110,"column":null}},"type":"if","locations":[{"start":{"line":104,"column":8},"end":{"line":110,"column":null}},{"start":{},"end":{}}],"line":104},"8":{"loc":{"start":{"line":112,"column":8},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":8},"end":{"line":132,"column":null}},{"start":{"line":118,"column":8},"end":{"line":132,"column":null}}],"line":112},"9":{"loc":{"start":{"line":112,"column":12},"end":{"line":112,"column":68}},"type":"binary-expr","locations":[{"start":{"line":112,"column":12},"end":{"line":112,"column":42}},{"start":{"line":112,"column":42},"end":{"line":112,"column":68}}],"line":112},"10":{"loc":{"start":{"line":118,"column":8},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":118,"column":8},"end":{"line":132,"column":null}},{"start":{"line":126,"column":15},"end":{"line":132,"column":null}}],"line":118},"11":{"loc":{"start":{"line":118,"column":19},"end":{"line":118,"column":73}},"type":"binary-expr","locations":[{"start":{"line":118,"column":19},"end":{"line":118,"column":48}},{"start":{"line":118,"column":48},"end":{"line":118,"column":73}}],"line":118},"12":{"loc":{"start":{"line":152,"column":10},"end":{"line":152,"column":null}},"type":"cond-expr","locations":[{"start":{"line":152,"column":33},"end":{"line":152,"column":47}},{"start":{"line":152,"column":47},"end":{"line":152,"column":null}}],"line":152}},"s":{"0":57,"1":5,"2":5,"3":5,"4":5,"5":1,"6":4,"7":4,"8":0,"9":6,"10":6,"11":6,"12":6,"13":1,"14":5,"15":1,"16":4,"17":3,"18":1,"19":4,"20":3,"21":0},"f":{"0":57,"1":5,"2":6,"3":3},"b":{"0":[5],"1":[5],"2":[5,0],"3":[1,4],"4":[0,0],"5":[6],"6":[6,0],"7":[1,5],"8":[1,4],"9":[5,1],"10":[3,1],"11":[4,3],"12":[0,0]},"meta":{"lastBranch":13,"lastFunction":4,"lastStatement":22,"seen":{"f:36:16:36:32":0,"s:37:2:157:Infinity":0,"f:41:10:41:21":1,"s:47:10:47:Infinity":1,"b:45:22:45:Infinity":0,"b:46:25:46:Infinity":1,"b:47:10:47:18:47:18:47:Infinity":2,"s:48:6:87:Infinity":2,"s:49:45:52:Infinity":3,"b:53:8:59:Infinity:undefined:undefined:undefined:undefined":3,"s:53:8:59:Infinity":4,"s:54:10:58:Infinity":5,"s:60:23:67:Infinity":6,"s:68:8:80:Infinity":7,"s:82:8:86:Infinity":8,"b:84:33:84:47:84:47:84:Infinity":4,"f:93:10:93:22":2,"s:99:10:99:Infinity":9,"b:97:16:97:Infinity":5,"b:99:10:99:18:99:18:99:Infinity":6,"s:100:6:155:Infinity":10,"s:101:30:103:Infinity":11,"b:104:8:110:Infinity:undefined:undefined:undefined:undefined":7,"s:104:8:110:Infinity":12,"s:105:10:109:Infinity":13,"b:112:8:132:Infinity:118:8:132:Infinity":8,"s:112:8:132:Infinity":14,"b:112:12:112:42:112:42:112:68":9,"s:113:10:117:Infinity":15,"b:118:8:132:Infinity:126:15:132:Infinity":10,"s:118:8:132:Infinity":16,"b:118:19:118:48:118:48:118:73":11,"s:119:10:125:Infinity":17,"s:127:10:131:Infinity":18,"s:133:8:148:Infinity":19,"f:137:33:137:34":3,"s:137:46:144:14":20,"s:150:8:154:Infinity":21,"b:152:33:152:47:152:47:152:Infinity":12}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/tools/handlers/ref-tools.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/tools/handlers/ref-tools.ts","statementMap":{"0":{"start":{"line":43,"column":2},"end":{"line":212,"column":null}},"1":{"start":{"line":55,"column":10},"end":{"line":55,"column":null}},"2":{"start":{"line":57,"column":6},"end":{"line":64,"column":null}},"3":{"start":{"line":58,"column":8},"end":{"line":63,"column":null}},"4":{"start":{"line":66,"column":27},"end":{"line":66,"column":null}},"5":{"start":{"line":67,"column":6},"end":{"line":74,"column":null}},"6":{"start":{"line":68,"column":8},"end":{"line":73,"column":null}},"7":{"start":{"line":76,"column":6},"end":{"line":210,"column":null}},"8":{"start":{"line":77,"column":25},"end":{"line":77,"column":null}},"9":{"start":{"line":78,"column":32},"end":{"line":78,"column":null}},"10":{"start":{"line":82,"column":10},"end":{"line":82,"column":null}},"11":{"start":{"line":85,"column":8},"end":{"line":118,"column":null}},"12":{"start":{"line":90,"column":25},"end":{"line":90,"column":null}},"13":{"start":{"line":91,"column":16},"end":{"line":91,"column":null}},"14":{"start":{"line":92,"column":29},"end":{"line":95,"column":null}},"15":{"start":{"line":95,"column":35},"end":{"line":95,"column":47}},"16":{"start":{"line":97,"column":10},"end":{"line":117,"column":null}},"17":{"start":{"line":98,"column":12},"end":{"line":116,"column":null}},"18":{"start":{"line":99,"column":26},"end":{"line":99,"column":null}},"19":{"start":{"line":100,"column":14},"end":{"line":113,"column":null}},"20":{"start":{"line":101,"column":30},"end":{"line":101,"column":null}},"21":{"start":{"line":102,"column":16},"end":{"line":112,"column":null}},"22":{"start":{"line":103,"column":18},"end":{"line":111,"column":null}},"23":{"start":{"line":121,"column":8},"end":{"line":173,"column":null}},"24":{"start":{"line":126,"column":29},"end":{"line":138,"column":null}},"25":{"start":{"line":139,"column":30},"end":{"line":139,"column":null}},"26":{"start":{"line":140,"column":29},"end":{"line":143,"column":null}},"27":{"start":{"line":143,"column":35},"end":{"line":143,"column":47}},"28":{"start":{"line":145,"column":10},"end":{"line":172,"column":null}},"29":{"start":{"line":146,"column":12},"end":{"line":171,"column":null}},"30":{"start":{"line":147,"column":30},"end":{"line":147,"column":null}},"31":{"start":{"line":148,"column":30},"end":{"line":148,"column":null}},"32":{"start":{"line":149,"column":28},"end":{"line":154,"column":null}},"33":{"start":{"line":155,"column":14},"end":{"line":168,"column":null}},"34":{"start":{"line":156,"column":32},"end":{"line":161,"column":null}},"35":{"start":{"line":162,"column":16},"end":{"line":167,"column":null}},"36":{"start":{"line":176,"column":8},"end":{"line":179,"column":null}},"37":{"start":{"line":177,"column":23},"end":{"line":177,"column":null}},"38":{"start":{"line":178,"column":10},"end":{"line":178,"column":null}},"39":{"start":{"line":182,"column":23},"end":{"line":188,"column":null}},"40":{"start":{"line":184,"column":12},"end":{"line":184,"column":null}},"41":{"start":{"line":184,"column":40},"end":{"line":184,"column":null}},"42":{"start":{"line":185,"column":12},"end":{"line":185,"column":null}},"43":{"start":{"line":185,"column":40},"end":{"line":185,"column":null}},"44":{"start":{"line":186,"column":12},"end":{"line":186,"column":null}},"45":{"start":{"line":190,"column":8},"end":{"line":203,"column":null}},"46":{"start":{"line":205,"column":8},"end":{"line":209,"column":null}},"47":{"start":{"line":226,"column":2},"end":{"line":226,"column":null}},"48":{"start":{"line":226,"column":14},"end":{"line":226,"column":null}},"49":{"start":{"line":227,"column":8},"end":{"line":227,"column":null}},"50":{"start":{"line":228,"column":2},"end":{"line":233,"column":null}},"51":{"start":{"line":233,"column":4},"end":{"line":233,"column":null}},"52":{"start":{"line":234,"column":2},"end":{"line":235,"column":null}},"53":{"start":{"line":235,"column":4},"end":{"line":235,"column":null}},"54":{"start":{"line":236,"column":2},"end":{"line":241,"column":null}},"55":{"start":{"line":241,"column":4},"end":{"line":241,"column":null}},"56":{"start":{"line":242,"column":2},"end":{"line":242,"column":null}},"57":{"start":{"line":253,"column":14},"end":{"line":253,"column":null}},"58":{"start":{"line":254,"column":15},"end":{"line":254,"column":null}},"59":{"start":{"line":255,"column":2},"end":{"line":261,"column":null}},"60":{"start":{"line":256,"column":15},"end":{"line":256,"column":null}},"61":{"start":{"line":257,"column":10},"end":{"line":257,"column":null}},"62":{"start":{"line":258,"column":4},"end":{"line":260,"column":null}},"63":{"start":{"line":259,"column":6},"end":{"line":259,"column":null}},"64":{"start":{"line":262,"column":2},"end":{"line":267,"column":null}},"65":{"start":{"line":263,"column":21},"end":{"line":263,"column":null}},"66":{"start":{"line":264,"column":4},"end":{"line":266,"column":null}},"67":{"start":{"line":264,"column":41},"end":{"line":264,"column":75}},"68":{"start":{"line":265,"column":6},"end":{"line":265,"column":null}},"69":{"start":{"line":265,"column":15},"end":{"line":266,"column":null}},"70":{"start":{"line":266,"column":38},"end":{"line":266,"column":null}},"71":{"start":{"line":268,"column":2},"end":{"line":268,"column":null}},"72":{"start":{"line":280,"column":14},"end":{"line":280,"column":null}},"73":{"start":{"line":281,"column":16},"end":{"line":281,"column":null}},"74":{"start":{"line":282,"column":20},"end":{"line":282,"column":null}},"75":{"start":{"line":283,"column":2},"end":{"line":288,"column":null}},"76":{"start":{"line":284,"column":15},"end":{"line":284,"column":null}},"77":{"start":{"line":285,"column":10},"end":{"line":285,"column":null}},"78":{"start":{"line":286,"column":4},"end":{"line":286,"column":null}},"79":{"start":{"line":287,"column":4},"end":{"line":287,"column":null}},"80":{"start":{"line":287,"column":34},"end":{"line":287,"column":null}},"81":{"start":{"line":289,"column":2},"end":{"line":297,"column":null}},"82":{"start":{"line":290,"column":21},"end":{"line":290,"column":null}},"83":{"start":{"line":291,"column":10},"end":{"line":295,"column":null}},"84":{"start":{"line":296,"column":4},"end":{"line":296,"column":null}},"85":{"start":{"line":298,"column":2},"end":{"line":298,"column":null}},"86":{"start":{"line":310,"column":16},"end":{"line":310,"column":null}},"87":{"start":{"line":311,"column":17},"end":{"line":311,"column":null}},"88":{"start":{"line":312,"column":18},"end":{"line":312,"column":null}},"89":{"start":{"line":313,"column":2},"end":{"line":324,"column":null}},"90":{"start":{"line":313,"column":15},"end":{"line":313,"column":18}},"91":{"start":{"line":314,"column":18},"end":{"line":314,"column":null}},"92":{"start":{"line":315,"column":16},"end":{"line":315,"column":null}},"93":{"start":{"line":316,"column":4},"end":{"line":316,"column":null}},"94":{"start":{"line":316,"column":56},"end":{"line":316,"column":null}},"95":{"start":{"line":317,"column":4},"end":{"line":319,"column":null}},"96":{"start":{"line":318,"column":6},"end":{"line":318,"column":null}},"97":{"start":{"line":318,"column":32},"end":{"line":318,"column":null}},"98":{"start":{"line":320,"column":4},"end":{"line":323,"column":null}},"99":{"start":{"line":321,"column":6},"end":{"line":321,"column":null}},"100":{"start":{"line":322,"column":6},"end":{"line":322,"column":null}},"101":{"start":{"line":325,"column":2},"end":{"line":325,"column":null}},"102":{"start":{"line":325,"column":23},"end":{"line":325,"column":null}},"103":{"start":{"line":326,"column":16},"end":{"line":326,"column":null}},"104":{"start":{"line":327,"column":14},"end":{"line":327,"column":null}},"105":{"start":{"line":328,"column":2},"end":{"line":328,"column":null}},"106":{"start":{"line":338,"column":28},"end":{"line":338,"column":null}},"107":{"start":{"line":339,"column":21},"end":{"line":350,"column":null}},"108":{"start":{"line":352,"column":15},"end":{"line":371,"column":null}},"109":{"start":{"line":353,"column":4},"end":{"line":353,"column":null}},"110":{"start":{"line":353,"column":19},"end":{"line":353,"column":null}},"111":{"start":{"line":354,"column":4},"end":{"line":370,"column":null}},"112":{"start":{"line":355,"column":22},"end":{"line":355,"column":null}},"113":{"start":{"line":356,"column":6},"end":{"line":367,"column":null}},"114":{"start":{"line":357,"column":8},"end":{"line":366,"column":null}},"115":{"start":{"line":358,"column":10},"end":{"line":360,"column":null}},"116":{"start":{"line":359,"column":12},"end":{"line":359,"column":null}},"117":{"start":{"line":361,"column":8},"end":{"line":366,"column":null}},"118":{"start":{"line":362,"column":22},"end":{"line":362,"column":null}},"119":{"start":{"line":363,"column":10},"end":{"line":365,"column":null}},"120":{"start":{"line":364,"column":12},"end":{"line":364,"column":null}},"121":{"start":{"line":373,"column":2},"end":{"line":373,"column":null}},"122":{"start":{"line":374,"column":2},"end":{"line":374,"column":null}},"123":{"start":{"line":381,"column":21},"end":{"line":392,"column":null}},"124":{"start":{"line":394,"column":15},"end":{"line":418,"column":null}},"125":{"start":{"line":395,"column":4},"end":{"line":395,"column":null}},"126":{"start":{"line":395,"column":26},"end":{"line":395,"column":null}},"127":{"start":{"line":396,"column":17},"end":{"line":396,"column":null}},"128":{"start":{"line":397,"column":28},"end":{"line":397,"column":null}},"129":{"start":{"line":398,"column":4},"end":{"line":416,"column":null}},"130":{"start":{"line":399,"column":22},"end":{"line":401,"column":null}},"131":{"start":{"line":402,"column":6},"end":{"line":413,"column":null}},"132":{"start":{"line":403,"column":8},"end":{"line":412,"column":null}},"133":{"start":{"line":408,"column":24},"end":{"line":408,"column":null}},"134":{"start":{"line":409,"column":10},"end":{"line":409,"column":null}},"135":{"start":{"line":409,"column":21},"end":{"line":409,"column":null}},"136":{"start":{"line":410,"column":8},"end":{"line":412,"column":null}},"137":{"start":{"line":411,"column":10},"end":{"line":411,"column":null}},"138":{"start":{"line":417,"column":4},"end":{"line":417,"column":null}},"139":{"start":{"line":420,"column":2},"end":{"line":420,"column":null}}},"fnMap":{"0":{"name":"createRefTools","decl":{"start":{"line":42,"column":16},"end":{"line":42,"column":31}},"loc":{"start":{"line":42,"column":52},"end":{"line":213,"column":null}},"line":42},"1":{"name":"(anonymous_1)","decl":{"start":{"line":47,"column":10},"end":{"line":47,"column":20}},"loc":{"start":{"line":47,"column":48},"end":{"line":211,"column":null}},"line":47},"2":{"name":"(anonymous_2)","decl":{"start":{"line":95,"column":20},"end":{"line":95,"column":21}},"loc":{"start":{"line":95,"column":35},"end":{"line":95,"column":47}},"line":95},"3":{"name":"(anonymous_3)","decl":{"start":{"line":143,"column":20},"end":{"line":143,"column":21}},"loc":{"start":{"line":143,"column":35},"end":{"line":143,"column":47}},"line":143},"4":{"name":"(anonymous_4)","decl":{"start":{"line":183,"column":16},"end":{"line":183,"column":17}},"loc":{"start":{"line":183,"column":26},"end":{"line":187,"column":11}},"line":183},"5":{"name":"inferRefMode","decl":{"start":{"line":222,"column":9},"end":{"line":222,"column":null}},"loc":{"start":{"line":225,"column":57},"end":{"line":243,"column":null}},"line":225},"6":{"name":"scoreRefSection","decl":{"start":{"line":248,"column":9},"end":{"line":248,"column":null}},"loc":{"start":{"line":252,"column":10},"end":{"line":269,"column":null}},"line":252},"7":{"name":"(anonymous_7)","decl":{"start":{"line":264,"column":34},"end":{"line":264,"column":35}},"loc":{"start":{"line":264,"column":41},"end":{"line":264,"column":75}},"line":264},"8":{"name":"scoreRefCode","decl":{"start":{"line":274,"column":9},"end":{"line":274,"column":null}},"loc":{"start":{"line":279,"column":10},"end":{"line":299,"column":null}},"line":279},"9":{"name":"extractRefExcerpt","decl":{"start":{"line":304,"column":9},"end":{"line":304,"column":null}},"loc":{"start":{"line":309,"column":10},"end":{"line":329,"column":null}},"line":309},"10":{"name":"scanRefSourceFiles","decl":{"start":{"line":334,"column":9},"end":{"line":334,"column":null}},"loc":{"start":{"line":337,"column":12},"end":{"line":375,"column":null}},"line":337},"11":{"name":"(anonymous_11)","decl":{"start":{"line":352,"column":15},"end":{"line":352,"column":16}},"loc":{"start":{"line":352,"column":47},"end":{"line":371,"column":null}},"line":352},"12":{"name":"buildRefDirTree","decl":{"start":{"line":380,"column":9},"end":{"line":380,"column":25}},"loc":{"start":{"line":380,"column":66},"end":{"line":421,"column":null}},"line":380},"13":{"name":"(anonymous_13)","decl":{"start":{"line":394,"column":15},"end":{"line":394,"column":16}},"loc":{"start":{"line":394,"column":52},"end":{"line":418,"column":null}},"line":394}},"branchMap":{"0":{"loc":{"start":{"line":50,"column":8},"end":{"line":50,"column":null}},"type":"default-arg","locations":[{"start":{"line":50,"column":16},"end":{"line":50,"column":null}}],"line":50},"1":{"loc":{"start":{"line":51,"column":8},"end":{"line":51,"column":null}},"type":"default-arg","locations":[{"start":{"line":51,"column":15},"end":{"line":51,"column":null}}],"line":51},"2":{"loc":{"start":{"line":53,"column":8},"end":{"line":53,"column":null}},"type":"default-arg","locations":[{"start":{"line":53,"column":16},"end":{"line":53,"column":null}}],"line":53},"3":{"loc":{"start":{"line":54,"column":8},"end":{"line":54,"column":null}},"type":"default-arg","locations":[{"start":{"line":54,"column":18},"end":{"line":54,"column":null}}],"line":54},"4":{"loc":{"start":{"line":55,"column":10},"end":{"line":55,"column":null}},"type":"binary-expr","locations":[{"start":{"line":55,"column":10},"end":{"line":55,"column":18}},{"start":{"line":55,"column":18},"end":{"line":55,"column":null}}],"line":55},"5":{"loc":{"start":{"line":57,"column":6},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":6},"end":{"line":64,"column":null}},{"start":{},"end":{}}],"line":57},"6":{"loc":{"start":{"line":57,"column":10},"end":{"line":57,"column":53}},"type":"binary-expr","locations":[{"start":{"line":57,"column":10},"end":{"line":57,"column":23}},{"start":{"line":57,"column":23},"end":{"line":57,"column":53}}],"line":57},"7":{"loc":{"start":{"line":67,"column":6},"end":{"line":74,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":6},"end":{"line":74,"column":null}},{"start":{},"end":{}}],"line":67},"8":{"loc":{"start":{"line":82,"column":10},"end":{"line":82,"column":null}},"type":"cond-expr","locations":[{"start":{"line":82,"column":28},"end":{"line":82,"column":58}},{"start":{"line":82,"column":58},"end":{"line":82,"column":null}}],"line":82},"9":{"loc":{"start":{"line":85,"column":8},"end":{"line":118,"column":null}},"type":"if","locations":[{"start":{"line":85,"column":8},"end":{"line":118,"column":null}},{"start":{},"end":{}}],"line":85},"10":{"loc":{"start":{"line":86,"column":10},"end":{"line":88,"column":null}},"type":"binary-expr","locations":[{"start":{"line":86,"column":10},"end":{"line":86,"column":null}},{"start":{"line":87,"column":10},"end":{"line":87,"column":null}},{"start":{"line":88,"column":10},"end":{"line":88,"column":null}}],"line":86},"11":{"loc":{"start":{"line":102,"column":16},"end":{"line":112,"column":null}},"type":"if","locations":[{"start":{"line":102,"column":16},"end":{"line":112,"column":null}},{"start":{},"end":{}}],"line":102},"12":{"loc":{"start":{"line":102,"column":20},"end":{"line":102,"column":58}},"type":"binary-expr","locations":[{"start":{"line":102,"column":20},"end":{"line":102,"column":33}},{"start":{"line":102,"column":33},"end":{"line":102,"column":58}}],"line":102},"13":{"loc":{"start":{"line":107,"column":29},"end":{"line":107,"column":null}},"type":"binary-expr","locations":[{"start":{"line":107,"column":29},"end":{"line":107,"column":44}},{"start":{"line":107,"column":44},"end":{"line":107,"column":null}}],"line":107},"14":{"loc":{"start":{"line":121,"column":8},"end":{"line":173,"column":null}},"type":"if","locations":[{"start":{"line":121,"column":8},"end":{"line":173,"column":null}},{"start":{},"end":{}}],"line":121},"15":{"loc":{"start":{"line":122,"column":10},"end":{"line":124,"column":null}},"type":"binary-expr","locations":[{"start":{"line":122,"column":10},"end":{"line":122,"column":null}},{"start":{"line":123,"column":10},"end":{"line":123,"column":null}},{"start":{"line":124,"column":10},"end":{"line":124,"column":null}}],"line":122},"16":{"loc":{"start":{"line":155,"column":14},"end":{"line":168,"column":null}},"type":"if","locations":[{"start":{"line":155,"column":14},"end":{"line":168,"column":null}},{"start":{},"end":{}}],"line":155},"17":{"loc":{"start":{"line":166,"column":27},"end":{"line":166,"column":null}},"type":"binary-expr","locations":[{"start":{"line":166,"column":27},"end":{"line":166,"column":38}},{"start":{"line":166,"column":38},"end":{"line":166,"column":null}}],"line":166},"18":{"loc":{"start":{"line":176,"column":8},"end":{"line":179,"column":null}},"type":"if","locations":[{"start":{"line":176,"column":8},"end":{"line":179,"column":null}},{"start":{},"end":{}}],"line":176},"19":{"loc":{"start":{"line":176,"column":12},"end":{"line":176,"column":70}},"type":"binary-expr","locations":[{"start":{"line":176,"column":12},"end":{"line":176,"column":39}},{"start":{"line":176,"column":39},"end":{"line":176,"column":70}}],"line":176},"20":{"loc":{"start":{"line":184,"column":12},"end":{"line":184,"column":null}},"type":"if","locations":[{"start":{"line":184,"column":12},"end":{"line":184,"column":null}},{"start":{},"end":{}}],"line":184},"21":{"loc":{"start":{"line":185,"column":12},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":185,"column":12},"end":{"line":185,"column":null}},{"start":{},"end":{}}],"line":185},"22":{"loc":{"start":{"line":186,"column":20},"end":{"line":186,"column":37}},"type":"binary-expr","locations":[{"start":{"line":186,"column":20},"end":{"line":186,"column":31}},{"start":{"line":186,"column":31},"end":{"line":186,"column":37}}],"line":186},"23":{"loc":{"start":{"line":186,"column":37},"end":{"line":186,"column":null}},"type":"binary-expr","locations":[{"start":{"line":186,"column":37},"end":{"line":186,"column":48}},{"start":{"line":186,"column":48},"end":{"line":186,"column":null}}],"line":186},"24":{"loc":{"start":{"line":195,"column":20},"end":{"line":195,"column":null}},"type":"binary-expr","locations":[{"start":{"line":195,"column":20},"end":{"line":195,"column":30}},{"start":{"line":195,"column":30},"end":{"line":195,"column":null}}],"line":195},"25":{"loc":{"start":{"line":207,"column":10},"end":{"line":207,"column":null}},"type":"cond-expr","locations":[{"start":{"line":207,"column":35},"end":{"line":207,"column":51}},{"start":{"line":207,"column":51},"end":{"line":207,"column":null}}],"line":207},"26":{"loc":{"start":{"line":226,"column":2},"end":{"line":226,"column":null}},"type":"if","locations":[{"start":{"line":226,"column":2},"end":{"line":226,"column":null}},{"start":{},"end":{}}],"line":226},"27":{"loc":{"start":{"line":227,"column":17},"end":{"line":227,"column":30}},"type":"binary-expr","locations":[{"start":{"line":227,"column":17},"end":{"line":227,"column":26}},{"start":{"line":227,"column":26},"end":{"line":227,"column":30}}],"line":227},"28":{"loc":{"start":{"line":228,"column":2},"end":{"line":233,"column":null}},"type":"if","locations":[{"start":{"line":228,"column":2},"end":{"line":233,"column":null}},{"start":{},"end":{}}],"line":228},"29":{"loc":{"start":{"line":234,"column":2},"end":{"line":235,"column":null}},"type":"if","locations":[{"start":{"line":234,"column":2},"end":{"line":235,"column":null}},{"start":{},"end":{}}],"line":234},"30":{"loc":{"start":{"line":236,"column":2},"end":{"line":241,"column":null}},"type":"if","locations":[{"start":{"line":236,"column":2},"end":{"line":241,"column":null}},{"start":{},"end":{}}],"line":236},"31":{"loc":{"start":{"line":257,"column":19},"end":{"line":257,"column":41}},"type":"binary-expr","locations":[{"start":{"line":257,"column":19},"end":{"line":257,"column":37}},{"start":{"line":257,"column":37},"end":{"line":257,"column":41}}],"line":257},"32":{"loc":{"start":{"line":258,"column":4},"end":{"line":260,"column":null}},"type":"if","locations":[{"start":{"line":258,"column":4},"end":{"line":260,"column":null}},{"start":{},"end":{}}],"line":258},"33":{"loc":{"start":{"line":259,"column":24},"end":{"line":259,"column":null}},"type":"cond-expr","locations":[{"start":{"line":259,"column":71},"end":{"line":259,"column":75}},{"start":{"line":259,"column":75},"end":{"line":259,"column":null}}],"line":259},"34":{"loc":{"start":{"line":262,"column":2},"end":{"line":267,"column":null}},"type":"if","locations":[{"start":{"line":262,"column":2},"end":{"line":267,"column":null}},{"start":{},"end":{}}],"line":262},"35":{"loc":{"start":{"line":264,"column":4},"end":{"line":266,"column":null}},"type":"if","locations":[{"start":{"line":264,"column":4},"end":{"line":266,"column":null}},{"start":{"line":265,"column":15},"end":{"line":266,"column":null}}],"line":264},"36":{"loc":{"start":{"line":265,"column":15},"end":{"line":266,"column":null}},"type":"if","locations":[{"start":{"line":265,"column":15},"end":{"line":266,"column":null}},{"start":{},"end":{}}],"line":265},"37":{"loc":{"start":{"line":285,"column":19},"end":{"line":285,"column":42}},"type":"binary-expr","locations":[{"start":{"line":285,"column":19},"end":{"line":285,"column":38}},{"start":{"line":285,"column":38},"end":{"line":285,"column":42}}],"line":285},"38":{"loc":{"start":{"line":287,"column":4},"end":{"line":287,"column":null}},"type":"if","locations":[{"start":{"line":287,"column":4},"end":{"line":287,"column":null}},{"start":{},"end":{}}],"line":287},"39":{"loc":{"start":{"line":289,"column":2},"end":{"line":297,"column":null}},"type":"if","locations":[{"start":{"line":289,"column":2},"end":{"line":297,"column":null}},{"start":{},"end":{}}],"line":289},"40":{"loc":{"start":{"line":292,"column":6},"end":{"line":294,"column":null}},"type":"binary-expr","locations":[{"start":{"line":292,"column":6},"end":{"line":294,"column":11}},{"start":{"line":294,"column":11},"end":{"line":294,"column":null}}],"line":292},"41":{"loc":{"start":{"line":316,"column":4},"end":{"line":316,"column":null}},"type":"if","locations":[{"start":{"line":316,"column":4},"end":{"line":316,"column":null}},{"start":{},"end":{}}],"line":316},"42":{"loc":{"start":{"line":316,"column":8},"end":{"line":316,"column":56}},"type":"binary-expr","locations":[{"start":{"line":316,"column":8},"end":{"line":316,"column":18}},{"start":{"line":316,"column":18},"end":{"line":316,"column":56}}],"line":316},"43":{"loc":{"start":{"line":318,"column":6},"end":{"line":318,"column":null}},"type":"if","locations":[{"start":{"line":318,"column":6},"end":{"line":318,"column":null}},{"start":{},"end":{}}],"line":318},"44":{"loc":{"start":{"line":320,"column":4},"end":{"line":323,"column":null}},"type":"if","locations":[{"start":{"line":320,"column":4},"end":{"line":323,"column":null}},{"start":{},"end":{}}],"line":320},"45":{"loc":{"start":{"line":325,"column":2},"end":{"line":325,"column":null}},"type":"if","locations":[{"start":{"line":325,"column":2},"end":{"line":325,"column":null}},{"start":{},"end":{}}],"line":325},"46":{"loc":{"start":{"line":353,"column":4},"end":{"line":353,"column":null}},"type":"if","locations":[{"start":{"line":353,"column":4},"end":{"line":353,"column":null}},{"start":{},"end":{}}],"line":353},"47":{"loc":{"start":{"line":357,"column":8},"end":{"line":366,"column":null}},"type":"if","locations":[{"start":{"line":357,"column":8},"end":{"line":366,"column":null}},{"start":{"line":361,"column":8},"end":{"line":366,"column":null}}],"line":357},"48":{"loc":{"start":{"line":358,"column":10},"end":{"line":360,"column":null}},"type":"if","locations":[{"start":{"line":358,"column":10},"end":{"line":360,"column":null}},{"start":{},"end":{}}],"line":358},"49":{"loc":{"start":{"line":358,"column":14},"end":{"line":358,"column":74}},"type":"binary-expr","locations":[{"start":{"line":358,"column":14},"end":{"line":358,"column":45}},{"start":{"line":358,"column":45},"end":{"line":358,"column":74}}],"line":358},"50":{"loc":{"start":{"line":361,"column":8},"end":{"line":366,"column":null}},"type":"if","locations":[{"start":{"line":361,"column":8},"end":{"line":366,"column":null}},{"start":{},"end":{}}],"line":361},"51":{"loc":{"start":{"line":363,"column":10},"end":{"line":365,"column":null}},"type":"if","locations":[{"start":{"line":363,"column":10},"end":{"line":365,"column":null}},{"start":{},"end":{}}],"line":363},"52":{"loc":{"start":{"line":395,"column":4},"end":{"line":395,"column":null}},"type":"if","locations":[{"start":{"line":395,"column":4},"end":{"line":395,"column":null}},{"start":{},"end":{}}],"line":395},"53":{"loc":{"start":{"line":403,"column":8},"end":{"line":412,"column":null}},"type":"if","locations":[{"start":{"line":403,"column":8},"end":{"line":412,"column":null}},{"start":{"line":410,"column":8},"end":{"line":412,"column":null}}],"line":403},"54":{"loc":{"start":{"line":404,"column":10},"end":{"line":406,"column":null}},"type":"binary-expr","locations":[{"start":{"line":404,"column":10},"end":{"line":404,"column":null}},{"start":{"line":405,"column":10},"end":{"line":405,"column":null}},{"start":{"line":406,"column":10},"end":{"line":406,"column":null}}],"line":404},"55":{"loc":{"start":{"line":409,"column":10},"end":{"line":409,"column":null}},"type":"if","locations":[{"start":{"line":409,"column":10},"end":{"line":409,"column":null}},{"start":{},"end":{}}],"line":409},"56":{"loc":{"start":{"line":410,"column":8},"end":{"line":412,"column":null}},"type":"if","locations":[{"start":{"line":410,"column":8},"end":{"line":412,"column":null}},{"start":{},"end":{}}],"line":410},"57":{"loc":{"start":{"line":417,"column":11},"end":{"line":417,"column":null}},"type":"cond-expr","locations":[{"start":{"line":417,"column":33},"end":{"line":417,"column":54}},{"start":{"line":417,"column":54},"end":{"line":417,"column":null}}],"line":417}},"s":{"0":57,"1":2,"2":2,"3":1,"4":1,"5":1,"6":0,"7":1,"8":1,"9":1,"10":1,"11":2,"12":1,"13":1,"14":1,"15":2,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":2,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"40":2,"41":1,"42":1,"43":0,"44":1,"45":1,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":1,"58":1,"59":1,"60":2,"61":2,"62":2,"63":2,"64":1,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":1,"72":1,"73":1,"74":1,"75":1,"76":2,"77":2,"78":2,"79":2,"80":1,"81":1,"82":0,"83":0,"84":0,"85":1,"86":1,"87":1,"88":1,"89":1,"90":1,"91":1,"92":1,"93":1,"94":0,"95":1,"96":2,"97":0,"98":1,"99":0,"100":0,"101":1,"102":1,"103":0,"104":0,"105":0,"106":1,"107":1,"108":1,"109":2,"110":0,"111":2,"112":2,"113":2,"114":3,"115":1,"116":1,"117":2,"118":2,"119":2,"120":1,"121":1,"122":1,"123":1,"124":1,"125":2,"126":0,"127":2,"128":2,"129":2,"130":2,"131":2,"132":3,"133":1,"134":1,"135":1,"136":2,"137":2,"138":2,"139":1},"f":{"0":57,"1":2,"2":2,"3":2,"4":2,"5":0,"6":1,"7":0,"8":1,"9":1,"10":1,"11":2,"12":1,"13":2},"b":{"0":[2],"1":[2],"2":[2],"3":[2],"4":[2,0],"5":[1,1],"6":[2,1],"7":[0,1],"8":[0,1],"9":[1,1],"10":[2,1,1],"11":[1,0],"12":[1,0],"13":[1,0],"14":[1,0],"15":[1,1,1],"16":[1,0],"17":[1,0],"18":[1,0],"19":[1,0],"20":[1,1],"21":[0,1],"22":[1,0],"23":[2,0],"24":[1,1],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[2,0],"32":[2,0],"33":[1,1],"34":[0,1],"35":[0,0],"36":[0,0],"37":[2,2],"38":[1,1],"39":[0,1],"40":[0,0],"41":[0,1],"42":[1,0],"43":[0,2],"44":[0,1],"45":[1,0],"46":[0,2],"47":[1,2],"48":[1,0],"49":[1,1],"50":[2,0],"51":[1,1],"52":[0,2],"53":[1,2],"54":[3,1,1],"55":[1,0],"56":[2,0],"57":[2,0]},"meta":{"lastBranch":58,"lastFunction":14,"lastStatement":140,"seen":{"f:42:16:42:31":0,"s:43:2:212:Infinity":0,"f:47:10:47:20":1,"s:55:10:55:Infinity":1,"b:50:16:50:Infinity":0,"b:51:15:51:Infinity":1,"b:53:16:53:Infinity":2,"b:54:18:54:Infinity":3,"b:55:10:55:18:55:18:55:Infinity":4,"b:57:6:64:Infinity:undefined:undefined:undefined:undefined":5,"s:57:6:64:Infinity":2,"b:57:10:57:23:57:23:57:53":6,"s:58:8:63:Infinity":3,"s:66:27:66:Infinity":4,"b:67:6:74:Infinity:undefined:undefined:undefined:undefined":7,"s:67:6:74:Infinity":5,"s:68:8:73:Infinity":6,"s:76:6:210:Infinity":7,"s:77:25:77:Infinity":8,"s:78:32:78:Infinity":9,"s:82:10:82:Infinity":10,"b:82:28:82:58:82:58:82:Infinity":8,"b:85:8:118:Infinity:undefined:undefined:undefined:undefined":9,"s:85:8:118:Infinity":11,"b:86:10:86:Infinity:87:10:87:Infinity:88:10:88:Infinity":10,"s:90:25:90:Infinity":12,"s:91:16:91:Infinity":13,"s:92:29:95:Infinity":14,"f:95:20:95:21":2,"s:95:35:95:47":15,"s:97:10:117:Infinity":16,"s:98:12:116:Infinity":17,"s:99:26:99:Infinity":18,"s:100:14:113:Infinity":19,"s:101:30:101:Infinity":20,"b:102:16:112:Infinity:undefined:undefined:undefined:undefined":11,"s:102:16:112:Infinity":21,"b:102:20:102:33:102:33:102:58":12,"s:103:18:111:Infinity":22,"b:107:29:107:44:107:44:107:Infinity":13,"b:121:8:173:Infinity:undefined:undefined:undefined:undefined":14,"s:121:8:173:Infinity":23,"b:122:10:122:Infinity:123:10:123:Infinity:124:10:124:Infinity":15,"s:126:29:138:Infinity":24,"s:139:30:139:Infinity":25,"s:140:29:143:Infinity":26,"f:143:20:143:21":3,"s:143:35:143:47":27,"s:145:10:172:Infinity":28,"s:146:12:171:Infinity":29,"s:147:30:147:Infinity":30,"s:148:30:148:Infinity":31,"s:149:28:154:Infinity":32,"b:155:14:168:Infinity:undefined:undefined:undefined:undefined":16,"s:155:14:168:Infinity":33,"s:156:32:161:Infinity":34,"s:162:16:167:Infinity":35,"b:166:27:166:38:166:38:166:Infinity":17,"b:176:8:179:Infinity:undefined:undefined:undefined:undefined":18,"s:176:8:179:Infinity":36,"b:176:12:176:39:176:39:176:70":19,"s:177:23:177:Infinity":37,"s:178:10:178:Infinity":38,"s:182:23:188:Infinity":39,"f:183:16:183:17":4,"b:184:12:184:Infinity:undefined:undefined:undefined:undefined":20,"s:184:12:184:Infinity":40,"s:184:40:184:Infinity":41,"b:185:12:185:Infinity:undefined:undefined:undefined:undefined":21,"s:185:12:185:Infinity":42,"s:185:40:185:Infinity":43,"s:186:12:186:Infinity":44,"b:186:20:186:31:186:31:186:37":22,"b:186:37:186:48:186:48:186:Infinity":23,"s:190:8:203:Infinity":45,"b:195:20:195:30:195:30:195:Infinity":24,"s:205:8:209:Infinity":46,"b:207:35:207:51:207:51:207:Infinity":25,"f:222:9:222:Infinity":5,"b:226:2:226:Infinity:undefined:undefined:undefined:undefined":26,"s:226:2:226:Infinity":47,"s:226:14:226:Infinity":48,"s:227:8:227:Infinity":49,"b:227:17:227:26:227:26:227:30":27,"b:228:2:233:Infinity:undefined:undefined:undefined:undefined":28,"s:228:2:233:Infinity":50,"s:233:4:233:Infinity":51,"b:234:2:235:Infinity:undefined:undefined:undefined:undefined":29,"s:234:2:235:Infinity":52,"s:235:4:235:Infinity":53,"b:236:2:241:Infinity:undefined:undefined:undefined:undefined":30,"s:236:2:241:Infinity":54,"s:241:4:241:Infinity":55,"s:242:2:242:Infinity":56,"f:248:9:248:Infinity":6,"s:253:14:253:Infinity":57,"s:254:15:254:Infinity":58,"s:255:2:261:Infinity":59,"s:256:15:256:Infinity":60,"s:257:10:257:Infinity":61,"b:257:19:257:37:257:37:257:41":31,"b:258:4:260:Infinity:undefined:undefined:undefined:undefined":32,"s:258:4:260:Infinity":62,"s:259:6:259:Infinity":63,"b:259:71:259:75:259:75:259:Infinity":33,"b:262:2:267:Infinity:undefined:undefined:undefined:undefined":34,"s:262:2:267:Infinity":64,"s:263:21:263:Infinity":65,"b:264:4:266:Infinity:265:15:266:Infinity":35,"s:264:4:266:Infinity":66,"f:264:34:264:35":7,"s:264:41:264:75":67,"s:265:6:265:Infinity":68,"b:265:15:266:Infinity:undefined:undefined:undefined:undefined":36,"s:265:15:266:Infinity":69,"s:266:38:266:Infinity":70,"s:268:2:268:Infinity":71,"f:274:9:274:Infinity":8,"s:280:14:280:Infinity":72,"s:281:16:281:Infinity":73,"s:282:20:282:Infinity":74,"s:283:2:288:Infinity":75,"s:284:15:284:Infinity":76,"s:285:10:285:Infinity":77,"b:285:19:285:38:285:38:285:42":37,"s:286:4:286:Infinity":78,"b:287:4:287:Infinity:undefined:undefined:undefined:undefined":38,"s:287:4:287:Infinity":79,"s:287:34:287:Infinity":80,"b:289:2:297:Infinity:undefined:undefined:undefined:undefined":39,"s:289:2:297:Infinity":81,"s:290:21:290:Infinity":82,"s:291:10:295:Infinity":83,"b:292:6:294:11:294:11:294:Infinity":40,"s:296:4:296:Infinity":84,"s:298:2:298:Infinity":85,"f:304:9:304:Infinity":9,"s:310:16:310:Infinity":86,"s:311:17:311:Infinity":87,"s:312:18:312:Infinity":88,"s:313:2:324:Infinity":89,"s:313:15:313:18":90,"s:314:18:314:Infinity":91,"s:315:16:315:Infinity":92,"b:316:4:316:Infinity:undefined:undefined:undefined:undefined":41,"s:316:4:316:Infinity":93,"b:316:8:316:18:316:18:316:56":42,"s:316:56:316:Infinity":94,"s:317:4:319:Infinity":95,"b:318:6:318:Infinity:undefined:undefined:undefined:undefined":43,"s:318:6:318:Infinity":96,"s:318:32:318:Infinity":97,"b:320:4:323:Infinity:undefined:undefined:undefined:undefined":44,"s:320:4:323:Infinity":98,"s:321:6:321:Infinity":99,"s:322:6:322:Infinity":100,"b:325:2:325:Infinity:undefined:undefined:undefined:undefined":45,"s:325:2:325:Infinity":101,"s:325:23:325:Infinity":102,"s:326:16:326:Infinity":103,"s:327:14:327:Infinity":104,"s:328:2:328:Infinity":105,"f:334:9:334:Infinity":10,"s:338:28:338:Infinity":106,"s:339:21:350:Infinity":107,"s:352:15:371:Infinity":108,"f:352:15:352:16":11,"b:353:4:353:Infinity:undefined:undefined:undefined:undefined":46,"s:353:4:353:Infinity":109,"s:353:19:353:Infinity":110,"s:354:4:370:Infinity":111,"s:355:22:355:Infinity":112,"s:356:6:367:Infinity":113,"b:357:8:366:Infinity:361:8:366:Infinity":47,"s:357:8:366:Infinity":114,"b:358:10:360:Infinity:undefined:undefined:undefined:undefined":48,"s:358:10:360:Infinity":115,"b:358:14:358:45:358:45:358:74":49,"s:359:12:359:Infinity":116,"b:361:8:366:Infinity:undefined:undefined:undefined:undefined":50,"s:361:8:366:Infinity":117,"s:362:22:362:Infinity":118,"b:363:10:365:Infinity:undefined:undefined:undefined:undefined":51,"s:363:10:365:Infinity":119,"s:364:12:364:Infinity":120,"s:373:2:373:Infinity":121,"s:374:2:374:Infinity":122,"f:380:9:380:25":12,"s:381:21:392:Infinity":123,"s:394:15:418:Infinity":124,"f:394:15:394:16":13,"b:395:4:395:Infinity:undefined:undefined:undefined:undefined":52,"s:395:4:395:Infinity":125,"s:395:26:395:Infinity":126,"s:396:17:396:Infinity":127,"s:397:28:397:Infinity":128,"s:398:4:416:Infinity":129,"s:399:22:401:Infinity":130,"s:402:6:413:Infinity":131,"b:403:8:412:Infinity:410:8:412:Infinity":53,"s:403:8:412:Infinity":132,"b:404:10:404:Infinity:405:10:405:Infinity:406:10:406:Infinity":54,"s:408:24:408:Infinity":133,"b:409:10:409:Infinity:undefined:undefined:undefined:undefined":55,"s:409:10:409:Infinity":134,"s:409:21:409:Infinity":135,"b:410:8:412:Infinity:undefined:undefined:undefined:undefined":56,"s:410:8:412:Infinity":136,"s:411:10:411:Infinity":137,"s:417:4:417:Infinity":138,"b:417:33:417:54:417:54:417:Infinity":57,"s:420:2:420:Infinity":139}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/tools/handlers/test-tools.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/tools/handlers/test-tools.ts","statementMap":{"0":{"start":{"line":41,"column":2},"end":{"line":243,"column":null}},"1":{"start":{"line":50,"column":10},"end":{"line":50,"column":null}},"2":{"start":{"line":52,"column":6},"end":{"line":61,"column":null}},"3":{"start":{"line":53,"column":23},"end":{"line":56,"column":null}},"4":{"start":{"line":58,"column":8},"end":{"line":58,"column":null}},"5":{"start":{"line":60,"column":8},"end":{"line":60,"column":null}},"6":{"start":{"line":68,"column":54},"end":{"line":68,"column":null}},"7":{"start":{"line":70,"column":6},"end":{"line":104,"column":null}},"8":{"start":{"line":71,"column":8},"end":{"line":71,"column":null}},"9":{"start":{"line":72,"column":22},"end":{"line":72,"column":null}},"10":{"start":{"line":74,"column":8},"end":{"line":101,"column":null}},"11":{"start":{"line":103,"column":8},"end":{"line":103,"column":null}},"12":{"start":{"line":111,"column":22},"end":{"line":111,"column":null}},"13":{"start":{"line":112,"column":20},"end":{"line":112,"column":null}},"14":{"start":{"line":113,"column":37},"end":{"line":117,"column":null}},"15":{"start":{"line":119,"column":6},"end":{"line":141,"column":null}},"16":{"start":{"line":120,"column":8},"end":{"line":140,"column":null}},"17":{"start":{"line":143,"column":6},"end":{"line":171,"column":null}},"18":{"start":{"line":144,"column":23},"end":{"line":148,"column":null}},"19":{"start":{"line":150,"column":8},"end":{"line":168,"column":null}},"20":{"start":{"line":170,"column":8},"end":{"line":170,"column":null}},"21":{"start":{"line":178,"column":71},"end":{"line":178,"column":null}},"22":{"start":{"line":180,"column":6},"end":{"line":241,"column":null}},"23":{"start":{"line":181,"column":8},"end":{"line":192,"column":null}},"24":{"start":{"line":182,"column":10},"end":{"line":191,"column":null}},"25":{"start":{"line":195,"column":20},"end":{"line":201,"column":null}},"26":{"start":{"line":203,"column":8},"end":{"line":203,"column":null}},"27":{"start":{"line":206,"column":8},"end":{"line":234,"column":null}},"28":{"start":{"line":207,"column":16},"end":{"line":211,"column":null}},"29":{"start":{"line":213,"column":10},"end":{"line":221,"column":null}},"30":{"start":{"line":224,"column":10},"end":{"line":233,"column":null}},"31":{"start":{"line":236,"column":8},"end":{"line":240,"column":null}}},"fnMap":{"0":{"name":"createTestTools","decl":{"start":{"line":40,"column":16},"end":{"line":40,"column":32}},"loc":{"start":{"line":40,"column":54},"end":{"line":244,"column":null}},"line":40},"1":{"name":"(anonymous_1)","decl":{"start":{"line":45,"column":10},"end":{"line":45,"column":22}},"loc":{"start":{"line":45,"column":50},"end":{"line":62,"column":null}},"line":45},"2":{"name":"(anonymous_2)","decl":{"start":{"line":67,"column":10},"end":{"line":67,"column":26}},"loc":{"start":{"line":67,"column":54},"end":{"line":105,"column":null}},"line":67},"3":{"name":"(anonymous_3)","decl":{"start":{"line":110,"column":10},"end":{"line":110,"column":25}},"loc":{"start":{"line":110,"column":53},"end":{"line":172,"column":null}},"line":110},"4":{"name":"(anonymous_4)","decl":{"start":{"line":177,"column":10},"end":{"line":177,"column":19}},"loc":{"start":{"line":177,"column":47},"end":{"line":242,"column":null}},"line":177}},"branchMap":{"0":{"loc":{"start":{"line":48,"column":8},"end":{"line":48,"column":null}},"type":"default-arg","locations":[{"start":{"line":48,"column":29},"end":{"line":48,"column":null}}],"line":48},"1":{"loc":{"start":{"line":49,"column":8},"end":{"line":49,"column":null}},"type":"default-arg","locations":[{"start":{"line":49,"column":18},"end":{"line":49,"column":null}}],"line":49},"2":{"loc":{"start":{"line":68,"column":14},"end":{"line":68,"column":30}},"type":"default-arg","locations":[{"start":{"line":68,"column":26},"end":{"line":68,"column":30}}],"line":68},"3":{"loc":{"start":{"line":68,"column":30},"end":{"line":68,"column":50}},"type":"default-arg","locations":[{"start":{"line":68,"column":40},"end":{"line":68,"column":50}}],"line":68},"4":{"loc":{"start":{"line":111,"column":22},"end":{"line":111,"column":null}},"type":"binary-expr","locations":[{"start":{"line":111,"column":22},"end":{"line":111,"column":39}},{"start":{"line":111,"column":39},"end":{"line":111,"column":null}}],"line":111},"5":{"loc":{"start":{"line":112,"column":20},"end":{"line":112,"column":null}},"type":"cond-expr","locations":[{"start":{"line":112,"column":54},"end":{"line":112,"column":67}},{"start":{"line":112,"column":67},"end":{"line":112,"column":null}}],"line":112},"6":{"loc":{"start":{"line":113,"column":37},"end":{"line":117,"column":null}},"type":"cond-expr","locations":[{"start":{"line":114,"column":10},"end":{"line":114,"column":null}},{"start":{"line":115,"column":10},"end":{"line":117,"column":null}}],"line":113},"7":{"loc":{"start":{"line":115,"column":10},"end":{"line":117,"column":null}},"type":"cond-expr","locations":[{"start":{"line":116,"column":12},"end":{"line":116,"column":null}},{"start":{"line":117,"column":12},"end":{"line":117,"column":null}}],"line":115},"8":{"loc":{"start":{"line":119,"column":6},"end":{"line":141,"column":null}},"type":"if","locations":[{"start":{"line":119,"column":6},"end":{"line":141,"column":null}},{"start":{},"end":{}}],"line":119},"9":{"loc":{"start":{"line":161,"column":18},"end":{"line":163,"column":null}},"type":"cond-expr","locations":[{"start":{"line":162,"column":22},"end":{"line":162,"column":null}},{"start":{"line":163,"column":22},"end":{"line":163,"column":null}}],"line":161},"10":{"loc":{"start":{"line":178,"column":14},"end":{"line":178,"column":30}},"type":"default-arg","locations":[{"start":{"line":178,"column":26},"end":{"line":178,"column":30}}],"line":178},"11":{"loc":{"start":{"line":178,"column":30},"end":{"line":178,"column":47}},"type":"default-arg","locations":[{"start":{"line":178,"column":41},"end":{"line":178,"column":47}}],"line":178},"12":{"loc":{"start":{"line":178,"column":47},"end":{"line":178,"column":67}},"type":"default-arg","locations":[{"start":{"line":178,"column":57},"end":{"line":178,"column":67}}],"line":178},"13":{"loc":{"start":{"line":181,"column":8},"end":{"line":192,"column":null}},"type":"if","locations":[{"start":{"line":181,"column":8},"end":{"line":192,"column":null}},{"start":{},"end":{}}],"line":181},"14":{"loc":{"start":{"line":181,"column":12},"end":{"line":181,"column":50}},"type":"binary-expr","locations":[{"start":{"line":181,"column":12},"end":{"line":181,"column":26}},{"start":{"line":181,"column":26},"end":{"line":181,"column":50}}],"line":181},"15":{"loc":{"start":{"line":197,"column":10},"end":{"line":199,"column":null}},"type":"cond-expr","locations":[{"start":{"line":198,"column":14},"end":{"line":198,"column":null}},{"start":{"line":199,"column":14},"end":{"line":199,"column":null}}],"line":197},"16":{"loc":{"start":{"line":229,"column":22},"end":{"line":229,"column":null}},"type":"binary-expr","locations":[{"start":{"line":229,"column":22},"end":{"line":229,"column":72}},{"start":{"line":229,"column":72},"end":{"line":229,"column":null}}],"line":229},"17":{"loc":{"start":{"line":238,"column":36},"end":{"line":238,"column":90}},"type":"cond-expr","locations":[{"start":{"line":238,"column":61},"end":{"line":238,"column":77}},{"start":{"line":238,"column":77},"end":{"line":238,"column":90}}],"line":238}},"s":{"0":57,"1":1,"2":1,"3":1,"4":1,"5":0,"6":1,"7":1,"8":1,"9":1,"10":1,"11":0,"12":4,"13":4,"14":4,"15":4,"16":1,"17":3,"18":3,"19":3,"20":0,"21":1,"22":1,"23":1,"24":1,"25":0,"26":1,"27":1,"28":1,"29":1,"30":0,"31":0},"f":{"0":57,"1":1,"2":1,"3":4,"4":1},"b":{"0":[1],"1":[1],"2":[1],"3":[1],"4":[4,3],"5":[3,1],"6":[3,1],"7":[1,0],"8":[1,3],"9":[0,3],"10":[1],"11":[1],"12":[1],"13":[1,0],"14":[1,1],"15":[0,0],"16":[0,0],"17":[0,0]},"meta":{"lastBranch":18,"lastFunction":5,"lastStatement":32,"seen":{"f:40:16:40:32":0,"s:41:2:243:Infinity":0,"f:45:10:45:22":1,"s:50:10:50:Infinity":1,"b:48:29:48:Infinity":0,"b:49:18:49:Infinity":1,"s:52:6:61:Infinity":2,"s:53:23:56:Infinity":3,"s:58:8:58:Infinity":4,"s:60:8:60:Infinity":5,"f:67:10:67:26":2,"s:68:54:68:Infinity":6,"b:68:26:68:30":2,"b:68:40:68:50":3,"s:70:6:104:Infinity":7,"s:71:8:71:Infinity":8,"s:72:22:72:Infinity":9,"s:74:8:101:Infinity":10,"s:103:8:103:Infinity":11,"f:110:10:110:25":3,"s:111:22:111:Infinity":12,"b:111:22:111:39:111:39:111:Infinity":4,"s:112:20:112:Infinity":13,"b:112:54:112:67:112:67:112:Infinity":5,"s:113:37:117:Infinity":14,"b:114:10:114:Infinity:115:10:117:Infinity":6,"b:116:12:116:Infinity:117:12:117:Infinity":7,"b:119:6:141:Infinity:undefined:undefined:undefined:undefined":8,"s:119:6:141:Infinity":15,"s:120:8:140:Infinity":16,"s:143:6:171:Infinity":17,"s:144:23:148:Infinity":18,"s:150:8:168:Infinity":19,"b:162:22:162:Infinity:163:22:163:Infinity":9,"s:170:8:170:Infinity":20,"f:177:10:177:19":4,"s:178:71:178:Infinity":21,"b:178:26:178:30":10,"b:178:41:178:47":11,"b:178:57:178:67":12,"s:180:6:241:Infinity":22,"b:181:8:192:Infinity:undefined:undefined:undefined:undefined":13,"s:181:8:192:Infinity":23,"b:181:12:181:26:181:26:181:50":14,"s:182:10:191:Infinity":24,"s:195:20:201:Infinity":25,"b:198:14:198:Infinity:199:14:199:Infinity":15,"s:203:8:203:Infinity":26,"s:206:8:234:Infinity":27,"s:207:16:211:Infinity":28,"s:213:10:221:Infinity":29,"s:224:10:233:Infinity":30,"b:229:22:229:72:229:72:229:Infinity":16,"s:236:8:240:Infinity":31,"b:238:61:238:77:238:77:238:90":17}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/utils/exec-utils.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/utils/exec-utils.ts","statementMap":{"0":{"start":{"line":32,"column":6},"end":{"line":32,"column":null}},"1":{"start":{"line":34,"column":2},"end":{"line":57,"column":null}},"2":{"start":{"line":35,"column":10},"end":{"line":40,"column":null}},"3":{"start":{"line":42,"column":4},"end":{"line":42,"column":null}},"4":{"start":{"line":44,"column":4},"end":{"line":55,"column":null}},"5":{"start":{"line":45,"column":6},"end":{"line":49,"column":null}},"6":{"start":{"line":46,"column":8},"end":{"line":48,"column":null}},"7":{"start":{"line":50,"column":6},"end":{"line":54,"column":null}},"8":{"start":{"line":51,"column":8},"end":{"line":53,"column":null}},"9":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"10":{"start":{"line":70,"column":2},"end":{"line":76,"column":null}},"11":{"start":{"line":71,"column":19},"end":{"line":71,"column":null}},"12":{"start":{"line":72,"column":4},"end":{"line":72,"column":null}},"13":{"start":{"line":74,"column":21},"end":{"line":74,"column":null}},"14":{"start":{"line":75,"column":4},"end":{"line":75,"column":null}}},"fnMap":{"0":{"name":"execWithTimeout","decl":{"start":{"line":23,"column":16},"end":{"line":23,"column":null}},"loc":{"start":{"line":26,"column":10},"end":{"line":58,"column":null}},"line":26},"1":{"name":"execWithTimeoutSafe","decl":{"start":{"line":66,"column":16},"end":{"line":66,"column":null}},"loc":{"start":{"line":69,"column":60},"end":{"line":77,"column":null}},"line":69}},"branchMap":{"0":{"loc":{"start":{"line":25,"column":2},"end":{"line":25,"column":null}},"type":"default-arg","locations":[{"start":{"line":25,"column":29},"end":{"line":25,"column":null}}],"line":25},"1":{"loc":{"start":{"line":28,"column":4},"end":{"line":28,"column":null}},"type":"default-arg","locations":[{"start":{"line":28,"column":14},"end":{"line":28,"column":null}}],"line":28},"2":{"loc":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"type":"default-arg","locations":[{"start":{"line":29,"column":21},"end":{"line":29,"column":null}}],"line":29},"3":{"loc":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"type":"default-arg","locations":[{"start":{"line":30,"column":15},"end":{"line":30,"column":null}}],"line":30},"4":{"loc":{"start":{"line":44,"column":4},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":44,"column":4},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":44},"5":{"loc":{"start":{"line":45,"column":6},"end":{"line":49,"column":null}},"type":"if","locations":[{"start":{"line":45,"column":6},"end":{"line":49,"column":null}},{"start":{},"end":{}}],"line":45},"6":{"loc":{"start":{"line":50,"column":6},"end":{"line":54,"column":null}},"type":"if","locations":[{"start":{"line":50,"column":6},"end":{"line":54,"column":null}},{"start":{},"end":{}}],"line":50},"7":{"loc":{"start":{"line":68,"column":2},"end":{"line":68,"column":null}},"type":"default-arg","locations":[{"start":{"line":68,"column":29},"end":{"line":68,"column":null}}],"line":68},"8":{"loc":{"start":{"line":74,"column":21},"end":{"line":74,"column":null}},"type":"cond-expr","locations":[{"start":{"line":74,"column":46},"end":{"line":74,"column":62}},{"start":{"line":74,"column":62},"end":{"line":74,"column":null}}],"line":74}},"s":{"0":5,"1":5,"2":5,"3":5,"4":3,"5":3,"6":1,"7":2,"8":1,"9":1,"10":2,"11":2,"12":2,"13":1,"14":1},"f":{"0":5,"1":2},"b":{"0":[5],"1":[5],"2":[5],"3":[5],"4":[3,0],"5":[1,2],"6":[1,1],"7":[2],"8":[1,0]},"meta":{"lastBranch":9,"lastFunction":2,"lastStatement":15,"seen":{"f:23:16:23:Infinity":0,"b:25:29:25:Infinity":0,"s:32:6:32:Infinity":0,"b:28:14:28:Infinity":1,"b:29:21:29:Infinity":2,"b:30:15:30:Infinity":3,"s:34:2:57:Infinity":1,"s:35:10:40:Infinity":2,"s:42:4:42:Infinity":3,"b:44:4:55:Infinity:undefined:undefined:undefined:undefined":4,"s:44:4:55:Infinity":4,"b:45:6:49:Infinity:undefined:undefined:undefined:undefined":5,"s:45:6:49:Infinity":5,"s:46:8:48:Infinity":6,"b:50:6:54:Infinity:undefined:undefined:undefined:undefined":6,"s:50:6:54:Infinity":7,"s:51:8:53:Infinity":8,"s:56:4:56:Infinity":9,"f:66:16:66:Infinity":1,"b:68:29:68:Infinity":7,"s:70:2:76:Infinity":10,"s:71:19:71:Infinity":11,"s:72:4:72:Infinity":12,"s:74:21:74:Infinity":13,"b:74:46:74:62:74:62:74:Infinity":8,"s:75:4:75:Infinity":14}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/utils/validation.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/utils/validation.ts","statementMap":{"0":{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},"1":{"start":{"line":16,"column":4},"end":{"line":16,"column":null}},"2":{"start":{"line":19,"column":2},"end":{"line":21,"column":null}},"3":{"start":{"line":20,"column":4},"end":{"line":20,"column":null}},"4":{"start":{"line":23,"column":2},"end":{"line":27,"column":null}},"5":{"start":{"line":24,"column":4},"end":{"line":26,"column":null}},"6":{"start":{"line":29,"column":2},"end":{"line":29,"column":null}},"7":{"start":{"line":39,"column":2},"end":{"line":41,"column":null}},"8":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"9":{"start":{"line":43,"column":2},"end":{"line":45,"column":null}},"10":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"11":{"start":{"line":48,"column":2},"end":{"line":50,"column":null}},"12":{"start":{"line":49,"column":4},"end":{"line":49,"column":null}},"13":{"start":{"line":52,"column":2},"end":{"line":52,"column":null}},"14":{"start":{"line":66,"column":2},"end":{"line":68,"column":null}},"15":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"16":{"start":{"line":70,"column":2},"end":{"line":74,"column":null}},"17":{"start":{"line":71,"column":4},"end":{"line":73,"column":null}},"18":{"start":{"line":76,"column":2},"end":{"line":76,"column":null}},"19":{"start":{"line":86,"column":2},"end":{"line":88,"column":null}},"20":{"start":{"line":87,"column":4},"end":{"line":87,"column":null}},"21":{"start":{"line":90,"column":2},"end":{"line":94,"column":null}},"22":{"start":{"line":91,"column":4},"end":{"line":93,"column":null}},"23":{"start":{"line":97,"column":21},"end":{"line":97,"column":null}},"24":{"start":{"line":98,"column":2},"end":{"line":106,"column":null}},"25":{"start":{"line":108,"column":2},"end":{"line":108,"column":null}},"26":{"start":{"line":117,"column":2},"end":{"line":119,"column":null}},"27":{"start":{"line":118,"column":4},"end":{"line":118,"column":null}},"28":{"start":{"line":121,"column":2},"end":{"line":123,"column":null}},"29":{"start":{"line":122,"column":4},"end":{"line":122,"column":null}},"30":{"start":{"line":127,"column":16},"end":{"line":127,"column":null}},"31":{"start":{"line":128,"column":2},"end":{"line":132,"column":null}},"32":{"start":{"line":129,"column":4},"end":{"line":131,"column":null}},"33":{"start":{"line":134,"column":2},"end":{"line":134,"column":null}},"34":{"start":{"line":147,"column":2},"end":{"line":149,"column":null}},"35":{"start":{"line":148,"column":4},"end":{"line":148,"column":null}},"36":{"start":{"line":151,"column":19},"end":{"line":151,"column":null}},"37":{"start":{"line":153,"column":2},"end":{"line":157,"column":null}},"38":{"start":{"line":154,"column":4},"end":{"line":156,"column":null}},"39":{"start":{"line":159,"column":2},"end":{"line":159,"column":null}},"40":{"start":{"line":172,"column":2},"end":{"line":174,"column":null}},"41":{"start":{"line":173,"column":4},"end":{"line":173,"column":null}},"42":{"start":{"line":176,"column":2},"end":{"line":180,"column":null}},"43":{"start":{"line":177,"column":4},"end":{"line":179,"column":null}},"44":{"start":{"line":182,"column":2},"end":{"line":182,"column":null}},"45":{"start":{"line":196,"column":2},"end":{"line":198,"column":null}},"46":{"start":{"line":212,"column":2},"end":{"line":214,"column":null}},"47":{"start":{"line":213,"column":4},"end":{"line":213,"column":null}},"48":{"start":{"line":216,"column":16},"end":{"line":216,"column":null}},"49":{"start":{"line":217,"column":2},"end":{"line":219,"column":null}},"50":{"start":{"line":218,"column":4},"end":{"line":218,"column":null}},"51":{"start":{"line":221,"column":20},"end":{"line":221,"column":null}},"52":{"start":{"line":222,"column":2},"end":{"line":224,"column":null}},"53":{"start":{"line":223,"column":4},"end":{"line":223,"column":null}},"54":{"start":{"line":226,"column":2},"end":{"line":226,"column":null}},"55":{"start":{"line":243,"column":16},"end":{"line":243,"column":null}},"56":{"start":{"line":244,"column":2},"end":{"line":249,"column":null}},"57":{"start":{"line":263,"column":8},"end":{"line":263,"column":null}},"58":{"start":{"line":264,"column":2},"end":{"line":264,"column":null}}},"fnMap":{"0":{"name":"validateProjectId","decl":{"start":{"line":14,"column":16},"end":{"line":14,"column":34}},"loc":{"start":{"line":14,"column":62},"end":{"line":30,"column":null}},"line":14},"1":{"name":"validateFilePath","decl":{"start":{"line":38,"column":16},"end":{"line":38,"column":33}},"loc":{"start":{"line":38,"column":60},"end":{"line":53,"column":null}},"line":38},"2":{"name":"validateQuery","decl":{"start":{"line":62,"column":16},"end":{"line":62,"column":null}},"loc":{"start":{"line":65,"column":10},"end":{"line":77,"column":null}},"line":65},"3":{"name":"validateCypherQuery","decl":{"start":{"line":85,"column":16},"end":{"line":85,"column":36}},"loc":{"start":{"line":85,"column":60},"end":{"line":109,"column":null}},"line":85},"4":{"name":"validateNodeId","decl":{"start":{"line":116,"column":16},"end":{"line":116,"column":31}},"loc":{"start":{"line":116,"column":56},"end":{"line":135,"column":null}},"line":116},"5":{"name":"validateLimit","decl":{"start":{"line":143,"column":16},"end":{"line":143,"column":null}},"loc":{"start":{"line":146,"column":10},"end":{"line":160,"column":null}},"line":146},"6":{"name":"validateMode","decl":{"start":{"line":168,"column":16},"end":{"line":168,"column":null}},"loc":{"start":{"line":171,"column":10},"end":{"line":183,"column":null}},"line":171},"7":{"name":"createValidationError","decl":{"start":{"line":191,"column":16},"end":{"line":191,"column":null}},"loc":{"start":{"line":195,"column":9},"end":{"line":199,"column":null}},"line":195},"8":{"name":"extractProjectIdFromScopedId","decl":{"start":{"line":208,"column":16},"end":{"line":208,"column":null}},"loc":{"start":{"line":211,"column":10},"end":{"line":227,"column":null}},"line":211},"9":{"name":"parseScopedId","decl":{"start":{"line":235,"column":16},"end":{"line":235,"column":null}},"loc":{"start":{"line":242,"column":2},"end":{"line":250,"column":null}},"line":242},"10":{"name":"generateSecureId","decl":{"start":{"line":259,"column":16},"end":{"line":259,"column":null}},"loc":{"start":{"line":262,"column":10},"end":{"line":265,"column":null}},"line":262}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},"type":"if","locations":[{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},{"start":{},"end":{}}],"line":15},"1":{"loc":{"start":{"line":19,"column":2},"end":{"line":21,"column":null}},"type":"if","locations":[{"start":{"line":19,"column":2},"end":{"line":21,"column":null}},{"start":{},"end":{}}],"line":19},"2":{"loc":{"start":{"line":19,"column":6},"end":{"line":19,"column":56}},"type":"binary-expr","locations":[{"start":{"line":19,"column":6},"end":{"line":19,"column":32}},{"start":{"line":19,"column":32},"end":{"line":19,"column":56}}],"line":19},"3":{"loc":{"start":{"line":23,"column":2},"end":{"line":27,"column":null}},"type":"if","locations":[{"start":{"line":23,"column":2},"end":{"line":27,"column":null}},{"start":{},"end":{}}],"line":23},"4":{"loc":{"start":{"line":39,"column":2},"end":{"line":41,"column":null}},"type":"if","locations":[{"start":{"line":39,"column":2},"end":{"line":41,"column":null}},{"start":{},"end":{}}],"line":39},"5":{"loc":{"start":{"line":43,"column":2},"end":{"line":45,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":2},"end":{"line":45,"column":null}},{"start":{},"end":{}}],"line":43},"6":{"loc":{"start":{"line":43,"column":6},"end":{"line":43,"column":55}},"type":"binary-expr","locations":[{"start":{"line":43,"column":6},"end":{"line":43,"column":31}},{"start":{"line":43,"column":31},"end":{"line":43,"column":55}}],"line":43},"7":{"loc":{"start":{"line":48,"column":2},"end":{"line":50,"column":null}},"type":"if","locations":[{"start":{"line":48,"column":2},"end":{"line":50,"column":null}},{"start":{},"end":{}}],"line":48},"8":{"loc":{"start":{"line":48,"column":6},"end":{"line":48,"column":59}},"type":"binary-expr","locations":[{"start":{"line":48,"column":6},"end":{"line":48,"column":33}},{"start":{"line":48,"column":33},"end":{"line":48,"column":59}}],"line":48},"9":{"loc":{"start":{"line":64,"column":2},"end":{"line":64,"column":null}},"type":"default-arg","locations":[{"start":{"line":64,"column":22},"end":{"line":64,"column":null}}],"line":64},"10":{"loc":{"start":{"line":66,"column":2},"end":{"line":68,"column":null}},"type":"if","locations":[{"start":{"line":66,"column":2},"end":{"line":68,"column":null}},{"start":{},"end":{}}],"line":66},"11":{"loc":{"start":{"line":70,"column":2},"end":{"line":74,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":2},"end":{"line":74,"column":null}},{"start":{},"end":{}}],"line":70},"12":{"loc":{"start":{"line":70,"column":6},"end":{"line":70,"column":54}},"type":"binary-expr","locations":[{"start":{"line":70,"column":6},"end":{"line":70,"column":28}},{"start":{"line":70,"column":28},"end":{"line":70,"column":54}}],"line":70},"13":{"loc":{"start":{"line":86,"column":2},"end":{"line":88,"column":null}},"type":"if","locations":[{"start":{"line":86,"column":2},"end":{"line":88,"column":null}},{"start":{},"end":{}}],"line":86},"14":{"loc":{"start":{"line":90,"column":2},"end":{"line":94,"column":null}},"type":"if","locations":[{"start":{"line":90,"column":2},"end":{"line":94,"column":null}},{"start":{},"end":{}}],"line":90},"15":{"loc":{"start":{"line":90,"column":6},"end":{"line":90,"column":50}},"type":"binary-expr","locations":[{"start":{"line":90,"column":6},"end":{"line":90,"column":28}},{"start":{"line":90,"column":28},"end":{"line":90,"column":50}}],"line":90},"16":{"loc":{"start":{"line":98,"column":2},"end":{"line":106,"column":null}},"type":"if","locations":[{"start":{"line":98,"column":2},"end":{"line":106,"column":null}},{"start":{},"end":{}}],"line":98},"17":{"loc":{"start":{"line":98,"column":2},"end":{"line":102,"column":null}},"type":"binary-expr","locations":[{"start":{"line":99,"column":5},"end":{"line":99,"column":null}},{"start":{"line":100,"column":6},"end":{"line":100,"column":null}},{"start":{"line":101,"column":6},"end":{"line":101,"column":null}},{"start":{"line":102,"column":4},"end":{"line":102,"column":null}}],"line":98},"18":{"loc":{"start":{"line":117,"column":2},"end":{"line":119,"column":null}},"type":"if","locations":[{"start":{"line":117,"column":2},"end":{"line":119,"column":null}},{"start":{},"end":{}}],"line":117},"19":{"loc":{"start":{"line":121,"column":2},"end":{"line":123,"column":null}},"type":"if","locations":[{"start":{"line":121,"column":2},"end":{"line":123,"column":null}},{"start":{},"end":{}}],"line":121},"20":{"loc":{"start":{"line":121,"column":6},"end":{"line":121,"column":50}},"type":"binary-expr","locations":[{"start":{"line":121,"column":6},"end":{"line":121,"column":29}},{"start":{"line":121,"column":29},"end":{"line":121,"column":50}}],"line":121},"21":{"loc":{"start":{"line":128,"column":2},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":2},"end":{"line":132,"column":null}},{"start":{},"end":{}}],"line":128},"22":{"loc":{"start":{"line":128,"column":6},"end":{"line":128,"column":45}},"type":"binary-expr","locations":[{"start":{"line":128,"column":6},"end":{"line":128,"column":26}},{"start":{"line":128,"column":26},"end":{"line":128,"column":45}}],"line":128},"23":{"loc":{"start":{"line":145,"column":2},"end":{"line":145,"column":null}},"type":"default-arg","locations":[{"start":{"line":145,"column":21},"end":{"line":145,"column":null}}],"line":145},"24":{"loc":{"start":{"line":147,"column":2},"end":{"line":149,"column":null}},"type":"if","locations":[{"start":{"line":147,"column":2},"end":{"line":149,"column":null}},{"start":{},"end":{}}],"line":147},"25":{"loc":{"start":{"line":147,"column":6},"end":{"line":147,"column":62}},"type":"binary-expr","locations":[{"start":{"line":147,"column":6},"end":{"line":147,"column":35}},{"start":{"line":147,"column":35},"end":{"line":147,"column":62}}],"line":147},"26":{"loc":{"start":{"line":151,"column":19},"end":{"line":151,"column":null}},"type":"cond-expr","locations":[{"start":{"line":151,"column":47},"end":{"line":151,"column":69}},{"start":{"line":151,"column":69},"end":{"line":151,"column":null}}],"line":151},"27":{"loc":{"start":{"line":153,"column":2},"end":{"line":157,"column":null}},"type":"if","locations":[{"start":{"line":153,"column":2},"end":{"line":157,"column":null}},{"start":{},"end":{}}],"line":153},"28":{"loc":{"start":{"line":153,"column":6},"end":{"line":153,"column":74}},"type":"binary-expr","locations":[{"start":{"line":153,"column":6},"end":{"line":153,"column":37}},{"start":{"line":153,"column":37},"end":{"line":153,"column":53}},{"start":{"line":153,"column":53},"end":{"line":153,"column":74}}],"line":153},"29":{"loc":{"start":{"line":172,"column":2},"end":{"line":174,"column":null}},"type":"if","locations":[{"start":{"line":172,"column":2},"end":{"line":174,"column":null}},{"start":{},"end":{}}],"line":172},"30":{"loc":{"start":{"line":176,"column":2},"end":{"line":180,"column":null}},"type":"if","locations":[{"start":{"line":176,"column":2},"end":{"line":180,"column":null}},{"start":{},"end":{}}],"line":176},"31":{"loc":{"start":{"line":210,"column":2},"end":{"line":210,"column":null}},"type":"default-arg","locations":[{"start":{"line":210,"column":29},"end":{"line":210,"column":null}}],"line":210},"32":{"loc":{"start":{"line":212,"column":2},"end":{"line":214,"column":null}},"type":"if","locations":[{"start":{"line":212,"column":2},"end":{"line":214,"column":null}},{"start":{},"end":{}}],"line":212},"33":{"loc":{"start":{"line":212,"column":6},"end":{"line":212,"column":37}},"type":"binary-expr","locations":[{"start":{"line":212,"column":6},"end":{"line":212,"column":13}},{"start":{"line":212,"column":13},"end":{"line":212,"column":37}}],"line":212},"34":{"loc":{"start":{"line":217,"column":2},"end":{"line":219,"column":null}},"type":"if","locations":[{"start":{"line":217,"column":2},"end":{"line":219,"column":null}},{"start":{},"end":{}}],"line":217},"35":{"loc":{"start":{"line":222,"column":2},"end":{"line":224,"column":null}},"type":"if","locations":[{"start":{"line":222,"column":2},"end":{"line":224,"column":null}},{"start":{},"end":{}}],"line":222},"36":{"loc":{"start":{"line":222,"column":6},"end":{"line":222,"column":44}},"type":"binary-expr","locations":[{"start":{"line":222,"column":6},"end":{"line":222,"column":20}},{"start":{"line":222,"column":20},"end":{"line":222,"column":44}}],"line":222},"37":{"loc":{"start":{"line":245,"column":15},"end":{"line":245,"column":null}},"type":"binary-expr","locations":[{"start":{"line":245,"column":15},"end":{"line":245,"column":27}},{"start":{"line":245,"column":27},"end":{"line":245,"column":null}}],"line":245},"38":{"loc":{"start":{"line":260,"column":2},"end":{"line":260,"column":null}},"type":"default-arg","locations":[{"start":{"line":260,"column":19},"end":{"line":260,"column":null}}],"line":260},"39":{"loc":{"start":{"line":261,"column":2},"end":{"line":261,"column":null}},"type":"default-arg","locations":[{"start":{"line":261,"column":19},"end":{"line":261,"column":null}}],"line":261}},"s":{"0":4,"1":1,"2":3,"3":1,"4":2,"5":1,"6":1,"7":3,"8":0,"9":3,"10":0,"11":3,"12":2,"13":1,"14":3,"15":1,"16":2,"17":1,"18":1,"19":3,"20":1,"21":2,"22":1,"23":1,"24":1,"25":1,"26":3,"27":1,"28":2,"29":0,"30":2,"31":2,"32":1,"33":1,"34":4,"35":0,"36":4,"37":4,"38":2,"39":2,"40":3,"41":1,"42":2,"43":1,"44":1,"45":1,"46":18,"47":1,"48":17,"49":17,"50":0,"51":17,"52":18,"53":1,"54":16,"55":2,"56":2,"57":5,"58":5},"f":{"0":4,"1":3,"2":3,"3":3,"4":3,"5":4,"6":3,"7":1,"8":18,"9":2,"10":5},"b":{"0":[1,3],"1":[1,2],"2":[3,2],"3":[1,1],"4":[0,3],"5":[0,3],"6":[3,3],"7":[2,1],"8":[3,2],"9":[3],"10":[1,2],"11":[1,1],"12":[2,2],"13":[1,2],"14":[1,1],"15":[2,1],"16":[0,1],"17":[1,1,1,0],"18":[1,2],"19":[0,2],"20":[2,2],"21":[1,1],"22":[2,2],"23":[4],"24":[0,4],"25":[4,3],"26":[3,1],"27":[2,2],"28":[4,3,2],"29":[1,2],"30":[1,1],"31":[18],"32":[1,17],"33":[18,17],"34":[0,17],"35":[1,17],"36":[18,16],"37":[2,0],"38":[5],"39":[5]},"meta":{"lastBranch":40,"lastFunction":11,"lastStatement":59,"seen":{"f:14:16:14:34":0,"b:15:2:17:Infinity:undefined:undefined:undefined:undefined":0,"s:15:2:17:Infinity":0,"s:16:4:16:Infinity":1,"b:19:2:21:Infinity:undefined:undefined:undefined:undefined":1,"s:19:2:21:Infinity":2,"b:19:6:19:32:19:32:19:56":2,"s:20:4:20:Infinity":3,"b:23:2:27:Infinity:undefined:undefined:undefined:undefined":3,"s:23:2:27:Infinity":4,"s:24:4:26:Infinity":5,"s:29:2:29:Infinity":6,"f:38:16:38:33":1,"b:39:2:41:Infinity:undefined:undefined:undefined:undefined":4,"s:39:2:41:Infinity":7,"s:40:4:40:Infinity":8,"b:43:2:45:Infinity:undefined:undefined:undefined:undefined":5,"s:43:2:45:Infinity":9,"b:43:6:43:31:43:31:43:55":6,"s:44:4:44:Infinity":10,"b:48:2:50:Infinity:undefined:undefined:undefined:undefined":7,"s:48:2:50:Infinity":11,"b:48:6:48:33:48:33:48:59":8,"s:49:4:49:Infinity":12,"s:52:2:52:Infinity":13,"f:62:16:62:Infinity":2,"b:64:22:64:Infinity":9,"b:66:2:68:Infinity:undefined:undefined:undefined:undefined":10,"s:66:2:68:Infinity":14,"s:67:4:67:Infinity":15,"b:70:2:74:Infinity:undefined:undefined:undefined:undefined":11,"s:70:2:74:Infinity":16,"b:70:6:70:28:70:28:70:54":12,"s:71:4:73:Infinity":17,"s:76:2:76:Infinity":18,"f:85:16:85:36":3,"b:86:2:88:Infinity:undefined:undefined:undefined:undefined":13,"s:86:2:88:Infinity":19,"s:87:4:87:Infinity":20,"b:90:2:94:Infinity:undefined:undefined:undefined:undefined":14,"s:90:2:94:Infinity":21,"b:90:6:90:28:90:28:90:50":15,"s:91:4:93:Infinity":22,"s:97:21:97:Infinity":23,"b:98:2:106:Infinity:undefined:undefined:undefined:undefined":16,"s:98:2:106:Infinity":24,"b:99:5:99:Infinity:100:6:100:Infinity:101:6:101:Infinity:102:4:102:Infinity":17,"s:108:2:108:Infinity":25,"f:116:16:116:31":4,"b:117:2:119:Infinity:undefined:undefined:undefined:undefined":18,"s:117:2:119:Infinity":26,"s:118:4:118:Infinity":27,"b:121:2:123:Infinity:undefined:undefined:undefined:undefined":19,"s:121:2:123:Infinity":28,"b:121:6:121:29:121:29:121:50":20,"s:122:4:122:Infinity":29,"s:127:16:127:Infinity":30,"b:128:2:132:Infinity:undefined:undefined:undefined:undefined":21,"s:128:2:132:Infinity":31,"b:128:6:128:26:128:26:128:45":22,"s:129:4:131:Infinity":32,"s:134:2:134:Infinity":33,"f:143:16:143:Infinity":5,"b:145:21:145:Infinity":23,"b:147:2:149:Infinity:undefined:undefined:undefined:undefined":24,"s:147:2:149:Infinity":34,"b:147:6:147:35:147:35:147:62":25,"s:148:4:148:Infinity":35,"s:151:19:151:Infinity":36,"b:151:47:151:69:151:69:151:Infinity":26,"b:153:2:157:Infinity:undefined:undefined:undefined:undefined":27,"s:153:2:157:Infinity":37,"b:153:6:153:37:153:37:153:53:153:53:153:74":28,"s:154:4:156:Infinity":38,"s:159:2:159:Infinity":39,"f:168:16:168:Infinity":6,"b:172:2:174:Infinity:undefined:undefined:undefined:undefined":29,"s:172:2:174:Infinity":40,"s:173:4:173:Infinity":41,"b:176:2:180:Infinity:undefined:undefined:undefined:undefined":30,"s:176:2:180:Infinity":42,"s:177:4:179:Infinity":43,"s:182:2:182:Infinity":44,"f:191:16:191:Infinity":7,"s:196:2:198:Infinity":45,"f:208:16:208:Infinity":8,"b:210:29:210:Infinity":31,"b:212:2:214:Infinity:undefined:undefined:undefined:undefined":32,"s:212:2:214:Infinity":46,"b:212:6:212:13:212:13:212:37":33,"s:213:4:213:Infinity":47,"s:216:16:216:Infinity":48,"b:217:2:219:Infinity:undefined:undefined:undefined:undefined":34,"s:217:2:219:Infinity":49,"s:218:4:218:Infinity":50,"s:221:20:221:Infinity":51,"b:222:2:224:Infinity:undefined:undefined:undefined:undefined":35,"s:222:2:224:Infinity":52,"b:222:6:222:20:222:20:222:44":36,"s:223:4:223:Infinity":53,"s:226:2:226:Infinity":54,"f:235:16:235:Infinity":9,"s:243:16:243:Infinity":55,"s:244:2:249:Infinity":56,"b:245:15:245:27:245:27:245:Infinity":37,"f:259:16:259:Infinity":10,"b:260:19:260:Infinity":38,"b:261:19:261:Infinity":39,"s:263:8:263:Infinity":57,"s:264:2:264:Infinity":58}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/vector/embedding-engine.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/vector/embedding-engine.ts","statementMap":{"0":{"start":{"line":36,"column":4},"end":{"line":36,"column":null}},"1":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"2":{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},"3":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"4":{"start":{"line":47,"column":24},"end":{"line":47,"column":null}},"5":{"start":{"line":48,"column":21},"end":{"line":48,"column":null}},"6":{"start":{"line":49,"column":20},"end":{"line":49,"column":null}},"7":{"start":{"line":52,"column":22},"end":{"line":52,"column":null}},"8":{"start":{"line":53,"column":4},"end":{"line":57,"column":null}},"9":{"start":{"line":54,"column":24},"end":{"line":54,"column":null}},"10":{"start":{"line":55,"column":6},"end":{"line":55,"column":null}},"11":{"start":{"line":56,"column":6},"end":{"line":56,"column":null}},"12":{"start":{"line":60,"column":20},"end":{"line":60,"column":null}},"13":{"start":{"line":61,"column":4},"end":{"line":65,"column":null}},"14":{"start":{"line":62,"column":24},"end":{"line":62,"column":null}},"15":{"start":{"line":63,"column":6},"end":{"line":63,"column":null}},"16":{"start":{"line":64,"column":6},"end":{"line":64,"column":null}},"17":{"start":{"line":68,"column":18},"end":{"line":68,"column":null}},"18":{"start":{"line":69,"column":4},"end":{"line":73,"column":null}},"19":{"start":{"line":70,"column":24},"end":{"line":70,"column":null}},"20":{"start":{"line":71,"column":6},"end":{"line":71,"column":null}},"21":{"start":{"line":72,"column":6},"end":{"line":72,"column":null}},"22":{"start":{"line":75,"column":4},"end":{"line":75,"column":null}},"23":{"start":{"line":76,"column":4},"end":{"line":76,"column":null}},"24":{"start":{"line":77,"column":4},"end":{"line":77,"column":null}},"25":{"start":{"line":78,"column":4},"end":{"line":78,"column":null}},"26":{"start":{"line":80,"column":4},"end":{"line":80,"column":null}},"27":{"start":{"line":94,"column":17},"end":{"line":94,"column":null}},"28":{"start":{"line":95,"column":19},"end":{"line":95,"column":null}},"29":{"start":{"line":98,"column":10},"end":{"line":98,"column":null}},"30":{"start":{"line":100,"column":4},"end":{"line":113,"column":null}},"31":{"start":{"line":120,"column":28},"end":{"line":120,"column":null}},"32":{"start":{"line":122,"column":4},"end":{"line":122,"column":null}},"33":{"start":{"line":122,"column":20},"end":{"line":122,"column":null}},"34":{"start":{"line":123,"column":4},"end":{"line":123,"column":null}},"35":{"start":{"line":123,"column":27},"end":{"line":123,"column":null}},"36":{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},"37":{"start":{"line":124,"column":20},"end":{"line":124,"column":null}},"38":{"start":{"line":125,"column":4},"end":{"line":125,"column":null}},"39":{"start":{"line":125,"column":26},"end":{"line":125,"column":null}},"40":{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},"41":{"start":{"line":126,"column":23},"end":{"line":126,"column":null}},"42":{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},"43":{"start":{"line":127,"column":26},"end":{"line":127,"column":null}},"44":{"start":{"line":128,"column":4},"end":{"line":128,"column":null}},"45":{"start":{"line":128,"column":20},"end":{"line":128,"column":null}},"46":{"start":{"line":130,"column":4},"end":{"line":130,"column":null}},"47":{"start":{"line":138,"column":29},"end":{"line":138,"column":null}},"48":{"start":{"line":141,"column":4},"end":{"line":145,"column":null}},"49":{"start":{"line":141,"column":17},"end":{"line":141,"column":20}},"50":{"start":{"line":142,"column":23},"end":{"line":142,"column":null}},"51":{"start":{"line":143,"column":12},"end":{"line":143,"column":null}},"52":{"start":{"line":144,"column":6},"end":{"line":144,"column":null}},"53":{"start":{"line":148,"column":22},"end":{"line":148,"column":null}},"54":{"start":{"line":148,"column":58},"end":{"line":148,"column":71}},"55":{"start":{"line":149,"column":4},"end":{"line":149,"column":null}},"56":{"start":{"line":149,"column":45},"end":{"line":149,"column":58}},"57":{"start":{"line":156,"column":4},"end":{"line":159,"column":null}},"58":{"start":{"line":157,"column":6},"end":{"line":157,"column":null}},"59":{"start":{"line":158,"column":6},"end":{"line":158,"column":null}},"60":{"start":{"line":162,"column":4},"end":{"line":162,"column":null}},"61":{"start":{"line":163,"column":4},"end":{"line":163,"column":null}},"62":{"start":{"line":164,"column":4},"end":{"line":164,"column":null}},"63":{"start":{"line":167,"column":46},"end":{"line":167,"column":null}},"64":{"start":{"line":168,"column":43},"end":{"line":168,"column":null}},"65":{"start":{"line":169,"column":42},"end":{"line":169,"column":null}},"66":{"start":{"line":171,"column":4},"end":{"line":186,"column":null}},"67":{"start":{"line":172,"column":33},"end":{"line":181,"column":null}},"68":{"start":{"line":183,"column":6},"end":{"line":185,"column":null}},"69":{"start":{"line":183,"column":41},"end":{"line":183,"column":null}},"70":{"start":{"line":183,"column":70},"end":{"line":185,"column":null}},"71":{"start":{"line":184,"column":43},"end":{"line":184,"column":null}},"72":{"start":{"line":184,"column":69},"end":{"line":185,"column":null}},"73":{"start":{"line":185,"column":42},"end":{"line":185,"column":null}},"74":{"start":{"line":189,"column":4},"end":{"line":191,"column":null}},"75":{"start":{"line":190,"column":6},"end":{"line":190,"column":null}},"76":{"start":{"line":192,"column":4},"end":{"line":194,"column":null}},"77":{"start":{"line":193,"column":6},"end":{"line":193,"column":null}},"78":{"start":{"line":195,"column":4},"end":{"line":197,"column":null}},"79":{"start":{"line":196,"column":6},"end":{"line":196,"column":null}},"80":{"start":{"line":199,"column":4},"end":{"line":199,"column":null}},"81":{"start":{"line":215,"column":24},"end":{"line":215,"column":null}},"82":{"start":{"line":217,"column":4},"end":{"line":230,"column":null}},"83":{"start":{"line":218,"column":22},"end":{"line":218,"column":null}},"84":{"start":{"line":219,"column":6},"end":{"line":229,"column":null}},"85":{"start":{"line":221,"column":28},"end":{"line":221,"column":null}},"86":{"start":{"line":222,"column":10},"end":{"line":222,"column":null}},"87":{"start":{"line":225,"column":10},"end":{"line":225,"column":null}},"88":{"start":{"line":225,"column":18},"end":{"line":225,"column":null}},"89":{"start":{"line":226,"column":10},"end":{"line":226,"column":null}},"90":{"start":{"line":226,"column":54},"end":{"line":226,"column":null}},"91":{"start":{"line":227,"column":10},"end":{"line":227,"column":null}},"92":{"start":{"line":232,"column":23},"end":{"line":236,"column":null}},"93":{"start":{"line":233,"column":6},"end":{"line":233,"column":null}},"94":{"start":{"line":233,"column":31},"end":{"line":233,"column":null}},"95":{"start":{"line":234,"column":6},"end":{"line":234,"column":null}},"96":{"start":{"line":234,"column":54},"end":{"line":234,"column":null}},"97":{"start":{"line":235,"column":6},"end":{"line":235,"column":null}},"98":{"start":{"line":238,"column":4},"end":{"line":245,"column":null}},"99":{"start":{"line":239,"column":27},"end":{"line":242,"column":8}},"100":{"start":{"line":243,"column":22},"end":{"line":243,"column":39}},"101":{"start":{"line":245,"column":20},"end":{"line":245,"column":33}},"102":{"start":{"line":249,"column":14},"end":{"line":249,"column":null}},"103":{"start":{"line":250,"column":24},"end":{"line":250,"column":null}},"104":{"start":{"line":251,"column":25},"end":{"line":251,"column":null}},"105":{"start":{"line":253,"column":17},"end":{"line":253,"column":null}},"106":{"start":{"line":254,"column":4},"end":{"line":258,"column":null}},"107":{"start":{"line":254,"column":17},"end":{"line":254,"column":20}},"108":{"start":{"line":255,"column":6},"end":{"line":255,"column":null}},"109":{"start":{"line":256,"column":6},"end":{"line":256,"column":null}},"110":{"start":{"line":257,"column":6},"end":{"line":257,"column":null}},"111":{"start":{"line":260,"column":4},"end":{"line":262,"column":null}},"112":{"start":{"line":261,"column":6},"end":{"line":261,"column":null}},"113":{"start":{"line":264,"column":4},"end":{"line":264,"column":null}},"114":{"start":{"line":271,"column":4},"end":{"line":271,"column":null}},"115":{"start":{"line":278,"column":17},"end":{"line":286,"column":null}},"116":{"start":{"line":278,"column":66},"end":{"line":286,"column":6}},"117":{"start":{"line":288,"column":4},"end":{"line":288,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":35,"column":2},"end":{"line":35,"column":14}},"loc":{"start":{"line":35,"column":62},"end":{"line":39,"column":null}},"line":35},"1":{"name":"(anonymous_1)","decl":{"start":{"line":44,"column":8},"end":{"line":44,"column":96}},"loc":{"start":{"line":44,"column":96},"end":{"line":81,"column":null}},"line":44},"2":{"name":"(anonymous_2)","decl":{"start":{"line":86,"column":10},"end":{"line":86,"column":null}},"loc":{"start":{"line":90,"column":19},"end":{"line":114,"column":null}},"line":90},"3":{"name":"(anonymous_3)","decl":{"start":{"line":119,"column":10},"end":{"line":119,"column":27}},"loc":{"start":{"line":119,"column":63},"end":{"line":131,"column":null}},"line":119},"4":{"name":"(anonymous_4)","decl":{"start":{"line":137,"column":10},"end":{"line":137,"column":23}},"loc":{"start":{"line":137,"column":58},"end":{"line":150,"column":null}},"line":137},"5":{"name":"(anonymous_5)","decl":{"start":{"line":148,"column":46},"end":{"line":148,"column":47}},"loc":{"start":{"line":148,"column":58},"end":{"line":148,"column":71}},"line":148},"6":{"name":"(anonymous_6)","decl":{"start":{"line":149,"column":38},"end":{"line":149,"column":39}},"loc":{"start":{"line":149,"column":45},"end":{"line":149,"column":58}},"line":149},"7":{"name":"(anonymous_7)","decl":{"start":{"line":155,"column":8},"end":{"line":155,"column":39}},"loc":{"start":{"line":155,"column":39},"end":{"line":200,"column":null}},"line":155},"8":{"name":"(anonymous_8)","decl":{"start":{"line":209,"column":8},"end":{"line":209,"column":null}},"loc":{"start":{"line":214,"column":30},"end":{"line":246,"column":null}},"line":214},"9":{"name":"(anonymous_9)","decl":{"start":{"line":220,"column":13},"end":{"line":220,"column":14}},"loc":{"start":{"line":220,"column":25},"end":{"line":223,"column":9}},"line":220},"10":{"name":"(anonymous_10)","decl":{"start":{"line":224,"column":16},"end":{"line":224,"column":17}},"loc":{"start":{"line":224,"column":23},"end":{"line":228,"column":9}},"line":224},"11":{"name":"(anonymous_11)","decl":{"start":{"line":232,"column":67},"end":{"line":232,"column":68}},"loc":{"start":{"line":232,"column":78},"end":{"line":236,"column":5}},"line":232},"12":{"name":"(anonymous_12)","decl":{"start":{"line":239,"column":11},"end":{"line":239,"column":12}},"loc":{"start":{"line":239,"column":27},"end":{"line":242,"column":8}},"line":239},"13":{"name":"(anonymous_13)","decl":{"start":{"line":243,"column":12},"end":{"line":243,"column":13}},"loc":{"start":{"line":243,"column":22},"end":{"line":243,"column":39}},"line":243},"14":{"name":"(anonymous_14)","decl":{"start":{"line":245,"column":11},"end":{"line":245,"column":12}},"loc":{"start":{"line":245,"column":20},"end":{"line":245,"column":33}},"line":245},"15":{"name":"(anonymous_15)","decl":{"start":{"line":248,"column":10},"end":{"line":248,"column":27}},"loc":{"start":{"line":248,"column":68},"end":{"line":265,"column":null}},"line":248},"16":{"name":"(anonymous_16)","decl":{"start":{"line":270,"column":2},"end":{"line":270,"column":38}},"loc":{"start":{"line":270,"column":38},"end":{"line":272,"column":null}},"line":270},"17":{"name":"(anonymous_17)","decl":{"start":{"line":277,"column":2},"end":{"line":277,"column":19}},"loc":{"start":{"line":277,"column":19},"end":{"line":289,"column":null}},"line":277},"18":{"name":"(anonymous_18)","decl":{"start":{"line":278,"column":58},"end":{"line":278,"column":59}},"loc":{"start":{"line":278,"column":66},"end":{"line":286,"column":6}},"line":278}},"branchMap":{"0":{"loc":{"start":{"line":103,"column":12},"end":{"line":103,"column":null}},"type":"binary-expr","locations":[{"start":{"line":103,"column":12},"end":{"line":103,"column":31}},{"start":{"line":103,"column":31},"end":{"line":103,"column":50}},{"start":{"line":103,"column":50},"end":{"line":103,"column":null}}],"line":103},"1":{"loc":{"start":{"line":122,"column":4},"end":{"line":122,"column":null}},"type":"if","locations":[{"start":{"line":122,"column":4},"end":{"line":122,"column":null}},{"start":{},"end":{}}],"line":122},"2":{"loc":{"start":{"line":123,"column":4},"end":{"line":123,"column":null}},"type":"if","locations":[{"start":{"line":123,"column":4},"end":{"line":123,"column":null}},{"start":{},"end":{}}],"line":123},"3":{"loc":{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},"type":"if","locations":[{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},{"start":{},"end":{}}],"line":124},"4":{"loc":{"start":{"line":125,"column":4},"end":{"line":125,"column":null}},"type":"if","locations":[{"start":{"line":125,"column":4},"end":{"line":125,"column":null}},{"start":{},"end":{}}],"line":125},"5":{"loc":{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},"type":"if","locations":[{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},{"start":{},"end":{}}],"line":126},"6":{"loc":{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},"type":"if","locations":[{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},{"start":{},"end":{}}],"line":127},"7":{"loc":{"start":{"line":128,"column":4},"end":{"line":128,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":4},"end":{"line":128,"column":null}},{"start":{},"end":{}}],"line":128},"8":{"loc":{"start":{"line":137,"column":37},"end":{"line":137,"column":58}},"type":"default-arg","locations":[{"start":{"line":137,"column":43},"end":{"line":137,"column":58}}],"line":137},"9":{"loc":{"start":{"line":149,"column":11},"end":{"line":149,"column":null}},"type":"cond-expr","locations":[{"start":{"line":149,"column":27},"end":{"line":149,"column":62}},{"start":{"line":149,"column":62},"end":{"line":149,"column":null}}],"line":149},"10":{"loc":{"start":{"line":156,"column":4},"end":{"line":159,"column":null}},"type":"if","locations":[{"start":{"line":156,"column":4},"end":{"line":159,"column":null}},{"start":{},"end":{}}],"line":156},"11":{"loc":{"start":{"line":183,"column":6},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":183,"column":6},"end":{"line":185,"column":null}},{"start":{"line":183,"column":70},"end":{"line":185,"column":null}}],"line":183},"12":{"loc":{"start":{"line":183,"column":70},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":183,"column":70},"end":{"line":185,"column":null}},{"start":{"line":184,"column":69},"end":{"line":185,"column":null}}],"line":183},"13":{"loc":{"start":{"line":184,"column":69},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":184,"column":69},"end":{"line":185,"column":null}},{"start":{},"end":{}}],"line":184},"14":{"loc":{"start":{"line":189,"column":4},"end":{"line":191,"column":null}},"type":"if","locations":[{"start":{"line":189,"column":4},"end":{"line":191,"column":null}},{"start":{},"end":{}}],"line":189},"15":{"loc":{"start":{"line":192,"column":4},"end":{"line":194,"column":null}},"type":"if","locations":[{"start":{"line":192,"column":4},"end":{"line":194,"column":null}},{"start":{},"end":{}}],"line":192},"16":{"loc":{"start":{"line":195,"column":4},"end":{"line":197,"column":null}},"type":"if","locations":[{"start":{"line":195,"column":4},"end":{"line":197,"column":null}},{"start":{},"end":{}}],"line":195},"17":{"loc":{"start":{"line":211,"column":4},"end":{"line":211,"column":null}},"type":"default-arg","locations":[{"start":{"line":211,"column":42},"end":{"line":211,"column":null}}],"line":211},"18":{"loc":{"start":{"line":212,"column":4},"end":{"line":212,"column":null}},"type":"default-arg","locations":[{"start":{"line":212,"column":12},"end":{"line":212,"column":null}}],"line":212},"19":{"loc":{"start":{"line":217,"column":4},"end":{"line":230,"column":null}},"type":"if","locations":[{"start":{"line":217,"column":4},"end":{"line":230,"column":null}},{"start":{},"end":{}}],"line":217},"20":{"loc":{"start":{"line":225,"column":10},"end":{"line":225,"column":null}},"type":"if","locations":[{"start":{"line":225,"column":10},"end":{"line":225,"column":null}},{"start":{},"end":{}}],"line":225},"21":{"loc":{"start":{"line":226,"column":10},"end":{"line":226,"column":null}},"type":"if","locations":[{"start":{"line":226,"column":10},"end":{"line":226,"column":null}},{"start":{},"end":{}}],"line":226},"22":{"loc":{"start":{"line":226,"column":14},"end":{"line":226,"column":54}},"type":"binary-expr","locations":[{"start":{"line":226,"column":14},"end":{"line":226,"column":27}},{"start":{"line":226,"column":27},"end":{"line":226,"column":54}}],"line":226},"23":{"loc":{"start":{"line":233,"column":6},"end":{"line":233,"column":null}},"type":"if","locations":[{"start":{"line":233,"column":6},"end":{"line":233,"column":null}},{"start":{},"end":{}}],"line":233},"24":{"loc":{"start":{"line":234,"column":6},"end":{"line":234,"column":null}},"type":"if","locations":[{"start":{"line":234,"column":6},"end":{"line":234,"column":null}},{"start":{},"end":{}}],"line":234},"25":{"loc":{"start":{"line":234,"column":10},"end":{"line":234,"column":54}},"type":"binary-expr","locations":[{"start":{"line":234,"column":10},"end":{"line":234,"column":23}},{"start":{"line":234,"column":23},"end":{"line":234,"column":54}}],"line":234},"26":{"loc":{"start":{"line":260,"column":4},"end":{"line":262,"column":null}},"type":"if","locations":[{"start":{"line":260,"column":4},"end":{"line":262,"column":null}},{"start":{},"end":{}}],"line":260},"27":{"loc":{"start":{"line":260,"column":8},"end":{"line":260,"column":53}},"type":"binary-expr","locations":[{"start":{"line":260,"column":8},"end":{"line":260,"column":31}},{"start":{"line":260,"column":31},"end":{"line":260,"column":53}}],"line":260}},"s":{"0":62,"1":62,"2":62,"3":6,"4":6,"5":6,"6":6,"7":6,"8":6,"9":5,"10":5,"11":5,"12":6,"13":6,"14":5,"15":5,"16":5,"17":6,"18":6,"19":5,"20":5,"21":5,"22":6,"23":6,"24":6,"25":6,"26":6,"27":15,"28":15,"29":15,"30":15,"31":15,"32":15,"33":10,"34":15,"35":10,"36":15,"37":5,"38":15,"39":5,"40":15,"41":5,"42":15,"43":0,"44":15,"45":15,"46":15,"47":17,"48":17,"49":17,"50":745,"51":745,"52":745,"53":17,"54":2176,"55":17,"56":2176,"57":2,"58":1,"59":1,"60":1,"61":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":3,"68":3,"69":1,"70":2,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":2,"82":2,"83":1,"84":1,"85":2,"86":2,"87":2,"88":1,"89":1,"90":0,"91":1,"92":1,"93":3,"94":2,"95":1,"96":0,"97":1,"98":1,"99":1,"100":0,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":128,"109":128,"110":128,"111":1,"112":0,"113":1,"114":4,"115":0,"116":0,"117":0},"f":{"0":62,"1":6,"2":15,"3":15,"4":17,"5":2176,"6":2176,"7":2,"8":2,"9":2,"10":2,"11":3,"12":1,"13":0,"14":1,"15":1,"16":4,"17":0,"18":0},"b":{"0":[15,5,0],"1":[10,5],"2":[10,5],"3":[5,10],"4":[5,10],"5":[5,10],"6":[0,15],"7":[15,0],"8":[17],"9":[17,0],"10":[1,1],"11":[1,2],"12":[1,1],"13":[1,0],"14":[1,0],"15":[1,0],"16":[1,0],"17":[2],"18":[2],"19":[1,1],"20":[1,1],"21":[0,1],"22":[1,1],"23":[2,1],"24":[0,1],"25":[1,1],"26":[0,1],"27":[1,1]},"meta":{"lastBranch":28,"lastFunction":19,"lastStatement":118,"seen":{"f:35:2:35:14":0,"s:36:4:36:Infinity":0,"s:37:4:37:Infinity":1,"s:38:4:38:Infinity":2,"f:44:8:44:96":1,"s:45:4:45:Infinity":3,"s:47:24:47:Infinity":4,"s:48:21:48:Infinity":5,"s:49:20:49:Infinity":6,"s:52:22:52:Infinity":7,"s:53:4:57:Infinity":8,"s:54:24:54:Infinity":9,"s:55:6:55:Infinity":10,"s:56:6:56:Infinity":11,"s:60:20:60:Infinity":12,"s:61:4:65:Infinity":13,"s:62:24:62:Infinity":14,"s:63:6:63:Infinity":15,"s:64:6:64:Infinity":16,"s:68:18:68:Infinity":17,"s:69:4:73:Infinity":18,"s:70:24:70:Infinity":19,"s:71:6:71:Infinity":20,"s:72:6:72:Infinity":21,"s:75:4:75:Infinity":22,"s:76:4:76:Infinity":23,"s:77:4:77:Infinity":24,"s:78:4:78:Infinity":25,"s:80:4:80:Infinity":26,"f:86:10:86:Infinity":2,"s:94:17:94:Infinity":27,"s:95:19:95:Infinity":28,"s:98:10:98:Infinity":29,"s:100:4:113:Infinity":30,"b:103:12:103:31:103:31:103:50:103:50:103:Infinity":0,"f:119:10:119:27":3,"s:120:28:120:Infinity":31,"b:122:4:122:Infinity:undefined:undefined:undefined:undefined":1,"s:122:4:122:Infinity":32,"s:122:20:122:Infinity":33,"b:123:4:123:Infinity:undefined:undefined:undefined:undefined":2,"s:123:4:123:Infinity":34,"s:123:27:123:Infinity":35,"b:124:4:124:Infinity:undefined:undefined:undefined:undefined":3,"s:124:4:124:Infinity":36,"s:124:20:124:Infinity":37,"b:125:4:125:Infinity:undefined:undefined:undefined:undefined":4,"s:125:4:125:Infinity":38,"s:125:26:125:Infinity":39,"b:126:4:126:Infinity:undefined:undefined:undefined:undefined":5,"s:126:4:126:Infinity":40,"s:126:23:126:Infinity":41,"b:127:4:127:Infinity:undefined:undefined:undefined:undefined":6,"s:127:4:127:Infinity":42,"s:127:26:127:Infinity":43,"b:128:4:128:Infinity:undefined:undefined:undefined:undefined":7,"s:128:4:128:Infinity":44,"s:128:20:128:Infinity":45,"s:130:4:130:Infinity":46,"f:137:10:137:23":4,"b:137:43:137:58":8,"s:138:29:138:Infinity":47,"s:141:4:145:Infinity":48,"s:141:17:141:20":49,"s:142:23:142:Infinity":50,"s:143:12:143:Infinity":51,"s:144:6:144:Infinity":52,"s:148:22:148:Infinity":53,"f:148:46:148:47":5,"s:148:58:148:71":54,"s:149:4:149:Infinity":55,"b:149:27:149:62:149:62:149:Infinity":9,"f:149:38:149:39":6,"s:149:45:149:58":56,"f:155:8:155:39":7,"b:156:4:159:Infinity:undefined:undefined:undefined:undefined":10,"s:156:4:159:Infinity":57,"s:157:6:157:Infinity":58,"s:158:6:158:Infinity":59,"s:162:4:162:Infinity":60,"s:163:4:163:Infinity":61,"s:164:4:164:Infinity":62,"s:167:46:167:Infinity":63,"s:168:43:168:Infinity":64,"s:169:42:169:Infinity":65,"s:171:4:186:Infinity":66,"s:172:33:181:Infinity":67,"b:183:6:185:Infinity:183:70:185:Infinity":11,"s:183:6:185:Infinity":68,"s:183:41:183:Infinity":69,"b:183:70:185:Infinity:184:69:185:Infinity":12,"s:183:70:185:Infinity":70,"s:184:43:184:Infinity":71,"b:184:69:185:Infinity:undefined:undefined:undefined:undefined":13,"s:184:69:185:Infinity":72,"s:185:42:185:Infinity":73,"b:189:4:191:Infinity:undefined:undefined:undefined:undefined":14,"s:189:4:191:Infinity":74,"s:190:6:190:Infinity":75,"b:192:4:194:Infinity:undefined:undefined:undefined:undefined":15,"s:192:4:194:Infinity":76,"s:193:6:193:Infinity":77,"b:195:4:197:Infinity:undefined:undefined:undefined:undefined":16,"s:195:4:197:Infinity":78,"s:196:6:196:Infinity":79,"s:199:4:199:Infinity":80,"f:209:8:209:Infinity":8,"b:211:42:211:Infinity":17,"b:212:12:212:Infinity":18,"s:215:24:215:Infinity":81,"b:217:4:230:Infinity:undefined:undefined:undefined:undefined":19,"s:217:4:230:Infinity":82,"s:218:22:218:Infinity":83,"s:219:6:229:Infinity":84,"f:220:13:220:14":9,"s:221:28:221:Infinity":85,"s:222:10:222:Infinity":86,"f:224:16:224:17":10,"b:225:10:225:Infinity:undefined:undefined:undefined:undefined":20,"s:225:10:225:Infinity":87,"s:225:18:225:Infinity":88,"b:226:10:226:Infinity:undefined:undefined:undefined:undefined":21,"s:226:10:226:Infinity":89,"b:226:14:226:27:226:27:226:54":22,"s:226:54:226:Infinity":90,"s:227:10:227:Infinity":91,"s:232:23:236:Infinity":92,"f:232:67:232:68":11,"b:233:6:233:Infinity:undefined:undefined:undefined:undefined":23,"s:233:6:233:Infinity":93,"s:233:31:233:Infinity":94,"b:234:6:234:Infinity:undefined:undefined:undefined:undefined":24,"s:234:6:234:Infinity":95,"b:234:10:234:23:234:23:234:54":25,"s:234:54:234:Infinity":96,"s:235:6:235:Infinity":97,"s:238:4:245:Infinity":98,"f:239:11:239:12":12,"s:239:27:242:8":99,"f:243:12:243:13":13,"s:243:22:243:39":100,"f:245:11:245:12":14,"s:245:20:245:33":101,"f:248:10:248:27":15,"s:249:14:249:Infinity":102,"s:250:24:250:Infinity":103,"s:251:25:251:Infinity":104,"s:253:17:253:Infinity":105,"s:254:4:258:Infinity":106,"s:254:17:254:20":107,"s:255:6:255:Infinity":108,"s:256:6:256:Infinity":109,"s:257:6:257:Infinity":110,"b:260:4:262:Infinity:undefined:undefined:undefined:undefined":26,"s:260:4:262:Infinity":111,"b:260:8:260:31:260:31:260:53":27,"s:261:6:261:Infinity":112,"s:264:4:264:Infinity":113,"f:270:2:270:38":16,"s:271:4:271:Infinity":114,"f:277:2:277:19":17,"s:278:17:286:Infinity":115,"f:278:58:278:59":18,"s:278:66:286:6":116,"s:288:4:288:Infinity":117}}} -,"/home/alex_rod/projects/lexRAG-MCP/src/vector/qdrant-client.ts": {"path":"/home/alex_rod/projects/lexRAG-MCP/src/vector/qdrant-client.ts","statementMap":{"0":{"start":{"line":29,"column":22},"end":{"line":29,"column":null}},"1":{"start":{"line":32,"column":4},"end":{"line":32,"column":null}},"2":{"start":{"line":39,"column":4},"end":{"line":52,"column":null}},"3":{"start":{"line":41,"column":23},"end":{"line":41,"column":null}},"4":{"start":{"line":42,"column":6},"end":{"line":45,"column":null}},"5":{"start":{"line":43,"column":8},"end":{"line":43,"column":null}},"6":{"start":{"line":44,"column":8},"end":{"line":44,"column":null}},"7":{"start":{"line":47,"column":6},"end":{"line":50,"column":null}},"8":{"start":{"line":51,"column":6},"end":{"line":51,"column":null}},"9":{"start":{"line":59,"column":4},"end":{"line":62,"column":null}},"10":{"start":{"line":60,"column":6},"end":{"line":60,"column":null}},"11":{"start":{"line":61,"column":6},"end":{"line":61,"column":null}},"12":{"start":{"line":64,"column":4},"end":{"line":81,"column":null}},"13":{"start":{"line":65,"column":23},"end":{"line":74,"column":null}},"14":{"start":{"line":76,"column":6},"end":{"line":78,"column":null}},"15":{"start":{"line":77,"column":8},"end":{"line":77,"column":null}},"16":{"start":{"line":80,"column":6},"end":{"line":80,"column":null}},"17":{"start":{"line":91,"column":4},"end":{"line":94,"column":null}},"18":{"start":{"line":92,"column":6},"end":{"line":92,"column":null}},"19":{"start":{"line":93,"column":6},"end":{"line":93,"column":null}},"20":{"start":{"line":96,"column":4},"end":{"line":119,"column":null}},"21":{"start":{"line":97,"column":23},"end":{"line":110,"column":null}},"22":{"start":{"line":103,"column":39},"end":{"line":107,"column":14}},"23":{"start":{"line":112,"column":6},"end":{"line":116,"column":null}},"24":{"start":{"line":113,"column":8},"end":{"line":115,"column":null}},"25":{"start":{"line":118,"column":6},"end":{"line":118,"column":null}},"26":{"start":{"line":130,"column":4},"end":{"line":133,"column":null}},"27":{"start":{"line":131,"column":6},"end":{"line":131,"column":null}},"28":{"start":{"line":132,"column":6},"end":{"line":132,"column":null}},"29":{"start":{"line":135,"column":4},"end":{"line":163,"column":null}},"30":{"start":{"line":136,"column":23},"end":{"line":147,"column":null}},"31":{"start":{"line":149,"column":6},"end":{"line":158,"column":null}},"32":{"start":{"line":150,"column":22},"end":{"line":150,"column":null}},"33":{"start":{"line":151,"column":8},"end":{"line":156,"column":null}},"34":{"start":{"line":152,"column":43},"end":{"line":156,"column":12}},"35":{"start":{"line":159,"column":6},"end":{"line":159,"column":null}},"36":{"start":{"line":161,"column":6},"end":{"line":161,"column":null}},"37":{"start":{"line":162,"column":6},"end":{"line":162,"column":null}},"38":{"start":{"line":170,"column":4},"end":{"line":170,"column":null}},"39":{"start":{"line":170,"column":25},"end":{"line":170,"column":null}},"40":{"start":{"line":172,"column":4},"end":{"line":177,"column":null}},"41":{"start":{"line":173,"column":6},"end":{"line":173,"column":null}},"42":{"start":{"line":174,"column":6},"end":{"line":174,"column":null}},"43":{"start":{"line":176,"column":6},"end":{"line":176,"column":null}},"44":{"start":{"line":184,"column":4},"end":{"line":184,"column":null}},"45":{"start":{"line":184,"column":25},"end":{"line":184,"column":null}},"46":{"start":{"line":186,"column":4},"end":{"line":198,"column":null}},"47":{"start":{"line":187,"column":23},"end":{"line":187,"column":null}},"48":{"start":{"line":188,"column":6},"end":{"line":195,"column":null}},"49":{"start":{"line":189,"column":22},"end":{"line":189,"column":null}},"50":{"start":{"line":190,"column":8},"end":{"line":194,"column":null}},"51":{"start":{"line":197,"column":6},"end":{"line":197,"column":null}},"52":{"start":{"line":199,"column":4},"end":{"line":199,"column":null}},"53":{"start":{"line":206,"column":4},"end":{"line":206,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":31,"column":2},"end":{"line":31,"column":14}},"loc":{"start":{"line":31,"column":47},"end":{"line":33,"column":null}},"line":31},"1":{"name":"(anonymous_1)","decl":{"start":{"line":38,"column":8},"end":{"line":38,"column":33}},"loc":{"start":{"line":38,"column":33},"end":{"line":53,"column":null}},"line":38},"2":{"name":"(anonymous_2)","decl":{"start":{"line":58,"column":8},"end":{"line":58,"column":25}},"loc":{"start":{"line":58,"column":74},"end":{"line":82,"column":null}},"line":58},"3":{"name":"(anonymous_3)","decl":{"start":{"line":87,"column":8},"end":{"line":87,"column":null}},"loc":{"start":{"line":90,"column":19},"end":{"line":120,"column":null}},"line":90},"4":{"name":"(anonymous_4)","decl":{"start":{"line":103,"column":31},"end":{"line":103,"column":32}},"loc":{"start":{"line":103,"column":39},"end":{"line":107,"column":14}},"line":103},"5":{"name":"(anonymous_5)","decl":{"start":{"line":125,"column":8},"end":{"line":125,"column":null}},"loc":{"start":{"line":129,"column":29},"end":{"line":164,"column":null}},"line":129},"6":{"name":"(anonymous_6)","decl":{"start":{"line":152,"column":27},"end":{"line":152,"column":28}},"loc":{"start":{"line":152,"column":43},"end":{"line":156,"column":12}},"line":152},"7":{"name":"(anonymous_7)","decl":{"start":{"line":169,"column":8},"end":{"line":169,"column":25}},"loc":{"start":{"line":169,"column":54},"end":{"line":178,"column":null}},"line":169},"8":{"name":"(anonymous_8)","decl":{"start":{"line":183,"column":8},"end":{"line":183,"column":22}},"loc":{"start":{"line":183,"column":64},"end":{"line":200,"column":null}},"line":183},"9":{"name":"(anonymous_9)","decl":{"start":{"line":205,"column":2},"end":{"line":205,"column":25}},"loc":{"start":{"line":205,"column":25},"end":{"line":207,"column":null}},"line":205}},"branchMap":{"0":{"loc":{"start":{"line":31,"column":14},"end":{"line":31,"column":34}},"type":"default-arg","locations":[{"start":{"line":31,"column":21},"end":{"line":31,"column":34}}],"line":31},"1":{"loc":{"start":{"line":31,"column":34},"end":{"line":31,"column":47}},"type":"default-arg","locations":[{"start":{"line":31,"column":41},"end":{"line":31,"column":47}}],"line":31},"2":{"loc":{"start":{"line":42,"column":6},"end":{"line":45,"column":null}},"type":"if","locations":[{"start":{"line":42,"column":6},"end":{"line":45,"column":null}},{"start":{},"end":{}}],"line":42},"3":{"loc":{"start":{"line":59,"column":4},"end":{"line":62,"column":null}},"type":"if","locations":[{"start":{"line":59,"column":4},"end":{"line":62,"column":null}},{"start":{},"end":{}}],"line":59},"4":{"loc":{"start":{"line":76,"column":6},"end":{"line":78,"column":null}},"type":"if","locations":[{"start":{"line":76,"column":6},"end":{"line":78,"column":null}},{"start":{},"end":{}}],"line":76},"5":{"loc":{"start":{"line":91,"column":4},"end":{"line":94,"column":null}},"type":"if","locations":[{"start":{"line":91,"column":4},"end":{"line":94,"column":null}},{"start":{},"end":{}}],"line":91},"6":{"loc":{"start":{"line":112,"column":6},"end":{"line":116,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":6},"end":{"line":116,"column":null}},{"start":{},"end":{}}],"line":112},"7":{"loc":{"start":{"line":128,"column":4},"end":{"line":128,"column":null}},"type":"default-arg","locations":[{"start":{"line":128,"column":12},"end":{"line":128,"column":null}}],"line":128},"8":{"loc":{"start":{"line":130,"column":4},"end":{"line":133,"column":null}},"type":"if","locations":[{"start":{"line":130,"column":4},"end":{"line":133,"column":null}},{"start":{},"end":{}}],"line":130},"9":{"loc":{"start":{"line":149,"column":6},"end":{"line":158,"column":null}},"type":"if","locations":[{"start":{"line":149,"column":6},"end":{"line":158,"column":null}},{"start":{},"end":{}}],"line":149},"10":{"loc":{"start":{"line":152,"column":10},"end":{"line":156,"column":null}},"type":"binary-expr","locations":[{"start":{"line":152,"column":10},"end":{"line":156,"column":17}},{"start":{"line":156,"column":17},"end":{"line":156,"column":null}}],"line":152},"11":{"loc":{"start":{"line":170,"column":4},"end":{"line":170,"column":null}},"type":"if","locations":[{"start":{"line":170,"column":4},"end":{"line":170,"column":null}},{"start":{},"end":{}}],"line":170},"12":{"loc":{"start":{"line":184,"column":4},"end":{"line":184,"column":null}},"type":"if","locations":[{"start":{"line":184,"column":4},"end":{"line":184,"column":null}},{"start":{},"end":{}}],"line":184},"13":{"loc":{"start":{"line":188,"column":6},"end":{"line":195,"column":null}},"type":"if","locations":[{"start":{"line":188,"column":6},"end":{"line":195,"column":null}},{"start":{},"end":{}}],"line":188},"14":{"loc":{"start":{"line":192,"column":22},"end":{"line":192,"column":null}},"type":"binary-expr","locations":[{"start":{"line":192,"column":22},"end":{"line":192,"column":68}},{"start":{"line":192,"column":68},"end":{"line":192,"column":null}}],"line":192},"15":{"loc":{"start":{"line":193,"column":22},"end":{"line":193,"column":null}},"type":"binary-expr","locations":[{"start":{"line":193,"column":22},"end":{"line":193,"column":51}},{"start":{"line":193,"column":51},"end":{"line":193,"column":null}}],"line":193}},"s":{"0":62,"1":62,"2":61,"3":61,"4":3,"5":3,"6":3,"7":1,"8":1,"9":1,"10":0,"11":0,"12":1,"13":1,"14":1,"15":1,"16":0,"17":1,"18":0,"19":0,"20":1,"21":1,"22":1,"23":1,"24":1,"25":0,"26":3,"27":1,"28":1,"29":2,"30":2,"31":1,"32":1,"33":1,"34":1,"35":0,"36":1,"37":1,"38":1,"39":0,"40":1,"41":1,"42":1,"43":0,"44":2,"45":0,"46":2,"47":2,"48":1,"49":1,"50":1,"51":1,"52":1,"53":5},"f":{"0":62,"1":61,"2":1,"3":1,"4":1,"5":3,"6":1,"7":1,"8":2,"9":5},"b":{"0":[62],"1":[62],"2":[3,0],"3":[0,1],"4":[1,0],"5":[0,1],"6":[1,0],"7":[3],"8":[1,2],"9":[1,0],"10":[1,0],"11":[0,1],"12":[0,2],"13":[1,0],"14":[1,0],"15":[1,0]},"meta":{"lastBranch":16,"lastFunction":10,"lastStatement":54,"seen":{"s:29:22:29:Infinity":0,"f:31:2:31:14":0,"b:31:21:31:34":0,"b:31:41:31:47":1,"s:32:4:32:Infinity":1,"f:38:8:38:33":1,"s:39:4:52:Infinity":2,"s:41:23:41:Infinity":3,"b:42:6:45:Infinity:undefined:undefined:undefined:undefined":2,"s:42:6:45:Infinity":4,"s:43:8:43:Infinity":5,"s:44:8:44:Infinity":6,"s:47:6:50:Infinity":7,"s:51:6:51:Infinity":8,"f:58:8:58:25":2,"b:59:4:62:Infinity:undefined:undefined:undefined:undefined":3,"s:59:4:62:Infinity":9,"s:60:6:60:Infinity":10,"s:61:6:61:Infinity":11,"s:64:4:81:Infinity":12,"s:65:23:74:Infinity":13,"b:76:6:78:Infinity:undefined:undefined:undefined:undefined":4,"s:76:6:78:Infinity":14,"s:77:8:77:Infinity":15,"s:80:6:80:Infinity":16,"f:87:8:87:Infinity":3,"b:91:4:94:Infinity:undefined:undefined:undefined:undefined":5,"s:91:4:94:Infinity":17,"s:92:6:92:Infinity":18,"s:93:6:93:Infinity":19,"s:96:4:119:Infinity":20,"s:97:23:110:Infinity":21,"f:103:31:103:32":4,"s:103:39:107:14":22,"b:112:6:116:Infinity:undefined:undefined:undefined:undefined":6,"s:112:6:116:Infinity":23,"s:113:8:115:Infinity":24,"s:118:6:118:Infinity":25,"f:125:8:125:Infinity":5,"b:128:12:128:Infinity":7,"b:130:4:133:Infinity:undefined:undefined:undefined:undefined":8,"s:130:4:133:Infinity":26,"s:131:6:131:Infinity":27,"s:132:6:132:Infinity":28,"s:135:4:163:Infinity":29,"s:136:23:147:Infinity":30,"b:149:6:158:Infinity:undefined:undefined:undefined:undefined":9,"s:149:6:158:Infinity":31,"s:150:22:150:Infinity":32,"s:151:8:156:Infinity":33,"b:152:10:156:17:156:17:156:Infinity":10,"f:152:27:152:28":6,"s:152:43:156:12":34,"s:159:6:159:Infinity":35,"s:161:6:161:Infinity":36,"s:162:6:162:Infinity":37,"f:169:8:169:25":7,"b:170:4:170:Infinity:undefined:undefined:undefined:undefined":11,"s:170:4:170:Infinity":38,"s:170:25:170:Infinity":39,"s:172:4:177:Infinity":40,"s:173:6:173:Infinity":41,"s:174:6:174:Infinity":42,"s:176:6:176:Infinity":43,"f:183:8:183:22":8,"b:184:4:184:Infinity:undefined:undefined:undefined:undefined":12,"s:184:4:184:Infinity":44,"s:184:25:184:Infinity":45,"s:186:4:198:Infinity":46,"s:187:23:187:Infinity":47,"b:188:6:195:Infinity:undefined:undefined:undefined:undefined":13,"s:188:6:195:Infinity":48,"s:189:22:189:Infinity":49,"s:190:8:194:Infinity":50,"b:192:22:192:68:192:68:192:Infinity":14,"b:193:22:193:51:193:51:193:Infinity":15,"s:197:6:197:Infinity":51,"s:199:4:199:Infinity":52,"f:205:2:205:25":9,"s:206:4:206:Infinity":53}}} -} diff --git a/coverage/index.html b/coverage/index.html index 1d6c2df..250f3f7 100644 --- a/coverage/index.html +++ b/coverage/index.html @@ -23,30 +23,30 @@

All files

- 55.79% + 66.48% Statements - 2408/4316 + 3515/5287
- 44.19% + 56.99% Branches - 1485/3360 + 2229/3911
- 57.88% + 69.41% Functions - 411/710 + 597/860
- 56.94% + 67.67% Lines - 2321/4076 + 3360/4965
@@ -79,138 +79,168 @@

All files

- src - -
+ src + +
- 100% - 40/40 - 84.78% - 39/46 - 100% - 4/4 - 100% - 40/40 + 29.16% + 42/144 + 55.12% + 43/78 + 17.39% + 4/23 + 29.37% + 42/143 - src/engines - -
+ src/cli + +
- 42.8% - 339/792 - 26.3% - 161/612 - 42.94% - 67/156 - 43.69% - 319/730 + 0% + 0/208 + 0% + 0/74 + 0% + 0/20 + 0% + 0/198 + + + + src/engines + +
+ + 77.39% + 719/929 + 64.07% + 453/707 + 82.75% + 144/174 + 79.17% + 673/850 src/graph - -
+ +
- 50.86% - 469/922 - 33.93% - 225/663 - 60.57% - 106/175 - 52.23% - 456/873 + 64.06% + 681/1063 + 48.97% + 357/729 + 64.42% + 134/208 + 64.83% + 649/1001 - src/parsers - -
+ src/parsers + +
- 46.32% - 347/749 - 33% - 136/412 - 47.7% - 52/109 - 47.31% - 326/689 + 61.81% + 463/749 + 46.35% + 191/412 + 72.47% + 79/109 + 64.13% + 440/686 src/response - -
+ +
- 73.45% - 83/113 - 63.96% - 71/111 + 74.33% + 84/113 + 67.56% + 75/111 90% 18/20 - 73.63% - 81/110 + 74.54% + 82/110 src/tools - -
+ +
+ + 57.46% + 431/750 + 48.75% + 313/642 + 55.55% + 75/135 + 58.37% + 425/728 + + + + src/tools/handlers + +
- 59.42% - 738/1242 - 51.5% - 599/1163 - 56.74% - 101/178 - 60.08% - 727/1210 + 81.89% + 837/1022 + 67.74% + 628/927 + 83.47% + 96/115 + 83.79% + 812/969 - src/tools/handlers - -
+ src/types + +
- 79.71% - 169/212 - 63.12% - 113/179 - 92.3% - 24/26 - 82.41% - 164/199 + 0% + 0/23 + 0% + 0/25 + 0% + 0/5 + 0% + 0/21 src/utils - -
+ +
- 93.24% - 69/74 - 89.01% - 81/91 + 92.38% + 97/105 + 87.17% + 102/117 100% - 13/13 - 93.24% - 69/74 + 20/20 + 92.07% + 93/101 src/vector - -
+ +
- 89.53% - 154/172 - 72.28% - 60/83 - 89.65% - 26/29 - 92.05% - 139/151 + 88.95% + 161/181 + 75.28% + 67/89 + 87.09% + 27/31 + 91.13% + 144/158 @@ -221,7 +251,7 @@

All files

+ + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/prettify.css b/coverage/lcov-report/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/lcov-report/prettify.js b/coverage/lcov-report/prettify.js new file mode 100644 index 0000000..b322523 --- /dev/null +++ b/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/lcov-report/sort-arrow-sprite.png b/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000..6ed6831 Binary files /dev/null and b/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/coverage/lcov-report/sorter.js b/coverage/lcov-report/sorter.js new file mode 100644 index 0000000..4ed70ae --- /dev/null +++ b/coverage/lcov-report/sorter.js @@ -0,0 +1,210 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + + // Try to create a RegExp from the searchValue. If it fails (invalid regex), + // it will be treated as a plain text search + let searchRegex; + try { + searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive + } catch (error) { + searchRegex = null; + } + + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + let isMatch = false; + + if (searchRegex) { + // If a valid regex was created, use it for matching + isMatch = searchRegex.test(row.textContent); + } else { + // Otherwise, fall back to the original plain text search + isMatch = row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()); + } + + row.style.display = isMatch ? '' : 'none'; + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/coverage/lcov-report/src/cli/build.ts.html b/coverage/lcov-report/src/cli/build.ts.html new file mode 100644 index 0000000..a6e457b --- /dev/null +++ b/coverage/lcov-report/src/cli/build.ts.html @@ -0,0 +1,445 @@ + + + + + + Code coverage report for src/cli/build.ts + + + + + + + + + +
+
+

All files / src/cli build.ts

+
+ +
+ 0% + Statements + 0/48 +
+ + +
+ 0% + Branches + 0/16 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 0% + Lines + 0/46 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
#!/usr/bin/env node
+ 
+/**
+ * Graph Build CLI
+ * Builds the code graph from a workspace's source files.
+ *
+ * Usage:
+ *   npm run graph:build
+ *   npm run graph:build -- --full
+ *   npm run graph:build -- --verbose
+ */
+ 
+import * as path from "path";
+import * as fs from "fs";
+import { GraphOrchestrator } from "../graph/orchestrator.js";
+import MemgraphClient from "../graph/client.js";
+import * as env from "../env.js";
+import { logger } from "../utils/logger.js";
+ 
+async function main() {
+  const args = process.argv.slice(2);
+  const isFullBuild = args.includes("--full");
+  const isVerbose = args.includes("--verbose");
+  const projectRoot = path.resolve(process.cwd());
+ 
+  logger.error("🔨 Code Graph Builder");
+  logger.error(`📁 Project root: ${projectRoot}`);
+  logger.error(`🔄 Build mode: ${isFullBuild ? "FULL" : "INCREMENTAL"}`);
+  logger.error("");
+ 
+  try {
+    // Initialize Memgraph client
+    logger.error("🔌 Connecting to Memgraph...");
+    const memgraph = new MemgraphClient({
+      host: env.MEMGRAPH_HOST,
+      port: env.MEMGRAPH_PORT,
+    });
+ 
+    await memgraph.connect();
+    logger.error("✅ Connected to Memgraph\n");
+ 
+    // Create orchestrator
+    const orchestrator = new GraphOrchestrator(memgraph, isVerbose);
+ 
+    // Build the graph
+    logger.error("📊 Building code graph...\n");
+    const startTime = Date.now();
+ 
+    const result = await orchestrator.build({
+      mode: isFullBuild ? "full" : "incremental",
+      verbose: isVerbose,
+      sourceDir: path.join(projectRoot, "src"),
+      exclude: [
+        "node_modules/**",
+        "dist/**",
+        "build/**",
+        ".lxrag/**",
+        "**/*.test.ts",
+        "**/*.test.tsx",
+        "**/__tests__/**",
+      ],
+    });
+ 
+    const duration = Date.now() - startTime;
+ 
+    // Display results
+    logger.error("\n📈 Build Results:");
+    logger.error(`   ✅ Success: ${result.success}`);
+    logger.error(`   ⏱️  Duration: ${(duration / 1000).toFixed(2)}s`);
+    logger.error(`   📄 Files processed: ${result.filesProcessed}`);
+    logger.error(`   📍 Nodes created: ${result.nodesCreated}`);
+    logger.error(`   🔗 Relationships created: ${result.relationshipsCreated}`);
+    if (result.filesChanged > 0) {
+      logger.error(`   🔄 Files changed: ${result.filesChanged}`);
+    }
+ 
+    if (result.errors.length > 0) {
+      logger.error(`\n❌ Errors (${result.errors.length}):`);
+      result.errors.forEach((err) => logger.error(`   - ${err}`));
+    }
+ 
+    if (result.warnings.length > 0) {
+      logger.error(`\n⚠️  Warnings (${result.warnings.length}):`);
+      result.warnings.forEach((warn) => logger.error(`   - ${warn}`));
+    }
+ 
+    // Save build metadata
+    const codeGraphDir = path.join(projectRoot, ".lxrag");
+    if (!fs.existsSync(codeGraphDir)) {
+      fs.mkdirSync(codeGraphDir, { recursive: true });
+    }
+ 
+    const metadata = {
+      timestamp: new Date().toISOString(),
+      duration,
+      mode: isFullBuild ? "full" : "incremental",
+      success: result.success,
+      filesProcessed: result.filesProcessed,
+      nodesCreated: result.nodesCreated,
+      relationshipsCreated: result.relationshipsCreated,
+    };
+ 
+    fs.writeFileSync(path.join(codeGraphDir, "build.log.json"), JSON.stringify(metadata, null, 2));
+ 
+    logger.error("\n✨ Build complete!");
+    logger.error("   View graph at: http://localhost:3000 (Memgraph Lab)");
+    logger.error('   Query graph: npm run graph:query "MATCH (f:FILE) RETURN count(f)"');
+ 
+    // Exit with appropriate code
+    process.exit(result.success ? 0 : 1);
+  } catch (error) {
+    logger.error("❌ Build failed:", error);
+    process.exit(1);
+  }
+}
+ 
+main().catch((error) => {
+  logger.error("Fatal error:", error);
+  process.exit(1);
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/cli/index.html b/coverage/lcov-report/src/cli/index.html new file mode 100644 index 0000000..bdc1cef --- /dev/null +++ b/coverage/lcov-report/src/cli/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/cli + + + + + + + + + +
+
+

All files src/cli

+
+ +
+ 0% + Statements + 0/208 +
+ + +
+ 0% + Branches + 0/74 +
+ + +
+ 0% + Functions + 0/20 +
+ + +
+ 0% + Lines + 0/198 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
build.ts +
+
0%0/480%0/160%0/40%0/46
query.ts +
+
0%0/250%0/60%0/20%0/25
test-affected.ts +
+
0%0/830%0/260%0/80%0/78
validate.ts +
+
0%0/520%0/260%0/60%0/49
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/cli/query.ts.html b/coverage/lcov-report/src/cli/query.ts.html new file mode 100644 index 0000000..eefa94e --- /dev/null +++ b/coverage/lcov-report/src/cli/query.ts.html @@ -0,0 +1,271 @@ + + + + + + Code coverage report for src/cli/query.ts + + + + + + + + + +
+
+

All files / src/cli query.ts

+
+ +
+ 0% + Statements + 0/25 +
+ + +
+ 0% + Branches + 0/6 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/25 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
#!/usr/bin/env node
+ 
+/**
+ * Graph Query CLI
+ * Execute Cypher queries against the code graph
+ *
+ * Usage:
+ *   npm run graph:query "MATCH (f:FILE) RETURN count(f)"
+ *   npm run graph:query "find all functions named create*"
+ */
+ 
+import MemgraphClient from "../graph/client.js";
+import * as env from "../env.js";
+import { logger } from "../utils/logger.js";
+ 
+async function main() {
+  const args = process.argv.slice(2);
+  const query = args.join(" ");
+ 
+  if (!query) {
+    logger.error("❌ No query provided");
+    logger.error('Usage: npm run graph:query "MATCH (n) RETURN n LIMIT 5"');
+    process.exit(1);
+  }
+ 
+  try {
+    logger.error("🔍 Executing query...\n");
+ 
+    const memgraph = new MemgraphClient({
+      host: env.MEMGRAPH_HOST,
+      port: env.MEMGRAPH_PORT,
+    });
+ 
+    await memgraph.connect();
+ 
+    const result = await memgraph.executeCypher(query);
+ 
+    if (result.error) {
+      logger.error("❌ Query error:", result.error);
+      process.exit(1);
+    }
+ 
+    // Display results
+    if (result.data.length === 0) {
+      logger.error("📭 No results found");
+    } else {
+      logger.error(`📊 Results (${result.data.length} rows):\n`);
+      console.table(result.data);
+    }
+ 
+    await memgraph.disconnect();
+    process.exit(0);
+  } catch (error) {
+    logger.error("❌ Query failed:", error);
+    process.exit(1);
+  }
+}
+ 
+main().catch((error) => {
+  logger.error("Fatal error:", error);
+  process.exit(1);
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/cli/test-affected.ts.html b/coverage/lcov-report/src/cli/test-affected.ts.html new file mode 100644 index 0000000..fedef44 --- /dev/null +++ b/coverage/lcov-report/src/cli/test-affected.ts.html @@ -0,0 +1,511 @@ + + + + + + Code coverage report for src/cli/test-affected.ts + + + + + + + + + +
+
+

All files / src/cli test-affected.ts

+
+ +
+ 0% + Statements + 0/83 +
+ + +
+ 0% + Branches + 0/26 +
+ + +
+ 0% + Functions + 0/8 +
+ + +
+ 0% + Lines + 0/78 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
#!/usr/bin/env node
+ 
+/**
+ * Test Affected CLI
+ * Selects and optionally runs tests affected by changed files
+ *
+ * Usage:
+ *   npm run test:affected src/engine/calculations/columns.ts
+ *   npm run test:affected src/utils/units.ts --run
+ *   npm run test:affected src/engine/**\/*.ts --depth=2
+ */
+ 
+import { execSync } from "child_process";
+import GraphIndexManager from "../graph/index.js";
+import { loadConfig } from "../config.js";
+import TestEngine from "../engines/test-engine.js";
+ 
+async function main() {
+  const args = process.argv.slice(2);
+ 
+  if (args.length === 0) {
+    console.error("🧪 Test Affected Selector");
+    console.error("");
+    console.error("Usage: npm run test:affected <files> [--run] [--depth=N]");
+    console.error("");
+    console.error("Options:");
+    console.error("  --run         Run tests after selection (requires Vitest)");
+    console.error("  --depth=N     Set transitive dependency depth (default: 1)");
+    console.error("");
+    console.error("Examples:");
+    console.error("  npm run test:affected src/utils/units.ts");
+    console.error("  npm run test:affected src/engine/calculations/\\*.ts --run");
+    console.error("  npm run test:affected src/context/BuildingContext.tsx --depth=2 --run");
+    process.exit(0);
+  }
+ 
+  const runTests = args.includes("--run");
+  const depthArg = args.find((a) => a.startsWith("--depth="));
+  const depth = depthArg ? parseInt(depthArg.split("=")[1]) : 1;
+ 
+  // Filter out flag arguments
+  const changedFiles = args.filter((a) => !a.startsWith("--run") && !a.startsWith("--depth="));
+ 
+  console.error("🧪 Test Affected Selector");
+  console.error(`📁 Changed files: ${changedFiles.length}`);
+  console.error(`🔄 Dependency depth: ${depth}`);
+  console.error(`▶️  Auto-run: ${runTests ? "YES" : "NO"}\n`);
+ 
+  try {
+    // Create in-memory graph index
+    console.error("📊 Building test dependency map...");
+    const index = new GraphIndexManager();
+    const testEngine = new TestEngine(index);
+    console.error("✅ Ready\n");
+ 
+    // Select affected tests
+    console.error("🔍 Analyzing dependencies...\n");
+    const result = testEngine.selectAffectedTests(changedFiles, true, depth);
+ 
+    // Display results
+    if (result.selectedTests.length === 0) {
+      console.error("ℹ️  No tests directly affected by these changes");
+      console.error(
+        "   (Possibly: new file, not imported by tests, or test dependencies not built)",
+      );
+      process.exit(0);
+    }
+ 
+    console.error(`✅ Selected ${result.selectedTests.length} test(s):`);
+    console.error("");
+    result.selectedTests.forEach((test) => {
+      console.error(`   📄 ${test}`);
+    });
+ 
+    console.error("");
+    console.error("📊 Statistics:");
+    console.error(
+      `   Coverage: ${result.coverage.percentage}% (${result.coverage.testsSelected}/${result.coverage.totalTests})`,
+    );
+    console.error(`   Category: ${result.category}`);
+    console.error(
+      `   Est. time: ${result.estimatedTime > 0 ? result.estimatedTime + "ms" : "unknown"}`,
+    );
+    console.error("");
+ 
+    // Optionally run tests
+    if (runTests) {
+      console.error("\u25b6\ufe0f  Running selected tests...\n");
+      try {
+        const config = await loadConfig();
+        const runner = config.testing?.testRunner;
+        const testList = result.selectedTests.join(" ");
+ 
+        let runCmd: string;
+        if (runner) {
+          // Explicit runner from .lxrag/config.json
+          const runnerArgs = [...(runner.args ?? []), ...result.selectedTests].join(" ");
+          runCmd = `${runner.command} ${runnerArgs}`;
+        } else {
+          // Auto-detect from test file extensions
+          const hasPy = result.selectedTests.some((f) => f.endsWith(".py"));
+          const hasRb = result.selectedTests.some((f) => f.endsWith(".rb"));
+          const hasGo = result.selectedTests.some((f) => f.endsWith(".go"));
+          if (hasPy) {
+            runCmd = `pytest ${testList}`;
+          } else if (hasRb) {
+            runCmd = `bundle exec rspec ${testList}`;
+          } else if (hasGo) {
+            runCmd = `go test ${testList}`;
+          } else {
+            // Default: vitest (JS/TS)
+            runCmd = `npx vitest run ${testList}`;
+          }
+        }
+ 
+        console.error(`\u25b6\ufe0f  ${runCmd}`);
+        execSync(runCmd, {
+          cwd: process.cwd(),
+          stdio: "inherit",
+        });
+        console.error("\n\u2705 Tests completed successfully");
+        process.exit(0);
+      } catch (_error) {
+        console.error("\n\u274c Some tests failed");
+        process.exit(1);
+      }
+    } else {
+      console.error("💡 To run these tests, add --run flag:");
+      console.error(`   npm run test:affected ${changedFiles.join(" ")} --run`);
+      console.error("");
+      process.exit(0);
+    }
+  } catch (error) {
+    console.error("❌ Error:", error instanceof Error ? error.message : String(error));
+    process.exit(1);
+  }
+}
+ 
+main().catch((error) => {
+  console.error("Fatal error:", error);
+  process.exit(1);
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/cli/validate.ts.html b/coverage/lcov-report/src/cli/validate.ts.html new file mode 100644 index 0000000..cf7518b --- /dev/null +++ b/coverage/lcov-report/src/cli/validate.ts.html @@ -0,0 +1,403 @@ + + + + + + Code coverage report for src/cli/validate.ts + + + + + + + + + +
+
+

All files / src/cli validate.ts

+
+ +
+ 0% + Statements + 0/52 +
+ + +
+ 0% + Branches + 0/26 +
+ + +
+ 0% + Functions + 0/6 +
+ + +
+ 0% + Lines + 0/49 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
#!/usr/bin/env node
+ 
+/**
+ * Graph Validate CLI
+ * Validates architecture constraints against the code graph
+ *
+ * Usage:
+ *   npm run graph:validate
+ *   npm run graph:validate -- --strict
+ *   npm run graph:validate -- --file src/engine/calculations/columns.ts
+ */
+ 
+import { ArchitectureEngine } from "../engines/architecture-engine.js";
+import { loadConfig } from "../config.js";
+import GraphIndexManager from "../graph/index.js";
+import { MemgraphClient } from "../graph/client.js";
+import { logger } from "../utils/logger.js";
+ 
+async function main() {
+  const args = process.argv.slice(2);
+  const isStrict = args.includes("--strict");
+  const writeViolations = args.includes("--write");
+  const fileIndex = args.indexOf("--file");
+  const targetFile = fileIndex >= 0 ? args[fileIndex + 1] : undefined;
+ 
+  logger.error("🏗️  Architecture Validator");
+  if (targetFile) {
+    logger.error(`📄 Validating: ${targetFile}`);
+  } else {
+    logger.error("📄 Validating all files");
+  }
+  logger.error(`🔒 Strict mode: ${isStrict ? "ON" : "OFF"}\n`);
+ 
+  try {
+    // Load configuration
+    const config = await loadConfig();
+ 
+    // Create in-memory graph index (MVP - no Memgraph connection needed for validation)
+    logger.error("📊 Preparing validation engine...");
+    const index = new GraphIndexManager();
+    logger.error("✅ Ready\n");
+ 
+    // Run validation
+    logger.error("🔍 Checking architecture constraints...\n");
+    const layers = config.architecture.layers.map((layer) => ({
+      ...layer,
+      description: layer.description || layer.name,
+    }));
+    const engine = new ArchitectureEngine(layers, config.architecture.rules, index, undefined, {
+      sourceGlobs: config.testing?.sourceGlobs,
+      defaultExtension: config.testing?.defaultExtension,
+    });
+    const filesToValidate = targetFile ? [targetFile] : undefined;
+    const result = await engine.validate(filesToValidate);
+    const violations = result.violations || [];
+ 
+    // Write violations to Memgraph if --write flag is set
+    if (writeViolations && violations.length > 0) {
+      try {
+        const client = new MemgraphClient();
+        await client.connect();
+        await engine.writeViolationsToMemgraph(client, violations);
+        await client.disconnect();
+      } catch (error) {
+        logger.warn(
+          "⚠️  Could not write violations to Memgraph:",
+          error instanceof Error ? error.message : String(error),
+        );
+      }
+    }
+ 
+    // Display results
+    if (violations.length === 0) {
+      logger.error("✅ No violations found!");
+    } else {
+      logger.error(`⚠️  Found ${violations.length} violation(s):\n`);
+      violations.forEach((violation, index) => {
+        const icon = violation.severity === "error" ? "❌" : "⚠️";
+        logger.error(`${icon} ${index + 1}. ${violation.message}`);
+        logger.error(`   File: ${violation.file}`);
+        logger.error(`   Layer: ${violation.layer}`);
+        logger.error("");
+      });
+ 
+      const errorCount = violations.filter((v) => v.severity === "error").length;
+      const warningCount = violations.filter((v) => v.severity === "warn").length;
+ 
+      logger.error(`Summary: ${errorCount} error(s), ${warningCount} warning(s)`);
+ 
+      if (isStrict && errorCount > 0) {
+        logger.error("\n🛑 Strict mode: exiting with error code 1");
+        process.exit(1);
+      }
+    }
+ 
+    process.exit(0);
+  } catch (error) {
+    logger.error("❌ Validation failed:", error);
+    process.exit(1);
+  }
+}
+ 
+main().catch((error) => {
+  logger.error("Fatal error:", error);
+  process.exit(1);
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/config.ts.html b/coverage/lcov-report/src/config.ts.html new file mode 100644 index 0000000..f7437c2 --- /dev/null +++ b/coverage/lcov-report/src/config.ts.html @@ -0,0 +1,787 @@ + + + + + + Code coverage report for src/config.ts + + + + + + + + + +
+
+

All files / src config.ts

+
+ +
+ 0% + Statements + 0/13 +
+ + +
+ 0% + Branches + 0/6 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Configuration loader
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import { logger } from "./utils/logger.js";
+ 
+export interface ArchitectureConfig {
+  layers: LayerConfig[];
+  rules: RuleConfig[];
+}
+ 
+export interface LayerConfig {
+  id: string;
+  name: string;
+  paths: string[];
+  canImport: string[];
+  description?: string;
+}
+ 
+export interface RuleConfig {
+  id: string;
+  severity: "error" | "warn";
+  pattern: string;
+  description: string;
+}
+ 
+export interface ProgressConfig {
+  features: Array<{
+    id: string;
+    name: string;
+    status: "not-started" | "in-progress" | "blocked" | "completed";
+    priority: "low" | "medium" | "high";
+    description?: string;
+    tasks?: string[];
+  }>;
+}
+ 
+export interface Config {
+  architecture: ArchitectureConfig;
+  testing?: {
+    categories: Array<{
+      id: string;
+      patterns: string[];
+    }>;
+    /**
+     * Explicit test runner to invoke via `test_run` and `test:affected`.
+     * When omitted the runner is auto-detected from the test file extensions
+     * (e.g. .py → pytest, .rb → bundle exec rspec, .ts/.js → vitest).
+     * @example { "command": "pytest", "args": ["--tb=short"] }
+     */
+    testRunner?: {
+      command: string;
+      args?: string[];
+    };
+    /**
+     * Glob patterns used by the architecture engine to discover source files.
+     * Defaults to ["src/**\/*.{ts,tsx}"] when not specified.
+     * @example ["src/**\/*.py", "lib/**\/*.py"]
+     */
+    sourceGlobs?: string[];
+    /**
+     * Default file extension appended when generating new file paths (e.g. via
+     * arch_suggest). Defaults to ".ts". Use ".py", ".rb", ".go", etc. for
+     * non-TypeScript projects.
+     */
+    defaultExtension?: string;
+  };
+  progress?: ProgressConfig;
+}
+ 
+// Generic TypeScript server defaults — create .lxrag/config.json at your project root
+// to override with project-specific layers and rules.
+// Tip: run arch_suggest to get placement guidance; update this file if suggestions
+// look wrong (e.g. always "src/types/").
+const DEFAULT_CONFIG: Config = {
+  architecture: {
+    layers: [
+      {
+        id: "types",
+        name: "Types",
+        paths: ["src/types/**"],
+        canImport: [],
+        description: "Shared type definitions — no runtime dependencies",
+      },
+      {
+        id: "utils",
+        name: "Utilities",
+        paths: ["src/utils/**", "src/lib/**", "src/helpers/**"],
+        canImport: ["types"],
+        description: "Stateless utility and helper functions",
+      },
+      {
+        id: "parsers",
+        name: "Parsers",
+        paths: ["src/parsers/**"],
+        canImport: ["types", "utils"],
+        description: "File parsers and language-specific analysis",
+      },
+      {
+        id: "graph",
+        name: "Graph",
+        paths: ["src/graph/**"],
+        canImport: ["types", "utils", "parsers"],
+        description: "Graph building, caching and Memgraph client",
+      },
+      {
+        id: "vector",
+        name: "Vector",
+        paths: ["src/vector/**"],
+        canImport: ["types", "utils", "graph"],
+        description: "Embedding engine and Qdrant client",
+      },
+      {
+        id: "engines",
+        name: "Engines",
+        paths: ["src/engines/**"],
+        canImport: ["types", "utils", "parsers", "graph", "vector"],
+        description: "Feature engines — architecture, community, docs, test, progress",
+      },
+      {
+        id: "tools",
+        name: "Tools",
+        paths: ["src/tools/**"],
+        canImport: ["types", "utils", "parsers", "graph", "vector", "engines"],
+        description: "MCP tool handlers — highest-level layer, may use all lower layers",
+      },
+      {
+        id: "server",
+        name: "Server",
+        paths: ["src/*.ts"],
+        canImport: ["types", "utils", "graph", "vector", "engines", "tools"],
+        description: "Server entry points — wires all layers together",
+      },
+    ],
+    rules: [
+      {
+        id: "no-tools-in-engines",
+        severity: "error",
+        pattern: "engines imports from tools",
+        description: "Engines must not import from tool handlers",
+      },
+      {
+        id: "no-graph-in-parsers",
+        severity: "warn",
+        pattern: "parsers imports from graph",
+        description: "Parsers should be graph-agnostic for reuse and testability",
+      },
+    ],
+  },
+  testing: {
+    categories: [
+      {
+        id: "unit",
+        patterns: ["**/__tests__/**/*.test.ts", "!**/*.integration.test.ts"],
+      },
+      {
+        id: "integration",
+        patterns: ["**/__tests__/**/*.integration.test.ts"],
+      },
+    ],
+  },
+  progress: {
+    features: [
+      {
+        id: "phase-1",
+        name: "Code Graph MVP",
+        status: "completed",
+        priority: "high",
+        description: "Parse codebase and build graph",
+        tasks: ["parse-files", "build-graph", "validate-output"],
+      },
+      {
+        id: "phase-2",
+        name: "Architecture Validation",
+        status: "completed",
+        priority: "high",
+        description: "Layer validation and constraint checking",
+        tasks: ["layer-rules", "circular-detection", "pre-commit-hook"],
+      },
+      {
+        id: "phase-3",
+        name: "Test Intelligence",
+        status: "completed",
+        priority: "high",
+        description: "Test selection and execution",
+        tasks: ["test-extraction", "test-selection", "vitest-integration"],
+      },
+      {
+        id: "phase-4",
+        name: "MCP Tools",
+        status: "completed",
+        priority: "high",
+        description: "Wire all 14 MCP tools",
+        tasks: ["tool-schemas", "tool-handlers", "claude-integration"],
+      },
+      {
+        id: "phase-5",
+        name: "Progress Tracking",
+        status: "in-progress",
+        priority: "medium",
+        description: "Track features and tasks",
+        tasks: ["config-progress", "seed-nodes", "persistence"],
+      },
+    ],
+  },
+};
+ 
+export async function loadConfig(): Promise<Config> {
+  const configPath = path.join(process.cwd(), ".lxrag", "config.json");
+ 
+  try {
+    if (fs.existsSync(configPath)) {
+      const data = fs.readFileSync(configPath, "utf-8");
+      return JSON.parse(data);
+    }
+  } catch (error) {
+    logger.warn("[Config] Error loading config file:", error);
+  }
+ 
+  return DEFAULT_CONFIG;
+}
+ 
+export function saveConfig(config: Config, configPath?: string): void {
+  const targetPath = configPath || path.join(process.cwd(), ".lxrag", "config.json");
+  const dir = path.dirname(targetPath);
+ 
+  if (!fs.existsSync(dir)) {
+    fs.mkdirSync(dir, { recursive: true });
+  }
+ 
+  fs.writeFileSync(targetPath, JSON.stringify(config, null, 2));
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/architecture-engine.ts.html b/coverage/lcov-report/src/engines/architecture-engine.ts.html new file mode 100644 index 0000000..5bdb0d4 --- /dev/null +++ b/coverage/lcov-report/src/engines/architecture-engine.ts.html @@ -0,0 +1,2191 @@ + + + + + + Code coverage report for src/engines/architecture-engine.ts + + + + + + + + + +
+
+

All files / src/engines architecture-engine.ts

+
+ +
+ 67.65% + Statements + 159/235 +
+ + +
+ 50% + Branches + 68/136 +
+ + +
+ 82.6% + Functions + 19/23 +
+ + +
+ 68.77% + Lines + 152/221 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +39x +9x +9x +9x +9x +  +  +  +  +  +  +5x +5x +  +  +  +5x +1x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +8x +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +8x +  +5x +  +  +  +  +5x +5x +  +5x +5x +  +  +5x +3x +  +  +  +  +  +  +  +  +  +  +5x +3x +  +  +  +  +  +  +  +  +  +  +  +  +5x +5x +  +8x +8x +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +36x +36x +15x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +36x +  +  +  +  +  +  +36x +36x +  +  +  +  +  +  +  +  +  +16x +16x +16x +16x +  +16x +  +  +  +  +  +  +  +  +16x +  +16x +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +10x +10x +  +  +  +  +  +  +  +  +  +10x +10x +  +  +  +  +10x +  +10x +  +10x +  +10x +  +  +  +10x +  +  +  +  +  +  +  +  +10x +20x +20x +10x +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +8x +3x +  +  +  +5x +  +  +  +5x +  +  +  +  +  +  +5x +  +  +5x +  +  +  +  +  +  +5x +5x +5x +5x +5x +  +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +8x +8x +  +8x +5x +5x +5x +5x +  +  +  +  +8x +  +  +  +5x +  +15x +15x +2x +2x +  +  +13x +  +13x +13x +13x +  +13x +15x +7x +  +  +13x +13x +13x +  +  +  +5x +8x +8x +  +  +  +  +5x +5x +2x +2x +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +  +6x +6x +33x +33x +3x +3x +  +  +  +  +33x +33x +  +  +  +6x +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +6x +  +6x +6x +6x +33x +33x +33x +124x +  +5x +5x +  +  +33x +11x +11x +  +  +  +6x +  +6x +  +  +  +6x +  +  +  +  +  +  +  +  +6x +6x +  +  +6x +  +  +  +  +6x +2x +2x +2x +4x +4x +4x +  +4x +3x +  +1x +  +  +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file engines/architecture-engine
+ * @description Validates source dependencies against configured architecture layers and rules.
+ * @remarks Supports filesystem scanning and explicit file-list validation modes.
+ */
+ 
+import * as path from "path";
+import * as fs from "fs";
+import { globSync } from "glob";
+import type { GraphIndexManager } from "../graph/index.js";
+import type { MemgraphClient } from "../graph/client.js";
+import type { CypherStatement } from "../graph/types.js";
+import { logger } from "../utils/logger.js";
+ 
+export interface LayerDefinition {
+  id: string;
+  name: string;
+  paths: string[];
+  canImport: string[];
+  cannotImport?: string[];
+  description: string;
+}
+ 
+export interface ArchitectureRule {
+  id: string;
+  severity: "error" | "warn";
+  pattern: string;
+  description: string;
+}
+ 
+export interface ValidationViolation {
+  type: "layer-violation" | "rule-violation" | "unused" | "circular";
+  severity: "error" | "warn";
+  file: string;
+  layer: string;
+  message: string;
+  suggestion?: string;
+  lineNumber?: number;
+}
+ 
+export interface ValidationResult {
+  success: boolean;
+  violations: ValidationViolation[];
+  statistics: {
+    totalViolations: number;
+    errorCount: number;
+    warningCount: number;
+    filesChecked: number;
+  };
+}
+ 
+export class ArchitectureEngine {
+  private layers: Map<string, LayerDefinition>;
+  private rules: ArchitectureRule[];
+  private workspaceRoot: string;
+  /** Glob patterns used to discover source files (e.g. for validation/circular-dep scan). */
+  private sourceGlobs: string[];
+  /** Default file extension used when generating suggested paths. */
+  private defaultExtension: string;
+ 
+  constructor(
+    layers: LayerDefinition[],
+    rules: ArchitectureRule[],
+    _index: GraphIndexManager,
+    workspaceRoot?: string,
+    options?: {
+      /** Override the glob patterns used to scan source files. Defaults to ["src/**\/*.{ts,tsx}"]. */
+      sourceGlobs?: string[];
+      /** Default extension for generated file paths. Defaults to ".ts". */
+      defaultExtension?: string;
+    },
+  ) {
+    this.layers = new Map(layers.map((l) => [l.id, l]));
+    this.rules = rules;
+    this.workspaceRoot = workspaceRoot ?? process.cwd();
+    this.sourceGlobs = options?.sourceGlobs ?? ["src/**/*.{ts,tsx}"];
+    this.defaultExtension = options?.defaultExtension ?? ".ts";
+  }
+ 
+  /**
+   * Validate architecture of all files by scanning file system
+   */
+  async validate(files?: string[]): Promise<ValidationResult> {
+    const violations: ValidationViolation[] = [];
+    const projectRoot = this.workspaceRoot;
+ 
+    // Get source files to validate
+    let filesToCheck: string[];
+    if (files && files.length > 0) {
+      filesToCheck = files;
+    } else {
+      // Scan source files using configured globs (language-agnostic)
+      filesToCheck = this.sourceGlobs.flatMap((pattern) =>
+        globSync(pattern, {
+          cwd: projectRoot,
+          ignore: [
+            "**/node_modules/**",
+            "**/*.test.*",
+            "**/*.spec.*",
+            "**/test_*.py",
+            "**/*_test.go",
+            "**/*_spec.rb",
+          ],
+        }),
+      );
+    }
+ 
+    for (const filePath of filesToCheck) {
+      const layer = this.determineLayer(filePath);
+ 
+      Iif (!layer) {
+        violations.push({
+          type: "rule-violation",
+          severity: "warn",
+          file: filePath,
+          layer: "unknown",
+          message: `File not assigned to any layer: ${filePath}`,
+          suggestion: "Update .lxrag/config.json with appropriate layer path pattern",
+        });
+        continue;
+      }
+ 
+      // Extract imports from file
+      const imports = this.extractImportsFromFile(path.join(projectRoot, filePath));
+ 
+      for (const imp of imports) {
+        // Skip external imports
+        Iif (imp.startsWith("@") || (imp.startsWith(".") === false && !imp.startsWith("src"))) {
+          continue;
+        }
+ 
+        // Resolve imported file
+        const importedPath = this.resolveImportPath(filePath, imp, projectRoot);
+        Iif (!importedPath) continue;
+ 
+        const importedLayer = this.determineLayer(importedPath);
+        Iif (!importedLayer) continue;
+ 
+        // Check if import is allowed
+        if (!this.isImportAllowed(layer, importedLayer)) {
+          violations.push({
+            type: "layer-violation",
+            severity: "error",
+            file: filePath,
+            layer: layer.id,
+            message: `Layer '${layer.id}' cannot import from layer '${importedLayer.id}'`,
+            suggestion: `Check your imports in ${filePath}. Layer rules: ${layer.id} can import ${layer.canImport.join(", ")}`,
+          });
+        }
+ 
+        // Check forbidden imports
+        if (layer.cannotImport && this.isForbiddenImport(layer, importedLayer)) {
+          violations.push({
+            type: "layer-violation",
+            severity: "error",
+            file: filePath,
+            layer: layer.id,
+            message: `Layer '${layer.id}' cannot import from layer '${importedLayer.id}' (explicitly forbidden)`,
+            suggestion: `Remove import of ${importedPath} from ${filePath}`,
+          });
+        }
+      }
+    }
+ 
+    // Check for circular dependencies
+    const circularViolations = this.detectCircularDependencies();
+    violations.push(...circularViolations);
+ 
+    const errorCount = violations.filter((v) => v.severity === "error").length;
+    const warningCount = violations.filter((v) => v.severity === "warn").length;
+ 
+    return {
+      success: errorCount === 0,
+      violations,
+      statistics: {
+        totalViolations: violations.length,
+        errorCount,
+        warningCount,
+        filesChecked: filesToCheck.length,
+      },
+    };
+  }
+ 
+  /**
+   * Determine which layer a file belongs to
+   */
+  private determineLayer(filePath: string): LayerDefinition | null {
+    for (const layer of this.layers.values()) {
+      for (const pattern of layer.paths) {
+        if (this.matchesPattern(filePath, pattern)) {
+          return layer;
+        }
+      }
+    }
+    return null;
+  }
+ 
+  /**
+   * Check if pattern matches file path
+   */
+  private matchesPattern(filePath: string, pattern: string): boolean {
+    // Simple glob-like matching
+    // Example: "src/components/**" matches "src/components/Button.tsx"
+    // Example: "src/types/**" matches "src/types/building.types.ts"
+ 
+    const patternRegex = pattern
+      .replace(/\//g, "/")
+      .replace(/\*\*/g, "__DOUBLE_STAR__")
+      .replace(/\*/g, "[^/]*")
+      .replace(/\?/g, ".")
+      .replace(/__DOUBLE_STAR__/g, ".*");
+ 
+    const regex = new RegExp(`^${patternRegex}$`);
+    return regex.test(filePath);
+  }
+ 
+  /**
+   * Extract import statements from a source file.
+   * Dispatches to language-specific logic based on the file extension.
+   * Supported: TypeScript/JavaScript (.ts, .tsx, .js, .jsx, .mjs, .cjs),
+   * Python (.py), Ruby (.rb), Go (.go).
+   */
+  private extractImportsFromFile(filePath: string): string[] {
+    const ext = path.extname(filePath).toLowerCase();
+    try {
+      const content = fs.readFileSync(filePath, "utf-8");
+      const imports: Set<string> = new Set();
+ 
+      if (
+        ext === ".ts" ||
+        ext === ".tsx" ||
+        ext === ".js" ||
+        ext === ".jsx" ||
+        ext === ".mjs" ||
+        ext === ".cjs"
+      ) {
+        // ES module: import/export ... from '...'
+        const importRegex = /(?:import|export)\s+(?:[^"']*\s+)?from\s+['"]([^'"]+)['"]/g;
+        let match;
+        while ((match = importRegex.exec(content)) !== null) {
+          imports.add(match[1]);
+        }
+      E} else if (ext === ".py") {
+        // Python: from module.path import ... / import module.path
+        const fromRegex = /^from\s+([\w.]+)\s+import\s+/gm;
+        const importRegex = /^import\s+([\w.]+)/gm;
+        let match;
+        while ((match = fromRegex.exec(content)) !== null) {
+          // Convert dotted module path to slash-separated path
+          imports.add(match[1].replace(/\./g, "/"));
+        }
+        while ((match = importRegex.exec(content)) !== null) {
+          imports.add(match[1].replace(/\./g, "/"));
+        }
+      } else if (ext === ".rb") {
+        // Ruby: require 'path' / require_relative 'path'
+        const reqRegex = /require(?:_relative)?\s+['"]([^'"]+)['"]/g;
+        let match;
+        while ((match = reqRegex.exec(content)) !== null) {
+          imports.add(match[1]);
+        }
+      } else if (ext === ".go") {
+        // Go: import "path" (single or block)
+        const blockRegex = /import\s*\(([\s\S]*?)\)/g;
+        const singleRegex = /import\s+"([^"]+)"/g;
+        let match;
+        while ((match = blockRegex.exec(content)) !== null) {
+          const block = match[1];
+          const lineRegex = /"([^"]+)"/g;
+          let lineMatch;
+          while ((lineMatch = lineRegex.exec(block)) !== null) {
+            imports.add(lineMatch[1]);
+          }
+        }
+        while ((match = singleRegex.exec(content)) !== null) {
+          imports.add(match[1]);
+        }
+      }
+ 
+      return Array.from(imports);
+    } catch {
+      return [];
+    }
+  }
+ 
+  /**
+   * Resolve import path to actual file (with .ts, .tsx, /index extensions)
+   */
+  private resolveImportPath(
+    fromPath: string,
+    importPath: string,
+    projectRoot: string,
+  ): string | null {
+    let resolvedPath: string;
+ 
+    if (importPath.startsWith(".")) {
+      // Relative import: resolve from importing file's directory within projectRoot.
+      // path.join(projectRoot, fromPath) gives an absolute base so that
+      // path.resolve() anchors to projectRoot instead of process.cwd().
+      const absoluteFromDir = path.dirname(path.join(projectRoot, fromPath));
+      resolvedPath = path.resolve(absoluteFromDir, importPath);
+    E} else if (importPath.startsWith("src/")) {
+      // Absolute src import
+      resolvedPath = importPath;
+    } else {
+      // External import, skip
+      return null;
+    }
+ 
+    // Normalize to project-relative path
+    let relPath = path.relative(projectRoot, resolvedPath).replace(/\\/g, "/");
+    Iif (!relPath.startsWith("src/")) {
+      relPath = path.relative(projectRoot, resolvedPath).replace(/\\/g, "/");
+    }
+ 
+    // Try different extensions based on the source file's language
+    const fromExt = path.extname(fromPath).toLowerCase();
+    let candidates: string[];
+    Iif (fromExt === ".py") {
+      candidates = [relPath, `${relPath}.py`, `${relPath}/__init__.py`];
+    I} else if (fromExt === ".rb") {
+      candidates = [relPath, `${relPath}.rb`];
+    I} else if (fromExt === ".go") {
+      candidates = [relPath];
+    } else {
+      // JS/TS (default)
+      candidates = [
+        relPath,
+        `${relPath}.ts`,
+        `${relPath}.tsx`,
+        `${relPath}/index.ts`,
+        `${relPath}/index.tsx`,
+      ];
+    }
+ 
+    for (const candidate of candidates) {
+      const fullPath = path.join(projectRoot, candidate);
+      if (fs.existsSync(fullPath)) {
+        return candidate;
+      }
+    }
+ 
+    // Return best guess if file doesn't exist yet (use source extension or configured default)
+    const fromExt2 = path.extname(fromPath).toLowerCase();
+    const bestExt = fromExt2 || this.defaultExtension;
+    Iif (relPath.includes(".")) return relPath;
+    return relPath.endsWith(bestExt) ? relPath : `${relPath}${bestExt}`;
+  }
+ 
+  /**
+   * Check if import from one layer to another is allowed
+   */
+  private isImportAllowed(fromLayer: LayerDefinition, toLayer: LayerDefinition): boolean {
+    // Can always import from same layer
+    if (fromLayer.id === toLayer.id) {
+      return true;
+    }
+ 
+    // Check canImport list
+    Iif (fromLayer.canImport.includes("*")) {
+      return true; // Can import anything
+    }
+ 
+    return fromLayer.canImport.includes(toLayer.id);
+  }
+ 
+  /**
+   * Check if import is explicitly forbidden
+   */
+  private isForbiddenImport(fromLayer: LayerDefinition, toLayer: LayerDefinition): boolean {
+    Iif (!fromLayer.cannotImport) {
+      return false;
+    }
+    return fromLayer.cannotImport.includes(toLayer.id);
+  }
+ 
+  /**
+   * Detect circular dependencies using DFS
+   */
+  private detectCircularDependencies(): ValidationViolation[] {
+    const violations: ValidationViolation[] = [];
+    const projectRoot = this.workspaceRoot;
+    const visited = new Set<string>();
+    const recursionStack = new Set<string>();
+    const cycles: string[][] = [];
+ 
+    // Build import graph
+    const importGraph = new Map<string, string[]>();
+    const sourceFiles = this.sourceGlobs.flatMap((pattern) =>
+      globSync(pattern, {
+        cwd: projectRoot,
+        ignore: [
+          "**/node_modules/**",
+          "**/*.test.*",
+          "**/*.spec.*",
+          "**/test_*.py",
+          "**/*_test.go",
+          "**/*_spec.rb",
+        ],
+      }),
+    );
+ 
+    for (const file of sourceFiles) {
+      const imports = this.extractImportsFromFile(path.join(projectRoot, file));
+      const resolvedImports: string[] = [];
+ 
+      for (const imp of imports) {
+        Eif (imp.startsWith(".") || imp.startsWith("src/")) {
+          const resolved = this.resolveImportPath(file, imp, projectRoot);
+          Eif (resolved) {
+            resolvedImports.push(resolved);
+          }
+        }
+      }
+ 
+      importGraph.set(file, resolvedImports);
+    }
+ 
+    // DFS to detect cycles
+    const dfs = (node: string, currentPath: string[]): void => {
+      // Check for cycle BEFORE adding to path
+      const cycleStart = currentPath.indexOf(node);
+      if (cycleStart >= 0) {
+        cycles.push([...currentPath.slice(cycleStart), node]);
+        return;
+      }
+ 
+      Iif (visited.has(node)) return;
+ 
+      visited.add(node);
+      recursionStack.add(node);
+      currentPath.push(node);
+ 
+      const neighbors = importGraph.get(node) || [];
+      for (const neighbor of neighbors) {
+        dfs(neighbor, currentPath);
+      }
+ 
+      currentPath.pop();
+      recursionStack.delete(node);
+      visited.delete(node); // allow revisiting via different paths for cycle detection
+    };
+ 
+    // Run DFS from each unvisited node
+    for (const file of sourceFiles) {
+      Eif (!visited.has(file)) {
+        dfs(file, []);
+      }
+    }
+ 
+    // Report unique cycles (limit to first 10 to avoid spam)
+    const reportedCycles = new Set<string>();
+    for (const cycle of cycles) {
+      Iif (reportedCycles.size >= 10) break;
+      const cycleKey = cycle.join(" -> ");
+      Eif (!reportedCycles.has(cycleKey)) {
+        reportedCycles.add(cycleKey);
+        violations.push({
+          type: "circular",
+          severity: "warn",
+          file: cycle[0],
+          layer: this.determineLayer(cycle[0])?.id || "unknown",
+          message: `Circular dependency detected: ${cycle.slice(0, 3).join(" -> ")}...`,
+          suggestion: "Break the circular dependency by moving code to a shared utility module",
+        });
+      }
+    }
+ 
+    return violations;
+  }
+ 
+  /**
+   * Get suggestion for placing new code.
+   *
+   * Layer selection strategy:
+   * 1. Filter to layers that can import from all dependency layer IDs.
+   *    External package names (e.g. "react", "zustand") are not layer IDs and
+   *    are skipped; they do not constrain layer selection.
+   * 2. Among eligible layers, rank by affinity with codeType to pick the
+   *    semantically best match (e.g. "service" → services/lib layer, not types).
+   */
+  getSuggestion(
+    codeName: string,
+    codeType: string,
+    dependencies: string[],
+  ): {
+    suggestedLayer: LayerDefinition;
+    suggestedPath: string;
+    reasoning: string;
+  } | null {
+    // Only use deps that are recognized layer IDs; external packages are ignored
+    const layerDeps = dependencies.filter((dep) => this.layers.has(dep));
+ 
+    // Find all layers that can import from every required layer dependency
+    const eligibleLayers: LayerDefinition[] = [];
+    for (const layer of this.layers.values()) {
+      let canImportAll = true;
+      for (const dep of layerDeps) {
+        const depLayer = this.layers.get(dep)!;
+        Iif (!this.isImportAllowed(layer, depLayer)) {
+          canImportAll = false;
+          break;
+        }
+      }
+      Eif (canImportAll) {
+        eligibleLayers.push(layer);
+      }
+    }
+ 
+    Iif (eligibleLayers.length === 0) {
+      return null;
+    }
+ 
+    // Rank eligible layers by codeType affinity (higher-priority terms first)
+    const affinityMap: Record<string, string[]> = {
+      component: ["component", "ui", "view", "page", "widget", "presentation"],
+      hook: ["hook", "custom"],
+      service: ["service", "api", "engine", "lib", "utils"],
+      context: ["context", "store", "state", "provider"],
+      utility: ["util", "lib", "common", "shared", "helper"],
+      engine: ["engine", "service", "lib"],
+      class: ["engine", "service", "lib", "model"],
+      module: ["lib", "util", "common", "shared"],
+    };
+    const affinityTerms: string[] = affinityMap[codeType] ?? [];
+ 
+    let bestLayer = eligibleLayers[0];
+    let bestScore = -1;
+    for (const layer of eligibleLayers) {
+      const layerIdLower = layer.id.toLowerCase();
+      let score = 0;
+      for (let i = 0; i < affinityTerms.length; i++) {
+        if (layerIdLower.includes(affinityTerms[i])) {
+          // Earlier terms carry higher weight
+          score = affinityTerms.length - i;
+          break;
+        }
+      }
+      if (score > bestScore) {
+        bestScore = score;
+        bestLayer = layer;
+      }
+    }
+ 
+    const suggestedPath = this.getSuggestedPath(bestLayer, codeName, codeType);
+    const importableFrom =
+      bestLayer.canImport.length > 0
+        ? bestLayer.canImport.join(", ")
+        : "no other layers (foundational layer)";
+ 
+    return {
+      suggestedLayer: bestLayer,
+      suggestedPath,
+      reasoning: `Layer '${bestLayer.name}' best matches '${codeType}' and can import from: ${importableFrom}`,
+    };
+  }
+ 
+  private getSuggestedPath(layer: LayerDefinition, codeName: string, codeType: string): string {
+    // Use first path pattern and apply naming convention
+    const basePattern = layer.paths[0];
+    const basePath = basePattern.replace("/**", "").replace(/\/\*$/, "");
+ 
+    let fileName: string;
+    Iif (codeType === "component") {
+      // Components typically use .tsx (React) — honour configured extension if it differs
+      const compExt = this.defaultExtension === ".tsx" ? ".tsx" : `${this.defaultExtension}`;
+      const hasExt = /\.[^/\\]+$/.test(codeName);
+      fileName = hasExt ? codeName : `${codeName}${compExt}`;
+    } else if (codeType === "hook") {
+      fileName = codeName.startsWith("use") ? codeName : `use${codeName}`;
+      const hasExt = /\.[^/\\]+$/.test(fileName);
+      fileName = hasExt ? fileName : `${fileName}${this.defaultExtension}`;
+    } else if (codeType === "service") {
+      const hasExt = /\.[^/\\]+$/.test(codeName);
+      Iif (hasExt) {
+        fileName = codeName;
+      } else if (codeName.endsWith("Service")) {
+        fileName = `${codeName}${this.defaultExtension}`;
+      } else {
+        fileName = `${codeName}Service${this.defaultExtension}`;
+      }
+    } else E{
+      // Default: ensure configured extension
+      const hasExt = /\.[^/\\]+$/.test(codeName);
+      fileName = hasExt ? codeName : `${codeName}${this.defaultExtension}`;
+    }
+ 
+    return `${basePath}/${fileName}`;
+  }
+ 
+  /**
+   * Write violations to Memgraph as VIOLATES_RULE relationships
+   */
+  async writeViolationsToMemgraph(
+    client: MemgraphClient,
+    violations: ValidationViolation[],
+  ): Promise<void> {
+    logger.error(`\n📝 Writing ${violations.length} violations to Memgraph...`);
+ 
+    const statements: CypherStatement[] = [];
+ 
+    // Create RULE nodes for each rule type
+    for (const rule of this.rules) {
+      statements.push({
+        query: `
+          MERGE (r:RULE {id: $ruleId})
+          SET r.severity = $severity, r.pattern = $pattern, r.description = $description
+        `,
+        params: {
+          ruleId: rule.id,
+          severity: rule.severity,
+          pattern: rule.pattern,
+          description: rule.description,
+        },
+      });
+    }
+ 
+    // Create FILE nodes and VIOLATES_RULE relationships
+    for (const violation of violations) {
+      // Resolve to absolute path to match FILE nodes created by the graph builder
+      const absoluteFilePath = path.isAbsolute(violation.file)
+        ? violation.file
+        : path.resolve(this.workspaceRoot, violation.file);
+ 
+      // Create or update FILE node
+      statements.push({
+        query: `
+          MERGE (f:FILE {path: $filePath})
+          SET f.lastViolationCheck = timestamp()
+        `,
+        params: {
+          filePath: absoluteFilePath,
+        },
+      });
+ 
+      // Create VIOLATES_RULE relationship
+      // Map violation type to rule ID for relationship
+      const ruleId = this.mapViolationTypeToRuleId(violation.type);
+      if (ruleId) {
+        statements.push({
+          query: `
+            MATCH (f:FILE {path: $filePath})
+            MERGE (r:RULE {id: $ruleId})
+            MERGE (f)-[vr:VIOLATES_RULE]->(r)
+            SET vr.severity = $severity, vr.message = $message, vr.timestamp = timestamp()
+          `,
+          params: {
+            filePath: absoluteFilePath,
+            ruleId: ruleId,
+            severity: violation.severity,
+            message: violation.message,
+          },
+        });
+      }
+    }
+ 
+    // Execute all statements in batch
+    const results = await client.executeBatch(statements);
+ 
+    // Check for errors
+    const errors = results.filter((r) => r.error);
+    if (errors.length > 0) {
+      logger.error(`⚠️  ${errors.length} Cypher statements failed:`);
+      errors.slice(0, 3).forEach((e) => logger.error(`   - ${e.error}`));
+    } else {
+      logger.error(`✅ Successfully wrote ${violations.length} violations to graph`);
+    }
+  }
+ 
+  /**
+   * Reload engine state from updated graph index
+   * Called when project context changes
+   */
+  reload(_index: GraphIndexManager, projectId?: string, workspaceRoot?: string): void {
+    logger.error(`[ArchitectureEngine] Reloading architecture validation (projectId=${projectId})`);
+    Eif (workspaceRoot) {
+      this.workspaceRoot = workspaceRoot;
+    }
+    // ArchitectureEngine doesn't hold other project-specific state in index
+    // so reload is mainly for consistency with other engines
+  }
+ 
+  /**
+   * Map violation type to a rule ID
+   */
+  private mapViolationTypeToRuleId(type: string): string | null {
+    switch (type) {
+      case "layer-violation":
+        return "no-forbidden-imports";
+      case "circular":
+        return "no-circular-dependencies";
+      case "unused":
+        return "no-unused-imports";
+      case "rule-violation":
+        return "layer-assignment";
+      default:
+        return null;
+    }
+  }
+}
+ 
+export default ArchitectureEngine;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/community-detector.ts.html b/coverage/lcov-report/src/engines/community-detector.ts.html new file mode 100644 index 0000000..8e4d7d4 --- /dev/null +++ b/coverage/lcov-report/src/engines/community-detector.ts.html @@ -0,0 +1,850 @@ + + + + + + Code coverage report for src/engines/community-detector.ts + + + + + + + + + +
+
+

All files / src/engines community-detector.ts

+
+ +
+ 96.47% + Statements + 82/85 +
+ + +
+ 79.24% + Branches + 42/53 +
+ + +
+ 94.44% + Functions + 17/18 +
+ + +
+ 98.66% + Lines + 74/75 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +141x +  +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +16x +29x +  +  +  +  +  +29x +  +16x +2x +  +  +  +14x +14x +6x +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +14x +  +  +14x +  +  +  +  +  +  +  +  +14x +8x +  +  +  +6x +6x +12x +12x +12x +12x +  +  +  +6x +  +  +6x +6x +13x +13x +12x +12x +  +  +6x +6x +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +8x +16x +16x +16x +  +  +  +8x +8x +8x +12x +12x +  +  +8x +8x +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +14x +20x +20x +20x +20x +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +28x +  +  +  +  +  +  +  +  +  +  +  +  +28x +20x +28x +20x +  +  +  +44x +  +  +  +44x +  +  +  +  +  +  +  +  +58x +44x +40x +  +40x +  +  +4x +4x +4x +  +  +  +28x +20x +  +  +  +20x +20x +28x +  +20x +1x +21x +  +  +20x +  +  + 
/**
+ * @file engines/community-detector
+ * @description Builds code communities from graph relationships for higher-level context retrieval.
+ * @remarks Persists detected communities in Memgraph for query-time use.
+ */
+ 
+import type MemgraphClient from "../graph/client.js";
+import { logger } from "../utils/logger.js";
+ 
+interface CommunityMember {
+  id: string;
+  filePath: string;
+  name: string;
+  type: string;
+  communityId?: number;
+}
+ 
+type DetectionMode = "mage_leiden" | "directory_heuristic";
+ 
+export interface CommunityRunResult {
+  communities: number;
+  members: number;
+  mode: DetectionMode;
+}
+ 
+export default class CommunityDetector {
+  constructor(private memgraph: MemgraphClient) {}
+ 
+  async run(projectId: string): Promise<CommunityRunResult> {
+    // --- Fetch member nodes -------------------------------------------
+    const nodeResult = await this.memgraph.executeCypher(
+      `MATCH (n)
+       WHERE n.projectId = $projectId
+         AND (n:FILE OR n:FUNCTION OR n:CLASS)
+       OPTIONAL MATCH (parentFile:FILE)-[:CONTAINS]->(n)
+       RETURN n.id AS id,
+              labels(n)[0] AS type,
+              coalesce(n.path, n.filePath, parentFile.path, '') AS filePath,
+              coalesce(n.name, n.id) AS name`,
+      { projectId },
+    );
+ 
+    const members: CommunityMember[] = (nodeResult.data || [])
+      .map((row) => ({
+        id: String(row.id || ""),
+        filePath: String(row.filePath || ""),
+        name: String(row.name || row.id || ""),
+        type: String(row.type || "UNKNOWN"),
+      }))
+      .filter((row) => row.id.length > 0);
+ 
+    if (!members.length) {
+      return { communities: 0, members: 0, mode: "directory_heuristic" };
+    }
+ 
+    // --- Try MAGE Leiden community_detection.get() --------------------
+    const mageResult = await this.tryMageCommunityDetection(projectId, members);
+    if (mageResult) {
+      return mageResult;
+    }
+ 
+    // --- Fallback: directory-grouping heuristic -----------------------
+    return this.runDirectoryHeuristic(projectId, members);
+  }
+ 
+  /**
+   * Attempt native MAGE Leiden algorithm.
+   * Returns null if MAGE is not available or the query fails.
+   */
+  private async tryMageCommunityDetection(
+    projectId: string,
+    members: CommunityMember[],
+  ): Promise<CommunityRunResult | null> {
+    try {
+      // community_detection.get() runs on the full in-memory graph.
+      // We filter to only the nodes belonging to this project.
+      const response = await this.memgraph.executeCypher(
+        `CALL community_detection.get()
+         YIELD node, community_id
+         WHERE node.projectId = $projectId
+           AND (node:FILE OR node:FUNCTION OR node:CLASS)
+         RETURN toString(node.id) AS nodeId, toInteger(community_id) AS cid`,
+        { projectId },
+      );
+ 
+      if (response.error || !Array.isArray(response.data) || response.data.length === 0) {
+        return null;
+      }
+ 
+      // Build nodeId → community_id map
+      const communityMap = new Map<string, number>();
+      for (const row of response.data) {
+        const nodeId = String(row.nodeId || "");
+        const cid = Number(row.cid ?? -1);
+        Eif (nodeId && cid >= 0) {
+          communityMap.set(nodeId, cid);
+        }
+      }
+ 
+      Iif (communityMap.size === 0) return null;
+ 
+      // Group members by Leiden community id
+      const grouped = new Map<number, CommunityMember[]>();
+      for (const member of members) {
+        const cid = communityMap.get(member.id);
+        if (cid === undefined) continue;
+        if (!grouped.has(cid)) grouped.set(cid, []);
+        grouped.get(cid)!.push({ ...member, communityId: cid });
+      }
+ 
+      await this.writeCommunities(projectId, grouped, "leiden");
+      logger.error(
+        `[community] MAGE Leiden: ${grouped.size} communities across ${communityMap.size} member node(s) for project ${projectId}`,
+      );
+      return {
+        communities: grouped.size,
+        members: communityMap.size,
+        mode: "mage_leiden",
+      };
+    } catch {
+      // MAGE module not installed or unsupported Memgraph edition — fall through
+      return null;
+    }
+  }
+ 
+  /**
+   * Directory-grouping heuristic (always-available fallback).
+   */
+  private async runDirectoryHeuristic(
+    projectId: string,
+    members: CommunityMember[],
+  ): Promise<CommunityRunResult> {
+    const grouped = new Map<string, CommunityMember[]>();
+    for (const member of members) {
+      const label = this.communityLabel(member.filePath);
+      if (!grouped.has(label)) grouped.set(label, []);
+      grouped.get(label)!.push(member);
+    }
+ 
+    // Convert string labels to numeric-keyed map for writeCommunities
+    const numericGrouped = new Map<number, CommunityMember[]>();
+    let idx = 0;
+    for (const [, group] of grouped.entries()) {
+      numericGrouped.set(idx, group);
+      idx += 1;
+    }
+ 
+    await this.writeCommunities(projectId, numericGrouped, "dir");
+    logger.error(
+      `[community] directory heuristic: ${grouped.size} communities across ${members.length} member node(s) for project ${projectId}`,
+    );
+    return {
+      communities: grouped.size,
+      members: members.length,
+      mode: "directory_heuristic",
+    };
+  }
+ 
+  /**
+   * Write COMMUNITY nodes and BELONGS_TO edges for a set of computed groups.
+   */
+  private async writeCommunities(
+    projectId: string,
+    grouped: Map<number, CommunityMember[]>,
+    prefix: string,
+  ): Promise<void> {
+    for (const [cid, group] of grouped.entries()) {
+      const communityId = `${projectId}::community::${prefix}::${cid}`;
+      const label = this.labelForGroup(group);
+      const summary = this.buildSummary(label, group);
+      const centralNode = this.centralNode(group);
+ 
+      await this.memgraph.executeCypher(
+        `MERGE (c:COMMUNITY {id: $id, projectId: $projectId})
+         SET c.label = $label,
+             c.summary = $summary,
+             c.memberCount = $memberCount,
+             c.size = $memberCount,
+             c.centralNode = $centralNode,
+             c.computedAt = $computedAt`,
+        {
+          id: communityId,
+          projectId,
+          label,
+          summary,
+          memberCount: group.length,
+          centralNode,
+          computedAt: Date.now(),
+        },
+      );
+ 
+      for (const member of group) {
+        await this.memgraph.executeCypher(
+          `MATCH (n {id: $nodeId, projectId: $projectId})
+           MATCH (c:COMMUNITY {id: $communityId, projectId: $projectId})
+           SET n.communityId = $communityId
+           MERGE (n)-[:BELONGS_TO]->(c)`,
+          { nodeId: member.id, projectId, communityId },
+        );
+      }
+    }
+  }
+ 
+  private labelForGroup(group: CommunityMember[]): string {
+    // For Leiden groups, infer a label from the most common path prefix
+    const prefixes = group.map((m) => this.communityLabel(m.filePath));
+    const freq = new Map<string, number>();
+    for (const p of prefixes) freq.set(p, (freq.get(p) || 0) + 1);
+    return [...freq.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] ?? "misc";
+  }
+ 
+  private communityLabel(filePath: string): string {
+    const segments = filePath.split("/").filter(Boolean);
+    // Look for a well-known source-root marker and return the directory that follows it.
+    // This correctly handles absolute paths like /home/user/project/src/engines/foo.ts
+    // by returning "engines" instead of "home".
+    const sourceRoots = new Set([
+      "src",
+      "lib",
+      "app",
+      "pages",
+      "packages",
+      "components",
+      "services",
+    ]);
+    const rootIdx = segments.findIndex((s) => sourceRoots.has(s));
+    if (rootIdx >= 0 && rootIdx + 1 < segments.length) {
+      const next = segments[rootIdx + 1];
+      // If next segment is a filename (has extension), use the root marker itself
+      return next.includes(".") ? segments[rootIdx] : next;
+    }
+    // Fallback: use the last non-trivial directory segment before the filename
+    const dirSegments = segments.slice(0, -1);
+    const trivial = new Set(["home", "root", "usr", "var", "tmp", "opt"]);
+    return dirSegments.filter((s) => !trivial.has(s)).pop() || "misc";
+  }
+ 
+  private centralNode(group: CommunityMember[]): string {
+    const withFunctionBias = group.find((item) => item.type === "FUNCTION");
+    return withFunctionBias?.id || group[0]?.id || "";
+  }
+ 
+  private buildSummary(label: string, members: CommunityMember[]): string {
+    const types = new Map<string, number>();
+    for (const member of members) {
+      types.set(member.type, (types.get(member.type) || 0) + 1);
+    }
+    const profile = [...types.entries()]
+      .sort((a, b) => b[1] - a[1])
+      .map(([type, count]) => `${count} ${type.toLowerCase()} node(s)`)
+      .slice(0, 3)
+      .join(", ");
+    return `Community '${label}' groups ${members.length} code node(s): ${profile}.`;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/coordination-engine.ts.html b/coverage/lcov-report/src/engines/coordination-engine.ts.html new file mode 100644 index 0000000..1865137 --- /dev/null +++ b/coverage/lcov-report/src/engines/coordination-engine.ts.html @@ -0,0 +1,823 @@ + + + + + + Code coverage report for src/engines/coordination-engine.ts + + + + + + + + + +
+
+

All files / src/engines coordination-engine.ts

+
+ +
+ 95.91% + Statements + 47/49 +
+ + +
+ 56.06% + Branches + 37/66 +
+ + +
+ 100% + Functions + 19/19 +
+ + +
+ 95.91% + Lines + 47/49 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +145x +  +  +  +  +3x +  +  +  +  +  +3x +3x +1x +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +1x +  +  +3x +3x +1x +  +  +2x +  +  +  +  +  +2x +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +3x +2x +2x +  +3x +  +  +1x +  +  +  +  +  +  +2x +  +  +  +  +  +8x +  +  +  +  +  +  +  +8x +  +2x +2x +  +2x +2x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +2x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +  +  +  +  +2x +  +  +  +  +  +  +  +  +2x +  +  +  +  +2x +2x +  +  +  +  +2x +  +2x +  +  +  +  +  + 
/**
+ * @file engines/coordination-engine
+ * @description Manages agent claim lifecycle, conflict detection, and fleet coordination state.
+ * @remarks Uses extracted query/constants and pure utilities for maintainability.
+ */
+ 
+import type MemgraphClient from "../graph/client.js";
+import { CoordinationQueries as Q } from "./coordination-queries.js";
+import { makeClaimId, rowToClaim } from "./coordination-utils.js";
+ 
+// Re-export all public types so existing importers keep working.
+export type {
+  AgentClaim,
+  AgentStatus,
+  ClaimInput,
+  ClaimResult,
+  ClaimType,
+  CoordinationOverview,
+  InvalidationReason,
+  ReleaseFeedback,
+} from "./coordination-types.js";
+ 
+import type {
+  AgentClaim,
+  AgentStatus,
+  ClaimInput,
+  ClaimResult,
+  CoordinationOverview,
+  ReleaseFeedback,
+} from "./coordination-types.js";
+ 
+export default class CoordinationEngine {
+  constructor(private memgraph: MemgraphClient) {}
+ 
+  // ── Public API ─────────────────────────────────────────────────────────────
+ 
+  async claim(input: ClaimInput): Promise<ClaimResult> {
+    const conflictCheck = await this.memgraph.executeCypher(Q.CONFLICT_CHECK, {
+      targetId: input.targetId,
+      projectId: input.projectId,
+      agentId: input.agentId,
+    });
+ 
+    const conflict = conflictCheck.data?.[0];
+    if (conflict) {
+      return {
+        claimId: "",
+        status: "CONFLICT",
+        conflict: {
+          agentId: String(conflict.agentId || "unknown"),
+          intent: String(conflict.intent || ""),
+          since: Number(conflict.since || Date.now()),
+        },
+        targetVersionSHA: "unknown",
+      };
+    }
+ 
+    const now = Date.now();
+    const claimId = makeClaimId("claim", now);
+    const targetSnapshot = await this.getTargetSnapshot(input.targetId, input.projectId);
+ 
+    await this.memgraph.executeCypher(Q.CREATE_CLAIM, {
+      id: claimId,
+      agentId: input.agentId,
+      sessionId: input.sessionId,
+      taskId: input.taskId || null,
+      claimType: input.claimType,
+      targetId: input.targetId,
+      intent: input.intent,
+      validFrom: now,
+      targetVersionSHA: targetSnapshot.targetVersionSHA,
+      projectId: input.projectId,
+    });
+ 
+    Iif (targetSnapshot.targetExists) {
+      await this.memgraph.executeCypher(Q.LINK_CLAIM_TO_TARGET, {
+        claimId,
+        targetId: input.targetId,
+        projectId: input.projectId,
+      });
+    }
+ 
+    return {
+      claimId,
+      status: "ok",
+      targetVersionSHA: targetSnapshot.targetVersionSHA,
+    };
+  }
+ 
+  /**
+   * Close a claim.  Returns feedback indicating whether the claim was found
+   * and whether it was already closed before this call — instead of silently
+   * returning void.
+   */
+  async release(claimId: string, outcome?: string): Promise<ReleaseFeedback> {
+    // First check current state so we can give accurate feedback.
+    const checkResult = await this.memgraph.executeCypher(Q.RELEASE_CLAIM_OPEN_CHECK, { claimId });
+ 
+    if (!checkResult.data.length) {
+      return { found: false, alreadyClosed: false };
+    }
+ 
+    const row = checkResult.data[0] as Record<string, unknown>;
+    if (row.validTo != null) {
+      return { found: true, alreadyClosed: true };
+    }
+ 
+    await this.memgraph.executeCypher(Q.RELEASE_CLAIM, {
+      claimId,
+      now: Date.now(),
+      outcome: outcome ?? null,
+    });
+ 
+    return { found: true, alreadyClosed: false };
+  }
+ 
+  async status(agentId: string, projectId: string): Promise<AgentStatus> {
+    const [claimsResult, episodesResult] = await Promise.all([
+      this.memgraph.executeCypher(Q.AGENT_ACTIVE_CLAIMS, {
+        projectId,
+        agentId,
+      }),
+      this.memgraph.executeCypher(Q.AGENT_RECENT_EPISODES, {
+        projectId,
+        agentId,
+      }),
+    ]);
+ 
+    const activeClaims = claimsResult.data
+      .map((row) => rowToClaim(row))
+      .filter((row): row is AgentClaim => Boolean(row));
+ 
+    return {
+      agentId,
+      activeClaims,
+      recentEpisodes: episodesResult.data.map((row) => ({
+        id: String(row.id),
+        type: String(row.type || "OBSERVATION"),
+        content: String(row.content || ""),
+        timestamp: Number(row.timestamp || Date.now()),
+        taskId: row.taskId ? String(row.taskId) : undefined,
+      })),
+      currentTask: activeClaims.find((claim) => Boolean(claim.taskId))?.taskId,
+    };
+  }
+ 
+  async overview(projectId: string): Promise<CoordinationOverview> {
+    const [activeResult, staleResult, conflictsResult, summaryResult, totalResult] =
+      await Promise.all([
+        this.memgraph.executeCypher(Q.OVERVIEW_ACTIVE, { projectId }),
+        this.memgraph.executeCypher(Q.OVERVIEW_STALE, { projectId }),
+        this.memgraph.executeCypher(Q.OVERVIEW_CONFLICTS, { projectId }),
+        this.memgraph.executeCypher(Q.OVERVIEW_AGENT_SUMMARY, { projectId }),
+        this.memgraph.executeCypher(Q.OVERVIEW_TOTAL, { projectId }),
+      ]);
+ 
+    return {
+      activeClaims: activeResult.data
+        .map((row) => rowToClaim(row))
+        .filter((row): row is AgentClaim => Boolean(row)),
+      staleClaims: staleResult.data
+        .map((row) => rowToClaim(row))
+        .filter((row): row is AgentClaim => Boolean(row)),
+      conflicts: conflictsResult.data.map((row) => ({
+        targetId: String(row.targetId || "unknown"),
+        claimA: {
+          claimId: String(row.claimAId || ""),
+          agentId: String(row.claimAAgent || "unknown"),
+          intent: String(row.claimAIntent || ""),
+          since: Number(row.claimASince || Date.now()),
+        },
+        claimB: {
+          claimId: String(row.claimBId || ""),
+          agentId: String(row.claimBAgent || "unknown"),
+          intent: String(row.claimBIntent || ""),
+          since: Number(row.claimBSince || Date.now()),
+        },
+      })),
+      agentSummary: summaryResult.data.map((row) => ({
+        agentId: String(row.agentId || "unknown"),
+        claimCount: Number(row.claimCount || 0),
+        lastSeen: Number(row.lastSeen || Date.now()),
+      })),
+      totalClaims: Number(totalResult.data?.[0]?.totalClaims || 0),
+    };
+  }
+ 
+  async invalidateStaleClaims(projectId: string): Promise<number> {
+    const now = Date.now();
+    const staleResult = await this.memgraph.executeCypher(Q.INVALIDATE_STALE, {
+      projectId,
+      now,
+    });
+    return Number(staleResult.data?.[0]?.invalidated || 0);
+  }
+ 
+  async onTaskCompleted(taskId: string, agentId: string, projectId: string): Promise<void> {
+    await this.memgraph.executeCypher(Q.ON_TASK_COMPLETED, {
+      projectId,
+      taskId,
+      now: Date.now(),
+      outcome: `Task completed by ${agentId}`,
+    });
+  }
+ 
+  /**
+   * Expire all open claims older than `maxAgeMs` milliseconds.
+   * Implements the previously orphaned 'expired' InvalidationReason.
+   * @returns number of claims closed
+   */
+  async expireOldClaims(projectId: string, maxAgeMs: number): Promise<number> {
+    const now = Date.now();
+    const cutoffMs = now - maxAgeMs;
+    const result = await this.memgraph.executeCypher(Q.EXPIRE_OLD_CLAIMS, {
+      projectId,
+      now,
+      cutoffMs,
+    });
+    return Number(result.data?.[0]?.expired || 0);
+  }
+ 
+  // ── Private helpers ────────────────────────────────────────────────────────
+ 
+  private async getTargetSnapshot(
+    targetId: string,
+    projectId: string,
+  ): Promise<{ targetExists: boolean; targetVersionSHA: string }> {
+    const result = await this.memgraph.executeCypher(Q.TARGET_SNAPSHOT, {
+      targetId,
+      projectId,
+    });
+ 
+    Eif (!result.data.length) {
+      return { targetExists: false, targetVersionSHA: `unknown-${Date.now()}` };
+    }
+ 
+    const row = result.data[0] || {};
+    const sha =
+      row.contentHash || row.hash || row.gitCommit || `vf-${String(row.validFrom || Date.now())}`;
+ 
+    return {
+      targetExists: true,
+      targetVersionSHA: String(sha),
+    };
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/coordination-queries.ts.html b/coverage/lcov-report/src/engines/coordination-queries.ts.html new file mode 100644 index 0000000..267c807 --- /dev/null +++ b/coverage/lcov-report/src/engines/coordination-queries.ts.html @@ -0,0 +1,568 @@ + + + + + + Code coverage report for src/engines/coordination-queries.ts + + + + + + + + + +
+
+

All files / src/engines coordination-queries.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file engines/coordination-queries
+ * @description Shared Cypher query constants consumed by the coordination engine.
+ * @remarks Isolating queries improves readability, testability, and optimization review.
+ */
+ 
+export const CoordinationQueries = {
+  /** Check for an active conflicting claim on the same target from a *different* agent */
+  CONFLICT_CHECK: `
+    MATCH (c:CLAIM)-[:TARGETS]->(t {id: $targetId, projectId: $projectId})
+    WHERE c.validTo IS NULL
+      AND c.agentId <> $agentId
+    RETURN c.id AS claimId, c.agentId AS agentId, c.intent AS intent, c.validFrom AS since
+    ORDER BY c.validFrom DESC
+    LIMIT 1`,
+ 
+  /** Look up snapshot info (hash/commit) for a target node */
+  TARGET_SNAPSHOT: `
+    MATCH (t {id: $targetId, projectId: $projectId})
+    RETURN t.validFrom AS validFrom,
+           t.contentHash AS contentHash,
+           t.hash AS hash,
+           t.gitCommit AS gitCommit
+    ORDER BY t.validFrom DESC
+    LIMIT 1`,
+ 
+  /** Create a new CLAIM node */
+  CREATE_CLAIM: `
+    CREATE (c:CLAIM {
+      id: $id,
+      agentId: $agentId,
+      sessionId: $sessionId,
+      taskId: $taskId,
+      claimType: $claimType,
+      targetId: $targetId,
+      intent: $intent,
+      validFrom: $validFrom,
+      targetVersionSHA: $targetVersionSHA,
+      validTo: null,
+      invalidationReason: null,
+      outcome: null,
+      projectId: $projectId
+    })`,
+ 
+  /** Create TARGETS edge from a claim to its target node */
+  LINK_CLAIM_TO_TARGET: `
+    MATCH (c:CLAIM {id: $claimId, projectId: $projectId})
+    MATCH (t {id: $targetId, projectId: $projectId})
+    MERGE (c)-[:TARGETS]->(t)`,
+ 
+  /** Close (release) a claim — checks it is still open first */
+  RELEASE_CLAIM_OPEN_CHECK: `
+    MATCH (c:CLAIM {id: $claimId})
+    RETURN c.validTo AS validTo, c.id AS id`,
+ 
+  /** Actually close the claim */
+  RELEASE_CLAIM: `
+    MATCH (c:CLAIM {id: $claimId})
+    WHERE c.validTo IS NULL
+    SET c.validTo = $now,
+        c.invalidationReason = 'released',
+        c.outcome = $outcome`,
+ 
+  /** Active claims for a single agent */
+  AGENT_ACTIVE_CLAIMS: `
+    MATCH (c:CLAIM)
+    WHERE c.projectId = $projectId
+      AND c.agentId = $agentId
+      AND c.validTo IS NULL
+    RETURN c
+    ORDER BY c.validFrom DESC`,
+ 
+  /** Recent episodes for a single agent */
+  AGENT_RECENT_EPISODES: `
+    MATCH (e:EPISODE)
+    WHERE e.projectId = $projectId
+      AND e.agentId = $agentId
+    RETURN e.id AS id, e.type AS type, e.content AS content,
+           e.timestamp AS timestamp, e.taskId AS taskId
+    ORDER BY e.timestamp DESC
+    LIMIT 10`,
+ 
+  /** All active claims in a project */
+  OVERVIEW_ACTIVE: `
+    MATCH (c:CLAIM)
+    WHERE c.projectId = $projectId
+      AND c.validTo IS NULL
+    RETURN c
+    ORDER BY c.validFrom DESC`,
+ 
+  /** Stale claims — target node has been updated since the claim was created */
+  OVERVIEW_STALE: `
+    MATCH (c:CLAIM)-[:TARGETS]->(t)
+    WHERE c.projectId = $projectId
+      AND c.validTo IS NULL
+      AND t.projectId = $projectId
+      AND t.validFrom > c.validFrom
+    RETURN c
+    ORDER BY c.validFrom DESC`,
+ 
+  /** Conflicting claim pairs — two open claims on the same target from different agents */
+  OVERVIEW_CONFLICTS: `
+    MATCH (c1:CLAIM)-[:TARGETS]->(t)<-[:TARGETS]-(c2:CLAIM)
+    WHERE c1.projectId = $projectId
+      AND c2.projectId = $projectId
+      AND c1.validTo IS NULL
+      AND c2.validTo IS NULL
+      AND c1.id < c2.id
+      AND c1.agentId <> c2.agentId
+    RETURN t.id AS targetId,
+           c1.id AS claimAId, c1.agentId AS claimAAgent, c1.intent AS claimAIntent, c1.validFrom AS claimASince,
+           c2.id AS claimBId, c2.agentId AS claimBAgent, c2.intent AS claimBIntent, c2.validFrom AS claimBSince
+    ORDER BY targetId`,
+ 
+  /** Agent-level summary (claim counts + last seen) */
+  OVERVIEW_AGENT_SUMMARY: `
+    MATCH (c:CLAIM)
+    WHERE c.projectId = $projectId
+      AND c.validTo IS NULL
+    RETURN c.agentId AS agentId,
+           count(c) AS claimCount,
+           max(c.validFrom) AS lastSeen
+    ORDER BY claimCount DESC, lastSeen DESC`,
+ 
+  /** Total claim count for a project */
+  OVERVIEW_TOTAL: `
+    MATCH (c:CLAIM)
+    WHERE c.projectId = $projectId
+    RETURN count(c) AS totalClaims`,
+ 
+  /** Invalidate stale claims whose target node has been updated */
+  INVALIDATE_STALE: `
+    MATCH (c:CLAIM)-[:TARGETS]->(t)
+    WHERE c.projectId = $projectId
+      AND c.validTo IS NULL
+      AND t.projectId = $projectId
+      AND t.validFrom > c.validFrom
+    SET c.validTo = $now,
+        c.invalidationReason = 'code_changed'
+    RETURN count(c) AS invalidated`,
+ 
+  /** Close all open claims for a completed task */
+  ON_TASK_COMPLETED: `
+    MATCH (c:CLAIM)
+    WHERE c.projectId = $projectId
+      AND c.taskId = $taskId
+      AND c.validTo IS NULL
+    SET c.validTo = $now,
+        c.invalidationReason = 'task_completed',
+        c.outcome = coalesce(c.outcome, $outcome)`,
+ 
+  /** Expire claims older than a given timestamp (TTL enforcement) */
+  EXPIRE_OLD_CLAIMS: `
+    MATCH (c:CLAIM)
+    WHERE c.projectId = $projectId
+      AND c.validTo IS NULL
+      AND c.validFrom < $cutoffMs
+    SET c.validTo = $now,
+        c.invalidationReason = 'expired'
+    RETURN count(c) AS expired`,
+} as const;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/coordination-types.ts.html b/coverage/lcov-report/src/engines/coordination-types.ts.html new file mode 100644 index 0000000..08d27ec --- /dev/null +++ b/coverage/lcov-report/src/engines/coordination-types.ts.html @@ -0,0 +1,322 @@ + + + + + + Code coverage report for src/engines/coordination-types.ts + + + + + + + + + +
+
+

All files / src/engines coordination-types.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file engines/coordination-types
+ * @description Public type contracts for coordination workflows.
+ * @remarks Kept separate so callers can import types without importing engine runtime code.
+ */
+ 
+export type ClaimType = "task" | "file" | "function" | "feature";
+ 
+export type InvalidationReason = "released" | "code_changed" | "task_completed" | "expired";
+ 
+export interface AgentClaim {
+  id: string;
+  agentId: string;
+  sessionId: string;
+  taskId?: string;
+  claimType: ClaimType;
+  targetId: string;
+  intent: string;
+  validFrom: number;
+  targetVersionSHA?: string;
+  validTo: number | null;
+  invalidationReason?: InvalidationReason;
+  outcome?: string;
+  projectId: string;
+}
+ 
+export interface ClaimInput {
+  agentId: string;
+  sessionId: string;
+  projectId: string;
+  targetId: string;
+  claimType: ClaimType;
+  intent: string;
+  taskId?: string;
+}
+ 
+export interface ClaimResult {
+  claimId: string;
+  status: "ok" | "CONFLICT";
+  conflict?: { agentId: string; intent: string; since: number };
+  targetVersionSHA: string;
+}
+ 
+/** Typed result for the release() method — replaces the original void return. */
+export interface ReleaseFeedback {
+  /** true if the claim existed and was open when release was called */
+  found: boolean;
+  /** true if the claim existed but was already closed before this call */
+  alreadyClosed: boolean;
+}
+ 
+export interface AgentStatus {
+  agentId: string;
+  activeClaims: AgentClaim[];
+  recentEpisodes: Array<{
+    id: string;
+    type: string;
+    content: string;
+    timestamp: number;
+    taskId?: string;
+  }>;
+  currentTask?: string;
+}
+ 
+export interface CoordinationOverview {
+  activeClaims: AgentClaim[];
+  staleClaims: AgentClaim[];
+  conflicts: Array<{
+    targetId: string;
+    claimA: { claimId: string; agentId: string; intent: string; since: number };
+    claimB: { claimId: string; agentId: string; intent: string; since: number };
+  }>;
+  agentSummary: Array<{
+    agentId: string;
+    claimCount: number;
+    lastSeen: number;
+  }>;
+  totalClaims: number;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/coordination-utils.ts.html b/coverage/lcov-report/src/engines/coordination-utils.ts.html new file mode 100644 index 0000000..b21dd31 --- /dev/null +++ b/coverage/lcov-report/src/engines/coordination-utils.ts.html @@ -0,0 +1,226 @@ + + + + + + Code coverage report for src/engines/coordination-utils.ts + + + + + + + + + +
+
+

All files / src/engines coordination-utils.ts

+
+ +
+ 100% + Statements + 5/5 +
+ + +
+ 90.9% + Branches + 30/33 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 5/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +11x +2x +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  + 
/**
+ * @file engines/coordination-utils
+ * @description Pure helper functions for coordination IDs, mapping, and normalization.
+ * @remarks Utility functions are side-effect free and independently testable.
+ */
+ 
+import type { AgentClaim, ClaimType, InvalidationReason } from "./coordination-types.js";
+ 
+/**
+ * Maps a raw Memgraph row (or the nested `c` property) to an AgentClaim.
+ * Returns null if the row lacks a required `id` field.
+ */
+export function rowToClaim(row: Record<string, unknown>): AgentClaim | null {
+  const claim = (row.c as Record<string, unknown>) || (row.claim as Record<string, unknown>) || row;
+ 
+  if (!claim || typeof claim !== "object" || !claim.id) {
+    return null;
+  }
+ 
+  return {
+    id: String(claim.id),
+    agentId: String(claim.agentId ?? "unknown"),
+    sessionId: String(claim.sessionId ?? "unknown"),
+    taskId: claim.taskId ? String(claim.taskId) : undefined,
+    claimType: (claim.claimType ?? "task") as ClaimType,
+    targetId: String(claim.targetId ?? ""),
+    intent: String(claim.intent ?? ""),
+    validFrom: Number(claim.validFrom ?? Date.now()),
+    targetVersionSHA: claim.targetVersionSHA ? String(claim.targetVersionSHA) : undefined,
+    validTo: claim.validTo == null ? null : Number(claim.validTo),
+    invalidationReason: claim.invalidationReason
+      ? (String(claim.invalidationReason) as InvalidationReason)
+      : undefined,
+    outcome: claim.outcome ? String(claim.outcome) : undefined,
+    projectId: String(claim.projectId ?? "unknown"),
+  };
+}
+ 
+/**
+ * Generate a time-prefixed pseudo-unique ID.
+ * @param prefix  e.g. "claim"
+ * @param now     injectable timestamp (ms) — defaults to Date.now(); pass a
+ *                fixed value in tests to get deterministic IDs.
+ */
+export function makeClaimId(prefix: string, now: number = Date.now()): string {
+  return `${prefix}-${now}-${Math.random().toString(36).slice(2, 10)}`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/docs-engine.ts.html b/coverage/lcov-report/src/engines/docs-engine.ts.html new file mode 100644 index 0000000..f1a9e33 --- /dev/null +++ b/coverage/lcov-report/src/engines/docs-engine.ts.html @@ -0,0 +1,1225 @@ + + + + + + Code coverage report for src/engines/docs-engine.ts + + + + + + + + + +
+
+

All files / src/engines docs-engine.ts

+
+ +
+ 94.23% + Statements + 98/104 +
+ + +
+ 78.94% + Branches + 60/76 +
+ + +
+ 100% + Functions + 23/23 +
+ + +
+ 96.62% + Lines + 86/89 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +144x +144x +144x +144x +  +  +21x +21x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +9x +  +  +9x +9x +  +9x +9x +  +  +  +  +  +  +  +9x +  +  +  +9x +27x +27x +  +  +27x +3x +3x +  +  +  +24x +24x +24x +24x +3x +  +  +  +3x +  +  +  +21x +3x +3x +3x +  +  +  +  +  +  +  +  +  +21x +  +  +  +  +  +  +  +  +9x +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +5x +  +  +8x +  +5x +  +  +4x +4x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +1x +  +  +  +  +  +8x +  +  +  +  +8x +8x +8x +  +  +  +3x +3x +  +  +  +8x +  +  +  +  +  +  +  +4x +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +2x +  +  +  +  +  +  +  +  +  +  +  +2x +3x +  +2x +2x +3x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +21x +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +24x +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +24x +24x +441x +441x +  +24x +  +  +  +  +  +  +  +  +24x +24x +24x +379x +379x +2235x +  +379x +379x +  +  +9216x +9216x +  +  + 
/**
+ * @file engines/docs-engine
+ * @description Indexes markdown docs into graph sections and supports documentation search.
+ * @remarks Supports incremental hashing and optional Qdrant embeddings.
+ */
+ 
+import type { MemgraphClient } from "../graph/client.js";
+import type { QdrantClient, VectorPoint } from "../vector/qdrant-client.js";
+import { DocsBuilder } from "../graph/docs-builder.js";
+import { DocsParser, findMarkdownFiles } from "../parsers/docs-parser.js";
+import type { ParsedDoc } from "../parsers/docs-parser.js";
+import { logger } from "../utils/logger.js";
+ 
+// ─── Public types ─────────────────────────────────────────────────────────────
+ 
+export interface DocsIndexOptions {
+  /** Skip files whose stored hash matches current file hash (default: true) */
+  incremental?: boolean;
+  /** If true, also embed section content into Qdrant (default: false) */
+  withEmbeddings?: boolean;
+  txId?: string;
+}
+ 
+export interface DocsIndexResult {
+  indexed: number;
+  skipped: number;
+  errors: Array<{ file: string; error: string }>;
+  durationMs: number;
+}
+ 
+export interface DocsSearchOptions {
+  limit?: number;
+}
+ 
+export interface DocsSearchResult {
+  sectionId: string;
+  heading: string;
+  docRelativePath: string;
+  kind: string;
+  content: string;
+  score: number;
+  startLine: number;
+}
+ 
+export interface DocsEngineOptions {
+  qdrant?: QdrantClient;
+  /** Override parser (useful in tests) */
+  parser?: DocsParser;
+  /** Override builder factory (useful in tests) */
+  buildCypher?: (
+    doc: ParsedDoc,
+    projectId: string,
+    txId: string,
+  ) => ReturnType<DocsBuilder["buildFromParsedDoc"]>;
+}
+ 
+export const DOCS_COLLECTION = "document_sections";
+export const DOCS_VECTOR_SIZE = 384; // MiniLM-L6 dimension
+ 
+// ─── DocsEngine ───────────────────────────────────────────────────────────────
+ 
+export class DocsEngine {
+  private readonly memgraph: MemgraphClient;
+  private readonly qdrant?: QdrantClient;
+  private readonly parser: DocsParser;
+  private readonly buildCypher: (
+    doc: ParsedDoc,
+    projectId: string,
+    txId: string,
+  ) => ReturnType<DocsBuilder["buildFromParsedDoc"]>;
+ 
+  constructor(memgraph: MemgraphClient, opts: DocsEngineOptions = {}) {
+    this.memgraph = memgraph;
+    this.qdrant = opts.qdrant;
+    this.parser = opts.parser ?? new DocsParser();
+    this.buildCypher =
+      opts.buildCypher ??
+      ((doc, projectId, txId) => {
+        const builder = new DocsBuilder(projectId, undefined, txId, Date.now());
+        return builder.buildFromParsedDoc(doc);
+      });
+  }
+ 
+  // ── Indexing ─────────────────────────────────────────────────────────────────
+ 
+  /**
+   * Discover all markdown files under workspaceRoot, parse them, and upsert
+   * DOCUMENT + SECTION nodes into the graph.  Skips files whose hash has not
+   * changed since the last run (incremental mode, default: on).
+   */
+  async indexWorkspace(
+    workspaceRoot: string,
+    projectId: string,
+    opts: DocsIndexOptions = {},
+  ): Promise<DocsIndexResult> {
+    const t0 = Date.now();
+    const incremental = opts.incremental ?? true;
+    // withEmbeddings defaults to false — callers that want Qdrant embedding must opt in explicitly.
+    // (The orchestrator path does not supply a Qdrant client and must not attempt to embed.)
+    const withEmbeddings = opts.withEmbeddings ?? false;
+    const txId = opts.txId ?? `doc-tx-${Date.now()}`;
+ 
+    const files = findMarkdownFiles(workspaceRoot);
+    const result: DocsIndexResult = {
+      indexed: 0,
+      skipped: 0,
+      errors: [],
+      durationMs: 0,
+    };
+ 
+    // Fetch existing hashes in bulk for incremental check
+    const existingHashes = incremental
+      ? await this.fetchExistingHashes(projectId)
+      : new Map<string, string>();
+ 
+    for (const filePath of files) {
+      try {
+        const doc = this.parser.parseFile(filePath, workspaceRoot);
+ 
+        // Incremental: skip when hash unchanged
+        if (incremental && existingHashes.get(doc.relativePath) === doc.hash) {
+          result.skipped++;
+          continue;
+        }
+ 
+        // Write graph nodes
+        const stmts = this.buildCypher(doc, projectId, txId);
+        const results = await this.memgraph.executeBatch(stmts);
+        const firstError = results.find((r) => r.error);
+        if (firstError) {
+          result.errors.push({
+            file: filePath,
+            error: `Memgraph error: ${firstError.error}`,
+          });
+          continue;
+        }
+ 
+        // Phase 3.2: Embed sections into Qdrant
+        if (withEmbeddings && this.qdrant?.isConnected()) {
+          try {
+            await this.embedDoc(doc, projectId);
+            logger.error(`[Phase3.2] Generated embeddings for documentation: ${doc.relativePath}`);
+          } catch (embeddingError) {
+            logger.error(
+              `[Phase3.2] Failed to embed documentation ${doc.relativePath}:`,
+              embeddingError,
+            );
+            // Continue even if embeddings fail
+          }
+        }
+ 
+        result.indexed++;
+      } catch (err) {
+        result.errors.push({
+          file: filePath,
+          error: err instanceof Error ? err.message : String(err),
+        });
+      }
+    }
+ 
+    result.durationMs = Date.now() - t0;
+    return result;
+  }
+ 
+  // ── Search ──────────────────────────────────────────────────────────────────
+ 
+  /**
+   * Search SECTION nodes by text content.
+   * Uses a Memgraph CONTAINS fallback (text_search integration added in
+   * hybrid-retriever Step 9 is a separate enhancement).
+   */
+  async searchDocs(
+    query: string,
+    projectId: string,
+    opts: DocsSearchOptions = {},
+  ): Promise<DocsSearchResult[]> {
+    const limit = Math.min(opts.limit ?? 10, 50);
+    const terms = query
+      .toLowerCase()
+      .split(/\s+/)
+      .filter((t) => t.length > 2);
+ 
+    if (terms.length === 0) return [];
+ 
+    // Try native text_search first (if SECTION index exists)
+    const nativeResults = await this.nativeSearch(query, projectId, limit);
+    if (nativeResults !== null) return nativeResults;
+ 
+    // Fallback: Cypher CONTAINS scan (works without BM25 index)
+    return this.fallbackSearch(terms, projectId, limit);
+  }
+ 
+  /**
+   * Find SECTION nodes that have a DOC_DESCRIBES edge pointing at a named
+   * FUNCTION, CLASS, or FILE node.
+   */
+  async getDocsBySymbol(
+    symbolName: string,
+    projectId: string,
+    opts: DocsSearchOptions = {},
+  ): Promise<DocsSearchResult[]> {
+    const limit = Math.min(opts.limit ?? 10, 50);
+    const res = await this.memgraph.executeCypher(
+      `
+MATCH (s:SECTION { projectId: $projectId })-[r:DOC_DESCRIBES]->(target { projectId: $projectId, name: $name })
+MATCH (s)-[:SECTION_OF]->(d:DOCUMENT { projectId: $projectId })
+RETURN s.id AS sectionId,
+       s.heading AS heading,
+       d.relativePath AS relativePath,
+       d.kind AS kind,
+       s.content AS content,
+       s.startLine AS startLine,
+       r.strength AS score
+ORDER BY score DESC
+LIMIT ${limit}
+      `,
+      { projectId, name: symbolName },
+    );
+ 
+    if (res.error || !res.data.length) return [];
+    return res.data.map((row: Record<string, unknown>) => this.rowToResult(row));
+  }
+ 
+  // ── Private helpers ──────────────────────────────────────────────────────────
+ 
+  private async fetchExistingHashes(projectId: string): Promise<Map<string, string>> {
+    const res = await this.memgraph.executeCypher(
+      `MATCH (d:DOCUMENT { projectId: $projectId })
+       RETURN d.relativePath AS relativePath, d.hash AS hash`,
+      { projectId },
+    );
+    const map = new Map<string, string>();
+    Eif (!res.error) {
+      for (const row of res.data as Array<{
+        relativePath: unknown;
+        hash: unknown;
+      }>) {
+        Eif (typeof row.relativePath === "string" && typeof row.hash === "string") {
+          map.set(row.relativePath, row.hash);
+        }
+      }
+    }
+    return map;
+  }
+ 
+  private async nativeSearch(
+    query: string,
+    projectId: string,
+    limit: number,
+  ): Promise<DocsSearchResult[] | null> {
+    Iif (!this.memgraph) return null;
+    try {
+      const res = await this.memgraph.executeCypher(
+        `
+CALL text_search.search('docs_index', $query) YIELD node, score
+WHERE coalesce(node.projectId, '') = $projectId
+MATCH (node)-[:SECTION_OF]->(d:DOCUMENT { projectId: $projectId })
+RETURN node.id AS sectionId,
+       node.heading AS heading,
+       d.relativePath AS relativePath,
+       d.kind AS kind,
+       node.content AS content,
+       node.startLine AS startLine,
+       score
+ORDER BY score DESC
+LIMIT ${limit}
+        `,
+        { query, projectId },
+      );
+      if (res.error || res.data.length === 0) return null;
+      return res.data.map((row: Record<string, unknown>) => this.rowToResult(row));
+    } catch {
+      return null;
+    }
+  }
+ 
+  private async fallbackSearch(
+    terms: string[],
+    projectId: string,
+    limit: number,
+  ): Promise<DocsSearchResult[]> {
+    // Build a simple WHERE clause that checks heading and content
+    const whereClauses = terms.map(
+      (_, i) => `(toLower(s.heading) CONTAINS $term${i} OR toLower(s.content) CONTAINS $term${i})`,
+    );
+    const params: Record<string, unknown> = { projectId };
+    terms.forEach((t, i) => {
+      params[`term${i}`] = t;
+    });
+ 
+    const res = await this.memgraph.executeCypher(
+      `
+MATCH (s:SECTION { projectId: $projectId })-[:SECTION_OF]->(d:DOCUMENT { projectId: $projectId })
+WHERE ${whereClauses.join(" AND ")}
+RETURN s.id AS sectionId,
+       s.heading AS heading,
+       d.relativePath AS relativePath,
+       d.kind AS kind,
+       s.content AS content,
+       s.startLine AS startLine,
+       1.0 AS score
+ORDER BY s.heading
+LIMIT ${limit}
+      `,
+      params,
+    );
+ 
+    Iif (res.error || !res.data.length) return [];
+    return res.data.map((row: Record<string, unknown>) => this.rowToResult(row));
+  }
+ 
+  private rowToResult(row: Record<string, unknown>): DocsSearchResult {
+    return {
+      sectionId: String(row.sectionId ?? ""),
+      heading: String(row.heading ?? ""),
+      docRelativePath: String(row.relativePath ?? ""),
+      kind: String(row.kind ?? ""),
+      content: String(row.content ?? "").slice(0, 500),
+      score: Number(row.score ?? 0),
+      startLine: Number(row.startLine ?? 0),
+    };
+  }
+ 
+  // ── Vector embedding ─────────────────────────────────────────────────────────
+ 
+  private async embedDoc(doc: ParsedDoc, projectId: string): Promise<void> {
+    Iif (!this.qdrant) return;
+    const points: VectorPoint[] = doc.sections
+      .filter((s) => s.wordCount > 0)
+      .map((s) => ({
+        // Qdrant requires string or UUID ids
+        id: String(this.hashToUint(doc.relativePath + ":" + s.index)),
+        vector: this.tfidfVector(s.heading + " " + s.content),
+        payload: {
+          projectId,
+          relativePath: doc.relativePath,
+          kind: doc.kind,
+          heading: s.heading,
+          startLine: s.startLine,
+          sectionIndex: s.index,
+        },
+      }));
+ 
+    await this.qdrant.upsertPoints(DOCS_COLLECTION, points);
+  }
+ 
+  /**
+   * Deterministic mapping of a string to a 31-bit positive integer for use
+   * as a Qdrant point id.
+   */
+  private hashToUint(s: string): number {
+    let h = 0x811c9dc5;
+    for (let i = 0; i < s.length; i++) {
+      h ^= s.charCodeAt(i);
+      h = Math.imul(h, 0x01000193);
+    }
+    return h >>> 1; // strip sign bit
+  }
+ 
+  /**
+   * Minimal term-frequency vector for a text string.
+   * Produces a sparse-like float32 array of length DOCS_VECTOR_SIZE.
+   * Replace with a real embedding model for production use.
+   */
+  private tfidfVector(text: string): number[] {
+    const vec = new Float32Array(DOCS_VECTOR_SIZE);
+    const tokens = text.toLowerCase().match(/\w+/g) ?? [];
+    for (const tok of tokens) {
+      let h = 0;
+      for (let i = 0; i < tok.length; i++) {
+        h = ((h << 5) - h + tok.charCodeAt(i)) | 0;
+      }
+      const idx = Math.abs(h) % DOCS_VECTOR_SIZE;
+      vec[idx] = Math.min(vec[idx] + 1, 10);
+    }
+    // L2 normalise
+    const norm = Math.sqrt(vec.reduce((s, v) => s + v * v, 0)) || 1;
+    return Array.from(vec).map((v) => v / norm);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/episode-engine.ts.html b/coverage/lcov-report/src/engines/episode-engine.ts.html new file mode 100644 index 0000000..5514bac --- /dev/null +++ b/coverage/lcov-report/src/engines/episode-engine.ts.html @@ -0,0 +1,1192 @@ + + + + + + Code coverage report for src/engines/episode-engine.ts + + + + + + + + + +
+
+

All files / src/engines episode-engine.ts

+
+ +
+ 97.84% + Statements + 91/93 +
+ + +
+ 87.91% + Branches + 80/91 +
+ + +
+ 100% + Functions + 21/21 +
+ + +
+ 97.82% + Lines + 90/92 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +157x +  +  +15x +15x +15x +  +15x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +110x +  +  +  +  +  +  +  +  +  +  +  +15x +15x +  +  +  +28x +28x +  +  +  +  +28x +2x +2x +  +28x +1x +1x +  +28x +3x +3x +  +28x +1x +1x +  +  +28x +  +  +  +  +  +  +  +  +28x +28x +28x +  +28x +28x +28x +  +28x +26x +26x +  +26x +26x +  +26x +26x +  +26x +  +26x +  +  +28x +11x +  +  +  +  +2x +  +  +  +  +  +  +  +  +6x +  +  +  +  +  +  +  +6x +6x +11x +11x +  +  +  +6x +4x +  +7x +  +6x +  +  +6x +  +  +  +6x +  +  +  +  +  +  +7x +  +  +  +  +  +  +6x +6x +6x +6x +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +6x +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +  +  +  +  +15x +15x +14x +  +  +1x +  +  +  +  +  +  +  +  +28x +26x +  +28x +28x +  +  +  +26x +  +  +  +  +  +  +  +23x +  +  +  +  +  +  +  +  +  +  +26x +2x +  +  +24x +24x +  +1x +  +  +  +  +54x +  +  +  +143x +  +  +  +  +28x +  +  +28x +4x +  +  +24x +24x +44x +17x +  +  +24x +24x +  +  +  +21x +  +  + 
/**
+ * @file engines/episode-engine
+ * @description Persists and recalls agent episodes, decisions, and reflective learnings.
+ * @remarks Episode data is project-scoped and designed for long-term memory retrieval.
+ */
+ 
+import type MemgraphClient from "../graph/client.js";
+ 
+export type EpisodeType =
+  | "OBSERVATION"
+  | "DECISION"
+  | "EDIT"
+  | "TEST_RESULT"
+  | "ERROR"
+  | "REFLECTION"
+  | "LEARNING";
+ 
+export interface EpisodeInput {
+  agentId: string;
+  sessionId: string;
+  taskId?: string;
+  type: EpisodeType;
+  content: string;
+  entities?: string[];
+  outcome?: "success" | "failure" | "partial";
+  metadata?: Record<string, unknown>;
+  sensitive?: boolean;
+}
+ 
+export interface Episode extends EpisodeInput {
+  id: string;
+  timestamp: number;
+  projectId: string;
+  relevance?: number;
+}
+ 
+export interface RecallQuery {
+  query: string;
+  projectId: string;
+  agentId?: string;
+  taskId?: string;
+  types?: EpisodeType[];
+  entities?: string[];
+  limit?: number;
+  since?: number;
+}
+ 
+export interface ReflectionResult {
+  reflectionId: string;
+  insight: string;
+  learningsCreated: number;
+  patterns: Array<{ file: string; count: number }>;
+}
+ 
+export default class EpisodeEngine {
+  constructor(private memgraph: MemgraphClient) {}
+ 
+  async add(input: EpisodeInput, projectId: string): Promise<string> {
+    const id = this.makeId("ep");
+    const timestamp = Date.now();
+    const entities = (input.entities || []).slice(0, 100);
+ 
+    await this.memgraph.executeCypher(
+      `CREATE (e:EPISODE {
+        id: $id,
+        agentId: $agentId,
+        sessionId: $sessionId,
+        taskId: $taskId,
+        type: $type,
+        content: $content,
+        timestamp: $timestamp,
+        outcome: $outcome,
+        metadata: $metadata,
+        sensitive: $sensitive,
+        entities: $entities,
+        projectId: $projectId
+      })`,
+      {
+        id,
+        agentId: input.agentId,
+        sessionId: input.sessionId,
+        taskId: input.taskId || null,
+        type: input.type,
+        content: input.content,
+        timestamp,
+        outcome: input.outcome || null,
+        metadata: JSON.stringify(input.metadata || {}),
+        sensitive: Boolean(input.sensitive),
+        entities,
+        projectId,
+      },
+    );
+ 
+    for (const entity of entities) {
+      await this.memgraph.executeCypher(
+        `MATCH (e:EPISODE {id: $episodeId, projectId: $projectId})
+         MATCH (n {id: $entityId, projectId: $projectId})
+         MERGE (e)-[:INVOLVES]->(n)`,
+        {
+          episodeId: id,
+          entityId: entity,
+          projectId,
+        },
+      );
+    }
+ 
+    await this.linkToPreviousEpisode(id, input.agentId, input.sessionId, projectId);
+    return id;
+  }
+ 
+  async recall(query: RecallQuery): Promise<Episode[]> {
+    const conditions = ["e.projectId = $projectId", "(e.sensitive IS NULL OR e.sensitive = false)"];
+    const params: Record<string, unknown> = {
+      projectId: query.projectId,
+      limit: Math.max(1, Math.min(query.limit || 5, 50)),
+    };
+ 
+    if (query.agentId) {
+      conditions.push("e.agentId = $agentId");
+      params.agentId = query.agentId;
+    }
+    if (query.taskId) {
+      conditions.push("e.taskId = $taskId");
+      params.taskId = query.taskId;
+    }
+    if (query.types?.length) {
+      conditions.push("e.type IN $types");
+      params.types = query.types;
+    }
+    if (query.since) {
+      conditions.push("e.timestamp >= $since");
+      params.since = query.since;
+    }
+ 
+    const result = await this.memgraph.executeCypher(
+      `MATCH (e:EPISODE)
+       WHERE ${conditions.join(" AND ")}
+       RETURN e
+       ORDER BY e.timestamp DESC
+       LIMIT 200`,
+      params,
+    );
+ 
+    const episodes = result.data
+      .map((row) => this.rowToEpisode(row, query.projectId))
+      .filter((item): item is Episode => Boolean(item));
+ 
+    const queryTerms = this.tokenize(query.query);
+    const queryEntities = new Set(query.entities || []);
+    const now = Date.now();
+ 
+    const scored = episodes.map((episode) => {
+      const contentTerms = this.tokenize(episode.content);
+      const lexicalScore = this.jaccard(queryTerms, contentTerms);
+ 
+      const ageDays = Math.max(0, (now - episode.timestamp) / 86400000);
+      const temporalScore = Math.exp(-0.05 * ageDays);
+ 
+      const episodeEntities = new Set(episode.entities || []);
+      const graphScore = queryEntities.size > 0 ? this.jaccard(queryEntities, episodeEntities) : 0;
+ 
+      const relevance = 0.5 * lexicalScore + 0.3 * temporalScore + 0.2 * graphScore;
+ 
+      return { ...episode, relevance: Number(relevance.toFixed(4)) };
+    });
+ 
+    return scored
+      .sort((a, b) => (b.relevance || 0) - (a.relevance || 0))
+      .slice(0, params.limit as number);
+  }
+ 
+  async decisionQuery(query: Omit<RecallQuery, "types">): Promise<Episode[]> {
+    return this.recall({ ...query, types: ["DECISION"] });
+  }
+ 
+  async reflect(opts: {
+    taskId?: string;
+    agentId?: string;
+    limit?: number;
+    projectId: string;
+  }): Promise<ReflectionResult> {
+    const episodes = await this.recall({
+      query: opts.taskId || opts.agentId || "recent work",
+      projectId: opts.projectId,
+      taskId: opts.taskId,
+      agentId: opts.agentId,
+      limit: opts.limit || 20,
+    });
+ 
+    const frequency = new Map<string, number>();
+    for (const episode of episodes) {
+      for (const entity of episode.entities || []) {
+        frequency.set(entity, (frequency.get(entity) || 0) + 1);
+      }
+    }
+ 
+    const patterns = [...frequency.entries()]
+      .sort((a, b) => b[1] - a[1])
+      .slice(0, 5)
+      .map(([file, count]) => ({ file, count }));
+ 
+    const insight = patterns.length
+      ? `Reflection over ${episodes.length} episodes: recurring focus on ${patterns
+          .slice(0, 3)
+          .map((item) => item.file)
+          .join(", ")}.`
+      : `Reflection over ${episodes.length} episodes: no dominant recurring entities detected.`;
+ 
+    const reflectionId = await this.add(
+      {
+        agentId: opts.agentId || "system",
+        sessionId: `reflect-${Date.now()}`,
+        taskId: opts.taskId,
+        type: "REFLECTION",
+        content: insight,
+        entities: patterns.map((p) => p.file),
+        outcome: "partial",
+        metadata: { sourceCount: episodes.length, patterns },
+      },
+      opts.projectId,
+    );
+ 
+    let learningsCreated = 0;
+    for (const pattern of patterns.slice(0, 3)) {
+      const learningId = this.makeId("learn");
+      const learningText = `Repeated activity around ${pattern.file} (${pattern.count} related episodes).`;
+ 
+      await this.memgraph.executeCypher(
+        `CREATE (l:LEARNING {
+          id: $id,
+          content: $content,
+          extractedAt: $timestamp,
+          confidence: $confidence,
+          projectId: $projectId,
+          reflectionId: $reflectionId
+        })`,
+        {
+          id: learningId,
+          content: learningText,
+          timestamp: Date.now(),
+          confidence: Math.min(1, 0.5 + pattern.count / 10),
+          projectId: opts.projectId,
+          reflectionId,
+        },
+      );
+ 
+      await this.memgraph.executeCypher(
+        `MATCH (l:LEARNING {id: $learningId, projectId: $projectId})
+         MATCH (n {id: $entityId, projectId: $projectId})
+         MERGE (l)-[:APPLIES_TO]->(n)`,
+        {
+          learningId,
+          entityId: pattern.file,
+          projectId: opts.projectId,
+        },
+      );
+ 
+      learningsCreated += 1;
+    }
+ 
+    return {
+      reflectionId,
+      insight,
+      learningsCreated,
+      patterns,
+    };
+  }
+ 
+  private async linkToPreviousEpisode(
+    episodeId: string,
+    agentId: string,
+    sessionId: string,
+    projectId: string,
+  ): Promise<void> {
+    const prev = await this.memgraph.executeCypher(
+      `MATCH (e:EPISODE)
+       WHERE e.projectId = $projectId
+         AND e.agentId = $agentId
+         AND e.sessionId = $sessionId
+         AND e.id <> $episodeId
+       RETURN e.id AS id
+       ORDER BY e.timestamp DESC
+       LIMIT 1`,
+      { projectId, agentId, sessionId, episodeId },
+    );
+ 
+    const prevId = prev.data?.[0]?.id;
+    if (!prevId) {
+      return;
+    }
+ 
+    await this.memgraph.executeCypher(
+      `MATCH (prev:EPISODE {id: $prevId, projectId: $projectId})
+       MATCH (curr:EPISODE {id: $episodeId, projectId: $projectId})
+       MERGE (prev)-[:NEXT_EPISODE]->(curr)`,
+      { prevId, episodeId, projectId },
+    );
+  }
+ 
+  private rowToEpisode(row: Record<string, any>, projectId: string): Episode | null {
+    if (row == null || typeof row !== "object") return null;
+    const rawNode = row.e || row.episode || row;
+    const node =
+      rawNode && typeof rawNode === "object" && rawNode.properties ? rawNode.properties : rawNode;
+    Iif (!node || typeof node !== "object") {
+      return null;
+    }
+ 
+    return {
+      id: String(node.id),
+      agentId: String(node.agentId || "unknown"),
+      sessionId: String(node.sessionId || "unknown"),
+      taskId: node.taskId ? String(node.taskId) : undefined,
+      type: (node.type || "OBSERVATION") as EpisodeType,
+      content: String(node.content || ""),
+      entities: Array.isArray(node.entities)
+        ? node.entities.map((item: unknown) => String(item))
+        : [],
+      outcome: node.outcome || undefined,
+      metadata: this.tryParseJson(node.metadata),
+      sensitive: Boolean(node.sensitive),
+      timestamp: Number(node.timestamp || Date.now()),
+      projectId,
+    };
+  }
+ 
+  private tryParseJson(input: unknown): Record<string, unknown> | undefined {
+    if (!input || typeof input !== "string") {
+      return undefined;
+    }
+ 
+    try {
+      return JSON.parse(input) as Record<string, unknown>;
+    } catch {
+      return undefined;
+    }
+  }
+ 
+  private tokenize(text: string): Set<string> {
+    return new Set(
+      text
+        .toLowerCase()
+        .split(/[^a-z0-9_]+/)
+        .filter((token) => token.length > 1),
+    );
+  }
+ 
+  private jaccard(left: Set<string>, right: Set<string>): number {
+    Iif (left.size === 0 && right.size === 0) {
+      return 1;
+    }
+    if (left.size === 0 || right.size === 0) {
+      return 0;
+    }
+ 
+    let intersection = 0;
+    for (const item of left) {
+      if (right.has(item)) {
+        intersection += 1;
+      }
+    }
+    const union = left.size + right.size - intersection;
+    return union > 0 ? intersection / union : 0;
+  }
+ 
+  private makeId(prefix: string): string {
+    return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/index.html b/coverage/lcov-report/src/engines/index.html new file mode 100644 index 0000000..e4fc1d3 --- /dev/null +++ b/coverage/lcov-report/src/engines/index.html @@ -0,0 +1,266 @@ + + + + + + Code coverage report for src/engines + + + + + + + + + +
+
+

All files src/engines

+
+ +
+ 77.39% + Statements + 719/929 +
+ + +
+ 64.07% + Branches + 453/707 +
+ + +
+ 82.75% + Functions + 144/174 +
+ + +
+ 79.17% + Lines + 673/850 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
architecture-engine.ts +
+
67.65%159/23550%68/13682.6%19/2368.77%152/221
community-detector.ts +
+
96.47%82/8579.24%42/5394.44%17/1898.66%74/75
coordination-engine.ts +
+
95.91%47/4956.06%37/66100%19/1995.91%47/49
coordination-queries.ts +
+
100%1/1100%0/0100%0/0100%1/1
coordination-types.ts +
+
0%0/00%0/00%0/00%0/0
coordination-utils.ts +
+
100%5/590.9%30/33100%2/2100%5/5
docs-engine.ts +
+
94.23%98/10478.94%60/76100%23/2396.62%86/89
episode-engine.ts +
+
97.84%91/9387.91%80/91100%21/2197.82%90/92
migration-engine.ts +
+
0%0/470%0/180%0/130%0/43
progress-engine.ts +
+
69.56%112/16146.03%58/12672.72%24/3372.14%101/140
test-engine.ts +
+
83.22%124/14972.22%78/10886.36%19/2286.66%117/135
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/migration-engine.ts.html b/coverage/lcov-report/src/engines/migration-engine.ts.html new file mode 100644 index 0000000..1d2f9a4 --- /dev/null +++ b/coverage/lcov-report/src/engines/migration-engine.ts.html @@ -0,0 +1,760 @@ + + + + + + Code coverage report for src/engines/migration-engine.ts + + + + + + + + + +
+
+

All files / src/engines migration-engine.ts

+
+ +
+ 0% + Statements + 0/47 +
+ + +
+ 0% + Branches + 0/18 +
+ + +
+ 0% + Functions + 0/13 +
+ + +
+ 0% + Lines + 0/43 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file engines/migration-engine
+ * @description Migrates legacy markdown progress tracking into graph FEATURE/TASK nodes.
+ * @remarks Used for one-time or controlled migration workflows.
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import type { Feature, Task } from "./progress-engine.js";
+ 
+export interface MigrationResult {
+  success: boolean;
+  featuresCreated: number;
+  tasksCreated: number;
+  errors: string[];
+  summary: string;
+}
+ 
+export class MigrationEngine {
+  /**
+   * Migrate Canvas Performance V2 tracking
+   */
+  static migrateCanvasPerfV2(): Feature[] {
+    const features: Feature[] = [];
+ 
+    // Main feature
+    const mainFeature: Feature = {
+      id: "canvas-perf-v2",
+      name: "Canvas Performance V2",
+      status: "in-progress",
+      description:
+        "Optimize Konva.js canvas rendering with layer-level transforms, grid optimization, viewport culling, LOD system, and batch zoom",
+      adrReference: "ADR-012",
+      startedAt: new Date("2024-02-01").getTime(),
+      implementingFiles: [
+        "src/components/drawing/canvas-hooks/useCameraTransform.ts",
+        "src/components/drawing/canvas-layers/GridSceneLayer.tsx",
+        "src/components/drawing/canvas-utils/levelOfDetail.ts",
+        "src/components/drawing/canvas-hooks/useViewportBounds.ts",
+        "src/components/drawing/canvas-hooks/useInteractionSuspension.ts",
+      ],
+      relatedTests: [
+        "src/components/drawing/__tests__/GridCanvas.test.tsx",
+        "src/components/drawing/canvas-hooks/__tests__/useCameraTransform.test.ts",
+        "src/components/drawing/canvas-layers/__tests__/GridSceneLayer.test.tsx",
+      ],
+    };
+ 
+    features.push(mainFeature);
+ 
+    return features;
+  }
+ 
+  /**
+   * Migrate tracking from markdown file
+   */
+  static migrateFromMarkdown(filePath: string): MigrationResult {
+    const errors: string[] = [];
+    let featuresCreated = 0;
+    let tasksCreated = 0;
+ 
+    try {
+      if (!fs.existsSync(filePath)) {
+        return {
+          success: false,
+          featuresCreated: 0,
+          tasksCreated: 0,
+          errors: [`File not found: ${filePath}`],
+          summary: "Migration failed: file not found",
+        };
+      }
+ 
+      const content = fs.readFileSync(filePath, "utf-8");
+ 
+      // Parse markdown sections
+      const sections = this.parseSections(content);
+ 
+      for (const section of sections) {
+        if (section.type === "feature") {
+          featuresCreated++;
+        } else if (section.type === "task") {
+          tasksCreated++;
+        }
+      }
+ 
+      return {
+        success: true,
+        featuresCreated,
+        tasksCreated,
+        errors,
+        summary: `Migrated ${featuresCreated} features and ${tasksCreated} tasks from ${path.basename(filePath)}`,
+      };
+    } catch (error) {
+      errors.push(`Migration error: ${error}`);
+      return {
+        success: false,
+        featuresCreated,
+        tasksCreated,
+        errors,
+        summary: "Migration failed with errors",
+      };
+    }
+  }
+ 
+  /**
+   * Parse markdown into feature/task structure
+   */
+  private static parseSections(content: string): Array<{
+    type: "feature" | "task";
+    id: string;
+    title: string;
+    details: any;
+  }> {
+    const sections: Array<{
+      type: "feature" | "task";
+      id: string;
+      title: string;
+      details: any;
+    }> = [];
+ 
+    // Simple markdown parser (would be expanded for production)
+    const lines = content.split("\n");
+    let currentSection: any = null;
+ 
+    for (const line of lines) {
+      if (line.startsWith("## ")) {
+        // Feature section
+        currentSection = {
+          title: line.replace("## ", "").trim(),
+          details: {},
+        };
+      } else if (line.startsWith("### ")) {
+        // Task section
+        currentSection = {
+          title: line.replace("### ", "").trim(),
+          details: {},
+        };
+      } else if (line.startsWith("- [ ]") || line.startsWith("- [x]")) {
+        // Task item
+        const completed = line.includes("[x]");
+        const text = line.replace(/- \[[x ]\] /, "").trim();
+        if (currentSection) {
+          sections.push({
+            type: "task",
+            id: `task-${sections.length}`,
+            title: text,
+            details: { completed, description: text },
+          });
+        }
+      }
+    }
+ 
+    return sections;
+  }
+ 
+  /**
+   * Generate migration report
+   */
+  static generateReport(results: MigrationResult[]): string {
+    const totalFeatures = results.reduce((sum, r) => sum + r.featuresCreated, 0);
+    const totalTasks = results.reduce((sum, r) => sum + r.tasksCreated, 0);
+    const totalErrors = results.reduce((sum, r) => sum + r.errors.length, 0);
+ 
+    return `
+# Migration Report
+ 
+**Date**: ${new Date().toISOString()}
+ 
+## Summary
+- Features migrated: ${totalFeatures}
+- Tasks migrated: ${totalTasks}
+- Errors encountered: ${totalErrors}
+ 
+## Details
+${results.map((r) => `- ${r.summary}`).join("\n")}
+ 
+## Errors
+${
+  totalErrors > 0
+    ? results
+        .filter((r) => r.errors.length > 0)
+        .map((r) => r.errors.map((e) => `- ${e}`).join("\n"))
+        .join("\n")
+    : "None"
+}
+ 
+## Next Steps
+1. Review migrated features and tasks in graph
+2. Update any broken references
+3. Archive original markdown files
+4. Update team documentation
+`;
+  }
+ 
+  /**
+   * Create sample feature for testing
+   */
+  static createSampleFeature(): Feature {
+    return {
+      id: "test-feature",
+      name: "Sample Feature",
+      status: "pending",
+      description: "This is a sample feature for testing",
+      startedAt: Date.now(),
+      implementingFiles: ["src/sample.ts"],
+      relatedTests: ["src/__tests__/sample.test.ts"],
+    };
+  }
+ 
+  /**
+   * Create sample task for testing
+   */
+  static createSampleTask(): Task {
+    return {
+      id: "test-task-1",
+      name: "Sample Task",
+      description: "This is a sample task",
+      status: "pending",
+      assignee: "Team",
+      startedAt: Date.now(),
+    };
+  }
+}
+ 
+export default MigrationEngine;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/progress-engine.ts.html b/coverage/lcov-report/src/engines/progress-engine.ts.html new file mode 100644 index 0000000..2ca8859 --- /dev/null +++ b/coverage/lcov-report/src/engines/progress-engine.ts.html @@ -0,0 +1,1606 @@ + + + + + + Code coverage report for src/engines/progress-engine.ts + + + + + + + + + +
+
+

All files / src/engines progress-engine.ts

+
+ +
+ 69.56% + Statements + 112/161 +
+ + +
+ 46.03% + Branches + 58/126 +
+ + +
+ 72.72% + Functions + 24/33 +
+ + +
+ 72.14% + Lines + 101/140 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +131x +131x +131x +131x +131x +  +  +  +  +  +  +  +151x +151x +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +151x +151x +14x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +151x +14x +14x +14x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +1x +1x +1x +  +1x +1x +2x +2x +2x +2x +  +  +  +  +3x +3x +3x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +  +2x +1x +1x +1x +  +  +2x +  +  +  +  +  +  +1x +1x +  +  +2x +  +  +1x +1x +  +1x +1x +1x +1x +1x +  +  +  +  +1x +1x +  +1x +1x +1x +1x +  +1x +  +2x +1x +2x +2x +2x +2x +  +  +  +  +1x +1x +1x +1x +1x +  +  +  +1x +1x +1x +1x +1x +  +  +  +  +2x +  +  +2x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +  +20x +20x +20x +20x +  +  +20x +20x +2x +1x +  +  +  +20x +3x +1x +  +  +  +  +20x +20x +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file engines/progress-engine
+ * @description Manages feature/task status and progress queries backed by graph state.
+ * @remarks Provides both in-memory and Memgraph persistence pathways.
+ */
+ 
+import type { GraphIndexManager } from "../graph/index.js";
+import type { MemgraphClient } from "../graph/client.js";
+import type { CypherStatement } from "../graph/types.js";
+import { extractProjectIdFromScopedId } from "../utils/validation.js";
+import { logger } from "../utils/logger.js";
+ 
+export interface Feature {
+  id: string;
+  name: string;
+  status: "pending" | "in-progress" | "completed" | "blocked";
+  description?: string;
+  adrReference?: string;
+  startedAt?: number;
+  completedAt?: number;
+  implementingFiles?: string[];
+  relatedTests?: string[];
+}
+ 
+export interface Task {
+  id: string;
+  name: string;
+  description?: string;
+  status: "pending" | "in-progress" | "completed" | "blocked";
+  assignee?: string;
+  featureId?: string;
+  startedAt?: number;
+  dueDate?: number;
+  completedAt?: number;
+  blockedBy?: string[]; // Task IDs
+}
+ 
+export interface ProgressQueryResult {
+  items: (Feature | Task)[];
+  totalCount: number;
+  completedCount: number;
+  inProgressCount: number;
+  blockedCount: number;
+}
+ 
+export interface FeatureStatus {
+  feature: Feature;
+  tasks: Task[];
+  implementingCode: {
+    files: string[];
+    functions: number;
+    classes: number;
+  };
+  testCoverage: {
+    testSuites: number;
+    testCases: number;
+  };
+  blockingIssues: Task[];
+  progressPercentage: number;
+}
+ 
+export class ProgressEngine {
+  private features: Map<string, Feature>;
+  private tasks: Map<string, Task>;
+  private index: GraphIndexManager;
+  private memgraph?: MemgraphClient;
+ 
+  constructor(index: GraphIndexManager, memgraph?: MemgraphClient) {
+    this.index = index;
+    this.memgraph = memgraph;
+    this.features = new Map();
+    this.tasks = new Map();
+    this.loadFromGraph();
+  }
+ 
+  /**
+   * Load features and tasks from graph
+   */
+  private loadFromGraph(): void {
+    // Load FEATURE nodes
+    const featureNodes = this.index.getNodesByType("FEATURE");
+    for (const node of featureNodes) {
+      this.features.set(node.id, {
+        id: node.id,
+        name: node.properties.name,
+        status: node.properties.status || "pending",
+        description: node.properties.description,
+        adrReference: node.properties.adrReference,
+        startedAt: node.properties.startedAt,
+        completedAt: node.properties.completedAt,
+        implementingFiles: [],
+        relatedTests: [],
+      });
+    }
+ 
+    // Load TASK nodes
+    const taskNodes = this.index.getNodesByType("TASK");
+    for (const node of taskNodes) {
+      this.tasks.set(node.id, {
+        id: node.id,
+        name: node.properties.name,
+        description: node.properties.description,
+        status: node.properties.status || "pending",
+        assignee: node.properties.assignee,
+        featureId: node.properties.featureId,
+        startedAt: node.properties.startedAt,
+        dueDate: node.properties.dueDate,
+        completedAt: node.properties.completedAt,
+        blockedBy: node.properties.blockedBy || [],
+      });
+    }
+ 
+    // Link tasks to features via featureId relationship
+    for (const task of this.tasks.values()) {
+      Eif (task.featureId) {
+        const feature = this.features.get(task.featureId);
+        Iif (feature && Array.isArray((feature as any).taskIds)) {
+          (feature as any).taskIds.push(task.id);
+        }
+      }
+    }
+  }
+ 
+  /**
+   * Query features or tasks by filter criteria
+   */
+  query(
+    type: "feature" | "task",
+    filter?: {
+      status?: string;
+      assignee?: string;
+      featureId?: string;
+    },
+  ): ProgressQueryResult {
+    const items: (Feature | Task)[] = [];
+ 
+    if (type === "feature") {
+      for (const feature of this.features.values()) {
+        Iif (filter?.status && feature.status !== filter.status) continue;
+        items.push(feature);
+      }
+    E} else if (type === "task") {
+      for (const task of this.tasks.values()) {
+        Iif (filter?.status && task.status !== filter.status) continue;
+        Iif (filter?.assignee && task.assignee !== filter.assignee) continue;
+        Iif (filter?.featureId && task.featureId !== filter.featureId) continue;
+        items.push(task);
+      }
+    }
+ 
+    // Calculate statistics
+    const completed = items.filter((i) => i.status === "completed").length;
+    const inProgress = items.filter((i) => i.status === "in-progress").length;
+    const blocked = items.filter((i) => i.status === "blocked").length;
+ 
+    return {
+      items,
+      totalCount: items.length,
+      completedCount: completed,
+      inProgressCount: inProgress,
+      blockedCount: blocked,
+    };
+  }
+ 
+  /**
+   * Update task status
+   */
+  updateTask(taskId: string, updates: Partial<Task>): Task | null {
+    const task = this.tasks.get(taskId);
+    Iif (!task) return null;
+ 
+    Object.assign(task, updates);
+ 
+    if (updates.status === "completed") {
+      task.completedAt = Date.now();
+    E} else if (updates.status === "in-progress" && !task.startedAt) {
+      task.startedAt = Date.now();
+    }
+ 
+    return task;
+  }
+ 
+  /**
+   * Get detailed feature status
+   */
+  getFeatureStatus(featureId: string): FeatureStatus | null {
+    const feature = this.features.get(featureId);
+    Iif (!feature) return null;
+ 
+    // Get tasks for this feature
+    const tasks = Array.from(this.tasks.values()).filter((t) => t.featureId === featureId);
+ 
+    // Get implementing files (linked via IMPLEMENTS relationship in graph)
+    const implementingFiles: string[] = [];
+    const fileRels = this.index
+      .getRelationshipsFrom(featureId)
+      .filter((r) => r.type === "IMPLEMENTS");
+    for (const rel of fileRels) {
+      const file = this.index.getNode(rel.to);
+      Eif (file && file.properties.path) {
+        implementingFiles.push(file.properties.path);
+      }
+    }
+ 
+    // Count functions and classes in implementing files
+    let functionCount = 0;
+    let classCount = 0;
+ 
+    for (const filePath of implementingFiles) {
+      const fileNodes = this.index.getNodesByType("FILE");
+      const fileNode = fileNodes.find((n) => n.properties.path === filePath);
+      Iif (!fileNode) continue;
+ 
+      const funcRels = this.index
+        .getRelationshipsFrom(fileNode.id)
+        .filter((r) => r.type === "CONTAINS");
+      for (const rel of funcRels) {
+        const node = this.index.getNode(rel.to);
+        Iif (!node) continue;
+        if (node.type === "FUNCTION") functionCount++;
+        if (node.type === "CLASS") classCount++;
+      }
+    }
+ 
+    // Get test coverage
+    const testSuites = this.index.getNodesByType("TEST_SUITE").filter((n) => {
+      const testsRels = this.index.getRelationshipsFrom(n.id).filter((r) => r.type === "TESTS");
+      return testsRels.some((r) => {
+        const tested = this.index.getNode(r.to);
+        return tested && implementingFiles.includes(tested.properties.path || "");
+      });
+    });
+ 
+    const testCases = this.index.getNodesByType("TEST_CASE").filter((n) => {
+      const testRels = this.index.getRelationshipsFrom(n.id).filter((r) => r.type === "TESTS");
+      return testRels.some((r) => {
+        const tested = this.index.getNode(r.to);
+        return tested && implementingFiles.includes(tested.properties.path || "");
+      });
+    });
+ 
+    // Find blocking issues
+    const blockingIssues = tasks.filter((t) => t.status === "blocked");
+ 
+    // Calculate progress
+    const completedTasks = tasks.filter((t) => t.status === "completed").length;
+    const progressPercentage = tasks.length > 0 ? (completedTasks / tasks.length) * 100 : 0;
+ 
+    return {
+      feature,
+      tasks,
+      implementingCode: {
+        files: implementingFiles,
+        functions: functionCount,
+        classes: classCount,
+      },
+      testCoverage: {
+        testSuites: testSuites.length,
+        testCases: testCases.length,
+      },
+      blockingIssues,
+      progressPercentage: Math.round(progressPercentage * 100) / 100,
+    };
+  }
+ 
+  /**
+   * Find all blocking issues
+   */
+  getBlockingIssues(type?: "all" | "critical" | "features" | "tests"): Task[] {
+    const blocked = Array.from(this.tasks.values()).filter((t) => t.status === "blocked");
+ 
+    Iif (type === "critical") {
+      return blocked.filter((t) => t.blockedBy && t.blockedBy.length > 2);
+    }
+ 
+    Iif (type === "features") {
+      return blocked.filter((t) => {
+        const feature = this.features.get(t.featureId || "");
+        return feature && feature.status !== "completed";
+      });
+    }
+ 
+    return blocked;
+  }
+ 
+  /**
+   * Create a new feature
+   * Phase 2d: Memgraph persistence is mandatory
+   */
+  async createFeature(feature: Feature): Promise<Feature> {
+    Eif (!this.memgraph || !this.memgraph.isConnected()) {
+      throw new Error(
+        "[ProgressEngine] Cannot create feature: Memgraph is not connected. Feature persistence to database is mandatory.",
+      );
+    }
+ 
+    feature.startedAt = Date.now();
+ 
+    try {
+      const result = await this.memgraph.executeCypher(
+        `MERGE (f:FEATURE {id: $id})
+         SET f.name = $name, f.status = $status,
+             f.description = $description, f.startedAt = $startedAt,
+             f.createdAt = $createdAt, f.projectId = $projectId`,
+        {
+          id: feature.id,
+          name: feature.name,
+          status: feature.status,
+          description: feature.description ?? null,
+          startedAt: feature.startedAt,
+          createdAt: Date.now(),
+          projectId: extractProjectIdFromScopedId(feature.id),
+        },
+      );
+ 
+      if (result.error) {
+        throw new Error(`[ProgressEngine] Failed to persist feature to Memgraph: ${result.error}`);
+      }
+ 
+      // Only add to in-memory map after successful persistence
+      this.features.set(feature.id, feature);
+      logger.error(`[Phase2d] Feature ${feature.id} created and persisted to Memgraph`);
+      return feature;
+    } catch (err) {
+      throw new Error(
+        `[ProgressEngine] Failed to create feature: ${err instanceof Error ? err.message : String(err)}`,
+        { cause: err },
+      );
+    }
+  }
+ 
+  /**
+   * Create a new task
+   * Phase 2d: Memgraph persistence is mandatory
+   */
+  async createTask(task: Task): Promise<Task> {
+    if (!this.memgraph || !this.memgraph.isConnected()) {
+      throw new Error(
+        "[ProgressEngine] Cannot create task: Memgraph is not connected. Task persistence to database is mandatory.",
+      );
+    }
+ 
+    try {
+      const result = await this.memgraph.executeCypher(
+        `MERGE (t:TASK {id: $id})
+         SET t.name = $name, t.status = $status,
+             t.description = $description, t.createdAt = $createdAt,
+             t.featureId = $featureId, t.assignee = $assignee,
+             t.dueDate = $dueDate, t.projectId = $projectId`,
+        {
+          id: task.id,
+          name: task.name,
+          status: task.status,
+          description: task.description ?? null,
+          createdAt: Date.now(),
+          featureId: task.featureId ?? null,
+          assignee: task.assignee ?? null,
+          dueDate: task.dueDate ?? null,
+          projectId: extractProjectIdFromScopedId(task.id),
+        },
+      );
+ 
+      if (result.error) {
+        throw new Error(`[ProgressEngine] Failed to persist task to Memgraph: ${result.error}`);
+      }
+ 
+      // Only add to in-memory map after successful persistence
+      this.tasks.set(task.id, task);
+      logger.error(`[Phase2d] Task ${task.id} created and persisted to Memgraph`);
+      return task;
+    } catch (err) {
+      throw new Error(
+        `[ProgressEngine] Failed to create task: ${err instanceof Error ? err.message : String(err)}`,
+        { cause: err },
+      );
+    }
+  }
+ 
+  /**
+   * Persist task update to Memgraph (Phase 5.3)
+   */
+  async persistTaskUpdate(taskId: string, updates: Partial<Task>): Promise<boolean> {
+    Iif (!this.memgraph || !this.memgraph.isConnected()) {
+      return false;
+    }
+ 
+    try {
+      const statement: CypherStatement = {
+        query: `
+          MATCH (t:TASK {id: $taskId})
+          SET t.status = $status,
+              t.updatedAt = timestamp()
+              ${updates.description ? ", t.description = $description" : ""}
+              ${updates.startedAt ? ", t.startedAt = $startedAt" : ""}
+              ${updates.completedAt ? ", t.completedAt = $completedAt" : ""}
+        `,
+        params: {
+          taskId,
+          status: updates.status,
+          description: updates.description,
+          startedAt: updates.startedAt,
+          completedAt: updates.completedAt,
+        },
+      };
+ 
+      const result = await this.memgraph.executeCypher(statement.query, statement.params);
+      return !result.error;
+    } catch (error) {
+      logger.error("[ProgressEngine] Failed to persist task update:", error);
+      return false;
+    }
+  }
+ 
+  /**
+   * Persist feature update to Memgraph (Phase 5.3)
+   */
+  async persistFeatureUpdate(featureId: string, updates: Partial<Feature>): Promise<boolean> {
+    if (!this.memgraph || !this.memgraph.isConnected()) {
+      return false;
+    }
+ 
+    try {
+      const statement: CypherStatement = {
+        query: `
+          MATCH (f:FEATURE {id: $featureId})
+          SET f.status = $status,
+              f.updatedAt = timestamp()
+              ${updates.description ? ", f.description = $description" : ""}
+              ${updates.startedAt ? ", f.startedAt = $startedAt" : ""}
+              ${updates.completedAt ? ", f.completedAt = $completedAt" : ""}
+        `,
+        params: {
+          featureId,
+          status: updates.status,
+          description: updates.description,
+          startedAt: updates.startedAt,
+          completedAt: updates.completedAt,
+        },
+      };
+ 
+      const result = await this.memgraph.executeCypher(statement.query, statement.params);
+      return !result.error;
+    } catch (error) {
+      logger.error("[ProgressEngine] Failed to persist feature update:", error);
+      return false;
+    }
+  }
+ 
+  /**
+   * Reload engine state from updated graph index
+   * Called when project context changes to refresh feature/task data
+   */
+  reload(index: GraphIndexManager, projectId?: string): void {
+    logger.error(`[ProgressEngine] Reloading features and tasks (projectId=${projectId})`);
+ 
+    this.index = index;
+    this.features.clear();
+    this.tasks.clear();
+    this.loadFromGraph();
+ 
+    // Filter by projectId if provided
+    Eif (projectId) {
+      for (const [id] of this.features.entries()) {
+        if (!id.startsWith(`${projectId}:`)) {
+          this.features.delete(id);
+        }
+      }
+ 
+      for (const [id] of this.tasks.entries()) {
+        if (!id.startsWith(`${projectId}:`)) {
+          this.tasks.delete(id);
+        }
+      }
+    }
+ 
+    const featureCount = this.features.size;
+    const taskCount = this.tasks.size;
+    logger.error(`[ProgressEngine] Reloaded ${featureCount} features and ${taskCount} tasks`);
+  }
+ 
+  /**
+   * Export progress data to JSON
+   */
+  export(): string {
+    return JSON.stringify(
+      {
+        features: Array.from(this.features.values()),
+        tasks: Array.from(this.tasks.values()),
+        statistics: {
+          totalFeatures: this.features.size,
+          completedFeatures: Array.from(this.features.values()).filter(
+            (f) => f.status === "completed",
+          ).length,
+          totalTasks: this.tasks.size,
+          completedTasks: Array.from(this.tasks.values()).filter((t) => t.status === "completed")
+            .length,
+          blockedTasks: Array.from(this.tasks.values()).filter((t) => t.status === "blocked")
+            .length,
+        },
+      },
+      null,
+      2,
+    );
+  }
+}
+ 
+export default ProgressEngine;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/engines/test-engine.ts.html b/coverage/lcov-report/src/engines/test-engine.ts.html new file mode 100644 index 0000000..373e43c --- /dev/null +++ b/coverage/lcov-report/src/engines/test-engine.ts.html @@ -0,0 +1,1360 @@ + + + + + + Code coverage report for src/engines/test-engine.ts + + + + + + + + + +
+
+

All files / src/engines test-engine.ts

+
+ +
+ 83.22% + Statements + 124/149 +
+ + +
+ 72.22% + Branches + 78/108 +
+ + +
+ 86.36% + Functions + 19/22 +
+ + +
+ 86.66% + Lines + 117/135 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +151x +151x +151x +151x +  +  +  +  +  +  +172x +  +172x +35x +35x +35x +  +  +35x +  +48x +  +  +35x +24x +  +24x +  +24x +24x +24x +  +  +24x +24x +  +  +  +24x +  +12x +24x +12x +12x +12x +  +  +  +  +  +  +  +35x +72x +72x +24x +24x +  +  +  +35x +  +35x +  +  +  +  +  +  +35x +35x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +35x +  +35x +  +  +  +  +  +  +  +14x +  +  +21x +  +  +  +  +  +  +3x +  +  +18x +3x +  +15x +  +  +  +  +  +  +  +  +  +  +12x +12x +  +  +15x +  +  +12x +15x +27x +27x +  +  +27x +  +  +25x +11x +11x +11x +  +  +  +14x +  +  +  +  +  +  +  +  +  +12x +3x +3x +3x +  +  +  +  +12x +12x +12x +  +  +12x +12x +12x +12x +  +  +12x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +3x +3x +1x +  +  +  +3x +3x +3x +1x +  +  +  +3x +  +  +  +  +  +  +  +  +  +3x +3x +3x +3x +  +  +  +  +  +  +12x +12x +12x +  +12x +12x +12x +  +12x +12x +12x +  +  +12x +  +  +  +2x +  +  +10x +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +21x +  +21x +21x +21x +21x +  +21x +21x +  +  +  +  +  +  +  +  +  +  +  +  +  +13x +13x +13x +13x +13x +  +13x +14x +  +4x +4x +  +4x +4x +  +3x +3x +  +3x +3x +  +14x +  +  +13x +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file engines/test-engine
+ * @description Selects and categorizes tests based on dependency impact analysis.
+ * @remarks Used by tool handlers to drive targeted and risk-aware test execution.
+ */
+ 
+import * as path from "path";
+import type { GraphIndexManager } from "../graph/index.js";
+import { logger } from "../utils/logger.js";
+ 
+export interface TestMetadata {
+  path: string;
+  category: "unit" | "integration" | "performance" | "e2e";
+  duration: number;
+  status: "pass" | "fail" | "unknown";
+}
+ 
+export interface TestDependencyMap {
+  [testFile: string]: {
+    directDependencies: string[];
+    indirectDependencies: string[];
+    affectedByFiles: string[];
+  };
+}
+ 
+export interface TestSelectionResult {
+  selectedTests: string[];
+  affectedSources: string[];
+  estimatedTime: number;
+  category: "unit" | "integration" | "mixed";
+  coverage: {
+    percentage: number;
+    testsSelected: number;
+    totalTests: number;
+  };
+}
+ 
+export class TestEngine {
+  private index: GraphIndexManager;
+  private testMap: Map<string, TestMetadata>;
+  private dependencyMap: TestDependencyMap;
+ 
+  constructor(index: GraphIndexManager) {
+    this.index = index;
+    this.testMap = new Map();
+    this.dependencyMap = {};
+    this.buildTestDependencies();
+  }
+ 
+  /**
+   * Build test dependency map from graph
+   */
+  private buildTestDependencies(): void {
+    const testSuites = this.index.getNodesByType("TEST_SUITE");
+ 
+    for (const suite of testSuites) {
+      const testPath = suite.properties.path;
+      const direct: string[] = [];
+      const indirect: string[] = [];
+ 
+      // Find all test cases in this suite
+      const testCases = this.index
+        .getNodesByType("TEST_CASE")
+        .filter((tc) => tc.properties.path === testPath);
+ 
+      // Find what this test suite TESTS
+      for (const testCase of testCases) {
+        const testsRels = this.index
+          .getRelationshipsFrom(testCase.id)
+          .filter((r) => r.type === "TESTS");
+ 
+        for (const rel of testsRels) {
+          const testedElement = this.index.getNode(rel.to);
+          Iif (!testedElement) continue;
+ 
+          // Add as direct dependency
+          Eif (testedElement.properties.path) {
+            direct.push(testedElement.properties.path);
+          }
+ 
+          // Find indirect dependencies (what the tested element imports)
+          const importRels = this.index
+            .getRelationshipsFrom(rel.to)
+            .filter((r) => r.type === "IMPORTS");
+          for (const importRel of importRels) {
+            const imported = this.index.getNode(importRel.to);
+            Eif (imported && imported.properties.source) {
+              indirect.push(imported.properties.source);
+            }
+          }
+        }
+      }
+ 
+      // Find which source files import this test
+      // (for reverse dependency tracking)
+      const nodes = this.index.getNodesByType("FILE").filter((n) => {
+        const rels = this.index.getRelationshipsFrom(n.id).filter((r) => r.type === "IMPORTS");
+        return rels.some((r) => {
+          const imp = this.index.getNode(r.to);
+          return imp && imp.properties.source === testPath;
+        });
+      });
+ 
+      const affectedBy = nodes.map((n) => n.properties.path).filter(Boolean);
+ 
+      this.dependencyMap[testPath] = {
+        directDependencies: Array.from(new Set(direct)),
+        indirectDependencies: Array.from(new Set(indirect)),
+        affectedByFiles: affectedBy,
+      };
+ 
+      // Store metadata
+      const category = this.categorizeTest(testPath);
+      this.testMap.set(testPath, {
+        path: testPath,
+        category,
+        duration: suite.properties.avgDuration || 0,
+        status: suite.properties.lastStatus || "unknown",
+      });
+    }
+  }
+ 
+  /**
+   * Categorize test based on path and naming conventions.
+   * Handles JS/TS (.integration.test.*), Python (test_*_integration.py,
+   * *_integration_test.py), Go (*_integration_test.go), and Ruby
+   * (integration/..*_spec.rb) conventions.
+   */
+  private categorizeTest(testPath: string): "unit" | "integration" | "performance" | "e2e" {
+    const p = testPath.toLowerCase();
+    // Integration: any language
+    if (
+      p.includes(".integration.test.") ||
+      p.includes("_integration_test.") ||
+      p.includes("_integration_spec.") ||
+      p.includes("/integration/") ||
+      p.includes("/integration_") ||
+      p.includes("test_integration_")
+    ) {
+      return "integration";
+    }
+    // Performance: any language
+    if (
+      p.includes(".performance.test.") ||
+      p.includes("_performance_test.") ||
+      p.includes("_bench_test.") ||
+      p.includes("_benchmark") ||
+      p.includes("/benchmarks/")
+    ) {
+      return "performance";
+    }
+    // E2E: any language
+    if (p.includes("/e2e/") || p.includes("/end_to_end/") || p.includes("_e2e_")) {
+      return "e2e";
+    }
+    return "unit";
+  }
+ 
+  /**
+   * Select tests affected by changed files
+   */
+  selectAffectedTests(
+    changedFiles: string[],
+    includeIntegration = true,
+    depth = 1,
+  ): TestSelectionResult {
+    const selected = new Set<string>();
+    const affectedSources = new Set<string>();
+ 
+    // Normalize changed file paths
+    const normalizedChanges = changedFiles.map((f) => this.normalizePath(f));
+ 
+    // For each changed file, find tests that depend on it
+    for (const changedFile of normalizedChanges) {
+      for (const [testPath, deps] of Object.entries(this.dependencyMap)) {
+        const testMeta = this.testMap.get(testPath);
+        Iif (!testMeta) continue;
+ 
+        // Skip non-selected test categories
+        if (!includeIntegration && testMeta.category === "integration") continue;
+ 
+        // Check direct dependencies
+        if (deps.directDependencies.includes(changedFile)) {
+          selected.add(testPath);
+          affectedSources.add(changedFile);
+          continue;
+        }
+ 
+        // Check indirect dependencies (up to depth)
+        Iif (depth > 1 && this.isIndirectlyDependentOn(changedFile, testPath, depth - 1)) {
+          selected.add(testPath);
+          affectedSources.add(changedFile);
+          continue;
+        }
+      }
+    }
+ 
+    // If no tests directly depend on changed file, include related tests
+    // (e.g., if a utility changed, run tests that use that utility)
+    if (selected.size === 0) {
+      for (const changedFile of normalizedChanges) {
+        const relatedTests = this.findRelatedTests(changedFile);
+        relatedTests.forEach((t) => selected.add(t));
+      }
+    }
+ 
+    // Calculate coverage percentage
+    const totalTests = this.testMap.size;
+    const selectedCount = selected.size;
+    const coverage = totalTests > 0 ? (selectedCount / totalTests) * 100 : 0;
+ 
+    // Estimate total time
+    let estimatedTime = 0;
+    selected.forEach((test) => {
+      const meta = this.testMap.get(test);
+      Eif (meta) estimatedTime += meta.duration;
+    });
+ 
+    return {
+      selectedTests: Array.from(selected).sort(),
+      affectedSources: Array.from(affectedSources),
+      estimatedTime,
+      category: this.determineCategory(selected),
+      coverage: {
+        percentage: Math.round(coverage * 100) / 100,
+        testsSelected: selectedCount,
+        totalTests,
+      },
+    };
+  }
+ 
+  /**
+   * Find tests that are indirectly affected (via transitive dependencies)
+   */
+  private isIndirectlyDependentOn(
+    changedFile: string,
+    testPath: string,
+    remainingDepth: number,
+  ): boolean {
+    const deps = this.dependencyMap[testPath];
+    if (!deps) return false;
+ 
+    // Check if any direct dependency imports the changed file
+    for (const direct of deps.directDependencies) {
+      if (direct === changedFile) return true;
+ 
+      // Recursively check if this direct dependency has indirect dependencies
+      // that eventually lead to the changed file
+      if (remainingDepth > 0 && this.transitiveImportSearch(changedFile, direct, remainingDepth)) {
+        return true;
+      }
+    }
+ 
+    return false;
+  }
+ 
+  /**
+   * Search for transitive imports (what a file imports and what those imports import)
+   */
+  private transitiveImportSearch(
+    changedFile: string,
+    fromFile: string,
+    remainingDepth: number,
+  ): boolean {
+    // Look for tests that import fromFile and check if they import changedFile
+    for (const [testPath, deps] of Object.entries(this.dependencyMap)) {
+      // If this test imports fromFile
+      if (
+        deps.directDependencies.includes(fromFile) ||
+        deps.indirectDependencies.includes(fromFile)
+      ) {
+        // Check if this test also imports changedFile
+        if (
+          deps.directDependencies.includes(changedFile) ||
+          deps.indirectDependencies.includes(changedFile)
+        ) {
+          return true;
+        }
+ 
+        // Recursively check deeper if we have remaining depth
+        if (remainingDepth > 1) {
+          if (this.transitiveImportSearch(changedFile, testPath, remainingDepth - 1)) {
+            return true;
+          }
+        }
+      }
+    }
+ 
+    return false;
+  }
+ 
+  /**
+   * Find tests related to a file
+   */
+  private findRelatedTests(filePath: string): string[] {
+    const related: string[] = [];
+ 
+    // Find test file that mirrors this source file
+    // e.g., src/utils/units.ts → src/utils/__tests__/units.test.ts
+    const mirrorTestPath = this.getMirrorTestPath(filePath);
+    if (this.testMap.has(mirrorTestPath)) {
+      related.push(mirrorTestPath);
+    }
+ 
+    // Find tests in same folder
+    const folder = path.dirname(filePath);
+    for (const [testPath] of this.testMap) {
+      if (testPath.includes(folder) && testPath.includes(".test.")) {
+        related.push(testPath);
+      }
+    }
+ 
+    return Array.from(new Set(related));
+  }
+ 
+  /**
+   * Get mirror test path for a source file, preserving the source extension.
+   * e.g. src/utils/units.ts  → src/utils/__tests__/units.test.ts
+   *      src/utils/helpers.py → src/utils/__tests__/helpers.test.py
+   *      lib/foo.rb           → lib/__tests__/foo.test.rb
+   */
+  private getMirrorTestPath(sourcePath: string): string {
+    const dir = path.dirname(sourcePath);
+    const ext = path.extname(sourcePath);
+    const base = path.basename(sourcePath, ext);
+    return `${dir}/__tests__/${base}.test${ext}`;
+  }
+ 
+  /**
+   * Determine overall test category
+   */
+  private determineCategory(testPaths: Set<string>): "unit" | "integration" | "mixed" {
+    let hasUnit = false;
+    let hasIntegration = false;
+    let hasPerformance = false;
+ 
+    for (const testPath of testPaths) {
+      const meta = this.testMap.get(testPath);
+      Iif (!meta) continue;
+ 
+      if (meta.category === "unit") hasUnit = true;
+      if (meta.category === "integration") hasIntegration = true;
+      Iif (meta.category === "performance") hasPerformance = true;
+    }
+ 
+    if (
+      (hasUnit || hasIntegration || hasPerformance) &&
+      (hasUnit ? 1 : 0) + (hasIntegration ? 1 : 0) + (hasPerformance ? 1 : 0) > 1
+    ) {
+      return "mixed";
+    }
+ 
+    return hasIntegration ? "integration" : "unit";
+  }
+ 
+  /**
+   * Normalize file path
+   */
+  private normalizePath(filePath: string): string {
+    return filePath.replace(/\\/g, "/").replace(/^\.\//, "");
+  }
+ 
+  /**
+   * Reload engine state from updated graph index
+   * Called when project context changes to refresh test data
+   */
+  reload(index: GraphIndexManager, projectId?: string): void {
+    logger.debug("TestEngine reloading tests", { projectId });
+ 
+    this.index = index;
+    this.testMap.clear();
+    this.dependencyMap = {};
+    this.buildTestDependencies();
+ 
+    const testCount = this.testMap.size;
+    logger.debug("TestEngine reloaded", { testCount, projectId });
+  }
+ 
+  /**
+   * Get test statistics
+   */
+  getStatistics(): {
+    totalTests: number;
+    unitTests: number;
+    integrationTests: number;
+    performanceTests: number;
+    e2eTests: number;
+    averageDuration: number;
+  } {
+    let unitCount = 0;
+    let integrationCount = 0;
+    let performanceCount = 0;
+    let e2eCount = 0;
+    let totalDuration = 0;
+ 
+    for (const meta of this.testMap.values()) {
+      switch (meta.category) {
+        case "unit":
+          unitCount++;
+          break;
+        case "integration":
+          integrationCount++;
+          break;
+        case "performance":
+          performanceCount++;
+          break;
+        case "e2e":
+          e2eCount++;
+          break;
+      }
+      totalDuration += meta.duration;
+    }
+ 
+    return {
+      totalTests: this.testMap.size,
+      unitTests: unitCount,
+      integrationTests: integrationCount,
+      performanceTests: performanceCount,
+      e2eTests: e2eCount,
+      averageDuration: this.testMap.size > 0 ? totalDuration / this.testMap.size : 0,
+    };
+  }
+}
+ 
+export default TestEngine;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/env.ts.html b/coverage/lcov-report/src/env.ts.html new file mode 100644 index 0000000..8dae025 --- /dev/null +++ b/coverage/lcov-report/src/env.ts.html @@ -0,0 +1,961 @@ + + + + + + Code coverage report for src/env.ts + + + + + + + + + +
+
+

All files / src env.ts

+
+ +
+ 100% + Statements + 39/39 +
+ + +
+ 85.41% + Branches + 41/48 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 39/39 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +10x +  +  +  +  +10x +  +  +  +  +  +  +10x +10x +10x +  +  +  +  +  +  +  +  +10x +  +  +10x +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +10x +  +  +  +  +  +  +10x +  +  +10x +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +10x +  +  +10x +  +  +  +  +  +  +  +  +10x +  +  +10x +  +  +  +  +  +  +  +  +10x +  +  +10x +  +  +  +  +  +  +  +  +  +10x +  +  +10x +  +  +  +  +  +  +10x +  +10x +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +10x +  +  +10x +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +10x + 
/**
+ * Centralized environment configuration.
+ *
+ * This is the ONLY place in the codebase that reads `process.env`.
+ * Every other module imports the constants it needs from here.
+ *
+ * Copy `.env.example` to `.env` and adjust the values for your setup.
+ */
+ 
+import * as dotenv from "dotenv";
+import * as path from "path";
+ 
+// Load .env file as early as possible so all subsequent reads see the values.
+dotenv.config();
+ 
+// ── Workspace / Project ───────────────────────────────────────────────────────
+ 
+/**
+ * Absolute path to the workspace being indexed.
+ * Env: LXRAG_WORKSPACE_ROOT
+ * Default: process.cwd()
+ */
+export const LXRAG_WORKSPACE_ROOT: string = path.resolve(
+  process.env.LXRAG_WORKSPACE_ROOT || process.cwd(),
+);
+ 
+// Alias for backward compatibility
+export const CODE_GRAPH_WORKSPACE_ROOT = LXRAG_WORKSPACE_ROOT;
+ 
+/**
+ * Source sub-directory to index. Can be absolute or relative to WORKSPACE_ROOT.
+ * Env: GRAPH_SOURCE_DIR
+ * Default: <WORKSPACE_ROOT>/src
+ */
+export const GRAPH_SOURCE_DIR: string = (() => {
+  const raw = process.env.GRAPH_SOURCE_DIR || path.join(LXRAG_WORKSPACE_ROOT, "src");
+  return path.isAbsolute(raw) ? raw : path.resolve(LXRAG_WORKSPACE_ROOT, raw);
+})();
+ 
+/**
+ * Logical project identifier used as a namespace in the graph.
+ * Env: LXRAG_PROJECT_ID
+ * Default: basename of LXRAG_WORKSPACE_ROOT
+ */
+export const LXRAG_PROJECT_ID: string =
+  process.env.LXRAG_PROJECT_ID || path.basename(LXRAG_WORKSPACE_ROOT);
+ 
+// Alias for backward compatibility
+export const CODE_GRAPH_PROJECT_ID = LXRAG_PROJECT_ID;
+ 
+/**
+ * Transaction ID for graph write operations.
+ * Env: LXRAG_TX_ID
+ * Default: undefined (callers generate a fresh `tx-<timestamp>` per invocation)
+ */
+export const LXRAG_TX_ID: string | undefined = process.env.LXRAG_TX_ID || undefined;
+ 
+// ── MCP Transport ─────────────────────────────────────────────────────────────
+ 
+/**
+ * Transport mode for the MCP server.
+ * Env: MCP_TRANSPORT
+ * Default: "stdio"
+ */
+export const MCP_TRANSPORT: "stdio" | "http" =
+  (process.env.MCP_TRANSPORT as "stdio" | "http") || "stdio";
+ 
+/**
+ * HTTP port when MCP_TRANSPORT=http.
+ * Env: MCP_PORT
+ * Default: 9000
+ */
+export const MCP_PORT: number = parseInt(process.env.MCP_PORT || "9000", 10);
+ 
+/**
+ * Display name reported by the MCP server.
+ * Env: LXRAG_SERVER_NAME
+ * Default: "lxRAG MCP"
+ */
+export const LXRAG_SERVER_NAME: string = process.env.LXRAG_SERVER_NAME || "lxRAG MCP";
+ 
+// Alias for backward compatibility
+export const CODE_GRAPH_SERVER_NAME = LXRAG_SERVER_NAME;
+ 
+// ── Memgraph (graph database) ─────────────────────────────────────────────────
+ 
+/**
+ * Hostname of the Memgraph instance.
+ * Env: MEMGRAPH_HOST
+ * Default: "localhost"
+ */
+export const MEMGRAPH_HOST: string = process.env.MEMGRAPH_HOST || "localhost";
+ 
+/**
+ * Bolt port of the Memgraph instance.
+ * Env: MEMGRAPH_PORT
+ * Default: 7687
+ */
+export const MEMGRAPH_PORT: number = parseInt(process.env.MEMGRAPH_PORT || "7687", 10);
+ 
+// ── Qdrant (vector store) ─────────────────────────────────────────────────────
+ 
+/**
+ * Hostname of the Qdrant instance.
+ * Env: QDRANT_HOST
+ * Default: "localhost"
+ */
+export const QDRANT_HOST: string = process.env.QDRANT_HOST || "localhost";
+ 
+/**
+ * REST port of the Qdrant instance.
+ * Env: QDRANT_PORT
+ * Default: 6333
+ */
+export const QDRANT_PORT: number = parseInt(process.env.QDRANT_PORT || "6333", 10);
+ 
+// ── Code Summarizer ───────────────────────────────────────────────────────────
+ 
+/**
+ * URL of the optional LLM summarizer service (e.g. http://localhost:8080).
+ * When undefined, summarization is disabled and heuristic summaries are used.
+ * Env: LXRAG_SUMMARIZER_URL
+ */
+export const LXRAG_SUMMARIZER_URL: string | undefined =
+  process.env.LXRAG_SUMMARIZER_URL || undefined;
+ 
+// Alias for backward compatibility
+export const CODE_GRAPH_SUMMARIZER_URL = LXRAG_SUMMARIZER_URL;
+ 
+// ── Agent / Coordination ──────────────────────────────────────────────────────
+ 
+/**
+ * Identifier for the current agent instance used in coordination claims.
+ * Env: LXRAG_AGENT_ID
+ * Default: "agent-local"
+ */
+export const LXRAG_AGENT_ID: string = process.env.LXRAG_AGENT_ID || "agent-local";
+ 
+// Alias for backward compatibility
+export const CODE_GRAPH_AGENT_ID = LXRAG_AGENT_ID;
+ 
+// ── Parser ────────────────────────────────────────────────────────────────────
+ 
+/**
+ * Set to true to use the Tree-sitter parser instead of the regex parser.
+ * Env: LXRAG_USE_TREE_SITTER
+ * Default: false
+ */
+export const LXRAG_USE_TREE_SITTER: boolean = process.env.LXRAG_USE_TREE_SITTER === "true";
+ 
+// Alias for backward compatibility
+export const CODE_GRAPH_USE_TREE_SITTER = LXRAG_USE_TREE_SITTER;
+ 
+// ── File Watcher ──────────────────────────────────────────────────────────────
+ 
+/**
+ * Enables incremental file-change watching.
+ * Automatically considered true when MCP_TRANSPORT=http.
+ * Env: LXRAG_ENABLE_WATCHER
+ * Default: false
+ */
+export const LXRAG_ENABLE_WATCHER: boolean = process.env.LXRAG_ENABLE_WATCHER === "true";
+ 
+// Alias for backward compatibility
+export const CODE_GRAPH_ENABLE_WATCHER = LXRAG_ENABLE_WATCHER;
+ 
+/**
+ * Comma-separated glob patterns to exclude from indexing/watching.
+ * Env: LXRAG_IGNORE_PATTERNS
+ * Example: "node_modules/**,dist/**,.git/**"
+ */
+export const LXRAG_IGNORE_PATTERNS: string[] = (process.env.LXRAG_IGNORE_PATTERNS || "")
+  .split(",")
+  .map((p) => p.trim())
+  .filter(Boolean);
+ 
+// Alias for backward compatibility
+export const CODE_GRAPH_IGNORE_PATTERNS = LXRAG_IGNORE_PATTERNS;
+ 
+// ── Path Fallback ─────────────────────────────────────────────────────────────
+ 
+/**
+ * Allow the server to fall back to the mounted workspace path when the
+ * requested path is not accessible (useful inside Docker containers).
+ * Env: LXRAG_ALLOW_RUNTIME_PATH_FALLBACK
+ * Default: false
+ */
+export const LXRAG_ALLOW_RUNTIME_PATH_FALLBACK: boolean =
+  process.env.LXRAG_ALLOW_RUNTIME_PATH_FALLBACK === "true";
+ 
+// Alias for backward compatibility
+export const CODE_GRAPH_ALLOW_RUNTIME_PATH_FALLBACK = LXRAG_ALLOW_RUNTIME_PATH_FALLBACK;
+ 
+// ── Command Execution ──────────────────────────────────────────────────────
+ 
+/**
+ * Maximum execution time for command execution in milliseconds.
+ * Env: LXRAG_COMMAND_EXECUTION_TIMEOUT_MS
+ * Default: 30000 (30 seconds)
+ */
+export const LXRAG_COMMAND_EXECUTION_TIMEOUT_MS: number = parseInt(
+  process.env.LXRAG_COMMAND_EXECUTION_TIMEOUT_MS || "30000",
+  10,
+);
+ 
+/**
+ * Maximum time to wait synchronously for graph_rebuild before falling back
+ * to queued/background execution.
+ * Env: LXRAG_SYNC_REBUILD_THRESHOLD_MS
+ * Default: 12000 (12 seconds)
+ */
+export const LXRAG_SYNC_REBUILD_THRESHOLD_MS: number = parseInt(
+  process.env.LXRAG_SYNC_REBUILD_THRESHOLD_MS || "12000",
+  10,
+);
+ 
+/**
+ * Maximum output size for command results in bytes.
+ * Prevents DoS from commands producing massive output.
+ * Env: LXRAG_COMMAND_OUTPUT_SIZE_LIMIT_BYTES
+ * Default: 10485760 (10 MB)
+ */
+export const LXRAG_COMMAND_OUTPUT_SIZE_LIMIT_BYTES: number = parseInt(
+  process.env.LXRAG_COMMAND_OUTPUT_SIZE_LIMIT_BYTES || "10485760",
+  10,
+);
+ 
+// ── File Watcher ───────────────────────────────────────────────────────────
+ 
+/**
+ * Debounce time for file watcher in milliseconds.
+ * Env: LXRAG_WATCHER_DEBOUNCE_MS
+ * Default: 500 (500ms)
+ */
+export const LXRAG_WATCHER_DEBOUNCE_MS: number = parseInt(
+  process.env.LXRAG_WATCHER_DEBOUNCE_MS || "500",
+  10,
+);
+ 
+// ── Connection Pools ────────────────────────────────────────────────────────
+ 
+/**
+ * Maximum Memgraph connection pool size.
+ * Env: LXRAG_MEMGRAPH_MAX_POOL_SIZE
+ * Default: 50
+ */
+export const LXRAG_MEMGRAPH_MAX_POOL_SIZE: number = parseInt(
+  process.env.LXRAG_MEMGRAPH_MAX_POOL_SIZE || "50",
+  10,
+);
+ 
+/**
+ * Memgraph connection acquisition timeout in milliseconds.
+ * Env: LXRAG_MEMGRAPH_CONNECTION_TIMEOUT_MS
+ * Default: 10000 (10 seconds)
+ */
+export const LXRAG_MEMGRAPH_CONNECTION_TIMEOUT_MS: number = parseInt(
+  process.env.LXRAG_MEMGRAPH_CONNECTION_TIMEOUT_MS || "10000",
+  10,
+);
+ 
+/**
+ * Memgraph connection liveness check timeout in milliseconds.
+ * Env: LXRAG_MEMGRAPH_LIVENESS_TIMEOUT_MS
+ * Default: 5000 (5 seconds)
+ */
+export const LXRAG_MEMGRAPH_LIVENESS_TIMEOUT_MS: number = parseInt(
+  process.env.LXRAG_MEMGRAPH_LIVENESS_TIMEOUT_MS || "5000",
+  10,
+);
+ 
+// ── State Management ────────────────────────────────────────────────────────
+ 
+/**
+ * Maximum state history size (bounded for memory efficiency).
+ * Env: LXRAG_STATE_HISTORY_MAX_SIZE
+ * Default: 200 entries
+ */
+export const LXRAG_STATE_HISTORY_MAX_SIZE: number = parseInt(
+  process.env.LXRAG_STATE_HISTORY_MAX_SIZE || "200",
+  10,
+);
+ 
+// ── Logging ───────────────────────────────────────────────────────────────────
+ 
+/**
+ * Minimum log level emitted by the structured logger.
+ * Env: LXRAG_LOG_LEVEL
+ * Accepted values: "debug" | "info" | "warn" | "error"
+ * Default: "info"
+ */
+export const LXRAG_LOG_LEVEL: string = process.env.LXRAG_LOG_LEVEL ?? "info";
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/builder.ts.html b/coverage/lcov-report/src/graph/builder.ts.html new file mode 100644 index 0000000..756facb --- /dev/null +++ b/coverage/lcov-report/src/graph/builder.ts.html @@ -0,0 +1,2269 @@ + + + + + + Code coverage report for src/graph/builder.ts + + + + + + + + + +
+
+

All files / src/graph builder.ts

+
+ +
+ 75.59% + Statements + 96/127 +
+ + +
+ 55.55% + Branches + 65/117 +
+ + +
+ 83.33% + Functions + 20/24 +
+ + +
+ 80.55% + Lines + 87/108 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +133x +133x +  +  +  +  +  +  +133x +133x +133x +133x +  +  +  +144x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +14x +14x +4x +  +3x +3x +  +  +  +  +22x +22x +  +  +  +  +  +  +  +110x +  +  +  +10x +10x +  +  +10x +  +  +10x +  +  +10x +  +  +10x +  +  +10x +  +  +10x +  +  +10x +  +10x +  +  +  +  +10x +10x +10x +10x +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +10x +10x +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +40x +40x +40x +  +40x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +40x +40x +30x +  +  +30x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +10x +10x +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +4x +4x +4x +  +  +  +  +  +  +4x +20x +  +  +  +4x +  +  +  +  + 
/**
+ * @file graph/builder
+ * @description Translates parsed source artifacts into Cypher statements for graph persistence.
+ * @remarks Declares local parsed-file contracts to avoid parser dependency coupling.
+ */
+ 
+// Local type definitions (avoid importing from typescript-parser which has dependencies)
+export interface ParsedFile {
+  path: string;
+  filePath: string;
+  relativePath?: string;
+  language?: string;
+  LOC?: number;
+  hash?: string;
+  summary?: string;
+  imports: Array<{ source: string; specifiers: string[]; summary?: string }>;
+  exports: Array<{ name: string; type: string }>;
+  functions: FunctionNode[];
+  classes: ClassNode[];
+  variables?: any[];
+  testSuites?: Array<{
+    id: string;
+    name: string;
+    type: "describe" | "test" | "it";
+    startLine: number;
+    endLine?: number;
+    category?: "unit" | "integration" | "performance" | "e2e";
+    filePath?: string;
+  }>;
+  testCases?: Array<{
+    id: string;
+    name: string;
+    startLine: number;
+    endLine?: number;
+    parentSuiteId?: string;
+  }>;
+}
+ 
+interface FunctionNode {
+  name: string;
+  parameters: Array<{ name: string; type?: string }>;
+  returnType?: string;
+  async: boolean;
+  line: number;
+  id?: string;
+  kind?: string;
+  startLine?: number;
+  endLine?: number;
+  LOC?: number;
+  isExported?: boolean;
+  summary?: string;
+}
+ 
+interface ClassNode {
+  id: string;
+  name: string;
+  methods: Array<{ name: string; parameters: any[]; returnType?: string }>;
+  properties: Array<{ name: string; type?: string }>;
+  line: number;
+  implements?: string[];
+  kind?: string;
+  startLine?: number;
+  endLine?: number;
+  LOC?: number;
+  extends?: string;
+  isExported?: boolean;
+  summary?: string;
+}
+ 
+import * as path from "path";
+import { existsSync } from "fs";
+import * as env from "../env.js";
+ 
+export interface CypherStatement {
+  query: string;
+  params: Record<string, any>;
+}
+ 
+export class GraphBuilder {
+  private statements: CypherStatement[] = [];
+  private processedNodes = new Set<string>();
+  private projectId: string;
+  private workspaceRoot: string;
+  private txId: string;
+  private txTimestamp: number;
+ 
+  constructor(projectId?: string, workspaceRoot?: string, txId?: string, txTimestamp?: number) {
+    this.workspaceRoot = workspaceRoot || env.LXRAG_WORKSPACE_ROOT || process.cwd();
+    this.projectId = projectId || env.LXRAG_PROJECT_ID || path.basename(this.workspaceRoot);
+    this.txId = txId || env.LXRAG_TX_ID || `tx-${Date.now()}`;
+    this.txTimestamp = txTimestamp || Date.now();
+  }
+ 
+  private scopedId(rawId: string): string {
+    return `${this.projectId}:${rawId}`;
+  }
+ 
+  /**
+   * Compute a SCIP-style symbol descriptor for a node.
+   * Format follows the SCIP spec descriptor syntax:
+   *   File     → "{relPath}"
+   *   Function → "{relPath}::{name}()"
+   *   Method   → "{relPath}::{ClassName}#{name}()"
+   *   Class    → "{relPath}::{name}#"
+   */
+  private toScipId(
+    kind: "file" | "function" | "class",
+    relPath: string,
+    name?: string,
+    scopePath?: string,
+  ): string {
+    const clean = relPath.replace(/\\/g, "/");
+    if (kind === "file") return clean;
+    if (kind === "class") return `${clean}::${name}#`;
+    // function / method
+    Iif (scopePath) return `${clean}::${scopePath}#${name}()`;
+    return `${clean}::${name}()`;
+  }
+ 
+  private fileNodeId(parsedFile: ParsedFile): string {
+    const relativePath =
+      parsedFile.relativePath || path.relative(this.workspaceRoot, parsedFile.filePath);
+    return this.scopedId(`file:${relativePath}`);
+  }
+ 
+  private fileNodeIdFromRelative(relativePath: string): string {
+    return this.scopedId(`file:${relativePath}`);
+  }
+ 
+  private folderNodeId(folderPath: string): string {
+    return this.scopedId(`folder:${folderPath}`);
+  }
+ 
+  buildFromParsedFile(parsedFile: ParsedFile): CypherStatement[] {
+    this.statements = [];
+    this.processedNodes.clear();
+ 
+    // Create FILE node
+    this.createFileNode(parsedFile);
+ 
+    // Create FUNCTION nodes and relationships
+    parsedFile.functions.forEach((fn) => this.createFunctionNode(fn, parsedFile));
+ 
+    // Create CLASS nodes and relationships
+    parsedFile.classes.forEach((cls) => this.createClassNode(cls, parsedFile));
+ 
+    // Create VARIABLE nodes
+    parsedFile.variables?.forEach((variable) => this.createVariableNode(variable, parsedFile));
+ 
+    // Create IMPORT nodes and relationships
+    parsedFile.imports?.forEach((imp) => this.createImportNode(imp, parsedFile));
+ 
+    // Create EXPORT nodes
+    parsedFile.exports?.forEach((exp) => this.createExportNode(exp, parsedFile));
+ 
+    // Create TEST_SUITE nodes (if this is a test file)
+    this.buildTestNodes(parsedFile);
+ 
+    return this.statements;
+  }
+ 
+  private createFileNode(parsedFile: ParsedFile): void {
+    const relativePath =
+      parsedFile.relativePath || path.relative(this.workspaceRoot, parsedFile.filePath);
+    const nodeId = this.fileNodeId(parsedFile);
+    Iif (this.processedNodes.has(nodeId)) return;
+    this.processedNodes.add(nodeId);
+ 
+    const statement: CypherStatement = {
+      query: `
+        MERGE (f:FILE {id: $id})
+        SET f.name = $name,
+            f.path = $path,
+            f.language = $language,
+            f.LOC = $LOC,
+          f.summary = $summary,
+            f.hash = $hash,
+            f.relativePath = $relativePath,
+            f.scipId = $scipId,
+            f.projectId = $projectId,
+          f.validFrom = $validFrom,
+          f.validTo = $validTo,
+          f.createdAt = $createdAt,
+          f.txId = $txId,
+            f.lastModified = datetime()
+      `,
+      params: {
+        id: nodeId,
+        path: parsedFile.filePath,
+        name: path.basename(parsedFile.filePath),
+        language: parsedFile.language || "TypeScript",
+        LOC: parsedFile.LOC || 0,
+        summary: parsedFile.summary || null,
+        hash: parsedFile.hash || "",
+        relativePath: relativePath,
+        scipId: this.toScipId("file", relativePath),
+        projectId: this.projectId,
+        validFrom: this.txTimestamp,
+        validTo: null,
+        createdAt: this.txTimestamp,
+        txId: this.txId,
+      },
+    };
+    this.statements.push(statement);
+ 
+    // Create folder hierarchy
+    const folderPath = path.dirname(parsedFile.filePath);
+    this.createFolderHierarchy(folderPath);
+ 
+    // Connect FILE to FOLDER
+    this.statements.push({
+      query: `
+        MATCH (f:FILE {id: $fileId})
+        MERGE (folder:FOLDER {id: $folderId})
+        SET folder.path = $folderPath,
+            folder.projectId = $projectId
+        MERGE (folder)-[:CONTAINS]->(f)
+      `,
+      params: {
+        fileId: nodeId,
+        folderId: this.folderNodeId(folderPath),
+        folderPath,
+        projectId: this.projectId,
+      },
+    });
+  }
+ 
+  private createFolderHierarchy(folderPath: string): void {
+    const nodeId = this.folderNodeId(folderPath);
+    Iif (this.processedNodes.has(nodeId)) return;
+    this.processedNodes.add(nodeId);
+ 
+    this.statements.push({
+      query: `
+        MERGE (folder:FOLDER {id: $id})
+        SET folder.name = $name,
+            folder.path = $path,
+            folder.projectId = $projectId
+      `,
+      params: {
+        id: nodeId,
+        path: folderPath,
+        name: path.basename(folderPath),
+        projectId: this.projectId,
+      },
+    });
+ 
+    const parentPath = path.dirname(folderPath);
+    if (parentPath !== folderPath) {
+      this.createFolderHierarchy(parentPath);
+ 
+      // Connect parent to child
+      this.statements.push({
+        query: `
+          MATCH (parent:FOLDER {id: $parentId})
+          MATCH (child:FOLDER {id: $childId})
+          MERGE (parent)-[:CONTAINS]->(child)
+        `,
+        params: {
+          parentId: this.folderNodeId(parentPath),
+          childId: this.folderNodeId(folderPath),
+        },
+      });
+    }
+  }
+ 
+  private createFunctionNode(fn: FunctionNode, parsedFile: ParsedFile): void {
+    const nodeId = this.scopedId(fn.id || `func:${parsedFile.relativePath}:${fn.name}:${fn.line}`);
+    Iif (this.processedNodes.has(nodeId)) return;
+    this.processedNodes.add(nodeId);
+ 
+    this.statements.push({
+      query: `
+        MERGE (func:FUNCTION {id: $id})
+        SET func.name = $name,
+            func.kind = $kind,
+          func.filePath = $filePath,
+          func.path = $path,
+          func.relativePath = $relativePath,
+            func.startLine = $startLine,
+            func.endLine = $endLine,
+            func.LOC = $LOC,
+          func.summary = $summary,
+            func.parameters = $parameters,
+            func.scipId = $scipId,
+          func.validFrom = $validFrom,
+          func.validTo = $validTo,
+          func.createdAt = $createdAt,
+          func.txId = $txId,
+            func.projectId = $projectId
+      `,
+      params: {
+        id: nodeId,
+        name: fn.name,
+        kind: fn.kind || "function",
+        filePath: parsedFile.filePath,
+        path: parsedFile.filePath,
+        relativePath: parsedFile.relativePath || parsedFile.filePath,
+        startLine: fn.startLine || fn.line || 0,
+        endLine: fn.endLine || fn.line || 0,
+        LOC: fn.LOC || 1,
+        summary: fn.summary || null,
+        // Memgraph only supports lists of primitives as properties; serialize objects to JSON string
+        parameters: JSON.stringify(fn.parameters),
+        scipId: this.toScipId(
+          "function",
+          parsedFile.relativePath || "",
+          fn.name,
+          (fn as any).scopePath,
+        ),
+        validFrom: this.txTimestamp,
+        validTo: null,
+        createdAt: this.txTimestamp,
+        txId: this.txId,
+        projectId: this.projectId,
+      },
+    });
+ 
+    // Connect function to file
+    this.statements.push({
+      query: `
+        MATCH (func:FUNCTION {id: $funcId})
+        MATCH (f:FILE {id: $fileId})
+        MERGE (f)-[:CONTAINS]->(func)
+      `,
+      params: {
+        funcId: nodeId,
+        fileId: this.fileNodeId(parsedFile),
+      },
+    });
+ 
+    // Tag as exported if applicable
+    Eif (fn.isExported) {
+      this.statements.push({
+        query: `
+          MATCH (func:FUNCTION {id: $id})
+          SET func.isExported = true
+        `,
+        params: { id: nodeId },
+      });
+    }
+  }
+ 
+  private createClassNode(cls: ClassNode, parsedFile: ParsedFile): void {
+    const nodeId = this.scopedId(cls.id);
+    Iif (this.processedNodes.has(nodeId)) return;
+    this.processedNodes.add(nodeId);
+ 
+    this.statements.push({
+      query: `
+        MERGE (cls:CLASS {id: $id})
+        SET cls.name = $name,
+            cls.kind = $kind,
+          cls.filePath = $filePath,
+          cls.path = $path,
+          cls.relativePath = $relativePath,
+            cls.startLine = $startLine,
+            cls.endLine = $endLine,
+            cls.LOC = $LOC,
+          cls.summary = $summary,
+            cls.scipId = $scipId,
+          cls.validFrom = $validFrom,
+          cls.validTo = $validTo,
+          cls.createdAt = $createdAt,
+          cls.txId = $txId,
+            cls.projectId = $projectId
+      `,
+      params: {
+        id: nodeId,
+        name: cls.name,
+        kind: cls.kind || "class",
+        filePath: parsedFile.filePath,
+        path: parsedFile.filePath,
+        relativePath: parsedFile.relativePath || parsedFile.filePath,
+        startLine: cls.startLine || cls.line,
+        endLine: cls.endLine || cls.line,
+        LOC: cls.LOC || 1,
+        summary: cls.summary || null,
+        scipId: this.toScipId("class", parsedFile.relativePath || "", cls.name),
+        validFrom: this.txTimestamp,
+        validTo: null,
+        createdAt: this.txTimestamp,
+        txId: this.txId,
+        projectId: this.projectId,
+      },
+    });
+ 
+    // Connect class to file
+    this.statements.push({
+      query: `
+        MATCH (cls:CLASS {id: $classId})
+        MATCH (f:FILE {id: $fileId})
+        MERGE (f)-[:CONTAINS]->(cls)
+      `,
+      params: {
+        classId: nodeId,
+        fileId: this.fileNodeId(parsedFile),
+      },
+    });
+ 
+    // Handle inheritance
+    Iif (cls.extends) {
+      this.statements.push({
+        query: `
+          MATCH (cls:CLASS {id: $classId})
+          MERGE (parent:CLASS {id: $parentId})
+          SET parent.name = $parentName,
+              parent.projectId = $projectId
+          MERGE (cls)-[:EXTENDS]->(parent)
+        `,
+        params: {
+          classId: nodeId,
+          parentId: this.scopedId(`class:${cls.extends.split("<")[0].trim()}`),
+          parentName: cls.extends.split("<")[0].trim(),
+          projectId: this.projectId,
+        },
+      });
+    }
+ 
+    // Handle implementations
+    Iif (cls.implements) {
+      cls.implements.forEach((impl) => {
+        this.statements.push({
+          query: `
+            MATCH (cls:CLASS {id: $classId})
+            MERGE (iface:CLASS {id: $ifaceId})
+            SET iface.name = $implName,
+                iface.projectId = $projectId
+            MERGE (cls)-[:IMPLEMENTS]->(iface)
+          `,
+          params: {
+            classId: nodeId,
+            ifaceId: this.scopedId(`class:${impl.trim()}`),
+            implName: impl.trim(),
+            projectId: this.projectId,
+          },
+        });
+      });
+    }
+ 
+    Eif (cls.isExported) {
+      this.statements.push({
+        query: `
+          MATCH (cls:CLASS {id: $id})
+          SET cls.isExported = true
+        `,
+        params: { id: nodeId },
+      });
+    }
+  }
+ 
+  private createVariableNode(variable: any, parsedFile: ParsedFile): void {
+    const nodeId = this.scopedId(variable.id);
+    Iif (this.processedNodes.has(nodeId)) return;
+    this.processedNodes.add(nodeId);
+ 
+    this.statements.push({
+      query: `
+        MERGE (var:VARIABLE {id: $id})
+        SET var.name = $name,
+            var.kind = $kind,
+            var.startLine = $startLine,
+            var.type = $type,
+            var.projectId = $projectId
+      `,
+      params: {
+        id: nodeId,
+        name: variable.name,
+        kind: variable.kind,
+        startLine: variable.startLine,
+        type: variable.type || null,
+        projectId: this.projectId,
+      },
+    });
+ 
+    // Connect to file
+    this.statements.push({
+      query: `
+        MATCH (var:VARIABLE {id: $varId})
+        MATCH (f:FILE {id: $fileId})
+        MERGE (f)-[:CONTAINS]->(var)
+      `,
+      params: {
+        varId: nodeId,
+        fileId: this.fileNodeId(parsedFile),
+      },
+    });
+  }
+ 
+  private createImportNode(imp: any, parsedFile: ParsedFile): void {
+    const nodeId = this.scopedId(imp.id);
+    Iif (this.processedNodes.has(nodeId)) return;
+    this.processedNodes.add(nodeId);
+ 
+    this.statements.push({
+      query: `
+        MERGE (imp:IMPORT {id: $id})
+        SET imp.source = $source,
+            imp.specifiers = $specifiers,
+            imp.startLine = $startLine,
+          imp.summary = $summary,
+          imp.validFrom = $validFrom,
+          imp.validTo = $validTo,
+          imp.createdAt = $createdAt,
+          imp.txId = $txId,
+            imp.projectId = $projectId
+      `,
+      params: {
+        id: nodeId,
+        source: imp.source,
+        specifiers: imp.specifiers,
+        startLine: imp.startLine,
+        summary: imp.summary || null,
+        validFrom: this.txTimestamp,
+        validTo: null,
+        createdAt: this.txTimestamp,
+        txId: this.txId,
+        projectId: this.projectId,
+      },
+    });
+ 
+    // Connect to file
+    this.statements.push({
+      query: `
+        MATCH (imp:IMPORT {id: $impId})
+        MATCH (f:FILE {id: $fileId})
+        MERGE (f)-[:IMPORTS]->(imp)
+      `,
+      params: {
+        impId: nodeId,
+        fileId: this.fileNodeId(parsedFile),
+      },
+    });
+ 
+    // Try to resolve the imported module
+    const resolvedPath = this.resolveImportPath(imp.source, path.dirname(parsedFile.filePath));
+    Iif (resolvedPath) {
+      // resolvedPath is relative to workspaceRoot; compute absolute path so
+      // that FILE.path is always absolute, consistent with createFileNode.
+      const absoluteTargetPath = path.resolve(this.workspaceRoot, resolvedPath);
+      this.statements.push({
+        query: `
+          MATCH (imp:IMPORT {id: $impId})
+          MERGE (targetFile:FILE {id: $targetId})
+          SET targetFile.path = $absoluteTargetPath,
+              targetFile.relativePath = $relativePath,
+              targetFile.projectId = $projectId
+          MERGE (imp)-[:REFERENCES]->(targetFile)
+        `,
+        params: {
+          impId: nodeId,
+          targetId: this.fileNodeIdFromRelative(resolvedPath),
+          absoluteTargetPath,
+          relativePath: resolvedPath,
+          projectId: this.projectId,
+        },
+      });
+    }
+  }
+ 
+  private createExportNode(exp: any, parsedFile: ParsedFile): void {
+    const nodeId = this.scopedId(exp.id);
+    Iif (this.processedNodes.has(nodeId)) return;
+    this.processedNodes.add(nodeId);
+ 
+    this.statements.push({
+      query: `
+        MERGE (exp:EXPORT {id: $id})
+        SET exp.name = $name,
+            exp.isDefault = $isDefault,
+            exp.startLine = $startLine,
+            exp.projectId = $projectId
+      `,
+      params: {
+        id: nodeId,
+        name: exp.name,
+        isDefault: exp.isDefault,
+        startLine: exp.startLine,
+        projectId: this.projectId,
+      },
+    });
+ 
+    // Connect to file
+    this.statements.push({
+      query: `
+        MATCH (exp:EXPORT {id: $expId})
+        MATCH (f:FILE {id: $fileId})
+        MERGE (f)-[:EXPORTS]->(exp)
+      `,
+      params: {
+        expId: nodeId,
+        fileId: this.fileNodeId(parsedFile),
+      },
+    });
+  }
+ 
+  private buildTestNodes(parsedFile: ParsedFile): void {
+    const testSuites = parsedFile.testSuites || [];
+    const testCases = parsedFile.testCases || [];
+    Eif (testSuites.length === 0 && testCases.length === 0) return;
+ 
+    const relativePath =
+      parsedFile.relativePath || path.relative(this.workspaceRoot, parsedFile.filePath);
+ 
+    // Create TEST_SUITE nodes
+    testSuites.forEach((suite) => {
+      const nodeId = this.scopedId(`test_suite:${suite.id}`);
+      if (this.processedNodes.has(nodeId)) return;
+      this.processedNodes.add(nodeId);
+ 
+      // Create TEST_SUITE node
+      this.statements.push({
+        query: `
+          MERGE (ts:TEST_SUITE {id: $id})
+          SET ts.name = $name,
+              ts.type = $type,
+              ts.category = $category,
+              ts.startLine = $startLine,
+              ts.endLine = $endLine,
+              ts.filePath = $filePath,
+              ts.projectId = $projectId
+        `,
+        params: {
+          id: nodeId,
+          name: suite.name,
+          type: suite.type,
+          category: suite.category || "unit",
+          startLine: suite.startLine,
+          endLine: suite.endLine || suite.startLine,
+          filePath: relativePath,
+          projectId: this.projectId,
+        },
+      });
+ 
+      // Create FILE -[:CONTAINS]-> TEST_SUITE relationship
+      this.statements.push({
+        query: `
+          MATCH (f:FILE {id: $fileId})
+          MATCH (ts:TEST_SUITE {id: $testSuiteId})
+          MERGE (f)-[:CONTAINS]->(ts)
+        `,
+        params: {
+          fileId: this.fileNodeId(parsedFile),
+          testSuiteId: nodeId,
+        },
+      });
+    });
+ 
+    // Phase 3.1: Create individual TEST_CASE nodes
+    testCases.forEach((testCase: any) => {
+      const nodeId = this.scopedId(`test_case:${testCase.id}`);
+      if (this.processedNodes.has(nodeId)) return;
+      this.processedNodes.add(nodeId);
+ 
+      // Create TEST_CASE node
+      this.statements.push({
+        query: `
+          MERGE (tc:TEST_CASE {id: $id})
+          SET tc.name = $name,
+              tc.startLine = $startLine,
+              tc.endLine = $endLine,
+              tc.filePath = $filePath,
+              tc.projectId = $projectId
+        `,
+        params: {
+          id: nodeId,
+          name: testCase.name,
+          startLine: testCase.startLine,
+          endLine: testCase.endLine || testCase.startLine,
+          filePath: relativePath,
+          projectId: this.projectId,
+        },
+      });
+ 
+      // Create TEST_SUITE -[:CONTAINS]-> TEST_CASE relationship (if parent suite exists)
+      if (testCase.parentSuiteId) {
+        const parentNodeId = this.scopedId(`test_suite:${testCase.parentSuiteId}`);
+        this.statements.push({
+          query: `
+            MATCH (ts:TEST_SUITE {id: $testSuiteId})
+            MATCH (tc:TEST_CASE {id: $testCaseId})
+            MERGE (ts)-[:CONTAINS]->(tc)
+          `,
+          params: {
+            testSuiteId: parentNodeId,
+            testCaseId: nodeId,
+          },
+        });
+      }
+ 
+      // Create FILE -[:CONTAINS]-> TEST_CASE relationship
+      this.statements.push({
+        query: `
+          MATCH (f:FILE {id: $fileId})
+          MATCH (tc:TEST_CASE {id: $testCaseId})
+          MERGE (f)-[:CONTAINS]->(tc)
+        `,
+        params: {
+          fileId: this.fileNodeId(parsedFile),
+          testCaseId: nodeId,
+        },
+      });
+    });
+  }
+ 
+  private resolveImportPath(source: string, fromDir: string): string | null {
+    Iif (!source.startsWith(".")) return null; // skip node_modules / bare specifiers
+    // TypeScript projects often emit .js/.jsx imports (moduleResolution: node16/bundler).
+    // Strip the JS extension so we can probe the actual .ts/.tsx source file on disk.
+    const normalizedSource = source.replace(/\.jsx?$/, "");
+    const base = path.resolve(fromDir, normalizedSource);
+    const candidates = [
+      base, // exact match (source had no extension or was already .ts)
+      base + ".ts",
+      base + ".tsx",
+      path.join(base, "index.ts"),
+      path.join(base, "index.tsx"),
+    ];
+    for (const candidate of candidates) {
+      Iif (existsSync(candidate)) {
+        return path.relative(this.workspaceRoot, candidate).replace(/\\/g, "/");
+      }
+    }
+    return null;
+  }
+}
+ 
+export default GraphBuilder;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/cache.ts.html b/coverage/lcov-report/src/graph/cache.ts.html new file mode 100644 index 0000000..33aed32 --- /dev/null +++ b/coverage/lcov-report/src/graph/cache.ts.html @@ -0,0 +1,529 @@ + + + + + + Code coverage report for src/graph/cache.ts + + + + + + + + + +
+
+

All files / src/graph cache.ts

+
+ +
+ 60% + Statements + 18/30 +
+ + +
+ 36.36% + Branches + 4/11 +
+ + +
+ 70% + Functions + 7/10 +
+ + +
+ 60% + Lines + 18/30 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +123x +123x +  +  +  +123x +123x +123x +123x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +  +  +3x +3x +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file graph/cache
+ * @description Maintains file hash metadata for incremental graph rebuild decisions.
+ * @remarks Cache storage is filesystem-backed and scoped to the runtime workspace.
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import { logger } from "../utils/logger.js";
+ 
+export interface CacheEntry {
+  path: string;
+  hash: string;
+  timestamp: number;
+  LOC: number;
+}
+ 
+export interface CacheData {
+  version: string;
+  lastBuild: number;
+  files: Record<string, CacheEntry>;
+}
+ 
+/**
+ * File hash cache for incremental builds
+ * Stores hashes and timestamps to detect changed files
+ */
+export class CacheManager {
+  private cachePath: string;
+  private cache: CacheData;
+ 
+  constructor(cacheDir: string = ".lxrag/cache") {
+    this.cachePath = path.join(process.cwd(), cacheDir, "file-hashes.json");
+    this.cache = this.loadCache();
+  }
+ 
+  private loadCache(): CacheData {
+    try {
+      Eif (fs.existsSync(this.cachePath)) {
+        const data = fs.readFileSync(this.cachePath, "utf-8");
+        return JSON.parse(data);
+      }
+    } catch (error) {
+      logger.warn(`[CacheManager] Failed to load cache: ${error}`);
+    }
+ 
+    return {
+      version: "1.0",
+      lastBuild: 0,
+      files: {},
+    };
+  }
+ 
+  /**
+   * Save cache to disk
+   */
+  save(): void {
+    try {
+      const dir = path.dirname(this.cachePath);
+      Iif (!fs.existsSync(dir)) {
+        fs.mkdirSync(dir, { recursive: true });
+      }
+      this.cache.lastBuild = Date.now();
+      fs.writeFileSync(this.cachePath, JSON.stringify(this.cache, null, 2));
+    } catch (error) {
+      logger.error(`[CacheManager] Failed to save cache: ${error}`);
+    }
+  }
+ 
+  /**
+   * Add or update cache entry
+   */
+  set(filePath: string, hash: string, LOC: number): void {
+    const relPath = path.relative(process.cwd(), filePath);
+    this.cache.files[relPath] = {
+      path: relPath,
+      hash,
+      timestamp: Date.now(),
+      LOC,
+    };
+  }
+ 
+  /**
+   * Get cache entry
+   */
+  get(filePath: string): CacheEntry | undefined {
+    const relPath = path.relative(process.cwd(), filePath);
+    return this.cache.files[relPath];
+  }
+ 
+  /**
+   * Check if file has changed
+   */
+  hasChanged(filePath: string, currentHash: string): boolean {
+    const entry = this.get(filePath);
+    return !entry || entry.hash !== currentHash;
+  }
+ 
+  /**
+   * Get all changed files since last build
+   */
+  getChangedFiles(files: Array<{ path: string; hash: string; LOC: number }>): string[] {
+    const changed: string[] = [];
+    for (const file of files) {
+      const entry = this.get(file.path);
+      if (!entry || entry.hash !== file.hash) {
+        changed.push(file.path);
+      }
+    }
+ 
+    return changed;
+  }
+ 
+  /**
+   * Clear cache (for full rebuild)
+   */
+  clear(): void {
+    this.cache = {
+      version: "1.0",
+      lastBuild: Date.now(),
+      files: {},
+    };
+  }
+ 
+  /**
+   * Get cache statistics
+   */
+  getStats(): {
+    cachedFiles: number;
+    lastBuild: Date;
+    version: string;
+  } {
+    return {
+      cachedFiles: Object.keys(this.cache.files).length,
+      lastBuild: new Date(this.cache.lastBuild),
+      version: this.cache.version,
+    };
+  }
+ 
+  /**
+   * Export cache as JSON
+   */
+  export(): string {
+    return JSON.stringify(this.cache, null, 2);
+  }
+}
+ 
+export default CacheManager;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/client.ts.html b/coverage/lcov-report/src/graph/client.ts.html new file mode 100644 index 0000000..6bd1072 --- /dev/null +++ b/coverage/lcov-report/src/graph/client.ts.html @@ -0,0 +1,1426 @@ + + + + + + Code coverage report for src/graph/client.ts + + + + + + + + + +
+
+

All files / src/graph client.ts

+
+ +
+ 64.59% + Statements + 104/161 +
+ + +
+ 52.17% + Branches + 48/92 +
+ + +
+ 80% + Functions + 20/25 +
+ + +
+ 64.05% + Lines + 98/153 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +5x +  +  +5x +  +  +5x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +7x +  +  +  +7x +7x +7x +  +  +  +7x +  +  +7x +  +  +  +  +  +  +7x +  +7x +7x +  +  +  +1x +  +1x +1x +  +  +  +  +  +  +1x +1x +  +  +  +1x +1x +1x +  +1x +1x +1x +1x +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +7x +7x +  +  +  +  +7x +  +  +  +  +  +  +  +1x +  +  +  +1x +1x +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +4x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +3x +2x +  +  +  +3x +4x +1x +1x +  +  +  +  +1x +  +  +4x +4x +4x +2x +  +2x +2x +  +2x +2x +  +2x +1x +  +  +  +  +1x +  +  +1x +1x +  +  +  +1x +  +4x +  +  +  +1x +1x +  +  +  +2x +2x +2x +  +  +  +  +  +  +  +  +1x +  +1x +2x +2x +  +  +2x +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +1x +  +  +1x +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  + 
/**
+ * @file graph/client
+ * @description Memgraph client wrapper for Cypher execution and connection lifecycle.
+ * @remarks Provides resilient query utilities used across graph and engine modules.
+ */
+ 
+import type { CypherStatement } from "./types";
+import neo4j from "neo4j-driver";
+import * as env from "../env.js";
+import { logger } from "../utils/logger.js";
+ 
+export interface MemgraphConfig {
+  host: string;
+  port: number;
+  username?: string;
+  password?: string;
+}
+ 
+export interface QueryResult {
+  data: any[];
+  error?: string;
+}
+ 
+// ── Retry / resilience constants ─────────────────────────────────────────────
+ 
+/** Delays (ms) between successive retry attempts: 100 → 400 → 1600 ms. */
+const BACKOFF_INTERVALS_MS = [100, 400, 1600] as const;
+ 
+/**
+ * Number of consecutive query errors that open the circuit breaker.
+ * Once open, all queries short-circuit immediately until the cooldown expires.
+ */
+const CIRCUIT_BREAKER_THRESHOLD = 5;
+ 
+/** Milliseconds the circuit stays open before entering half-open state. */
+const CIRCUIT_BREAKER_COOLDOWN_MS = 30_000;
+ 
+/** Interval for background liveness pings while connected (ms). */
+const HEALTH_CHECK_INTERVAL_MS = 30_000;
+ 
+/** Sleep helper used for exponential backoff between retries. */
+function sleep(ms: number): Promise<void> {
+  return new Promise((resolve) => setTimeout(resolve, ms));
+}
+ 
+/**
+ * Memgraph client for executing Cypher queries.
+ *
+ * Resilience features:
+ *  - **3-retry with exponential backoff** (100ms → 400ms → 1600ms) for
+ *    transient errors (ServiceUnavailable, session expired, connection lost).
+ *  - **Circuit breaker** — after 5 consecutive failures the circuit opens
+ *    and all queries fail fast for 30 s, then auto-resets to half-open.
+ *  - **Periodic health check** — background ping every 30 s while connected;
+ *    marks client as disconnected if the ping fails so the next `executeCypher`
+ *    call triggers a reconnect.
+ */
+export class MemgraphClient {
+  private config: MemgraphConfig;
+  private driver: any;
+  private connected = false;
+  private readonly queryRetryAttempts = 3;
+ 
+  // ── Circuit breaker state ─────────────────────────────────────────────────
+ 
+  private consecutiveFailures = 0;
+  private circuitOpen = false;
+  private circuitOpenAt = 0;
+ 
+  // ── Health check handle ───────────────────────────────────────────────────
+ 
+  private healthCheckHandle: NodeJS.Timeout | null = null;
+ 
+  constructor(config: Partial<MemgraphConfig> = {}) {
+    this.config = {
+      host: config.host || "localhost",
+      port: config.port || 7687,
+      username: config.username || "memgraph",
+      password: config.password || "",
+    };
+ 
+    this.driver = this.createDriver(this.config.host);
+ 
+    const boltUrl = `bolt://${this.config.host}:${this.config.port}`;
+    logger.info("[MemgraphClient] Initialized", { boltUrl });
+  }
+ 
+  async connect(): Promise<void> {
+    try {
+      // Verify connection by running a simple query
+      const session = this.driver.session();
+      await session.run("RETURN 1");
+      await session.close();
+      this.connected = true;
+      this.resetCircuitBreaker();
+      logger.info("[Memgraph] Connected successfully via Bolt protocol");
+      this.startHealthCheck();
+    } catch (error) {
+      Eif (this.shouldFallbackToLocalhost(error)) {
+        logger.warn(
+          `[Memgraph] Host '${this.config.host}' is not resolvable from this runtime. Retrying with localhost...`,
+        );
+ 
+        await this.driver.close();
+        this.config.host = "localhost";
+        this.driver = this.createDriver(this.config.host);
+ 
+        const session = this.driver.session();
+        await session.run("RETURN 1");
+        await session.close();
+        this.connected = true;
+        this.resetCircuitBreaker();
+        logger.info("[Memgraph] Connected successfully via Bolt protocol");
+        this.startHealthCheck();
+        return;
+      }
+ 
+      logger.error("[Memgraph] Connection failed", error);
+      this.connected = false;
+      throw error;
+    }
+  }
+ 
+  private createDriver(host: string): any {
+    const boltUrl = `bolt://${host}:${this.config.port}`;
+    const authToken = neo4j.auth.basic(
+      this.config.username || "memgraph",
+      this.config.password || "",
+    );
+ 
+    return neo4j.driver(boltUrl, authToken, {
+      maxConnectionPoolSize: env.LXRAG_MEMGRAPH_MAX_POOL_SIZE,
+      connectionAcquisitionTimeout: env.LXRAG_MEMGRAPH_CONNECTION_TIMEOUT_MS,
+      connectionLivenessCheckTimeout: env.LXRAG_MEMGRAPH_LIVENESS_TIMEOUT_MS,
+    });
+  }
+ 
+  private shouldFallbackToLocalhost(error: unknown): boolean {
+    Iif (this.config.host === "localhost" || this.config.host === "127.0.0.1") {
+      return false;
+    }
+ 
+    const message = error instanceof Error ? error.message : String(error);
+    return message.includes("ENOTFOUND");
+  }
+ 
+  // ── Circuit breaker ───────────────────────────────────────────────────────
+ 
+  private resetCircuitBreaker(): void {
+    this.consecutiveFailures = 0;
+    this.circuitOpen = false;
+    this.circuitOpenAt = 0;
+  }
+ 
+  /**
+   * Returns true when the circuit is currently open (fast-fail mode).
+   * Transitions from open → half-open after the cooldown expires.
+   */
+  private isCircuitOpen(): boolean {
+    Eif (!this.circuitOpen) return false;
+    const elapsed = Date.now() - this.circuitOpenAt;
+    if (elapsed >= CIRCUIT_BREAKER_COOLDOWN_MS) {
+      // Half-open: allow one probe request through
+      logger.info("[Memgraph] Circuit breaker half-open — probing...");
+      this.circuitOpen = false;
+      return false;
+    }
+    return true;
+  }
+ 
+  private recordQuerySuccess(): void {
+    this.consecutiveFailures = 0;
+    Iif (this.circuitOpen) this.circuitOpen = false;
+  }
+ 
+  private recordQueryFailure(): void {
+    this.consecutiveFailures += 1;
+    Iif (this.consecutiveFailures >= CIRCUIT_BREAKER_THRESHOLD) {
+      this.circuitOpen = true;
+      this.circuitOpenAt = Date.now();
+      logger.error("[Memgraph] Circuit breaker OPENED — too many consecutive failures", {
+        threshold: CIRCUIT_BREAKER_THRESHOLD,
+        cooldownMs: CIRCUIT_BREAKER_COOLDOWN_MS,
+      });
+    }
+  }
+ 
+  // ── Periodic health check ─────────────────────────────────────────────────
+ 
+  private startHealthCheck(): void {
+    Iif (this.healthCheckHandle) return; // already running
+    this.healthCheckHandle = setInterval(async () => {
+      try {
+        const session = this.driver.session();
+        await session.run("RETURN 1");
+        await session.close();
+        // Silent success — no log spam on healthy ping
+      } catch (error) {
+        const msg = error instanceof Error ? error.message : String(error);
+        logger.warn("[Memgraph] Health check failed — marking as disconnected", { cause: msg });
+        this.connected = false;
+        this.stopHealthCheck();
+      }
+    }, HEALTH_CHECK_INTERVAL_MS);
+ 
+    // Don't hold the Node.js event loop open just for the health check
+    Eif (this.healthCheckHandle.unref) {
+      this.healthCheckHandle.unref();
+    }
+  }
+ 
+  private stopHealthCheck(): void {
+    if (this.healthCheckHandle) {
+      clearInterval(this.healthCheckHandle);
+      this.healthCheckHandle = null;
+    }
+  }
+ 
+  // ── Public methods ────────────────────────────────────────────────────────
+ 
+  async disconnect(): Promise<void> {
+    this.stopHealthCheck();
+    if (this.driver) {
+      await this.driver.close();
+      this.connected = false;
+      logger.info("[Memgraph] Disconnected");
+    }
+  }
+ 
+  async executeCypher(query: string, params: Record<string, any> = {}): Promise<QueryResult> {
+    // ── Circuit breaker fast-fail ─────────────────────────────────────────
+    Iif (this.isCircuitOpen()) {
+      return {
+        data: [],
+        error: "Circuit breaker open — Memgraph unavailable, retrying after cooldown",
+      };
+    }
+ 
+    // ── Lazy connect ──────────────────────────────────────────────────────
+    if (!this.connected) {
+      logger.warn("[Memgraph] Not connected - attempting to connect before executing query");
+      try {
+        await this.connect();
+      } catch (error) {
+        return {
+          data: [],
+          error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
+        };
+      }
+    }
+ 
+    // Sanitize params: replace undefined with null (Bolt requires explicit null)
+    const sanitizedParams = Object.fromEntries(
+      Object.entries(params).map(([k, v]) => [k, v === undefined ? null : v]),
+    );
+ 
+    // ── Retry loop with exponential backoff ───────────────────────────────
+    for (let attempt = 0; attempt <= this.queryRetryAttempts; attempt++) {
+      if (attempt > 0) {
+        const delayMs = BACKOFF_INTERVALS_MS[attempt - 1] ?? 1600;
+        logger.warn("[Memgraph] Retrying query after backoff", {
+          attempt,
+          maxAttempts: this.queryRetryAttempts,
+          delayMs,
+        });
+        await sleep(delayMs);
+      }
+ 
+      const session = this.driver.session();
+      try {
+        const result = await session.run(query, sanitizedParams);
+        const data = result.records.map((record: any) => record.toObject());
+ 
+        this.recordQuerySuccess();
+        return { data, error: undefined };
+      } catch (error) {
+        const errorMsg = error instanceof Error ? error.message : String(error);
+        const canRetry = attempt < this.queryRetryAttempts && this.isRetryableQueryError(error);
+ 
+        if (canRetry) {
+          logger.warn("[Memgraph] Transient query error, will retry", {
+            attempt: attempt + 1,
+            maxAttempts: this.queryRetryAttempts,
+            cause: errorMsg,
+          });
+          continue;
+        }
+ 
+        this.recordQueryFailure();
+        logger.error("[Memgraph] Query execution failed", {
+          cause: errorMsg,
+          query: query.substring(0, 200),
+        });
+        return { data: [], error: `Query failed: ${errorMsg}` };
+      } finally {
+        await session.close();
+      }
+    }
+ 
+    this.recordQueryFailure();
+    return { data: [], error: "Query failed: exhausted retry attempts" };
+  }
+ 
+  private isRetryableQueryError(error: unknown): boolean {
+    const message = error instanceof Error ? error.message : String(error);
+    const normalized = message.toLowerCase();
+    return (
+      normalized.includes("serviceunavailable") ||
+      normalized.includes("session expired") ||
+      normalized.includes("connection") ||
+      normalized.includes("temporarily unavailable")
+    );
+  }
+ 
+  async executeBatch(statements: CypherStatement[]): Promise<QueryResult[]> {
+    const results: QueryResult[] = [];
+ 
+    for (const statement of statements) {
+      const result = await this.executeCypher(statement.query, statement.params);
+      results.push(result);
+ 
+      // Log errors but continue
+      if (result.error) {
+        logger.error(`[Memgraph] Error in query: ${result.error}`);
+      }
+    }
+ 
+    return results;
+  }
+ 
+  /**
+   * Execute a natural language query and convert to Cypher.
+   *
+   * @deprecated Use HybridRetriever for natural language queries instead.
+   * This method uses simple hardcoded pattern matching and will be removed
+   * in a future release.
+   */
+  async queryNaturalLanguage(query: string): Promise<QueryResult> {
+    const cypher = this.naturalLanguageToCypher(query);
+    return this.executeCypher(cypher);
+  }
+ 
+  /**
+   * Convert common natural language patterns to Cypher.
+   *
+   * @deprecated Use HybridRetriever for production NL routing.
+   * This is an MVP stub retained for backward compatibility only.
+   */
+  private naturalLanguageToCypher(query: string): string {
+    const lower = query.toLowerCase();
+ 
+    // "Show all files"
+    if (lower.includes("all files") || lower.includes("list files")) {
+      return "MATCH (f:FILE) RETURN f.path, f.LOC, f.lastModified ORDER BY f.path";
+    }
+ 
+    // "Files in components layer"
+    if (lower.includes("files") && lower.includes("layer")) {
+      const layerMatch = /layer\s+['"]?(\w+)['"]?/i.exec(query);
+      const layerId = layerMatch ? layerMatch[1] : "components";
+      return `MATCH (l:LAYER {id: '${layerId}'})<-[:BELONGS_TO_LAYER]-(f:FILE) RETURN f.path, f.LOC`;
+    }
+ 
+    // "Functions in file"
+    if (lower.includes("functions")) {
+      const fileMatch = /file\s+['"]?([^'"]+)['"]?/i.exec(query);
+      const filePath = fileMatch ? fileMatch[1] : "";
+      return `MATCH (f:FILE {path: '${filePath}'})-[:CONTAINS]->(func:FUNCTION) RETURN func.name, func.kind, func.startLine`;
+    }
+ 
+    // "Test coverage"
+    if (lower.includes("test") && lower.includes("cover")) {
+      return `MATCH (t:TEST_CASE)-[:TESTS]->(c:CLASS|FUNCTION) RETURN c.name, count(t) as test_count ORDER BY test_count DESC`;
+    }
+ 
+    // "Architecture violations"
+    if (lower.includes("violation")) {
+      return `MATCH (f:FILE)-[:VIOLATES_RULE]->(r) RETURN f.path, r.rule`;
+    }
+ 
+    // Default fallback
+    return `MATCH (n) RETURN labels(n)[0] as type, count(n) as count ORDER BY count DESC`;
+  }
+ 
+  /**
+   * Load all nodes and relationships for a project from Memgraph
+   * Used for Phase 2c: Populate in-memory index from database on startup
+   */
+  async loadProjectGraph(projectId: string): Promise<{
+    nodes: Array<{ id: string; type: string; properties: Record<string, any> }>;
+    relationships: Array<{
+      id: string;
+      from: string;
+      to: string;
+      type: string;
+      properties?: Record<string, any>;
+    }>;
+  }> {
+    if (!this.connected) {
+      return { nodes: [], relationships: [] };
+    }
+ 
+    try {
+      // Load all nodes for this projectId
+      const nodesResult = await this.executeCypher(
+        `MATCH (n {projectId: $projectId})
+         RETURN n.id AS id, labels(n)[0] AS type, properties(n) AS props`,
+        { projectId },
+      );
+ 
+      const nodes = nodesResult.data.map((row: any) => ({
+        id: row.id,
+        type: row.type,
+        properties: row.props || {},
+      }));
+ 
+      // Load all relationships for this projectId
+      const relsResult = await this.executeCypher(
+        `MATCH (n1 {projectId: $projectId})-[r]->(n2 {projectId: $projectId})
+         RETURN n1.id AS from, n2.id AS to, type(r) AS type, properties(r) AS props`,
+        { projectId },
+      );
+ 
+      const relationships = relsResult.data.map((row: any) => ({
+        id: `${row.from}-${row.type}-${row.to}`,
+        from: row.from,
+        to: row.to,
+        type: row.type,
+        properties: row.props || {},
+      }));
+ 
+      return { nodes, relationships };
+    } catch (error) {
+      logger.error(`[MemgraphClient] Failed to load project graph for ${projectId}:`, error);
+      return { nodes: [], relationships: [] };
+    }
+  }
+ 
+  /**
+   * Check connection status
+   */
+  isConnected(): boolean {
+    return this.connected;
+  }
+}
+ 
+export default MemgraphClient;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/docs-builder.ts.html b/coverage/lcov-report/src/graph/docs-builder.ts.html new file mode 100644 index 0000000..e75a194 --- /dev/null +++ b/coverage/lcov-report/src/graph/docs-builder.ts.html @@ -0,0 +1,736 @@ + + + + + + Code coverage report for src/graph/docs-builder.ts + + + + + + + + + +
+
+

All files / src/graph docs-builder.ts

+
+ +
+ 100% + Statements + 31/31 +
+ + +
+ 45.45% + Branches + 5/11 +
+ + +
+ 100% + Functions + 9/9 +
+ + +
+ 100% + Lines + 30/30 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +51x +51x +51x +51x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +54x +54x +  +54x +  +54x +54x +204x +204x +204x +204x +  +  +  +54x +151x +  +  +  +54x +204x +204x +315x +  +  +  +54x +  +  +  +  +  +54x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +204x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +204x +  +  +  +  +  +  +  +  +  +  +151x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +315x +  +  +315x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +315x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +315x +  +  +  +  +  +54x +  +  +  +408x +  +  + 
/**
+ * @file graph/docs-builder
+ * @description Converts parsed markdown docs into idempotent Cypher graph statements.
+ * @remarks Mirrors graph builder conventions for consistent write behavior.
+ */
+ 
+import * as path from "node:path";
+import type { ParsedDoc, ParsedSection } from "../parsers/docs-parser.js";
+import type { CypherStatement } from "./builder.js";
+import * as env from "../env.js";
+ 
+// ─── Re-export CypherStatement for callers who import only this module ────────
+export type { CypherStatement };
+ 
+export class DocsBuilder {
+  private readonly projectId: string;
+  private readonly workspaceRoot: string;
+  private readonly txId: string;
+  private readonly txTimestamp: number;
+ 
+  constructor(projectId?: string, workspaceRoot?: string, txId?: string, txTimestamp?: number) {
+    this.workspaceRoot = workspaceRoot ?? env.LXRAG_WORKSPACE_ROOT ?? process.cwd();
+    this.projectId = projectId ?? env.LXRAG_PROJECT_ID ?? path.basename(this.workspaceRoot);
+    this.txId = txId ?? env.LXRAG_TX_ID ?? `tx-${Date.now()}`;
+    this.txTimestamp = txTimestamp ?? Date.now();
+  }
+ 
+  // ── Public API ───────────────────────────────────────────────────────────────
+ 
+  /**
+   * Build all Cypher statements to upsert one markdown document and its
+   * sections into the graph.  All statements are MERGE-based (idempotent).
+   *
+   * Schema produced:
+   *   (DOCUMENT { id, relativePath, filePath, title, kind, wordCount, hash,
+   *                projectId, validFrom, validTo, txId })
+   *   (SECTION  { id, heading, level, content, wordCount, startLine,
+   *                docId, projectId })
+   *   SECTION -[:SECTION_OF]-> DOCUMENT
+   *   SECTIONₙ -[:NEXT_SECTION]-> SECTIONₙ₊₁
+   *   SECTION -[:DOC_DESCRIBES { strength, matchedName }]-> FILE|FUNCTION|CLASS
+   */
+  buildFromParsedDoc(doc: ParsedDoc): CypherStatement[] {
+    const stmts: CypherStatement[] = [];
+    const docId = this.docId(doc.relativePath);
+ 
+    stmts.push(this.upsertDocument(docId, doc));
+ 
+    const sectionIds: string[] = [];
+    for (const section of doc.sections) {
+      const secId = this.sectionId(doc.relativePath, section.index);
+      sectionIds.push(secId);
+      stmts.push(this.upsertSection(secId, docId, section, doc.relativePath));
+      stmts.push(this.upsertSectionOf(secId, docId));
+    }
+ 
+    // Chain NEXT_SECTION edges
+    for (let i = 0; i < sectionIds.length - 1; i++) {
+      stmts.push(this.upsertNextSection(sectionIds[i], sectionIds[i + 1]));
+    }
+ 
+    // DOC_DESCRIBES edges from backtickRefs
+    for (const section of doc.sections) {
+      const secId = this.sectionId(doc.relativePath, section.index);
+      for (const ref of section.backtickRefs) {
+        stmts.push(...this.upsertDocDescribes(secId, ref, doc.relativePath));
+      }
+    }
+ 
+    return stmts;
+  }
+ 
+  // ── Node / edge builders ────────────────────────────────────────────────────
+ 
+  private upsertDocument(docId: string, doc: ParsedDoc): CypherStatement {
+    return {
+      query: `
+MERGE (d:DOCUMENT { id: $id, projectId: $projectId })
+SET d.relativePath = $relativePath,
+    d.filePath     = $filePath,
+    d.title        = $title,
+    d.kind         = $kind,
+    d.wordCount    = $wordCount,
+    d.hash         = $hash,
+    d.validFrom    = $validFrom,
+    d.validTo      = 9999999999999,
+    d.txId         = $txId
+`,
+      params: {
+        id: docId,
+        projectId: this.projectId,
+        relativePath: doc.relativePath,
+        filePath: doc.filePath,
+        title: doc.title,
+        kind: doc.kind,
+        wordCount: doc.wordCount,
+        hash: doc.hash,
+        validFrom: this.txTimestamp,
+        txId: this.txId,
+      },
+    };
+  }
+ 
+  private upsertSection(
+    secId: string,
+    docId: string,
+    section: ParsedSection,
+    relativePath: string,
+  ): CypherStatement {
+    return {
+      query: `
+MERGE (s:SECTION { id: $id, projectId: $projectId })
+SET s.heading      = $heading,
+    s.level        = $level,
+    s.content      = $content,
+    s.wordCount    = $wordCount,
+    s.startLine    = $startLine,
+    s.docId        = $docId,
+    s.relativePath = $relativePath,
+    s.txId         = $txId
+`,
+      params: {
+        id: secId,
+        projectId: this.projectId,
+        heading: section.heading,
+        level: section.level,
+        // Trim content to 4000 chars to stay within Memgraph string property limits
+        content: section.content.slice(0, 4000),
+        wordCount: section.wordCount,
+        startLine: section.startLine,
+        docId,
+        relativePath,
+        txId: this.txId,
+      },
+    };
+  }
+ 
+  private upsertSectionOf(secId: string, docId: string): CypherStatement {
+    return {
+      query: `
+MATCH (s:SECTION { id: $secId, projectId: $projectId })
+MATCH (d:DOCUMENT { id: $docId, projectId: $projectId })
+MERGE (s)-[:SECTION_OF]->(d)
+`,
+      params: { secId, docId, projectId: this.projectId },
+    };
+  }
+ 
+  private upsertNextSection(fromId: string, toId: string): CypherStatement {
+    return {
+      query: `
+MATCH (a:SECTION { id: $fromId, projectId: $projectId })
+MATCH (b:SECTION { id: $toId,   projectId: $projectId })
+MERGE (a)-[:NEXT_SECTION]->(b)
+`,
+      params: { fromId, toId, projectId: this.projectId },
+    };
+  }
+ 
+  /**
+   * Emit DOC_DESCRIBES edges from a section to any graph nodes whose name
+   * matches the backtick reference.
+   *
+   * Strength rules:
+   *   1.0 — exact backtick match to a name property on FILE/FUNCTION/CLASS
+   *   (The 0.9 code-fence-path and 0.6 prose-word-boundary variants are
+   *    produced by the engine layer which has richer context.)
+   */
+  private upsertDocDescribes(secId: string, ref: string, _docRelPath: string): CypherStatement[] {
+    const stmts: CypherStatement[] = [];
+ 
+    // Match FILE nodes by relativePath ending with the ref
+    stmts.push({
+      query: `
+MATCH (target:FILE { projectId: $projectId })
+WHERE target.relativePath = $ref OR target.relativePath ENDS WITH $slash_ref
+MATCH (s:SECTION { id: $secId, projectId: $projectId })
+MERGE (s)-[r:DOC_DESCRIBES]->(target)
+SET r.strength = 1.0, r.matchedName = $ref
+`,
+      params: {
+        secId,
+        projectId: this.projectId,
+        ref,
+        slash_ref: `/${ref}`,
+      },
+    });
+ 
+    // Match FUNCTION or CLASS nodes by name
+    stmts.push({
+      query: `
+MATCH (target { projectId: $projectId })
+WHERE (target:FUNCTION OR target:CLASS) AND target.name = $ref
+MATCH (s:SECTION { id: $secId, projectId: $projectId })
+MERGE (s)-[r:DOC_DESCRIBES]->(target)
+SET r.strength = 1.0, r.matchedName = $ref
+`,
+      params: {
+        secId,
+        projectId: this.projectId,
+        ref,
+      },
+    });
+ 
+    return stmts;
+  }
+ 
+  // ── ID helpers ───────────────────────────────────────────────────────────────
+ 
+  private docId(relativePath: string): string {
+    return `${this.projectId}:doc:${relativePath}`;
+  }
+ 
+  private sectionId(relativePath: string, index: number): string {
+    return `${this.projectId}:sec:${relativePath}:${index}`;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/hybrid-retriever.ts.html b/coverage/lcov-report/src/graph/hybrid-retriever.ts.html new file mode 100644 index 0000000..5ed224c --- /dev/null +++ b/coverage/lcov-report/src/graph/hybrid-retriever.ts.html @@ -0,0 +1,1168 @@ + + + + + + Code coverage report for src/graph/hybrid-retriever.ts + + + + + + + + + +
+
+

All files / src/graph hybrid-retriever.ts

+
+ +
+ 69.02% + Statements + 78/113 +
+ + +
+ 48.93% + Branches + 46/94 +
+ + +
+ 79.41% + Functions + 27/34 +
+ + +
+ 70% + Lines + 77/110 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +133x +  +  +  +  +133x +  +  +9x +  +  +  +11x +  +  +  +133x +133x +133x +  +  +  +2x +2x +2x +  +  +2x +  +  +  +2x +  +  +  +2x +3x +  +  +  +  +2x +  +  +  +2x +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +  +  +  +1x +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +75x +  +  +  +  +  +  +75x +75x +  +  +  +74x +287x +  +75x +  +2x +  +  +  +  +  +2x +2x +  +72x +  +  +  +  +72x +72x +  +  +  +  +72x +72x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +6x +3x +3x +3x +  +3x +3x +3x +  +  +  +2x +1x +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +1x +  +1x +  +  +  +  +  +1x +3x +2x +  +  +  +  +2x +1x +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +2x +3x +3x +  +  +  +  +  + 
/**
+ * @file graph/hybrid-retriever
+ * @description Combines lexical and vector retrieval over graph-indexed code entities.
+ * @remarks Supports fallback behavior when BM25 or vector backends are unavailable.
+ */
+ 
+import type { GraphIndexManager, GraphNode } from "./index.js";
+import type EmbeddingEngine from "../vector/embedding-engine.js";
+import type MemgraphClient from "./client.js";
+ 
+export interface RetrievalOptions {
+  query: string;
+  projectId: string;
+  limit?: number;
+  types?: string[];
+  mode?: "vector" | "bm25" | "graph" | "hybrid";
+  rrfK?: number;
+}
+ 
+interface RankedNode {
+  nodeId: string;
+  score: number;
+  source: "vector" | "bm25" | "graph";
+}
+ 
+export interface RetrievalResult {
+  nodeId: string;
+  name: string;
+  filePath: string;
+  type: string;
+  rrfScore: number;
+  scores: { vector?: number; bm25?: number; graph?: number };
+}
+ 
+export class HybridRetriever {
+  private _bm25Mode: "native" | "lexical_fallback" = "lexical_fallback";
+  /**
+   * True once ensureBM25Index() confirms the index exists (created or already present).
+   * Distinct from bm25Mode which only flips to "native" after a successful query.
+   */
+  private _bm25IndexKnownToExist = false;
+ 
+  get bm25Mode(): "native" | "lexical_fallback" {
+    return this._bm25Mode;
+  }
+ 
+  get bm25IndexKnownToExist(): boolean {
+    return this._bm25IndexKnownToExist;
+  }
+ 
+  constructor(
+    private index: GraphIndexManager,
+    private embeddingEngine?: EmbeddingEngine,
+    private memgraph?: MemgraphClient,
+  ) {}
+ 
+  async retrieve(opts: RetrievalOptions): Promise<RetrievalResult[]> {
+    const mode = opts.mode || "hybrid";
+    const limit = Math.max(1, Math.min(opts.limit || 10, 100));
+    const rrfK = opts.rrfK || 60;
+ 
+    const vectorList =
+      mode === "vector" || mode === "hybrid"
+        ? await this.vectorSearch(opts.query, { ...opts, limit })
+        : [];
+    const bm25List =
+      mode === "bm25" || mode === "hybrid"
+        ? await this.bm25Search(opts.query, { ...opts, limit })
+        : [];
+ 
+    const seedIds = [...vectorList, ...bm25List]
+      .map((item) => item.nodeId)
+      .filter(Boolean)
+      .slice(0, limit);
+ 
+    const graphList =
+      mode === "graph" || mode === "hybrid"
+        ? await this.graphExpansion(seedIds, { ...opts, limit })
+        : [];
+ 
+    const fused = this.fusionRRF([vectorList, bm25List, graphList], rrfK);
+    const projectScoped = this.filterByProject(fused, opts.projectId);
+    const filtered = this.filterByType(projectScoped, opts.types);
+ 
+    return filtered.slice(0, limit);
+  }
+ 
+  private async vectorSearch(query: string, opts: RetrievalOptions): Promise<RankedNode[]> {
+    const limit = Math.max(1, Math.min(opts.limit || 10, 100));
+    const rows: RankedNode[] = [];
+ 
+    if (this.embeddingEngine) {
+      try {
+        const [functions, classes, files] = await Promise.all([
+          this.embeddingEngine.findSimilar(query, "function", limit),
+          this.embeddingEngine.findSimilar(query, "class", limit),
+          this.embeddingEngine.findSimilar(query, "file", limit),
+        ]);
+ 
+        const merged = [...functions, ...classes, ...files];
+        merged.forEach((entry, index) => {
+          rows.push({
+            nodeId: entry.id,
+            score: 1 / (index + 1),
+            source: "vector",
+          });
+        });
+      } catch {
+        // Fall through to lexical fallback
+      }
+    }
+ 
+    if (rows.length > 0) {
+      return rows.slice(0, limit);
+    }
+ 
+    return this.lexicalFallback(query, opts.projectId, "vector", limit);
+  }
+ 
+  private async bm25Search(query: string, opts: RetrievalOptions): Promise<RankedNode[]> {
+    const limit = Math.max(1, Math.min(opts.limit || 10, 100));
+ 
+    Eif (this.memgraph) {
+      try {
+        const response = await this.memgraph.executeCypher(
+          `
+            CALL text_search.search('symbol_index', $query)
+            YIELD node, score
+            WHERE coalesce(node.projectId, '') = $projectId
+              AND labels(node)[0] IN ['FUNCTION', 'CLASS', 'FILE', 'SECTION']
+            RETURN node.id AS nodeId, score
+            ORDER BY score DESC
+            LIMIT $limit
+          `,
+          {
+            query,
+            projectId: opts.projectId,
+            limit,
+          },
+        );
+ 
+        Eif (!response.error && response.data.length > 0) {
+          this._bm25Mode = "native";
+          return response.data
+            .map((row: Record<string, unknown>) => ({
+              nodeId: String(row.nodeId || ""),
+              score: Number(row.score || 0),
+              source: "bm25" as const,
+            }))
+            .filter((row) => row.nodeId.length > 0 && Number.isFinite(row.score))
+            .slice(0, limit);
+        }
+      } catch {
+        // Fall through to in-memory lexical BM25 fallback
+      }
+    }
+ 
+    this._bm25Mode = "lexical_fallback";
+    return this.lexicalFallback(query, opts.projectId, "bm25", limit);
+  }
+ 
+  async ensureBM25Index(): Promise<{
+    created: boolean;
+    alreadyExists: boolean;
+    error?: string;
+  }> {
+    Iif (!this.memgraph) {
+      return {
+        created: false,
+        alreadyExists: false,
+        error: "no_memgraph_connection",
+      };
+    }
+    try {
+      const check = await this.memgraph.executeCypher(
+        `CALL text_search.list_indices() YIELD name RETURN name`,
+        {},
+      );
+      const names: string[] = (check.data || []).map((r: Record<string, unknown>) =>
+        String(r["name"] ?? ""),
+      );
+      if (names.includes("symbol_index")) {
+        // Upgrade path: symbol_index already exists but docs_index may be missing
+        Iif (!names.includes("docs_index")) {
+          await this.memgraph.executeCypher(
+            `CALL text_search.create_index('docs_index', 'SECTION', ['heading', 'content'], {analyzer: 'standard'})`,
+            {},
+          );
+        }
+        this._bm25IndexKnownToExist = true;
+        return { created: false, alreadyExists: true };
+      }
+      await this.memgraph.executeCypher(
+        `CALL text_search.create_index('symbol_index', 'FUNCTION|CLASS|FILE|SECTION', ['name', 'summary', 'path', 'heading', 'content'], {analyzer: 'standard'})`,
+        {},
+      );
+      // Also create docs_index for SECTION-only searches (used by DocsEngine)
+      Eif (!names.includes("docs_index")) {
+        await this.memgraph.executeCypher(
+          `CALL text_search.create_index('docs_index', 'SECTION', ['heading', 'content'], {analyzer: 'standard'})`,
+          {},
+        );
+      }
+      this._bm25IndexKnownToExist = true;
+      return { created: true, alreadyExists: false };
+    } catch (err) {
+      return {
+        created: false,
+        alreadyExists: false,
+        error: err instanceof Error ? err.message : String(err),
+      };
+    }
+  }
+ 
+  private async graphExpansion(seedIds: string[], opts: RetrievalOptions): Promise<RankedNode[]> {
+    const limit = Math.max(1, Math.min(opts.limit || 10, 100));
+    if (!seedIds.length) {
+      return [];
+    }
+ 
+    const weight: Record<string, number> = {
+      CALLS: 0.9,
+      IMPORTS: 0.7,
+      CONTAINS: 0.5,
+      TESTS: 0.4,
+      INVOLVES: 0.3,
+      APPLIES_TO: 0.4,
+    };
+ 
+    const scores = new Map<string, number>();
+ 
+    for (const seedId of seedIds) {
+      const outgoing = this.index.getRelationshipsFrom(seedId);
+      const incoming = this.index.getRelationshipsTo(seedId);
+ 
+      for (const rel of [...outgoing, ...incoming]) {
+        const nodeId = rel.from === seedId ? rel.to : rel.from;
+        const boost = weight[rel.type] || 0.2;
+        scores.set(nodeId, (scores.get(nodeId) || 0) + boost);
+      }
+    }
+ 
+    if (!scores.size) {
+      return [];
+    }
+ 
+    return [...scores.entries()]
+      .sort((a, b) => b[1] - a[1])
+      .slice(0, limit)
+      .map(([nodeId, score]) => ({
+        nodeId,
+        score,
+        source: "graph",
+      }));
+  }
+ 
+  private fusionRRF(lists: RankedNode[][], k: number): RetrievalResult[] {
+    const scores = new Map<string, number>();
+    const sourceScores = new Map<string, { vector?: number; bm25?: number; graph?: number }>();
+ 
+    lists.forEach((list) => {
+      list.forEach((node, idx) => {
+        const rank = idx + 1;
+        const inc = 1 / (k + rank);
+        scores.set(node.nodeId, (scores.get(node.nodeId) || 0) + inc);
+ 
+        const existing = sourceScores.get(node.nodeId) || {};
+        existing[node.source] = node.score;
+        sourceScores.set(node.nodeId, existing);
+      });
+    });
+ 
+    return [...scores.entries()]
+      .sort((a, b) => b[1] - a[1])
+      .map(([nodeId, rrfScore]) => {
+        const meta = this.nodeMeta(nodeId);
+        return {
+          nodeId,
+          name: meta.name,
+          filePath: meta.filePath,
+          type: meta.type,
+          rrfScore: Number(rrfScore.toFixed(6)),
+          scores: sourceScores.get(nodeId) || {},
+        };
+      });
+  }
+ 
+  private lexicalFallback(
+    query: string,
+    projectId: string,
+    source: "vector" | "bm25",
+    limit: number,
+  ): RankedNode[] {
+    const tokens = query
+      .toLowerCase()
+      .split(/[^a-z0-9_]+/)
+      .filter((token) => token.length >= 2);
+ 
+    const nodes = [
+      ...this.index.getNodesByType("FUNCTION"),
+      ...this.index.getNodesByType("CLASS"),
+      ...this.index.getNodesByType("FILE"),
+    ];
+ 
+    return nodes
+      .filter((node) => String(node.properties.projectId || "") === String(projectId))
+      .map((node) => ({
+        nodeId: node.id,
+        score: this.scoreNode(node, tokens),
+        source,
+      }))
+      .filter((row) => row.score > 0)
+      .sort((a, b) => b.score - a.score)
+      .slice(0, limit);
+  }
+ 
+  private scoreNode(node: GraphNode, tokens: string[]): number {
+    const haystack =
+      `${node.id} ${node.properties.name || ""} ${node.properties.path || ""} ${node.properties.summary || ""}`.toLowerCase();
+    return tokens.reduce((sum, token) => sum + (haystack.includes(token) ? 1 : 0), 0);
+  }
+ 
+  private nodeMeta(nodeId: string): {
+    name: string;
+    filePath: string;
+    type: string;
+  } {
+    const node = this.index.getNode(nodeId);
+    Iif (!node) {
+      return {
+        name: nodeId,
+        filePath: "",
+        type: "UNKNOWN",
+      };
+    }
+ 
+    return {
+      name: String(node.properties.name || node.properties.path || node.id),
+      filePath: String(node.properties.path || node.properties.filePath || ""),
+      type: String(node.type || "UNKNOWN"),
+    };
+  }
+ 
+  private filterByType(results: RetrievalResult[], types?: string[]): RetrievalResult[] {
+    Eif (!types?.length) {
+      return results;
+    }
+ 
+    const allowed = new Set(types.map((item) => item.toUpperCase()));
+    return results.filter((row) => allowed.has(row.type.toUpperCase()));
+  }
+ 
+  private filterByProject(results: RetrievalResult[], projectId: string): RetrievalResult[] {
+    return results.filter((row) => {
+      const node = this.index.getNode(row.nodeId);
+      return String(node?.properties?.projectId || "") === String(projectId);
+    });
+  }
+}
+ 
+export default HybridRetriever;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/index.html b/coverage/lcov-report/src/graph/index.html new file mode 100644 index 0000000..4dba5bc --- /dev/null +++ b/coverage/lcov-report/src/graph/index.html @@ -0,0 +1,266 @@ + + + + + + Code coverage report for src/graph + + + + + + + + + +
+
+

All files src/graph

+
+ +
+ 64.06% + Statements + 681/1063 +
+ + +
+ 48.97% + Branches + 357/729 +
+ + +
+ 64.42% + Functions + 134/208 +
+ + +
+ 64.83% + Lines + 649/1001 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
builder.ts +
+
75.59%96/12755.55%65/11783.33%20/2480.55%87/108
cache.ts +
+
60%18/3036.36%4/1170%7/1060%18/30
client.ts +
+
64.59%104/16152.17%48/9280%20/2564.05%98/153
docs-builder.ts +
+
100%31/3145.45%5/11100%9/9100%30/30
hybrid-retriever.ts +
+
69.02%78/11348.93%46/9479.41%27/3470%77/110
index.ts +
+
87.3%55/6389.18%33/3778.57%11/1487.09%54/62
orchestrator.ts +
+
49.68%159/32032.71%71/21749.01%25/5150.65%155/306
ppr.ts +
+
97.16%103/10665.42%70/107100%7/7100%93/93
sync-state.ts +
+
0%0/630%0/190%0/220%0/60
types.ts +
+
0%0/00%0/00%0/00%0/0
watcher.ts +
+
75.51%37/4962.5%15/2466.66%8/1275.51%37/49
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/index.ts.html b/coverage/lcov-report/src/graph/index.ts.html new file mode 100644 index 0000000..3173797 --- /dev/null +++ b/coverage/lcov-report/src/graph/index.ts.html @@ -0,0 +1,859 @@ + + + + + + Code coverage report for src/graph/index.ts + + + + + + + + + +
+
+

All files / src/graph index.ts

+
+ +
+ 87.3% + Statements + 55/63 +
+ + +
+ 89.18% + Branches + 33/37 +
+ + +
+ 78.57% + Functions + 11/14 +
+ + +
+ 87.09% + Lines + 54/62 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +307x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +220x +220x +3x +1x +  +  +2x +  +  +  +  +  +  +  +  +2x +  +2x +3x +3x +2x +  +  +2x +1x +  +2x +  +2x +1x +  +  +  +1x +  +  +  +2x +  +  +217x +  +217x +  +217x +149x +  +217x +  +217x +217x +  +  +  +  +  +  +  +  +  +  +  +  +75x +  +75x +70x +  +75x +  +75x +65x +  +75x +  +75x +49x +  +75x +  +75x +75x +  +  +  +  +  +  +  +643x +  +  +  +  +  +  +103x +  +  +  +  +  +  +136x +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +2x +3x +3x +  +  +  +2x +1x +1x +1x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file graph/index
+ * @description In-memory graph index for nodes, relationships, and fast lookups.
+ * @remarks Acts as the primary runtime cache for tool and engine query operations.
+ */
+ 
+export interface GraphNode {
+  id: string;
+  type: string;
+  properties: Record<string, any>;
+}
+ 
+export interface GraphRelationship {
+  id: string;
+  from: string;
+  to: string;
+  type: string;
+  properties?: Record<string, any>;
+}
+ 
+export interface GraphIndex {
+  nodesByType: Map<string, GraphNode[]>;
+  nodeById: Map<string, GraphNode>;
+  relationshipsByFrom: Map<string, GraphRelationship[]>;
+  relationshipsByTo: Map<string, GraphRelationship[]>;
+  relationshipsByType: Map<string, GraphRelationship[]>;
+  statistics: {
+    totalNodes: number;
+    totalRelationships: number;
+    nodesByType: Record<string, number>;
+    relationshipsByType: Record<string, number>;
+  };
+}
+ 
+export class GraphIndexManager {
+  private index: GraphIndex = {
+    nodesByType: new Map(),
+    nodeById: new Map(),
+    relationshipsByFrom: new Map(),
+    relationshipsByTo: new Map(),
+    relationshipsByType: new Map(),
+    statistics: {
+      totalNodes: 0,
+      totalRelationships: 0,
+      nodesByType: {},
+      relationshipsByType: {},
+    },
+  };
+ 
+  /**
+   * Add a node to the index
+   */
+  addNode(id: string, type: string, properties: Record<string, any>, overwrite = false): void {
+    const existing = this.index.nodeById.get(id);
+    if (existing) {
+      if (!overwrite) {
+        return; // Deduplication
+      }
+ 
+      const mergedNode: GraphNode = {
+        id: existing.id,
+        type,
+        properties: {
+          ...existing.properties,
+          ...properties,
+        },
+      };
+ 
+      this.index.nodeById.set(id, mergedNode);
+ 
+      const typeNodes = this.index.nodesByType.get(existing.type) || [];
+      const idx = typeNodes.findIndex((node) => node.id === id);
+      if (idx >= 0) {
+        typeNodes.splice(idx, 1);
+      }
+ 
+      if (!this.index.nodesByType.has(type)) {
+        this.index.nodesByType.set(type, []);
+      }
+      this.index.nodesByType.get(type)!.push(mergedNode);
+ 
+      if (existing.type !== type) {
+        this.index.statistics.nodesByType[existing.type] = Math.max(
+          (this.index.statistics.nodesByType[existing.type] || 1) - 1,
+          0,
+        );
+        this.index.statistics.nodesByType[type] =
+          (this.index.statistics.nodesByType[type] || 0) + 1;
+      }
+ 
+      return;
+    }
+ 
+    const node: GraphNode = { id, type, properties };
+ 
+    this.index.nodeById.set(id, node);
+ 
+    if (!this.index.nodesByType.has(type)) {
+      this.index.nodesByType.set(type, []);
+    }
+    this.index.nodesByType.get(type)!.push(node);
+ 
+    this.index.statistics.totalNodes++;
+    this.index.statistics.nodesByType[type] = (this.index.statistics.nodesByType[type] || 0) + 1;
+  }
+ 
+  /**
+   * Add a relationship to the index
+   */
+  addRelationship(
+    id: string,
+    from: string,
+    to: string,
+    type: string,
+    properties?: Record<string, any>,
+  ): void {
+    const rel: GraphRelationship = { id, from, to, type, properties };
+ 
+    if (!this.index.relationshipsByFrom.has(from)) {
+      this.index.relationshipsByFrom.set(from, []);
+    }
+    this.index.relationshipsByFrom.get(from)!.push(rel);
+ 
+    if (!this.index.relationshipsByTo.has(to)) {
+      this.index.relationshipsByTo.set(to, []);
+    }
+    this.index.relationshipsByTo.get(to)!.push(rel);
+ 
+    if (!this.index.relationshipsByType.has(type)) {
+      this.index.relationshipsByType.set(type, []);
+    }
+    this.index.relationshipsByType.get(type)!.push(rel);
+ 
+    this.index.statistics.totalRelationships++;
+    this.index.statistics.relationshipsByType[type] =
+      (this.index.statistics.relationshipsByType[type] || 0) + 1;
+  }
+ 
+  /**
+   * Query nodes by type
+   */
+  getNodesByType(type: string): GraphNode[] {
+    return this.index.nodesByType.get(type) || [];
+  }
+ 
+  /**
+   * Query node by ID
+   */
+  getNode(id: string): GraphNode | undefined {
+    return this.index.nodeById.get(id);
+  }
+ 
+  /**
+   * Query relationships from a node
+   */
+  getRelationshipsFrom(nodeId: string): GraphRelationship[] {
+    return this.index.relationshipsByFrom.get(nodeId) || [];
+  }
+ 
+  /**
+   * Query relationships to a node (Phase 7.1 - reverse lookup)
+   */
+  getRelationshipsTo(nodeId: string): GraphRelationship[] {
+    return this.index.relationshipsByTo.get(nodeId) || [];
+  }
+ 
+  /**
+   * Query relationships by type
+   */
+  getRelationshipsByType(type: string): GraphRelationship[] {
+    return this.index.relationshipsByType.get(type) || [];
+  }
+ 
+  /**
+   * Get graph statistics
+   */
+  getStatistics(): GraphIndex["statistics"] {
+    return this.index.statistics;
+  }
+ 
+  /**
+   * Clear the index
+   */
+  clear(): void {
+    this.index.nodesByType.clear();
+    this.index.nodeById.clear();
+    this.index.relationshipsByFrom.clear();
+    this.index.relationshipsByTo.clear();
+    this.index.relationshipsByType.clear();
+    this.index.statistics = {
+      totalNodes: 0,
+      totalRelationships: 0,
+      nodesByType: {},
+      relationshipsByType: {},
+    };
+  }
+ 
+  /**
+   * Get all nodes in the index
+   */
+  getAllNodes(): GraphNode[] {
+    return Array.from(this.index.nodeById.values());
+  }
+ 
+  /**
+   * Get all relationships in the index
+   */
+  getAllRelationships(): GraphRelationship[] {
+    return Array.from(this.index.relationshipsByType.values()).flat();
+  }
+ 
+  /**
+   * Sync nodes and relationships from another index into this one
+   * Used to merge orchestrator's built index into the shared context index
+   */
+  syncFrom(sourceIndex: GraphIndexManager): {
+    nodesSynced: number;
+    relationshipsSynced: number;
+  } {
+    let nodesSynced = 0;
+    let relationshipsSynced = 0;
+ 
+    // Sync all nodes from source
+    for (const node of sourceIndex.getAllNodes()) {
+      this.addNode(node.id, node.type, node.properties, true);
+      nodesSynced++;
+    }
+ 
+    // Sync all relationships from source
+    for (const rel of sourceIndex.getAllRelationships()) {
+      try {
+        this.addRelationship(rel.id, rel.from, rel.to, rel.type, rel.properties);
+        relationshipsSynced++;
+      } catch (_e) {
+        // Deduplication may skip relationships - that's okay
+      }
+    }
+ 
+    return { nodesSynced, relationshipsSynced };
+  }
+ 
+  /**
+   * Export index as JSON (for snapshots)
+   */
+  export(): string {
+    return JSON.stringify(
+      {
+        nodesByType: Array.from(this.index.nodesByType.entries()),
+        nodeById: Array.from(this.index.nodeById.entries()),
+        statistics: this.index.statistics,
+      },
+      null,
+      2,
+    );
+  }
+}
+ 
+export default GraphIndexManager;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/orchestrator.ts.html b/coverage/lcov-report/src/graph/orchestrator.ts.html new file mode 100644 index 0000000..4eef309 --- /dev/null +++ b/coverage/lcov-report/src/graph/orchestrator.ts.html @@ -0,0 +1,3328 @@ + + + + + + Code coverage report for src/graph/orchestrator.ts + + + + + + + + + +
+
+

All files / src/graph orchestrator.ts

+
+ +
+ 49.68% + Statements + 159/320 +
+ + +
+ 32.71% + Branches + 71/217 +
+ + +
+ 49.01% + Functions + 25/51 +
+ + +
+ 50.65% + Lines + 155/306 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +123x +123x +123x +123x +  +  +  +  +  +  +  +  +  +  +  +  +123x +123x +123x +  +  +  +123x +123x +123x +123x +  +  +  +  +  +  +  +  +  +  +  +123x +123x +123x +  +  +  +  +  +  +  +  +  +  +  +  +123x +123x +123x +  +492x +123x +492x +492x +  +  +492x +  +  +  +  +123x +123x +123x +  +  +  +  +  +  +  +  +123x +  +123x +492x +492x +  +123x +  +  +123x +123x +  +  +  +  +123x +123x +123x +123x +123x +123x +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +3x +3x +  +  +  +  +  +3x +  +3x +  +  +  +  +3x +3x +  +3x +2x +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +2x +2x +2x +2x +  +2x +  +  +  +  +  +  +  +1x +1x +  +  +  +3x +3x +3x +3x +  +  +  +  +  +  +3x +3x +3x +3x +3x +3x +3x +  +3x +  +  +3x +  +  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +3x +  +  +3x +  +  +3x +3x +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +3x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +3x +3x +  +  +  +  +  +3x +4x +16x +  +  +3x +3x +3x +3x +4x +4x +  +4x +  +4x +  +  +  +3x +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +2x +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +2x +2x +70x +70x +70x +  +2x +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +3x +2x +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +41x +39x +  +  +3x +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file graph/orchestrator
+ * @description Coordinates parsing, graph building, cache updates, and persistence flows.
+ * @remarks Handles full/incremental rebuild orchestration and parser strategy selection.
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import * as env from "../env.js";
+import TypeScriptParser, { type ParsedFile } from "../parsers/typescript-parser.js";
+import ParserRegistry from "../parsers/parser-registry.js";
+import type { ParseResult } from "../parsers/parser-interface.js";
+import {
+  PythonParser,
+  GoParser,
+  RustParser,
+  JavaParser,
+} from "../parsers/regex-language-parsers.js";
+import {
+  getTreeSitterParsers,
+  checkTreeSitterAvailability,
+} from "../parsers/tree-sitter-parser.js";
+import {
+  getTreeSitterTypeScriptParser,
+  getTreeSitterTSXParser,
+  getTreeSitterJavaScriptParser,
+  getTreeSitterJSXParser,
+  checkTsTreeSitterAvailability,
+  checkJsTreeSitterAvailability,
+  type TreeSitterTypeScriptParser,
+  type TreeSitterTSXParser,
+  type TreeSitterJavaScriptParser,
+  type TreeSitterJSXParser,
+} from "../parsers/tree-sitter-typescript-parser.js";
+import GraphBuilder, { type CypherStatement } from "./builder.js";
+import GraphIndexManager from "./index.js";
+import CacheManager from "./cache.js";
+import MemgraphClient from "./client.js";
+import CodeSummarizer from "../response/summarizer.js";
+import { DocsEngine } from "../engines/docs-engine.js";
+import { logger } from "../utils/logger.js";
+ 
+export interface BuildOptions {
+  mode: "full" | "incremental";
+  verbose: boolean;
+  workspaceRoot: string;
+  projectId: string;
+  sourceDir: string;
+  exclude: string[];
+  changedFiles?: string[];
+  txId?: string;
+  txTimestamp?: number;
+  /** Index markdown documentation files into DOCUMENT/SECTION nodes (default: true for full builds) */
+  indexDocs?: boolean;
+}
+ 
+export interface BuildResult {
+  success: boolean;
+  duration: number;
+  filesProcessed: number;
+  nodesCreated: number;
+  relationshipsCreated: number;
+  filesChanged: number;
+  errors: string[];
+  warnings: string[];
+  txId?: string;
+  txTimestamp?: number;
+}
+ 
+export class GraphOrchestrator {
+  private parser: TypeScriptParser;
+  private tsTsParser: TreeSitterTypeScriptParser | null = null;
+  private tsTsxParser: TreeSitterTSXParser | null = null;
+  private tsJsParser: TreeSitterJavaScriptParser | null = null;
+  private tsJsxParser: TreeSitterJSXParser | null = null;
+  private useTsTreeSitter: boolean;
+  private useJsTreeSitter: boolean;
+  private parserRegistry: ParserRegistry;
+  private builder: GraphBuilder;
+  private index: GraphIndexManager;
+  private sharedIndex?: GraphIndexManager;
+  private cache: CacheManager;
+  private memgraph: MemgraphClient;
+  private verbose: boolean;
+  private summarizer: CodeSummarizer;
+ 
+  constructor(memgraph?: MemgraphClient, verbose = false, sharedIndex?: GraphIndexManager) {
+    this.parser = new TypeScriptParser();
+    this.parserRegistry = new ParserRegistry();
+    this.sharedIndex = sharedIndex;
+ 
+    // ── Tree-sitter TypeScript / TSX ────────────────────────────────────────
+    // Enable when CODE_GRAPH_USE_TREE_SITTER=true AND native binding compiled.
+    const wantTsTs = env.LXRAG_USE_TREE_SITTER;
+    const tsAvailability = checkTsTreeSitterAvailability();
+    this.useTsTreeSitter = false;
+    Iif (wantTsTs) {
+      if (tsAvailability.typescript) {
+        this.tsTsParser = getTreeSitterTypeScriptParser();
+      }
+      if (tsAvailability.tsx) {
+        this.tsTsxParser = getTreeSitterTSXParser();
+      }
+      this.useTsTreeSitter = tsAvailability.typescript || tsAvailability.tsx;
+    }
+ 
+    // ── Tree-sitter JavaScript / JSX ───────────────────────────────────────
+    // Shares the same grammar (tree-sitter-javascript); both dialects load it.
+    const jsAvailability = checkJsTreeSitterAvailability();
+    this.useJsTreeSitter = false;
+    Iif (wantTsTs) {
+      if (jsAvailability.javascript) {
+        this.tsJsParser = getTreeSitterJavaScriptParser();
+      }
+      if (jsAvailability.jsx) {
+        this.tsJsxParser = getTreeSitterJSXParser();
+      }
+      this.useJsTreeSitter = jsAvailability.javascript;
+    }
+ 
+    // ── Python / Go / Rust / Java ────────────────────────────────────────────
+    // Register tree-sitter parsers (AST-accurate); fall back per language to
+    // regex parsers when the native binding is unavailable.
+    const tsParsers = getTreeSitterParsers();
+    const availability = checkTreeSitterAvailability();
+    const regexFallbacks = [new PythonParser(), new GoParser(), new RustParser(), new JavaParser()];
+ 
+    const tsByLang = new Map(tsParsers.map((p) => [p.language, p]));
+    for (const fallback of regexFallbacks) {
+      const tsParser = tsByLang.get(fallback.language);
+      Iif (tsParser && availability[fallback.language]) {
+        this.parserRegistry.register(tsParser);
+      } else {
+        this.parserRegistry.register(fallback);
+      }
+    }
+ 
+    // ── Startup log ─────────────────────────────────────────────────────────
+    const allAvailable: string[] = [];
+    const allFallback: string[] = [];
+    Iif (wantTsTs) {
+      if (tsAvailability.typescript) allAvailable.push("typescript");
+      else allFallback.push("typescript");
+      if (tsAvailability.tsx) allAvailable.push("tsx");
+      else allFallback.push("tsx");
+      if (jsAvailability.javascript) allAvailable.push("javascript", "jsx");
+      else allFallback.push("javascript", "jsx");
+    } else {
+      // TS/JS tree-sitter disabled by env — always regex
+      allFallback.push("typescript", "tsx", "javascript", "jsx");
+    }
+    for (const [lang, ok] of Object.entries(availability)) {
+      Iif (ok) allAvailable.push(lang);
+      else allFallback.push(lang);
+    }
+    Iif (allAvailable.length > 0) {
+      logger.error(`[parsers] tree-sitter active for: ${allAvailable.join(", ")}`);
+    }
+    Eif (allFallback.length > 0) {
+      logger.error(
+        `[parsers] regex fallback for: ${allFallback.join(", ")} (install tree-sitter grammar packages for AST accuracy)`,
+      );
+    }
+ 
+    this.builder = new GraphBuilder();
+    this.index = new GraphIndexManager();
+    this.cache = new CacheManager();
+    this.memgraph = memgraph || new MemgraphClient();
+    this.verbose = verbose;
+    this.summarizer = new CodeSummarizer(env.LXRAG_SUMMARIZER_URL);
+  }
+ 
+  /**
+   * Build the entire code graph
+   */
+  async build(options: Partial<BuildOptions> = {}): Promise<BuildResult> {
+    const startTime = Date.now();
+    const opts: BuildOptions = {
+      mode: options.mode || "incremental",
+      verbose: options.verbose ?? this.verbose,
+      workspaceRoot: options.workspaceRoot || env.LXRAG_WORKSPACE_ROOT,
+      projectId:
+        options.projectId ||
+        env.LXRAG_PROJECT_ID ||
+        path.basename(options.workspaceRoot || env.LXRAG_WORKSPACE_ROOT),
+      sourceDir: options.sourceDir || "src",
+      exclude: options.exclude || ["node_modules", "dist", ".next", ".lxrag"],
+      txId: options.txId,
+      txTimestamp: options.txTimestamp,
+    };
+ 
+    const errors: string[] = [];
+    const warnings: string[] = [];
+ 
+    try {
+      Iif (opts.verbose) {
+        logger.error("[GraphOrchestrator] Starting build...");
+        logger.error(`[GraphOrchestrator] Mode: ${opts.mode}`);
+      }
+ 
+      // Get all source files across supported languages
+      const files = await this.findSourceFiles(opts.sourceDir, opts.exclude, opts.workspaceRoot);
+ 
+      Iif (opts.verbose) {
+        logger.error(`[GraphOrchestrator] Found ${files.length} source files`);
+      }
+ 
+      // Determine which files to process
+      let filesToProcess = files;
+      let filesChanged = 0;
+ 
+      if (opts.mode === "incremental") {
+        const scopedChangedFiles = this.normalizeChangedFiles(
+          opts.changedFiles,
+          opts.workspaceRoot,
+        );
+ 
+        Iif (scopedChangedFiles.length > 0) {
+          filesToProcess = scopedChangedFiles.filter(
+            (filePath) => fs.existsSync(filePath) && files.includes(filePath),
+          );
+          filesChanged = filesToProcess.length;
+ 
+          if (opts.verbose) {
+            logger.error(
+              `[GraphOrchestrator] Incremental (explicit): ${filesToProcess.length} existing of ${filesChanged} changed file(s)`,
+            );
+          }
+        } else {
+          const hashes = await Promise.all(
+            files.map(async (f) => ({
+              path: f,
+              hash: await this.hashFile(f),
+              LOC: (fs.readFileSync(f, "utf-8").match(/\n/g) || []).length + 1,
+            })),
+          );
+ 
+          filesToProcess = hashes
+            .filter((f) => this.cache.hasChanged(f.path, f.hash))
+            .map((f) => f.path);
+          filesChanged = filesToProcess.length;
+ 
+          Iif (opts.verbose) {
+            logger.error(
+              `[GraphOrchestrator] Incremental: ${filesChanged} changed of ${files.length}`,
+            );
+          }
+        }
+      } else {
+        // Full rebuild
+        this.cache.clear();
+        filesChanged = files.length;
+      }
+ 
+      // Parse files and build graph
+      let nodesCreated = 0;
+      const statementsToExecute: CypherStatement[] = [];
+      const parsedFiles: Array<{ filePath: string; parsed: ParsedFile }> = [];
+      this.builder = new GraphBuilder(
+        opts.projectId,
+        opts.workspaceRoot,
+        opts.txId,
+        opts.txTimestamp,
+      );
+ 
+      for (const filePath of filesToProcess) {
+        try {
+          const parsed = await this.parseSourceFile(filePath, opts.workspaceRoot);
+          await this.attachSummaries(parsed);
+          parsedFiles.push({ filePath, parsed });
+          const adaptedParsed = this.adaptParsedFile(parsed);
+          const statements = this.builder.buildFromParsedFile(adaptedParsed);
+ 
+          statementsToExecute.push(...statements);
+ 
+          // Update cache
+          this.cache.set(filePath, parsed.hash, parsed.LOC);
+ 
+          // Track for index
+          this.addToIndex(parsed, opts.projectId);
+          nodesCreated += this.countNodesInStatements(statements);
+ 
+          Iif (opts.verbose && filesToProcess.indexOf(filePath) % 50 === 0) {
+            logger.error(
+              `[GraphOrchestrator] Processed ${filesToProcess.indexOf(filePath)}/${filesToProcess.length} files`,
+            );
+          }
+        } catch (error) {
+          errors.push(`Failed to parse ${filePath}: ${error}`);
+        }
+      }
+ 
+      // Build TEST_SUITE-[:TESTS]->FILE relationships (Phase 3.3)
+      const testRelationships = this.buildTestRelationships(
+        parsedFiles,
+        opts.workspaceRoot,
+        opts.projectId,
+      );
+      statementsToExecute.push(...testRelationships);
+ 
+      // Seed progress nodes if config has progress section (Phase 5.2)
+      Iif (opts.verbose) {
+        logger.error("[GraphOrchestrator] Seeding progress tracking nodes...");
+      }
+      const progressStatements = this.seedProgressNodes(opts.projectId);
+      statementsToExecute.push(...progressStatements);
+ 
+      // Execute statements against Memgraph (MVP: in offline mode, just count)
+      const relationshipsCreated = statementsToExecute.length;
+ 
+      Iif (this.memgraph.isConnected()) {
+        if (opts.verbose) {
+          logger.error(
+            `[GraphOrchestrator] Executing ${statementsToExecute.length} Cypher statements...`,
+          );
+        }
+        const results = await this.memgraph.executeBatch(statementsToExecute);
+        const failedStatements = results.filter((r) => r.error).length;
+        if (failedStatements > 0) {
+          warnings.push(`${failedStatements} Cypher statements failed`);
+        }
+      } else {
+        Iif (opts.verbose) {
+          logger.error(
+            `[GraphOrchestrator] Memgraph offline - statements prepared but not executed`,
+          );
+        }
+      }
+ 
+      // Index documentation files (Phase 6 — Docs/ADR Indexing)
+      const shouldIndexDocs =
+        (opts.indexDocs ?? true) && opts.mode === "full" && this.memgraph.isConnected();
+      Iif (shouldIndexDocs) {
+        if (opts.verbose) {
+          logger.error("[GraphOrchestrator] Indexing documentation files...");
+        }
+        try {
+          const docsEngine = new DocsEngine(this.memgraph);
+          const docsResult = await docsEngine.indexWorkspace(opts.workspaceRoot, opts.projectId, {
+            incremental: true,
+            txId: opts.txId,
+          });
+          if (opts.verbose) {
+            logger.error(
+              `[GraphOrchestrator] Docs indexed: ${docsResult.indexed} files, ` +
+                `${docsResult.skipped} skipped, ${docsResult.errors.length} errors`,
+            );
+          }
+          if (docsResult.errors.length > 0) {
+            for (const e of docsResult.errors) {
+              warnings.push(`[docs] ${e.file}: ${e.error}`);
+            }
+          }
+        } catch (docsErr) {
+          warnings.push(
+            `[docs] Indexing failed: ${docsErr instanceof Error ? docsErr.message : String(docsErr)}`,
+          );
+        }
+      }
+ 
+      // Save cache
+      this.cache.save();
+ 
+      // SYNC: Propagate internal index to shared context index
+      if (this.sharedIndex) {
+        try {
+          const syncResult = this.sharedIndex.syncFrom(this.index);
+          Iif (opts.verbose) {
+            logger.error(
+              `[GraphOrchestrator] Index synced: ${syncResult.nodesSynced} nodes, ${syncResult.relationshipsSynced} relationships`,
+            );
+          }
+        } catch (syncError) {
+          warnings.push(
+            `[sync] Failed to sync index: ${syncError instanceof Error ? syncError.message : String(syncError)}`,
+          );
+        }
+      }
+ 
+      const duration = Date.now() - startTime;
+ 
+      Iif (opts.verbose) {
+        const stats = this.index.getStatistics();
+        logger.error("[GraphOrchestrator] Build complete!");
+        logger.error(`[GraphOrchestrator] Duration: ${duration}ms`);
+        logger.error(`[GraphOrchestrator] Files processed: ${filesToProcess.length}`);
+        logger.error(`[GraphOrchestrator] Nodes created: ${nodesCreated}`);
+        logger.error(`[GraphOrchestrator] Relationships: ${relationshipsCreated}`);
+        logger.error(`[GraphOrchestrator] Statistics:`, stats);
+      }
+ 
+      return {
+        success: errors.length === 0,
+        duration,
+        filesProcessed: filesToProcess.length,
+        nodesCreated,
+        relationshipsCreated,
+        filesChanged,
+        errors,
+        warnings,
+        txId: opts.txId,
+        txTimestamp: opts.txTimestamp,
+      };
+    } catch (error) {
+      const duration = Date.now() - startTime;
+      errors.push(`Build failed: ${error}`);
+      return {
+        success: false,
+        duration,
+        filesProcessed: 0,
+        nodesCreated: 0,
+        relationshipsCreated: 0,
+        filesChanged: 0,
+        errors,
+        warnings,
+        txId: opts.txId,
+        txTimestamp: opts.txTimestamp,
+      };
+    }
+  }
+ 
+  /**
+   * Find all supported source files in source directory
+   */
+  private async findSourceFiles(
+    sourceDir: string,
+    exclude: string[],
+    workspaceRoot: string,
+  ): Promise<string[]> {
+    const files: string[] = [];
+    // If sourceDir is absolute, use it directly; otherwise resolve relative to workspace root
+    const basePath = path.isAbsolute(sourceDir)
+      ? sourceDir
+      : path.resolve(workspaceRoot, sourceDir);
+ 
+    if (fs.existsSync(basePath)) {
+      logger.error(`[GraphOrchestrator] Scanning directory: ${basePath}`);
+    } else E{
+      logger.warn(`[GraphOrchestrator] Source directory not found: ${basePath}`);
+      return files;
+    }
+ 
+    const shouldExclude = (filePath: string): boolean => {
+      const rel = path.relative(basePath, filePath);
+      return exclude.some((ex) => rel.includes(ex));
+    };
+ 
+    const walk = (dir: string): void => {
+      try {
+        const entries = fs.readdirSync(dir, { withFileTypes: true });
+        for (const entry of entries) {
+          const fullPath = path.join(dir, entry.name);
+          Iif (shouldExclude(fullPath)) continue;
+ 
+          Iif (entry.isDirectory()) {
+            walk(fullPath);
+          } else if (
+            entry.isFile() &&
+            /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java)$/.test(entry.name)
+          ) {
+            files.push(fullPath);
+          }
+        }
+      } catch (error) {
+        logger.warn(`[GraphOrchestrator] Error scanning directory ${dir}: ${error}`);
+      }
+    };
+ 
+    walk(basePath);
+    return files;
+  }
+ 
+  private normalizeChangedFiles(
+    changedFiles: string[] | undefined,
+    workspaceRoot: string,
+  ): string[] {
+    Eif (!Array.isArray(changedFiles) || changedFiles.length === 0) {
+      return [];
+    }
+ 
+    const normalizedWorkspaceRoot = path.resolve(workspaceRoot);
+    const seen = new Set<string>();
+ 
+    return changedFiles
+      .map((entry) => String(entry || "").trim())
+      .filter(Boolean)
+      .map((entry) =>
+        path.isAbsolute(entry) ? path.normalize(entry) : path.resolve(workspaceRoot, entry),
+      )
+      .filter((filePath) => {
+        const relative = path.relative(normalizedWorkspaceRoot, filePath);
+        return relative.length > 0 && !relative.startsWith("..") && !path.isAbsolute(relative);
+      })
+      .filter((filePath) => /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java)$/.test(filePath))
+      .filter((filePath) => {
+        if (seen.has(filePath)) {
+          return false;
+        }
+        seen.add(filePath);
+        return true;
+      });
+  }
+ 
+  private async parseSourceFile(filePath: string, workspaceRoot: string): Promise<ParsedFile> {
+    const extension = path.extname(filePath).toLowerCase();
+    Eif (extension === ".ts" || extension === ".tsx") {
+      // Prefer tree-sitter when available and opted in
+      Iif (this.useTsTreeSitter) {
+        const tsParser = extension === ".tsx" ? this.tsTsxParser : this.tsTsParser;
+        if (tsParser?.isAvailable) {
+          const content = fs.readFileSync(filePath, "utf-8");
+          const result = await tsParser.parse(filePath, content);
+          if (result.symbols.length > 0) {
+            return this.adaptLanguageParseResult(filePath, workspaceRoot, content, result);
+          }
+        }
+      }
+      return this.parser.parseFile(filePath, { workspaceRoot });
+    }
+ 
+    if (
+      extension === ".js" ||
+      extension === ".jsx" ||
+      extension === ".mjs" ||
+      extension === ".cjs"
+    ) {
+      if (this.useJsTreeSitter) {
+        const jsParser = extension === ".jsx" ? this.tsJsxParser : this.tsJsParser;
+        if (jsParser?.isAvailable) {
+          const content = fs.readFileSync(filePath, "utf-8");
+          const result = await jsParser.parse(filePath, content);
+          if (result.symbols.length > 0) {
+            return this.adaptLanguageParseResult(filePath, workspaceRoot, content, result);
+          }
+        }
+      }
+      // Fallback: FILE node only (no regex parser for plain JS)
+      const content = fs.readFileSync(filePath, "utf-8");
+      return this.adaptLanguageParseResult(filePath, workspaceRoot, content, {
+        file: path.basename(filePath),
+        language: this.languageFromExtension(extension),
+        symbols: [],
+      });
+    }
+ 
+    const content = fs.readFileSync(filePath, "utf-8");
+    const parsed = await this.parserRegistry.parse(filePath, content);
+    if (parsed) {
+      return this.adaptLanguageParseResult(filePath, workspaceRoot, content, parsed);
+    }
+ 
+    return this.adaptLanguageParseResult(filePath, workspaceRoot, content, {
+      file: path.basename(filePath),
+      language: this.languageFromExtension(extension),
+      symbols: [],
+    });
+  }
+ 
+  private async attachSummaries(parsed: ParsedFile): Promise<void> {
+    const fileHash = parsed.hash || "no-hash";
+    const relativePath = parsed.relativePath || parsed.filePath;
+ 
+    (parsed as ParsedFile & { summary?: string }).summary = await this.summarizer.summarize({
+      kind: "file",
+      cacheKey: `file:${relativePath}:${fileHash}`,
+      name: path.basename(parsed.filePath),
+      path: relativePath,
+      language: parsed.language,
+      loc: parsed.LOC,
+      metadata: {
+        functionCount: parsed.functions.length,
+        classCount: parsed.classes.length,
+        importCount: parsed.imports.length,
+      },
+    });
+ 
+    for (const [index, fn] of parsed.functions.entries()) {
+      (fn as typeof fn & { summary?: string }).summary = await this.summarizer.summarize({
+        kind: "function",
+        cacheKey: `function:${relativePath}:${fn.name}:${index}:${fileHash}`,
+        name: fn.name,
+        path: relativePath,
+        language: parsed.language,
+        loc: fn.LOC,
+        metadata: { startLine: fn.startLine, endLine: fn.endLine },
+      });
+    }
+ 
+    for (const [index, cls] of parsed.classes.entries()) {
+      (cls as typeof cls & { summary?: string }).summary = await this.summarizer.summarize({
+        kind: "class",
+        cacheKey: `class:${relativePath}:${cls.name}:${index}:${fileHash}`,
+        name: cls.name,
+        path: relativePath,
+        language: parsed.language,
+        loc: cls.LOC,
+        metadata: { kind: cls.kind, extends: cls.extends },
+      });
+    }
+ 
+    for (const [index, imp] of parsed.imports.entries()) {
+      (imp as typeof imp & { summary?: string }).summary = await this.summarizer.summarize({
+        kind: "import",
+        cacheKey: `import:${relativePath}:${imp.source}:${index}:${fileHash}`,
+        name: imp.source,
+        path: relativePath,
+        language: parsed.language,
+        metadata: { specifierCount: imp.specifiers.length },
+      });
+    }
+  }
+ 
+  private adaptLanguageParseResult(
+    filePath: string,
+    workspaceRoot: string,
+    content: string,
+    parsed: ParseResult,
+  ): ParsedFile {
+    const relativePath = path.relative(workspaceRoot, filePath).replace(/\\/g, "/");
+    const hash = this.simpleHash(content);
+    const LOC = content.split("\n").length;
+ 
+    const imports = parsed.symbols
+      .filter((symbol) => symbol.type === "import")
+      .map((symbol, index) => ({
+        id: `${relativePath}:import:${index}`,
+        source: symbol.name,
+        specifiers: [
+          {
+            name: symbol.name,
+            imported: symbol.name,
+            isDefault: false,
+          },
+        ],
+        startLine: symbol.startLine,
+      }));
+ 
+    const functions = parsed.symbols
+      .filter((symbol) => symbol.type === "function" || symbol.type === "method")
+      .map((symbol, index) => ({
+        id: `${relativePath}:function:${symbol.name}:${index}`,
+        name: symbol.name,
+        // Preserve kind from symbol ("arrow", "method", etc.) when present
+        kind: (symbol.kind as "function" | "arrow" | "method" | undefined) ?? ("function" as const),
+        startLine: symbol.startLine,
+        endLine: symbol.endLine,
+        LOC: Math.max(1, symbol.endLine - symbol.startLine + 1),
+        parameters: [],
+        isExported: false,
+        // Preserve scopePath for SCIP method-ID generation (builder uses (fn as any).scopePath)
+        scopePath: symbol.scopePath,
+      }));
+ 
+    const classes = parsed.symbols
+      .filter(
+        (symbol) =>
+          symbol.type === "class" ||
+          symbol.type === "interface" ||
+          symbol.kind === "interface" ||
+          symbol.kind === "type" ||
+          symbol.kind === "enum",
+      )
+      .map((symbol, index) => ({
+        id: `${relativePath}:class:${symbol.name}:${index}`,
+        name: symbol.name,
+        kind:
+          symbol.kind === "interface" || symbol.type === "interface"
+            ? ("interface" as const)
+            : ("class" as const),
+        startLine: symbol.startLine,
+        endLine: symbol.endLine,
+        LOC: Math.max(1, symbol.endLine - symbol.startLine + 1),
+        isExported: false,
+      }));
+ 
+    return {
+      filePath,
+      relativePath,
+      language: parsed.language,
+      LOC,
+      hash,
+      ast: {
+        type: "file",
+        name: path.basename(filePath),
+        startLine: 1,
+        endLine: LOC,
+        text: content,
+        children: [],
+      },
+      functions,
+      classes,
+      variables: [],
+      imports,
+      exports: [],
+      testSuites: [],
+    };
+  }
+ 
+  private languageFromExtension(extension: string): string {
+    const table: Record<string, string> = {
+      ".py": "python",
+      ".go": "go",
+      ".rs": "rust",
+      ".java": "java",
+      ".ts": "typescript",
+      ".tsx": "typescript",
+      ".js": "javascript",
+      ".jsx": "javascript",
+      ".mjs": "javascript",
+      ".cjs": "javascript",
+    };
+    return table[extension] || "unknown";
+  }
+ 
+  /**
+   * Calculate hash of file contents
+   */
+  private async hashFile(filePath: string): Promise<string> {
+    const content = fs.readFileSync(filePath, "utf-8");
+    return this.simpleHash(content);
+  }
+ 
+  private simpleHash(content: string): string {
+    let hash = 0;
+    for (let i = 0; i < content.length; i++) {
+      const char = content.charCodeAt(i);
+      hash = (hash << 5) - hash + char;
+      hash = hash & hash; // Convert to 32-bit integer
+    }
+    return Math.abs(hash).toString(16);
+  }
+ 
+  /**
+   * Add parsed file to in-memory index
+   */
+  private addToIndex(parsed: ParsedFile, projectId?: string): void {
+    // FILE node
+    this.index.addNode(`file:${parsed.relativePath}`, "FILE", {
+      path: parsed.filePath,
+      relativePath: parsed.relativePath,
+      language: parsed.language,
+      LOC: parsed.LOC,
+      hash: parsed.hash,
+      summary: (parsed as ParsedFile & { summary?: string }).summary,
+      ...(projectId ? { projectId } : {}),
+    });
+ 
+    // FUNCTION nodes
+    parsed.functions.forEach((fn) => {
+      this.index.addNode(fn.id, "FUNCTION", {
+        name: fn.name,
+        kind: fn.kind,
+        filePath: parsed.filePath,
+        startLine: fn.startLine,
+        endLine: fn.endLine,
+        LOC: fn.LOC,
+        parameters: fn.parameters,
+        isExported: fn.isExported,
+        summary: (fn as typeof fn & { summary?: string }).summary,
+        ...(projectId ? { projectId } : {}),
+      });
+      this.index.addRelationship(
+        `contains:${fn.id}`,
+        `file:${parsed.relativePath}`,
+        fn.id,
+        "CONTAINS",
+      );
+    });
+ 
+    // CLASS nodes
+    parsed.classes.forEach((cls) => {
+      this.index.addNode(cls.id, "CLASS", {
+        name: cls.name,
+        kind: cls.kind,
+        filePath: parsed.filePath,
+        startLine: cls.startLine,
+        endLine: cls.endLine,
+        LOC: cls.LOC,
+        isExported: cls.isExported,
+        extends: cls.extends,
+        summary: (cls as typeof cls & { summary?: string }).summary,
+        ...(projectId ? { projectId } : {}),
+      });
+      this.index.addRelationship(
+        `contains:${cls.id}`,
+        `file:${parsed.relativePath}`,
+        cls.id,
+        "CONTAINS",
+      );
+    });
+ 
+    // IMPORT nodes
+    parsed.imports.forEach((imp) => {
+      this.index.addNode(imp.id, "IMPORT", {
+        source: imp.source,
+        specifiers: imp.specifiers,
+        summary: (imp as typeof imp & { summary?: string }).summary,
+      });
+      this.index.addRelationship(
+        `imports:${imp.id}`,
+        `file:${parsed.relativePath}`,
+        imp.id,
+        "IMPORTS",
+      );
+    });
+  }
+ 
+  /**
+   * Count nodes created in Cypher statements
+   */
+  private countNodesInStatements(statements: CypherStatement[]): number {
+    let count = 0;
+    for (const stmt of statements) {
+      // Rough count: each MERGE with a node type
+      if (stmt.query.includes("MERGE (") || stmt.query.includes("CREATE (")) {
+        count++;
+      }
+    }
+    return Math.max(count, 1); // At least 1 node per file
+  }
+ 
+  /**
+   * Adapt TypeScriptParser ParsedFile to GraphBuilder ParsedFile interface
+   */
+  private adaptParsedFile(parsed: ParsedFile): any {
+    return {
+      path: parsed.relativePath,
+      filePath: parsed.filePath,
+      relativePath: parsed.relativePath,
+      language: parsed.language,
+      LOC: parsed.LOC,
+      hash: parsed.hash,
+      summary: (parsed as ParsedFile & { summary?: string }).summary,
+      imports: parsed.imports.map((imp) => ({
+        id: imp.id,
+        source: imp.source,
+        specifiers: imp.specifiers.map((spec) => spec.imported || spec.name),
+        startLine: imp.startLine,
+        summary: (imp as typeof imp & { summary?: string }).summary,
+      })),
+      exports: parsed.exports.map((exp) => ({
+        id: exp.id,
+        name: exp.name,
+        type: exp.isDefault ? "default" : "named",
+        isDefault: exp.isDefault,
+        startLine: exp.startLine,
+      })),
+      functions: parsed.functions.map((fn) => ({
+        id: fn.id,
+        name: fn.name,
+        kind: fn.kind,
+        parameters: fn.parameters.map((p) => ({ name: p, type: undefined })),
+        returnType: undefined,
+        async: false,
+        line: fn.startLine,
+        startLine: fn.startLine,
+        endLine: fn.endLine,
+        LOC: fn.LOC,
+        isExported: fn.isExported,
+        summary: (fn as typeof fn & { summary?: string }).summary,
+      })),
+      classes: parsed.classes.map((cls) => ({
+        id: cls.id,
+        name: cls.name,
+        methods: [],
+        properties: [],
+        line: cls.startLine,
+        startLine: cls.startLine,
+        endLine: cls.endLine,
+        LOC: cls.LOC,
+        isExported: cls.isExported,
+        implements: cls.implements,
+        extends: cls.extends,
+        summary: (cls as typeof cls & { summary?: string }).summary,
+      })),
+      variables: parsed.variables || [],
+    };
+  }
+ 
+  /**
+   * Build TEST_SUITE-[:TESTS]->FILE relationships (Phase 3.3)
+   * For each test file with test suites, find what source files it imports
+   * and create TESTS relationships to those files
+   */
+  private buildTestRelationships(
+    parsedFiles: Array<{ filePath: string; parsed: ParsedFile }>,
+    workspaceRoot: string,
+    projectId: string,
+  ): CypherStatement[] {
+    const statements: CypherStatement[] = [];
+ 
+    // Filter test files
+    const testFiles = parsedFiles.filter((f) => this.isTestFile(f.filePath));
+ 
+    for (const testFile of testFiles) {
+      const testSuites = testFile.parsed.testSuites || [];
+      if (testSuites.length === 0) continue;
+ 
+      // Get imports from test file
+      const imports = testFile.parsed.imports || [];
+ 
+      for (const imp of imports) {
+        // Try to find the imported file in our parsed files
+        const importedFile = this.resolveImportedFile(
+          imp.source,
+          testFile.filePath,
+          parsedFiles,
+          workspaceRoot,
+        );
+        if (!importedFile) continue;
+ 
+        // Create TEST_SUITE-[:TESTS]->FILE relationships
+        for (const suite of testSuites) {
+          statements.push({
+            query: `
+              MATCH (ts:TEST_SUITE {id: $testSuiteId})
+              MATCH (f:FILE {id: $targetFileId})
+              MERGE (ts)-[:TESTS]->(f)
+            `,
+            params: {
+              testSuiteId: `${projectId}:test_suite:${suite.id}`,
+              targetFileId: `${projectId}:file:${importedFile}`,
+            },
+          });
+        }
+      }
+    }
+ 
+    return statements;
+  }
+ 
+  /**
+   * Check if a file is a test file
+   */
+  private isTestFile(filePath: string): boolean {
+    return (
+      filePath.includes(".test.") ||
+      filePath.includes(".spec.") ||
+      filePath.includes("/e2e/") ||
+      filePath.includes("/__tests__/")
+    );
+  }
+ 
+  /**
+   * Resolve an import statement to an actual file path
+   */
+  private resolveImportedFile(
+    source: string,
+    fromFile: string,
+    parsedFiles: Array<{ filePath: string; parsed: ParsedFile }>,
+    workspaceRoot: string,
+  ): string | null {
+    // Skip external imports
+    if (!source.startsWith(".") && !source.startsWith("src/")) {
+      return null;
+    }
+ 
+    let resolvedPath: string;
+ 
+    if (source.startsWith(".")) {
+      // Relative import
+      const dir = path.dirname(fromFile);
+      resolvedPath = path.resolve(dir, source);
+    } else if (source.startsWith("src/")) {
+      // Absolute src import
+      resolvedPath = path.resolve(workspaceRoot, source);
+    } else {
+      return null;
+    }
+ 
+    // Try to find matching file in parsed files
+    const candidates = [
+      resolvedPath,
+      `${resolvedPath}.ts`,
+      `${resolvedPath}.tsx`,
+      path.join(resolvedPath, "index.ts"),
+      path.join(resolvedPath, "index.tsx"),
+    ];
+ 
+    for (const candidate of candidates) {
+      const parsed = parsedFiles.find((f) => f.filePath === candidate);
+      if (parsed) {
+        return path.relative(workspaceRoot, candidate).replace(/\\/g, "/");
+      }
+    }
+ 
+    return null;
+  }
+ 
+  /**
+   * Seed progress nodes from config (Phase 5.2)
+   */
+  private seedProgressNodes(projectId: string): CypherStatement[] {
+    const statements: CypherStatement[] = [];
+ 
+    // Skip if no progress config
+    Eif (!this.memgraph || !this.memgraph.isConnected()) {
+      return statements;
+    }
+ 
+    // This would normally read from config.progress
+    // For MVP, create sample feature nodes
+    const features = [
+      {
+        id: "phase-1",
+        name: "Code Graph MVP",
+        status: "completed",
+        priority: "high",
+      },
+      {
+        id: "phase-2",
+        name: "Architecture Validation",
+        status: "completed",
+        priority: "high",
+      },
+      {
+        id: "phase-3",
+        name: "Test Intelligence",
+        status: "completed",
+        priority: "high",
+      },
+      {
+        id: "phase-4",
+        name: "MCP Tools",
+        status: "completed",
+        priority: "high",
+      },
+      {
+        id: "phase-5",
+        name: "Progress Tracking",
+        status: "in-progress",
+        priority: "medium",
+      },
+    ];
+ 
+    for (const feature of features) {
+      statements.push({
+        query: `
+          MERGE (f:FEATURE {id: $id})
+          ON CREATE SET
+            f.name = $name,
+            f.status = $status,
+            f.priority = $priority,
+            f.projectId = $projectId,
+            f.createdAt = timestamp()
+          ON MATCH DO NOTHING
+        `,
+        params: {
+          id: `${projectId}:feature:${feature.id}`,
+          name: feature.name,
+          status: feature.status,
+          priority: feature.priority,
+          projectId,
+        },
+      });
+    }
+ 
+    return statements;
+  }
+ 
+  /**
+   * Get current graph statistics
+   */
+  getStatistics(): GraphIndexManager["getStatistics"] {
+    return () => this.index.getStatistics();
+  }
+ 
+  /**
+   * Export graph snapshot
+   */
+  exportSnapshot(outputPath: string): void {
+    const snapshot = {
+      timestamp: new Date().toISOString(),
+      statistics: this.index.getStatistics(),
+      cacheStats: this.cache.getStats(),
+    };
+    fs.writeFileSync(outputPath, JSON.stringify(snapshot, null, 2));
+  }
+}
+ 
+export default GraphOrchestrator;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/ppr.ts.html b/coverage/lcov-report/src/graph/ppr.ts.html new file mode 100644 index 0000000..9497215 --- /dev/null +++ b/coverage/lcov-report/src/graph/ppr.ts.html @@ -0,0 +1,913 @@ + + + + + + Code coverage report for src/graph/ppr.ts + + + + + + + + + +
+
+

All files / src/graph ppr.ts

+
+ +
+ 97.16% + Statements + 103/106 +
+ + +
+ 65.42% + Branches + 70/107 +
+ + +
+ 100% + Functions + 7/7 +
+ + +
+ 100% + Lines + 93/93 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +23x +23x +  +20x +23x +23x +  +23x +20x +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +20x +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +19x +10x +  +  +9x +9x +9x +42x +42x +42x +42x +  +  +  +  +  +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +9x +9x +9x +9x +3x +3x +3x +3x +3x +  +  +  +9x +9x +9x +42x +42x +42x +42x +42x +  +  +  +  +  +  +  +  +  +35x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +11x +11x +  +11x +23x +23x +23x +  +23x +23x +  +23x +23x +  +23x +10x +  +  +  +  +  +23x +23x +  +  +  +  +  +  +23x +23x +  +  +11x +11x +1x +  +  +  +11x +11x +11x +11x +11x +34x +  +  +11x +11x +34x +  +11x +11x +12x +23x +23x +  +  +  +11x +180x +180x +575x +575x +575x +395x +395x +2245x +395x +  +575x +575x +  +180x +  +  +180x +  +34x +  +  +  +  +34x +  +  +  +  +  +  +  +  +23x +  +  + 
/**
+ * @file graph/ppr
+ * @description Personalized PageRank scoring utilities for graph-based relevance ranking.
+ * @remarks Used by context-pack style retrieval pipelines to prioritize connected symbols.
+ */
+ 
+import type MemgraphClient from "./client.js";
+ 
+export interface PPROptions {
+  seedIds: string[];
+  edgeWeights?: Record<string, number>;
+  damping?: number;
+  iterations?: number;
+  maxResults?: number;
+  projectId: string;
+}
+ 
+export interface PPRResult {
+  nodeId: string;
+  score: number;
+  type: string;
+  filePath: string;
+  name: string;
+  pprMode?: "mage_pagerank" | "js_ppr";
+}
+ 
+const DEFAULT_EDGE_WEIGHTS: Record<string, number> = {
+  CALLS: 0.9,
+  IMPORTS: 0.7,
+  CONTAINS: 0.5,
+  TESTS: 0.4,
+  DEFINED_IN: 0.6,
+  INVOLVES: 0.3,
+  APPLIES_TO: 0.4,
+};
+ 
+/**
+ * PPR via MAGE pagerank + Cypher seed expansion.
+ *
+ * Strategy:
+ *  1. Fetch Memgraph-native pagerank prestige scores via CALL pagerank.get()
+ *  2. Expand seed nodes up to 3 hops via Cypher — no full edge download
+ *  3. score = prestige*(1-damping) + proximity_boost*damping
+ *
+ * Falls back to JS power-iteration when MAGE is unavailable or graph is empty.
+ */
+export async function runPPR(opts: PPROptions, client: MemgraphClient): Promise<PPRResult[]> {
+  const seedIds = [...new Set((opts.seedIds || []).filter(Boolean))];
+  if (!seedIds.length) return [];
+ 
+  const maxResults = Math.max(1, Math.min(opts.maxResults || 50, 500));
+  const damping = Number.isFinite(opts.damping) ? Number(opts.damping) : 0.85;
+  const iterations = Math.max(1, Math.min(opts.iterations || 20, 100));
+ 
+  const mageResult = await tryMagePPR(opts, client, seedIds, maxResults, damping);
+  if (mageResult) return mageResult;
+ 
+  return runJsPPR(opts, client, seedIds, maxResults, damping, iterations);
+}
+ 
+// ---------------------------------------------------------------------------
+// MAGE path
+// ---------------------------------------------------------------------------
+async function tryMagePPR(
+  opts: PPROptions,
+  client: MemgraphClient,
+  seedIds: string[],
+  maxResults: number,
+  damping: number,
+): Promise<PPRResult[] | null> {
+  try {
+    // 1. Global pagerank on the project subgraph (Memgraph-native, scales to 1M+ nodes)
+    const pagerankRes = await client.executeCypher(
+      `CALL pagerank.get()
+       YIELD node, rank
+       WHERE node.projectId = $projectId
+         AND (node:FILE OR node:FUNCTION OR node:CLASS)
+       RETURN toString(node.id) AS nodeId,
+              toFloat(rank) AS rank,
+              labels(node)[0] AS type,
+              coalesce(node.path, node.filePath, '') AS filePath,
+              coalesce(node.name, node.id) AS name`,
+      { projectId: opts.projectId },
+    );
+ 
+    if (pagerankRes.error || !Array.isArray(pagerankRes.data) || pagerankRes.data.length === 0) {
+      return null;
+    }
+ 
+    const prestige = new Map<string, number>();
+    const nodeMeta = new Map<string, { type: string; filePath: string; name: string }>();
+    for (const row of pagerankRes.data) {
+      const id = String(row.nodeId || "");
+      Iif (!id) continue;
+      prestige.set(id, Number(row.rank || 0));
+      nodeMeta.set(id, {
+        type: String(row.type || "UNKNOWN"),
+        filePath: String(row.filePath || ""),
+        name: String(row.name || id),
+      });
+    }
+ 
+    // 2. Seed proximity via variable-length Cypher path (1–3 hops)
+    const proximityRes = await client.executeCypher(
+      `UNWIND $seedIds AS seedId
+       MATCH (seed {id: seedId, projectId: $projectId})
+       MATCH p = (seed)-[*1..3]-(neighbor)
+       WHERE neighbor.projectId = $projectId
+         AND (neighbor:FILE OR neighbor:FUNCTION OR neighbor:CLASS)
+       RETURN DISTINCT toString(neighbor.id) AS nodeId,
+                        min(length(p)) AS hops`,
+      { seedIds, projectId: opts.projectId },
+    );
+ 
+    // hop → proximity score: 1=1.0, 2=0.6, 3=0.3
+    const hopScore: Record<number, number> = { 1: 1.0, 2: 0.6, 3: 0.3 };
+    const proximity = new Map<string, number>();
+    for (const sid of seedIds) proximity.set(sid, 2.0); // seeds get highest boost
+    for (const row of proximityRes.data || []) {
+      const id = String(row.nodeId || "");
+      Iif (!id) continue;
+      const current = proximity.get(id) ?? 0;
+      const h = Number(row.hops || 3);
+      proximity.set(id, Math.max(current, hopScore[h] ?? 0.1));
+    }
+ 
+    // 3. Combine: final = prestige*(1−damping) + proximity*damping
+    const scores: PPRResult[] = [];
+    const allIds = new Set([...prestige.keys(), ...proximity.keys()]);
+    for (const nodeId of allIds) {
+      const p = prestige.get(nodeId) ?? 0;
+      const prox = proximity.get(nodeId) ?? 0;
+      const score = p * (1 - damping) + prox * damping;
+      const meta = nodeMeta.get(nodeId);
+      scores.push({
+        nodeId,
+        score: Number(score.toFixed(6)),
+        type: meta?.type ?? "UNKNOWN",
+        filePath: meta?.filePath ?? "",
+        name: meta?.name ?? nodeId,
+        pprMode: "mage_pagerank",
+      });
+    }
+ 
+    return scores.sort((a, b) => b.score - a.score).slice(0, maxResults);
+  } catch {
+    // MAGE not available — fall through
+    return null;
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// JS power-iteration fallback (original, preserved for compatibility)
+// ---------------------------------------------------------------------------
+async function runJsPPR(
+  opts: PPROptions,
+  client: MemgraphClient,
+  seedIds: string[],
+  maxResults: number,
+  damping: number,
+  iterations: number,
+): Promise<PPRResult[]> {
+  const edgeWeights = { ...DEFAULT_EDGE_WEIGHTS, ...(opts.edgeWeights || {}) };
+ 
+  const edgeResult = await client.executeCypher(
+    `MATCH (a)-[r]->(b)
+     WHERE a.projectId = $projectId AND b.projectId = $projectId
+     RETURN a.id AS fromId,
+            b.id AS toId,
+            labels(a)[0] AS fromType,
+            labels(b)[0] AS toType,
+            type(r) AS relType,
+            coalesce(a.path, a.filePath, '') AS fromPath,
+            coalesce(b.path, b.filePath, '') AS toPath,
+            coalesce(a.name, a.id) AS fromName,
+            coalesce(b.name, b.id) AS toName
+     LIMIT 20000`,
+    { projectId: opts.projectId },
+  );
+ 
+  const nodes = new Set<string>(seedIds);
+  const nodeMeta = new Map<string, { type: string; filePath: string; name: string }>();
+  const outgoing = new Map<string, Array<{ to: string; weight: number }>>();
+ 
+  for (const row of edgeResult.data || []) {
+    const fromId = String(row.fromId || "");
+    const toId = String(row.toId || "");
+    Iif (!fromId || !toId) continue;
+ 
+    const relType = String(row.relType || "");
+    const weight = Number(edgeWeights[relType] || 0.2);
+ 
+    nodes.add(fromId);
+    nodes.add(toId);
+ 
+    if (!nodeMeta.has(fromId)) {
+      nodeMeta.set(fromId, {
+        type: String(row.fromType || "UNKNOWN"),
+        filePath: String(row.fromPath || ""),
+        name: String(row.fromName || fromId),
+      });
+    }
+    Eif (!nodeMeta.has(toId)) {
+      nodeMeta.set(toId, {
+        type: String(row.toType || "UNKNOWN"),
+        filePath: String(row.toPath || ""),
+        name: String(row.toName || toId),
+      });
+    }
+ 
+    if (!outgoing.has(fromId)) outgoing.set(fromId, []);
+    outgoing.get(fromId)!.push({ to: toId, weight });
+  }
+ 
+  for (const seed of seedIds) {
+    if (!nodeMeta.has(seed)) {
+      nodeMeta.set(seed, { type: "UNKNOWN", filePath: "", name: seed });
+    }
+  }
+ 
+  const nodeList = [...nodes];
+  const nodeCount = nodeList.length || 1;
+  const seedWeight = 1 / seedIds.length;
+  const personalization = new Map<string, number>();
+  for (const nodeId of nodeList) {
+    personalization.set(nodeId, seedIds.includes(nodeId) ? seedWeight : 0);
+  }
+ 
+  let rank = new Map<string, number>();
+  const uniform = 1 / nodeCount;
+  for (const nodeId of nodeList) rank.set(nodeId, uniform);
+ 
+  const incoming = new Map<string, Array<{ from: string; weight: number }>>();
+  for (const [from, edges] of outgoing.entries()) {
+    for (const edge of edges) {
+      Eif (!incoming.has(edge.to)) incoming.set(edge.to, []);
+      incoming.get(edge.to)!.push({ from, weight: edge.weight });
+    }
+  }
+ 
+  for (let i = 0; i < iterations; i += 1) {
+    const next = new Map<string, number>();
+    for (const nodeId of nodeList) {
+      const inEdges = incoming.get(nodeId) || [];
+      let propagated = 0;
+      for (const edge of inEdges) {
+        const fromRank = rank.get(edge.from) || 0;
+        const fromOutgoing = outgoing.get(edge.from) || [];
+        const sumWeights = fromOutgoing.reduce((s, item) => s + item.weight, 0);
+        Eif (sumWeights > 0) propagated += (fromRank * edge.weight) / sumWeights;
+      }
+      const p = personalization.get(nodeId) || 0;
+      next.set(nodeId, (1 - damping) * p + damping * propagated);
+    }
+    rank = next;
+  }
+ 
+  return nodeList
+    .map((nodeId) => {
+      const meta = nodeMeta.get(nodeId) || {
+        type: "UNKNOWN",
+        filePath: "",
+        name: nodeId,
+      };
+      return {
+        nodeId,
+        score: Number((rank.get(nodeId) || 0).toFixed(6)),
+        type: meta.type,
+        filePath: meta.filePath,
+        name: meta.name,
+        pprMode: "js_ppr" as const,
+      };
+    })
+    .sort((a, b) => b.score - a.score)
+    .slice(0, maxResults);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/sync-state.ts.html b/coverage/lcov-report/src/graph/sync-state.ts.html new file mode 100644 index 0000000..e96b3ac --- /dev/null +++ b/coverage/lcov-report/src/graph/sync-state.ts.html @@ -0,0 +1,763 @@ + + + + + + Code coverage report for src/graph/sync-state.ts + + + + + + + + + +
+
+

All files / src/graph sync-state.ts

+
+ +
+ 0% + Statements + 0/63 +
+ + +
+ 0% + Branches + 0/19 +
+ + +
+ 0% + Functions + 0/22 +
+ + +
+ 0% + Lines + 0/60 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file graph/sync-state
+ * @description Tracks cross-system synchronization health and drift indicators.
+ * @remarks Provides state-machine style diagnostics for graph, index, and embedding readiness.
+ */
+ 
+import * as env from "../env.js";
+import { logger } from "../utils/logger.js";
+ 
+export type SyncState = "uninitialized" | "synced" | "drifted" | "rebuilding";
+ 
+export interface SystemHealth {
+  memgraph: SyncState;
+  index: SyncState;
+  qdrant: SyncState;
+  embeddings: SyncState;
+}
+ 
+export class SyncStateManager {
+  private state: SystemHealth = {
+    memgraph: "uninitialized",
+    index: "uninitialized",
+    qdrant: "uninitialized",
+    embeddings: "uninitialized",
+  };
+ 
+  private stateHistory: Array<{ timestamp: number; state: SystemHealth }> = [];
+  // Phase 4.6: Use configurable history size limit
+  private maxHistorySize = env.LXRAG_STATE_HISTORY_MAX_SIZE;
+ 
+  constructor(private projectId: string) {
+    logger.error(`[SyncStateManager] Initialized for project ${projectId}`);
+  }
+ 
+  /**
+   * Update state of a specific system
+   */
+  setState(system: keyof SystemHealth, newState: SyncState): void {
+    const oldState = this.state[system];
+    if (oldState === newState) return;
+ 
+    this.state[system] = newState;
+    logger.error(`[SyncState:${this.projectId}] ${system}: ${oldState} → ${newState}`);
+ 
+    // Record history
+    this.recordHistory();
+  }
+ 
+  /**
+   * Get current state of a specific system
+   */
+  getSystemState(system: keyof SystemHealth): SyncState {
+    return this.state[system];
+  }
+ 
+  /**
+   * Get complete system health snapshot
+   */
+  getState(): SystemHealth {
+    return { ...this.state };
+  }
+ 
+  /**
+   * Check if system is healthy (all components synced)
+   */
+  isHealthy(): boolean {
+    return Object.values(this.state).every((s) => s === "synced");
+  }
+ 
+  /**
+   * Check if system is drifted
+   */
+  isDrifted(): boolean {
+    return Object.values(this.state).some((s) => s === "drifted");
+  }
+ 
+  /**
+   * Find first system that needs sync
+   */
+  needsSync(): keyof SystemHealth | null {
+    for (const [system, state] of Object.entries(this.state)) {
+      if (state !== "synced" && state !== "rebuilding") {
+        return system as keyof SystemHealth;
+      }
+    }
+    return null;
+  }
+ 
+  /**
+   * Get all systems that need attention
+   */
+  getDriftedSystems(): (keyof SystemHealth)[] {
+    return Object.entries(this.state)
+      .filter(([_, state]) => state === "drifted")
+      .map(([system, _]) => system as keyof SystemHealth);
+  }
+ 
+  /**
+   * Mark all systems as rebuilding
+   */
+  startRebuild(): void {
+    logger.error(`[SyncState:${this.projectId}] Starting rebuild - all systems rebuilding`);
+    this.setState("memgraph", "rebuilding");
+    this.setState("index", "rebuilding");
+    this.setState("qdrant", "rebuilding");
+    this.setState("embeddings", "rebuilding");
+  }
+ 
+  /**
+   * Mark all systems as synced after rebuild
+   */
+  completeRebuild(): void {
+    logger.error(`[SyncState:${this.projectId}] Rebuild complete - all systems synced`);
+    this.setState("memgraph", "synced");
+    this.setState("index", "synced");
+    this.setState("qdrant", "synced");
+    this.setState("embeddings", "synced");
+  }
+ 
+  /**
+   * Mark incremental build - index and embeddings need sync
+   */
+  startIncrementalRebuild(): void {
+    logger.error(`[SyncState:${this.projectId}] Starting incremental rebuild`);
+    this.setState("index", "rebuilding");
+    this.setState("embeddings", "rebuilding");
+  }
+ 
+  /**
+   * Complete incremental build
+   */
+  completeIncrementalRebuild(): void {
+    logger.error(`[SyncState:${this.projectId}] Incremental rebuild complete`);
+    this.setState("index", "synced");
+    this.setState("embeddings", "synced");
+  }
+ 
+  /**
+   * Record state snapshot to history
+   */
+  private recordHistory(): void {
+    this.stateHistory.push({
+      timestamp: Date.now(),
+      state: { ...this.state },
+    });
+ 
+    // Keep history size bounded
+    if (this.stateHistory.length > this.maxHistorySize) {
+      this.stateHistory.shift();
+    }
+  }
+ 
+  /**
+   * Get state history
+   */
+  getHistory(limit: number = 10): Array<{ timestamp: number; state: SystemHealth }> {
+    return this.stateHistory.slice(-limit);
+  }
+ 
+  /**
+   * Get diagnostics summary
+   */
+  getDiagnostics(): {
+    healthy: boolean;
+    drifted: boolean;
+    needsSync: keyof SystemHealth | null;
+    state: SystemHealth;
+    driftedSystems: (keyof SystemHealth)[];
+    recommendations: string[];
+  } {
+    const recommendations: string[] = [];
+ 
+    if (!this.isHealthy()) {
+      const drifted = this.getDriftedSystems();
+      if (drifted.length > 0) {
+        recommendations.push(
+          `Systems are drifted: ${drifted.join(", ")}. Run graph_rebuild to resync.`,
+        );
+      }
+ 
+      const needsSync = this.needsSync();
+      if (needsSync) {
+        recommendations.push(`${needsSync} needs sync. Run graph_rebuild to synchronize.`);
+      }
+    }
+ 
+    const rebuilding = Object.entries(this.state)
+      .filter(([_, s]) => s === "rebuilding")
+      .map(([k]) => k as keyof SystemHealth);
+ 
+    if (rebuilding.length > 0) {
+      recommendations.push(
+        `Systems are rebuilding: ${rebuilding.join(", ")}. Wait for rebuild to complete.`,
+      );
+    }
+ 
+    if (this.isHealthy()) {
+      recommendations.push("System is healthy - all components synchronized.");
+    }
+ 
+    return {
+      healthy: this.isHealthy(),
+      drifted: this.isDrifted(),
+      needsSync: this.needsSync(),
+      state: this.getState(),
+      driftedSystems: this.getDriftedSystems(),
+      recommendations,
+    };
+  }
+ 
+  /**
+   * Reset to initial state
+   */
+  reset(): void {
+    logger.error(`[SyncState:${this.projectId}] Resetting sync state`);
+    this.state = {
+      memgraph: "uninitialized",
+      index: "uninitialized",
+      qdrant: "uninitialized",
+      embeddings: "uninitialized",
+    };
+    this.stateHistory = [];
+  }
+}
+ 
+export default SyncStateManager;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/types.ts.html b/coverage/lcov-report/src/graph/types.ts.html new file mode 100644 index 0000000..2b8cfe9 --- /dev/null +++ b/coverage/lcov-report/src/graph/types.ts.html @@ -0,0 +1,112 @@ + + + + + + Code coverage report for src/graph/types.ts + + + + + + + + + +
+
+

All files / src/graph types.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10  +  +  +  +  +  +  +  +  + 
/**
+ * @file graph/types
+ * @description Shared low-level graph write/query type contracts.
+ */
+ 
+export interface CypherStatement {
+  query: string;
+  params: Record<string, any>;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/graph/watcher.ts.html b/coverage/lcov-report/src/graph/watcher.ts.html new file mode 100644 index 0000000..86aba6e --- /dev/null +++ b/coverage/lcov-report/src/graph/watcher.ts.html @@ -0,0 +1,511 @@ + + + + + + Code coverage report for src/graph/watcher.ts + + + + + + + + + +
+
+

All files / src/graph watcher.ts

+
+ +
+ 75.51% + Statements + 37/49 +
+ + +
+ 62.5% + Branches + 15/24 +
+ + +
+ 66.66% + Functions + 8/12 +
+ + +
+ 75.51% + Lines + 37/49 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +2x +  +  +2x +2x +  +  +  +3x +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +2x +  +  +  +  +2x +2x +2x +  +  +  +5x +5x +  +5x +2x +  +  +5x +5x +3x +3x +  +  +  +  +4x +1x +1x +  +1x +  +  +3x +3x +  +3x +3x +  +3x +3x +  +  +  +  +  +  +3x +3x +1x +1x +1x +1x +  +  +2x +  +  +  +  +  +  + 
/**
+ * @file graph/watcher
+ * @description Filesystem watcher for incremental rebuild triggering and change batching.
+ * @remarks Debounces events and emits normalized change sets per project context.
+ */
+ 
+import chokidar from "chokidar";
+ 
+export interface WatcherOptions {
+  workspaceRoot: string;
+  sourceDir: string;
+  projectId: string;
+  debounceMs?: number;
+  ignorePatterns?: string[];
+}
+ 
+export type WatcherState = "idle" | "detecting" | "debouncing" | "rebuilding";
+ 
+export type WatchBatchHandler = (payload: {
+  projectId: string;
+  workspaceRoot: string;
+  sourceDir: string;
+  changedFiles: string[];
+}) => Promise<void>;
+ 
+export class FileWatcher {
+  private watcher?: ReturnType<typeof chokidar.watch>;
+  private pending = new Set<string>();
+  private timer?: NodeJS.Timeout;
+  private processing = false;
+  private stateValue: WatcherState = "idle";
+ 
+  constructor(
+    private opts: WatcherOptions,
+    private onBatch: WatchBatchHandler,
+  ) {}
+ 
+  get pendingChanges(): number {
+    return this.pending.size;
+  }
+ 
+  get state(): WatcherState {
+    return this.stateValue;
+  }
+ 
+  start(): void {
+    if (this.watcher) {
+      return;
+    }
+ 
+    const ignored = [
+      "**/node_modules/**",
+      "**/dist/**",
+      "**/.git/**",
+      "**/.lxrag/**",
+      ...(this.opts.ignorePatterns || []),
+    ];
+ 
+    this.watcher = chokidar.watch(this.opts.sourceDir, {
+      ignored,
+      ignoreInitial: true,
+      persistent: true,
+      awaitWriteFinish: {
+        stabilityThreshold: 150,
+        pollInterval: 50,
+      },
+    });
+ 
+    this.watcher
+      .on("add", (filePath: string) => this.queue(filePath))
+      .on("change", (filePath: string) => this.queue(filePath))
+      .on("unlink", (filePath: string) => this.queue(filePath));
+  }
+ 
+  async stop(): Promise<void> {
+    Iif (this.timer) {
+      clearTimeout(this.timer);
+      this.timer = undefined;
+    }
+ 
+    Iif (this.watcher) {
+      await this.watcher.close();
+      this.watcher = undefined;
+    }
+ 
+    this.pending.clear();
+    this.processing = false;
+    this.stateValue = "idle";
+  }
+ 
+  private queue(filePath: string): void {
+    this.pending.add(filePath);
+    this.stateValue = "detecting";
+ 
+    if (this.timer) {
+      clearTimeout(this.timer);
+    }
+ 
+    this.stateValue = "debouncing";
+    this.timer = setTimeout(() => {
+      this.timer = undefined;
+      void this.flush();
+    }, this.opts.debounceMs ?? 500);
+  }
+ 
+  private async flush(): Promise<void> {
+    if (this.processing || this.pending.size === 0) {
+      Eif (!this.processing && this.pending.size === 0) {
+        this.stateValue = "idle";
+      }
+      return;
+    }
+ 
+    this.processing = true;
+    this.stateValue = "rebuilding";
+ 
+    const changedFiles = [...this.pending];
+    this.pending.clear();
+ 
+    try {
+      await this.onBatch({
+        projectId: this.opts.projectId,
+        workspaceRoot: this.opts.workspaceRoot,
+        sourceDir: this.opts.sourceDir,
+        changedFiles,
+      });
+    } finally {
+      this.processing = false;
+      if (this.pending.size > 0) {
+        this.stateValue = "debouncing";
+        this.timer = setTimeout(() => {
+          this.timer = undefined;
+          void this.flush();
+        }, this.opts.debounceMs ?? 500);
+      } else {
+        this.stateValue = "idle";
+      }
+    }
+  }
+}
+ 
+export default FileWatcher;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/index.html b/coverage/lcov-report/src/index.html new file mode 100644 index 0000000..e70e10b --- /dev/null +++ b/coverage/lcov-report/src/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 29.16% + Statements + 42/144 +
+ + +
+ 55.12% + Branches + 43/78 +
+ + +
+ 17.39% + Functions + 4/23 +
+ + +
+ 29.37% + Lines + 42/143 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
config.ts +
+
0%0/130%0/60%0/20%0/13
env.ts +
+
100%39/3985.41%41/48100%2/2100%39/39
request-context.ts +
+
100%3/3100%2/2100%2/2100%3/3
server.ts +
+
0%0/890%0/220%0/170%0/88
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/parsers/docs-parser.ts.html b/coverage/lcov-report/src/parsers/docs-parser.ts.html new file mode 100644 index 0000000..47a1e79 --- /dev/null +++ b/coverage/lcov-report/src/parsers/docs-parser.ts.html @@ -0,0 +1,1249 @@ + + + + + + Code coverage report for src/parsers/docs-parser.ts + + + + + + + + + +
+
+

All files / src/parsers docs-parser.ts

+
+ +
+ 98.05% + Statements + 151/154 +
+ + +
+ 93.61% + Branches + 88/94 +
+ + +
+ 100% + Functions + 16/16 +
+ + +
+ 99.3% + Lines + 142/143 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +43x +43x +  +  +  +  +  +  +  +  +  +64x +  +64x +  +64x +64x +64x +64x +358x +  +64x +  +  +  +  +  +  +81x +81x +  +81x +61x +58x +56x +  +  +  +  +5x +51x +  +48x +  +  +  +  +  +  +  +363x +363x +  +363x +550x +550x +549x +  +  +363x +  +  +  +  +  +  +  +  +  +  +64x +64x +64x +64x +64x +64x +64x +  +64x +414x +414x +357x +  +  +  +414x +414x +  +  +64x +1973x +1973x +  +  +1973x +1973x +96x +48x +48x +48x +48x +48x +  +96x +96x +  +  +1877x +92x +92x +  +  +  +1785x +1785x +349x +349x +  +  +349x +348x +348x +348x +348x +348x +  +  +  +  +1437x +1429x +1429x +  +1x +1x +1x +1x +1x +1x +  +1428x +1x +1x +1x +1x +1x +1x +  +  +  +1435x +  +  +  +64x +  +  +64x +1x +  +  +64x +  +  +  +  +  +  +  +  +  +  +  +358x +  +358x +  +358x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +358x +358x +358x +358x +358x +358x +358x +  +358x +1622x +1622x +  +1622x +48x +48x +48x +48x +48x +48x +  +  +1574x +140x +48x +  +  +  +  +48x +48x +48x +  +92x +  +  +  +  +358x +  +  +  +358x +  +  +  +358x +  +358x +  +358x +32x +  +358x +  +  +  +358x +  +  +  +  +  +64x +64x +  +13x +  +  +  +  +  +  +  +  +  +  +  +14x +14x +  +  +  +  +  +  +  +  +  +14x +25x +  +25x +25x +  +  +  +  +25x +111x +  +111x +  +111x +  +  +20x +  +20x +  +  +  +  +  +  +  +20x +11x +  +91x +34x +  +  +  +  +14x +14x +  + 
/**
+ * Docs Parser
+ * Parses markdown files (README, ADRs, docs/) into structured sections.
+ * Pure: no I/O, no external dependencies beyond node:crypto and node:path.
+ */
+ 
+import * as crypto from "node:crypto";
+import * as fs from "node:fs";
+import * as path from "node:path";
+ 
+// ─── Public types ─────────────────────────────────────────────────────────────
+ 
+export type DocKind = "readme" | "adr" | "changelog" | "guide" | "architecture" | "other";
+ 
+export interface CodeFence {
+  /** Language tag (may be empty string) */
+  lang: string;
+  /** Raw code inside the fence */
+  code: string;
+  /** 1-based start line of the opening ``` within the document */
+  startLine: number;
+}
+ 
+export interface DocLink {
+  text: string;
+  href: string;
+}
+ 
+export interface ParsedSection {
+  /** 0-based position within the document */
+  index: number;
+  /** Heading text without leading `#` marks */
+  heading: string;
+  /** Heading depth 1 = H1, 2 = H2, 3 = H3 (deeper headings are grouped into the H3 bucket) */
+  level: 1 | 2 | 3;
+  /** All body text below the heading, down to the next heading of equal or higher level */
+  content: string;
+  /** 1-based line number of the heading line */
+  startLine: number;
+  wordCount: number;
+  /** All names enclosed in backticks in this section's content */
+  backtickRefs: string[];
+  codeFences: CodeFence[];
+  links: DocLink[];
+}
+ 
+export interface ParsedDoc {
+  filePath: string;
+  relativePath: string;
+  title: string;
+  kind: DocKind;
+  /** SHA-256 hex digest of raw file content */
+  hash: string;
+  wordCount: number;
+  sections: ParsedSection[];
+}
+ 
+// ─── DocsParser ───────────────────────────────────────────────────────────────
+ 
+export class DocsParser {
+  // ── Public API ──────────────────────────────────────────────────────────────
+ 
+  /**
+   * Parse a markdown file from disk.
+   * @param filePath    Absolute path to the .md file.
+   * @param workspaceRoot  Used to derive relativePath only.
+   */
+  parseFile(filePath: string, workspaceRoot: string): ParsedDoc {
+    const content = fs.readFileSync(filePath, "utf-8");
+    return this.parseContent(content, filePath, workspaceRoot);
+  }
+ 
+  /**
+   * Parse markdown content directly (no I/O — fully unit-testable).
+   * @param content       Raw file content.
+   * @param filePath      Absolute or arbitrary path (used for id and kind inference).
+   * @param workspaceRoot Used to compute relativePath.
+   */
+  parseContent(content: string, filePath: string, workspaceRoot: string): ParsedDoc {
+    const relativePath = path.relative(workspaceRoot, filePath).replace(/\\/g, "/");
+ 
+    const hash = crypto.createHash("sha256").update(content, "utf-8").digest("hex");
+ 
+    const lines = content.split("\n");
+    const sections = this.splitSections(lines);
+    const title = this.inferTitle(sections, relativePath);
+    const kind = this.inferKind(relativePath);
+    const wordCount = sections.reduce((sum, s) => sum + s.wordCount, 0);
+ 
+    return { filePath, relativePath, title, kind, hash, wordCount, sections };
+  }
+ 
+  /**
+   * Classify a markdown file by its relative path.
+   */
+  inferKind(relativePath: string): DocKind {
+    const lower = relativePath.toLowerCase().replace(/\\/g, "/");
+    const basename = path.basename(lower);
+ 
+    if (/readme/i.test(basename)) return "readme";
+    if (/^changelog|^history/.test(basename)) return "changelog";
+    if (/^architecture|^arch\./.test(basename)) return "architecture";
+    if (
+      /adr[-_\s]?\d+/.test(lower) ||
+      /(?:^|\/)decisions?\//i.test(lower) ||
+      /(?:^|\/)adr\//i.test(lower)
+    )
+      return "adr";
+    if (/\/docs\//i.test(`/${lower}`) || lower.startsWith("docs/")) return "guide";
+ 
+    return "other";
+  }
+ 
+  /**
+   * Extract all `symbol` backtick-quoted names from a text string.
+   * Returns deduplicated names, non-empty, trimmed.
+   */
+  extractBacktickRefs(text: string): string[] {
+    const seen = new Set<string>();
+    const pattern = /`([^`\n]+)`/g;
+    let match: RegExpExecArray | null;
+    while ((match = pattern.exec(text)) !== null) {
+      const ref = match[1].trim();
+      if (ref.length > 0 && ref.length <= 120) {
+        seen.add(ref);
+      }
+    }
+    return Array.from(seen);
+  }
+ 
+  // ── Section splitting ────────────────────────────────────────────────────────
+ 
+  /**
+   * Split document lines into sections at H1/H2/H3 boundaries.
+   * Lines before the first heading are grouped into an implicit section
+   * with heading = "" and level = 1.
+   */
+  private splitSections(lines: string[]): ParsedSection[] {
+    const sections: ParsedSection[] = [];
+    let currentHeading = "";
+    let currentLevel: 1 | 2 | 3 = 1;
+    let currentStartLine = 1; // 1-based
+    let currentBodyLines: string[] = [];
+    let inCodeFence = false;
+    let fenceMarker = "";
+ 
+    const flush = (nextStartLine: number): void => {
+      const body = currentBodyLines.join("\n");
+      if (currentHeading.length > 0 || body.trim().length > 0) {
+        sections.push(
+          this.buildSection(sections.length, currentHeading, currentLevel, currentStartLine, body),
+        );
+      }
+      currentBodyLines = [];
+      currentStartLine = nextStartLine;
+    };
+ 
+    for (let i = 0; i < lines.length; i++) {
+      const line = lines[i];
+      const lineNumber = i + 1; // 1-based
+ 
+      // Track code fence state (don't parse headings inside fences)
+      const fenceMatch = line.match(/^(`{3,}|~{3,})/);
+      if (fenceMatch) {
+        if (!inCodeFence) {
+          inCodeFence = true;
+          fenceMarker = fenceMatch[1][0].repeat(fenceMatch[1].length); // normalize
+        E} else if (line.startsWith(fenceMarker)) {
+          inCodeFence = false;
+          fenceMarker = "";
+        }
+        currentBodyLines.push(line);
+        continue;
+      }
+ 
+      if (inCodeFence) {
+        currentBodyLines.push(line);
+        continue;
+      }
+ 
+      // ATX heading detection
+      const headingMatch = line.match(/^(#{1,6})\s+(.*)/);
+      if (headingMatch) {
+        const depth = headingMatch[1].length;
+        const headingText = headingMatch[2].trim();
+ 
+        // Only split at H1-H3 (deeper headings become body content)
+        if (depth <= 3) {
+          flush(lineNumber);
+          currentHeading = headingText;
+          currentLevel = Math.min(depth, 3) as 1 | 2 | 3;
+          currentStartLine = lineNumber;
+          continue;
+        }
+      }
+ 
+      // Setext H1 / H2 detection
+      if (i > 0 && !inCodeFence) {
+        const prevLine = currentBodyLines[currentBodyLines.length - 1] ?? "";
+        if (/^={3,}\s*$/.test(line) && prevLine.trim().length > 0) {
+          // Previous line is the heading text — move it from body to heading
+          const headingText = currentBodyLines.pop()?.trim() ?? "";
+          flush(lineNumber - 1);
+          currentHeading = headingText;
+          currentLevel = 1;
+          currentStartLine = lineNumber - 1;
+          continue;
+        }
+        if (/^-{3,}\s*$/.test(line) && prevLine.trim().length > 0 && !prevLine.startsWith("#")) {
+          const headingText = currentBodyLines.pop()?.trim() ?? "";
+          flush(lineNumber - 1);
+          currentHeading = headingText;
+          currentLevel = 2;
+          currentStartLine = lineNumber - 1;
+          continue;
+        }
+      }
+ 
+      currentBodyLines.push(line);
+    }
+ 
+    // Flush final section
+    flush(lines.length + 1);
+ 
+    // Ensure at least one section for empty / heading-free documents
+    if (sections.length === 0) {
+      sections.push(this.buildSection(0, "", 1, 1, ""));
+    }
+ 
+    return sections;
+  }
+ 
+  // ── Section builder ─────────────────────────────────────────────────────────
+ 
+  private buildSection(
+    index: number,
+    heading: string,
+    level: 1 | 2 | 3,
+    startLine: number,
+    body: string,
+  ): ParsedSection {
+    const codeFences = this.extractCodeFences(body, startLine);
+    // Remove code fence content from body before extracting prose references
+    const proseBody = this.stripCodeFences(body);
+ 
+    return {
+      index,
+      heading,
+      level,
+      content: body,
+      startLine,
+      wordCount: this.countWords(heading + " " + body),
+      backtickRefs: this.extractBacktickRefs(proseBody + " " + heading),
+      codeFences,
+      links: this.extractLinks(proseBody),
+    };
+  }
+ 
+  // ── Extraction helpers ───────────────────────────────────────────────────────
+ 
+  private extractCodeFences(body: string, sectionStartLine: number): CodeFence[] {
+    const fences: CodeFence[] = [];
+    const lines = body.split("\n");
+    let inFence = false;
+    let fenceMarker = "";
+    let lang = "";
+    let fenceLines: string[] = [];
+    let fenceStart = 0;
+ 
+    for (let i = 0; i < lines.length; i++) {
+      const line = lines[i];
+      const openMatch = line.match(/^(`{3,}|~{3,})(\S*)/);
+ 
+      if (!inFence && openMatch) {
+        inFence = true;
+        fenceMarker = openMatch[1][0].repeat(openMatch[1].length);
+        lang = openMatch[2] ?? "";
+        fenceLines = [];
+        fenceStart = sectionStartLine + i;
+        continue;
+      }
+ 
+      if (inFence) {
+        if (line.startsWith(fenceMarker)) {
+          fences.push({
+            lang,
+            code: fenceLines.join("\n"),
+            startLine: fenceStart,
+          });
+          inFence = false;
+          fenceMarker = "";
+          fenceLines = [];
+        } else {
+          fenceLines.push(line);
+        }
+      }
+    }
+ 
+    return fences;
+  }
+ 
+  private stripCodeFences(body: string): string {
+    return body.replace(/^(`{3,}|~{3,})[\s\S]*?\1/gm, "");
+  }
+ 
+  private extractLinks(text: string): DocLink[] {
+    const links: DocLink[] = [];
+    // Markdown inline links: [text](href)
+    const pattern = /\[([^\]]+)\]\(([^)]+)\)/g;
+    let match: RegExpExecArray | null;
+    while ((match = pattern.exec(text)) !== null) {
+      links.push({ text: match[1].trim(), href: match[2].trim() });
+    }
+    return links;
+  }
+ 
+  private countWords(text: string): number {
+    return (text.match(/\S+/g) ?? []).length;
+  }
+ 
+  // ── Title / kind helpers ─────────────────────────────────────────────────────
+ 
+  private inferTitle(sections: ParsedSection[], relativePath: string): string {
+    const h1 = sections.find((s) => s.level === 1 && s.heading.length > 0);
+    if (h1) return h1.heading;
+    // Fall back to filename without extension
+    return path.basename(relativePath, path.extname(relativePath));
+  }
+}
+ 
+// ─── File walker (used by DocsEngine, exported for testing) ──────────────────
+ 
+/**
+ * Returns absolute paths to all markdown files within workspaceRoot
+ * that belong to conventional documentation locations.
+ * Excludes node_modules, dist, .git, .lxrag.
+ */
+export function findMarkdownFiles(workspaceRoot: string): string[] {
+  const results: string[] = [];
+  const excluded = new Set([
+    "node_modules",
+    "dist",
+    ".git",
+    ".lxrag",
+    ".next",
+    "build",
+    "coverage",
+  ]);
+ 
+  const walk = (dir: string, depth: number): void => {
+    Iif (depth > 6) return; // Don't recurse infinitely
+    let entries: fs.Dirent[];
+    try {
+      entries = fs.readdirSync(dir, { withFileTypes: true });
+    } catch {
+      return;
+    }
+ 
+    for (const entry of entries) {
+      Iif (excluded.has(entry.name)) continue;
+ 
+      const fullPath = path.join(dir, entry.name);
+ 
+      if (entry.isDirectory()) {
+        // Only recurse into known doc directories at any depth,
+        // or at root depth 0 (to pick up top-level README/CHANGELOG)
+        const nameLower = entry.name.toLowerCase();
+        const isDocDir =
+          nameLower === "docs" ||
+          nameLower === "doc" ||
+          nameLower === "adr" ||
+          nameLower === "adrs" ||
+          nameLower === "decisions" ||
+          nameLower === "rfcs" ||
+          nameLower === "wiki" ||
+          nameLower === ".github";
+        if (depth === 0 || isDocDir) {
+          walk(fullPath, depth + 1);
+        }
+      } else if (entry.isFile() && /\.(md|mdx)$/i.test(entry.name)) {
+        results.push(fullPath);
+      }
+    }
+  };
+ 
+  walk(workspaceRoot, 0);
+  return results;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/parsers/index.html b/coverage/lcov-report/src/parsers/index.html new file mode 100644 index 0000000..c3952c8 --- /dev/null +++ b/coverage/lcov-report/src/parsers/index.html @@ -0,0 +1,206 @@ + + + + + + Code coverage report for src/parsers + + + + + + + + + +
+
+

All files src/parsers

+
+ +
+ 61.81% + Statements + 463/749 +
+ + +
+ 46.35% + Branches + 191/412 +
+ + +
+ 72.47% + Functions + 79/109 +
+ + +
+ 64.13% + Lines + 440/686 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
docs-parser.ts +
+
98.05%151/15493.61%88/94100%16/1699.3%142/143
parser-interface.ts +
+
0%0/00%0/00%0/00%0/0
parser-registry.ts +
+
100%9/9100%4/4100%3/3100%9/9
regex-language-parsers.ts +
+
100%125/12598.24%56/57100%27/27100%123/123
tree-sitter-parser.ts +
+
21.95%36/1645.26%5/9523.8%5/2122.91%33/144
tree-sitter-typescript-parser.ts +
+
28.57%46/16112.63%12/9555.55%10/1828.88%39/135
typescript-parser.ts +
+
70.58%96/13638.8%26/6775%18/2471.21%94/132
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/parsers/parser-interface.ts.html b/coverage/lcov-report/src/parsers/parser-interface.ts.html new file mode 100644 index 0000000..c1a3e03 --- /dev/null +++ b/coverage/lcov-report/src/parsers/parser-interface.ts.html @@ -0,0 +1,151 @@ + + + + + + Code coverage report for src/parsers/parser-interface.ts + + + + + + + + + +
+
+

All files / src/parsers parser-interface.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
export interface ParsedSymbol {
+  type: "function" | "class" | "method" | "variable" | "interface" | "import";
+  name: string;
+  startLine: number;
+  endLine: number;
+  kind?: string;
+  scopePath?: string;
+  calls?: string[];
+  imports?: string[];
+}
+ 
+export interface ParseResult {
+  file: string;
+  language: string;
+  symbols: ParsedSymbol[];
+}
+ 
+export interface LanguageParser {
+  readonly language: string;
+  readonly extensions: string[];
+  parse(filePath: string, content: string): Promise<ParseResult>;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/parsers/parser-registry.ts.html b/coverage/lcov-report/src/parsers/parser-registry.ts.html new file mode 100644 index 0000000..85e9543 --- /dev/null +++ b/coverage/lcov-report/src/parsers/parser-registry.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/parsers/parser-registry.ts + + + + + + + + + +
+
+

All files / src/parsers parser-registry.ts

+
+ +
+ 100% + Statements + 9/9 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 9/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28  +  +  +  +127x +  +  +494x +495x +  +  +  +  +5x +5x +  +  +  +2x +2x +1x +  +1x +  +  +  +  + 
import * as path from "path";
+import type { LanguageParser, ParseResult } from "./parser-interface.js";
+ 
+export class ParserRegistry {
+  private parsers = new Map<string, LanguageParser>();
+ 
+  register(parser: LanguageParser): void {
+    for (const ext of parser.extensions) {
+      this.parsers.set(ext.toLowerCase(), parser);
+    }
+  }
+ 
+  getParserForFile(filePath: string): LanguageParser | null {
+    const ext = path.extname(filePath).toLowerCase();
+    return this.parsers.get(ext) || null;
+  }
+ 
+  async parse(filePath: string, content: string): Promise<ParseResult | null> {
+    const parser = this.getParserForFile(filePath);
+    if (!parser) {
+      return null;
+    }
+    return parser.parse(filePath, content);
+  }
+}
+ 
+export default ParserRegistry;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/parsers/regex-language-parsers.ts.html b/coverage/lcov-report/src/parsers/regex-language-parsers.ts.html new file mode 100644 index 0000000..a65ed76 --- /dev/null +++ b/coverage/lcov-report/src/parsers/regex-language-parsers.ts.html @@ -0,0 +1,1132 @@ + + + + + + Code coverage report for src/parsers/regex-language-parsers.ts + + + + + + + + + +
+
+

All files / src/parsers regex-language-parsers.ts

+
+ +
+ 100% + Statements + 125/125 +
+ + +
+ 98.24% + Branches + 56/57 +
+ + +
+ 100% + Functions + 27/27 +
+ + +
+ 100% + Lines + 123/123 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350  +  +  +  +  +  +  +  +38x +38x +  +  +  +  +  +38x +  +  +  +  +  +  +  +  +  +  +  +32x +32x +  +32x +123x +123x +1764x +42x +42x +1722x +45x +45x +30x +  +  +  +  +  +2x +  +  +  +9x +9x +  +9x +21x +21x +8x +  +13x +21x +3x +  +  +  +6x +  +  +  +  +124x +124x +  +  +9x +  +9x +38x +38x +3x +  +  +  +  +  +  +  +38x +38x +3x +  +  +  +  +  +  +  +  +9x +  +  +  +9x +  +9x +38x +38x +33x +  +  +5x +  +  +  +  +  +  +  +9x +  +  +  +9x +  +9x +38x +38x +34x +  +  +4x +  +  +  +  +  +  +  +9x +  +  +  +  +124x +124x +  +  +9x +  +9x +37x +37x +2x +  +  +  +  +  +  +  +37x +37x +1x +  +  +  +  +  +  +  +  +9x +  +  +  +9x +  +9x +37x +37x +33x +  +  +4x +  +  +  +  +  +  +  +9x +  +  +  +9x +  +9x +37x +37x +34x +  +  +3x +  +  +  +  +  +  +  +9x +  +  +  +  +124x +124x +  +  +9x +  +9x +44x +44x +41x +  +  +3x +  +  +  +  +  +  +  +9x +  +  +  +9x +  +9x +44x +44x +38x +  +  +6x +  +  +  +  +  +  +  +9x +  +  +  +9x +  +9x +44x +44x +39x +  +  +5x +  +  +  +  +  +  +  +9x +  +  +  +  +124x +124x +  +  +11x +  +11x +55x +55x +50x +  +  +5x +  +  +  +  +  +  +  +11x +  +  +  +11x +  +11x +  +55x +  +  +55x +47x +  +  +8x +  +  +  +  +  +  +  +11x +  +  +  +11x +11x +  +11x +  +55x +  +  +55x +49x +  +  +6x +  +  +  +  +  +  +  +11x +  +  + 
import * as path from "path";
+import type { LanguageParser, ParseResult, ParsedSymbol } from "./parser-interface.js";
+ 
+abstract class BaseRegexParser implements LanguageParser {
+  abstract readonly language: string;
+  abstract readonly extensions: string[];
+ 
+  async parse(filePath: string, content: string): Promise<ParseResult> {
+    const lines = content.split("\n");
+    const symbols: ParsedSymbol[] = [
+      ...this.extractImports(lines),
+      ...this.extractClasses(lines),
+      ...this.extractFunctions(lines),
+    ];
+ 
+    return {
+      file: path.basename(filePath),
+      language: this.language,
+      symbols,
+    };
+  }
+ 
+  protected abstract extractImports(lines: string[]): ParsedSymbol[];
+  protected abstract extractClasses(lines: string[]): ParsedSymbol[];
+  protected abstract extractFunctions(lines: string[]): ParsedSymbol[];
+ 
+  protected findBraceBlockEnd(lines: string[], startLineIndex: number): number {
+    let balance = 0;
+    let seenOpening = false;
+ 
+    for (let i = startLineIndex; i < lines.length; i++) {
+      const line = lines[i];
+      for (const ch of line) {
+        if (ch === "{") {
+          balance += 1;
+          seenOpening = true;
+        } else if (ch === "}") {
+          balance -= 1;
+          if (seenOpening && balance <= 0) {
+            return i + 1;
+          }
+        }
+      }
+    }
+ 
+    return Math.min(lines.length, startLineIndex + 1);
+  }
+ 
+  protected findPythonBlockEnd(lines: string[], startLineIndex: number): number {
+    const startLine = lines[startLineIndex] || "";
+    const indent = startLine.match(/^\s*/)?.[0].length || 0;
+ 
+    for (let i = startLineIndex + 1; i < lines.length; i++) {
+      const line = lines[i];
+      if (!line.trim()) {
+        continue;
+      }
+      const currentIndent = line.match(/^\s*/)?.[0].length || 0;
+      if (currentIndent <= indent) {
+        return i;
+      }
+    }
+ 
+    return lines.length;
+  }
+}
+ 
+export class PythonParser extends BaseRegexParser {
+  readonly language = "python";
+  readonly extensions = [".py"];
+ 
+  protected extractImports(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const importMatch = /^\s*import\s+([a-zA-Z0-9_.]+)/.exec(line);
+      if (importMatch) {
+        symbols.push({
+          type: "import",
+          name: importMatch[1],
+          startLine: index + 1,
+          endLine: index + 1,
+        });
+      }
+ 
+      const fromMatch = /^\s*from\s+([a-zA-Z0-9_.]+)\s+import\s+/.exec(line);
+      if (fromMatch) {
+        symbols.push({
+          type: "import",
+          name: fromMatch[1],
+          startLine: index + 1,
+          endLine: index + 1,
+        });
+      }
+    });
+ 
+    return symbols;
+  }
+ 
+  protected extractClasses(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const match = /^\s*class\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(line);
+      if (!match) {
+        return;
+      }
+ 
+      symbols.push({
+        type: "class",
+        name: match[1],
+        startLine: index + 1,
+        endLine: this.findPythonBlockEnd(lines, index),
+      });
+    });
+ 
+    return symbols;
+  }
+ 
+  protected extractFunctions(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const match = /^\s*def\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(line);
+      if (!match) {
+        return;
+      }
+ 
+      symbols.push({
+        type: "function",
+        name: match[1],
+        startLine: index + 1,
+        endLine: this.findPythonBlockEnd(lines, index),
+      });
+    });
+ 
+    return symbols;
+  }
+}
+ 
+export class GoParser extends BaseRegexParser {
+  readonly language = "go";
+  readonly extensions = [".go"];
+ 
+  protected extractImports(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const single = /^\s*import\s+"([^"]+)"/.exec(line);
+      if (single) {
+        symbols.push({
+          type: "import",
+          name: single[1],
+          startLine: index + 1,
+          endLine: index + 1,
+        });
+      }
+ 
+      const blockEntry = /^\s*"([^"]+)"\s*$/.exec(line);
+      if (blockEntry && index > 0 && lines[index - 1].includes("import")) {
+        symbols.push({
+          type: "import",
+          name: blockEntry[1],
+          startLine: index + 1,
+          endLine: index + 1,
+        });
+      }
+    });
+ 
+    return symbols;
+  }
+ 
+  protected extractClasses(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const match = /^\s*type\s+([A-Za-z_][A-Za-z0-9_]*)\s+(struct|interface)/.exec(line);
+      if (!match) {
+        return;
+      }
+ 
+      symbols.push({
+        type: match[2] === "interface" ? "interface" : "class",
+        name: match[1],
+        startLine: index + 1,
+        endLine: this.findBraceBlockEnd(lines, index),
+      });
+    });
+ 
+    return symbols;
+  }
+ 
+  protected extractFunctions(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const match = /^\s*func\s+(?:\([^)]+\)\s*)?([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(line);
+      if (!match) {
+        return;
+      }
+ 
+      symbols.push({
+        type: "function",
+        name: match[1],
+        startLine: index + 1,
+        endLine: this.findBraceBlockEnd(lines, index),
+      });
+    });
+ 
+    return symbols;
+  }
+}
+ 
+export class RustParser extends BaseRegexParser {
+  readonly language = "rust";
+  readonly extensions = [".rs"];
+ 
+  protected extractImports(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const match = /^\s*use\s+([^;]+);/.exec(line);
+      if (!match) {
+        return;
+      }
+ 
+      symbols.push({
+        type: "import",
+        name: match[1].trim(),
+        startLine: index + 1,
+        endLine: index + 1,
+      });
+    });
+ 
+    return symbols;
+  }
+ 
+  protected extractClasses(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const match = /^\s*(?:pub\s+)?(struct|enum|trait)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(line);
+      if (!match) {
+        return;
+      }
+ 
+      symbols.push({
+        type: match[1] === "trait" ? "interface" : "class",
+        name: match[2],
+        startLine: index + 1,
+        endLine: this.findBraceBlockEnd(lines, index),
+      });
+    });
+ 
+    return symbols;
+  }
+ 
+  protected extractFunctions(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const match = /^\s*(?:pub\s+)?fn\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(line);
+      if (!match) {
+        return;
+      }
+ 
+      symbols.push({
+        type: "function",
+        name: match[1],
+        startLine: index + 1,
+        endLine: this.findBraceBlockEnd(lines, index),
+      });
+    });
+ 
+    return symbols;
+  }
+}
+ 
+export class JavaParser extends BaseRegexParser {
+  readonly language = "java";
+  readonly extensions = [".java"];
+ 
+  protected extractImports(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const match = /^\s*import\s+([A-Za-z0-9_.*]+);/.exec(line);
+      if (!match) {
+        return;
+      }
+ 
+      symbols.push({
+        type: "import",
+        name: match[1],
+        startLine: index + 1,
+        endLine: index + 1,
+      });
+    });
+ 
+    return symbols;
+  }
+ 
+  protected extractClasses(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    lines.forEach((line, index) => {
+      const match =
+        /^\s*(?:public|private|protected|abstract|final|static|\s)*\s*(class|interface|enum)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(
+          line,
+        );
+      if (!match) {
+        return;
+      }
+ 
+      symbols.push({
+        type: match[1] === "interface" ? "interface" : "class",
+        name: match[2],
+        startLine: index + 1,
+        endLine: this.findBraceBlockEnd(lines, index),
+      });
+    });
+ 
+    return symbols;
+  }
+ 
+  protected extractFunctions(lines: string[]): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+    const reserved = new Set(["if", "for", "while", "switch", "catch"]);
+ 
+    lines.forEach((line, index) => {
+      const match =
+        /^\s*(?:public|private|protected|static|final|synchronized|native|abstract|\s)+[A-Za-z0-9_<>,[\].?\s]+\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(
+          line,
+        );
+      if (!match || reserved.has(match[1])) {
+        return;
+      }
+ 
+      symbols.push({
+        type: "function",
+        name: match[1],
+        startLine: index + 1,
+        endLine: this.findBraceBlockEnd(lines, index),
+      });
+    });
+ 
+    return symbols;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/parsers/tree-sitter-parser.ts.html b/coverage/lcov-report/src/parsers/tree-sitter-parser.ts.html new file mode 100644 index 0000000..5154bd7 --- /dev/null +++ b/coverage/lcov-report/src/parsers/tree-sitter-parser.ts.html @@ -0,0 +1,1462 @@ + + + + + + Code coverage report for src/parsers/tree-sitter-parser.ts + + + + + + + + + +
+
+

All files / src/parsers tree-sitter-parser.ts

+
+ +
+ 21.95% + Statements + 36/164 +
+ + +
+ 5.26% + Branches + 5/95 +
+ + +
+ 23.8% + Functions + 5/21 +
+ + +
+ 22.91% + Lines + 33/144 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +16x +16x +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +16x +  +16x +  +  +  +492x +16x +  +16x +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +492x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +8x +8x +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +246x +4x +  +  +  +  +  +4x +  +  +  +  +  +  +  +123x +123x +123x +492x +  +123x +  + 
/**
+ * Tree-sitter–based language parsers.
+ *
+ * Uses the native `tree-sitter` npm package for accurate AST-based extraction
+ * of functions, classes, and imports from Python, Go, Rust, and Java source
+ * files.  All grammar packages are listed as `optionalDependencies` so the
+ * server starts normally even when the native bindings are unavailable
+ * (e.g., in environments without build tools) — the orchestrator falls back to
+ * the regex parsers in that case.
+ *
+ * Loading strategy: use `createRequire` to bridge ESM → CJS for native addons.
+ */
+ 
+import { createRequire } from "module";
+import * as path from "path";
+import type { LanguageParser, ParseResult, ParsedSymbol } from "./parser-interface.js";
+ 
+const _require = createRequire(import.meta.url);
+ 
+// ---------------------------------------------------------------------------
+// Safe loader — returns null instead of throwing if the module is missing
+// ---------------------------------------------------------------------------
+function tryRequire(name: string): unknown {
+  try {
+    return _require(name);
+  } catch {
+    return null;
+  }
+}
+ 
+/**
+ * Resolve the tree-sitter Language object from a grammar package.
+ * Grammar packages export either `{ language }` or a bare language object
+ * depending on the version.
+ */
+function resolveLanguage(mod: unknown): unknown {
+  if (!mod) return null;
+  if (typeof (mod as any).language !== "undefined") return (mod as any).language;
+  return mod;
+}
+ 
+// ---------------------------------------------------------------------------
+// Tree-sitter node helpers
+// ---------------------------------------------------------------------------
+type TSNode = {
+  type: string;
+  text: string;
+  startPosition: { row: number; column: number };
+  endPosition: { row: number; column: number };
+  childCount: number;
+  namedChildCount: number;
+  child(i: number): TSNode | null;
+  namedChild(i: number): TSNode | null;
+  childForFieldName(name: string): TSNode | null;
+  children: TSNode[];
+  namedChildren: TSNode[];
+};
+ 
+/** Recursively walk the tree, calling visitor on every node. */
+function walk(node: TSNode, visitor: (n: TSNode) => void): void {
+  visitor(node);
+  for (let i = 0; i < node.childCount; i++) {
+    const child = node.child(i);
+    if (child) walk(child, visitor);
+  }
+}
+ 
+/** Return the text of a named child field, or empty string. */
+function fieldText(node: TSNode, field: string): string {
+  return node.childForFieldName(field)?.text ?? "";
+}
+ 
+// ---------------------------------------------------------------------------
+// Base class
+// ---------------------------------------------------------------------------
+abstract class TreeSitterParser implements LanguageParser {
+  abstract readonly language: string;
+  abstract readonly extensions: string[];
+  protected abstract readonly grammarPkg: string;
+ 
+  private _parser: {
+    setLanguage(lang: unknown): void;
+    parse(source: string): { rootNode: TSNode };
+  } | null = null;
+ 
+  private _initialized = false;
+ 
+  /** Attempt to load tree-sitter and the grammar. Returns true on success. */
+  protected initParser(): boolean {
+    if (this._initialized) return this._parser !== null;
+    this._initialized = true;
+ 
+    const TreeSitter = tryRequire("tree-sitter") as any;
+    Eif (!TreeSitter) return false;
+ 
+    const grammarMod = tryRequire(this.grammarPkg);
+    const lang = resolveLanguage(grammarMod);
+    if (!lang) return false;
+ 
+    try {
+      const p = new (TreeSitter as any)();
+      p.setLanguage(lang);
+      this._parser = p;
+      return true;
+    } catch {
+      return false;
+    }
+  }
+ 
+  get isAvailable(): boolean {
+    return this.initParser();
+  }
+ 
+  async parse(filePath: string, content: string): Promise<ParseResult> {
+    if (!this.initParser() || !this._parser) {
+      // Tree-sitter not available — return empty result; caller uses regex fallback
+      return {
+        file: path.basename(filePath),
+        language: this.language,
+        symbols: [],
+      };
+    }
+ 
+    try {
+      const tree = this._parser.parse(content);
+      const symbols = this.extractSymbols(tree.rootNode, content);
+      return {
+        file: path.basename(filePath),
+        language: this.language,
+        symbols,
+      };
+    } catch {
+      return {
+        file: path.basename(filePath),
+        language: this.language,
+        symbols: [],
+      };
+    }
+  }
+ 
+  protected abstract extractSymbols(root: TSNode, source: string): ParsedSymbol[];
+ 
+  /** Helper: find all descendants matching a set of node types. */
+  protected findAll(root: TSNode, types: Set<string>): TSNode[] {
+    const results: TSNode[] = [];
+    walk(root, (n) => {
+      if (types.has(n.type)) results.push(n);
+    });
+    return results;
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// Python
+// ---------------------------------------------------------------------------
+export class TreeSitterPythonParser extends TreeSitterParser {
+  readonly language = "python";
+  readonly extensions = [".py"];
+  protected readonly grammarPkg = "tree-sitter-python";
+ 
+  protected extractSymbols(root: TSNode, _source: string): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    walk(root, (node) => {
+      switch (node.type) {
+        case "function_definition":
+        case "async_function_definition": {
+          const name = fieldText(node, "name");
+          if (!name) break;
+          symbols.push({
+            type: "function",
+            name,
+            startLine: node.startPosition.row + 1,
+            endLine: node.endPosition.row + 1,
+          });
+          break;
+        }
+        case "class_definition": {
+          const name = fieldText(node, "name");
+          if (!name) break;
+          symbols.push({
+            type: "class",
+            name,
+            startLine: node.startPosition.row + 1,
+            endLine: node.endPosition.row + 1,
+          });
+          break;
+        }
+        case "import_statement": {
+          // import foo, bar
+          walk(node, (child) => {
+            if (child.type === "dotted_name" || child.type === "aliased_import") {
+              const name = child.childForFieldName("name")?.text ?? child.text;
+              if (name && !symbols.some((s) => s.name === name && s.type === "import")) {
+                symbols.push({
+                  type: "import",
+                  name,
+                  startLine: node.startPosition.row + 1,
+                  endLine: node.startPosition.row + 1,
+                });
+              }
+            }
+          });
+          break;
+        }
+        case "import_from_statement": {
+          const mod = fieldText(node, "module_name");
+          if (mod) {
+            symbols.push({
+              type: "import",
+              name: mod,
+              startLine: node.startPosition.row + 1,
+              endLine: node.startPosition.row + 1,
+            });
+          }
+          break;
+        }
+      }
+    });
+ 
+    return symbols;
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// Go
+// ---------------------------------------------------------------------------
+export class TreeSitterGoParser extends TreeSitterParser {
+  readonly language = "go";
+  readonly extensions = [".go"];
+  protected readonly grammarPkg = "tree-sitter-go";
+ 
+  protected extractSymbols(root: TSNode, _source: string): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    walk(root, (node) => {
+      switch (node.type) {
+        case "function_declaration":
+        case "method_declaration": {
+          const nameNode = node.childForFieldName("name");
+          const name = nameNode?.text ?? "";
+          if (!name) break;
+          symbols.push({
+            type: "function",
+            name,
+            startLine: node.startPosition.row + 1,
+            endLine: node.endPosition.row + 1,
+          });
+          break;
+        }
+        case "type_spec": {
+          const nameNode = node.childForFieldName("name");
+          const typeNode = node.childForFieldName("type");
+          if (!nameNode) break;
+          const kind = typeNode?.type;
+          const symType = kind === "interface_type" ? "interface" : "class";
+          symbols.push({
+            type: symType,
+            name: nameNode.text,
+            startLine: node.startPosition.row + 1,
+            endLine: node.endPosition.row + 1,
+          });
+          break;
+        }
+        case "import_spec": {
+          // Quoted path string
+          const pathNode = node.childForFieldName("path") ?? node.namedChild(0);
+          const raw = pathNode?.text ?? "";
+          const name = raw.replace(/^"|"$/g, "");
+          if (name) {
+            symbols.push({
+              type: "import",
+              name,
+              startLine: node.startPosition.row + 1,
+              endLine: node.startPosition.row + 1,
+            });
+          }
+          break;
+        }
+      }
+    });
+ 
+    return symbols;
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// Rust
+// ---------------------------------------------------------------------------
+export class TreeSitterRustParser extends TreeSitterParser {
+  readonly language = "rust";
+  readonly extensions = [".rs"];
+  protected readonly grammarPkg = "tree-sitter-rust";
+ 
+  protected extractSymbols(root: TSNode, _source: string): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    walk(root, (node) => {
+      switch (node.type) {
+        case "function_item": {
+          const name = fieldText(node, "name");
+          if (!name) break;
+          symbols.push({
+            type: "function",
+            name,
+            startLine: node.startPosition.row + 1,
+            endLine: node.endPosition.row + 1,
+          });
+          break;
+        }
+        case "struct_item":
+        case "enum_item": {
+          const name = fieldText(node, "name");
+          if (!name) break;
+          symbols.push({
+            type: "class",
+            name,
+            startLine: node.startPosition.row + 1,
+            endLine: node.endPosition.row + 1,
+          });
+          break;
+        }
+        case "trait_item": {
+          const name = fieldText(node, "name");
+          if (!name) break;
+          symbols.push({
+            type: "interface",
+            name,
+            startLine: node.startPosition.row + 1,
+            endLine: node.endPosition.row + 1,
+          });
+          break;
+        }
+        case "use_declaration": {
+          // Grab the path identifier up to the last segment
+          const arg = node.namedChild(0);
+          if (arg) {
+            const name = arg.text.replace(/::.*$/, "").replace(/^::/, "");
+            if (name) {
+              symbols.push({
+                type: "import",
+                name,
+                startLine: node.startPosition.row + 1,
+                endLine: node.startPosition.row + 1,
+              });
+            }
+          }
+          break;
+        }
+      }
+    });
+ 
+    return symbols;
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// Java
+// ---------------------------------------------------------------------------
+export class TreeSitterJavaParser extends TreeSitterParser {
+  readonly language = "java";
+  readonly extensions = [".java"];
+  protected readonly grammarPkg = "tree-sitter-java";
+ 
+  private static readonly RESERVED = new Set([
+    "if",
+    "for",
+    "while",
+    "switch",
+    "catch",
+    "try",
+    "else",
+  ]);
+ 
+  protected extractSymbols(root: TSNode, _source: string): ParsedSymbol[] {
+    const symbols: ParsedSymbol[] = [];
+ 
+    walk(root, (node) => {
+      switch (node.type) {
+        case "class_declaration":
+        case "interface_declaration":
+        case "enum_declaration":
+        case "record_declaration": {
+          const nameNode = node.childForFieldName("name");
+          if (!nameNode) break;
+          symbols.push({
+            type: node.type === "interface_declaration" ? "interface" : "class",
+            name: nameNode.text,
+            startLine: node.startPosition.row + 1,
+            endLine: node.endPosition.row + 1,
+          });
+          break;
+        }
+        case "method_declaration":
+        case "constructor_declaration": {
+          const nameNode = node.childForFieldName("name");
+          if (!nameNode) break;
+          if (TreeSitterJavaParser.RESERVED.has(nameNode.text)) break;
+          symbols.push({
+            type: "function",
+            name: nameNode.text,
+            startLine: node.startPosition.row + 1,
+            endLine: node.endPosition.row + 1,
+          });
+          break;
+        }
+        case "import_declaration": {
+          // Collapse to the full dotted name
+          const name = node.text
+            .replace(/^import\s+(static\s+)?/, "")
+            .replace(/;$/, "")
+            .trim();
+          if (name) {
+            symbols.push({
+              type: "import",
+              name,
+              startLine: node.startPosition.row + 1,
+              endLine: node.startPosition.row + 1,
+            });
+          }
+          break;
+        }
+      }
+    });
+ 
+    return symbols;
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// Registry helpers
+// ---------------------------------------------------------------------------
+ 
+/** All tree-sitter parsers, instantiated lazily. */
+let _parsers: TreeSitterParser[] | null = null;
+ 
+export function getTreeSitterParsers(): TreeSitterParser[] {
+  if (_parsers) return _parsers;
+  _parsers = [
+    new TreeSitterPythonParser(),
+    new TreeSitterGoParser(),
+    new TreeSitterRustParser(),
+    new TreeSitterJavaParser(),
+  ];
+  return _parsers;
+}
+ 
+/**
+ * Returns true at least one grammar loaded successfully.
+ * Call this at startup to log the availability status once.
+ */
+export function checkTreeSitterAvailability(): Record<string, boolean> {
+  const parsers = getTreeSitterParsers();
+  const status: Record<string, boolean> = {};
+  for (const p of parsers) {
+    status[p.language] = p.isAvailable;
+  }
+  return status;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/parsers/tree-sitter-typescript-parser.ts.html b/coverage/lcov-report/src/parsers/tree-sitter-typescript-parser.ts.html new file mode 100644 index 0000000..472786c --- /dev/null +++ b/coverage/lcov-report/src/parsers/tree-sitter-typescript-parser.ts.html @@ -0,0 +1,1486 @@ + + + + + + Code coverage report for src/parsers/tree-sitter-typescript-parser.ts + + + + + + + + + +
+
+

All files / src/parsers tree-sitter-typescript-parser.ts

+
+ +
+ 28.57% + Statements + 46/161 +
+ + +
+ 12.63% + Branches + 12/95 +
+ + +
+ 55.55% + Functions + 10/18 +
+ + +
+ 28.88% + Lines + 39/135 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +12x +12x +  +12x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +8x +  +  +246x +8x +  +8x +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +246x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +  +  +  +  +  +  +4x +4x +4x +  +  +  +  +  +  +4x +4x +  +  +123x +123x +  +  +  +123x +123x +  +  +  +  +  +  +  +123x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +  +  +123x +4x +  +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +123x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +  +  +  +  +  +  +  +  +4x +4x +  +  +123x +123x +  +  +  +  +  +  +  +  +  +  +  +  +  +123x +123x +  + 
/**
+ * Tree-sitter–based TypeScript / TSX parser.
+ *
+ * Replaces the regex-based `typescript-parser.ts` for symbol extraction when
+ * the native `tree-sitter-typescript` grammar is available.  Both parsers can
+ * coexist; the orchestrator selects tree-sitter when:
+ *   1. `tree-sitter-typescript` native binding compiled successfully, AND
+ *   2. `CODE_GRAPH_USE_TREE_SITTER=true` (or the instance reports isAvailable)
+ *
+ * The grammar package (`tree-sitter-typescript`) exports two Language objects:
+ *   - `{ typescript: Language, tsx: Language }`
+ * We derive a separate parser instance for each dialect.
+ *
+ * Extracted symbols:
+ *   - function_declaration (top-level & nested)
+ *   - arrow_function assigned to a const/let variable (top-level)
+ *   - method_definition / method_signature (sets scopePath = parent class name)
+ *   - class_declaration / abstract_class_declaration
+ *   - interface_declaration  → type: 'class', kind: 'interface'
+ *   - type_alias_declaration → type: 'class', kind: 'type'
+ *   - import_statement
+ */
+ 
+import { createRequire } from "module";
+import * as path from "path";
+import type { LanguageParser, ParseResult, ParsedSymbol } from "./parser-interface.js";
+ 
+const _require = createRequire(import.meta.url);
+ 
+// ---------------------------------------------------------------------------
+// Safe loader
+// ---------------------------------------------------------------------------
+function tryRequire(name: string): unknown {
+  try {
+    return _require(name);
+  } catch {
+    return null;
+  }
+}
+ 
+/**
+ * Load the `tree-sitter-javascript` Language object.
+ * The package exports the Language directly in some versions, or as `{ language }`.
+ */
+function loadJsGrammar(): unknown {
+  const mod = tryRequire("tree-sitter-javascript") as any;
+  if (!mod) return null;
+  if (typeof mod.language !== "undefined") return mod.language;
+  // Older releases export the Language object directly (not a constructor/function)
+  return mod;
+}
+ 
+/**
+ * tree-sitter-typescript exports { typescript, tsx } where each value is
+ * the Language object directly (NOT wrapped in { language }).
+ * Handle both v0.20 (bare object) and v0.21 ({ language }) call conventions.
+ */
+function loadTsGrammar(dialect: "typescript" | "tsx"): unknown {
+  // Try the idiomatic split-package path first
+  const split = tryRequire(`tree-sitter-typescript/${dialect}`) as any;
+  if (split) {
+    return typeof split.language !== "undefined" ? split.language : split;
+  }
+  // Fall back to the combined package's named export
+  const combined = tryRequire("tree-sitter-typescript") as any;
+  if (!combined) return null;
+  const lang = combined[dialect];
+  if (!lang) return null;
+  return typeof lang.language !== "undefined" ? lang.language : lang;
+}
+ 
+// ---------------------------------------------------------------------------
+// Tree-sitter node shape (enough of the API we actually use)
+// ---------------------------------------------------------------------------
+type TSNode = {
+  type: string;
+  text: string;
+  startPosition: { row: number; column: number };
+  endPosition: { row: number; column: number };
+  childCount: number;
+  child(i: number): TSNode | null;
+  childForFieldName(name: string): TSNode | null;
+  namedChildren: TSNode[];
+};
+ 
+/** Depth-first walk, carrying a mutable context stack. */
+function walkWithScope(
+  node: TSNode,
+  callback: (n: TSNode, scope: string[]) => void,
+  scope: string[] = [],
+): void {
+  // When we enter a class body we push the class name onto the scope stack
+  let newScope = scope;
+  if (
+    node.type === "class_declaration" ||
+    node.type === "abstract_class_declaration" ||
+    node.type === "class"
+  ) {
+    const nameNode = node.childForFieldName("name");
+    if (nameNode?.text) {
+      newScope = [...scope, nameNode.text];
+    }
+  }
+  callback(node, newScope);
+  for (let i = 0; i < node.childCount; i++) {
+    const child = node.child(i);
+    if (child) walkWithScope(child, callback, newScope);
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// Core extraction logic (shared between TS and TSX dialects)
+// ---------------------------------------------------------------------------
+function extractSymbols(root: TSNode): ParsedSymbol[] {
+  const symbols: ParsedSymbol[] = [];
+ 
+  walkWithScope(root, (node, scope) => {
+    switch (node.type) {
+      // ── Functions ────────────────────────────────────────────────────────
+      case "function_declaration":
+      case "generator_function_declaration": {
+        const nameNode = node.childForFieldName("name");
+        if (!nameNode?.text) break;
+        symbols.push({
+          type: "function",
+          name: nameNode.text,
+          kind: node.type === "generator_function_declaration" ? "generator" : undefined,
+          startLine: node.startPosition.row + 1,
+          endLine: node.endPosition.row + 1,
+          scopePath: scope[scope.length - 1],
+        });
+        break;
+      }
+ 
+      // ── Arrow / function expressions assigned to variables ───────────────
+      case "lexical_declaration":
+      case "variable_declaration": {
+        // Look for: const/let foo = (...) => ... | function(...)
+        for (const declarator of node.namedChildren) {
+          if (declarator.type !== "variable_declarator") continue;
+          const nameNode = declarator.childForFieldName("name");
+          const value = declarator.childForFieldName("value");
+          if (!nameNode?.text || !value) continue;
+          if (
+            value.type === "arrow_function" ||
+            value.type === "function" ||
+            value.type === "generator_function"
+          ) {
+            symbols.push({
+              type: "function",
+              name: nameNode.text,
+              kind: "arrow",
+              startLine: node.startPosition.row + 1,
+              endLine: node.endPosition.row + 1,
+              scopePath: scope[scope.length - 1],
+            });
+          }
+        }
+        break;
+      }
+ 
+      // ── Methods ──────────────────────────────────────────────────────────
+      case "method_definition":
+      case "method_signature": {
+        const nameNode = node.childForFieldName("name");
+        if (!nameNode?.text) break;
+        const methodName = nameNode.text;
+        // Skip constructors — they're part of the class node
+        if (methodName === "constructor") break;
+        symbols.push({
+          type: "function",
+          name: methodName,
+          kind: "method",
+          startLine: node.startPosition.row + 1,
+          endLine: node.endPosition.row + 1,
+          // scope contains the enclosing class name (if any)
+          scopePath: scope[scope.length - 1],
+        });
+        break;
+      }
+ 
+      // ── Classes ──────────────────────────────────────────────────────────
+      case "class_declaration":
+      case "abstract_class_declaration": {
+        const nameNode = node.childForFieldName("name");
+        if (!nameNode?.text) break;
+        symbols.push({
+          type: "class",
+          name: nameNode.text,
+          kind: node.type === "abstract_class_declaration" ? "abstract" : "class",
+          startLine: node.startPosition.row + 1,
+          endLine: node.endPosition.row + 1,
+        });
+        break;
+      }
+ 
+      // ── Interfaces ───────────────────────────────────────────────────────
+      case "interface_declaration": {
+        const nameNode = node.childForFieldName("name");
+        if (!nameNode?.text) break;
+        symbols.push({
+          type: "class",
+          name: nameNode.text,
+          kind: "interface",
+          startLine: node.startPosition.row + 1,
+          endLine: node.endPosition.row + 1,
+        });
+        break;
+      }
+ 
+      // ── Type aliases ─────────────────────────────────────────────────────
+      case "type_alias_declaration": {
+        const nameNode = node.childForFieldName("name");
+        if (!nameNode?.text) break;
+        symbols.push({
+          type: "class",
+          name: nameNode.text,
+          kind: "type",
+          startLine: node.startPosition.row + 1,
+          endLine: node.endPosition.row + 1,
+        });
+        break;
+      }
+ 
+      // ── Enum declarations ────────────────────────────────────────────────
+      case "enum_declaration": {
+        const nameNode = node.childForFieldName("name");
+        if (!nameNode?.text) break;
+        symbols.push({
+          type: "class",
+          name: nameNode.text,
+          kind: "enum",
+          startLine: node.startPosition.row + 1,
+          endLine: node.endPosition.row + 1,
+        });
+        break;
+      }
+ 
+      // ── Imports ──────────────────────────────────────────────────────────
+      case "import_statement": {
+        // source is the string literal: import ... from 'foo'
+        const source = node.childForFieldName("source");
+        if (!source) break;
+        const moduleSpec = source.text.replace(/['"]/g, "");
+        symbols.push({
+          type: "import",
+          name: moduleSpec,
+          startLine: node.startPosition.row + 1,
+          endLine: node.endPosition.row + 1,
+          imports: [moduleSpec],
+        });
+        break;
+      }
+    }
+  });
+ 
+  return symbols;
+}
+ 
+// ---------------------------------------------------------------------------
+// Base — shared between TS and TSX dialect parsers
+// ---------------------------------------------------------------------------
+abstract class TSDialectParser implements LanguageParser {
+  abstract readonly language: string;
+  abstract readonly extensions: string[];
+  protected abstract readonly dialect: "typescript" | "tsx";
+ 
+  private _parser: {
+    setLanguage(lang: unknown): void;
+    parse(source: string): { rootNode: TSNode };
+  } | null = null;
+ 
+  private _initialized = false;
+ 
+  protected init(): boolean {
+    if (this._initialized) return this._parser !== null;
+    this._initialized = true;
+ 
+    const TreeSitter = tryRequire("tree-sitter") as any;
+    Eif (!TreeSitter) return false;
+ 
+    const lang = loadTsGrammar(this.dialect);
+    if (!lang) return false;
+ 
+    try {
+      const p = new TreeSitter();
+      p.setLanguage(lang);
+      this._parser = p;
+      return true;
+    } catch {
+      return false;
+    }
+  }
+ 
+  get isAvailable(): boolean {
+    return this.init();
+  }
+ 
+  async parse(filePath: string, content: string): Promise<ParseResult> {
+    if (!this.init() || !this._parser) {
+      return {
+        file: path.basename(filePath),
+        language: this.language,
+        symbols: [],
+      };
+    }
+    try {
+      const tree = this._parser.parse(content);
+      return {
+        file: path.basename(filePath),
+        language: this.language,
+        symbols: extractSymbols(tree.rootNode),
+      };
+    } catch {
+      return {
+        file: path.basename(filePath),
+        language: this.language,
+        symbols: [],
+      };
+    }
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// TypeScript (.ts)
+// ---------------------------------------------------------------------------
+export class TreeSitterTypeScriptParser extends TSDialectParser {
+  readonly language = "typescript";
+  readonly extensions = [".ts"];
+  protected readonly dialect = "typescript" as const;
+}
+ 
+// ---------------------------------------------------------------------------
+// TSX (.tsx)
+// ---------------------------------------------------------------------------
+export class TreeSitterTSXParser extends TSDialectParser {
+  readonly language = "tsx";
+  readonly extensions = [".tsx"];
+  protected readonly dialect = "tsx" as const;
+}
+ 
+// ---------------------------------------------------------------------------
+// Convenience helpers
+// ---------------------------------------------------------------------------
+ 
+let _tsParser: TreeSitterTypeScriptParser | null = null;
+let _tsxParser: TreeSitterTSXParser | null = null;
+ 
+export function getTreeSitterTypeScriptParser(): TreeSitterTypeScriptParser {
+  if (!_tsParser) _tsParser = new TreeSitterTypeScriptParser();
+  return _tsParser;
+}
+ 
+export function getTreeSitterTSXParser(): TreeSitterTSXParser {
+  if (!_tsxParser) _tsxParser = new TreeSitterTSXParser();
+  return _tsxParser;
+}
+ 
+/** Check whether tree-sitter TypeScript / TSX grammars are loadable. */
+export function checkTsTreeSitterAvailability(): {
+  typescript: boolean;
+  tsx: boolean;
+} {
+  return {
+    typescript: getTreeSitterTypeScriptParser().isAvailable,
+    tsx: getTreeSitterTSXParser().isAvailable,
+  };
+}
+ 
+// ---------------------------------------------------------------------------
+// JavaScript / JSX — uses tree-sitter-javascript grammar
+// Both .js/.mjs/.cjs and .jsx share the same grammar; JSX syntax is built in.
+// ---------------------------------------------------------------------------
+abstract class JSDialectParser implements LanguageParser {
+  abstract readonly language: string;
+  abstract readonly extensions: string[];
+ 
+  private _parser: {
+    setLanguage(lang: unknown): void;
+    parse(source: string): { rootNode: TSNode };
+  } | null = null;
+ 
+  private _initialized = false;
+ 
+  protected init(): boolean {
+    if (this._initialized) return this._parser !== null;
+    this._initialized = true;
+ 
+    const TreeSitter = tryRequire("tree-sitter") as any;
+    Eif (!TreeSitter) return false;
+ 
+    const lang = loadJsGrammar();
+    if (!lang) return false;
+ 
+    try {
+      const p = new TreeSitter();
+      p.setLanguage(lang);
+      this._parser = p;
+      return true;
+    } catch {
+      return false;
+    }
+  }
+ 
+  get isAvailable(): boolean {
+    return this.init();
+  }
+ 
+  async parse(filePath: string, content: string): Promise<ParseResult> {
+    if (!this.init() || !this._parser) {
+      return {
+        file: path.basename(filePath),
+        language: this.language,
+        symbols: [],
+      };
+    }
+    try {
+      const tree = this._parser.parse(content);
+      return {
+        file: path.basename(filePath),
+        language: this.language,
+        // JS and TS share the same node-type names for all constructs we extract
+        symbols: extractSymbols(tree.rootNode),
+      };
+    } catch {
+      return {
+        file: path.basename(filePath),
+        language: this.language,
+        symbols: [],
+      };
+    }
+  }
+}
+ 
+export class TreeSitterJavaScriptParser extends JSDialectParser {
+  readonly language = "javascript";
+  readonly extensions = [".js", ".mjs", ".cjs"];
+}
+ 
+export class TreeSitterJSXParser extends JSDialectParser {
+  readonly language = "jsx";
+  readonly extensions = [".jsx"];
+}
+ 
+// Singletons
+let _jsParser: TreeSitterJavaScriptParser | null = null;
+let _jsxParser: TreeSitterJSXParser | null = null;
+ 
+export function getTreeSitterJavaScriptParser(): TreeSitterJavaScriptParser {
+  if (!_jsParser) _jsParser = new TreeSitterJavaScriptParser();
+  return _jsParser;
+}
+ 
+export function getTreeSitterJSXParser(): TreeSitterJSXParser {
+  if (!_jsxParser) _jsxParser = new TreeSitterJSXParser();
+  return _jsxParser;
+}
+ 
+/** Check whether tree-sitter JavaScript / JSX grammar is loadable. */
+export function checkJsTreeSitterAvailability(): {
+  javascript: boolean;
+  jsx: boolean;
+} {
+  // Both parsers share the same grammar — one check suffices
+  const available = getTreeSitterJavaScriptParser().isAvailable;
+  return { javascript: available, jsx: available };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/parsers/typescript-parser.ts.html b/coverage/lcov-report/src/parsers/typescript-parser.ts.html new file mode 100644 index 0000000..c246b11 --- /dev/null +++ b/coverage/lcov-report/src/parsers/typescript-parser.ts.html @@ -0,0 +1,1570 @@ + + + + + + Code coverage report for src/parsers/typescript-parser.ts + + + + + + + + + +
+
+

All files / src/parsers typescript-parser.ts

+
+ +
+ 70.58% + Statements + 96/136 +
+ + +
+ 38.8% + Branches + 26/67 +
+ + +
+ 75% + Functions + 18/24 +
+ + +
+ 71.21% + Lines + 94/132 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +3x +3x +3x +  +  +3x +3x +3x +3x +3x +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +3x +6x +  +18x +2x +  +  +2x +  +  +  +  +2x +  +2x +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +3x +3x +  +3x +  +6x +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +3x +3x +  +3x +6x +6x +  +1x +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +3x +3x +  +3x +  +6x +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +3x +3x +  +3x +  +6x +6x +  +  +  +  +  +  +  +  +  +6x +6x +3x +  +  +  +  +  +  +  +  +6x +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +4x +4x +  +4x +4x +4x +198x +4x +4x +194x +4x +4x +4x +  +  +  +  +  +  +  +  +  +3x +3x +  +3x +  +6x +6x +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +3x +3x +  +  +3x +  +6x +6x +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +3x +3x +125x +125x +125x +  +3x +  +  +  +  + 
import * as fs from "fs";
+import * as path from "path";
+import * as env from "../env.js";
+import { logger } from "../utils/logger.js";
+// import Parser from 'web-tree-sitter'; // Optional dependency
+ 
+export interface ASTNode {
+  type: string;
+  name?: string;
+  kind?: string;
+  startLine: number;
+  endLine: number;
+  text: string;
+  children?: ASTNode[];
+  properties?: Record<string, any>;
+}
+ 
+export interface ParsedFile {
+  filePath: string;
+  relativePath: string;
+  language: string;
+  LOC: number;
+  hash: string;
+  ast: ASTNode;
+  functions: FunctionNode[];
+  classes: ClassNode[];
+  variables: VariableNode[];
+  imports: ImportNode[];
+  exports: ExportNode[];
+  testSuites?: TestSuiteNode[];
+  testCases?: TestCaseNode[];
+}
+ 
+interface ParseFileOptions {
+  workspaceRoot?: string;
+}
+ 
+export interface FunctionNode {
+  id: string;
+  name: string;
+  kind: "function" | "arrow" | "method";
+  startLine: number;
+  endLine: number;
+  LOC: number;
+  parameters: string[];
+  isExported: boolean;
+}
+ 
+export interface ClassNode {
+  id: string;
+  name: string;
+  kind: "class" | "interface" | "type";
+  startLine: number;
+  endLine: number;
+  LOC: number;
+  isExported: boolean;
+  extends?: string;
+  implements?: string[];
+}
+ 
+export interface VariableNode {
+  id: string;
+  name: string;
+  kind: "const" | "let" | "var";
+  startLine: number;
+  endLine: number;
+  isExported: boolean;
+  type?: string;
+}
+ 
+export interface ImportNode {
+  id: string;
+  source: string;
+  specifiers: {
+    name: string;
+    imported: string;
+    isDefault: boolean;
+  }[];
+  startLine: number;
+}
+ 
+export interface ExportNode {
+  id: string;
+  name: string;
+  source?: string;
+  isDefault: boolean;
+  startLine: number;
+}
+ 
+export interface TestSuiteNode {
+  id: string;
+  name: string;
+  type: "describe" | "test" | "it";
+  startLine: number;
+  endLine?: number;
+  category?: "unit" | "integration" | "performance" | "e2e";
+  filePath?: string;
+}
+ 
+export interface TestCaseNode {
+  id: string;
+  name: string;
+  startLine: number;
+  endLine?: number;
+  parentSuiteId?: string;
+}
+ 
+export class TypeScriptParser {
+  // private parser: Parser | null = null;
+  // private language: Parser.Language | null = null;
+ 
+  async initialize(): Promise<void> {
+    // Tree-sitter initialization removed for MVP
+    // Will be added back when web-tree-sitter is properly configured
+    logger.error("TypeScriptParser initialized with regex fallback");
+  }
+ 
+  parseFile(filePath: string, options?: ParseFileOptions): ParsedFile {
+    const content = fs.readFileSync(filePath, "utf-8");
+    const workspaceRoot = options?.workspaceRoot || env.LXRAG_WORKSPACE_ROOT;
+    const relativePath = path.relative(workspaceRoot, filePath);
+    const hash = this.hashContent(content);
+    const lines = content.split("\n");
+    const LOC = lines.length;
+ 
+    // Parse using regex-based fallback for MVP (Tree-sitter integration follows)
+    const functions = this.extractFunctions(content, filePath);
+    const classes = this.extractClasses(content, filePath);
+    const variables = this.extractVariables(content, filePath);
+    const imports = this.extractImports(content, filePath);
+    const exports = this.extractExports(content, filePath);
+    const testSuites = this.extractTestSuites(content, filePath);
+    const testCases = this.extractTestCases(content, filePath);
+ 
+    return {
+      filePath,
+      relativePath,
+      language: "TypeScript",
+      LOC,
+      hash,
+      ast: {
+        type: "file",
+        name: path.basename(filePath),
+        startLine: 1,
+        endLine: LOC,
+        text: content,
+        children: [],
+      },
+      functions,
+      classes,
+      variables,
+      imports,
+      exports,
+      testSuites,
+      testCases,
+    };
+  }
+ 
+  private extractFunctions(content: string, filePath: string): FunctionNode[] {
+    const functions: FunctionNode[] = [];
+    const lines = content.split("\n");
+ 
+    // Control flow keywords to exclude (Phase 7.2)
+    const controlFlowKeywords = new Set([
+      "if",
+      "for",
+      "while",
+      "switch",
+      "catch",
+      "else",
+      "do",
+      "with",
+    ]);
+ 
+    // Match: function name, const name =, => style
+    const patterns = [
+      /^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\((.*?)\)/gm,
+      /^\s*(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s*)?\((.*?)\)\s*=>/gm,
+      /^\s*(?:async\s+)?(\w+)\s*\((.*?)\)\s*{/gm, // method in class
+    ];
+ 
+    content.split("\n").forEach((line, index) => {
+      for (const pattern of patterns) {
+        let match;
+        while ((match = pattern.exec(line)) !== null) {
+          const name = match[1];
+ 
+          // Skip control flow keywords (Phase 7.2 - false positive fix)
+          Iif (controlFlowKeywords.has(name.toLowerCase())) {
+            continue;
+          }
+ 
+          const params =
+            match[2]
+              ?.split(",")
+              .map((p) => p.trim())
+              .filter(Boolean) || [];
+          const isExported = line.includes("export");
+ 
+          functions.push({
+            id: `${path.basename(filePath)}:${name}:${index}`,
+            name,
+            kind: line.includes("=>") ? "arrow" : "function",
+            startLine: index + 1,
+            endLine: this.findBlockEnd(lines, index),
+            LOC: this.findBlockEnd(lines, index) - index,
+            parameters: params,
+            isExported,
+          });
+        }
+      }
+    });
+ 
+    return functions;
+  }
+ 
+  private extractClasses(content: string, filePath: string): ClassNode[] {
+    const classes: ClassNode[] = [];
+    const lines = content.split("\n");
+ 
+    lines.forEach((line, index) => {
+      const classMatch =
+        /^\s*(?:export\s+)?(?:abstract\s+)?class\s+(\w+)(?:\s+(?:extends|implements)\s+(.+?))?(?:\s*{|$)/.exec(
+          line,
+        );
+      Iif (classMatch) {
+        classes.push({
+          id: `${path.basename(filePath)}:${classMatch[1]}`,
+          name: classMatch[1],
+          kind: "class",
+          startLine: index + 1,
+          endLine: this.findBlockEnd(lines, index),
+          LOC: this.findBlockEnd(lines, index) - index,
+          isExported: line.includes("export"),
+          extends: classMatch[2]?.includes("extends")
+            ? classMatch[2]?.split(/extends|implements/)[0].trim()
+            : undefined,
+        });
+      }
+ 
+      const interfaceMatch =
+        /^\s*(?:export\s+)?interface\s+(\w+)(?:\s+(?:extends)\s+(.+?))?(?:\s*{|$)/.exec(line);
+      Iif (interfaceMatch) {
+        classes.push({
+          id: `${path.basename(filePath)}:${interfaceMatch[1]}`,
+          name: interfaceMatch[1],
+          kind: "interface",
+          startLine: index + 1,
+          endLine: this.findBlockEnd(lines, index),
+          LOC: this.findBlockEnd(lines, index) - index,
+          isExported: line.includes("export"),
+          extends: interfaceMatch[2]?.trim(),
+        });
+      }
+ 
+      const typeMatch = /^\s*(?:export\s+)?type\s+(\w+)\s*=/.exec(line);
+      Iif (typeMatch) {
+        classes.push({
+          id: `${path.basename(filePath)}:${typeMatch[1]}`,
+          name: typeMatch[1],
+          kind: "type",
+          startLine: index + 1,
+          endLine: index + 1,
+          LOC: 1,
+          isExported: line.includes("export"),
+        });
+      }
+    });
+ 
+    return classes;
+  }
+ 
+  private extractVariables(content: string, filePath: string): VariableNode[] {
+    const variables: VariableNode[] = [];
+    const lines = content.split("\n");
+ 
+    lines.forEach((line, index) => {
+      const match = /^\s*(?:export\s+)?(?:const|let|var)\s+(\w+)\s*(?::\s*(.+?))?\s*=/.exec(line);
+      if (match && !line.includes("(")) {
+        // Don't match function declarations
+        variables.push({
+          id: `${path.basename(filePath)}:${match[1]}`,
+          name: match[1],
+          kind: line.includes("const") ? "const" : line.includes("let") ? "let" : "var",
+          startLine: index + 1,
+          endLine: index + 1,
+          isExported: line.includes("export"),
+          type: match[2]?.trim(),
+        });
+      }
+    });
+ 
+    return variables;
+  }
+ 
+  private extractImports(content: string, filePath: string): ImportNode[] {
+    const imports: ImportNode[] = [];
+    const lines = content.split("\n");
+ 
+    lines.forEach((line, index) => {
+      const match =
+        /^import\s+(?:{([^}]+)}|(\w+)|(\w+)\s*,\s*{([^}]+)})\s+from\s+['"]([^'"]+)['"]/gm.exec(
+          line,
+        );
+      Iif (match) {
+        const source = match[5];
+        const specifierStr = match[1] || match[4] || "";
+        const defaultImport = match[2] || (match[3] ? match[3] : "");
+ 
+        const specifiers = [
+          ...(defaultImport ? [{ name: defaultImport, imported: "default", isDefault: true }] : []),
+          ...specifierStr
+            .split(",")
+            .map((s) => s.trim())
+            .filter(Boolean)
+            .map((s) => {
+              const [imported, name] = s.includes(" as ")
+                ? s.split(" as ").map((x) => x.trim())
+                : [s, s];
+              return { name, imported, isDefault: false };
+            }),
+        ];
+ 
+        imports.push({
+          id: `${path.basename(filePath)}:import:${index}`,
+          source,
+          specifiers,
+          startLine: index + 1,
+        });
+      }
+    });
+ 
+    return imports;
+  }
+ 
+  private extractExports(content: string, filePath: string): ExportNode[] {
+    const exports: ExportNode[] = [];
+    const lines = content.split("\n");
+ 
+    lines.forEach((line, index) => {
+      // export default
+      const defaultMatch = /^export\s+default\s+(.+)/.exec(line);
+      Iif (defaultMatch) {
+        exports.push({
+          id: `${path.basename(filePath)}:export:default`,
+          name: defaultMatch[1].split(/[({]/)[0].trim(),
+          isDefault: true,
+          startLine: index + 1,
+        });
+      }
+ 
+      // named exports
+      const namedMatch = /^export\s+(?:const|function|class|interface|type)\s+(\w+)/.exec(line);
+      if (namedMatch) {
+        exports.push({
+          id: `${path.basename(filePath)}:export:${namedMatch[1]}`,
+          name: namedMatch[1],
+          isDefault: false,
+          startLine: index + 1,
+        });
+      }
+ 
+      // export from
+      const reexportMatch = /^export\s+(?:{([^}]+)}|\*)\s+from\s+['"]([^'"]+)['"]/.exec(line);
+      Iif (reexportMatch) {
+        const items = reexportMatch[1]?.split(",").map((s) => s.trim()) || ["*"];
+        items.forEach((item) => {
+          exports.push({
+            id: `${path.basename(filePath)}:export:${item}`,
+            name: item,
+            source: reexportMatch[2],
+            isDefault: false,
+            startLine: index + 1,
+          });
+        });
+      }
+    });
+ 
+    return exports;
+  }
+ 
+  private findBlockEnd(lines: string[], startIndex: number): number {
+    let braceCount = 0;
+    let foundOpen = false;
+ 
+    for (let i = startIndex; i < lines.length; i++) {
+      const line = lines[i];
+      for (const char of line) {
+        if (char === "{") {
+          braceCount++;
+          foundOpen = true;
+        } else if (char === "}") {
+          braceCount--;
+          Eif (foundOpen && braceCount === 0) {
+            return i + 1;
+          }
+        }
+      }
+    }
+ 
+    return lines.length;
+  }
+ 
+  private extractTestSuites(content: string, filePath: string): TestSuiteNode[] {
+    const testSuites: TestSuiteNode[] = [];
+    const lines = content.split("\n");
+ 
+    lines.forEach((line, index) => {
+      // Match: describe|test|it( "name" or 'name' or `name`
+      const regex = new RegExp(/^\s*(describe|test|it)\s*\(\s*['"`]([^'"`]+)['"`]/);
+      const match = regex.exec(line);
+ 
+      Iif (match) {
+        const type = match[1] as "describe" | "test" | "it";
+        const name = match[2];
+ 
+        // Determine category based on file path
+        let category: "unit" | "integration" | "performance" | "e2e" | undefined = undefined;
+        if (filePath.includes(".integration.test.")) {
+          category = "integration";
+        } else if (filePath.includes(".performance.test.")) {
+          category = "performance";
+        } else if (filePath.includes("e2e")) {
+          category = "e2e";
+        } else if (filePath.includes(".test.")) {
+          category = "unit";
+        }
+ 
+        testSuites.push({
+          id: `${path.basename(filePath)}:${type}:${index}:${name}`,
+          name,
+          type,
+          startLine: index + 1,
+          endLine: this.findBlockEnd(lines, index),
+          category,
+          filePath,
+        });
+      }
+    });
+ 
+    return testSuites;
+  }
+ 
+  /**
+   * Phase 3.1: Extract individual test cases (it/test blocks)
+   */
+  private extractTestCases(content: string, filePath: string): TestCaseNode[] {
+    const testCases: TestCaseNode[] = [];
+    const lines = content.split("\n");
+ 
+    // Match individual it() or test() blocks (inside describe blocks)
+    lines.forEach((line, index) => {
+      // Match: it|test( "name" or 'name' or `name`
+      const regex = new RegExp(/^\s*(it|test)\s*\(\s*['"`]([^'"`]+)['"`]/);
+      const match = regex.exec(line);
+ 
+      Iif (match) {
+        const name = match[2];
+        // Generate a parent suite ID based on context
+        // Find the nearest describe block above this test
+        let parentSuiteId: string | undefined;
+        for (let i = index - 1; i >= 0; i--) {
+          const describeMatch = /^\s*describe\s*\(\s*['"`]([^'"`]+)['"`]/.exec(lines[i]);
+          if (describeMatch) {
+            parentSuiteId = `${path.basename(filePath)}:describe:${i}:${describeMatch[1]}`;
+            break;
+          }
+        }
+ 
+        testCases.push({
+          id: `${path.basename(filePath)}:it:${index}:${name}`,
+          name,
+          startLine: index + 1,
+          endLine: this.findBlockEnd(lines, index),
+          parentSuiteId,
+        });
+      }
+    });
+ 
+    return testCases;
+  }
+ 
+  private hashContent(content: string): string {
+    // Simple hash for MVP - replace with crypto.createHash in production
+    let hash = 0;
+    for (let i = 0; i < content.length; i++) {
+      const char = content.charCodeAt(i);
+      hash = (hash << 5) - hash + char;
+      hash = hash & hash; // Convert to 32-bit integer
+    }
+    return hash.toString(16);
+  }
+}
+ 
+export default TypeScriptParser;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/request-context.ts.html b/coverage/lcov-report/src/request-context.ts.html new file mode 100644 index 0000000..6935328 --- /dev/null +++ b/coverage/lcov-report/src/request-context.ts.html @@ -0,0 +1,139 @@ + + + + + + Code coverage report for src/request-context.ts + + + + + + + + + +
+
+

All files / src request-context.ts

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19  +  +  +  +  +  +13x +  +  +  +  +  +12x +  +  +  +3110x +  + 
import { AsyncLocalStorage } from "node:async_hooks";
+ 
+export interface RequestContext {
+  sessionId?: string;
+}
+ 
+const requestContextStorage = new AsyncLocalStorage<RequestContext>();
+ 
+export function runWithRequestContext<T>(
+  context: RequestContext,
+  fn: () => Promise<T>,
+): Promise<T> {
+  return requestContextStorage.run(context, fn);
+}
+ 
+export function getRequestContext(): RequestContext {
+  return requestContextStorage.getStore() || {};
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/response/budget.ts.html b/coverage/lcov-report/src/response/budget.ts.html new file mode 100644 index 0000000..dbeeace --- /dev/null +++ b/coverage/lcov-report/src/response/budget.ts.html @@ -0,0 +1,283 @@ + + + + + + Code coverage report for src/response/budget.ts + + + + + + + + + +
+
+

All files / src/response budget.ts

+
+ +
+ 100% + Statements + 14/14 +
+ + +
+ 100% + Branches + 8/8 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 14/14 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +137x +  +  +  +  +  +  +  +158x +158x +  +  +  +  +  +  +  +3x +3x +  +3x +10x +10x +5x +  +  +5x +5x +  +  +3x +  + 
export type ResponseProfile = "compact" | "balanced" | "debug";
+ 
+export const DEFAULT_TOKEN_BUDGETS: Record<ResponseProfile, number> = {
+  compact: 300,
+  balanced: 1200,
+  debug: Number.POSITIVE_INFINITY,
+};
+ 
+export interface BudgetAllocation {
+  coreCode: number;
+  dependencies: number;
+  decisions: number;
+  plan: number;
+  episodeHistory: number;
+}
+ 
+export interface ContextBudget {
+  maxTokens: number;
+  profile: ResponseProfile;
+  allocation: BudgetAllocation;
+}
+ 
+const DEFAULT_ALLOCATION: BudgetAllocation = {
+  coreCode: 0.4,
+  dependencies: 0.25,
+  decisions: 0.2,
+  plan: 0.1,
+  episodeHistory: 0.05,
+};
+ 
+export function makeBudget(
+  profile: ResponseProfile,
+  override?: Partial<ContextBudget>,
+): ContextBudget {
+  return {
+    maxTokens: override?.maxTokens ?? DEFAULT_TOKEN_BUDGETS[profile],
+    profile,
+    allocation: override?.allocation ?? DEFAULT_ALLOCATION,
+  };
+}
+ 
+export function estimateTokens(value: unknown): number {
+  const text = typeof value === "string" ? value : JSON.stringify(value);
+  return Math.ceil(text.length / 4);
+}
+ 
+export function fillSlot<T>(
+  items: T[],
+  tokenFn: (item: T) => number,
+  slotBudget: number,
+): { selected: T[]; usedTokens: number } {
+  let usedTokens = 0;
+  const selected: T[] = [];
+ 
+  for (const item of items) {
+    const itemCost = tokenFn(item);
+    if (usedTokens + itemCost > slotBudget) {
+      continue;
+    }
+ 
+    selected.push(item);
+    usedTokens += itemCost;
+  }
+ 
+  return { selected, usedTokens };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/response/index.html b/coverage/lcov-report/src/response/index.html new file mode 100644 index 0000000..807c63c --- /dev/null +++ b/coverage/lcov-report/src/response/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/response + + + + + + + + + +
+
+

All files src/response

+
+ +
+ 74.33% + Statements + 84/113 +
+ + +
+ 67.56% + Branches + 75/111 +
+ + +
+ 90% + Functions + 18/20 +
+ + +
+ 74.54% + Lines + 82/110 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
budget.ts +
+
100%14/14100%8/8100%3/3100%14/14
schemas.ts +
+
90%18/2075%6/8100%5/589.47%17/19
shaper.ts +
+
91.42%32/3591.3%42/46100%6/691.17%31/34
summarizer.ts +
+
45.45%20/4438.77%19/4966.66%4/646.51%20/43
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/response/schemas.ts.html b/coverage/lcov-report/src/response/schemas.ts.html new file mode 100644 index 0000000..0b24ddc --- /dev/null +++ b/coverage/lcov-report/src/response/schemas.ts.html @@ -0,0 +1,1351 @@ + + + + + + Code coverage report for src/response/schemas.ts + + + + + + + + + +
+
+

All files / src/response schemas.ts

+
+ +
+ 90% + Statements + 18/20 +
+ + +
+ 75% + Branches + 6/8 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 89.47% + Lines + 17/19 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +16x +16x +80x +  +  +16x +22x +14x +  +  +8x +23x +5x +  +8x +5x +  +  +5x +  +  +5x +4x +  +  +  +  +16x +  + 
export type FieldPriority = "required" | "high" | "medium" | "low";
+ 
+export interface OutputField {
+  key: string;
+  priority: FieldPriority;
+  description: string;
+}
+ 
+export const TOOL_OUTPUT_SCHEMAS: Record<string, OutputField[]> = {
+  graph_query: [
+    {
+      key: "intent",
+      priority: "required",
+      description: "Detected query intent or cypher mode",
+    },
+    {
+      key: "projectId",
+      priority: "required",
+      description: "Active project scope",
+    },
+    {
+      key: "count",
+      priority: "required",
+      description: "Number of returned rows",
+    },
+    {
+      key: "results",
+      priority: "required",
+      description: "Query result rows",
+    },
+    {
+      key: "workspaceRoot",
+      priority: "low",
+      description: "Workspace path",
+    },
+  ],
+  graph_health: [
+    {
+      key: "status",
+      priority: "required",
+      description: "Health state",
+    },
+    {
+      key: "projectId",
+      priority: "required",
+      description: "Active project scope",
+    },
+    {
+      key: "graphIndex",
+      priority: "high",
+      description: "Graph index counts",
+    },
+    {
+      key: "embeddings",
+      priority: "medium",
+      description: "Embedding status",
+    },
+    {
+      key: "freshness",
+      priority: "medium",
+      description: "Pending changes and watcher state",
+    },
+  ],
+  graph_rebuild: [
+    {
+      key: "success",
+      priority: "required",
+      description: "Whether rebuild request was accepted",
+    },
+    {
+      key: "status",
+      priority: "required",
+      description: "Queue/execution status",
+    },
+    {
+      key: "projectId",
+      priority: "high",
+      description: "Project scope",
+    },
+    {
+      key: "message",
+      priority: "high",
+      description: "Human-readable rebuild summary",
+    },
+    {
+      key: "note",
+      priority: "low",
+      description: "Follow-up hint",
+    },
+  ],
+  context_pack: [
+    {
+      key: "summary",
+      priority: "required",
+      description: "Task briefing summary",
+    },
+    {
+      key: "entryPoint",
+      priority: "required",
+      description: "Best entry file/symbol",
+    },
+    {
+      key: "coreSymbols",
+      priority: "high",
+      description: "Primary relevant symbols and code slices",
+    },
+    {
+      key: "activeBlockers",
+      priority: "high",
+      description: "Claims from other agents that block work",
+    },
+    {
+      key: "decisions",
+      priority: "medium",
+      description: "Relevant decision episodes",
+    },
+    {
+      key: "learnings",
+      priority: "medium",
+      description: "Relevant learnings",
+    },
+    {
+      key: "episodes",
+      priority: "low",
+      description: "Recent related episodes",
+    },
+    {
+      key: "pprScores",
+      priority: "low",
+      description: "Debug PPR score map",
+    },
+  ],
+  semantic_slice: [
+    {
+      key: "symbolName",
+      priority: "required",
+      description: "Resolved symbol name",
+    },
+    {
+      key: "file",
+      priority: "required",
+      description: "Source file path",
+    },
+    {
+      key: "startLine",
+      priority: "required",
+      description: "Slice start line",
+    },
+    {
+      key: "endLine",
+      priority: "required",
+      description: "Slice end line",
+    },
+    {
+      key: "code",
+      priority: "high",
+      description: "Extracted source code",
+    },
+    {
+      key: "incomingCallers",
+      priority: "medium",
+      description: "Callers of the selected symbol",
+    },
+    {
+      key: "outgoingCalls",
+      priority: "medium",
+      description: "Callees of the selected symbol",
+    },
+    {
+      key: "relevantDecisions",
+      priority: "low",
+      description: "Related decision episodes",
+    },
+    {
+      key: "relevantLearnings",
+      priority: "low",
+      description: "Related learning nodes",
+    },
+  ],
+  diff_since: [
+    {
+      key: "summary",
+      priority: "required",
+      description: "Human-readable change summary",
+    },
+    {
+      key: "projectId",
+      priority: "required",
+      description: "Project scope",
+    },
+    {
+      key: "since",
+      priority: "high",
+      description: "Resolved anchor details",
+    },
+    {
+      key: "added",
+      priority: "high",
+      description: "Added nodes since anchor",
+    },
+    {
+      key: "removed",
+      priority: "high",
+      description: "Removed nodes since anchor",
+    },
+    {
+      key: "modified",
+      priority: "high",
+      description: "Modified nodes since anchor",
+    },
+    {
+      key: "txIds",
+      priority: "medium",
+      description: "Covered transaction ids",
+    },
+  ],
+  episode_add: [
+    {
+      key: "episodeId",
+      priority: "required",
+      description: "Persisted episode id",
+    },
+    { key: "type", priority: "required", description: "Episode type" },
+    { key: "projectId", priority: "high", description: "Project scope" },
+    { key: "taskId", priority: "medium", description: "Optional task id" },
+  ],
+  episode_recall: [
+    { key: "query", priority: "required", description: "Recall query" },
+    { key: "count", priority: "required", description: "Episode count" },
+    { key: "episodes", priority: "high", description: "Ranked recall results" },
+    { key: "projectId", priority: "medium", description: "Project scope" },
+    {
+      key: "entityHints",
+      priority: "low",
+      description: "Embedding-derived entity hints",
+    },
+  ],
+  decision_query: [
+    { key: "query", priority: "required", description: "Decision query" },
+    { key: "count", priority: "required", description: "Decision count" },
+    { key: "decisions", priority: "high", description: "Decision episodes" },
+    { key: "projectId", priority: "medium", description: "Project scope" },
+  ],
+  reflect: [
+    {
+      key: "reflectionId",
+      priority: "required",
+      description: "Reflection episode id",
+    },
+    { key: "insight", priority: "high", description: "Reflection summary" },
+    {
+      key: "learningsCreated",
+      priority: "high",
+      description: "Number of learnings",
+    },
+    { key: "patterns", priority: "medium", description: "Recurring entities" },
+  ],
+  agent_claim: [
+    {
+      key: "status",
+      priority: "required",
+      description: "Claim outcome status",
+    },
+    { key: "claimId", priority: "high", description: "Claim identifier" },
+    { key: "projectId", priority: "high", description: "Project scope" },
+    { key: "conflicts", priority: "medium", description: "Conflicting claims" },
+  ],
+  agent_release: [
+    { key: "claimId", priority: "required", description: "Released claim id" },
+    {
+      key: "released",
+      priority: "required",
+      description: "Release success flag",
+    },
+    {
+      key: "outcome",
+      priority: "medium",
+      description: "Optional release outcome",
+    },
+  ],
+  agent_status: [
+    { key: "agentId", priority: "required", description: "Agent identifier" },
+    { key: "activeClaims", priority: "high", description: "Open claims" },
+    {
+      key: "recentEpisodes",
+      priority: "medium",
+      description: "Recent episode ids",
+    },
+    { key: "projectId", priority: "high", description: "Project scope" },
+  ],
+  coordination_overview: [
+    {
+      key: "activeClaims",
+      priority: "required",
+      description: "Active claim set",
+    },
+    { key: "staleClaims", priority: "high", description: "Stale claims" },
+    { key: "conflicts", priority: "high", description: "Current conflicts" },
+    { key: "projectId", priority: "high", description: "Project scope" },
+  ],
+  graph_set_workspace: [
+    { key: "success", priority: "required", description: "Operation success" },
+    {
+      key: "projectContext",
+      priority: "required",
+      description: "Active project context",
+    },
+    {
+      key: "watcherState",
+      priority: "high",
+      description: "Watcher runtime state",
+    },
+    {
+      key: "pendingChanges",
+      priority: "high",
+      description: "Queued filesystem changes",
+    },
+    { key: "message", priority: "medium", description: "Operation summary" },
+  ],
+  contract_validate: [
+    { key: "tool", priority: "required", description: "Validated tool name" },
+    {
+      key: "normalized",
+      priority: "required",
+      description: "Normalized arguments",
+    },
+    { key: "valid", priority: "required", description: "Validation result" },
+    {
+      key: "errors",
+      priority: "required",
+      description: "Zod validation errors",
+    },
+    {
+      key: "missingRequired",
+      priority: "required",
+      description: "Required fields absent from input",
+    },
+    {
+      key: "extraFields",
+      priority: "required",
+      description: "Unknown fields not in tool schema",
+    },
+    {
+      key: "warnings",
+      priority: "high",
+      description: "Normalization and advisory warnings",
+    },
+  ],
+  progress_query: [
+    { key: "type", priority: "required", description: "Progress entity type" },
+    { key: "count", priority: "high", description: "Returned items" },
+    { key: "items", priority: "high", description: "Progress records" },
+  ],
+  task_update: [
+    { key: "success", priority: "required", description: "Update success" },
+    { key: "task", priority: "high", description: "Updated task payload" },
+    {
+      key: "postActions",
+      priority: "medium",
+      description: "Triggered side effects",
+    },
+  ],
+  feature_status: [
+    { key: "id", priority: "required", description: "Feature identifier" },
+    { key: "status", priority: "required", description: "Feature status" },
+    { key: "tasks", priority: "high", description: "Linked tasks" },
+  ],
+  blocking_issues: [
+    {
+      key: "totalBlocked",
+      priority: "required",
+      description: "Blocked item count",
+    },
+    {
+      key: "blockingIssues",
+      priority: "high",
+      description: "Blocking issue list",
+    },
+    {
+      key: "recommendation",
+      priority: "medium",
+      description: "Suggested next action",
+    },
+  ],
+};
+ 
+const PRIORITY_ORDER: FieldPriority[] = ["low", "medium", "high"];
+ 
+export function applyFieldPriority(
+  data: Record<string, unknown>,
+  schema: OutputField[],
+  budget: number,
+): Record<string, unknown> {
+  const result: Record<string, unknown> = { ...data };
+  const required = new Set(
+    schema.filter((field) => field.priority === "required").map((f) => f.key),
+  );
+ 
+  for (const priority of PRIORITY_ORDER) {
+    if (Math.ceil(JSON.stringify(result).length / 4) <= budget) {
+      break;
+    }
+ 
+    const candidates = schema
+      .filter((field) => field.priority === priority)
+      .map((field) => field.key);
+ 
+    for (const key of candidates) {
+      Iif (required.has(key)) {
+        continue;
+      }
+      Iif (Math.ceil(JSON.stringify(result).length / 4) <= budget) {
+        break;
+      }
+      if (key in result) {
+        delete result[key];
+      }
+    }
+  }
+ 
+  return result;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/response/shaper.ts.html b/coverage/lcov-report/src/response/shaper.ts.html new file mode 100644 index 0000000..73f43c5 --- /dev/null +++ b/coverage/lcov-report/src/response/shaper.ts.html @@ -0,0 +1,538 @@ + + + + + + Code coverage report for src/response/shaper.ts + + + + + + + + + +
+
+

All files / src/response shaper.ts

+
+ +
+ 91.42% + Statements + 32/35 +
+ + +
+ 91.3% + Branches + 42/46 +
+ + +
+ 100% + Functions + 6/6 +
+ + +
+ 91.17% + Lines + 31/34 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +919x +919x +  +  +  +  +  +  +  +  +  +  +  +  +  +2206x +  +2206x +2206x +  +2206x +  +2206x +1x +  +  +2205x +919x +  +  +1286x +201x +291x +201x +  +  +201x +  +  +1085x +449x +449x +1783x +  +449x +449x +  +  +449x +  +  +636x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +132x +132x +  +132x +  +  +  +  +  +  +17x +17x +12x +  +  +  +132x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +  +  +  +  +  +  +  + 
/**
+ * @file response/shaper
+ * @description Shapes tool responses to fit profile budgets and output schemas.
+ * @remarks This module is pure formatting logic and should not perform I/O.
+ */
+ 
+import { estimateTokens, makeBudget, type ResponseProfile } from "./budget.js";
+import { TOOL_OUTPUT_SCHEMAS, applyFieldPriority } from "./schemas.js";
+ 
+/**
+ * Canonical response envelope returned by tool handlers.
+ */
+export interface ToolResponse {
+  ok: boolean;
+  profile: ResponseProfile;
+  summary: string;
+  data?: unknown;
+  _tokenEstimate: number;
+  hint?: string;
+  errorCode?: string;
+}
+ 
+/**
+ * Truncates long strings while preserving a visible truncation marker.
+ *
+ * @param input - Original string value.
+ * @param maxLength - Maximum number of characters allowed.
+ * @returns The original string when within bounds, otherwise a truncated string.
+ */
+function truncateString(input: string, maxLength: number): string {
+  Eif (!Number.isFinite(maxLength) || input.length <= maxLength) {
+    return input;
+  }
+  return `${input.slice(0, maxLength)}…(truncated)`;
+}
+ 
+/**
+ * Recursively shapes values to stay within profile-specific depth and size limits.
+ *
+ * @param value - Value to transform for output safety.
+ * @param profile - Output verbosity profile.
+ * @param depth - Current recursion depth.
+ * @returns A shaped value safe for transport in tool responses.
+ */
+function shapeValue(value: unknown, profile: ResponseProfile, depth = 0): unknown {
+  const maxDepth = profile === "debug" ? 20 : 6;
+  const maxArray =
+    profile === "balanced" ? 30 : profile === "debug" ? Number.POSITIVE_INFINITY : 10;
+  const maxKeys = profile === "balanced" ? 50 : profile === "debug" ? Number.POSITIVE_INFINITY : 20;
+  const maxStrLen =
+    profile === "balanced" ? 4000 : profile === "debug" ? Number.POSITIVE_INFINITY : 1200;
+ 
+  if (depth > maxDepth) {
+    return "[…depth limit]";
+  }
+ 
+  if (typeof value === "string") {
+    return truncateString(value, maxStrLen);
+  }
+ 
+  if (Array.isArray(value)) {
+    const limited = value.slice(0, maxArray);
+    const mapped = limited.map((item) => shapeValue(item, profile, depth + 1));
+    Iif (value.length > maxArray) {
+      mapped.push(`…${value.length - maxArray} more items`);
+    }
+    return mapped;
+  }
+ 
+  if (value !== null && typeof value === "object") {
+    const entries = Object.entries(value as Record<string, unknown>).slice(0, maxKeys);
+    const shaped = Object.fromEntries(
+      entries.map(([key, item]) => [key, shapeValue(item, profile, depth + 1)]),
+    );
+    const totalKeys = Object.keys(value as Record<string, unknown>).length;
+    Iif (totalKeys > maxKeys) {
+      (shaped as Record<string, unknown>)["…omitted"] = `${totalKeys - maxKeys} more keys`;
+    }
+    return shaped;
+  }
+ 
+  return value;
+}
+ 
+/**
+ * Builds a successful tool response and applies profile-aware shaping.
+ *
+ * @param summary - Human-readable success summary.
+ * @param data - Raw payload to include in response.
+ * @param profile - Desired response profile.
+ * @param toolName - Optional tool name for schema-priority shaping.
+ * @param hint - Optional user-facing follow-up hint.
+ * @returns A standardized success response envelope.
+ */
+export function formatResponse(
+  summary: string,
+  data: unknown,
+  profile: ResponseProfile = "compact",
+  toolName?: string,
+  hint?: string,
+): ToolResponse {
+  const budget = makeBudget(profile);
+  let shaped = shapeValue(data, profile);
+ 
+  if (
+    profile !== "debug" &&
+    toolName &&
+    shaped !== null &&
+    typeof shaped === "object" &&
+    !Array.isArray(shaped)
+  ) {
+    const schema = TOOL_OUTPUT_SCHEMAS[toolName];
+    if (schema?.length) {
+      shaped = applyFieldPriority(shaped as Record<string, unknown>, schema, budget.maxTokens);
+    }
+  }
+ 
+  return {
+    ok: true,
+    profile,
+    summary,
+    data: shaped,
+    _tokenEstimate: estimateTokens(shaped),
+    ...(hint ? { hint } : {}),
+  };
+}
+ 
+/**
+ * Builds a standardized error response envelope.
+ *
+ * @param errorCode - Stable machine-readable error code.
+ * @param reason - Human-readable failure reason.
+ * @param hint - Suggested next action for recovery.
+ * @param profile - Response profile to include in envelope.
+ * @returns A standardized error response envelope.
+ */
+export function errorResponse(
+  errorCode: string,
+  reason: string,
+  hint: string,
+  profile: ResponseProfile = "compact",
+): ToolResponse {
+  return {
+    ok: false,
+    profile,
+    summary: reason,
+    _tokenEstimate: estimateTokens(reason),
+    hint,
+    errorCode,
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/response/summarizer.ts.html b/coverage/lcov-report/src/response/summarizer.ts.html new file mode 100644 index 0000000..8e1dce6 --- /dev/null +++ b/coverage/lcov-report/src/response/summarizer.ts.html @@ -0,0 +1,415 @@ + + + + + + Code coverage report for src/response/summarizer.ts + + + + + + + + + +
+
+

All files / src/response summarizer.ts

+
+ +
+ 45.45% + Statements + 20/44 +
+ + +
+ 38.77% + Branches + 19/49 +
+ + +
+ 66.66% + Functions + 4/6 +
+ + +
+ 46.51% + Lines + 20/43 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111  +  +  +  +  +  +  +  +  +  +  +  +  +123x +  +123x +  +  +  +  +  +  +5x +5x +  +  +  +5x +5x +5x +5x +  +  +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +5x +5x +  +5x +3x +3x +3x +3x +  +  +2x +2x +  +  +  +  +  +  +  +  +  + 
export type SummaryKind = "file" | "function" | "class" | "import";
+ 
+export interface SummaryInput {
+  kind: SummaryKind;
+  cacheKey: string;
+  name?: string;
+  path?: string;
+  language?: string;
+  loc?: number;
+  metadata?: Record<string, unknown>;
+}
+ 
+export default class CodeSummarizer {
+  private cache = new Map<string, string>();
+ 
+  constructor(private endpointUrl?: string) {}
+ 
+  isConfigured(): boolean {
+    return !!this.endpointUrl;
+  }
+ 
+  async summarize(input: SummaryInput): Promise<string> {
+    const existing = this.cache.get(input.cacheKey);
+    Iif (existing) {
+      return existing;
+    }
+ 
+    const remote = await this.tryRemoteSummary(input);
+    const summary = remote || this.localSummary(input);
+    this.cache.set(input.cacheKey, summary);
+    return summary;
+  }
+ 
+  private async tryRemoteSummary(input: SummaryInput): Promise<string | null> {
+    Eif (!this.endpointUrl) {
+      return null;
+    }
+ 
+    const controller = new AbortController();
+    const timeout = setTimeout(() => controller.abort(), 2000);
+ 
+    try {
+      const response = await fetch(this.endpointUrl, {
+        method: "POST",
+        headers: { "content-type": "application/json" },
+        body: JSON.stringify({
+          kind: input.kind,
+          name: input.name,
+          path: input.path,
+          language: input.language,
+          loc: input.loc,
+          metadata: input.metadata || {},
+        }),
+        signal: controller.signal,
+      });
+ 
+      if (!response.ok) {
+        return null;
+      }
+ 
+      const payload = (await response.json()) as unknown;
+      if (typeof payload === "string") {
+        return payload.slice(0, 400);
+      }
+ 
+      if (payload && typeof payload === "object") {
+        const obj = payload as Record<string, unknown>;
+        if (typeof obj.summary === "string") {
+          return obj.summary.slice(0, 400);
+        }
+        if (
+          obj.data &&
+          typeof obj.data === "object" &&
+          typeof (obj.data as Record<string, unknown>).summary === "string"
+        ) {
+          return String((obj.data as Record<string, unknown>).summary).slice(0, 400);
+        }
+      }
+ 
+      return null;
+    } catch {
+      return null;
+    } finally {
+      clearTimeout(timeout);
+    }
+  }
+ 
+  private localSummary(input: SummaryInput): string {
+    const name = input.name || "unknown";
+    const path = input.path || "";
+    const loc = Number.isFinite(input.loc) ? Number(input.loc) : undefined;
+ 
+    if (input.kind === "file") {
+      const functions = Number(input.metadata?.functionCount || 0);
+      const classes = Number(input.metadata?.classCount || 0);
+      const imports = Number(input.metadata?.importCount || 0);
+      return `${input.language || "source"} file ${path} with ${loc || 0} LOC, ${functions} function(s), ${classes} class(es), and ${imports} import(s).`;
+    }
+ 
+    Eif (input.kind === "function") {
+      return `Function ${name} in ${path}${loc ? ` (${loc} LOC)` : ""}.`;
+    }
+ 
+    if (input.kind === "class") {
+      return `Class/interface ${name} in ${path}${loc ? ` (${loc} LOC)` : ""}.`;
+    }
+ 
+    return `Import ${name} used in ${path}.`;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/server.ts.html b/coverage/lcov-report/src/server.ts.html new file mode 100644 index 0000000..f8628a5 --- /dev/null +++ b/coverage/lcov-report/src/server.ts.html @@ -0,0 +1,943 @@ + + + + + + Code coverage report for src/server.ts + + + + + + + + + +
+
+

All files / src server.ts

+
+ +
+ 0% + Statements + 0/89 +
+ + +
+ 0% + Branches + 0/22 +
+ + +
+ 0% + Functions + 0/17 +
+ + +
+ 0% + Lines + 0/88 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file server
+ * @description MCP server bootstrap supporting stdio and Streamable HTTP transports.
+ * @remarks Tool registration is sourced from the centralized tool registry.
+ */
+ 
+import * as env from "./env.js";
+import * as z from "zod";
+import { randomUUID } from "node:crypto";
+import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
+import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
+import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
+import MemgraphClient from "./graph/client.js";
+import GraphIndexManager from "./graph/index.js";
+import { ToolHandlers } from "./tools/tool-handlers.js";
+import { toolRegistry } from "./tools/registry.js";
+import { loadConfig } from "./config.js";
+import GraphOrchestrator from "./graph/orchestrator.js";
+import { runWithRequestContext } from "./request-context.js";
+import { logger } from "./utils/logger.js";
+ 
+// Initialize components
+const memgraph = new MemgraphClient({
+  host: env.MEMGRAPH_HOST,
+  port: env.MEMGRAPH_PORT,
+});
+ 
+const index = new GraphIndexManager();
+let toolHandlers: ToolHandlers;
+let config: any = {};
+let orchestrator: GraphOrchestrator;
+ 
+/**
+ * Initializes shared infrastructure required before serving requests.
+ *
+ * @remarks
+ * This connects Memgraph, loads architecture config, and wires `ToolHandlers`
+ * with the shared index/orchestrator instances.
+ */
+async function initialize() {
+  try {
+    await memgraph.connect();
+    logger.error("[MCP] Memgraph connected");
+ 
+    // Load architecture config if exists
+    try {
+      config = await loadConfig();
+      logger.error("[MCP] Configuration loaded");
+    } catch (_err) {
+      logger.error("[MCP] No configuration file found, using defaults");
+      config = { architecture: { layers: [], rules: [] } };
+    }
+ 
+    // Initialize GraphOrchestrator — pass shared index so post-build sync populates it
+    orchestrator = new GraphOrchestrator(memgraph, false, index);
+ 
+    toolHandlers = new ToolHandlers({
+      index,
+      memgraph,
+      config,
+      orchestrator: orchestrator,
+    });
+ 
+    logger.error("[MCP] Tool handlers initialized");
+  } catch (error) {
+    logger.error("[MCP] Initialization error:", error);
+  }
+}
+ 
+// Server implementation info
+const serverInfo = {
+  name: env.LXRAG_SERVER_NAME,
+  version: "1.0.0",
+};
+ 
+/**
+ * Creates a configured MCP server instance and binds all registered tools.
+ *
+ * @returns A ready-to-connect `McpServer` instance.
+ */
+function createMcpServerInstance(): McpServer {
+  const mcpServer = new McpServer(serverInfo);
+ 
+  /**
+   * Wraps registry-based tool execution into MCP response envelopes.
+   */
+  const invokeRegisteredTool = (toolName: string) => async (args: any) => {
+    if (!toolHandlers) {
+      return {
+        content: [{ type: "text" as const, text: "Server not initialized" }],
+        isError: true,
+      };
+    }
+    try {
+      const result = await toolHandlers.callTool(toolName, args);
+      return { content: [{ type: "text" as const, text: result }] };
+    } catch (error: any) {
+      return {
+        content: [{ type: "text" as const, text: `Error: ${error.message}` }],
+        isError: true,
+      };
+    }
+  };
+ 
+  /**
+   * Registers one tool definition with zod input validation.
+   */
+  const registerTool = (name: string, description: string, inputSchema: z.ZodTypeAny) => {
+    mcpServer.registerTool(
+      name,
+      {
+        description,
+        inputSchema,
+      },
+      invokeRegisteredTool(name),
+    );
+  };
+ 
+  // Register all tools from centralized registry.
+  for (const definition of toolRegistry) {
+    registerTool(definition.name, definition.description, z.object(definition.inputShape));
+  }
+ 
+  return mcpServer;
+}
+ 
+/**
+ * Process entrypoint.
+ *
+ * @remarks
+ * Chooses transport mode (`stdio` or `http`), initializes per-session state,
+ * and starts serving requests.
+ */
+async function main() {
+  await initialize();
+ 
+  const transportMode = env.MCP_TRANSPORT;
+ 
+  if (transportMode === "http") {
+    const port = env.MCP_PORT;
+    const app = createMcpExpressApp();
+    const sessions = new Map<
+      string,
+      { server: McpServer; transport: StreamableHTTPServerTransport }
+    >();
+ 
+    const handleMcpRequest = async (req: any, res: any) => {
+      try {
+        const headerSessionId = req.headers?.["mcp-session-id"];
+        const sessionId =
+          typeof headerSessionId === "string"
+            ? headerSessionId
+            : Array.isArray(headerSessionId)
+              ? headerSessionId[0]
+              : undefined;
+        const isInitialize = req.body?.method === "initialize";
+ 
+        if (isInitialize) {
+          const sessionServer = createMcpServerInstance();
+          const transport = new StreamableHTTPServerTransport({
+            sessionIdGenerator: () => randomUUID(),
+            onsessioninitialized: (newSessionId: string) => {
+              sessions.set(newSessionId, {
+                server: sessionServer,
+                transport,
+              });
+            },
+          });
+ 
+          transport.onclose = () => {
+            const closedSessionId = transport.sessionId;
+            if (!closedSessionId) {
+              return;
+            }
+ 
+            const existing = sessions.get(closedSessionId);
+            if (existing?.transport === transport) {
+              sessions.delete(closedSessionId);
+              void existing.server.close().catch((closeError) => {
+                logger.warn(
+                  "[MCP] Failed to close session server after transport close:",
+                  closeError,
+                );
+              });
+            }
+          };
+ 
+          await sessionServer.connect(transport);
+ 
+          await runWithRequestContext({ sessionId: transport.sessionId }, async () => {
+            await transport!.handleRequest(req, res, req.body);
+          });
+          return;
+        }
+ 
+        if (!sessionId || !sessions.has(sessionId)) {
+          res.status(400).json({
+            jsonrpc: "2.0",
+            error: {
+              code: -32000,
+              message: "Bad Request: Invalid or missing MCP session",
+            },
+            id: null,
+          });
+          return;
+        }
+ 
+        const sessionState = sessions.get(sessionId)!;
+        await runWithRequestContext({ sessionId }, async () => {
+          await sessionState.transport.handleRequest(req, res, req.body);
+        });
+      } catch (error: any) {
+        logger.error("[MCP] HTTP transport error:", error);
+        if (!res.headersSent) {
+          res.status(500).json({
+            jsonrpc: "2.0",
+            error: {
+              code: -32603,
+              message: error?.message || "Internal server error",
+            },
+            id: null,
+          });
+        }
+      }
+    };
+ 
+    app.post("/", handleMcpRequest);
+    app.post("/mcp", handleMcpRequest);
+ 
+    app.get("/health", (_req: any, res: any) => {
+      res.status(200).json({ status: "ok", transport: "http" });
+    });
+ 
+    // A2A Agent Card — Phase 4 / Section 0.4 of AGENT_CONTEXT_ENGINE_PLAN.md
+    // Allows A2A-aware orchestrators (LangGraph, AutoGen, etc.) to discover
+    // this server as a memory + coordination specialist agent.
+    app.get("/.well-known/agent.json", (_req: any, res: any) => {
+      const serverName = env.LXRAG_SERVER_NAME;
+      res.status(200).json({
+        "@context": "https://schema.a2aprotocol.dev/v1",
+        "@type": "Agent",
+        name: serverName,
+        description:
+          "External long-term memory and coordination layer for LLM agent fleets working on software codebases. Provides code graph queries, agent episode memory, multi-agent coordination, and PPR-ranked context packing.",
+        capabilities: [
+          "code-graph",
+          "agent-memory",
+          "agent-coordination",
+          "multi-agent-coordination",
+          "context-packing",
+          "architecture-validation",
+          "test-impact-analysis",
+        ],
+        mcpEndpoint: "/mcp",
+        transport: "StreamableHTTP",
+        version: "1.0.0",
+      });
+    });
+ 
+    app.listen(port, () => {
+      logger.error(`[MCP] Server started on HTTP transport (port ${port})`);
+      logger.error("[MCP] Endpoints: POST / and POST /mcp");
+      logger.error("[MCP] A2A Agent Card: GET /.well-known/agent.json");
+      logger.error(
+        `[MCP] Available tools: 38 (5 GraphRAG + 2 Architecture + 4 Test + 4 Progress + 4 Utility + 5 Vector Search + 2 Docs + 1 Reference + 2 Setup)`,
+      );
+    });
+ 
+    return;
+  }
+ 
+  const mcpServer = createMcpServerInstance();
+  const stdioTransport = new StdioServerTransport();
+  await mcpServer.connect(stdioTransport);
+ 
+  logger.error("[MCP] Server started on stdio transport");
+  logger.error(
+    `[MCP] Available tools: 38 (5 GraphRAG + 2 Architecture + 4 Test + 4 Progress + 4 Utility + 5 Vector Search + 2 Docs + 1 Reference + 2 Setup)`,
+  );
+}
+ 
+main().catch((error) => {
+  logger.error("[MCP] Fatal error:", error);
+  process.exit(1);
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/contract-validator.ts.html b/coverage/lcov-report/src/tools/contract-validator.ts.html new file mode 100644 index 0000000..a8a5b96 --- /dev/null +++ b/coverage/lcov-report/src/tools/contract-validator.ts.html @@ -0,0 +1,472 @@ + + + + + + Code coverage report for src/tools/contract-validator.ts + + + + + + + + + +
+
+

All files / src/tools contract-validator.ts

+
+ +
+ 92% + Statements + 23/25 +
+ + +
+ 66.66% + Branches + 12/18 +
+ + +
+ 100% + Functions + 7/7 +
+ + +
+ 95.65% + Lines + 22/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +3x +  +3x +6x +3x +  +3x +  +  +  +  +  +3x +3x +  +3x +1x +  +  +  +  +  +  +  +  +2x +3x +3x +  +  +  +  +  +  +2x +  +3x +  +3x +3x +3x +  +3x +3x +  +3x +  +  +  +  +  +  +  + 
/**
+ * @file tools/contract-validator
+ * @description Zod-based schema validation for tool arguments.
+ *
+ * Provides a standalone `validateToolArgs` function that validates a raw
+ * argument object against a tool's declared `inputShape`.  This module
+ * statically imports `registry.ts` — that is safe because the import graph
+ * only goes in one direction:
+ *
+ *   tool-handler-base → contract-validator → registry → handlers → types
+ *
+ * The handler files do NOT import
+ * `tool-handler-base` or `contract-validator`, so there is no cycle.
+ */
+ 
+import * as z from "zod";
+import { toolRegistryMap } from "./registry.js";
+ 
+// ─── Public contract ────────────────────────────────────────────────────────
+ 
+/**
+ * The result of validating tool arguments against the declared schema.
+ */
+export interface ContractValidation {
+  /** True when all required fields are present and have correct types. */
+  valid: boolean;
+ 
+  /**
+   * Zod validation errors describing incorrect or missing fields.
+   * Empty when `valid` is true.
+   */
+  errors: string[];
+ 
+  /**
+   * Fields present in the raw args that are not part of the tool's schema.
+   * These can indicate typos in parameter names (e.g. `codeType` instead
+   * of `type`) and are surfaced as warnings even when `valid` is true.
+   */
+  extraFields: string[];
+ 
+  /**
+   * Required schema fields that were absent from the raw args.
+   * Derived from Zod issues with `received: "undefined"`.
+   */
+  missingRequired: string[];
+ 
+  /**
+   * Human-readable advisory messages (e.g. unknown field hints).
+   * Does NOT indicate a validation failure on its own.
+   */
+  warnings: string[];
+}
+ 
+// ─── Implementation ─────────────────────────────────────────────────────────
+ 
+/**
+ * Validate `args` against the Zod `inputShape` registered for `toolName`.
+ *
+ * @param toolName - Canonical tool name as registered (e.g. `"semantic_diff"`).
+ * @param args     - Raw unvalidated arguments object (may be `null` / `undefined`).
+ * @returns        A {@link ContractValidation} describing the result.
+ */
+export function validateToolArgs(toolName: string, args: unknown): ContractValidation {
+  const def = toolRegistryMap.get(toolName);
+ 
+  Iif (!def) {
+    return {
+      valid: false,
+      errors: [`Unknown tool: '${toolName}'. Use tools_list to see valid names.`],
+      extraFields: [],
+      missingRequired: [],
+      warnings: [],
+    };
+  }
+ 
+  const inputKeys =
+    args !== null && typeof args === "object" ? Object.keys(args as Record<string, unknown>) : [];
+ 
+  const knownKeys = new Set(Object.keys(def.inputShape));
+  const extraFields = inputKeys.filter((k) => !knownKeys.has(k));
+  const warnings = extraFields.map(
+    (k) =>
+      `Unknown field '${k}' is not part of '${toolName}' schema — possible typo? Known fields: ${[...knownKeys].join(", ")}`,
+  );
+ 
+  // Build a strict Zod object schema to validate required/optional fields.
+  // We intentionally do NOT use .strict() here so that pass-through of extra
+  // fields does not cause a Zod error — we report them separately as warnings.
+  const schema = z.object(def.inputShape as z.ZodRawShape);
+  const result = schema.safeParse(args ?? {});
+ 
+  if (result.success) {
+    return {
+      valid: true,
+      errors: [],
+      extraFields,
+      missingRequired: [],
+      warnings,
+    };
+  }
+ 
+  const errors = result.error.issues.map((issue) => {
+    const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
+    return `${path}: ${issue.message}`;
+  });
+ 
+  // A field is "missing required" when the error references a top-level key
+  // that was not supplied in the input at all.  This handles both string/number
+  // (`invalid_type`) and enum (`invalid_value`) Zod v4 error codes.
+  const argsObj: Record<string, unknown> =
+    args !== null && typeof args === "object" ? (args as Record<string, unknown>) : {};
+ 
+  const missingRequired = result.error.issues
+    .filter((issue) => {
+      Iif (issue.path.length === 0) return false;
+      const topKey = String(issue.path[0]);
+      return !(topKey in argsObj);
+    })
+    .map((issue) => String(issue.path[0]))
+    .filter((key, idx, arr) => arr.indexOf(key) === idx); // deduplicate
+ 
+  return {
+    valid: false,
+    errors,
+    extraFields,
+    missingRequired,
+    warnings,
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/arch-tools.ts.html b/coverage/lcov-report/src/tools/handlers/arch-tools.ts.html new file mode 100644 index 0000000..0302a1b --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/arch-tools.ts.html @@ -0,0 +1,448 @@ + + + + + + Code coverage report for src/tools/handlers/arch-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers arch-tools.ts

+
+ +
+ 85% + Statements + 17/20 +
+ + +
+ 91.66% + Branches + 11/12 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 85% + Lines + 17/20 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +5x +  +5x +  +  +  +  +  +5x +3x +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +3x +3x +  +3x +2x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Architecture Validation Tools
+ * Registry-backed architecture tool definitions.
+ *
+ * Tools:
+ * - arch_validate: validate code against architecture rules
+ * - arch_suggest: suggest appropriate layer for code
+ */
+ 
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const archToolDefinitions: ToolDefinition[] = [
+  {
+    name: "arch_validate",
+    category: "arch",
+    description: "Validate code against layer rules",
+    inputShape: {
+      files: z.array(z.string()).optional().describe("Files to validate"),
+      strict: z.boolean().default(false).describe("Strict validation mode"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { files, strict = false, profile = "compact" } = args;
+ 
+      const archEngine = ctx.engines.arch as
+        | {
+            validate: (files?: string[]) => Promise<any>;
+          }
+        | undefined;
+ 
+      if (!archEngine) {
+        return ctx.errorEnvelope(
+          "ARCH_ENGINE_UNAVAILABLE",
+          "Architecture engine not initialized",
+          true,
+        );
+      }
+ 
+      try {
+        const result = await archEngine.validate(files);
+ 
+        const output = {
+          success: result.success,
+          violations: result.violations.slice(0, 20),
+          statistics: result.statistics,
+          severity: strict ? "error" : "warning",
+        };
+ 
+        return ctx.formatSuccess(output, profile);
+      } catch (error) {
+        return ctx.errorEnvelope("ARCH_VALIDATE_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "arch_suggest",
+    category: "arch",
+    description: "Suggest best location for new code",
+    inputShape: {
+      name: z.string().describe("Code name/identifier"),
+      type: z
+        .enum(["component", "hook", "service", "context", "utility", "engine", "class", "module"])
+        .describe("Code type"),
+      dependencies: z.array(z.string()).optional().describe("Required dependencies"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { name, type, dependencies = [], profile = "compact" } = args;
+ 
+      const archEngine = ctx.engines.arch as
+        | {
+            getSuggestion: (
+              name: string,
+              type: string,
+              dependencies: string[],
+            ) =>
+              | {
+                  suggestedLayer: string;
+                  suggestedPath: string;
+                  reasoning: string;
+                }
+              | undefined;
+          }
+        | undefined;
+ 
+      Iif (!archEngine) {
+        return ctx.errorEnvelope(
+          "ARCH_ENGINE_UNAVAILABLE",
+          "Architecture engine not initialized",
+          true,
+        );
+      }
+ 
+      try {
+        const suggestion = archEngine.getSuggestion(name, type, dependencies);
+ 
+        if (!suggestion) {
+          return ctx.formatSuccess(
+            {
+              success: false,
+              message: "No suitable layer found for this code",
+              reason: `No layer can import from all dependencies: ${dependencies.join(", ")}`,
+            },
+            profile,
+          );
+        }
+ 
+        return ctx.formatSuccess(
+          {
+            success: true,
+            suggestedLayer: suggestion.suggestedLayer,
+            suggestedPath: suggestion.suggestedPath,
+            reasoning: suggestion.reasoning,
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("ARCH_SUGGEST_FAILED", String(error), true);
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/core-analysis-tools.ts.html b/coverage/lcov-report/src/tools/handlers/core-analysis-tools.ts.html new file mode 100644 index 0000000..1b8e586 --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/core-analysis-tools.ts.html @@ -0,0 +1,1039 @@ + + + + + + Code coverage report for src/tools/handlers/core-analysis-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers core-analysis-tools.ts

+
+ +
+ 76.29% + Statements + 103/135 +
+ + +
+ 47.7% + Branches + 52/109 +
+ + +
+ 73.33% + Functions + 11/15 +
+ + +
+ 78.74% + Lines + 100/127 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +5x +  +5x +5x +5x +5x +  +  +5x +  +1x +  +5x +1x +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +5x +5x +1x +1x +1x +  +  +  +  +  +  +4x +4x +2x +2x +2x +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +3x +3x +  +  +  +  +  +3x +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +3x +2x +2x +2x +4x +4x +4x +  +  +  +  +  +4x +  +  +2x +2x +  +  +4x +2x +  +2x +4x +4x +  +4x +  +4x +4x +4x +  +  +  +  +  +  +  +4x +  +4x +4x +4x +4x +  +  +  +  +4x +  +  +  +  +4x +  +  +2x +2x +2x +2x +2x +  +2x +2x +2x +2x +2x +2x +2x +  +  +  +2x +  +  +2x +4x +4x +4x +  +4x +4x +4x +2x +2x +  +  +2x +2x +2x +2x +2x +2x +2x +2x +  +  +  +  +  +4x +4x +4x +  +  +2x +4x +2x +  +  +  +2x +  +6x +6x +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  + 
/**
+ * @file tools/handlers/core-analysis-tools
+ * @description Code-analysis tool definitions — code_explain, find_pattern.
+ */
+ 
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const coreAnalysisToolDefinitions: ToolDefinition[] = [
+  {
+    name: "code_explain",
+    category: "code",
+    description: "Explain code element with dependency context",
+    inputShape: {
+      element: z.string().describe("File path, class or function name"),
+      depth: z.number().min(1).max(3).default(2).describe("Analysis depth"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { element, depth = 2, profile = "compact" } = args;
+ 
+      try {
+        const files = ctx.context.index.getNodesByType("FILE");
+        const funcs = ctx.context.index.getNodesByType("FUNCTION");
+        const classes = ctx.context.index.getNodesByType("CLASS");
+ 
+        const targetNode =
+          files.find((n: any) => n.properties.path?.includes(element)) ||
+          funcs.find((n: any) => n.properties.name === element) ||
+          classes.find((n: any) => n.properties.name === element);
+ 
+        if (!targetNode) {
+          return ctx.errorEnvelope(
+            "ELEMENT_NOT_FOUND",
+            `Element not found: ${element}`,
+            true,
+            "Provide a file path, class name, or function name present in the index.",
+          );
+        }
+ 
+        const explanation: any = {
+          element: targetNode.properties.name || targetNode.properties.path,
+          type: targetNode.type,
+          properties: targetNode.properties,
+          dependencies: [] as any[],
+          dependents: [] as any[],
+        };
+ 
+        const outgoing = ctx.context.index.getRelationshipsFrom(targetNode.id);
+        for (const rel of outgoing.slice(0, depth * 10)) {
+          const target = ctx.context.index.getNode(rel.to);
+          Eif (target) {
+            explanation.dependencies.push({
+              type: rel.type,
+              target: target.properties.name || target.properties.path || target.id,
+            });
+          }
+        }
+ 
+        const incoming = ctx.context.index.getRelationshipsTo(targetNode.id);
+        for (const rel of incoming.slice(0, depth * 10)) {
+          const source = ctx.context.index.getNode(rel.from);
+          Eif (source) {
+            explanation.dependents.push({
+              type: rel.type,
+              source: source.properties.name || source.properties.path || source.id,
+            });
+          }
+        }
+ 
+        return ctx.formatSuccess(explanation, profile);
+      } catch (error) {
+        return ctx.errorEnvelope("CODE_EXPLAIN_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "find_pattern",
+    category: "code",
+    description: "Find architectural patterns or violations in code",
+    inputShape: {
+      pattern: z.string().describe("Pattern to search for"),
+      type: z
+        .enum(["pattern", "violation", "unused", "circular"])
+        .default("pattern")
+        .describe("Pattern type"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { pattern, type = "pattern", profile = "compact" } = args;
+ 
+      const archEngine = ctx.engines.arch as
+        | {
+            validate: () => Promise<{ violations: unknown[] }>;
+          }
+        | undefined;
+ 
+      try {
+        const results: any = {
+          pattern,
+          type,
+          matches: [] as any[],
+        };
+ 
+        Iif (type === "violation") {
+          if (!archEngine) {
+            return "Architecture engine not initialized";
+          }
+          const result = await archEngine.validate();
+          results.matches = result.violations.slice(0, 10);
+        I} else if (type === "unused") {
+          const files = ctx.context.index.getNodesByType("FILE");
+          for (const file of files) {
+            const rels = ctx.context.index.getRelationshipsFrom(file.id);
+            if (rels.length === 0) {
+              results.matches.push({
+                path: file.properties.path,
+                reason: "No incoming or outgoing relationships",
+              });
+            }
+          }
+        } else if (type === "circular") {
+          const { projectId } = ctx.getActiveProjectContext();
+          const allFiles = ctx.context.index.getNodesByType("FILE");
+          let files = allFiles.filter((node: any) => {
+            const nodeProjectId = String(node.properties.projectId || "");
+            Iif (!projectId) return true;
+            Iif (!nodeProjectId) {
+              if (node.id.startsWith(`${projectId}:`)) {
+                return true;
+              }
+              return true;
+            }
+            return nodeProjectId === projectId;
+          });
+ 
+          Eif (!files.length) {
+            files = allFiles;
+          }
+ 
+          const fileIds = new Set(files.map((f: any) => f.id));
+          const adjacency = new Map<string, Set<string>>();
+ 
+          for (const file of files) {
+            const targets = new Set<string>();
+            const importRels = ctx.context.index
+              .getRelationshipsFrom(file.id)
+              .filter((rel: any) => rel.type === "IMPORTS");
+ 
+            for (const importRel of importRels) {
+              const directTarget = ctx.context.index.getNode(importRel.to);
+              Iif (
+                directTarget?.type === "FILE" &&
+                fileIds.has(directTarget.id) &&
+                directTarget.id !== file.id
+              ) {
+                targets.add(directTarget.id);
+              }
+ 
+              const refs = ctx.context.index
+                .getRelationshipsFrom(importRel.to)
+                .filter((rel: any) => rel.type === "REFERENCES");
+              for (const ref of refs) {
+                const targetFile = ctx.context.index.getNode(ref.to);
+                Eif (
+                  targetFile?.type === "FILE" &&
+                  fileIds.has(targetFile.id) &&
+                  targetFile.id !== file.id
+                ) {
+                  targets.add(targetFile.id);
+                }
+              }
+            }
+ 
+            adjacency.set(file.id, targets);
+          }
+ 
+          const cycles: string[][] = [];
+          const seenCycles = new Set<string>();
+          const tempVisited = new Set<string>();
+          const permVisited = new Set<string>();
+          const stack: string[] = [];
+ 
+          const canonicalizeCycle = (cycle: string[]): string => {
+            const normalized = cycle.slice(0, -1);
+            Iif (!normalized.length) return "";
+            let best = normalized;
+            for (let i = 1; i < normalized.length; i++) {
+              const rotated = [...normalized.slice(i), ...normalized.slice(0, i)];
+              Iif (rotated.join("|") < best.join("|")) {
+                best = rotated;
+              }
+            }
+            return best.join("|");
+          };
+ 
+          const visit = (nodeId: string): void => {
+            Iif (permVisited.has(nodeId)) return;
+            tempVisited.add(nodeId);
+            stack.push(nodeId);
+ 
+            const neighbors = adjacency.get(nodeId) || new Set<string>();
+            for (const nextId of neighbors) {
+              if (!tempVisited.has(nextId) && !permVisited.has(nextId)) {
+                visit(nextId);
+                continue;
+              }
+ 
+              Eif (tempVisited.has(nextId)) {
+                const start = stack.indexOf(nextId);
+                Eif (start >= 0) {
+                  const cycle = [...stack.slice(start), nextId];
+                  const key = canonicalizeCycle(cycle);
+                  Eif (key && !seenCycles.has(key)) {
+                    seenCycles.add(key);
+                    cycles.push(cycle);
+                  }
+                }
+              }
+            }
+ 
+            stack.pop();
+            tempVisited.delete(nodeId);
+            permVisited.add(nodeId);
+          };
+ 
+          for (const file of files) {
+            if (!permVisited.has(file.id)) {
+              visit(file.id);
+            }
+          }
+ 
+          results.matches = cycles.slice(0, 20).map((cycle) => ({
+            cycle: cycle.map((id) => {
+              const node = ctx.context.index.getNode(id);
+              return String(node?.properties.path || id);
+            }),
+            length: Math.max(1, cycle.length - 1),
+          }));
+ 
+          Iif (!results.matches.length && !files.length && ctx.context.memgraph.isConnected()) {
+            const { projectId: pid } = ctx.getActiveProjectContext();
+            const cypherCycles = await ctx.context.memgraph.executeCypher(
+              `MATCH (a:FILE)-[:IMPORTS]->(:IMPORT)-[:REFERENCES]->(b:FILE)
+                     -[:IMPORTS]->(:IMPORT)-[:REFERENCES]->(a)
+               WHERE a.projectId = $projectId
+                 AND b.projectId = $projectId
+                 AND id(a) < id(b)
+               RETURN coalesce(a.relativePath, a.path, a.id) AS fileA,
+                      coalesce(b.relativePath, b.path, b.id) AS fileB
+               LIMIT 20`,
+              { projectId: pid },
+            );
+            if (cypherCycles.data?.length) {
+              results.matches = cypherCycles.data.map((row: any) => ({
+                cycle: [String(row.fileA), String(row.fileB), String(row.fileA)],
+                length: 2,
+                source: "cypher",
+              }));
+            }
+          }
+ 
+          Iif (!results.matches.length) {
+            results.matches.push({
+              status: "none-found",
+              note: files.length
+                ? "No circular dependencies detected in FILE import graph"
+                : "In-memory index is empty — run graph_rebuild then retry for full DFS analysis",
+            });
+          }
+        } else {
+          if (ctx.context.memgraph.isConnected()) {
+            const { projectId } = ctx.getActiveProjectContext();
+            const searchResult = await ctx.context.memgraph.executeCypher(
+              `MATCH (n)
+               WHERE n.projectId = $projectId
+                 AND (n:FUNCTION OR n:CLASS OR n:FILE)
+                 AND (
+                   toLower(coalesce(n.name, '')) CONTAINS toLower($pattern)
+                   OR toLower(coalesce(n.path, '')) CONTAINS toLower($pattern)
+                 )
+               RETURN labels(n)[0] AS type,
+                      coalesce(n.name, n.path, n.id) AS name,
+                      coalesce(n.relativePath, n.path, '') AS location
+               LIMIT 20`,
+              { projectId, pattern: String(pattern || "") },
+            );
+            results.matches = (searchResult.data || []).map((row: any) => ({
+              type: String(row.type || ""),
+              name: String(row.name || ""),
+              location: String(row.location || ""),
+            }));
+          } else E{
+            const allNodes = [
+              ...ctx.context.index.getNodesByType("FUNCTION"),
+              ...ctx.context.index.getNodesByType("CLASS"),
+              ...ctx.context.index.getNodesByType("FILE"),
+            ];
+            const lp = String(pattern || "").toLowerCase();
+            results.matches = allNodes
+              .filter((n: any) => {
+                const name = String(n.properties.name || n.properties.path || n.id);
+                return name.toLowerCase().includes(lp);
+              })
+              .slice(0, 20)
+              .map((n: any) => ({
+                type: n.type,
+                name: String(n.properties.name || n.properties.path || n.id),
+                location: String(n.properties.relativePath || n.properties.path || ""),
+              }));
+          }
+        }
+ 
+        return ctx.formatSuccess(results, profile);
+      } catch (error) {
+        return ctx.errorEnvelope("PATTERN_SEARCH_FAILED", String(error), true);
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/core-graph-tools.ts.html b/coverage/lcov-report/src/tools/handlers/core-graph-tools.ts.html new file mode 100644 index 0000000..611c831 --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/core-graph-tools.ts.html @@ -0,0 +1,3031 @@ + + + + + + Code coverage report for src/tools/handlers/core-graph-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers core-graph-tools.ts

+
+ +
+ 80.09% + Statements + 165/206 +
+ + +
+ 69.23% + Branches + 162/234 +
+ + +
+ 82.6% + Functions + 19/23 +
+ + +
+ 80.19% + Lines + 162/202 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +6x +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +1x +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +13x +  +13x +  +  +  +  +  +  +  +  +  +  +13x +  +13x +13x +13x +  +13x +  +10x +  +10x +  +  +  +  +  +  +3x +1x +  +1x +  +  +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +2x +2x +  +  +  +13x +  +  +  +  +  +  +  +  +13x +13x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +4x +4x +  +  +  +  +  +  +  +4x +4x +  +4x +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +4x +4x +  +4x +3x +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +4x +  +  +  +4x +3x +  +  +  +  +  +3x +2x +2x +  +  +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +3x +3x +3x +  +  +  +  +3x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +1x +1x +1x +  +  +1x +1x +  +  +1x +  +  +4x +  +4x +3x +  +  +  +  +4x +  +  +  +3x +3x +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +15x +15x +15x +  +15x +  +15x +  +  +  +  +1x +  +  +  +  +  +  +  +14x +  +14x +  +  +  +  +  +  +  +  +14x +  +  +  +  +  +  +  +  +14x +14x +  +14x +  +14x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +6x +  +  +  +  +  +  +6x +6x +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +6x +6x +6x +6x +6x +  +6x +  +6x +6x +6x +6x +6x +  +6x +6x +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +6x +6x +  +6x +  +  +  +  +  +  +6x +6x +6x +  +  +6x +  +6x +6x +2x +  +  +  +6x +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +3x +3x +  +3x +  +  +  +3x +  +9x +9x +  +  +3x +  +  +  +  +  +  +  +3x +3x +1x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +2x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +3x +  +  +  +  +  +  +  +  +2x +3x +3x +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file tools/handlers/core-graph-tools
+ * @description Graph tool definitions — graph_query, graph_rebuild, graph_set_workspace, graph_health, diff_since.
+ */
+ 
+import * as fs from "fs";
+import * as z from "zod";
+import * as env from "../../env.js";
+import { generateSecureId } from "../../utils/validation.js";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+import { logger } from "../../utils/logger.js";
+ 
+/**
+ * Derives coarse label hints for global community search fallback queries.
+ */
+function deriveLabelHints(query: string): string[] {
+  const raw = query.toLowerCase();
+  const hints = ["tools", "engines", "graph", "parsers", "vector", "config"];
+  return hints.filter((hint) => raw.includes(hint));
+}
+ 
+/**
+ * Filters retrieval rows using temporal validity windows.
+ */
+function filterTemporalRows(
+  ctx: HandlerBridge,
+  rows: Array<{ nodeId?: string }>,
+  asOfTs?: number | null,
+): Array<{ nodeId?: string }> {
+  Eif (asOfTs === null || asOfTs === undefined) {
+    return rows;
+  }
+ 
+  return rows.filter((row) => {
+    if (!row.nodeId) {
+      return true;
+    }
+ 
+    const node = ctx.context.index.getNode(row.nodeId);
+    const validFrom = Number(node?.properties?.validFrom);
+    const validToRaw = node?.properties?.validTo;
+    const validTo =
+      validToRaw === null || validToRaw === undefined ? undefined : Number(validToRaw);
+ 
+    if (!Number.isFinite(validFrom)) {
+      return true;
+    }
+ 
+    return (
+      validFrom <= asOfTs &&
+      (!Number.isFinite(validTo) || (validTo !== undefined && validTo > asOfTs))
+    );
+  });
+}
+ 
+/**
+ * Resolves global community candidates used by graph query hybrid/global modes.
+ */
+async function fetchGlobalCommunityRows(
+  ctx: HandlerBridge,
+  query: string,
+  projectId: string,
+  limit: number,
+): Promise<any[]> {
+  const keywordHint = query
+    .toLowerCase()
+    .split(/[^a-z0-9_]+/)
+    .find((token) => token.length >= 4);
+ 
+  const params: Record<string, unknown> = {
+    projectId,
+    limit,
+    keywordHint: keywordHint || null,
+    labels: deriveLabelHints(query),
+  };
+ 
+  const scoped = await ctx.context.memgraph.executeCypher(
+    `MATCH (c:COMMUNITY {projectId: $projectId})
+     WHERE ($keywordHint IS NOT NULL AND toLower(c.summary) CONTAINS $keywordHint)
+        OR toLower(c.label) IN $labels
+     RETURN c.id AS id, c.label AS label, c.summary AS summary, c.memberCount AS memberCount
+     ORDER BY c.memberCount DESC
+     LIMIT $limit`,
+    params,
+  );
+ 
+  Eif (scoped.data.length > 0) {
+    return scoped.data;
+  }
+ 
+  const fallback = await ctx.context.memgraph.executeCypher(
+    `MATCH (c:COMMUNITY {projectId: $projectId})
+     RETURN c.id AS id, c.label AS label, c.summary AS summary, c.memberCount AS memberCount
+     ORDER BY c.memberCount DESC
+     LIMIT $limit`,
+    { projectId, limit },
+  );
+ 
+  return fallback.data;
+}
+ 
+/**
+ * Canonical list of core tool definitions consumed by split category modules.
+ */
+ 
+export const coreGraphToolDefinitions: ToolDefinition[] = [
+  {
+    name: "graph_query",
+    category: "graph",
+    description: "Execute Cypher or natural language query against the code graph",
+    inputShape: {
+      query: z.string().describe("Cypher or natural language query"),
+      language: z.enum(["cypher", "natural"]).default("natural").describe("Query language"),
+      mode: z
+        .enum(["local", "global", "hybrid"])
+        .default("local")
+        .describe("Query mode for natural language"),
+      limit: z.number().default(100).describe("Result limit"),
+      asOf: z
+        .string()
+        .optional()
+        .describe("Optional ISO timestamp or epoch ms for temporal query mode"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        query,
+        language = "natural",
+        limit = 100,
+        profile = "compact",
+        asOf,
+        mode = "local",
+      } = args;
+ 
+      const hybridRetriever = ctx.engines.hybrid as
+        | {
+            retrieve: (args: {
+              query: string;
+              projectId: string;
+              limit: number;
+              mode: "hybrid";
+            }) => Promise<Array<{ nodeId?: string }>>;
+          }
+        | undefined;
+ 
+      try {
+        let result;
+        const { projectId, workspaceRoot } = ctx.getActiveProjectContext();
+        const asOfTs = ctx.toEpochMillis(asOf);
+        const queryMode = mode === "global" || mode === "hybrid" ? mode : "local";
+ 
+        if (language === "cypher") {
+          const cypherQuery =
+            asOfTs !== null ? (ctx as any).applyTemporalFilterToCypher(query) : query;
+ 
+          result =
+            asOfTs !== null
+              ? await ctx.context.memgraph.executeCypher(cypherQuery, {
+                  asOfTs,
+                })
+              : await ctx.context.memgraph.executeCypher(cypherQuery);
+        } else {
+          if (queryMode === "global" || queryMode === "hybrid") {
+            const globalRows = await fetchGlobalCommunityRows(ctx, query, projectId, limit);
+ 
+            Iif (queryMode === "global") {
+              result = { data: globalRows };
+            } else {
+              const localResults = await hybridRetriever!.retrieve({
+                query,
+                projectId,
+                limit,
+                mode: "hybrid",
+              });
+              const filteredLocal = filterTemporalRows(ctx, localResults, asOfTs);
+              result = {
+                data: [
+                  {
+                    section: "global",
+                    communities: globalRows,
+                  },
+                  {
+                    section: "local",
+                    results: filteredLocal,
+                  },
+                ],
+              };
+            }
+          } else {
+            const localResults = await hybridRetriever!.retrieve({
+              query,
+              projectId,
+              limit,
+              mode: "hybrid",
+            });
+            const filteredLocal = filterTemporalRows(ctx, localResults, asOfTs);
+            result = { data: filteredLocal };
+          }
+        }
+ 
+        Iif (result.error) {
+          return ctx.errorEnvelope(
+            "GRAPH_QUERY_FAILED",
+            result.error,
+            true,
+            "Try using language='cypher' with an explicit query.",
+          );
+        }
+ 
+        const limited = result.data.slice(0, limit);
+        return ctx.formatSuccess(
+          {
+            intent: language === "natural" ? (ctx as any).classifyIntent(query) : "cypher",
+            mode: queryMode,
+            projectId,
+            workspaceRoot,
+            asOf: asOfTs,
+            count: limited.length,
+            results: limited,
+          },
+          profile,
+          `Query returned ${limited.length} row(s).`,
+          "graph_query",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("GRAPH_QUERY_EXCEPTION", String(error), true);
+      }
+    },
+  },
+  {
+    name: "graph_rebuild",
+    category: "graph",
+    description: "Rebuild code graph from source",
+    inputShape: {
+      mode: z.enum(["full", "incremental"]).default("incremental").describe("Build mode"),
+      verbose: z.boolean().default(false).describe("Verbose output"),
+      workspaceRoot: z.string().optional().describe("Workspace root path (absolute preferred)"),
+      workspacePath: z.string().optional().describe("Alias for workspaceRoot"),
+      sourceDir: z
+        .string()
+        .optional()
+        .describe("Source directory path (absolute or relative to workspace root)"),
+      projectId: z.string().optional().describe("Project namespace for graph isolation"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+      indexDocs: z
+        .boolean()
+        .default(true)
+        .describe(
+          "Index markdown documentation files (READMEs, ADRs) during rebuild (default: true). Set false to skip docs indexing.",
+        ),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { mode = "incremental", verbose = false, profile = "compact", indexDocs = true } = args;
+ 
+      const orchestrator = ctx.engines.orchestrator as
+        | {
+            build: (args: Record<string, unknown>) => Promise<{
+              success: boolean;
+              duration: number;
+              filesProcessed: number;
+              nodesCreated: number;
+              relationshipsCreated: number;
+              filesChanged: number;
+              warnings: string[];
+              errors: string[];
+            }>;
+          }
+        | undefined;
+ 
+      const coordinationEngine = ctx.engines.coordination as
+        | {
+            invalidateStaleClaims: (projectId: string) => Promise<number>;
+          }
+        | undefined;
+ 
+      const embeddingEngine = ctx.engines.embedding as
+        | {
+            generateAllEmbeddings: () => Promise<{
+              functions: number;
+              classes: number;
+              files: number;
+            }>;
+            storeInQdrant: () => Promise<void>;
+          }
+        | undefined;
+ 
+      const communityDetector = ctx.engines.community as
+        | {
+            run: (projectId: string) => Promise<{
+              mode: string;
+              communities: number;
+              members: number;
+            }>;
+          }
+        | undefined;
+ 
+      const hybridRetriever = ctx.engines.hybrid as
+        | {
+            ensureBM25Index: () => Promise<{ created?: boolean; error?: string } | undefined>;
+          }
+        | undefined;
+ 
+      try {
+        Iif (!orchestrator) {
+          return ctx.errorEnvelope(
+            "GRAPH_ORCHESTRATOR_UNAVAILABLE",
+            "Graph orchestrator not initialized",
+            true,
+          );
+        }
+ 
+        let resolvedContext = ctx.resolveProjectContext(args || {});
+        const adapted = (ctx as any).adaptWorkspaceForRuntime(resolvedContext);
+        const explicitWorkspaceProvided =
+          typeof args?.workspaceRoot === "string" && args.workspaceRoot.trim().length > 0;
+ 
+        Iif (
+          adapted.usedFallback &&
+          explicitWorkspaceProvided &&
+          !(ctx as any).runtimePathFallbackAllowed()
+        ) {
+          return ctx.errorEnvelope(
+            "WORKSPACE_PATH_SANDBOXED",
+            `Requested workspaceRoot is not accessible from this runtime: ${resolvedContext.workspaceRoot}`,
+            true,
+            "Mount the target project into the container (e.g. LXRAG_TARGET_WORKSPACE) and restart docker-compose, or set LXRAG_ALLOW_RUNTIME_PATH_FALLBACK=true to force fallback to mounted workspace.",
+          );
+        }
+ 
+        resolvedContext = adapted.context;
+        (ctx as any).setActiveProjectContext(resolvedContext);
+        const { workspaceRoot, sourceDir, projectId } = resolvedContext;
+        const txTimestamp = Date.now();
+        const txId = generateSecureId("tx", 4);
+ 
+        if (ctx.context.memgraph.isConnected()) {
+          await ctx.context.memgraph.executeCypher(
+            `CREATE (tx:GRAPH_TX {id: $id, projectId: $projectId, type: $type, timestamp: $timestamp, mode: $mode, sourceDir: $sourceDir})`,
+            {
+              id: txId,
+              projectId,
+              type: mode === "full" ? "full_rebuild" : "incremental_rebuild",
+              timestamp: txTimestamp,
+              mode,
+              sourceDir,
+            },
+          );
+        }
+ 
+        Iif (!fs.existsSync(workspaceRoot)) {
+          return ctx.errorEnvelope(
+            "WORKSPACE_NOT_FOUND",
+            `Workspace root does not exist: ${workspaceRoot}`,
+            true,
+            "Call graph_set_workspace first with a valid path.",
+          );
+        }
+ 
+        Iif (!fs.existsSync(sourceDir)) {
+          return ctx.errorEnvelope(
+            "SOURCE_DIR_NOT_FOUND",
+            `Source directory does not exist: ${sourceDir}`,
+            true,
+            "Provide sourceDir in graph_rebuild or graph_set_workspace.",
+          );
+        }
+ 
+        const postBuild = async (result: {
+          success: boolean;
+          duration: number;
+          filesProcessed: number;
+          nodesCreated: number;
+          relationshipsCreated: number;
+          filesChanged: number;
+          warnings: string[];
+          errors: string[];
+        }) => {
+          logger.error(
+            `[graph_rebuild] ${mode} build completed in ${result.duration}ms (${result.filesProcessed} files, ${result.nodesCreated} nodes, ${result.errors.length} errors, ${result.warnings.length} warnings) for project ${projectId}`,
+          );
+ 
+          const invalidated = await coordinationEngine!.invalidateStaleClaims(projectId);
+          Iif (invalidated > 0) {
+            logger.error(
+              `[coordination] Invalidated ${invalidated} stale claim(s) post-rebuild for project ${projectId}`,
+            );
+          }
+ 
+          if (mode === "incremental") {
+            (ctx as any).setProjectEmbeddingsReady(projectId, false);
+            logger.error(
+              `[Phase2a] Embeddings flag reset for incremental rebuild of project ${projectId}`,
+            );
+          E} else if (mode === "full") {
+            try {
+              const generated = await embeddingEngine?.generateAllEmbeddings();
+              Iif (generated && generated.functions + generated.classes + generated.files > 0) {
+                await embeddingEngine?.storeInQdrant();
+                (ctx as any).setProjectEmbeddingsReady(projectId, true);
+                logger.error(
+                  `[Phase2b] Embeddings auto-generated for full rebuild: ${generated.functions} functions, ${generated.classes} classes, ${generated.files} files for project ${projectId}`,
+                );
+              }
+            } catch (embeddingError) {
+              logger.error(
+                `[Phase2b] Embedding generation failed during full rebuild for project ${projectId}:`,
+                embeddingError,
+              );
+            }
+ 
+            const communityRun = await communityDetector!.run(projectId);
+            logger.error(
+              `[community] ${communityRun.mode}: ${communityRun.communities} communities across ${communityRun.members} member node(s) for project ${projectId}`,
+            );
+          }
+ 
+          const bm25Result = await hybridRetriever?.ensureBM25Index();
+          if (bm25Result?.created) {
+            logger.error(`[bm25] Created text_search symbol_index for project ${projectId}`);
+          E} else if (bm25Result?.error) {
+            logger.error(`[bm25] symbol_index unavailable: ${bm25Result.error}`);
+          }
+ 
+          return result;
+        };
+ 
+        const buildPromise = orchestrator
+          .build({
+            mode,
+            verbose,
+            workspaceRoot,
+            projectId,
+            sourceDir,
+            txId,
+            txTimestamp,
+            indexDocs,
+            exclude: ["node_modules", "dist", ".next", ".lxrag", "__tests__", "coverage", ".git"],
+          })
+          .then(postBuild)
+          .catch((err) => {
+            const context = `mode=${mode}, projectId=${projectId}`;
+            (ctx as any).recordBuildError(projectId, err, context);
+ 
+            const errorMsg = err instanceof Error ? err.message : String(err);
+            const stack = err instanceof Error ? err.stack : "";
+            logger.error(
+              `[Phase4.5] Background build failed for project ${projectId} (${mode}): ${errorMsg}`,
+            );
+            Eif (stack) {
+              logger.error(`[Phase4.5] Stack trace: ${stack.substring(0, 500)}`);
+            }
+ 
+            throw err;
+          });
+ 
+        const thresholdMs = Math.max(1000, env.LXRAG_SYNC_REBUILD_THRESHOLD_MS);
+ 
+        const raceResult = await Promise.race([
+          buildPromise.then((result) => ({
+            status: "completed" as const,
+            result,
+          })),
+          new Promise<{ status: "queued" }>((resolve) =>
+            setTimeout(() => resolve({ status: "queued" }), thresholdMs),
+          ),
+        ]);
+ 
+        (ctx as any).lastGraphRebuildAt = new Date().toISOString();
+        (ctx as any).lastGraphRebuildMode = mode;
+ 
+        Eif (raceResult.status === "completed") {
+          return ctx.formatSuccess(
+            {
+              success: raceResult.result.success,
+              status: "COMPLETED",
+              mode,
+              verbose,
+              sourceDir,
+              workspaceRoot,
+              projectId,
+              txId,
+              txTimestamp,
+              durationMs: raceResult.result.duration,
+              filesProcessed: raceResult.result.filesProcessed,
+              nodesCreated: raceResult.result.nodesCreated,
+              relationshipsCreated: raceResult.result.relationshipsCreated,
+              filesChanged: raceResult.result.filesChanged,
+              warnings: raceResult.result.warnings,
+              errors: raceResult.result.errors,
+              runtimePathFallback: adapted.usedFallback,
+              runtimePathFallbackReason: adapted.fallbackReason || null,
+              message: `Graph rebuild ${mode} mode completed in ${raceResult.result.duration}ms.`,
+            },
+            profile,
+            `Graph rebuild completed in ${raceResult.result.duration}ms for project ${projectId}.`,
+            "graph_rebuild",
+          );
+        }
+ 
+        buildPromise.catch(() => {
+          // Background errors are already captured above.
+        });
+ 
+        return ctx.formatSuccess(
+          {
+            success: true,
+            status: "QUEUED",
+            mode,
+            verbose,
+            sourceDir,
+            workspaceRoot,
+            projectId,
+            txId,
+            txTimestamp,
+            syncThresholdMs: thresholdMs,
+            pollIntervalMs: 2000,
+            completionCriteria: {
+              driftDetected: false,
+              embeddingsGeneratedGreaterThan: 0,
+            },
+            runtimePathFallback: adapted.usedFallback,
+            runtimePathFallbackReason: adapted.fallbackReason || null,
+            message: `Graph rebuild ${mode} mode initiated. Processing ${mode === "full" ? "all" : "changed"} files in background...`,
+            note: "Use graph_health to poll until cache.driftDetected=false and embeddings.generated>0.",
+          },
+          profile,
+          `Graph rebuild queued in ${mode} mode for project ${projectId}.`,
+          "graph_rebuild",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "GRAPH_REBUILD_FAILED",
+          `Graph rebuild failed to start: ${String(error)}`,
+          true,
+        );
+      }
+    },
+  },
+  {
+    name: "graph_set_workspace",
+    category: "graph",
+    description: "Set active workspace/project context for subsequent graph tools",
+    inputShape: {
+      workspaceRoot: z.string().optional().describe("Workspace root path (absolute preferred)"),
+      workspacePath: z.string().optional().describe("Alias for workspaceRoot"),
+      sourceDir: z
+        .string()
+        .optional()
+        .describe("Source directory path (absolute or relative to workspace root)"),
+      projectId: z.string().optional().describe("Project namespace for graph isolation"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { profile = "compact" } = args || {};
+ 
+      try {
+        let nextContext = ctx.resolveProjectContext(args || {});
+        const adapted = (ctx as any).adaptWorkspaceForRuntime(nextContext);
+        const explicitWorkspaceProvided =
+          typeof args?.workspaceRoot === "string" && args.workspaceRoot.trim().length > 0;
+ 
+        if (
+          adapted.usedFallback &&
+          explicitWorkspaceProvided &&
+          !(ctx as any).runtimePathFallbackAllowed()
+        ) {
+          return ctx.errorEnvelope(
+            "WORKSPACE_PATH_SANDBOXED",
+            `Requested workspaceRoot is not accessible from this runtime: ${nextContext.workspaceRoot}`,
+            true,
+            "Mount the target project into the container (e.g. LXRAG_TARGET_WORKSPACE) and restart docker-compose, or set LXRAG_ALLOW_RUNTIME_PATH_FALLBACK=true to force fallback to mounted workspace.",
+          );
+        }
+ 
+        nextContext = adapted.context;
+ 
+        Iif (!fs.existsSync(nextContext.workspaceRoot)) {
+          return ctx.errorEnvelope(
+            "WORKSPACE_NOT_FOUND",
+            `Workspace root does not exist: ${nextContext.workspaceRoot}`,
+            true,
+            "Pass an existing absolute path as workspaceRoot (or workspacePath).",
+          );
+        }
+ 
+        Iif (!fs.existsSync(nextContext.sourceDir)) {
+          return ctx.errorEnvelope(
+            "SOURCE_DIR_NOT_FOUND",
+            `Source directory does not exist: ${nextContext.sourceDir}`,
+            true,
+            "Pass sourceDir explicitly if your source folder is not <workspaceRoot>/src.",
+          );
+        }
+ 
+        (ctx as any).setActiveProjectContext(nextContext);
+        await (ctx as any).startActiveWatcher(nextContext);
+ 
+        const watcher = (ctx as any).getActiveWatcher();
+ 
+        return ctx.formatSuccess(
+          {
+            success: true,
+            projectContext: ctx.getActiveProjectContext(),
+            watcherEnabled: (ctx as any).watcherEnabledForRuntime(),
+            watcherState: watcher?.state || "not_started",
+            pendingChanges: watcher?.pendingChanges ?? 0,
+            runtimePathFallback: adapted.usedFallback,
+            runtimePathFallbackReason: adapted.fallbackReason || null,
+            message: "Workspace context updated. Subsequent graph tools will use this project.",
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "SET_WORKSPACE_FAILED",
+          String(error),
+          true,
+          "Retry with workspaceRoot and sourceDir values.",
+        );
+      }
+    },
+  },
+  {
+    name: "graph_health",
+    category: "graph",
+    description: "Report graph/index/vector health and freshness status",
+    inputShape: {
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const profile = args?.profile || "compact";
+ 
+      const hybridRetriever = ctx.engines.hybrid as
+        | {
+            bm25IndexKnownToExist?: boolean;
+            bm25Mode?: string;
+          }
+        | undefined;
+ 
+      try {
+        const { workspaceRoot, sourceDir, projectId } = ctx.getActiveProjectContext();
+ 
+        const healthStatsResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (n {projectId: $projectId})
+           WITH count(n) AS totalNodes
+           MATCH (n1 {projectId: $projectId})-[r]->(n2 {projectId: $projectId})
+           WITH totalNodes, count(r) AS totalRels
+           MATCH (f:FILE {projectId: $projectId})
+           WITH totalNodes, totalRels, count(f) AS fileCount
+           MATCH (fc:FUNCTION {projectId: $projectId})
+           WITH totalNodes, totalRels, fileCount, count(fc) AS funcCount
+           MATCH (c:CLASS {projectId: $projectId})
+           WITH totalNodes, totalRels, fileCount, funcCount, count(c) AS classCount
+           MATCH (imp:IMPORT {projectId: $projectId})
+           RETURN totalNodes, totalRels, fileCount, funcCount, classCount, count(imp) AS importCount`,
+          { projectId },
+        );
+ 
+        const stats = healthStatsResult.data?.[0] || {};
+        const memgraphNodeCount = (ctx as any).toSafeNumber(stats.totalNodes) ?? 0;
+        const memgraphRelCount = (ctx as any).toSafeNumber(stats.totalRels) ?? 0;
+        const memgraphFileCount = (ctx as any).toSafeNumber(stats.fileCount) ?? 0;
+        const memgraphFuncCount = (ctx as any).toSafeNumber(stats.funcCount) ?? 0;
+        const memgraphClassCount = (ctx as any).toSafeNumber(stats.classCount) ?? 0;
+        const memgraphImportCount = (ctx as any).toSafeNumber(stats.importCount) ?? 0;
+        const memgraphIndexableCount =
+          memgraphFileCount + memgraphFuncCount + memgraphClassCount + memgraphImportCount;
+ 
+        const indexStats = ctx.context.index.getStatistics();
+        const indexFileCount = ctx.context.index.getNodesByType("FILE").length;
+        const indexFuncCount = ctx.context.index.getNodesByType("FUNCTION").length;
+        const indexClassCount = ctx.context.index.getNodesByType("CLASS").length;
+        const indexedSymbols = indexFileCount + indexFuncCount + indexClassCount;
+ 
+        let embeddingCount = 0;
+        Iif ((ctx.engines.qdrant as any)?.isConnected?.()) {
+          try {
+            const [fnColl, clsColl, fileColl] = await Promise.all([
+              (ctx.engines.qdrant as any).getCollection("functions"),
+              (ctx.engines.qdrant as any).getCollection("classes"),
+              (ctx.engines.qdrant as any).getCollection("files"),
+            ]);
+            embeddingCount =
+              (fnColl?.pointCount ?? 0) + (clsColl?.pointCount ?? 0) + (fileColl?.pointCount ?? 0);
+          } catch {
+            // Fall back to in-memory count below.
+          }
+        }
+        Eif (embeddingCount === 0) {
+          embeddingCount =
+            ((ctx.engines.embedding as any)
+              ?.getAllEmbeddings()
+              .filter((e: any) => e.projectId === projectId).length as number) || 0;
+        }
+        const embeddingCoverage =
+          memgraphFuncCount + memgraphClassCount + memgraphFileCount > 0
+            ? Number(
+                (
+                  embeddingCount /
+                  (memgraphFuncCount + memgraphClassCount + memgraphFileCount)
+                ).toFixed(3),
+              )
+            : 0;
+ 
+        const indexDrift = Math.abs(indexStats.totalNodes - memgraphIndexableCount) > 3;
+        const embeddingDrift = embeddingCount < indexedSymbols;
+ 
+        const txMetadataResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (tx:GRAPH_TX {projectId: $projectId})
+           WITH tx ORDER BY tx.timestamp DESC
+           WITH collect({id: tx.id, timestamp: tx.timestamp})[0] AS latestTx, count(*) AS txCount
+           RETURN latestTx, txCount`,
+          { projectId },
+        );
+        const txMetadata = txMetadataResult.data?.[0] || {};
+        const latestTxRow = txMetadata.latestTx || {};
+        const txCountRow = {
+          txCount: (ctx as any).toSafeNumber(txMetadata.txCount) ?? 0,
+        };
+        const watcher = (ctx as any).getActiveWatcher();
+ 
+        const recommendations: string[] = [];
+        if (indexDrift) {
+          recommendations.push(
+            "Index is out of sync with Memgraph - run graph_rebuild to synchronize",
+          );
+        }
+        Iif (embeddingDrift && (ctx as any).isProjectEmbeddingsReady(projectId)) {
+          recommendations.push(
+            "Some entities don't have embeddings - run semantic_search or graph_rebuild to generate them",
+          );
+        }
+ 
+        return ctx.formatSuccess(
+          {
+            status: indexDrift ? "drift_detected" : "ok",
+            projectId,
+            workspaceRoot,
+            sourceDir,
+            memgraphConnected: ctx.context.memgraph.isConnected(),
+            qdrantConnected: (ctx.engines.qdrant as any)?.isConnected() || false,
+            graphIndex: {
+              totalNodes: memgraphNodeCount,
+              totalRelationships: memgraphRelCount,
+              indexedFiles: memgraphFileCount,
+              indexedFunctions: memgraphFuncCount,
+              indexedClasses: memgraphClassCount,
+            },
+            indexHealth: {
+              driftDetected: indexDrift,
+              memgraphNodes: memgraphNodeCount,
+              memgraphIndexableNodes: memgraphIndexableCount,
+              cachedNodes: indexStats.totalNodes,
+              memgraphRels: memgraphRelCount,
+              cachedRels: indexStats.totalRelationships,
+              recommendation: indexDrift
+                ? "Index out of sync - run graph_rebuild to refresh"
+                : "Index synchronized",
+            },
+            embeddings: {
+              ready: (ctx as any).isProjectEmbeddingsReady(projectId),
+              generated: embeddingCount,
+              coverage: embeddingCoverage,
+              driftDetected: embeddingDrift,
+              recommendation:
+                embeddingCount === 0 &&
+                memgraphFuncCount + memgraphClassCount + memgraphFileCount > 0
+                  ? "No embeddings generated — run graph_rebuild (full mode) to enable semantic search"
+                  : embeddingDrift
+                    ? "Embeddings incomplete - run semantic_search or rebuild to regenerate"
+                    : "Embeddings complete",
+            },
+            retrieval: {
+              bm25IndexExists: hybridRetriever?.bm25IndexKnownToExist ?? false,
+              mode: hybridRetriever?.bm25Mode ?? "not_initialized",
+            },
+            summarizer: {
+              configured: !!env.LXRAG_SUMMARIZER_URL,
+              endpoint: env.LXRAG_SUMMARIZER_URL ? "[configured]" : null,
+            },
+            rebuild: {
+              lastRequestedAt: (ctx as any).lastGraphRebuildAt || null,
+              lastMode: (ctx as any).lastGraphRebuildMode || null,
+              latestTxId: latestTxRow.id ?? null,
+              latestTxTimestamp:
+                (ctx as any).toSafeNumber(latestTxRow.timestamp) ?? latestTxRow.timestamp ?? null,
+              txCount: txCountRow.txCount ?? 0,
+              recentErrors: (ctx as any).getRecentBuildErrors(projectId, 3),
+            },
+            freshness: {
+              staleFileEstimate: null,
+              note: "Use graph_rebuild incremental to refresh changed files.",
+            },
+            pendingChanges: watcher?.pendingChanges ?? 0,
+            watcherState: watcher?.state || "not_started",
+            recommendations,
+          },
+          profile,
+          indexDrift ? "Graph drift detected - see recommendations" : "Graph health is OK.",
+          "graph_health",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("GRAPH_HEALTH_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "diff_since",
+    category: "utility",
+    description: "Summarize temporal graph changes since txId, timestamp, git commit, or agentId",
+    inputShape: {
+      since: z.string().describe("Anchor value: txId, ISO timestamp, git commit SHA, or agentId"),
+      projectId: z
+        .string()
+        .optional()
+        .describe("Optional project override (defaults to active context)"),
+      types: z
+        .array(z.enum(["FILE", "FUNCTION", "CLASS"]))
+        .optional()
+        .describe("Optional node types to include"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { since, types = ["FILE", "FUNCTION", "CLASS"], profile = "compact" } = args || {};
+ 
+      Iif (!since || typeof since !== "string") {
+        return ctx.errorEnvelope(
+          "DIFF_SINCE_INVALID_INPUT",
+          "Field 'since' is required and must be a string.",
+          true,
+          "Provide txId, ISO timestamp, git commit SHA, or agentId.",
+        );
+      }
+ 
+      try {
+        const active = ctx.getActiveProjectContext();
+        const projectId =
+          typeof args?.projectId === "string" && args.projectId.trim().length > 0
+            ? args.projectId
+            : active.projectId;
+ 
+        const normalizedTypes = Array.isArray(types)
+          ? types
+              .map((item) => String(item).toUpperCase())
+              .filter((item) => ["FILE", "FUNCTION", "CLASS"].includes(item))
+          : ["FILE", "FUNCTION", "CLASS"];
+ 
+        Iif (!normalizedTypes.length) {
+          return ctx.errorEnvelope(
+            "DIFF_SINCE_INVALID_TYPES",
+            "Field 'types' must include at least one of FILE, FUNCTION, CLASS.",
+            true,
+          );
+        }
+ 
+        const anchor = await (ctx as any).resolveSinceAnchor(since, projectId);
+        if (!anchor) {
+          return ctx.errorEnvelope(
+            "DIFF_SINCE_ANCHOR_NOT_FOUND",
+            `Unable to resolve 'since' anchor: ${since}`,
+            true,
+            "Use a known txId, ISO timestamp, git commit SHA, or agentId with recorded GRAPH_TX entries.",
+          );
+        }
+ 
+        const txResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (tx:GRAPH_TX {projectId: $projectId})
+           WHERE tx.timestamp >= $sinceTs
+           RETURN tx.id AS id
+           ORDER BY tx.timestamp ASC`,
+          { projectId, sinceTs: anchor.sinceTs },
+        );
+        const txIds = (txResult.data || []).map((row: any) => String(row.id || "")).filter(Boolean);
+ 
+        const addedResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (n)
+           WHERE n.projectId = $projectId
+             AND labels(n)[0] IN $types
+             AND n.validFrom IS NOT NULL
+             AND n.validFrom >= $sinceTs
+           RETURN labels(n)[0] AS type,
+                  n.id AS scip_id,
+                  coalesce(n.path, n.relativePath, '') AS path,
+                  n.name AS symbolName,
+                  n.validFrom AS validFrom,
+                  n.validTo AS validTo
+           ORDER BY n.validFrom DESC
+           LIMIT 500`,
+          { projectId, sinceTs: anchor.sinceTs, types: normalizedTypes },
+        );
+ 
+        const removedResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (n)
+           WHERE n.projectId = $projectId
+             AND labels(n)[0] IN $types
+             AND n.validTo IS NOT NULL
+             AND n.validTo >= $sinceTs
+           RETURN labels(n)[0] AS type,
+                  n.id AS scip_id,
+                  coalesce(n.path, n.relativePath, '') AS path,
+                  n.name AS symbolName,
+                  n.validFrom AS validFrom,
+                  n.validTo AS validTo
+           ORDER BY n.validTo DESC
+           LIMIT 500`,
+          { projectId, sinceTs: anchor.sinceTs, types: normalizedTypes },
+        );
+ 
+        const modifiedResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (newer)
+           WHERE newer.projectId = $projectId
+             AND labels(newer)[0] IN $types
+             AND newer.validFrom IS NOT NULL
+             AND newer.validFrom >= $sinceTs
+           MATCH (older)
+           WHERE older.projectId = $projectId
+             AND labels(older)[0] IN $types
+             AND older.id = newer.id
+             AND older.validTo IS NOT NULL
+             AND older.validTo >= $sinceTs
+           RETURN DISTINCT labels(newer)[0] AS type,
+                  newer.id AS scip_id,
+                  coalesce(newer.path, newer.relativePath, '') AS path,
+                  newer.name AS symbolName,
+                  newer.validFrom AS validFrom,
+                  newer.validTo AS validTo
+           ORDER BY validFrom DESC
+           LIMIT 500`,
+          { projectId, sinceTs: anchor.sinceTs, types: normalizedTypes },
+        );
+ 
+        const mapDelta = (rows: any[]) =>
+          (rows || []).map((row) => ({
+            scip_id: String(row.scip_id || ""),
+            type: String(row.type || "UNKNOWN"),
+            path: String(row.path || ""),
+            symbolName: row.symbolName ? String(row.symbolName) : undefined,
+            validFrom: (ctx as any).toSafeNumber(row.validFrom),
+            validTo: (ctx as any).toSafeNumber(row.validTo) ?? undefined,
+          }));
+ 
+        const added = mapDelta(addedResult.data || []);
+        const removed = mapDelta(removedResult.data || []);
+        const modified = mapDelta(modifiedResult.data || []);
+ 
+        const summary = `${added.length} added, ${removed.length} removed, ${modified.length} modified since ${anchor.anchorValue}.`;
+ 
+        return ctx.formatSuccess(
+          {
+            summary,
+            projectId,
+            since: {
+              input: since,
+              resolvedMode: anchor.mode,
+              resolvedTimestamp: anchor.sinceTs,
+            },
+            added,
+            removed,
+            modified,
+            txIds,
+          },
+          profile,
+          summary,
+          "diff_since",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("DIFF_SINCE_FAILED", String(error), true);
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/core-semantic-tools.ts.html b/coverage/lcov-report/src/tools/handlers/core-semantic-tools.ts.html new file mode 100644 index 0000000..ba604ac --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/core-semantic-tools.ts.html @@ -0,0 +1,1180 @@ + + + + + + Code coverage report for src/tools/handlers/core-semantic-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers core-semantic-tools.ts

+
+ +
+ 88.15% + Statements + 67/76 +
+ + +
+ 74.46% + Branches + 35/47 +
+ + +
+ 93.75% + Functions + 15/16 +
+ + +
+ 88% + Lines + 66/75 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +2x +  +2x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +4x +  +  +1x +1x +4x +4x +4x +2x +  +4x +  +  +1x +2x +  +  +  +  +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +2x +2x +  +2x +1x +  +  +  +  +  +  +1x +2x +2x +2x +6x +  +2x +6x +  +  +2x +  +  +  +  +  +  +6x +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +2x +  +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +2x +  +  +  + 
/**
+ * @file tools/handlers/core-semantic-tools
+ * @description Semantic/code-intelligence tool definitions — semantic_search, find_similar_code, code_clusters, semantic_diff, suggest_tests, context_pack, semantic_slice.
+ */
+ 
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const coreSemanticToolDefinitions: ToolDefinition[] = [
+  {
+    name: "semantic_search",
+    category: "code",
+    description: "Search code semantically using vector similarity",
+    inputShape: {
+      query: z.string().describe("Search query"),
+      type: z.enum(["function", "class", "file"]).optional().describe("Code type to search"),
+      limit: z.number().default(5).describe("Result limit"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { query, type = "function", limit = 5, profile = "compact" } = args;
+ 
+      const embeddingEngine = ctx.engines.embedding as
+        | {
+            findSimilar: (
+              query: string,
+              type: string,
+              limit: number,
+              projectId: string,
+            ) => Promise<
+              Array<{
+                id: string;
+                name: string;
+                type: string;
+                metadata: { path?: string };
+              }>
+            >;
+          }
+        | undefined;
+ 
+      try {
+        await ctx.ensureEmbeddings();
+        const { projectId } = ctx.getActiveProjectContext();
+        const results = await embeddingEngine!.findSimilar(query, type, limit, projectId);
+ 
+        return ctx.formatSuccess(
+          {
+            query,
+            type,
+            count: results.length,
+            results: results.map((item) => ({
+              id: item.id,
+              name: item.name,
+              type: item.type,
+              path: item.metadata.path,
+            })),
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("SEMANTIC_SEARCH_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "find_similar_code",
+    category: "code",
+    description: "Find code similar to a given function or class",
+    inputShape: {
+      elementId: z.string().describe("Code element ID"),
+      threshold: z.number().default(0.7).describe("Similarity threshold (0-1)"),
+      limit: z.number().default(10).describe("Result limit"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { elementId, threshold = 0.7, limit = 10, profile = "compact" } = args;
+ 
+      const embeddingEngine = ctx.engines.embedding as
+        | {
+            findSimilar: (
+              query: string,
+              type: string,
+              limit: number,
+              projectId: string,
+            ) => Promise<
+              Array<{
+                id: string;
+                name: string;
+                type: string;
+                metadata: { path?: string };
+              }>
+            >;
+          }
+        | undefined;
+ 
+      try {
+        await ctx.ensureEmbeddings();
+        const { projectId } = ctx.getActiveProjectContext();
+        const results = await embeddingEngine!.findSimilar(elementId, "function", limit, projectId);
+        const filtered = results.slice(0, limit);
+ 
+        return ctx.formatSuccess(
+          {
+            elementId,
+            threshold,
+            count: filtered.length,
+            similar: filtered.map((item) => ({
+              id: item.id,
+              name: item.name,
+              type: item.type,
+              path: item.metadata.path,
+            })),
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("FIND_SIMILAR_CODE_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "code_clusters",
+    category: "code",
+    description: "Find clusters of related code",
+    inputShape: {
+      type: z.enum(["function", "class", "file"]).describe("Code type to cluster"),
+      count: z.number().default(5).describe("Number of clusters"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { type, count = 5, profile = "compact" } = args;
+ 
+      const embeddingEngine = ctx.engines.embedding as
+        | {
+            getAllEmbeddings: () => Array<{
+              type: string;
+              projectId: string;
+              name: string;
+              metadata: { path?: string };
+            }>;
+          }
+        | undefined;
+ 
+      try {
+        await ctx.ensureEmbeddings();
+        const { projectId } = ctx.getActiveProjectContext();
+        const embeddings = embeddingEngine!
+          .getAllEmbeddings()
+          .filter((item) => item.type === type && item.projectId === projectId)
+          .slice(0, 200);
+ 
+        const clusters: Record<string, string[]> = {};
+        for (const item of embeddings) {
+          const itemPath = item.metadata.path || "unknown";
+          const key = itemPath.split("/").slice(0, 2).join("/") || "root";
+          if (!clusters[key]) {
+            clusters[key] = [];
+          }
+          clusters[key].push(item.name);
+        }
+ 
+        const clusterRows = Object.entries(clusters)
+          .map(([clusterId, names]) => ({
+            clusterId,
+            size: names.length,
+            sample: names.slice(0, 5),
+          }))
+          .sort((a, b) => b.size - a.size)
+          .slice(0, count);
+ 
+        return ctx.formatSuccess(
+          { type, count: clusterRows.length, clusters: clusterRows },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("CODE_CLUSTERS_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "semantic_diff",
+    category: "code",
+    description: "Find semantic differences between code elements",
+    inputShape: {
+      elementId1: z.string().describe("First code element ID"),
+      elementId2: z.string().describe("Second code element ID"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { elementId1, elementId2, profile = "compact" } = args;
+ 
+      try {
+        const left = ctx.resolveElement(elementId1);
+        const right = ctx.resolveElement(elementId2);
+ 
+        if (!left || !right) {
+          return ctx.errorEnvelope(
+            "SEMANTIC_DIFF_ELEMENT_NOT_FOUND",
+            `Could not resolve one or both elements: ${elementId1}, ${elementId2}`,
+            true,
+          );
+        }
+ 
+        const leftProps = left.properties || {};
+        const rightProps = right.properties || {};
+        const leftKeys = new Set(Object.keys(leftProps));
+        const rightKeys = new Set(Object.keys(rightProps));
+        const commonKeys = [...leftKeys].filter((key) => rightKeys.has(key));
+ 
+        const changedKeys = commonKeys.filter(
+          (key) => JSON.stringify(leftProps[key]) !== JSON.stringify(rightProps[key]),
+        );
+ 
+        return ctx.formatSuccess(
+          {
+            left: left.properties.name || left.properties.path || left.id,
+            right: right.properties.name || right.properties.path || right.id,
+            leftType: left.type,
+            rightType: right.type,
+            changedKeys,
+            leftOnlyKeys: [...leftKeys].filter((key) => !rightKeys.has(key)),
+            rightOnlyKeys: [...rightKeys].filter((key) => !leftKeys.has(key)),
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("SEMANTIC_DIFF_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "suggest_tests",
+    category: "test",
+    description: "Suggest tests for a code element based on semantics",
+    inputShape: {
+      elementId: z.string().describe("Code element ID"),
+      limit: z.number().default(5).describe("Number of suggestions"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { elementId, limit = 5, profile = "compact" } = args;
+ 
+      const testEngine = ctx.engines.test as
+        | {
+            selectAffectedTests: (
+              changedFiles: string[],
+              includeIntegration?: boolean,
+              depth?: number,
+            ) => {
+              selectedTests: string[];
+              estimatedTime: number;
+              coverage: unknown;
+            };
+          }
+        | undefined;
+ 
+      try {
+        const resolved = ctx.resolveElement(elementId);
+        const candidatePath =
+          resolved?.properties.path ||
+          resolved?.properties.filePath ||
+          resolved?.properties.relativePath ||
+          (typeof elementId === "string" && elementId.includes("/") ? elementId : undefined);
+ 
+        Iif (!candidatePath) {
+          return ctx.errorEnvelope(
+            "SUGGEST_TESTS_ELEMENT_NOT_FOUND",
+            `Unable to resolve file path for element: ${elementId}`,
+            true,
+          );
+        }
+ 
+        const selection = testEngine!.selectAffectedTests([candidatePath], true, 2);
+        const suggested = selection.selectedTests.slice(0, limit);
+ 
+        return ctx.formatSuccess(
+          {
+            elementId,
+            file: candidatePath,
+            suggestedTests: suggested,
+            estimatedTime: selection.estimatedTime,
+            coverage: selection.coverage,
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("SUGGEST_TESTS_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "context_pack",
+    category: "coordination",
+    description:
+      "Build a single-call task briefing using PPR-ranked retrieval across code, decisions, learnings, and blockers",
+    inputShape: {
+      task: z.string().describe("Task description"),
+      taskId: z.string().optional().describe("Optional task id"),
+      agentId: z.string().optional().describe("Agent identifier"),
+      includeDecisions: z.boolean().default(true).describe("Include decision episodes"),
+      includeEpisodes: z.boolean().default(true).describe("Include recent episodes"),
+      includeLearnings: z.boolean().default(true).describe("Include learnings"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const impl = (ctx as any).core_context_pack_impl;
+      Iif (typeof impl !== "function") {
+        return ctx.errorEnvelope(
+          "TOOL_NOT_IMPLEMENTED",
+          "context_pack implementation is unavailable",
+          true,
+        );
+      }
+      return impl.call(ctx, args);
+    },
+  },
+  {
+    name: "semantic_slice",
+    category: "code",
+    description: "Return relevant exact source lines with optional dependency and memory context",
+    inputShape: {
+      file: z.string().optional().describe("Relative or absolute source file path"),
+      symbol: z.string().optional().describe("Symbol id/name (e.g. ToolHandlers.callTool)"),
+      query: z.string().optional().describe("Natural-language fallback query"),
+      context: z
+        .enum(["signature", "body", "with-deps", "full"])
+        .default("body")
+        .describe("Slice detail mode"),
+      pprScore: z.number().optional().describe("Optional PPR score from context_pack pipeline"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const impl = (ctx as any).core_semantic_slice_impl;
+      Iif (typeof impl !== "function") {
+        return ctx.errorEnvelope(
+          "TOOL_NOT_IMPLEMENTED",
+          "semantic_slice implementation is unavailable",
+          true,
+        );
+      }
+      return impl.call(ctx, args);
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/core-setup-tools.ts.html b/coverage/lcov-report/src/tools/handlers/core-setup-tools.ts.html new file mode 100644 index 0000000..411c8a1 --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/core-setup-tools.ts.html @@ -0,0 +1,1708 @@ + + + + + + Code coverage report for src/tools/handlers/core-setup-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers core-setup-tools.ts

+
+ +
+ 80% + Statements + 108/135 +
+ + +
+ 75.6% + Branches + 93/123 +
+ + +
+ 57.14% + Functions + 4/7 +
+ + +
+ 83.47% + Lines + 101/121 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +1x +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +2x +  +2x +2x +2x +2x +  +  +2x +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +2x +2x +  +2x +2x +2x +2x +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +2x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +  +6x +6x +  +  +  +  +  +6x +1x +  +  +  +  +  +  +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +5x +5x +6x +6x +  +  +  +6x +6x +6x +  +  +  +  +6x +  +6x +6x +  +6x +  +  +6x +6x +  +6x +  +6x +6x +  +6x +  +  +6x +1x +5x +5x +5x +5x +5x +  +5x +  +5x +  +  +1x +  +  +  +6x +  +9x +  +6x +6x +6x +4x +4x +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +6x +6x +  +  +  +5x +5x +  +  +  +  +5x +1x +1x +1x +1x +  +  +  +  +  +5x +1x +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +5x +  +5x +1x +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +  +4x +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file tools/handlers/core-setup-tools
+ * @description Project setup/onboarding tool definitions — init_project_setup, setup_copilot_instructions.
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const coreSetupToolDefinitions: ToolDefinition[] = [
+  {
+    name: "init_project_setup",
+    category: "setup",
+    description:
+      "One-shot project initialization: sets workspace context, triggers graph rebuild, and generates .github/copilot-instructions.md if not present. Use this as the first step when onboarding a new project or starting a fresh session.",
+    inputShape: {
+      workspaceRoot: z.string().describe("Absolute path to the project root to initialize"),
+      sourceDir: z
+        .string()
+        .optional()
+        .describe("Source directory relative to workspaceRoot (default: src)"),
+      projectId: z
+        .string()
+        .optional()
+        .describe("Project identifier (default: basename of workspaceRoot)"),
+      rebuildMode: z
+        .enum(["incremental", "full"])
+        .default("incremental")
+        .describe("incremental = changed files only; full = rebuild entire graph"),
+      withDocs: z.boolean().default(true).describe("Also index markdown docs during rebuild"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        workspaceRoot,
+        sourceDir,
+        projectId,
+        rebuildMode = "incremental",
+        withDocs = true,
+        profile = "compact",
+      } = args ?? {};
+ 
+      if (!workspaceRoot || typeof workspaceRoot !== "string") {
+        return ctx.errorEnvelope(
+          "INIT_MISSING_WORKSPACE",
+          "workspaceRoot is required",
+          false,
+          "Provide the absolute path to the project you want to initialize.",
+        );
+      }
+ 
+      const resolvedRoot = path.resolve(workspaceRoot);
+      Iif (!fs.existsSync(resolvedRoot)) {
+        return ctx.errorEnvelope(
+          "INIT_WORKSPACE_NOT_FOUND",
+          `Workspace path does not exist: ${resolvedRoot}`,
+          false,
+          "Ensure the project is accessible from this machine/container.",
+        );
+      }
+ 
+      const steps: Array<{ step: string; status: string; detail?: string }> = [];
+ 
+      try {
+        const setArgs: any = { workspaceRoot: resolvedRoot, profile };
+        if (sourceDir) setArgs.sourceDir = sourceDir;
+        if (projectId) setArgs.projectId = projectId;
+ 
+        let setResult: string;
+        try {
+          setResult = await ctx.callTool("graph_set_workspace", setArgs);
+          const setJson = JSON.parse(setResult);
+          Iif (setJson?.error) {
+            steps.push({
+              step: "graph_set_workspace",
+              status: "failed",
+              detail: setJson.error,
+            });
+            return ctx.formatSuccess(
+              { steps, abortedAt: "graph_set_workspace" },
+              profile,
+              "Initialization aborted at workspace setup",
+              "init_project_setup",
+            );
+          }
+          const setCtx = setJson?.data?.projectContext ?? setJson?.data ?? {};
+          steps.push({
+            step: "graph_set_workspace",
+            status: "ok",
+            detail: `projectId=${setCtx.projectId ?? "?"}, sourceDir=${setCtx.sourceDir ?? "?"}`,
+          });
+        } catch (err) {
+          steps.push({
+            step: "graph_set_workspace",
+            status: "failed",
+            detail: String(err),
+          });
+          return ctx.formatSuccess(
+            { steps, abortedAt: "graph_set_workspace" },
+            profile,
+            "Initialization aborted at workspace setup",
+            "init_project_setup",
+          );
+        }
+ 
+        const rebuildArgs: any = {
+          workspaceRoot: resolvedRoot,
+          mode: rebuildMode,
+          indexDocs: withDocs,
+          profile,
+        };
+        if (sourceDir) rebuildArgs.sourceDir = sourceDir;
+        if (projectId) rebuildArgs.projectId = projectId;
+ 
+        try {
+          const rebuildResult = await ctx.callTool("graph_rebuild", rebuildArgs);
+          const rebuildJson = JSON.parse(rebuildResult);
+          if (rebuildJson?.error) {
+            steps.push({
+              step: "graph_rebuild",
+              status: "failed",
+              detail: rebuildJson.error,
+            });
+          } else {
+            steps.push({
+              step: "graph_rebuild",
+              status: "queued",
+              detail: `mode=${rebuildMode}, indexDocs=${withDocs}`,
+            });
+          }
+        } catch (err) {
+          steps.push({
+            step: "graph_rebuild",
+            status: "failed",
+            detail: String(err),
+          });
+        }
+ 
+        const copilotPath = path.join(resolvedRoot, ".github", "copilot-instructions.md");
+        if (!fs.existsSync(copilotPath)) {
+          try {
+            await ctx.callTool("setup_copilot_instructions", {
+              targetPath: resolvedRoot,
+              dryRun: false,
+              overwrite: false,
+              profile: "compact",
+            });
+            steps.push({
+              step: "setup_copilot_instructions",
+              status: "created",
+              detail: ".github/copilot-instructions.md",
+            });
+          } catch (err) {
+            steps.push({
+              step: "setup_copilot_instructions",
+              status: "skipped",
+              detail: String(err),
+            });
+          }
+        } else E{
+          steps.push({
+            step: "setup_copilot_instructions",
+            status: "exists",
+            detail: "File already present — skipped",
+          });
+        }
+ 
+        const projCtx = ctx.resolveProjectContext({
+          workspaceRoot: resolvedRoot,
+          ...(sourceDir ? { sourceDir } : {}),
+          ...(projectId ? { projectId } : {}),
+        });
+ 
+        return ctx.formatSuccess(
+          {
+            projectId: projCtx.projectId,
+            workspaceRoot: projCtx.workspaceRoot,
+            sourceDir: projCtx.sourceDir,
+            steps,
+            nextAction:
+              "Call graph_health to confirm the rebuild completed, then graph_query to start exploring.",
+          },
+          profile,
+          `Project ${projCtx.projectId} initialized — graph rebuild queued`,
+          "init_project_setup",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "INIT_PROJECT_FAILED",
+          error instanceof Error ? error.message : String(error),
+          true,
+        );
+      }
+    },
+  },
+  {
+    name: "setup_copilot_instructions",
+    category: "setup",
+    description:
+      "Analyze a repository and generate a tailored .github/copilot-instructions.md file with tech-stack detection, key commands, required session flow, and tool-usage guidance. Makes it immediately efficient to work with the repo via Copilot or any AI assistant.",
+    inputShape: {
+      targetPath: z
+        .string()
+        .optional()
+        .describe("Absolute path to the target repository (defaults to the active workspace)"),
+      projectName: z.string().optional().describe("Override the detected project name"),
+      dryRun: z
+        .boolean()
+        .default(false)
+        .describe("Return the generated content without writing the file"),
+      overwrite: z.boolean().default(false).describe("Replace an existing copilot-instructions.md"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        targetPath,
+        projectName: forceProjectName,
+        dryRun = false,
+        overwrite = false,
+        profile = "compact",
+      } = args ?? {};
+ 
+      let resolvedTarget: string;
+      if (targetPath && typeof targetPath === "string") {
+        resolvedTarget = path.resolve(targetPath);
+      } else E{
+        const active = ctx.resolveProjectContext({});
+        resolvedTarget = active.workspaceRoot;
+      }
+ 
+      if (!fs.existsSync(resolvedTarget)) {
+        return ctx.errorEnvelope(
+          "COPILOT_INSTR_TARGET_NOT_FOUND",
+          `Target path does not exist: ${resolvedTarget}`,
+          false,
+          "Provide an accessible absolute path via targetPath parameter.",
+        );
+      }
+ 
+      const destFile = path.join(resolvedTarget, ".github", "copilot-instructions.md");
+      Iif (fs.existsSync(destFile) && !overwrite && !dryRun) {
+        return ctx.formatSuccess(
+          {
+            status: "already_exists",
+            path: destFile,
+            hint: "Pass overwrite=true to replace it.",
+          },
+          profile,
+          ".github/copilot-instructions.md already exists — skipped",
+          "setup_copilot_instructions",
+        );
+      }
+ 
+      try {
+        const repoName = forceProjectName || path.basename(resolvedTarget);
+        const pkgPath = path.join(resolvedTarget, "package.json");
+        const pkgJson: any = fs.existsSync(pkgPath)
+          ? JSON.parse(fs.readFileSync(pkgPath, "utf-8"))
+          : null;
+ 
+        const name = forceProjectName || pkgJson?.name || repoName;
+        const description = pkgJson?.description || "";
+        const deps: Record<string, string> = {
+          ...(pkgJson?.dependencies ?? {}),
+          ...(pkgJson?.devDependencies ?? {}),
+        };
+ 
+        const stack: string[] = [];
+        const isTypeScript =
+          fs.existsSync(path.join(resolvedTarget, "tsconfig.json")) || !!deps["typescript"];
+        const isNode = !!pkgJson || fs.existsSync(path.join(resolvedTarget, "package.json"));
+        const isPython =
+          fs.existsSync(path.join(resolvedTarget, "pyproject.toml")) ||
+          fs.existsSync(path.join(resolvedTarget, "setup.py")) ||
+          fs.existsSync(path.join(resolvedTarget, "requirements.txt"));
+        const isGo = fs.existsSync(path.join(resolvedTarget, "go.mod"));
+        const isRust = fs.existsSync(path.join(resolvedTarget, "Cargo.toml"));
+        const isJava =
+          fs.existsSync(path.join(resolvedTarget, "pom.xml")) ||
+          fs.existsSync(path.join(resolvedTarget, "build.gradle"));
+        const isReact = !!deps["react"];
+        const isNextJs = !!deps["next"];
+        const isDocker =
+          fs.existsSync(path.join(resolvedTarget, "Dockerfile")) ||
+          fs.existsSync(path.join(resolvedTarget, "docker-compose.yml"));
+ 
+        Iif (isTypeScript) stack.push("TypeScript");
+        else if (isNode) stack.push("JavaScript / Node.js");
+        Iif (isPython) stack.push("Python");
+        Iif (isGo) stack.push("Go");
+        Iif (isRust) stack.push("Rust");
+        Iif (isJava) stack.push("Java");
+        Iif (isNextJs) stack.push("Next.js"I);
+        else if (isReact) stack.push("React");
+        Iif (isDocker) stack.push("Docker");
+ 
+        const scripts = pkgJson?.scripts
+          ? Object.entries(pkgJson.scripts)
+              .slice(0, 10)
+              .map(([k, v]) => `- \`${k}\`: \`${v}\``)
+              .join("\n")
+          : "";
+ 
+        const candidateSrcDirs = ["src", "lib", "app", "packages", "source"];
+        const srcDir =
+          candidateSrcDirs.find((d) => fs.existsSync(path.join(resolvedTarget, d))) ?? "src";
+ 
+        const srcPath = path.join(resolvedTarget, srcDir);
+        let subDirs: string[] = [];
+        if (fs.existsSync(srcPath)) {
+          try {
+            subDirs = fs
+              .readdirSync(srcPath, { withFileTypes: true })
+              .filter((e) => e.isDirectory())
+              .map((e) => e.name)
+              .slice(0, 10);
+          } catch {
+            // ignore
+          }
+        }
+ 
+        const isMcpServer =
+          !!deps["@modelcontextprotocol/sdk"] ||
+          fs.existsSync(path.join(resolvedTarget, "src", "mcp-server.ts")) ||
+          fs.existsSync(path.join(resolvedTarget, "src", "server.ts"));
+ 
+        const lines: string[] = [`# Copilot Instructions for ${name}`, ""];
+        Iif (description) {
+          lines.push(description, "");
+        }
+ 
+        lines.push("## Primary Goal", "");
+        lines.push(
+          "Understand the codebase before making changes. Use graph-backed tools first for code intelligence, then fall back to file reads only when needed.",
+          "",
+        );
+ 
+        if (stack.length > 0) {
+          lines.push("## Runtime Truths", "");
+          lines.push(`- **Stack**: ${stack.join(", ")}`);
+          lines.push(`- **Source root**: \`${srcDir}/\``);
+          Iif (subDirs.length > 0) {
+            lines.push(
+              `- **Key directories**: ${subDirs.map((d) => `\`${srcDir}/${d}\``).join(", ")}`,
+            );
+          }
+        }
+        if (scripts) {
+          lines.push("", "## Available Commands", "", scripts);
+        }
+ 
+        Iif (isMcpServer) {
+          lines.push(
+            "",
+            "## Required Session Flow",
+            "",
+            "**One-shot (recommended):**",
+            "```",
+            'init_project_setup({ projectId: "my-proj", workspaceRoot: "/abs/path" })',
+            "```",
+            "",
+            "**Manual:**",
+            "1. `graph_set_workspace({ projectId, workspaceRoot })` — anchor the session",
+            '2. `graph_rebuild({ projectId, mode: "full", workspaceRoot })` — capture `txId` from response',
+            '3. `graph_health({ profile: "balanced" })` — verify nodes > 0',
+            '4. `graph_query({ query: "MATCH (n) RETURN labels(n)[0], count(n) LIMIT 8", projectId })` — confirm data',
+            "",
+            "**HTTP transport only:** capture `mcp-session-id` from `initialize` response and include on every request.",
+          );
+        } else {
+          lines.push(
+            "",
+            "## Required Session Flow",
+            "",
+            "1. Call `init_project_setup({ projectId, workspaceRoot })` — sets context, triggers graph rebuild, writes copilot instructions.",
+            '2. Validate with `graph_health({ profile: "balanced" })`',
+            '3. Explore with `graph_query({ query: "MATCH (n) RETURN labels(n)[0], count(n) DESC LIMIT 10" })`',
+          );
+        }
+ 
+        lines.push(
+          "",
+          "## Tool Decision Guide",
+          "",
+          "| Goal | First choice | Fallback |",
+          "|---|---|---|",
+          "| Count/list nodes | `graph_query` (Cypher) | `graph_health` |",
+          "| Understand a symbol | `code_explain` (symbol name) | `semantic_slice` |",
+          "| Find related code | `find_similar_code` | `semantic_search` |",
+          "| Check arch violations | `arch_validate` | `blocking_issues` |",
+          "| Place new code | `arch_suggest` | — |",
+          "| Docs lookup | `search_docs` → `index_docs` if empty | file read |",
+          "| Tests after change | `test_select` → `test_run` | `suggest_tests` |",
+          "| Track decisions | `episode_add` (DECISION) | — |",
+          "| Release agent lock | `agent_release` with `claimId` | — |",
+        );
+ 
+        lines.push(
+          "",
+          "## Correct Tool Signatures (verified)",
+          "",
+          "```jsonc",
+          `// graph — capture txId from graph_rebuild response for diff_since`,
+          `graph_rebuild({ "projectId": "proj", "mode": "full" })  // → { txId }`,
+          `diff_since({ "since": "<txId | ISO-8601>" })            // NOT git refs like HEAD~3`,
+          "",
+          `// semantic`,
+          `code_explain({ "element": "SymbolName", "depth": 2 })   // symbol name, NOT qualified ID`,
+          `semantic_diff({ "elementId1": "...", "elementId2": "..." })  // NOT elementA/elementB`,
+          `semantic_slice({ "symbol": "MyClass" })                 // NOT entryPoint`,
+          "",
+          `// clustering`,
+          `code_clusters({ "type": "file" })  // type: "function"|"class"|"file"  NOT granularity`,
+          `arch_suggest({ "name": "NewEngine", "codeType": "engine" })  // NOT codeName`,
+          "",
+          `// memory — DECISION requires metadata.rationale, type is uppercase`,
+          `episode_add({ "type": "DECISION", "content": "...", "outcome": "success",`,
+          `             "metadata": { "rationale": "because..." } })`,
+          `episode_add({ "type": "LEARNING", "content": "..." })`,
+          `decision_query({ "query": "..." })   // NOT topic`,
+          `progress_query({ "query": "..." })   // query is required, NOT status`,
+          "",
+          `// coordination — capture claimId from agent_claim for release`,
+          `agent_claim({ "agentId": "a1", "targetId": "src/file.ts", "intent": "..." })  // NOT target`,
+          `agent_release({ "claimId": "claim-xxx" })   // NOT agentId/taskId`,
+          `context_pack({ "task": "Description..." }) // task string is REQUIRED`,
+          "",
+          `// tests — suggest_tests needs fully-qualified element ID`,
+          `suggest_tests({ "elementId": "proj:file.ts:symbolName:line" })`,
+          "```",
+        );
+ 
+        lines.push(
+          "",
+          "## Common Pitfalls",
+          "",
+          "| Wrong | Correct |",
+          "|---|---|",
+          '| `code_explain({ elementId: ... })` | `code_explain({ element: "SymbolName" })` |',
+          "| `semantic_diff({ elementA, elementB })` | `semantic_diff({ elementId1, elementId2 })` |",
+          '| `code_clusters({ granularity: "module" })` | `code_clusters({ type: "file" })` |',
+          '| `arch_suggest({ codeName: "X" })` | `arch_suggest({ name: "X" })` |',
+          '| `episode_add({ type: "decision" })` | `episode_add({ type: "DECISION" })` (uppercase) |',
+          '| DECISION without `metadata.rationale` | always include `metadata: { rationale: "..." }` |',
+          '| `decision_query({ topic: "X" })` | `decision_query({ query: "X" })` |',
+          '| `agent_claim({ target: "f.ts" })` | `agent_claim({ targetId: "f.ts" })` |',
+          '| `agent_release({ agentId, taskId })` | `agent_release({ claimId: "claim-xxx" })` |',
+        );
+ 
+        lines.push(
+          "",
+          "## Copilot Skills — Usage Patterns",
+          "",
+          "### Explore unfamiliar codebase",
+          "```",
+          "1. init_project_setup({ projectId, workspaceRoot })",
+          '2. graph_query("MATCH (n) RETURN labels(n)[0], count(n) ORDER BY count(n) DESC LIMIT 10")',
+          '3. code_explain({ element: "MainEntryPoint" })',
+          "```",
+          "",
+          "### Safe refactor + test impact",
+          "```",
+          '1. impact_analyze({ changedFiles: ["src/x.ts"] })',
+          '2. test_select({ changedFiles: ["src/x.ts"] })',
+          '3. arch_validate({ files: ["src/x.ts"] })',
+          "4. test_run({ testFiles: [...from test_select...] })",
+          '5. episode_add({ type: "DECISION", content: "...", metadata: { rationale: "..." } })',
+          "```",
+          "",
+          "### Multi-agent safe edit",
+          "```",
+          '1. agent_claim({ agentId, targetId: "src/file.ts", intent: "..." })  → save claimId',
+          "2. ... make changes ...",
+          '3. agent_release({ claimId, outcome: "done" })',
+          "```",
+          "",
+          "### Docs cold start",
+          "```",
+          '1. search_docs({ query: "topic" })           — if count=0:',
+          '2. index_docs({ paths: ["/abs/README.md"] })',
+          '3. search_docs({ query: "topic" })           — now returns results',
+          "```",
+        );
+ 
+        lines.push(
+          "",
+          "## Source of Truth",
+          "",
+          "`README.md`, `QUICK_START.md`, `ARCHITECTURE.md`.",
+        );
+ 
+        const content = lines.join("\n") + "\n";
+ 
+        if (dryRun) {
+          return ctx.formatSuccess(
+            {
+              dryRun: true,
+              targetPath: destFile,
+              content,
+            },
+            profile,
+            "Dry run — copilot-instructions.md content generated (not written)",
+            "setup_copilot_instructions",
+          );
+        }
+ 
+        const githubDir = path.join(resolvedTarget, ".github");
+        Eif (!fs.existsSync(githubDir)) {
+          fs.mkdirSync(githubDir, { recursive: true });
+        }
+        fs.writeFileSync(destFile, content, "utf-8");
+ 
+        return ctx.formatSuccess(
+          {
+            status: "created",
+            path: destFile,
+            projectName: name,
+            stackDetected: stack,
+            overwritten: overwrite && fs.existsSync(destFile),
+          },
+          profile,
+          `Copilot instructions written to ${path.relative(resolvedTarget, destFile)}`,
+          "setup_copilot_instructions",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "SETUP_COPILOT_FAILED",
+          error instanceof Error ? error.message : String(error),
+          true,
+        );
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/core-utility-tools.ts.html b/coverage/lcov-report/src/tools/handlers/core-utility-tools.ts.html new file mode 100644 index 0000000..c2a94c9 --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/core-utility-tools.ts.html @@ -0,0 +1,505 @@ + + + + + + Code coverage report for src/tools/handlers/core-utility-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers core-utility-tools.ts

+
+ +
+ 88.46% + Statements + 23/26 +
+ + +
+ 66.66% + Branches + 8/12 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 88.46% + Lines + 23/26 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +16x +16x +16x +72x +72x +72x +  +  +  +  +16x +  +  +2x +16x +  +  +2x +16x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +3x +  +3x +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file tools/handlers/core-utility-tools
+ * @description Utility tool definitions — tools_list, contract_validate.
+ */
+ 
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const coreUtilityToolDefinitions: ToolDefinition[] = [
+  {
+    name: "tools_list",
+    category: "utility",
+    description:
+      "List all MCP tools and their availability in the current session, grouped by category",
+    inputShape: {
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const profile = args?.profile ?? "compact";
+ 
+      const KNOWN_CATEGORIES: Record<string, string[]> = {
+        graph: [
+          "graph_set_workspace",
+          "graph_rebuild",
+          "graph_query",
+          "graph_health",
+          "tools_list",
+          "ref_query",
+        ],
+        architecture: ["arch_validate", "arch_suggest"],
+        semantic: [
+          "semantic_search",
+          "find_similar_code",
+          "code_explain",
+          "semantic_slice",
+          "semantic_diff",
+          "code_clusters",
+          "find_pattern",
+          "blocking_issues",
+        ],
+        docs: ["index_docs", "search_docs"],
+        test: ["test_select", "test_categorize", "test_run", "suggest_tests", "impact_analyze"],
+        memory: ["episode_add", "episode_recall", "decision_query", "reflect", "context_pack"],
+        progress: ["progress_query", "task_update", "feature_status"],
+        coordination: [
+          "agent_claim",
+          "agent_release",
+          "coordination_overview",
+          "contract_validate",
+          "diff_since",
+        ],
+      };
+ 
+      const result: Record<string, { available: string[]; unavailable: string[] }> = {};
+ 
+      for (const [category, tools] of Object.entries(KNOWN_CATEGORIES)) {
+        const available: string[] = [];
+        const unavailable: string[] = [];
+        for (const toolName of tools) {
+          const bound = (ctx as any)[toolName];
+          if (typeof bound === "function") {
+            available.push(toolName);
+          } else E{
+            unavailable.push(toolName);
+          }
+        }
+        result[category] = { available, unavailable };
+      }
+ 
+      const totalAvailable = Object.values(result).reduce(
+        (sum, cat) => sum + cat.available.length,
+        0,
+      );
+      const totalUnavailable = Object.values(result).reduce(
+        (sum, cat) => sum + cat.unavailable.length,
+        0,
+      );
+ 
+      return ctx.formatSuccess(
+        {
+          summary: `${totalAvailable} tools available, ${totalUnavailable} unavailable in this session`,
+          categories: result,
+          note: "Unavailable tools may require missing configuration, a running engine, or a different server entrypoint.",
+        },
+        profile,
+      );
+    },
+  },
+  {
+    name: "contract_validate",
+    category: "utility",
+    description: "Normalize and validate tool argument contracts before execution",
+    inputShape: {
+      tool: z.string().describe("Target tool name"),
+      arguments: z.record(z.string(), z.any()).optional().describe("Raw arguments to normalize"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { tool, arguments: inputArgs = {}, profile = "compact" } = args || {};
+ 
+      Iif (!tool || typeof tool !== "string") {
+        return ctx.errorEnvelope(
+          "CONTRACT_VALIDATE_INVALID_INPUT",
+          "Field 'tool' is required and must be a string",
+          true,
+        );
+      }
+ 
+      try {
+        // Step 1: normalise field aliases (e.g. changedFiles → files)
+        const { normalized, warnings: normWarnings } = ctx.normalizeForDispatch(tool, inputArgs);
+ 
+        // Step 2: validate normalised args against the tool's Zod schema
+        const validation = ctx.validateToolArgs(tool, normalized);
+ 
+        return ctx.formatSuccess(
+          {
+            tool,
+            input: inputArgs,
+            normalized,
+            valid: validation.valid,
+            errors: validation.errors,
+            missingRequired: validation.missingRequired,
+            extraFields: validation.extraFields,
+            warnings: [...normWarnings, ...validation.warnings],
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("CONTRACT_VALIDATE_FAILED", String(error), true);
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/docs-tools.ts.html b/coverage/lcov-report/src/tools/handlers/docs-tools.ts.html new file mode 100644 index 0000000..76ad467 --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/docs-tools.ts.html @@ -0,0 +1,643 @@ + + + + + + Code coverage report for src/tools/handlers/docs-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers docs-tools.ts

+
+ +
+ 91.66% + Statements + 22/24 +
+ + +
+ 73.91% + Branches + 17/23 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 91.66% + Lines + 22/24 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +6x +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +1x +  +  +5x +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +7x +7x +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +1x +  +  +  +6x +1x +  +  +5x +4x +  +  +  +1x +  +  +  +  +  +  +5x +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Documentation Tools
+ * Registry-backed documentation tool definitions.
+ *
+ * Tools:
+ * - index_docs: index documentation files in workspace
+ * - search_docs: search indexed documentation
+ */
+ 
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const docsToolDefinitions: ToolDefinition[] = [
+  {
+    name: "index_docs",
+    category: "docs",
+    description:
+      "Discover and index all markdown documentation files (README, ADRs, guides, CHANGELOG, ARCHITECTURE) under the workspace root into DOCUMENT and SECTION graph nodes. Supports incremental mode (skips unchanged files). Emits DOC_DESCRIBES edges linking sections to the code symbols they mention.",
+    inputShape: {
+      workspaceRoot: z
+        .string()
+        .optional()
+        .describe("Workspace root path (defaults to active session context)"),
+      projectId: z.string().optional().describe("Project ID (defaults to active session context)"),
+      incremental: z
+        .boolean()
+        .default(true)
+        .describe("Skip files whose hash has not changed (default: true)"),
+      withEmbeddings: z
+        .boolean()
+        .default(false)
+        .describe("Also embed section content into Qdrant vector store"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        workspaceRoot: argsRoot,
+        projectId: argsProject,
+        incremental = true,
+        withEmbeddings = false,
+      } = args ?? {};
+      try {
+        const { workspaceRoot, projectId } = ctx.resolveProjectContext({
+          workspaceRoot: argsRoot,
+          projectId: argsProject,
+        });
+ 
+        const docsEngine = ctx.engines.docs as
+          | {
+              indexWorkspace: (
+                workspaceRoot: string,
+                projectId: string,
+                options: { incremental: boolean; withEmbeddings: boolean },
+              ) => Promise<{
+                indexed: number;
+                skipped: number;
+                errors: unknown[];
+                durationMs: number;
+              }>;
+            }
+          | undefined;
+ 
+        if (!docsEngine) {
+          return ctx.errorEnvelope("ENGINE_UNAVAILABLE", "DocsEngine not initialised", false);
+        }
+ 
+        const result = await docsEngine.indexWorkspace(workspaceRoot, projectId, {
+          incremental,
+          withEmbeddings,
+        });
+ 
+        return ctx.formatSuccess(
+          {
+            ok: true,
+            indexed: result.indexed,
+            skipped: result.skipped,
+            errorCount: result.errors.length,
+            errors: result.errors.slice(0, 10),
+            durationMs: result.durationMs,
+            projectId,
+            workspaceRoot,
+          },
+          "compact",
+        );
+      } catch (err) {
+        return ctx.errorEnvelope(
+          "INDEX_DOCS_ERROR",
+          err instanceof Error ? err.message : String(err),
+          true,
+        );
+      }
+    },
+  },
+  {
+    name: "search_docs",
+    category: "docs",
+    description:
+      "Search indexed documentation sections by full-text query or by code symbol name. Returns matching SECTION nodes with heading, source document, kind (readme/adr/guide/…), line number, relevance score, and a short content excerpt. Run index_docs first to populate the index.",
+    inputShape: {
+      query: z
+        .string()
+        .optional()
+        .describe("Full-text search query (cannot be combined with symbol)"),
+      symbol: z
+        .string()
+        .optional()
+        .describe(
+          "Symbol name to look up (finds Sections that document this function/class/file via DOC_DESCRIBES edges)",
+        ),
+      limit: z
+        .number()
+        .int()
+        .min(1)
+        .max(50)
+        .default(10)
+        .describe("Maximum number of results to return"),
+      projectId: z.string().optional().describe("Project ID (defaults to active session context)"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { query, symbol, limit = 10, projectId: argsProject } = args ?? {};
+      try {
+        const { projectId } = ctx.resolveProjectContext({
+          projectId: argsProject,
+        });
+ 
+        const docsEngine = ctx.engines.docs as
+          | {
+              getDocsBySymbol: (
+                symbol: string,
+                projectId: string,
+                options: { limit: number },
+              ) => Promise<any[]>;
+              searchDocs: (
+                query: string,
+                projectId: string,
+                options: { limit: number },
+              ) => Promise<any[]>;
+            }
+          | undefined;
+ 
+        if (!docsEngine) {
+          return ctx.errorEnvelope("ENGINE_UNAVAILABLE", "DocsEngine not initialised", false);
+        }
+ 
+        let results;
+        if (typeof symbol === "string" && symbol.trim().length > 0) {
+          results = await docsEngine.getDocsBySymbol(symbol.trim(), projectId, {
+            limit,
+          });
+        } else if (typeof query === "string" && query.trim().length > 0) {
+          results = await docsEngine.searchDocs(query.trim(), projectId, {
+            limit,
+          });
+        } else {
+          return ctx.errorEnvelope(
+            "MISSING_PARAM",
+            "Provide either `query` (full-text search) or `symbol` (symbol lookup)",
+            true,
+          );
+        }
+ 
+        return ctx.formatSuccess(
+          {
+            ok: true,
+            count: results.length,
+            results: results.map((r: any) => ({
+              heading: r.heading,
+              doc: r.docRelativePath,
+              kind: r.kind,
+              startLine: r.startLine,
+              score: r.score,
+              excerpt: r.content.slice(0, 200),
+            })),
+            projectId,
+          },
+          "compact",
+        );
+      } catch (err) {
+        return ctx.errorEnvelope(
+          "SEARCH_DOCS_ERROR",
+          err instanceof Error ? err.message : String(err),
+          true,
+        );
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/index.html b/coverage/lcov-report/src/tools/handlers/index.html new file mode 100644 index 0000000..c208eb7 --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/index.html @@ -0,0 +1,266 @@ + + + + + + Code coverage report for src/tools/handlers + + + + + + + + + +
+
+

All files src/tools/handlers

+
+ +
+ 81.89% + Statements + 837/1022 +
+ + +
+ 67.74% + Branches + 628/927 +
+ + +
+ 83.47% + Functions + 96/115 +
+ + +
+ 83.79% + Lines + 812/969 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
arch-tools.ts +
+
85%17/2091.66%11/12100%2/285%17/20
core-analysis-tools.ts +
+
76.29%103/13547.7%52/10973.33%11/1578.74%100/127
core-graph-tools.ts +
+
80.09%165/20669.23%162/23482.6%19/2380.19%162/202
core-semantic-tools.ts +
+
88.15%67/7674.46%35/4793.75%15/1688%66/75
core-setup-tools.ts +
+
80%108/13575.6%93/12357.14%4/783.47%101/121
core-utility-tools.ts +
+
88.46%23/2666.66%8/12100%4/488.46%23/26
docs-tools.ts +
+
91.66%22/2473.91%17/23100%3/391.66%22/24
memory-coordination-tools.ts +
+
85.55%77/9082.52%85/10375%9/1285.55%77/90
ref-tools.ts +
+
86.42%121/14066.08%76/11592.3%12/1392.74%115/124
task-tools.ts +
+
85.13%63/7468.57%48/7085.71%6/785.13%63/74
test-tools.ts +
+
73.95%71/9651.89%41/7984.61%11/1376.74%66/86
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/memory-coordination-tools.ts.html b/coverage/lcov-report/src/tools/handlers/memory-coordination-tools.ts.html new file mode 100644 index 0000000..43396b2 --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/memory-coordination-tools.ts.html @@ -0,0 +1,1819 @@ + + + + + + Code coverage report for src/tools/handlers/memory-coordination-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers memory-coordination-tools.ts

+
+ +
+ 85.55% + Statements + 77/90 +
+ + +
+ 82.52% + Branches + 85/103 +
+ + +
+ 75% + Functions + 9/12 +
+ + +
+ 85.55% + Lines + 77/90 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +8x +  +  +8x +1x +1x +  +  +  +  +  +  +  +7x +7x +7x +2x +  +8x +8x +  +  +  +  +  +8x +2x +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +5x +8x +8x +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +1x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +2x +  +  +3x +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +1x +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +4x +4x +  +4x +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +  +4x +2x +2x +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +2x +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file tools/handlers/memory-coordination-tools
+ * @description Memory episode and multi-agent coordination MCP tool definitions.
+ * @remarks These handlers orchestrate `EpisodeEngine` and `CoordinationEngine` workflows.
+ */
+ 
+import * as z from "zod";
+import * as env from "../../env.js";
+import type { EpisodeType } from "../../engines/episode-engine.js";
+import type { ClaimType } from "../../engines/coordination-engine.js";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+import { logger } from "../../utils/logger.js";
+ 
+/**
+ * Registry definitions for memory and coordination tool endpoints.
+ */
+export const memoryCoordinationToolDefinitions: ToolDefinition[] = [
+  {
+    name: "episode_add",
+    category: "memory",
+    description: "Persist a structured episode in long-term agent memory",
+    inputShape: {
+      type: z
+        .enum(["OBSERVATION", "DECISION", "EDIT", "TEST_RESULT", "ERROR", "REFLECTION", "LEARNING"])
+        .describe("Episode type"),
+      content: z.string().describe("Episode content"),
+      entities: z.array(z.string()).optional().describe("Related graph entity IDs"),
+      taskId: z.string().optional().describe("Related task ID"),
+      outcome: z
+        .enum(["success", "failure", "partial"])
+        .optional()
+        .describe("Outcome classification"),
+      metadata: z.record(z.string(), z.any()).optional().describe("Extra metadata"),
+      sensitive: z.boolean().optional().describe("Exclude from default recalls"),
+      agentId: z.string().optional().describe("Agent identifier"),
+      sessionId: z.string().optional().describe("Session identifier"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        type,
+        content,
+        entities = [],
+        taskId,
+        outcome,
+        metadata,
+        sensitive = false,
+        profile = "compact",
+        agentId,
+        sessionId,
+      } = args || {};
+ 
+      logger.error(
+        `[episode_add] ENTER rawType=${JSON.stringify(type)} content-length=${String(content ?? "").length} agentId=${agentId ?? "(none)"}`,
+      );
+      if (!type || !content) {
+        logger.error(`[episode_add] REJECT missing type=${!type} missing content=${!content}`);
+        return ctx.errorEnvelope(
+          "EPISODE_ADD_INVALID_INPUT",
+          "Fields 'type' and 'content' are required.",
+          true,
+          "Provide type (e.g. OBSERVATION) and content.",
+        );
+      }
+ 
+      const normalizedType = String(type).toUpperCase();
+      logger.error(`[episode_add] normalizedType=${normalizedType}`);
+      const normalizedEntities = Array.isArray(entities)
+        ? entities.map((item) => String(item))
+        : [];
+      const normalizedMetadata = metadata && typeof metadata === "object" ? metadata : undefined;
+      const validationError = ctx.validateEpisodeInput({
+        type: normalizedType,
+        outcome,
+        entities: normalizedEntities,
+        metadata: normalizedMetadata,
+      });
+      if (validationError) {
+        return ctx.errorEnvelope("EPISODE_ADD_INVALID_METADATA", validationError, true);
+      }
+ 
+      const episodeEngine = ctx.engines.episode as
+        | {
+            add: (
+              args: {
+                type: EpisodeType;
+                content: string;
+                entities?: string[];
+                taskId?: string;
+                outcome?: "success" | "failure" | "partial";
+                metadata?: Record<string, unknown>;
+                sensitive?: boolean;
+                agentId: string;
+                sessionId: string;
+              },
+              projectId: string,
+            ) => Promise<string>;
+          }
+        | undefined;
+ 
+      try {
+        const contextSessionId = ctx.getCurrentSessionId() || "session-unknown";
+        const runtimeAgentId = String(agentId || env.LXRAG_AGENT_ID);
+        const { projectId } = ctx.getActiveProjectContext();
+ 
+        const episodeId = await episodeEngine!.add(
+          {
+            type: normalizedType as EpisodeType,
+            content: String(content),
+            entities: normalizedEntities,
+            taskId: taskId ? String(taskId) : undefined,
+            outcome,
+            metadata: normalizedMetadata,
+            sensitive: Boolean(sensitive),
+            agentId: runtimeAgentId,
+            sessionId: String(sessionId || contextSessionId),
+          },
+          projectId,
+        );
+ 
+        return ctx.formatSuccess(
+          {
+            episodeId,
+            type: String(type).toUpperCase(),
+            projectId,
+            taskId: taskId || null,
+          },
+          profile,
+          `Episode ${episodeId} persisted.`,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("EPISODE_ADD_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "episode_recall",
+    category: "memory",
+    description: "Recall episodes by semantic, temporal, and entity relevance",
+    inputShape: {
+      query: z.string().describe("Recall query"),
+      agentId: z.string().optional().describe("Agent filter"),
+      taskId: z.string().optional().describe("Task filter"),
+      types: z.array(z.string()).optional().describe("Episode type filters"),
+      entities: z.array(z.string()).optional().describe("Entity filters"),
+      limit: z.number().default(5).describe("Result limit"),
+      since: z.string().optional().describe("ISO timestamp or epoch ms"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        query,
+        agentId,
+        taskId,
+        types,
+        entities,
+        limit = 5,
+        since,
+        profile = "compact",
+      } = args || {};
+ 
+      if (!query || typeof query !== "string") {
+        return ctx.errorEnvelope(
+          "EPISODE_RECALL_INVALID_INPUT",
+          "Field 'query' is required.",
+          true,
+        );
+      }
+ 
+      const episodeEngine = ctx.engines.episode as
+        | {
+            recall: (args: {
+              query: string;
+              projectId: string;
+              agentId?: string;
+              taskId?: string;
+              types?: EpisodeType[];
+              entities?: string[];
+              limit: number;
+              since?: number;
+            }) => Promise<unknown[]>;
+          }
+        | undefined;
+ 
+      try {
+        const sinceMs = ctx.toEpochMillis(since);
+        const { projectId } = ctx.getActiveProjectContext();
+        const explicitEntities = Array.isArray(entities)
+          ? entities.map((item) => String(item))
+          : [];
+        const embeddingEntityHints = await ctx.inferEpisodeEntityHints(query, limit);
+        const mergedEntities = [...new Set([...explicitEntities, ...embeddingEntityHints])];
+        const episodes = await episodeEngine!.recall({
+          query,
+          projectId,
+          agentId,
+          taskId,
+          types: Array.isArray(types)
+            ? types.map((item) => String(item).toUpperCase() as EpisodeType)
+            : undefined,
+          entities: mergedEntities.length ? mergedEntities : undefined,
+          limit,
+          since: sinceMs || undefined,
+        });
+ 
+        return ctx.formatSuccess(
+          {
+            query,
+            projectId,
+            entityHints: profile === "debug" ? embeddingEntityHints : undefined,
+            count: episodes.length,
+            episodes,
+          },
+          profile,
+          `Recalled ${episodes.length} episode(s).`,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("EPISODE_RECALL_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "decision_query",
+    category: "memory",
+    description: "Query decision episodes for a target topic",
+    inputShape: {
+      query: z.string().describe("Decision query text"),
+      affectedFiles: z.array(z.string()).optional().describe("Related files/entities"),
+      taskId: z.string().optional().describe("Task filter"),
+      agentId: z.string().optional().describe("Agent filter"),
+      limit: z.number().default(5).describe("Result limit"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        query,
+        affectedFiles = [],
+        limit = 5,
+        taskId,
+        agentId,
+        profile = "compact",
+      } = args || {};
+ 
+      Iif (!query || typeof query !== "string") {
+        return ctx.errorEnvelope(
+          "DECISION_QUERY_INVALID_INPUT",
+          "Field 'query' is required.",
+          true,
+        );
+      }
+ 
+      const episodeEngine = ctx.engines.episode as
+        | {
+            decisionQuery: (args: {
+              query: string;
+              projectId: string;
+              taskId?: string;
+              agentId?: string;
+              entities?: string[];
+              limit: number;
+            }) => Promise<unknown[]>;
+          }
+        | undefined;
+ 
+      try {
+        const { projectId } = ctx.getActiveProjectContext();
+        const decisions = await episodeEngine!.decisionQuery({
+          query,
+          projectId,
+          taskId,
+          agentId,
+          entities: Array.isArray(affectedFiles)
+            ? affectedFiles.map((item) => String(item))
+            : undefined,
+          limit,
+        });
+ 
+        return ctx.formatSuccess(
+          {
+            query,
+            projectId,
+            count: decisions.length,
+            decisions,
+          },
+          profile,
+          `Found ${decisions.length} decision episode(s).`,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("DECISION_QUERY_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "reflect",
+    category: "memory",
+    description: "Synthesize reflections and learning nodes from recent episodes",
+    inputShape: {
+      taskId: z.string().optional().describe("Task filter"),
+      agentId: z.string().optional().describe("Agent filter"),
+      limit: z.number().default(20).describe("Episodes to analyze"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { taskId, agentId, limit = 20, profile = "compact" } = args || {};
+ 
+      const episodeEngine = ctx.engines.episode as
+        | {
+            reflect: (args: {
+              taskId?: string;
+              agentId?: string;
+              limit: number;
+              projectId: string;
+            }) => Promise<{ learningsCreated: number }>;
+          }
+        | undefined;
+ 
+      try {
+        const { projectId } = ctx.getActiveProjectContext();
+        const result = await episodeEngine!.reflect({
+          taskId,
+          agentId,
+          limit,
+          projectId,
+        });
+ 
+        return ctx.formatSuccess(
+          result,
+          profile,
+          `Reflection completed with ${result.learningsCreated} learning(s).`,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("REFLECT_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "agent_claim",
+    category: "coordination",
+    description: "Create a coordination claim for a task or code target with conflict detection",
+    inputShape: {
+      targetId: z.string().describe("Target task/code node id"),
+      claimType: z
+        .enum(["task", "file", "function", "feature"])
+        .default("task")
+        .describe("Claim target type"),
+      intent: z.string().describe("Natural language intent"),
+      taskId: z.string().optional().describe("Related task id"),
+      agentId: z.string().optional().describe("Agent identifier"),
+      sessionId: z.string().optional().describe("Session identifier"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        targetId,
+        claimType = "task",
+        intent,
+        taskId,
+        agentId,
+        sessionId,
+        profile = "compact",
+      } = args || {};
+ 
+      if (!targetId || !intent) {
+        return ctx.errorEnvelope(
+          "AGENT_CLAIM_INVALID_INPUT",
+          "Fields 'targetId' and 'intent' are required.",
+          true,
+        );
+      }
+ 
+      const coordinationEngine = ctx.engines.coordination as
+        | {
+            claim: (args: {
+              targetId: string;
+              claimType: ClaimType;
+              intent: string;
+              taskId?: string;
+              agentId: string;
+              sessionId: string;
+              projectId: string;
+            }) => Promise<{ status: string; claimId?: string } & Record<string, unknown>>;
+          }
+        | undefined;
+ 
+      try {
+        const runtimeSessionId = ctx.getCurrentSessionId() || "session-unknown";
+        const runtimeAgentId = String(agentId || env.LXRAG_AGENT_ID);
+        const { projectId } = ctx.getActiveProjectContext();
+ 
+        const result = await coordinationEngine!.claim({
+          targetId: String(targetId),
+          claimType: String(claimType).toLowerCase() as ClaimType,
+          intent: String(intent),
+          taskId: taskId ? String(taskId) : undefined,
+          agentId: runtimeAgentId,
+          sessionId: String(sessionId || runtimeSessionId),
+          projectId,
+        });
+ 
+        return ctx.formatSuccess(
+          {
+            projectId,
+            ...result,
+          },
+          profile,
+          result.status === "CONFLICT"
+            ? `Conflict detected for target ${targetId}.`
+            : `Claim ${result.claimId} created for ${targetId}.`,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("AGENT_CLAIM_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "agent_release",
+    category: "coordination",
+    description: "Release an active claim",
+    inputShape: {
+      claimId: z.string().describe("Claim id"),
+      outcome: z.string().optional().describe("Optional outcome summary"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { claimId, outcome, profile = "compact" } = args || {};
+ 
+      Iif (!claimId) {
+        return ctx.errorEnvelope(
+          "AGENT_RELEASE_INVALID_INPUT",
+          "Field 'claimId' is required.",
+          true,
+        );
+      }
+ 
+      const coordinationEngine = ctx.engines.coordination as
+        | {
+            release: (
+              claimId: string,
+              outcome?: string,
+            ) => Promise<{ found: boolean; alreadyClosed: boolean }>;
+          }
+        | undefined;
+ 
+      try {
+        const feedback = await coordinationEngine!.release(String(claimId), outcome);
+ 
+        return ctx.formatSuccess(
+          {
+            claimId: String(claimId),
+            released: feedback.found && !feedback.alreadyClosed,
+            alreadyClosed: feedback.alreadyClosed,
+            notFound: !feedback.found,
+            outcome: outcome || null,
+          },
+          profile,
+          feedback.found ? `Claim ${claimId} released.` : `Claim ${claimId} not found.`,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("AGENT_RELEASE_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "agent_status",
+    category: "coordination",
+    description: "Get active claims and recent episodes for an agent",
+    inputShape: {
+      agentId: z.string().optional().describe("Agent identifier (omit to list all agents)"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { agentId, profile = "compact" } = args || {};
+ 
+      const coordinationEngine = ctx.engines.coordination as
+        | {
+            overview: (projectId: string) => Promise<{
+              activeClaims: unknown[];
+              staleClaims: unknown[];
+            }>;
+            status: (
+              agentId: string,
+              projectId: string,
+            ) => Promise<{ activeClaims: unknown[] } & Record<string, unknown>>;
+          }
+        | undefined;
+ 
+      try {
+        const { projectId } = ctx.getActiveProjectContext();
+ 
+        if (!agentId || typeof agentId !== "string") {
+          const overview = await coordinationEngine!.overview(projectId);
+          return ctx.formatSuccess(
+            {
+              projectId,
+              mode: "overview",
+              ...overview,
+            },
+            profile,
+            `Fleet: ${overview.activeClaims.length} active claim(s), ${overview.staleClaims.length} stale.`,
+          );
+        }
+ 
+        const status = await coordinationEngine!.status(agentId, projectId);
+ 
+        return ctx.formatSuccess(
+          {
+            projectId,
+            ...status,
+          },
+          profile,
+          `Agent ${agentId} has ${status.activeClaims.length} active claim(s).`,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("AGENT_STATUS_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "coordination_overview",
+    category: "coordination",
+    description: "Fleet-wide claim view including active claims, stale claims, and conflicts",
+    inputShape: {
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { profile = "compact" } = args || {};
+ 
+      const coordinationEngine = ctx.engines.coordination as
+        | {
+            overview: (projectId: string) => Promise<{
+              activeClaims: unknown[];
+              staleClaims: unknown[];
+            }>;
+          }
+        | undefined;
+ 
+      try {
+        const { projectId } = ctx.getActiveProjectContext();
+        const overview = await coordinationEngine!.overview(projectId);
+ 
+        return ctx.formatSuccess(
+          {
+            projectId,
+            ...overview,
+          },
+          profile,
+          `Coordination overview: ${overview.activeClaims.length} active claim(s), ${overview.staleClaims.length} stale claim(s).`,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("COORDINATION_OVERVIEW_FAILED", String(error), true);
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/ref-tools.ts.html b/coverage/lcov-report/src/tools/handlers/ref-tools.ts.html new file mode 100644 index 0000000..858b524 --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/ref-tools.ts.html @@ -0,0 +1,1231 @@ + + + + + + Code coverage report for src/tools/handlers/ref-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers ref-tools.ts

+
+ +
+ 86.42% + Statements + 121/140 +
+ + +
+ 66.08% + Branches + 76/115 +
+ + +
+ 92.3% + Functions + 12/13 +
+ + +
+ 92.74% + Lines + 115/124 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +1x +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +2x +2x +2x +  +2x +  +3x +  +  +  +  +2x +2x +2x +  +  +4x +  +2x +1x +1x +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +4x +  +2x +2x +2x +2x +2x +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +  +  +2x +  +3x +1x +1x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +  +1x +1x +1x +2x +2x +2x +2x +  +  +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +2x +4x +4x +4x +4x +  +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +2x +3x +3x +3x +3x +6x +  +3x +1x +1x +  +  +2x +1x +1x +1x +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +4x +4x +4x +4x +5x +2x +2x +  +3x +3x +3x +2x +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +4x +4x +4x +4x +4x +4x +5x +2x +2x +3x +3x +  +  +  +  +  +4x +  +  +2x +  + 
/**
+ * Reference Query Tools
+ * Registry-backed reference query tool definitions.
+ *
+ * Tools:
+ * - ref_query: search external reference repositories for documentation and code patterns
+ *
+ * This module is completely self-contained with no engine dependencies.
+ * It only uses the file system and DocsParser for scanning and parsing.
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import { DocsParser, findMarkdownFiles, type ParsedSection } from "../../parsers/docs-parser.js";
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const refToolDefinitions: ToolDefinition[] = [
+  {
+    name: "ref_query",
+    category: "ref",
+    description:
+      "Query a reference repository on the same machine for architecture insights, design patterns, conventions, or code examples. Useful for borrowing context from a well-structured sibling repo when working on the current workspace.",
+    inputShape: {
+      repoPath: z.string().describe("Absolute path to the reference repository on this machine"),
+      query: z
+        .string()
+        .default("")
+        .describe(
+          "What to look for — architecture patterns, conventions, a specific concept, or a code example",
+        ),
+      mode: z
+        .enum(["auto", "docs", "architecture", "code", "patterns", "all", "structure"])
+        .default("auto")
+        .describe(
+          "auto = infer from query; docs/architecture = markdown only; code/patterns = source files only; structure = dir tree only; all = everything",
+        ),
+      symbol: z
+        .string()
+        .optional()
+        .describe(
+          "Specific symbol name (function/class/interface) to locate in the reference repo",
+        ),
+      limit: z.number().int().min(1).max(20).default(10).describe("Max results to return"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        repoPath,
+        query = "",
+        mode = "auto",
+        symbol,
+        limit = 10,
+        profile = "compact",
+      } = args ?? {};
+ 
+      if (!repoPath || typeof repoPath !== "string") {
+        return ctx.errorEnvelope(
+          "REF_REPO_MISSING",
+          "repoPath is required",
+          false,
+          "Provide the absolute path to the reference repository on this machine.",
+        );
+      }
+ 
+      const resolvedRepo = path.resolve(repoPath);
+      Iif (!fs.existsSync(resolvedRepo)) {
+        return ctx.errorEnvelope(
+          "REF_REPO_NOT_FOUND",
+          `Path does not exist: ${resolvedRepo}`,
+          false,
+          "Ensure the repository is cloned and the path is accessible from this machine/container.",
+        );
+      }
+ 
+      try {
+        const repoName = path.basename(resolvedRepo);
+        const findings: any[] = [];
+ 
+        const effectiveMode = mode === "auto" ? inferRefMode(query, symbol) : mode;
+ 
+        if (
+          effectiveMode === "docs" ||
+          effectiveMode === "architecture" ||
+          effectiveMode === "all"
+        ) {
+          const parser = new DocsParser();
+          const mdFiles = findMarkdownFiles(resolvedRepo);
+          const queryTerms = query
+            .toLowerCase()
+            .split(/\s+/)
+            .filter((t: string) => t.length > 2);
+ 
+          for (const mdFile of mdFiles.slice(0, 60)) {
+            try {
+              const doc = parser.parseFile(mdFile, resolvedRepo);
+              for (const sec of doc.sections) {
+                const score = scoreRefSection(sec, queryTerms, symbol);
+                Eif (score > 0 || queryTerms.length === 0) {
+                  findings.push({
+                    type: "doc",
+                    file: doc.relativePath,
+                    kind: doc.kind,
+                    heading: sec.heading || doc.title,
+                    score,
+                    excerpt: sec.content.slice(0, 300).trim(),
+                    line: sec.startLine,
+                  });
+                }
+              }
+            } catch {
+              // skip unreadable files
+            }
+          }
+        }
+ 
+        Eif (effectiveMode === "code" || effectiveMode === "patterns" || effectiveMode === "all") {
+          const sourceExts = [
+            ".ts",
+            ".tsx",
+            ".js",
+            ".mjs",
+            ".cjs",
+            ".py",
+            ".go",
+            ".java",
+            ".rs",
+            ".rb",
+            ".cs",
+          ];
+          const sourceFiles = scanRefSourceFiles(resolvedRepo, sourceExts);
+          const queryTerms = query
+            .toLowerCase()
+            .split(/\s+/)
+            .filter((t: string) => t.length > 2);
+ 
+          for (const filePath of sourceFiles.slice(0, 120)) {
+            try {
+              const content = fs.readFileSync(filePath, "utf-8");
+              const relPath = path.relative(resolvedRepo, filePath);
+              const score = scoreRefCode(content, queryTerms, symbol, relPath);
+              Eif (score > 0) {
+                const excerpt = extractRefExcerpt(content, queryTerms, symbol, 6);
+                findings.push({
+                  type: "code",
+                  file: relPath,
+                  score,
+                  excerpt: excerpt || content.slice(0, 300),
+                });
+              }
+            } catch {
+              // skip unreadable files
+            }
+          }
+        }
+ 
+        Eif (effectiveMode === "all" || effectiveMode === "structure") {
+          const tree = buildRefDirTree(resolvedRepo, 3);
+          findings.push({ type: "structure", file: ".", score: 0, tree });
+        }
+ 
+        const sorted = findings
+          .sort((a, b) => {
+            if (a.type === "structure") return 1;
+            Iif (b.type === "structure") return -1;
+            return (b.score ?? 0) - (a.score ?? 0);
+          })
+          .slice(0, limit);
+ 
+        return ctx.formatSuccess(
+          {
+            repoName,
+            repoPath: resolvedRepo,
+            query,
+            symbol: symbol ?? null,
+            mode: effectiveMode,
+            resultCount: sorted.length,
+            findings: sorted,
+          },
+          profile,
+          `${sorted.length} result(s) from reference repo ${repoName}`,
+          "ref_query",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "REF_QUERY_FAILED",
+          error instanceof Error ? error.message : String(error),
+          true,
+        );
+      }
+    },
+  },
+];
+ 
+// ──────────────────────────────────────────────────────────────────────────────
+// Private Helpers (internal to this module)
+// ──────────────────────────────────────────────────────────────────────────────
+ 
+/**
+ * Infer the search mode based on query content
+ */
+function inferRefMode(
+  query: string,
+  symbol?: string,
+): "docs" | "code" | "architecture" | "patterns" | "all" {
+  Iif (symbol) return "code";
+  const lower = (query || "").toLowerCase();
+  Iif (
+    /(architect|structure|pattern|design|layer|module|overview|convention|best.?practice)/.test(
+      lower,
+    )
+  )
+    return "architecture";
+  Iif (/(how to|example|guide|decision|adr|changelog)/.test(lower)) return "docs";
+  Iif (/(function|class|method|import|export|interface|type|impl|usage)/.test(lower)) return "code";
+  return "all";
+}
+ 
+/**
+ * Score a documentation section based on query terms
+ */
+function scoreRefSection(section: ParsedSection, queryTerms: string[], symbol?: string): number {
+  let score = 0;
+  const text = `${section.heading} ${section.content}`.toLowerCase();
+  for (const term of queryTerms) {
+    const re = new RegExp(term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
+    const count = (text.match(re) ?? []).length;
+    Eif (count > 0) {
+      score += count * (section.heading.toLowerCase().includes(term) ? 3 : 1);
+    }
+  }
+  Iif (symbol) {
+    const symLower = symbol.toLowerCase();
+    if (section.backtickRefs.some((r) => r.toLowerCase().includes(symLower))) score += 10;
+    else if (text.includes(symLower)) score += 5;
+  }
+  return score;
+}
+ 
+/**
+ * Score source code based on query terms
+ */
+function scoreRefCode(
+  content: string,
+  queryTerms: string[],
+  symbol: string | undefined,
+  relPath: string,
+): number {
+  let score = 0;
+  const lower = content.toLowerCase();
+  const pathLower = relPath.toLowerCase();
+  for (const term of queryTerms) {
+    const re = new RegExp(term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
+    const count = (lower.match(re) ?? []).length;
+    score += count;
+    if (pathLower.includes(term)) score += 3;
+  }
+  Iif (symbol) {
+    const symLower = symbol.toLowerCase();
+    const symCount = (
+      lower.match(new RegExp(symLower.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g")) ?? []
+    ).length;
+    score += symCount * 5;
+  }
+  return score;
+}
+ 
+/**
+ * Extract a meaningful excerpt from code based on query terms
+ */
+function extractRefExcerpt(
+  content: string,
+  queryTerms: string[],
+  symbol: string | undefined,
+  contextLines: number,
+): string {
+  const lines = content.split("\n");
+  let bestLine = 0;
+  let bestScore = 0;
+  for (let i = 0; i < lines.length; i++) {
+    const lower = lines[i].toLowerCase();
+    let score = 0;
+    Iif (symbol && lower.includes(symbol.toLowerCase())) score += 10;
+    for (const term of queryTerms) {
+      if (lower.includes(term)) score++;
+    }
+    if (score > bestScore) {
+      bestScore = score;
+      bestLine = i;
+    }
+  }
+  if (bestScore === 0) return lines.slice(0, contextLines * 2).join("\n");
+  const start = Math.max(0, bestLine - contextLines);
+  const end = Math.min(lines.length, bestLine + contextLines + 1);
+  return lines.slice(start, end).join("\n");
+}
+ 
+/**
+ * Recursively scan for source files matching given extensions
+ */
+function scanRefSourceFiles(rootPath: string, extensions: string[]): string[] {
+  const results: string[] = [];
+  const ignoreDirs = new Set([
+    "node_modules",
+    "dist",
+    ".git",
+    ".next",
+    "coverage",
+    "__pycache__",
+    ".venv",
+    "vendor",
+    "build",
+    ".turbo",
+  ]);
+ 
+  const walk = (dir: string, depth: number) => {
+    Iif (depth > 7) return;
+    try {
+      const entries = fs.readdirSync(dir, { withFileTypes: true });
+      for (const entry of entries) {
+        if (entry.isDirectory()) {
+          Eif (!ignoreDirs.has(entry.name) && !entry.name.startsWith(".")) {
+            walk(path.join(dir, entry.name), depth + 1);
+          }
+        E} else if (entry.isFile()) {
+          const ext = path.extname(entry.name).toLowerCase();
+          if (extensions.includes(ext)) {
+            results.push(path.join(dir, entry.name));
+          }
+        }
+      }
+    } catch {
+      // skip permission errors
+    }
+  };
+ 
+  walk(rootPath, 0);
+  return results;
+}
+ 
+/**
+ * Build a directory tree structure for display
+ */
+function buildRefDirTree(rootPath: string, maxDepth: number): any {
+  const ignoreDirs = new Set([
+    "node_modules",
+    "dist",
+    ".git",
+    ".next",
+    "coverage",
+    "__pycache__",
+    ".venv",
+    "vendor",
+    "build",
+    ".turbo",
+  ]);
+ 
+  const walk = (dir: string, depth: number): any => {
+    Iif (depth > maxDepth) return null;
+    const name = path.basename(dir);
+    const children: any[] = [];
+    try {
+      const entries = fs.readdirSync(dir, { withFileTypes: true }).slice(0, 40);
+      for (const entry of entries) {
+        if (entry.isDirectory() && !ignoreDirs.has(entry.name) && !entry.name.startsWith(".")) {
+          const child = walk(path.join(dir, entry.name), depth + 1);
+          Eif (child) children.push(child);
+        E} else if (entry.isFile()) {
+          children.push({ name: entry.name });
+        }
+      }
+    } catch {
+      // skip
+    }
+    return children.length > 0 ? { name, children } : { name };
+  };
+ 
+  return walk(rootPath, 0);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/task-tools.ts.html b/coverage/lcov-report/src/tools/handlers/task-tools.ts.html new file mode 100644 index 0000000..748cd4b --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/task-tools.ts.html @@ -0,0 +1,1093 @@ + + + + + + Code coverage report for src/tools/handlers/task-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers task-tools.ts

+
+ +
+ 85.13% + Statements + 63/74 +
+ + +
+ 68.57% + Branches + 48/70 +
+ + +
+ 85.71% + Functions + 6/7 +
+ + +
+ 85.13% + Lines + 63/74 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +3x +  +  +3x +  +3x +  +  +  +  +3x +  +  +  +  +  +3x +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +1x +  +  +  +  +1x +1x +1x +1x +1x +  +1x +1x +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +3x +3x +  +3x +3x +2x +  +  +  +2x +  +  +  +  +  +  +  +  +  +1x +1x +  +1x +1x +1x +1x +1x +  +  +  +  +  +  +  +1x +1x +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +3x +  +  +  +  +  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file tools/handlers/task-tools
+ * @description Task and progress-related MCP tool definitions.
+ * @remarks These tools delegate to `ProgressEngine`, with optional coordination hooks.
+ */
+ 
+import * as z from "zod";
+import * as env from "../../env.js";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+import { logger } from "../../utils/logger.js";
+ 
+/**
+ * Registry definitions for task/progress tool endpoints.
+ */
+export const taskToolDefinitions: ToolDefinition[] = [
+  {
+    name: "progress_query",
+    category: "task",
+    description: "Query progress tracking data",
+    inputShape: {
+      query: z.string().describe("Progress query"),
+      status: z
+        .enum(["all", "active", "blocked", "completed"])
+        .optional()
+        .describe("Filter by status"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .optional()
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const profile = args?.profile || "compact";
+      const status = args?.status || args?.filter?.status;
+      const queryText = String(args?.query || args?.type || "task").toLowerCase();
+      const type: "feature" | "task" = queryText.includes("feature") ? "feature" : "task";
+ 
+      const normalizedStatus =
+        status === "active" ? "in-progress" : status === "all" ? undefined : status;
+ 
+      const filter = {
+        ...(args?.filter || {}),
+        ...(normalizedStatus ? { status: normalizedStatus } : {}),
+      };
+ 
+      const progressEngine = ctx.engines.progress as
+        | {
+            query: (type: "feature" | "task", filter?: Record<string, unknown>) => unknown;
+          }
+        | undefined;
+ 
+      try {
+        const result = progressEngine!.query(type, filter);
+        return ctx.formatSuccess(result, profile);
+      } catch (error) {
+        return ctx.errorEnvelope("PROGRESS_QUERY_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "task_update",
+    category: "task",
+    description: "Update task status",
+    inputShape: {
+      taskId: z.string().describe("Task ID"),
+      status: z.string().describe("New status"),
+      notes: z.string().optional().describe("Optional notes"),
+      assignee: z.string().optional().describe("Task assignee"),
+      dueDate: z.string().optional().describe("Task due date"),
+      agentId: z.string().optional().describe("Agent identifier"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { taskId, status, assignee, dueDate, notes, profile = "compact" } = args;
+ 
+      const progressEngine = ctx.engines.progress as
+        | {
+            updateTask: (
+              taskId: string,
+              updates: { status?: string; assignee?: string; dueDate?: string },
+            ) => unknown;
+            persistTaskUpdate: (
+              taskId: string,
+              updates: { status?: string; assignee?: string; dueDate?: string },
+            ) => Promise<boolean>;
+          }
+        | undefined;
+ 
+      const coordinationEngine = ctx.engines.coordination as
+        | {
+            onTaskCompleted: (taskId: string, agentId: string, projectId: string) => Promise<void>;
+          }
+        | undefined;
+ 
+      const episodeEngine = ctx.engines.episode as
+        | {
+            reflect: (args: {
+              taskId: string;
+              agentId: string;
+              projectId: string;
+              limit: number;
+            }) => Promise<{ reflectionId?: string; learningsCreated?: number }>;
+            add: (
+              args: {
+                type: string;
+                content: string;
+                taskId: string;
+                outcome: "success" | "failure" | "partial";
+                agentId: string;
+                sessionId: string;
+                metadata: Record<string, unknown>;
+              },
+              projectId: string,
+            ) => Promise<string>;
+          }
+        | undefined;
+ 
+      try {
+        const updated = progressEngine!.updateTask(taskId, {
+          status,
+          assignee,
+          dueDate,
+        });
+ 
+        Iif (!updated) {
+          return ctx.errorEnvelope(
+            "TASK_NOT_FOUND",
+            `Task not found: ${taskId}`,
+            false,
+            "Use feature_status to list valid task IDs",
+          );
+        }
+ 
+        Eif (status || assignee || dueDate) {
+          const persistedSuccessfully = await progressEngine!.persistTaskUpdate(taskId, {
+            status,
+            assignee,
+            dueDate,
+          });
+          Iif (!persistedSuccessfully) {
+            logger.warn(`[task_update] Failed to persist task update to Memgraph for ${taskId}`);
+          }
+        }
+ 
+        const postActions: Record<string, unknown> = {};
+        Eif (String(status || "").toLowerCase() === "completed") {
+          const sessionId = ctx.getCurrentSessionId() || "session-unknown";
+          const runtimeAgentId = String(assignee || args?.agentId || env.LXRAG_AGENT_ID);
+          const { projectId } = ctx.getActiveProjectContext();
+ 
+          try {
+            await coordinationEngine!.onTaskCompleted(String(taskId), runtimeAgentId, projectId);
+            postActions.claimsReleased = true;
+          } catch (error) {
+            postActions.claimsReleased = false;
+            postActions.claimReleaseError = String(error);
+          }
+ 
+          try {
+            const reflection = await episodeEngine!.reflect({
+              taskId: String(taskId),
+              agentId: runtimeAgentId,
+              projectId,
+              limit: 20,
+            });
+            postActions.reflection = {
+              reflectionId: reflection.reflectionId,
+              learningsCreated: reflection.learningsCreated,
+            };
+          } catch (error) {
+            postActions.reflectionError = String(error);
+          }
+ 
+          try {
+            const decisionEpisodeId = await episodeEngine!.add(
+              {
+                type: "DECISION",
+                content:
+                  `Task ${taskId} marked completed. ${notes ? `Notes: ${String(notes)}` : ""}`.trim(),
+                taskId: String(taskId),
+                outcome: "success",
+                agentId: runtimeAgentId,
+                sessionId,
+                metadata: {
+                  source: "task_update",
+                  status: String(status),
+                  rationale: `Task ${taskId} transitioned to status '${status}' via task_update.${notes ? ` Notes: ${String(notes)}` : ""}`,
+                },
+              },
+              projectId,
+            );
+            postActions.decisionEpisodeId = decisionEpisodeId;
+          } catch (error) {
+            postActions.decisionEpisodeError = String(error);
+          }
+        }
+ 
+        return ctx.formatSuccess({ success: true, task: updated, notes, postActions }, profile);
+      } catch (error) {
+        return ctx.errorEnvelope("TASK_UPDATE_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "feature_status",
+    category: "task",
+    description: "Get feature implementation status",
+    inputShape: {
+      featureId: z.string().describe("Feature ID"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { featureId, profile = "compact" } = args;
+ 
+      const progressEngine = ctx.engines.progress as
+        | {
+            query: (type: "feature" | "task") => {
+              items: Array<{ id: string; name?: string; status?: string }>;
+            };
+            getFeatureStatus: (featureId: string) => unknown;
+          }
+        | undefined;
+ 
+      try {
+        const allFeatures = progressEngine!.query("feature").items;
+ 
+        const requested = String(featureId || "").trim();
+        if (!requested || requested === "*" || requested.toLowerCase() === "list") {
+          return ctx.formatSuccess(
+            {
+              success: true,
+              totalFeatures: allFeatures.length,
+              features: allFeatures.slice(0, 100).map((feature) => ({
+                id: feature.id,
+                name: feature.name || "",
+                status: feature.status || "unknown",
+              })),
+            },
+            profile,
+          );
+        }
+ 
+        let resolvedFeatureId = requested;
+        let status = progressEngine!.getFeatureStatus(resolvedFeatureId);
+ 
+        Eif (!status) {
+          const lowered = requested.toLowerCase();
+          const matched = allFeatures.find((feature) => {
+            const name = String(feature.name || "").toLowerCase();
+            return (
+              feature.id === requested ||
+              feature.id.endsWith(`:${requested}`) ||
+              feature.id.toLowerCase().endsWith(`:${lowered}`) ||
+              name === lowered
+            );
+          });
+ 
+          Eif (matched) {
+            resolvedFeatureId = matched.id;
+            status = progressEngine!.getFeatureStatus(resolvedFeatureId);
+          }
+        }
+ 
+        Iif (!status) {
+          return ctx.formatSuccess(
+            {
+              success: false,
+              error: `Feature not found: ${featureId}`,
+              availableFeatureIds: allFeatures.map((feature) => feature.id).slice(0, 50),
+              hint: "Use feature_status with featureId='list' to inspect available IDs",
+            },
+            profile,
+          );
+        }
+ 
+        return ctx.formatSuccess(
+          {
+            ...(status as Record<string, unknown>),
+            resolvedFeatureId,
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("FEATURE_STATUS_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "blocking_issues",
+    category: "task",
+    description: "Find blocking issues",
+    inputShape: {
+      type: z.enum(["all", "feature", "task"]).optional().describe("Scope of blockers"),
+      context: z.string().optional().describe("Issue context"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const type = args?.type ?? "all";
+      const profile = args?.profile || "compact";
+ 
+      const progressEngine = ctx.engines.progress as
+        | {
+            getBlockingIssues: (type: string) => unknown[];
+          }
+        | undefined;
+ 
+      try {
+        const issues = progressEngine!.getBlockingIssues(type);
+ 
+        return ctx.formatSuccess(
+          {
+            type,
+            blockingIssues: issues.slice(0, 20),
+            totalBlocked: issues.length,
+            recommendation:
+              issues.length > 0
+                ? `Address ${issues.length} blocking issue(s)`
+                : "No blocking issues",
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("BLOCKING_ISSUES_FAILED", String(error), true);
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/handlers/test-tools.ts.html b/coverage/lcov-report/src/tools/handlers/test-tools.ts.html new file mode 100644 index 0000000..168a34f --- /dev/null +++ b/coverage/lcov-report/src/tools/handlers/test-tools.ts.html @@ -0,0 +1,1333 @@ + + + + + + Code coverage report for src/tools/handlers/test-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers test-tools.ts

+
+ +
+ 73.95% + Statements + 71/96 +
+ + +
+ 51.89% + Branches + 41/79 +
+ + +
+ 84.61% + Functions + 11/13 +
+ + +
+ 76.74% + Lines + 66/86 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +2x +2x +2x +  +2x +  +  +2x +  +  +2x +  +  +  +  +2x +2x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +  +6x +3x +3x +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +1x +  +  +  +  +  +  +  +5x +6x +  +  +  +5x +5x +5x +  +6x +  +5x +  +  +  +  +  +  +5x +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +  +  +  +  +3x +3x +  +3x +12x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +7x +7x +  +  +  +  +  +7x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +6x +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +4x +2x +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +2x +  +  +  +  +  +4x +  +4x +4x +4x +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Test Intelligence Tools
+ * Registry-backed test tool definitions.
+ *
+ * Tools:
+ * - test_select: select affected tests for changed files
+ * - test_categorize: categorize tests by type
+ * - impact_analyze: analyze blast radius of changes
+ * - test_run: execute tests with vitest
+ */
+ 
+import * as path from "path";
+import { execWithTimeout } from "../../utils/exec-utils.js";
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+/**
+ * Determine the command and arguments used to execute tests.
+ *
+ * Priority:
+ * 1. `config.testing.testRunner` — explicit override in .lxrag/config.json
+ * 2. Auto-detect from file extension of the first test file:
+ *    .py → pytest, .rb → bundle exec rspec, .go → go test, else → vitest
+ */
+function resolveTestRunner(
+  testFiles: string[],
+  cwd: string,
+  config?: { testRunner?: { command: string; args?: string[] } },
+): { cmd: string; env?: Record<string, string> } {
+  // 1. Explicit config override
+  Iif (config?.testRunner) {
+    const { command, args = [] } = config.testRunner;
+    return { cmd: [command, ...args, ...testFiles].join(" ") };
+  }
+ 
+  // 2. Auto-detect from file extensions
+  const hasPy = testFiles.some((f) => f.endsWith(".py"));
+  const hasRb = testFiles.some((f) => f.endsWith(".rb"));
+  const hasGo = testFiles.some((f) => f.endsWith(".go"));
+ 
+  Iif (hasPy) {
+    return { cmd: ["pytest", ...testFiles].join(" ") };
+  }
+  Iif (hasRb) {
+    return { cmd: ["bundle", "exec", "rspec", ...testFiles].join(" ") };
+  }
+  Iif (hasGo) {
+    return { cmd: ["go", "test", ...testFiles].join(" ") };
+  }
+ 
+  // 3. Default: vitest for JS/TS
+  const vitestBin = path.resolve(cwd, "node_modules", ".bin", "vitest");
+  const env: Record<string, string> = {
+    PATH: `${path.resolve(cwd, "node_modules", ".bin")}:${path.dirname(process.execPath)}:${process.env.PATH ?? ""}`,
+    NODE: process.execPath,
+  };
+  return {
+    cmd: `"${process.execPath}" "${vitestBin}" run --reporter=verbose ${testFiles.join(" ")}`,
+    env,
+  };
+}
+ 
+/**
+ * Resolve which source files directly import the given changed files by
+ * traversing IMPORTS → REFERENCES edges in Memgraph.
+ *
+ * Falls back to the in-memory index if Memgraph is not connected.
+ * Returns at most 50 paths, sorted alphabetically.
+ */
+async function resolveDirectImpact(ctx: HandlerBridge, changedFiles: string[]): Promise<string[]> {
+  const memgraph = ctx.context?.memgraph;
+ 
+  // Try Memgraph graph traversal first (most accurate, uses persisted graph)
+  if (memgraph?.isConnected?.()) {
+    try {
+      const projectId = ctx.getActiveProjectContext?.()?.projectId ?? "";
+ 
+      // Normalize input: accept both relative and absolute paths as search keys
+      const result = await memgraph.executeCypher(
+        `MATCH (changed:FILE)
+         WHERE changed.projectId = $projectId
+           AND (changed.relativePath IN $changedPaths
+                OR changed.path IN $changedPaths
+                OR any(cp IN $changedPaths WHERE changed.relativePath = cp
+                                              OR changed.path = cp
+                                              OR changed.relativePath ENDS WITH cp
+                                              OR changed.path ENDS WITH cp))
+         WITH collect(DISTINCT changed) AS changedFiles
+         UNWIND changedFiles AS changed
+         MATCH (changed)<-[:REFERENCES]-(imp:IMPORT)<-[:IMPORTS]-(importer:FILE)
+         WHERE importer.projectId = $projectId
+           AND importer.id <> changed.id
+         RETURN DISTINCT
+           coalesce(importer.relativePath, importer.path) AS path
+         ORDER BY path
+         LIMIT 50`,
+        { projectId, changedPaths: changedFiles },
+      );
+ 
+      const paths: string[] = result.data.map((row: any) => String(row.path ?? "")).filter(Boolean);
+ 
+      if (paths.length > 0) {
+        return paths;
+      }
+    } catch {
+      // Fall through to index-based fallback
+    }
+  }
+ 
+  // Fallback: traverse in-memory index (less accurate, no projectId scoping)
+  const index = ctx.context?.index;
+  Iif (!index?.getRelationshipsTo) {
+    return [];
+  }
+ 
+  const importers = new Set<string>();
+  try {
+    const fileNodes: any[] = index.getNodesByType("FILE") ?? [];
+ 
+    for (const changed of changedFiles) {
+      // Find FILE node whose relativePath or path matches the changed file
+      const targetNode = fileNodes.find(
+        (n: any) =>
+          n.properties?.relativePath === changed ||
+          n.properties?.path === changed ||
+          n.properties?.relativePath?.endsWith(changed) ||
+          n.properties?.path?.endsWith(changed),
+      );
+      Eif (!targetNode) continue;
+ 
+      // incoming REFERENCES edges → IMPORT nodes
+      const refsToTarget: any[] = index.getRelationshipsTo(targetNode.id) ?? [];
+      for (const ref of refsToTarget) {
+        if (ref.type !== "REFERENCES") continue;
+        // incoming IMPORTS edges → source FILE nodes
+        const importsToImp: any[] = index.getRelationshipsTo(ref.from) ?? [];
+        for (const imp of importsToImp) {
+          if (imp.type !== "IMPORTS") continue;
+          const sourceNode = index.getNode(imp.from);
+          if (!sourceNode) continue;
+          const p =
+            sourceNode.properties?.relativePath || sourceNode.properties?.path || sourceNode.id;
+          if (p && p !== changed) importers.add(p);
+        }
+      }
+    }
+  } catch {
+    // best-effort
+  }
+ 
+  return Array.from(importers).sort().slice(0, 50);
+}
+ 
+export const testToolDefinitions: ToolDefinition[] = [
+  {
+    name: "test_select",
+    category: "test",
+    description: "Select tests affected by changed files",
+    inputShape: {
+      changedFiles: z.array(z.string()).describe("Files that changed"),
+      mode: z
+        .enum(["direct", "transitive", "full"])
+        .default("transitive")
+        .describe("Selection mode"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { changedFiles, includeIntegration = true, profile = "compact" } = args;
+ 
+      const testEngine = ctx.engines.test as
+        | {
+            selectAffectedTests: (
+              changedFiles: string[],
+              includeIntegration?: boolean,
+              depth?: number,
+            ) => any;
+          }
+        | undefined;
+ 
+      try {
+        const result = testEngine!.selectAffectedTests(changedFiles, includeIntegration);
+ 
+        return ctx.formatSuccess(result, profile);
+      } catch (error) {
+        return ctx.errorEnvelope("TEST_SELECT_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "test_categorize",
+    category: "test",
+    description: "Categorize tests by type",
+    inputShape: {
+      testFiles: z.array(z.string()).optional().describe("Test files to categorize"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { testFiles = [], profile = "compact" } = args;
+ 
+      const testEngine = ctx.engines.test as
+        | {
+            getStatistics: () => {
+              unitTests: number;
+              integrationTests: number;
+              performanceTests: number;
+              e2eTests: number;
+            };
+          }
+        | undefined;
+ 
+      try {
+        console.error(`[Test] Categorizing ${testFiles.length} test files...`);
+        const stats = testEngine!.getStatistics();
+ 
+        // Use config-supplied patterns when available; fall back to
+        // language-agnostic wildcard patterns (no hardcoded .ts extension).
+        const cfgCategories: Array<{ id: string; patterns: string[] }> =
+          ctx.context.config?.testing?.categories ?? [];
+        const cfgById = Object.fromEntries(cfgCategories.map((c) => [c.id, c]));
+ 
+        const buildPattern = (id: string, fallback: string): string =>
+          cfgById[id]?.patterns?.[0] ?? fallback;
+ 
+        return ctx.formatSuccess(
+          {
+            statistics: stats,
+            categorization: {
+              unit: {
+                count: stats.unitTests,
+                pattern: buildPattern("unit", "**/__tests__/**/*.test.*"),
+                timeout: 5000,
+              },
+              integration: {
+                count: stats.integrationTests,
+                pattern: buildPattern("integration", "**/__tests__/**/*.integration.test.*"),
+                timeout: 15000,
+              },
+              performance: {
+                count: stats.performanceTests,
+                pattern: buildPattern("performance", "**/*.performance.test.*"),
+                timeout: 30000,
+              },
+              e2e: {
+                count: stats.e2eTests,
+                pattern: buildPattern("e2e", "**/e2e/**/*.test.*"),
+                timeout: 60000,
+              },
+            },
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("TEST_CATEGORIZE_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "impact_analyze",
+    category: "test",
+    description: "Analyze impact of changes",
+    inputShape: {
+      files: z.array(z.string()).optional().describe("Changed files"),
+      changedFiles: z.array(z.string()).optional().describe("Changed files (alternate contract)"),
+      depth: z.number().default(3).describe("Analysis depth"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const profile = args?.profile || "compact";
+      const depth = typeof args?.depth === "number" ? args.depth : 2;
+      const changedFiles: string[] = Array.isArray(args?.files)
+        ? args.files
+        : Array.isArray(args?.changedFiles)
+          ? args.changedFiles
+          : [];
+ 
+      if (!changedFiles.length) {
+        return ctx.formatSuccess(
+          {
+            changedFiles: [],
+            analysis: {
+              directImpact: [],
+              estimatedTestTime: 0,
+              coverage: {
+                percentage: 0,
+                testsSelected: 0,
+                totalTests: 0,
+              },
+              blastRadius: {
+                testsAffected: 0,
+                percentage: 0,
+                recommendation: "Provide at least one changed file",
+              },
+            },
+            warning: "No changed files were provided",
+          },
+          profile,
+        );
+      }
+ 
+      const testEngine = ctx.engines.test as
+        | {
+            selectAffectedTests: (
+              changedFiles: string[],
+              includeIntegration?: boolean,
+              depth?: number,
+            ) => {
+              estimatedTime: number;
+              coverage: { percentage: number };
+              selectedTests: string[];
+            };
+          }
+        | undefined;
+ 
+      try {
+        const result = testEngine!.selectAffectedTests(changedFiles, true, depth);
+        const directImpact = await resolveDirectImpact(ctx, changedFiles);
+ 
+        return ctx.formatSuccess(
+          {
+            changedFiles,
+            analysis: {
+              directImpact,
+              estimatedTestTime: result.estimatedTime,
+              coverage: result.coverage,
+              blastRadius: {
+                testsAffected: result.selectedTests.length,
+                percentage: result.coverage.percentage,
+                recommendation:
+                  result.coverage.percentage > 50 ? "Run full suite" : "Run affected tests",
+              },
+            },
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("IMPACT_ANALYZE_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "test_run",
+    category: "test",
+    description: "Execute test suite",
+    inputShape: {
+      testFiles: z.array(z.string()).describe("Test files to run"),
+      parallel: z.boolean().default(true).describe("Run tests in parallel"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { testFiles = [], parallel: _parallel = true, profile = "compact" } = args;
+ 
+      try {
+        if (!testFiles || testFiles.length === 0) {
+          return ctx.formatSuccess(
+            {
+              status: "error",
+              message: "No test files specified",
+              executed: 0,
+              passed: 0,
+              failed: 0,
+            },
+            profile,
+          );
+        }
+ 
+        const cwd = process.cwd();
+ 
+        // Resolve runner: config > auto-detect by extension > vitest fallback
+        const { cmd, env: runnerEnv } = resolveTestRunner(
+          testFiles,
+          cwd,
+          ctx.context.config?.testing,
+        );
+ 
+        console.error(`[ToolHandlers] Executing: ${cmd}`);
+ 
+        try {
+          const augmentedEnv = { ...process.env, ...(runnerEnv ?? {}) };
+          const output = execWithTimeout(cmd, {
+            cwd: process.cwd(),
+            encoding: "utf-8",
+            stdio: ["pipe", "pipe", "pipe"],
+            env: augmentedEnv,
+          });
+ 
+          return ctx.formatSuccess(
+            {
+              status: "passed",
+              message: "All tests passed",
+              output: output.substring(0, 1000),
+              testsRun: testFiles.length,
+            },
+            profile,
+          );
+        } catch (execError: any) {
+          return ctx.formatSuccess(
+            {
+              status: "failed",
+              message: "Some tests failed",
+              error: execError.message.substring(0, 500),
+              output: execError.stdout?.toString().substring(0, 500) || "",
+              testsRun: testFiles.length,
+            },
+            profile,
+          );
+        }
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "TEST_RUN_FAILED",
+          `Test execution failed: ${error instanceof Error ? error.message : String(error)}`,
+          true,
+        );
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/index.html b/coverage/lcov-report/src/tools/index.html new file mode 100644 index 0000000..4e868a7 --- /dev/null +++ b/coverage/lcov-report/src/tools/index.html @@ -0,0 +1,191 @@ + + + + + + Code coverage report for src/tools + + + + + + + + + +
+
+

All files src/tools

+
+ +
+ 57.46% + Statements + 431/750 +
+ + +
+ 48.75% + Branches + 313/642 +
+ + +
+ 55.55% + Functions + 75/135 +
+ + +
+ 58.37% + Lines + 425/728 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
contract-validator.ts +
+
92%23/2566.66%12/18100%7/795.65%22/23
registry.ts +
+
100%3/3100%0/0100%1/1100%3/3
tool-handler-base.ts +
+
71.53%299/41865.2%223/34283.05%49/5971.6%295/412
tool-handlers.ts +
+
46.28%106/22931.45%78/24833.96%18/5347.94%105/219
types.ts +
+
0%0/00%0/00%0/00%0/0
vector-tools.ts +
+
0%0/750%0/340%0/150%0/71
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/registry.ts.html b/coverage/lcov-report/src/tools/registry.ts.html new file mode 100644 index 0000000..1fa2ab6 --- /dev/null +++ b/coverage/lcov-report/src/tools/registry.ts.html @@ -0,0 +1,211 @@ + + + + + + Code coverage report for src/tools/registry.ts + + + + + + + + + +
+
+

All files / src/tools registry.ts

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +156x +  + 
/**
+ * @file tools/registry
+ * @description Central registry composition for all MCP tool definitions.
+ * @remarks Registration order is explicit and should stay stable for predictability.
+ */
+ 
+import type { ToolDefinition } from "./types.js";
+import { archToolDefinitions } from "./handlers/arch-tools.js";
+import { docsToolDefinitions } from "./handlers/docs-tools.js";
+import { refToolDefinitions } from "./handlers/ref-tools.js";
+import { testToolDefinitions } from "./handlers/test-tools.js";
+import { taskToolDefinitions } from "./handlers/task-tools.js";
+import { memoryCoordinationToolDefinitions } from "./handlers/memory-coordination-tools.js";
+import { coreGraphToolDefinitions } from "./handlers/core-graph-tools.js";
+import { coreAnalysisToolDefinitions } from "./handlers/core-analysis-tools.js";
+import { coreUtilityToolDefinitions } from "./handlers/core-utility-tools.js";
+import { coreSemanticToolDefinitions } from "./handlers/core-semantic-tools.js";
+import { coreSetupToolDefinitions } from "./handlers/core-setup-tools.js";
+ 
+/**
+ * Ordered list of all available tool definitions.
+ */
+export const toolRegistry: ToolDefinition[] = [
+  ...coreGraphToolDefinitions,
+  ...coreAnalysisToolDefinitions,
+  ...coreUtilityToolDefinitions,
+  ...coreSemanticToolDefinitions,
+  ...coreSetupToolDefinitions,
+  ...archToolDefinitions,
+  ...docsToolDefinitions,
+  ...refToolDefinitions,
+  ...testToolDefinitions,
+  ...taskToolDefinitions,
+  ...memoryCoordinationToolDefinitions,
+];
+ 
+/**
+ * Name-indexed lookup map for O(1) dispatch binding.
+ */
+export const toolRegistryMap = new Map<string, ToolDefinition>(
+  toolRegistry.map((definition) => [definition.name, definition]),
+);
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/tool-handler-base.ts.html b/coverage/lcov-report/src/tools/tool-handler-base.ts.html new file mode 100644 index 0000000..7b2b148 --- /dev/null +++ b/coverage/lcov-report/src/tools/tool-handler-base.ts.html @@ -0,0 +1,3661 @@ + + + + + + Code coverage report for src/tools/tool-handler-base.ts + + + + + + + + + +
+
+

All files / src/tools tool-handler-base.ts

+
+ +
+ 71.53% + Statements + 299/418 +
+ + +
+ 65.2% + Branches + 223/342 +
+ + +
+ 83.05% + Functions + 49/59 +
+ + +
+ 71.6% + Lines + 295/412 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108 +1109 +1110 +1111 +1112 +1113 +1114 +1115 +1116 +1117 +1118 +1119 +1120 +1121 +1122 +1123 +1124 +1125 +1126 +1127 +1128 +1129 +1130 +1131 +1132 +1133 +1134 +1135 +1136 +1137 +1138 +1139 +1140 +1141 +1142 +1143 +1144 +1145 +1146 +1147 +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +1157 +1158 +1159 +1160 +1161 +1162 +1163 +1164 +1165 +1166 +1167 +1168 +1169 +1170 +1171 +1172 +1173 +1174 +1175 +1176 +1177 +1178 +1179 +1180 +1181 +1182 +1183 +1184 +1185 +1186 +1187 +1188 +1189 +1190 +1191 +1192 +1193  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +126x +  +  +  +  +126x +  +  +  +126x +  +  +126x +126x +  +126x +126x +126x +  +126x +  +  +  +135x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +165x +165x +131x +  +  +34x +  +  +  +117x +117x +99x +  +  +18x +  +  +  +19x +19x +13x +  +6x +  +  +  +19x +  +  +  +19x +  +19x +19x +19x +19x +  +  +  +  +19x +  +  +  +  +  +  +126x +126x +126x +  +126x +  +  +  +  +  +  +  +34x +  +34x +34x +34x +34x +34x +  +  +  +34x +  +  +  +34x +  +  +  +  +  +  +  +  +  +  +  +19x +18x +  +  +1x +1x +  +  +  +1x +1x +1x +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +28x +  +  +  +  +  +  +  +20x +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +14x +14x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +126x +126x +  +  +126x +  +  +  +126x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +126x +  +  +126x +126x +  +126x +126x +  +126x +126x +  +126x +126x +  +126x +126x +  +  +126x +  +  +126x +  +  +  +126x +126x +  +  +  +126x +126x +126x +126x +  +  +126x +126x +126x +126x +  +  +  +  +126x +126x +  +  +126x +  +126x +  +  +  +  +  +  +  +  +  +  +  +  +126x +126x +126x +70x +68x +  +  +68x +68x +  +  +  +  +  +  +  +  +  +126x +126x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +126x +126x +24x +  +  +24x +  +  +70x +70x +  +70x +67x +  +67x +67x +  +  +67x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +35x +  +  +  +  +  +  +  +  +  +21x +  +  +  +  +21x +  +  +  +  +  +21x +  +  +  +374x +  +  +  +  +  +  +906x +374x +374x +  +  +532x +93x +  +  +439x +166x +767x +  +  +273x +  +  +  +  +  +  +  +  +132x +132x +132x +  +  +2866x +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +3x +  +  +  +3x +  +  +  +3x +2x +  +  +1x +  +  +  +  +  +  +111x +111x +  +111x +5x +  +  +  +  +  +5x +2x +  +  +5x +5x +  +  +111x +1x +1x +1x +1x +  +  +1x +  +  +  +  +1x +  +  +  +  +  +111x +1x +  +  +  +  +  +111x +17x +  +  +  +2x +2x +  +17x +  +  +111x +  +  +  +5x +  +  +  +  +  +  +  +  +  +3x +  +  +  +106x +  +  +106x +106x +  +106x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +106x +106x +  +  +  +  +  +106x +106x +106x +106x +106x +  +  +  +  +106x +102x +  +  +4x +4x +4x +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +16x +14x +  +  +2x +2x +2x +  +  +  +  +  +  +  +56x +8x +  +  +48x +7x +  +  +41x +4x +4x +  +  +37x +  +  +  +  +  +  +  +  +  +37x +  +  +  +  +  +  +  +  +  +  +  +  +7x +7x +7x +7x +  +  +  +7x +5x +5x +  +  +5x +2x +  +  +  +5x +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +5x +  +  +  +2x +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +3x +3x +2x +  +  +  +2x +2x +1x +  +1x +  +  +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +6x +  +  +  +6x +2x +  +  +2x +  +  +4x +4x +4x +2x +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +2x +  +  +2x +  +  +  +  +21x +  +  +  +8x +  +  +  +19x +  +  +  +  +  +  +  +1x +1x +  +1x +  +  +  +  +  +  +1x +  +  +  +1x +  +  +  +  +  +  +6x +6x +  +  +  +  +  +  +  +6x +6x +  +  +  +  +  +  +6x +  +6x +  +  +  +6x +2x +  +  +4x +4x +  +  +  +4x +4x +  +  +6x +6x +  +6x +6x +6x +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +1x +  +  +  +  +  +1x +1x +  +1x +1x +  +1x +  +  +  +  +1x +  +1x +1x +1x +1x +  +  +  +1x +1x +  +  +  +1x +  +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +2x +2x +  +2x +1x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +2x +2x +  +  + 
/**
+ * Tool Handler Base Class
+ * Shared state, interfaces, and helper methods for tool implementations
+ * Phase 5: Long file decomposition - extract base infrastructure
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import * as env from "../env.js";
+import { generateSecureId } from "../utils/validation.js";
+import type { GraphIndexManager } from "../graph/index.js";
+import type MemgraphClient from "../graph/client.js";
+import ArchitectureEngine from "../engines/architecture-engine.js";
+import TestEngine from "../engines/test-engine.js";
+import ProgressEngine from "../engines/progress-engine.js";
+import GraphOrchestrator from "../graph/orchestrator.js";
+import QdrantClient from "../vector/qdrant-client.js";
+import EmbeddingEngine from "../vector/embedding-engine.js";
+import type { GraphNode } from "../graph/index.js";
+import { getRequestContext } from "../request-context.js";
+import { formatResponse, errorResponse } from "../response/shaper.js";
+import EpisodeEngine from "../engines/episode-engine.js";
+import CoordinationEngine from "../engines/coordination-engine.js";
+import CommunityDetector from "../engines/community-detector.js";
+import HybridRetriever from "../graph/hybrid-retriever.js";
+import FileWatcher from "../graph/watcher.js";
+import { DocsEngine } from "../engines/docs-engine.js";
+import type { EngineSet } from "./types.js";
+import {
+  validateToolArgs as _validateToolArgs,
+  type ContractValidation,
+} from "./contract-validator.js";
+import { logger } from "../utils/logger.js";
+ 
+export interface ToolContext {
+  index: GraphIndexManager;
+  memgraph: MemgraphClient;
+  config: any;
+  orchestrator?: GraphOrchestrator;
+}
+ 
+export interface ProjectContext {
+  workspaceRoot: string;
+  sourceDir: string;
+  projectId: string;
+}
+ 
+/**
+ * Abstract base class for tool handlers
+ * Contains all shared state, session management, and helper methods
+ * Subclasses (ToolHandlers) add the actual tool implementations
+ */
+export abstract class ToolHandlerBase {
+  // ─────── Engines (Phase 4.6: Configurable, instantiated in constructor) ───────
+  protected archEngine?: ArchitectureEngine;
+  protected testEngine?: TestEngine;
+  protected progressEngine?: ProgressEngine;
+  protected orchestrator?: GraphOrchestrator;
+  protected qdrant?: QdrantClient;
+  protected embeddingEngine?: EmbeddingEngine;
+  protected episodeEngine?: EpisodeEngine;
+  protected coordinationEngine?: CoordinationEngine;
+  protected communityDetector?: CommunityDetector;
+  protected hybridRetriever?: HybridRetriever;
+  protected docsEngine?: DocsEngine;
+ 
+  // ─────── Session and Project State ─────────────────────────────────────────────
+  // Phase 4.3: Per-project embedding readiness to prevent race conditions
+  protected projectEmbeddingsReady = new Map<string, boolean>();
+  protected lastGraphRebuildAt?: string;
+  protected lastGraphRebuildMode?: "full" | "incremental";
+ 
+  // Phase 4.5: Track background build errors for diagnostics
+  public backgroundBuildErrors = new Map<
+    string,
+    Array<{ timestamp: number; error: string; context?: string }>
+  >();
+  protected readonly maxBuildErrorsPerProject = 10;
+ 
+  protected defaultActiveProjectContext: ProjectContext;
+  protected sessionProjectContexts = new Map<string, ProjectContext>();
+  protected sessionWatchers = new Map<string, FileWatcher>();
+ 
+  constructor(public readonly context: ToolContext) {
+    this.defaultActiveProjectContext = this.defaultProjectContext();
+    this.initializeEngines();
+    // Phase 2c: Load index from Memgraph on startup (fire and forget)
+    void this.initializeIndexFromMemgraph();
+  }
+ 
+  public get engines(): EngineSet {
+    return {
+      arch: this.archEngine,
+      test: this.testEngine,
+      progress: this.progressEngine,
+      orchestrator: this.orchestrator,
+      qdrant: this.qdrant,
+      embedding: this.embeddingEngine,
+      episode: this.episodeEngine,
+      coordination: this.coordinationEngine,
+      community: this.communityDetector,
+      hybrid: this.hybridRetriever,
+      docs: this.docsEngine,
+    };
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Session and Context Management
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  public getCurrentSessionId(): string | undefined {
+    const sessionId = getRequestContext().sessionId;
+    if (typeof sessionId !== "string" || sessionId.trim().length === 0) {
+      return undefined;
+    }
+ 
+    return sessionId;
+  }
+ 
+  public getActiveProjectContext(): ProjectContext {
+    const sessionId = this.getCurrentSessionId();
+    if (!sessionId) {
+      return this.defaultActiveProjectContext;
+    }
+ 
+    return this.sessionProjectContexts.get(sessionId) || this.defaultActiveProjectContext;
+  }
+ 
+  public setActiveProjectContext(context: ProjectContext): void {
+    const sessionId = this.getCurrentSessionId();
+    if (!sessionId) {
+      this.defaultActiveProjectContext = context;
+    } else {
+      this.sessionProjectContexts.set(sessionId, context);
+    }
+ 
+    // Reload engines with new project context
+    this.reloadEnginesForContext(context);
+  }
+ 
+  protected reloadEnginesForContext(context: ProjectContext): void {
+    logger.error(`[ToolHandlers] Reloading engines for project context: ${context.projectId}`);
+ 
+    try {
+      this.progressEngine?.reload(this.context.index, context.projectId);
+      this.testEngine?.reload(this.context.index, context.projectId);
+      Iif (this.archEngine) {
+        this.archEngine.reload(this.context.index, context.projectId, context.workspaceRoot);
+      }
+ 
+      // Phase 4.3: Reset embedding flag per-project to prevent race conditions
+      this.clearProjectEmbeddingsReady(context.projectId);
+    } catch (error) {
+      logger.error("[ToolHandlers] Failed to reload engines:", error);
+    }
+  }
+ 
+  protected defaultProjectContext(): ProjectContext {
+    const workspaceRoot = env.LXRAG_WORKSPACE_ROOT;
+    const sourceDir = env.GRAPH_SOURCE_DIR;
+    const projectId = env.LXRAG_PROJECT_ID;
+ 
+    return {
+      workspaceRoot,
+      sourceDir,
+      projectId,
+    };
+  }
+ 
+  public resolveProjectContext(overrides: any = {}): ProjectContext {
+    const base = this.getActiveProjectContext() || this.defaultProjectContext();
+    const workspaceProvided =
+      typeof overrides.workspaceRoot === "string" && overrides.workspaceRoot.trim().length > 0;
+    const workspaceInput = workspaceProvided ? overrides.workspaceRoot : base.workspaceRoot;
+    const workspaceRoot = path.resolve(workspaceInput);
+    const sourceInput = overrides.sourceDir || path.join(workspaceRoot, "src");
+    const sourceDir = path.isAbsolute(sourceInput)
+      ? sourceInput
+      : path.resolve(workspaceRoot, sourceInput);
+    const projectId =
+      overrides.projectId ||
+      (workspaceProvided ? path.basename(workspaceRoot) : env.LXRAG_PROJECT_ID) ||
+      path.basename(workspaceRoot);
+ 
+    return {
+      workspaceRoot,
+      sourceDir,
+      projectId,
+    };
+  }
+ 
+  public adaptWorkspaceForRuntime(context: ProjectContext): {
+    context: ProjectContext;
+    usedFallback: boolean;
+    fallbackReason?: string;
+  } {
+    if (fs.existsSync(context.workspaceRoot)) {
+      return { context, usedFallback: false };
+    }
+ 
+    const fallbackRoot = env.LXRAG_WORKSPACE_ROOT;
+    Iif (!fallbackRoot || !fs.existsSync(fallbackRoot)) {
+      return { context, usedFallback: false };
+    }
+ 
+    let mappedSourceDir = context.sourceDir;
+    Eif (path.isAbsolute(context.sourceDir) && context.sourceDir.startsWith(context.workspaceRoot)) {
+      const relativeSource = path.relative(context.workspaceRoot, context.sourceDir);
+      mappedSourceDir = path.resolve(fallbackRoot, relativeSource);
+    }
+ 
+    return {
+      usedFallback: true,
+      fallbackReason:
+        "Requested workspace path is not directly accessible in current runtime; using mounted workspace root.",
+      context: {
+        ...context,
+        workspaceRoot: fallbackRoot,
+        sourceDir: mappedSourceDir,
+      },
+    };
+  }
+ 
+  public runtimePathFallbackAllowed(): boolean {
+    return env.LXRAG_ALLOW_RUNTIME_PATH_FALLBACK;
+  }
+ 
+  public watcherEnabledForRuntime(): boolean {
+    return env.MCP_TRANSPORT === "http" || env.LXRAG_ENABLE_WATCHER;
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // File Watcher Management
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  protected watcherKey(): string {
+    return this.getCurrentSessionId() || "__default__";
+  }
+ 
+  protected getActiveWatcher(): FileWatcher | undefined {
+    return this.sessionWatchers.get(this.watcherKey());
+  }
+ 
+  public async stopActiveWatcher(): Promise<void> {
+    const key = this.watcherKey();
+    const existing = this.sessionWatchers.get(key);
+    if (!existing) {
+      return;
+    }
+ 
+    await existing.stop();
+    this.sessionWatchers.delete(key);
+  }
+ 
+  public async startActiveWatcher(context: ProjectContext): Promise<void> {
+    Eif (!this.watcherEnabledForRuntime()) {
+      return;
+    }
+ 
+    await this.stopActiveWatcher();
+ 
+    const watcher = new FileWatcher(
+      {
+        workspaceRoot: context.workspaceRoot,
+        sourceDir: context.sourceDir,
+        projectId: context.projectId,
+        debounceMs: env.LXRAG_WATCHER_DEBOUNCE_MS,
+        ignorePatterns: env.LXRAG_IGNORE_PATTERNS,
+      },
+      async ({ projectId, workspaceRoot, sourceDir, changedFiles }) => {
+        await this.runWatcherIncrementalRebuild({
+          projectId,
+          workspaceRoot,
+          sourceDir,
+          changedFiles,
+        });
+      },
+    );
+ 
+    watcher.start();
+    this.sessionWatchers.set(this.watcherKey(), watcher);
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Session Lifecycle Management
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  /**
+   * Phase 4.1: Clean up session resources when a session ends
+   * Prevents memory leaks from unbounded session map growth
+   */
+  async cleanupSession(sessionId: string): Promise<void> {
+    if (!sessionId) return;
+ 
+    try {
+      // Stop watcher for this session
+      const watcherKey = sessionId;
+      const watcher = this.sessionWatchers.get(watcherKey);
+      if (watcher) {
+        await watcher.stop();
+        this.sessionWatchers.delete(watcherKey);
+        logger.error(`[ToolHandlers] Session cleanup: stopped watcher for ${sessionId}`);
+      }
+ 
+      // Remove project context for this session
+      if (this.sessionProjectContexts.has(sessionId)) {
+        this.sessionProjectContexts.delete(sessionId);
+        logger.error(`[ToolHandlers] Session cleanup: removed project context for ${sessionId}`);
+      }
+    } catch (error) {
+      logger.error(`[ToolHandlers] Error cleaning up session ${sessionId}:`, error);
+    }
+  }
+ 
+  /**
+   * Clean up all session resources
+   * Called during server shutdown or restart
+   */
+  async cleanupAllSessions(): Promise<void> {
+    const sessionIds = Array.from(this.sessionProjectContexts.keys());
+    const watcherKeys = Array.from(this.sessionWatchers.keys());
+ 
+    // Clean up watchers
+    for (const key of watcherKeys) {
+      try {
+        const watcher = this.sessionWatchers.get(key);
+        if (watcher) {
+          await watcher.stop();
+        }
+      } catch (error) {
+        logger.error(`[ToolHandlers] Error stopping watcher ${key}:`, error);
+      }
+    }
+ 
+    this.sessionWatchers.clear();
+    this.sessionProjectContexts.clear();
+    logger.error(`[ToolHandlers] Cleaned up all ${sessionIds.length} session contexts`);
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Engine Initialization
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  protected initializeEngines(): void {
+    logger.error("[initializeEngines] Starting engine initialization...");
+    logger.error(
+      `[initializeEngines] projectId=${this.defaultActiveProjectContext.projectId} workspaceRoot=${this.defaultActiveProjectContext.workspaceRoot}`,
+    );
+    logger.error(
+      `[initializeEngines] memgraphConnected=${this.context.memgraph.isConnected?.() ?? "unknown"}`,
+    );
+ 
+    Iif (this.context.config.architecture) {
+      this.archEngine = new ArchitectureEngine(
+        this.context.config.architecture.layers,
+        this.context.config.architecture.rules,
+        this.context.index,
+        this.defaultActiveProjectContext.workspaceRoot,
+        {
+          sourceGlobs: this.context.config.testing?.sourceGlobs,
+          defaultExtension: this.context.config.testing?.defaultExtension,
+        },
+      );
+      logger.error(
+        `[initializeEngines] archEngine=ready layers=${this.context.config.architecture.layers?.length ?? 0}`,
+      );
+    } else {
+      logger.error("[initializeEngines] archEngine=skipped (no architecture config)");
+    }
+ 
+    this.testEngine = new TestEngine(this.context.index);
+    logger.error("[initializeEngines] testEngine=ready");
+ 
+    this.progressEngine = new ProgressEngine(this.context.index, this.context.memgraph);
+    logger.error("[initializeEngines] progressEngine=ready");
+ 
+    this.episodeEngine = new EpisodeEngine(this.context.memgraph);
+    logger.error("[initializeEngines] episodeEngine=ready");
+ 
+    this.coordinationEngine = new CoordinationEngine(this.context.memgraph);
+    logger.error("[initializeEngines] coordinationEngine=ready");
+ 
+    this.communityDetector = new CommunityDetector(this.context.memgraph);
+    logger.error("[initializeEngines] communityDetector=ready");
+ 
+    // Initialize GraphOrchestrator if not provided
+    this.orchestrator =
+      this.context.orchestrator ||
+      new GraphOrchestrator(this.context.memgraph, false, this.context.index);
+    logger.error(
+      `[initializeEngines] orchestrator=${this.context.orchestrator ? "provided" : "created"}`,
+    );
+ 
+    this.initializeVectorEngine();
+    logger.error("[initializeEngines] All engines initialized.");
+  }
+ 
+  protected initializeVectorEngine(): void {
+    const host = env.QDRANT_HOST;
+    const port = env.QDRANT_PORT;
+    logger.error(`[initializeVectorEngine] qdrant=${host}:${port}`);
+    logger.error(
+      `[initializeVectorEngine] summarizerUrl=${env.LXRAG_SUMMARIZER_URL ?? "(not set)"}`,
+    );
+    this.qdrant = new QdrantClient(host, port);
+    this.embeddingEngine = new EmbeddingEngine(this.context.index, this.qdrant);
+    logger.error("[initializeVectorEngine] embeddingEngine=created");
+    this.hybridRetriever = new HybridRetriever(
+      this.context.index,
+      this.embeddingEngine,
+      this.context.memgraph,
+    );
+    logger.error("[initializeVectorEngine] hybridRetriever=created");
+    this.docsEngine = new DocsEngine(this.context.memgraph, {
+      qdrant: this.qdrant,
+    });
+    logger.error("[initializeVectorEngine] docsEngine=created");
+ 
+    void this.qdrant
+      .connect()
+      .then(() => {
+        logger.error("[initializeVectorEngine] qdrant=CONNECTED");
+      })
+      .catch((error: unknown) => {
+        logger.warn("[initializeVectorEngine] qdrant=FAILED:", String(error));
+      });
+ 
+    // Ensure the Memgraph text_search BM25 index exists at startup.
+    // Fire-and-forget: failure is non-fatal; retrieval falls back to lexical mode.
+    // Deferred with setImmediate so it runs after the current microtask queue
+    // (important for test isolation — avoids polluting executeCypher call counts).
+    setImmediate(() => {
+      Iif (!this.hybridRetriever) return;
+      if (!this.context.memgraph.isConnected?.()) return;
+      if (typeof (this.hybridRetriever as any).ensureBM25Index !== "function") return;
+      void this.hybridRetriever
+        .ensureBM25Index()
+        .then((result) => {
+          if (result.created) {
+            logger.error("[bm25] Created text_search symbol_index at startup");
+          E} else if (result.error) {
+            logger.warn(`[bm25] BM25 index unavailable at startup: ${result.error}`);
+          }
+        })
+        .catch(() => {
+          // Memgraph not yet connected at startup — index will be created on next rebuild
+        });
+    });
+ 
+    Eif (!env.LXRAG_SUMMARIZER_URL) {
+      logger.warn(
+        "[summarizer] LXRAG_SUMMARIZER_URL is not set. " +
+          "Heuristic local summaries will be used, reducing vector search quality and " +
+          "compact-profile accuracy. " +
+          "Point this to an OpenAI-compatible /v1/chat/completions endpoint for production use.",
+      );
+    }
+  }
+ 
+  /**
+   * Phase 2c: Load index from Memgraph on startup
+   * Populates the in-memory index with data from the database
+   * This enables tools to work immediately without requiring a rebuild first
+   */
+  protected async initializeIndexFromMemgraph(): Promise<void> {
+    try {
+      if (!this.context.memgraph.isConnected()) {
+        logger.error(
+          "[Phase2c] Memgraph not connected, skipping index initialization from database",
+        );
+        return;
+      }
+ 
+      const projectId = this.defaultActiveProjectContext.projectId;
+      logger.error(`[Phase2c] Loading index from Memgraph for project ${projectId}...`);
+ 
+      const graphData = await this.context.memgraph.loadProjectGraph(projectId);
+      const { nodes, relationships } = graphData;
+ 
+      Eif (nodes.length === 0 && relationships.length === 0) {
+        logger.error(
+          `[Phase2c] No data found in Memgraph for project ${projectId}, index remains empty`,
+        );
+        return;
+      }
+ 
+      // Add all nodes to the index
+      for (const node of nodes) {
+        this.context.index.addNode(node.id, node.type, node.properties);
+      }
+ 
+      // Add all relationships to the index
+      for (const rel of relationships) {
+        this.context.index.addRelationship(rel.id, rel.from, rel.to, rel.type, rel.properties);
+      }
+ 
+      logger.error(
+        `[Phase2c] Index loaded from Memgraph: ${nodes.length} nodes, ${relationships.length} relationships for project ${projectId}`,
+      );
+    } catch (error) {
+      logger.error("[Phase2c] Failed to initialize index from Memgraph:", error);
+      // Continue regardless - index is optional for startup
+    }
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Response Formatting
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  public errorEnvelope(code: string, reason: string, recoverable = true, hint?: string): string {
+    const response = errorResponse(
+      code,
+      reason,
+      hint || "Review tool input and retry.",
+    ) as unknown as Record<string, unknown>;
+    response.error = {
+      code,
+      reason,
+      recoverable,
+      hint,
+    };
+    return JSON.stringify(response, null, 2);
+  }
+ 
+  public canonicalizePaths(text: string): string {
+    return text
+      .replaceAll("/workspace/", "")
+      .replace(/\/home\/[^/]+\/stratSolver\//g, "")
+      .replaceAll("//", "/");
+  }
+ 
+  protected compactValue(value: unknown): unknown {
+    if (typeof value === "string") {
+      const normalized = this.canonicalizePaths(value);
+      return normalized.length > 320 ? `${normalized.slice(0, 317)}...` : normalized;
+    }
+ 
+    if (Array.isArray(value)) {
+      return value.slice(0, 10).map((item) => this.compactValue(item));
+    }
+ 
+    if (value && typeof value === "object") {
+      const entries = Object.entries(value as Record<string, unknown>).slice(0, 20);
+      return Object.fromEntries(entries.map(([key, val]) => [key, this.compactValue(val)]));
+    }
+ 
+    return value;
+  }
+ 
+  public formatSuccess(
+    data: unknown,
+    profile: string = "compact",
+    summary?: string,
+    toolName?: string,
+  ): string {
+    const shaped = profile === "debug" ? data : this.compactValue(data);
+    const safeProfile = profile === "balanced" || profile === "debug" ? profile : "compact";
+    return JSON.stringify(
+      formatResponse(summary || "Operation completed successfully.", shaped, safeProfile, toolName),
+      // Safety net: convert any residual BigInt values to Number
+      (_key, value) => (typeof value === "bigint" ? Number(value) : value),
+      2,
+    );
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Input Processing and Normalization
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  public classifyIntent(
+    query: string,
+  ): "structure" | "dependency" | "test-impact" | "progress" | "general" {
+    const lower = query.toLowerCase();
+ 
+    Iif (/(test|coverage|spec|affected)/.test(lower)) {
+      return "test-impact";
+    }
+ 
+    Iif (/(progress|feature|task|blocked|milestone)/.test(lower)) {
+      return "progress";
+    }
+ 
+    Iif (/(import|dependency|depends|caller|called by|uses)/.test(lower)) {
+      return "dependency";
+    }
+ 
+    if (/(file|folder|class|function|structure|tree|list)/.test(lower)) {
+      return "structure";
+    }
+ 
+    return "general";
+  }
+ 
+  protected normalizeToolArgs(
+    toolName: string,
+    rawArgs: any,
+  ): { normalized: any; warnings: string[] } {
+    const warnings: string[] = [];
+    const normalized = { ...(rawArgs || {}) };
+ 
+    if (toolName === "impact_analyze") {
+      const files = Array.isArray(normalized.files)
+        ? normalized.files
+        : Array.isArray(normalized.changedFiles)
+          ? normalized.changedFiles
+          : [];
+ 
+      if (Array.isArray(normalized.changedFiles) && !Array.isArray(normalized.files)) {
+        warnings.push("mapped changedFiles -> files");
+      }
+ 
+      normalized.files = files;
+      delete normalized.changedFiles;
+    }
+ 
+    if (toolName === "progress_query") {
+      Eif (typeof normalized.type !== "string") {
+        const queryText = String(normalized.query || "task").toLowerCase();
+        normalized.type = queryText.includes("feature") ? "feature" : "task";
+        warnings.push("derived type from query text");
+      }
+ 
+      Iif (normalized.status === "active") {
+        normalized.status = "in-progress";
+        warnings.push("mapped status active -> in-progress");
+      }
+ 
+      Iif (normalized.status === "all") {
+        delete normalized.status;
+        warnings.push("mapped status all -> undefined");
+      }
+    }
+ 
+    if (toolName === "task_update") {
+      Iif (normalized.status === "active") {
+        normalized.status = "in-progress";
+        warnings.push("mapped status active -> in-progress");
+      }
+    }
+ 
+    if (toolName === "graph_set_workspace" || toolName === "graph_rebuild") {
+      if (
+        typeof normalized.workspacePath === "string" &&
+        typeof normalized.workspaceRoot !== "string"
+      ) {
+        normalized.workspaceRoot = normalized.workspacePath;
+        warnings.push("mapped workspacePath -> workspaceRoot");
+      }
+      delete normalized.workspacePath;
+    }
+ 
+    return { normalized, warnings };
+  }
+ 
+  normalizeForDispatch(toolName: string, rawArgs: any): { normalized: any; warnings: string[] } {
+    return this.normalizeToolArgs(toolName, rawArgs);
+  }
+ 
+  /**
+   * Validate `args` against the Zod schema registered for `toolName`.
+   *
+   * Delegates to the standalone {@link _validateToolArgs} function so that
+   * the validation logic stays testable in isolation.
+   */
+  validateToolArgs(toolName: string, args: unknown): ContractValidation {
+    return _validateToolArgs(toolName, args);
+  }
+ 
+  async callTool(toolName: string, rawArgs: any): Promise<string> {
+    logger.error(
+      `[callTool] ENTER tool=${toolName} args=${JSON.stringify(rawArgs ?? {}).slice(0, 256)}`,
+    );
+    const { normalized, warnings } = this.normalizeToolArgs(toolName, rawArgs);
+    const target = (this as any)[toolName];
+ 
+    Iif (typeof target !== "function") {
+      logger.error(
+        `[callTool] TOOL_NOT_FOUND tool=${toolName} — method does not exist on ToolHandlers`,
+      );
+      const registered = Object.getOwnPropertyNames(Object.getPrototypeOf(this))
+        .filter((k) => typeof (this as any)[k] === "function" && !k.startsWith("_"))
+        .join(", ");
+      logger.error(`[callTool] Registered methods: ${registered}`);
+      return this.errorEnvelope(
+        "TOOL_NOT_FOUND",
+        `Tool not found in handler registry: ${toolName}`,
+        false,
+      );
+    }
+ 
+    let result: string;
+    try {
+      result = await target.call(this, normalized);
+    } catch (err) {
+      logger.error(`[callTool] UNCAUGHT_EXCEPTION tool=${toolName} error=${String(err)}`);
+      throw err;
+    }
+ 
+    try {
+      const parsed = JSON.parse(result);
+      const ok = parsed?.ok ?? true;
+      const code = parsed?.error?.code ?? (ok ? "ok" : "error");
+      logger.error(`[callTool] EXIT tool=${toolName} status=${ok} code=${code}`);
+    } catch {
+      logger.error(`[callTool] EXIT tool=${toolName} result-length=${result.length}`);
+    }
+ 
+    if (!warnings.length) {
+      return result;
+    }
+ 
+    try {
+      const parsed = JSON.parse(result);
+      Eif (parsed && typeof parsed === "object") {
+        parsed.contractWarnings = warnings;
+        return JSON.stringify(parsed, null, 2);
+      }
+      return result;
+    } catch {
+      return result;
+    }
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Utility Conversions
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  public toEpochMillis(asOf?: string): number | null {
+    if (!asOf || typeof asOf !== "string") {
+      return null;
+    }
+ 
+    Eif (/^\d+$/.test(asOf)) {
+      const numeric = Number(asOf);
+      return Number.isFinite(numeric) ? numeric : null;
+    }
+ 
+    const parsed = Date.parse(asOf);
+    return Number.isNaN(parsed) ? null : parsed;
+  }
+ 
+  public toSafeNumber(value: unknown): number | null {
+    if (typeof value === "number") {
+      return Number.isFinite(value) ? value : null;
+    }
+ 
+    if (typeof value === "bigint") {
+      return Number(value);
+    }
+ 
+    if (typeof value === "string" && /^-?\d+(?:\.\d+)?$/.test(value)) {
+      const parsed = Number(value);
+      return Number.isFinite(parsed) ? parsed : null;
+    }
+ 
+    Iif (value && typeof value === "object" && "low" in (value as Record<string, unknown>)) {
+      const low = Number((value as Record<string, unknown>).low);
+      const highRaw = (value as Record<string, unknown>).high;
+      const high = typeof highRaw === "number" ? highRaw : Number(highRaw || 0);
+ 
+      if (Number.isFinite(low) && Number.isFinite(high)) {
+        return high * 4294967296 + low;
+      }
+    }
+ 
+    return null;
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Episode and Entity Validation
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  public validateEpisodeInput(args: {
+    type: string;
+    outcome?: unknown;
+    entities?: string[];
+    metadata?: Record<string, unknown>;
+  }): string | null {
+    const type = String(args.type || "").toUpperCase();
+    const entities = Array.isArray(args.entities) ? args.entities : [];
+    const metadata = args.metadata || {};
+    logger.error(
+      `[validateEpisodeInput] type=${type} outcome=${String(args.outcome ?? "")} entities=${entities.length} metadataKeys=${Object.keys(metadata).join(",") || "none"}`,
+    );
+ 
+    if (type === "DECISION") {
+      const outcome = String(args.outcome || "").toLowerCase();
+      Iif (!outcome || !["success", "failure", "partial"].includes(outcome)) {
+        return "DECISION episodes require outcome: success | failure | partial.";
+      }
+      if (typeof metadata.rationale !== "string" && typeof metadata.reason !== "string") {
+        return "DECISION episodes require metadata.rationale (or metadata.reason).";
+      }
+    }
+ 
+    Iif (type === "EDIT") {
+      if (!entities.length) {
+        return "EDIT episodes require at least one entity reference.";
+      }
+    }
+ 
+    Iif (type === "TEST_RESULT") {
+      const outcome = String(args.outcome || "").toLowerCase();
+      if (!outcome || !["success", "failure", "partial"].includes(outcome)) {
+        return "TEST_RESULT episodes require outcome: success | failure | partial.";
+      }
+      if (typeof metadata.testName !== "string" && typeof metadata.testFile !== "string") {
+        return "TEST_RESULT episodes require metadata.testName or metadata.testFile.";
+      }
+    }
+ 
+    Iif (type === "ERROR") {
+      if (typeof metadata.errorCode !== "string" && typeof metadata.stack !== "string") {
+        return "ERROR episodes require metadata.errorCode or metadata.stack.";
+      }
+    }
+ 
+    return null;
+  }
+ 
+  public async inferEpisodeEntityHints(query: string, limit: number): Promise<string[]> {
+    Iif (!this.embeddingEngine || !query.trim()) {
+      return [];
+    }
+ 
+    try {
+      await this.ensureEmbeddings();
+      const { projectId } = this.getActiveProjectContext();
+      const topK = Math.max(1, Math.min(limit, 10));
+      const [functions, classes, files] = await Promise.all([
+        this.embeddingEngine.findSimilar(query, "function", topK, projectId),
+        this.embeddingEngine.findSimilar(query, "class", topK, projectId),
+        this.embeddingEngine.findSimilar(query, "file", topK, projectId),
+      ]);
+ 
+      return [...functions, ...classes, ...files]
+        .map((item) => String(item.id || ""))
+        .filter(Boolean)
+        .slice(0, topK * 2);
+    } catch {
+      return [];
+    }
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Temporal Query Helpers
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  public async resolveSinceAnchor(
+    since: string,
+    projectId: string,
+  ): Promise<{
+    sinceTs: number;
+    mode: "txId" | "timestamp" | "gitCommit" | "agentId";
+    anchorValue: string;
+  } | null> {
+    const trimmed = since.trim();
+    Iif (!trimmed) {
+      return null;
+    }
+ 
+    const txIdPattern =
+      /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
+    if (txIdPattern.test(trimmed) || trimmed.startsWith("tx-")) {
+      const txLookup = await this.context.memgraph.executeCypher(
+        "MATCH (tx:GRAPH_TX {projectId: $projectId, id: $id}) RETURN tx.timestamp AS timestamp ORDER BY tx.timestamp DESC LIMIT 1",
+        { projectId, id: trimmed },
+      );
+      const ts = this.toSafeNumber(txLookup.data?.[0]?.timestamp);
+      if (ts !== null) {
+        return { sinceTs: ts, mode: "txId", anchorValue: trimmed };
+      }
+      return null;
+    }
+ 
+    const timestamp = this.toEpochMillis(trimmed);
+    Eif (timestamp !== null) {
+      return { sinceTs: timestamp, mode: "timestamp", anchorValue: trimmed };
+    }
+ 
+    if (/^[a-f0-9]{7,40}$/i.test(trimmed)) {
+      const commitLookup = await this.context.memgraph.executeCypher(
+        "MATCH (tx:GRAPH_TX {projectId: $projectId, gitCommit: $gitCommit}) RETURN tx.timestamp AS timestamp ORDER BY tx.timestamp DESC LIMIT 1",
+        { projectId, gitCommit: trimmed },
+      );
+      const ts = this.toSafeNumber(commitLookup.data?.[0]?.timestamp);
+      if (ts !== null) {
+        return { sinceTs: ts, mode: "gitCommit", anchorValue: trimmed };
+      }
+      return null;
+    }
+ 
+    const agentLookup = await this.context.memgraph.executeCypher(
+      "MATCH (tx:GRAPH_TX {projectId: $projectId, agentId: $agentId}) RETURN tx.timestamp AS timestamp ORDER BY tx.timestamp DESC LIMIT 1",
+      { projectId, agentId: trimmed },
+    );
+    const agentTs = this.toSafeNumber(agentLookup.data?.[0]?.timestamp);
+    Iif (agentTs !== null) {
+      return { sinceTs: agentTs, mode: "agentId", anchorValue: trimmed };
+    }
+ 
+    return null;
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Embedding Management
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  // Phase 4.3: Project-scoped embedding readiness check to prevent race conditions
+  // Phase 4.5: Improved error handling for Qdrant operations
+  public async ensureEmbeddings(projectId?: string): Promise<void> {
+    const activeProjectId = projectId || this.getActiveProjectContext().projectId;
+ 
+    logger.error(
+      `[ensureEmbeddings] projectId=${activeProjectId} embeddingEngineReady=${!!this.embeddingEngine} alreadyReady=${this.isProjectEmbeddingsReady(activeProjectId)} qdrantConnected=${this.qdrant?.isConnected?.() ?? "unknown"}`,
+    );
+ 
+    if (this.isProjectEmbeddingsReady(activeProjectId) || !this.embeddingEngine) {
+      logger.error(
+        `[ensureEmbeddings] SKIP — embeddingEngine=${!!this.embeddingEngine} alreadyReady=${this.isProjectEmbeddingsReady(activeProjectId)}`,
+      );
+      return;
+    }
+ 
+    try {
+      const generated = await this.embeddingEngine.generateAllEmbeddings();
+      if (generated.functions + generated.classes + generated.files === 0) {
+        throw new Error("No indexed symbols found. Run graph_rebuild first.");
+      }
+ 
+      try {
+        await this.embeddingEngine.storeInQdrant();
+      } catch (qdrantError) {
+        const errorMsg = qdrantError instanceof Error ? qdrantError.message : String(qdrantError);
+        logger.error(
+          `[Phase4.5] Qdrant storage failed for project ${activeProjectId}: ${errorMsg}`,
+        );
+        // Don't throw - continue with embeddings ready flag set locally
+        // Qdrant failures are non-critical for indexing functionality
+        logger.warn(
+          `[Phase4.5] Continuing without Qdrant - semantic search may be unavailable for project ${activeProjectId}`,
+        );
+      }
+ 
+      this.setProjectEmbeddingsReady(activeProjectId, true);
+    } catch (error) {
+      const errorMsg = error instanceof Error ? error.message : String(error);
+      logger.error(
+        `[Phase4.5] Embedding generation failed for project ${activeProjectId}: ${errorMsg}`,
+      );
+      throw error;
+    }
+  }
+ 
+  protected isProjectEmbeddingsReady(projectId: string): boolean {
+    return this.projectEmbeddingsReady.get(projectId) ?? false;
+  }
+ 
+  protected setProjectEmbeddingsReady(projectId: string, ready: boolean): void {
+    this.projectEmbeddingsReady.set(projectId, ready);
+  }
+ 
+  protected clearProjectEmbeddingsReady(projectId: string): void {
+    this.projectEmbeddingsReady.delete(projectId);
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Build Error Tracking (Phase 4.5)
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  public recordBuildError(projectId: string, error: unknown, context?: string): void {
+    const errorMsg = error instanceof Error ? error.message : String(error);
+    const errors = this.backgroundBuildErrors.get(projectId) || [];
+ 
+    errors.push({
+      timestamp: Date.now(),
+      error: errorMsg,
+      context,
+    });
+ 
+    // Keep history bounded
+    Iif (errors.length > this.maxBuildErrorsPerProject) {
+      errors.shift();
+    }
+ 
+    this.backgroundBuildErrors.set(projectId, errors);
+  }
+ 
+  protected getRecentBuildErrors(
+    projectId: string,
+    limit: number = 5,
+  ): Array<{ timestamp: number; error: string; context?: string }> {
+    const errors = this.backgroundBuildErrors.get(projectId) || [];
+    return errors.slice(-limit);
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Element Resolution
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  public resolveElement(elementId: string): GraphNode | undefined {
+    const requested = String(elementId || "").trim();
+    Iif (!requested) {
+      return undefined;
+    }
+ 
+    // Try exact match first, then also try with the active projectId prefix
+    // (Memgraph nodes use "projectId:file:name:line" while the in-memory index
+    // built during a rebuild uses the raw "file:name:line" format)
+    const { projectId } = this.getActiveProjectContext();
+    const exact =
+      this.context.index.getNode(requested) ||
+      (projectId && requested && !requested.startsWith(`${projectId}:`)
+        ? this.context.index.getNode(`${projectId}:${requested}`)
+        : undefined);
+    if (exact) {
+      return exact;
+    }
+ 
+    const normalizedPath = requested.replace(/\\/g, "/");
+    const basename = path.basename(normalizedPath);
+ 
+    // For IDs in format "file.ts:symbolName:lineNum" (parser output), the last
+    // segment is a line number — use the second-to-last as the symbol name.
+    const parts = requested.split(":");
+    const scopedTail = parts.length > 1 ? parts[parts.length - 1] : requested;
+    // If last segment is a number, treat the preceding segment as the name
+    const scopedName =
+      parts.length > 2 && /^\d+$/.test(scopedTail) ? parts[parts.length - 2] : scopedTail;
+    const symbolTail = requested.includes("::") ? requested.split("::").slice(-1)[0] : scopedName;
+ 
+    const files = this.context.index.getNodesByType("FILE");
+    const functions = this.context.index.getNodesByType("FUNCTION");
+    const classes = this.context.index.getNodesByType("CLASS");
+ 
+    return (
+      files.find((node) => {
+        const nodePath = String(
+          node.properties.path || node.properties.filePath || node.properties.relativePath || "",
+        ).replace(/\\/g, "/");
+        return (
+          nodePath === normalizedPath ||
+          nodePath.endsWith(normalizedPath) ||
+          normalizedPath.endsWith(nodePath) ||
+          path.basename(nodePath) === basename ||
+          node.id === requested ||
+          node.id.endsWith(`:${normalizedPath}`)
+        );
+      }) ||
+      functions.find((node) => {
+        const name = String(node.properties.name || "");
+        return (
+          name === requested ||
+          name === scopedTail ||
+          name === scopedName ||
+          name === symbolTail ||
+          node.id === requested ||
+          node.id.endsWith(`:${requested}`)
+        );
+      }) ||
+      classes.find((node) => {
+        const name = String(node.properties.name || "");
+        return (
+          name === requested ||
+          name === scopedTail ||
+          name === scopedName ||
+          name === symbolTail ||
+          node.id === requested ||
+          node.id.endsWith(`:${requested}`)
+        );
+      })
+    );
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Temporal Query Building
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  protected buildTemporalPredicateForVars(variables: string[]): string {
+    const unique = [...new Set(variables.filter(Boolean))];
+    return unique
+      .map(
+        (name) =>
+          `(${name}.validFrom <= $asOfTs AND (${name}.validTo IS NULL OR ${name}.validTo > $asOfTs))`,
+      )
+      .join(" AND ");
+  }
+ 
+  protected extractMatchVariables(segment: string): string[] {
+    const vars: string[] = [];
+    const regex = /\(([A-Za-z_][A-Za-z0-9_]*)\s*(?::|\)|\{)/g;
+    let match: RegExpExecArray | null;
+    while ((match = regex.exec(segment)) !== null) {
+      vars.push(match[1]);
+    }
+    return vars;
+  }
+ 
+  protected applyTemporalFilterToCypher(query: string): string {
+    const matchSegmentRegex =
+      /((?:OPTIONAL\s+MATCH|MATCH)\b[\s\S]*?)(?=\n\s*(?:OPTIONAL\s+MATCH|MATCH|WITH|RETURN|UNWIND|CALL|CREATE|MERGE|SET|DELETE|REMOVE|FOREACH|ORDER\s+BY|LIMIT|SKIP|UNION)\b|$)/gi;
+ 
+    let touched = false;
+    const rewritten = query.replace(matchSegmentRegex, (segment) => {
+      const vars = this.extractMatchVariables(segment);
+      Iif (!vars.length) {
+        return segment;
+      }
+ 
+      const predicate = this.buildTemporalPredicateForVars(vars);
+      Iif (!predicate) {
+        return segment;
+      }
+ 
+      touched = true;
+      const inlineClauseRegex =
+        /\b(?:WITH|RETURN|UNWIND|CALL|CREATE|MERGE|SET|DELETE|REMOVE|FOREACH|ORDER\s+BY|LIMIT|SKIP|UNION)\b/i;
+      const boundaryIndex = segment.search(inlineClauseRegex);
+      const whereMatch = /\bWHERE\b/i.exec(segment);
+ 
+      Iif (whereMatch) {
+        if (boundaryIndex > whereMatch.index) {
+          const head = segment.slice(0, boundaryIndex).trimEnd();
+          const tail = segment.slice(boundaryIndex).trimStart();
+          return `${head} AND ${predicate}\n${tail}`;
+        }
+        return `${segment} AND ${predicate}`;
+      }
+ 
+      Eif (boundaryIndex > 0) {
+        const head = segment.slice(0, boundaryIndex).trimEnd();
+        const tail = segment.slice(boundaryIndex).trimStart();
+        return `${head} WHERE ${predicate}\n${tail}`;
+      }
+ 
+      return `${segment}\nWHERE ${predicate}`;
+    });
+ 
+    return touched ? rewritten : query;
+  }
+ 
+  // ──────────────────────────────────────────────────────────────────────────────
+  // Watcher-driven Incremental Rebuild
+  // ──────────────────────────────────────────────────────────────────────────────
+ 
+  protected async runWatcherIncrementalRebuild(
+    context: ProjectContext & { changedFiles?: string[] },
+  ): Promise<void> {
+    Iif (!this.orchestrator) {
+      return;
+    }
+ 
+    // Phase 4.2: Use crypto-secure random ID generation instead of Math.random()
+    const txTimestamp = Date.now();
+    const txId = generateSecureId("tx", 4);
+ 
+    if (this.context.memgraph.isConnected()) {
+      await this.context.memgraph.executeCypher(
+        `CREATE (tx:GRAPH_TX {id: $id, projectId: $projectId, type: $type, timestamp: $timestamp, mode: $mode, sourceDir: $sourceDir})`,
+        {
+          id: txId,
+          projectId: context.projectId,
+          type: "incremental_rebuild",
+          timestamp: txTimestamp,
+          mode: "incremental",
+          sourceDir: context.sourceDir,
+        },
+      );
+    }
+ 
+    await this.orchestrator.build({
+      mode: "incremental",
+      verbose: false,
+      workspaceRoot: context.workspaceRoot,
+      projectId: context.projectId,
+      sourceDir: context.sourceDir,
+      changedFiles: context.changedFiles,
+      txId,
+      txTimestamp,
+      exclude: ["node_modules", "dist", ".next", ".lxrag", "__tests__", "coverage", ".git"],
+    });
+ 
+    // Phase 2a & 4.3: Reset embeddings for watcher-driven incremental builds (per-project to prevent race conditions)
+    this.setProjectEmbeddingsReady(context.projectId, false);
+    logger.error(
+      `[Phase2a] Embeddings flag reset for watcher incremental rebuild of project ${context.projectId}`,
+    );
+ 
+    this.lastGraphRebuildAt = new Date().toISOString();
+    this.lastGraphRebuildMode = "incremental";
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/tool-handlers.ts.html b/coverage/lcov-report/src/tools/tool-handlers.ts.html new file mode 100644 index 0000000..746c3cf --- /dev/null +++ b/coverage/lcov-report/src/tools/tool-handlers.ts.html @@ -0,0 +1,2065 @@ + + + + + + Code coverage report for src/tools/tool-handlers.ts + + + + + + + + + +
+
+

All files / src/tools tool-handlers.ts

+
+ +
+ 46.28% + Statements + 106/229 +
+ + +
+ 31.45% + Branches + 78/248 +
+ + +
+ 33.96% + Functions + 18/53 +
+ + +
+ 47.94% + Lines + 105/219 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +126x +  +126x +4914x +  +  +4914x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +1x +  +  +1x +1x +2x +  +2x +2x +1x +  +  +  +  +  +  +  +  +1x +  +  +1x +  +1x +1x +1x +  +  +2x +2x +  +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +2x +  +2x +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +2x +2x +2x +2x +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +2x +  +  +  +  +  +  +2x +2x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +1x +  +  +4x +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +1x +1x +  +  +  +1x +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +2x +2x +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +2x +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +1x +1x +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +  +  +  +  +2x +2x +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +2x +  +  +  +2x +1x +  +1x +1x +  +  +  +  +  +  + 
/**
+ * Tool Handlers - Concrete Tool Implementations
+ * Registry-backed runtime dispatch + complex helper implementations.
+ *
+ * Tool entrypoints are bound from `toolRegistry`; this class keeps shared helper logic
+ * for implementations that require cross-cutting context assembly.
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import * as env from "../env.js";
+import type { GraphNode } from "../graph/index.js";
+import { runPPR } from "../graph/ppr.js";
+import type { ResponseProfile } from "../response/budget.js";
+import { estimateTokens, makeBudget } from "../response/budget.js";
+import { ToolHandlerBase, type ToolContext } from "./tool-handler-base.js";
+import { toolRegistryMap } from "./registry.js";
+ 
+// Re-export base types for external consumers
+export type { ToolContext, ProjectContext } from "./tool-handler-base.js";
+ 
+/**
+ * Main tool handler class that implements all MCP tools
+ * Extends ToolHandlerBase which provides shared state, session management, and helpers
+ *
+ * This class remains the public API for tool invocation:
+ * - callTool(toolName, args): central dispatch
+ * - cleanupSession(sessionId): session cleanup
+ * - cleanupAllSessions(): bulk cleanup
+ * - normalizeForDispatch(toolName, args): input normalization for backward compatibility
+ */
+export class ToolHandlers extends ToolHandlerBase {
+  constructor(context: ToolContext) {
+    super(context);
+    // Bind migrated tools from centralized registry
+    for (const [toolName, definition] of toolRegistryMap.entries()) {
+      Iif (typeof (this as any)[toolName] === "function") {
+        continue;
+      }
+      (this as any)[toolName] = (args: any) => definition.impl(args, this);
+    }
+  }
+ 
+  // Core query/graph/search contract tools are now implemented in core-tools.ts
+  // and bound via toolRegistry in the constructor.
+ 
+  // Episode/coordination tools migrated to handler modules and bound via toolRegistry.
+ 
+  public async core_context_pack_impl(args: any): Promise<string> {
+    const {
+      task,
+      taskId,
+      agentId,
+      profile = "compact",
+      includeDecisions = true,
+      includeLearnings = true,
+      includeEpisodes = true,
+    } = args || {};
+ 
+    if (!task || typeof task !== "string") {
+      return this.errorEnvelope("CONTEXT_PACK_INVALID_INPUT", "Field 'task' is required.", true);
+    }
+ 
+    try {
+      const runtimeAgentId = String(agentId || env.LXRAG_AGENT_ID);
+      const { projectId, workspaceRoot } = this.getActiveProjectContext();
+ 
+      const seedIds = this.findSeedNodeIds(task, 5);
+      const expandedSeedIds = await this.expandInterfaceSeeds(seedIds, projectId);
+      const pprResults = await runPPR(
+        {
+          projectId,
+          seedIds: expandedSeedIds.length ? expandedSeedIds : seedIds,
+          maxResults: 60,
+        },
+        this.context.memgraph,
+      );
+ 
+      const codeCandidates = pprResults.filter((item) =>
+        ["FUNCTION", "CLASS", "FILE"].includes(String(item.type || "").toUpperCase()),
+      );
+      const coreSymbols = await this.materializeCoreSymbols(codeCandidates, workspaceRoot);
+ 
+      const selectedIds = coreSymbols.map((item) => item.nodeId);
+      const activeBlockers = await this.findActiveBlockers(selectedIds, runtimeAgentId, projectId);
+      const decisions = includeDecisions
+        ? await this.findDecisionEpisodes(selectedIds, projectId)
+        : [];
+      const learnings = includeLearnings ? await this.findLearnings(selectedIds, projectId) : [];
+      const episodes = includeEpisodes
+        ? await this.findRecentEpisodes(taskId, runtimeAgentId, projectId)
+        : [];
+ 
+      const entryPoint =
+        coreSymbols[0]?.symbolName || coreSymbols[0]?.file || "No entry point found";
+      const summary = `Task briefing for '${task}': start at ${entryPoint}. Focus on ${coreSymbols.length} high-relevance symbol(s) and resolve ${activeBlockers.length} active blocker(s).`;
+ 
+      const pack: Record<string, unknown> = {
+        summary,
+        entryPoint,
+        task,
+        taskId: taskId || null,
+        projectId,
+        coreSymbols,
+        dependencies: coreSymbols.flatMap((item) => [
+          ...item.incomingCallers.map((caller: any) => ({
+            from: caller.id,
+            to: item.nodeId,
+            type: "CALLS",
+          })),
+          ...item.outgoingCalls.map((callee: any) => ({
+            from: item.nodeId,
+            to: callee.id,
+            type: "CALLS",
+          })),
+        ]),
+        decisions,
+        learnings,
+        episodes,
+        activeBlockers,
+        plan: taskId
+          ? {
+              taskId,
+              status: "unknown",
+              note: "Plan-node integration deferred to later phase.",
+            }
+          : null,
+        pprScores:
+          profile === "debug"
+            ? Object.fromEntries(pprResults.map((item) => [item.nodeId, item.score]))
+            : undefined,
+      };
+ 
+      const safeProfile: ResponseProfile =
+        profile === "balanced" || profile === "debug" ? profile : "compact";
+      const budget = makeBudget(safeProfile);
+      this.trimContextPackToBudget(pack, budget.maxTokens);
+      pack.tokenEstimate = estimateTokens(pack);
+ 
+      return this.formatSuccess(pack, safeProfile, summary, "context_pack");
+    } catch (error) {
+      return this.errorEnvelope("CONTEXT_PACK_FAILED", String(error), true);
+    }
+  }
+ 
+  public async core_semantic_slice_impl(args: any): Promise<string> {
+    const { file, symbol, query, context = "body", pprScore, profile = "compact" } = args || {};
+ 
+    Iif (!symbol && !query && !file) {
+      return this.errorEnvelope(
+        "SEMANTIC_SLICE_INVALID_INPUT",
+        "Provide at least one of: symbol, query, or file.",
+        true,
+      );
+    }
+ 
+    try {
+      const { workspaceRoot, projectId } = this.getActiveProjectContext();
+      const resolved = this.resolveSemanticSliceAnchor({ file, symbol, query });
+      Iif (!resolved) {
+        return this.errorEnvelope(
+          "SEMANTIC_SLICE_NOT_FOUND",
+          "Unable to resolve a symbol or file anchor for semantic slicing.",
+          true,
+          "Provide symbol + file for exact lookup or a more specific query.",
+        );
+      }
+ 
+      const { node, filePath, startLine, endLine } = resolved;
+      const absolutePath = path.isAbsolute(filePath)
+        ? filePath
+        : path.resolve(workspaceRoot, filePath);
+ 
+      const sliceContext =
+        context === "signature" ||
+        context === "body" ||
+        context === "with-deps" ||
+        context === "full"
+          ? context
+          : "body";
+ 
+      const [rangeStart, rangeEnd] = this.computeSliceRange(startLine, endLine, sliceContext);
+      const code = this.readExactLines(absolutePath, rangeStart, rangeEnd);
+ 
+      const incomingCallers =
+        sliceContext === "with-deps" || sliceContext === "full"
+          ? this.context.index
+              .getRelationshipsTo(node.id)
+              .filter((rel) => rel.type === "CALLS")
+              .slice(0, 10)
+              .map((rel) => ({
+                id: rel.from,
+                name: this.context.index.getNode(rel.from)?.properties?.name || rel.from,
+              }))
+          : [];
+ 
+      const outgoingCalls =
+        sliceContext === "with-deps" || sliceContext === "full"
+          ? this.context.index
+              .getRelationshipsFrom(node.id)
+              .filter((rel) => rel.type === "CALLS")
+              .slice(0, 10)
+              .map((rel) => ({
+                id: rel.to,
+                name: this.context.index.getNode(rel.to)?.properties?.name || rel.to,
+              }))
+          : [];
+ 
+      const includeKnowledge = sliceContext === "full";
+      const decisions = includeKnowledge
+        ? await this.findDecisionEpisodes([node.id], projectId)
+        : [];
+      const learnings = includeKnowledge ? await this.findLearnings([node.id], projectId) : [];
+ 
+      const response = {
+        file: filePath,
+        startLine: rangeStart,
+        endLine: rangeEnd,
+        code,
+        symbolName: String(node.properties.name || path.basename(filePath)),
+        pprScore: typeof pprScore === "number" ? pprScore : undefined,
+        incomingCallers,
+        outgoingCalls,
+        relevantDecisions: decisions,
+        relevantLearnings: learnings,
+        validFrom: node.properties.validFrom || null,
+        context: sliceContext,
+        projectId,
+      };
+ 
+      const summary = `Semantic slice resolved ${response.symbolName} in ${response.file}:${response.startLine}-${response.endLine}.`;
+ 
+      return this.formatSuccess(response, profile, summary, "semantic_slice");
+    } catch (error) {
+      return this.errorEnvelope("SEMANTIC_SLICE_FAILED", String(error), true);
+    }
+  }
+ 
+  private findSeedNodeIds(task: string, limit: number): string[] {
+    const tokens = task
+      .toLowerCase()
+      .split(/[^a-z0-9_]+/)
+      .filter((token) => token.length >= 3);
+ 
+    const candidates = [
+      ...this.context.index.getNodesByType("FUNCTION"),
+      ...this.context.index.getNodesByType("CLASS"),
+      ...this.context.index.getNodesByType("FILE"),
+    ];
+ 
+    const scored = candidates
+      .map((node) => {
+        const haystack =
+          `${node.id} ${node.properties.name || ""} ${node.properties.path || ""}`.toLowerCase();
+        const score = tokens.reduce((acc, token) => acc + (haystack.includes(token) ? 1 : 0), 0);
+        return { nodeId: node.id, score };
+      })
+      .sort((a, b) => b.score - a.score);
+ 
+    const selected = scored.filter((item) => item.score > 0).slice(0, limit);
+    Iif (selected.length) {
+      return selected.map((item) => item.nodeId);
+    }
+ 
+    return candidates.slice(0, limit).map((node) => node.id);
+  }
+ 
+  private async expandInterfaceSeeds(seedIds: string[], projectId: string): Promise<string[]> {
+    Eif (!seedIds.length) {
+      return [];
+    }
+ 
+    const expanded = new Set(seedIds);
+    const relationExpansion = await this.context.memgraph.executeCypher(
+      `MATCH (iface {projectId: $projectId})
+       WHERE iface.id IN $seedIds
+         AND (toLower(coalesce(iface.kind, '')) IN ['interface', 'abstract'])
+       OPTIONAL MATCH (iface)-[:IMPLEMENTED_BY]->(impl {projectId: $projectId})
+       RETURN collect(DISTINCT impl.id) AS implIds`,
+      { projectId, seedIds },
+    );
+ 
+    const implIds = relationExpansion.data?.[0]?.implIds;
+    Iif (Array.isArray(implIds)) {
+      for (const implId of implIds) {
+        if (implId) {
+          expanded.add(String(implId));
+        }
+      }
+    }
+ 
+    return [...expanded];
+  }
+ 
+  private async materializeCoreSymbols(
+    pprResults: Array<{ nodeId: string; score: number }>,
+    workspaceRoot: string,
+  ): Promise<any[]> {
+    const maxSymbols = 8;
+    const selected = pprResults.slice(0, maxSymbols);
+    const slices: any[] = [];
+ 
+    for (const item of selected) {
+      const resolved = this.resolveNodeForSlice(item.nodeId);
+      if (!resolved) {
+        continue;
+      }
+ 
+      const { node, filePath, startLine, endLine } = resolved;
+      const absolutePath = path.isAbsolute(filePath)
+        ? filePath
+        : path.resolve(workspaceRoot, filePath);
+ 
+      const code = this.readCodeSnippet(absolutePath, startLine, endLine, 800);
+      const incomingCallers = this.context.index
+        .getRelationshipsTo(node.id)
+        .filter((rel) => rel.type === "CALLS")
+        .slice(0, 5)
+        .map((rel) => ({ id: rel.from }));
+      const outgoingCalls = this.context.index
+        .getRelationshipsFrom(node.id)
+        .filter((rel) => rel.type === "CALLS")
+        .slice(0, 5)
+        .map((rel) => ({ id: rel.to }));
+ 
+      slices.push({
+        nodeId: node.id,
+        file: filePath,
+        startLine,
+        endLine,
+        code,
+        symbolName: String(node.properties.name || path.basename(filePath)),
+        pprScore: Number(item.score.toFixed(6)),
+        incomingCallers,
+        outgoingCalls,
+        validFrom: node.properties.validFrom || null,
+        relevantDecisions: [],
+        relevantLearnings: [],
+      });
+    }
+ 
+    return slices;
+  }
+ 
+  private resolveNodeForSlice(nodeId: string): {
+    node: GraphNode;
+    filePath: string;
+    startLine: number;
+    endLine: number;
+  } | null {
+    const node = this.context.index.getNode(nodeId);
+    Iif (!node) {
+      return null;
+    }
+ 
+    let filePath = String(node.properties.path || node.properties.filePath || "");
+    Iif (!filePath) {
+      const parents = this.context.index
+        .getRelationshipsTo(node.id)
+        .filter((rel) => rel.type === "CONTAINS");
+      const fileNode = parents
+        .map((rel) => this.context.index.getNode(rel.from))
+        .find((candidate) => candidate?.type === "FILE");
+      filePath = String(fileNode?.properties.path || fileNode?.properties.filePath || "");
+    }
+ 
+    Iif (!filePath) {
+      filePath = node.id;
+    }
+ 
+    const startLine = Number(node.properties.startLine || node.properties.line || 1);
+    const endLine = Number(node.properties.endLine || startLine + 40);
+ 
+    return {
+      node,
+      filePath,
+      startLine,
+      endLine,
+    };
+  }
+ 
+  private readCodeSnippet(
+    absolutePath: string,
+    startLine: number,
+    endLine: number,
+    maxChars: number,
+  ): string {
+    try {
+      if (!fs.existsSync(absolutePath)) {
+        return "";
+      }
+      const lines = fs.readFileSync(absolutePath, "utf-8").split("\n");
+      const snippet = lines
+        .slice(Math.max(0, startLine - 1), Math.max(startLine, endLine))
+        .join("\n");
+      return snippet.length > maxChars ? `${snippet.slice(0, maxChars - 3)}...` : snippet;
+    } catch {
+      return "";
+    }
+  }
+ 
+  private async findActiveBlockers(
+    selectedIds: string[],
+    requestingAgentId: string,
+    projectId: string,
+  ): Promise<any[]> {
+    Eif (!selectedIds.length) {
+      return [];
+    }
+ 
+    const blockers = await this.context.memgraph.executeCypher(
+      `MATCH (c:CLAIM)-[:TARGETS]->(t)
+       WHERE c.projectId = $projectId
+         AND t.projectId = $projectId
+         AND c.validTo IS NULL
+         AND t.id IN $selectedIds
+         AND c.agentId <> $requestingAgentId
+       RETURN c.id AS claimId, c.agentId AS agentId, c.intent AS intent, t.id AS targetId, c.validFrom AS since
+       ORDER BY c.validFrom DESC
+       LIMIT 20`,
+      { projectId, selectedIds, requestingAgentId },
+    );
+ 
+    return (blockers.data || []).map((row) => ({
+      claimId: String(row.claimId || ""),
+      agentId: String(row.agentId || "unknown"),
+      intent: String(row.intent || ""),
+      targetId: String(row.targetId || ""),
+      since: Number(row.since || Date.now()),
+    }));
+  }
+ 
+  private async findDecisionEpisodes(selectedIds: string[], projectId: string): Promise<any[]> {
+    Eif (!selectedIds.length) {
+      return [];
+    }
+ 
+    const result = await this.context.memgraph.executeCypher(
+      `MATCH (e:EPISODE {projectId: $projectId, type: 'DECISION'})-[:INVOLVES]->(n)
+       WHERE n.projectId = $projectId AND n.id IN $selectedIds
+       RETURN e.id AS id, e.content AS content, e.timestamp AS timestamp
+       ORDER BY e.timestamp DESC
+       LIMIT 10`,
+      { projectId, selectedIds },
+    );
+ 
+    return (result.data || []).map((row) => ({
+      id: String(row.id || ""),
+      content: String(row.content || ""),
+      timestamp: Number(row.timestamp || Date.now()),
+    }));
+  }
+ 
+  private async findLearnings(selectedIds: string[], projectId: string): Promise<any[]> {
+    Eif (!selectedIds.length) {
+      return [];
+    }
+ 
+    const result = await this.context.memgraph.executeCypher(
+      `MATCH (l:LEARNING {projectId: $projectId})-[:APPLIES_TO]->(n)
+       WHERE n.projectId = $projectId AND n.id IN $selectedIds
+       RETURN l.id AS id, l.content AS content, l.confidence AS confidence
+       ORDER BY l.confidence DESC
+       LIMIT 10`,
+      { projectId, selectedIds },
+    );
+ 
+    return (result.data || []).map((row) => ({
+      id: String(row.id || ""),
+      content: String(row.content || ""),
+      confidence: Number(row.confidence || 0),
+    }));
+  }
+ 
+  private async findRecentEpisodes(
+    taskId: string | undefined,
+    agentId: string,
+    projectId: string,
+  ): Promise<any[]> {
+    const conditions: string[] = ["e.projectId = $projectId"];
+    const params: Record<string, unknown> = { projectId };
+ 
+    if (taskId) {
+      conditions.push("e.taskId = $taskId");
+      params.taskId = taskId;
+    } else E{
+      conditions.push("e.agentId = $agentId");
+      params.agentId = agentId;
+    }
+ 
+    const result = await this.context.memgraph.executeCypher(
+      `MATCH (e:EPISODE)
+       WHERE ${conditions.join(" AND ")}
+       RETURN e.id AS id, e.type AS type, e.content AS content, e.timestamp AS timestamp
+       ORDER BY e.timestamp DESC
+       LIMIT 10`,
+      params,
+    );
+ 
+    return (result.data || []).map((row) => ({
+      id: String(row.id || ""),
+      type: String(row.type || "OBSERVATION"),
+      content: String(row.content || ""),
+      timestamp: Number(row.timestamp || Date.now()),
+    }));
+  }
+ 
+  private trimContextPackToBudget(pack: Record<string, any>, budget: number): void {
+    Iif (!Number.isFinite(budget)) {
+      return;
+    }
+ 
+    const pruneStep = () => {
+      if (Array.isArray(pack.coreSymbols) && pack.coreSymbols.length > 1) {
+        pack.coreSymbols.pop();
+        return true;
+      }
+      if (Array.isArray(pack.decisions) && pack.decisions.length > 2) {
+        pack.decisions.pop();
+        return true;
+      }
+      if (Array.isArray(pack.learnings) && pack.learnings.length > 2) {
+        pack.learnings.pop();
+        return true;
+      }
+      if (Array.isArray(pack.episodes) && pack.episodes.length > 2) {
+        pack.episodes.pop();
+        return true;
+      }
+      if (Array.isArray(pack.coreSymbols)) {
+        for (const symbol of pack.coreSymbols) {
+          if (typeof symbol.code === "string" && symbol.code.length > 220) {
+            symbol.code = `${symbol.code.slice(0, 217)}...`;
+            return true;
+          }
+        }
+      }
+      return false;
+    };
+ 
+    let estimated = estimateTokens(pack);
+    let guard = 0;
+    while (estimated > budget && guard < 200) {
+      const changed = pruneStep();
+      if (!changed) {
+        break;
+      }
+      estimated = estimateTokens(pack);
+      guard += 1;
+    }
+  }
+ 
+  private resolveSemanticSliceAnchor(input: { file?: string; symbol?: string; query?: string }): {
+    node: GraphNode;
+    filePath: string;
+    startLine: number;
+    endLine: number;
+  } | null {
+    const normalizedFile = input.file ? String(input.file) : undefined;
+    const normalizedSymbol = input.symbol ? String(input.symbol) : undefined;
+ 
+    Iif (normalizedSymbol?.includes("::")) {
+      const exact = this.resolveNodeForSlice(normalizedSymbol);
+      if (exact) {
+        return exact;
+      }
+    }
+ 
+    Iif (normalizedSymbol && normalizedFile) {
+      const fileNode = this.context.index.getNodesByType("FILE").find((candidate) => {
+        const candidatePath = String(
+          candidate.properties.path || candidate.properties.filePath || "",
+        );
+        return (
+          candidatePath === normalizedFile ||
+          candidatePath.endsWith(normalizedFile) ||
+          normalizedFile.endsWith(candidatePath)
+        );
+      });
+ 
+      if (fileNode) {
+        const childIds = this.context.index
+          .getRelationshipsFrom(fileNode.id)
+          .filter((rel) => rel.type === "CONTAINS")
+          .map((rel) => rel.to);
+        const targetName = normalizedSymbol.split(".").pop() || normalizedSymbol;
+        const child = childIds
+          .map((id) => this.context.index.getNode(id))
+          .find((node) => node?.properties?.name === targetName);
+        if (child) {
+          return this.resolveNodeForSlice(child.id);
+        }
+      }
+    }
+ 
+    Eif (normalizedSymbol) {
+      const targetName = normalizedSymbol.split(".").pop() || normalizedSymbol;
+      const direct = [
+        ...this.context.index.getNodesByType("FUNCTION"),
+        ...this.context.index.getNodesByType("CLASS"),
+        ...this.context.index.getNodesByType("FILE"),
+      ].find((node) => {
+        const name = String(node.properties.name || node.properties.path || "");
+        return name === targetName || name.includes(targetName);
+      });
+ 
+      Eif (direct) {
+        return this.resolveNodeForSlice(direct.id);
+      }
+    }
+ 
+    if (input.query) {
+      const fallbackId = this.findSeedNodeIds(String(input.query), 1)[0];
+      if (fallbackId) {
+        return this.resolveNodeForSlice(fallbackId);
+      }
+    }
+ 
+    if (normalizedFile) {
+      const fileNode = this.context.index.getNodesByType("FILE").find((candidate) => {
+        const candidatePath = String(
+          candidate.properties.path || candidate.properties.filePath || "",
+        );
+        return (
+          candidatePath === normalizedFile ||
+          candidatePath.endsWith(normalizedFile) ||
+          normalizedFile.endsWith(candidatePath)
+        );
+      });
+      if (fileNode) {
+        return this.resolveNodeForSlice(fileNode.id);
+      }
+    }
+ 
+    return null;
+  }
+ 
+  private computeSliceRange(
+    startLine: number,
+    endLine: number,
+    context: "signature" | "body" | "with-deps" | "full",
+  ): [number, number] {
+    Iif (context === "signature") {
+      return [startLine, startLine];
+    }
+    return [startLine, Math.max(startLine, endLine)];
+  }
+ 
+  private readExactLines(absolutePath: string, startLine: number, endLine: number): string {
+    if (!fs.existsSync(absolutePath)) {
+      return "";
+    }
+    const lines = fs.readFileSync(absolutePath, "utf-8").split("\n");
+    return lines.slice(Math.max(0, startLine - 1), Math.max(startLine, endLine)).join("\n");
+  }
+ 
+  // Setup tools are implemented in core-tools.ts and bound via toolRegistry.
+}
+ 
+export default ToolHandlers;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/types.ts.html b/coverage/lcov-report/src/tools/types.ts.html new file mode 100644 index 0000000..afd7c8a --- /dev/null +++ b/coverage/lcov-report/src/tools/types.ts.html @@ -0,0 +1,379 @@ + + + + + + Code coverage report for src/tools/types.ts + + + + + + + + + +
+
+

All files / src/tools types.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file tools/types
+ * @description Shared type contracts for tool registration and runtime dispatch.
+ * @remarks These types define the bridge between registry definitions and handlers.
+ */
+ 
+import type * as z from "zod";
+ 
+/**
+ * High-level categories used to group tools in the registry and metadata output.
+ */
+export type ToolCategory =
+  | "graph"
+  | "code"
+  | "task"
+  | "memory"
+  | "coordination"
+  | "setup"
+  | "utility"
+  | "arch"
+  | "docs"
+  | "ref"
+  | "test";
+ 
+/**
+ * Session-aware project context used for workspace-scoped operations.
+ */
+export interface ProjectContextLike {
+  workspaceRoot: string;
+  sourceDir: string;
+  projectId: string;
+}
+ 
+/**
+ * Collection of lazily-initialized engines available to tool implementations.
+ */
+export interface EngineSet {
+  arch?: unknown;
+  test?: unknown;
+  progress?: unknown;
+  orchestrator?: unknown;
+  qdrant?: unknown;
+  embedding?: unknown;
+  episode?: unknown;
+  coordination?: unknown;
+  community?: unknown;
+  hybrid?: unknown;
+  docs?: unknown;
+}
+ 
+/**
+ * Runtime bridge exposed to tool definitions.
+ *
+ * @remarks
+ * Implementations use this bridge to access engines, context, formatting, and
+ * utility helpers while keeping tool modules decoupled from class internals.
+ */
+export interface HandlerBridge {
+  context: {
+    memgraph: any;
+    index: any;
+    config: any;
+    orchestrator?: any;
+  };
+  engines: EngineSet;
+  getCurrentSessionId(): string | undefined;
+  callTool(toolName: string, rawArgs: any): Promise<string>;
+  getActiveProjectContext(): ProjectContextLike;
+  resolveProjectContext(overrides?: any): ProjectContextLike;
+  normalizeForDispatch(toolName: string, rawArgs: any): { normalized: any; warnings: string[] };
+  validateToolArgs(
+    toolName: string,
+    args: unknown,
+  ): import("./contract-validator.js").ContractValidation;
+  toEpochMillis(asOf?: string): number | null;
+  ensureEmbeddings(projectId?: string): Promise<void>;
+  resolveElement(elementId: string): any | undefined;
+  validateEpisodeInput(args: {
+    type: string;
+    outcome?: unknown;
+    entities?: string[];
+    metadata?: Record<string, unknown>;
+  }): string | null;
+  inferEpisodeEntityHints(query: string, limit: number): Promise<string[]>;
+  errorEnvelope(code: string, reason: string, recoverable?: boolean, hint?: string): string;
+  formatSuccess(data: unknown, profile?: string, summary?: string, toolName?: string): string;
+}
+ 
+/**
+ * Registry contract for a single tool definition.
+ */
+export interface ToolDefinition {
+  name: string;
+  category: ToolCategory;
+  description: string;
+  inputShape: z.ZodRawShape;
+  impl(args: any, bridge: HandlerBridge): Promise<string>;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/tools/vector-tools.ts.html b/coverage/lcov-report/src/tools/vector-tools.ts.html new file mode 100644 index 0000000..2ddc72e --- /dev/null +++ b/coverage/lcov-report/src/tools/vector-tools.ts.html @@ -0,0 +1,949 @@ + + + + + + Code coverage report for src/tools/vector-tools.ts + + + + + + + + + +
+
+

All files / src/tools vector-tools.ts

+
+ +
+ 0% + Statements + 0/75 +
+ + +
+ 0% + Branches + 0/34 +
+ + +
+ 0% + Functions + 0/15 +
+ + +
+ 0% + Lines + 0/71 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Vector Search Tools
+ * Semantic code search capabilities
+ */
+ 
+import type EmbeddingEngine from "../vector/embedding-engine.js";
+import type { GraphIndexManager } from "../graph/index.js";
+ 
+export interface SemanticSearchResult {
+  id: string;
+  name: string;
+  type: "function" | "class" | "file";
+  similarity: number;
+  path?: string;
+  description?: string;
+}
+ 
+/**
+ * Vector search tools for semantic code analysis
+ */
+export class VectorTools {
+  constructor(
+    private embeddingEngine: EmbeddingEngine | null,
+    private index: GraphIndexManager,
+  ) {}
+ 
+  /**
+   * Find similar code to a query
+   */
+  async code_search_semantic(args: any): Promise<string> {
+    if (!this.embeddingEngine) {
+      return JSON.stringify({
+        error: "Embedding engine not initialized",
+        suggestion: "Run graph:build with embeddings enabled",
+      });
+    }
+ 
+    const { query, type = "function", limit = 5 } = args;
+ 
+    try {
+      const results = await this.embeddingEngine.findSimilar(query, type, limit);
+ 
+      const formatted = results.map((r) => ({
+        id: r.id,
+        name: r.name,
+        type: r.type,
+        path: r.metadata.path,
+        relevance: "high",
+      }));
+ 
+      return JSON.stringify(
+        {
+          query,
+          type,
+          results: formatted,
+          count: formatted.length,
+          note: "Results ranked by semantic similarity",
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Search failed: ${error}` });
+    }
+  }
+ 
+  /**
+   * Find duplicate or similar implementations
+   */
+  async code_find_duplicates(args: any): Promise<string> {
+    if (!this.embeddingEngine) {
+      return JSON.stringify({
+        error: "Embedding engine not initialized",
+      });
+    }
+ 
+    const { name, type = "function" } = args;
+ 
+    try {
+      const similar = await this.embeddingEngine.findSimilar(name, type, 10);
+ 
+      const grouped: Record<string, any[]> = {};
+      for (const result of similar) {
+        const group = result.metadata.path?.split("/")[1] || "other";
+        if (!grouped[group]) grouped[group] = [];
+        grouped[group].push({
+          name: result.name,
+          path: result.metadata.path,
+          type: result.type,
+        });
+      }
+ 
+      return JSON.stringify(
+        {
+          query: name,
+          searchType: type,
+          duplicatesByArea: grouped,
+          totalFound: similar.length,
+          recommendation:
+            similar.length > 3
+              ? "Consider refactoring to shared utility"
+              : "No significant duplicates",
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Duplicate search failed: ${error}` });
+    }
+  }
+ 
+  /**
+   * Find code by semantic meaning
+   */
+  async code_search_meaning(args: any): Promise<string> {
+    if (!this.embeddingEngine) {
+      return JSON.stringify({
+        error: "Embedding engine not initialized",
+      });
+    }
+ 
+    const { meaning, limit = 10 } = args;
+ 
+    try {
+      // Search across all types
+      const functionResults = await this.embeddingEngine.findSimilar(
+        meaning,
+        "function",
+        Math.ceil(limit / 3),
+      );
+      const classResults = await this.embeddingEngine.findSimilar(
+        meaning,
+        "class",
+        Math.ceil(limit / 3),
+      );
+      const fileResults = await this.embeddingEngine.findSimilar(
+        meaning,
+        "file",
+        Math.ceil(limit / 3),
+      );
+ 
+      const allResults = [...functionResults, ...classResults, ...fileResults].slice(0, limit);
+ 
+      return JSON.stringify(
+        {
+          query: meaning,
+          results: allResults.map((r) => ({
+            name: r.name,
+            type: r.type,
+            path: r.metadata.path,
+            description: `${r.type} matching: ${meaning}`,
+          })),
+          count: allResults.length,
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Semantic search failed: ${error}` });
+    }
+  }
+ 
+  /**
+   * Suggest refactoring opportunities based on similarity
+   */
+  async code_suggest_refactor(args: any): Promise<string> {
+    if (!this.embeddingEngine) {
+      return JSON.stringify({
+        error: "Embedding engine not initialized",
+      });
+    }
+ 
+    const { element, type = "function" } = args;
+ 
+    try {
+      const similar = await this.embeddingEngine.findSimilar(element, type, 5);
+ 
+      if (similar.length < 2) {
+        return JSON.stringify({
+          element,
+          status: "unique",
+          suggestion: "No similar code found - this is a unique implementation",
+        });
+      }
+ 
+      const suggestions: string[] = [];
+      if (similar.length >= 3) {
+        suggestions.push(
+          `Found ${similar.length} similar implementations - consider extracting common logic`,
+        );
+        suggestions.push("Create a shared utility or service class");
+        suggestions.push("Document the pattern for team consistency");
+      }
+ 
+      return JSON.stringify(
+        {
+          element,
+          type,
+          similarCount: similar.length,
+          similar: similar.map((s) => ({
+            name: s.name,
+            path: s.metadata.path,
+          })),
+          suggestions,
+          priority: similar.length >= 3 ? "high" : "medium",
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Refactor suggestion failed: ${error}` });
+    }
+  }
+ 
+  /**
+   * Hybrid search combining graph and vector queries
+   */
+  async code_hybrid_search(args: any): Promise<string> {
+    const { query, type = "function" } = args;
+ 
+    try {
+      // Vector search (semantic)
+      let vectorResults: any[] = [];
+      if (this.embeddingEngine) {
+        const embedResults = await this.embeddingEngine.findSimilar(query, type, 5);
+        vectorResults = embedResults.map((r) => ({
+          id: r.id,
+          name: r.name,
+          source: "vector",
+          score: 0.8,
+        }));
+      }
+ 
+      // Graph search (structural)
+      const graphResults: any[] = [];
+      if (type === "function") {
+        const nodes = this.index.getNodesByType("FUNCTION");
+        nodes
+          .filter((n) => n.properties.name?.includes(query) || n.properties.name === query)
+          .slice(0, 5)
+          .forEach((n) => {
+            graphResults.push({
+              id: n.id,
+              name: n.properties.name,
+              source: "graph",
+              score: 1.0, // Exact match
+            });
+          });
+      }
+ 
+      // Combine and rank
+      const combined = [...graphResults, ...vectorResults];
+      const ranked = combined
+        .reduce((acc, item) => {
+          const existing = acc.find((a: any) => a.id === item.id);
+          if (existing) {
+            existing.combinedScore = Math.max(existing.combinedScore, item.score);
+            existing.sources.push(item.source);
+          } else {
+            acc.push({
+              ...item,
+              combinedScore: item.score,
+              sources: [item.source],
+            });
+          }
+          return acc;
+        }, [] as any[])
+        .sort((a: any, b: any) => b.combinedScore - a.combinedScore)
+        .slice(0, 10);
+ 
+      return JSON.stringify(
+        {
+          query,
+          type,
+          results: ranked,
+          totalFound: ranked.length,
+          method: "hybrid (graph + vector)",
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Hybrid search failed: ${error}` });
+    }
+  }
+}
+ 
+export default VectorTools;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/types/config.ts.html b/coverage/lcov-report/src/types/config.ts.html new file mode 100644 index 0000000..bffad69 --- /dev/null +++ b/coverage/lcov-report/src/types/config.ts.html @@ -0,0 +1,406 @@ + + + + + + Code coverage report for src/types/config.ts + + + + + + + + + +
+
+

All files / src/types config.ts

+
+ +
+ 0% + Statements + 0/8 +
+ + +
+ 0% + Branches + 0/10 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Configuration type definitions
+ * Phase 4.6: Type safety improvements
+ */
+ 
+/**
+ * Architecture layer configuration
+ */
+export interface ArchitectureLayer {
+  id: string;
+  name: string;
+  description?: string;
+  contains?: string[];
+  canDependOn?: string[];
+}
+ 
+/**
+ * Architecture rule configuration
+ */
+export interface ArchitectureRule {
+  id: string;
+  type: "dependency" | "file-pattern" | "custom";
+  severity: "error" | "warning" | "info";
+  description: string;
+  pattern?: string;
+  from?: string;
+  to?: string;
+}
+ 
+/**
+ * Architecture configuration
+ */
+export interface ArchitectureConfig {
+  layers: ArchitectureLayer[];
+  rules: ArchitectureRule[];
+  projectStructure?: {
+    src?: string;
+    tests?: string;
+    docs?: string;
+  };
+}
+ 
+/**
+ * Full configuration object
+ */
+export interface ApplicationConfig {
+  architecture: ArchitectureConfig;
+  version?: string;
+  name?: string;
+}
+ 
+/**
+ * Memgraph connection config
+ */
+export interface MemgraphConfig {
+  host: string;
+  port: number;
+  username?: string;
+  password?: string;
+}
+ 
+/**
+ * Qdrant connection config
+ */
+export interface QdrantConfig {
+  host: string;
+  port: number;
+  apiKey?: string;
+}
+ 
+/**
+ * MCP server config
+ */
+export interface MCPServerConfig {
+  transport: "stdio" | "http";
+  port?: number;
+  name?: string;
+  version?: string;
+}
+ 
+/**
+ * System configuration combining all sub-configs
+ */
+export interface SystemConfig {
+  application: ApplicationConfig;
+  memgraph: MemgraphConfig;
+  qdrant: QdrantConfig;
+  mcp: MCPServerConfig;
+}
+ 
+/**
+ * Type guard to check if value is valid architecture config
+ */
+export function isValidArchitectureConfig(obj: unknown): obj is ArchitectureConfig {
+  if (!obj || typeof obj !== "object") return false;
+  const config = obj as Record<string, unknown>;
+  return Array.isArray(config.layers) && Array.isArray(config.rules);
+}
+ 
+/**
+ * Type guard for application config
+ */
+export function isValidApplicationConfig(obj: unknown): obj is ApplicationConfig {
+  if (!obj || typeof obj !== "object") return false;
+  const config = obj as Record<string, unknown>;
+  return isValidArchitectureConfig(config.architecture);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/types/index.html b/coverage/lcov-report/src/types/index.html new file mode 100644 index 0000000..7b0f029 --- /dev/null +++ b/coverage/lcov-report/src/types/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/types + + + + + + + + + +
+
+

All files src/types

+
+ +
+ 0% + Statements + 0/23 +
+ + +
+ 0% + Branches + 0/25 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 0% + Lines + 0/21 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
config.ts +
+
0%0/80%0/100%0/20%0/6
tool-args.ts +
+
0%0/150%0/150%0/30%0/15
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/types/tool-args.ts.html b/coverage/lcov-report/src/types/tool-args.ts.html new file mode 100644 index 0000000..0327366 --- /dev/null +++ b/coverage/lcov-report/src/types/tool-args.ts.html @@ -0,0 +1,586 @@ + + + + + + Code coverage report for src/types/tool-args.ts + + + + + + + + + +
+
+

All files / src/types tool-args.ts

+
+ +
+ 0% + Statements + 0/15 +
+ + +
+ 0% + Branches + 0/15 +
+ + +
+ 0% + Functions + 0/3 +
+ + +
+ 0% + Lines + 0/15 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Type definitions for MCP tool arguments
+ * Phase 4.6: Type safety improvements
+ */
+ 
+/**
+ * Generic tool arguments with required and optional fields
+ */
+export interface ToolArgs {
+  [key: string]: unknown;
+}
+ 
+/**
+ * Graph query tool arguments
+ */
+export interface GraphQueryArgs extends ToolArgs {
+  query: string;
+  language?: "cypher" | "natural";
+  mode?: "local" | "global" | "hybrid";
+  limit?: number;
+  asOf?: string;
+}
+ 
+/**
+ * Graph set workspace arguments
+ */
+export interface GraphSetWorkspaceArgs extends ToolArgs {
+  workspaceRoot: string;
+  sourceDir?: string;
+  projectId?: string;
+}
+ 
+/**
+ * Graph rebuild arguments
+ */
+export interface GraphRebuildArgs extends ToolArgs {
+  mode?: "full" | "incremental";
+  verbose?: boolean;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Graph health arguments
+ */
+export interface GraphHealthArgs extends ToolArgs {
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Semantic search arguments
+ */
+export interface SemanticSearchArgs extends ToolArgs {
+  query: string;
+  type?: "function" | "class" | "file";
+  limit?: number;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Find similar arguments
+ */
+export interface FindSimilarArgs extends ToolArgs {
+  elementId: string;
+  limit?: number;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Code clusters arguments
+ */
+export interface CodeClustersArgs extends ToolArgs {
+  type?: "function" | "class" | "file";
+  count?: number;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Create feature arguments
+ */
+export interface CreateFeatureArgs extends ToolArgs {
+  name: string;
+  description?: string;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Create task arguments
+ */
+export interface CreateTaskArgs extends ToolArgs {
+  name: string;
+  featureId?: string;
+  description?: string;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Update task arguments
+ */
+export interface UpdateTaskArgs extends ToolArgs {
+  taskId: string;
+  status?: "pending" | "in-progress" | "completed" | "blocked";
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Union type for all tool arguments
+ */
+export type AnyToolArgs =
+  | GraphQueryArgs
+  | GraphSetWorkspaceArgs
+  | GraphRebuildArgs
+  | GraphHealthArgs
+  | SemanticSearchArgs
+  | FindSimilarArgs
+  | CodeClustersArgs
+  | CreateFeatureArgs
+  | CreateTaskArgs
+  | UpdateTaskArgs
+  | ToolArgs;
+ 
+/**
+ * Type guard to safely extract typed arguments
+ */
+export function extractToolArgs<T extends ToolArgs>(
+  args: unknown,
+  requiredFields: string[] = [],
+): T {
+  if (!args || typeof args !== "object") {
+    throw new Error(`Invalid tool arguments: expected object, got ${typeof args}`);
+  }
+ 
+  const obj = args as Record<string, unknown>;
+ 
+  for (const field of requiredFields) {
+    if (!(field in obj)) {
+      throw new Error(`Missing required field: ${field}`);
+    }
+  }
+ 
+  return obj as T;
+}
+ 
+/**
+ * Get profile from tool arguments (safely)
+ */
+export function getProfileFromArgs(args: ToolArgs): "compact" | "balanced" | "debug" {
+  const profile = args.profile;
+  if (typeof profile === "string" && ["compact", "balanced", "debug"].includes(profile)) {
+    return profile as "compact" | "balanced" | "debug";
+  }
+  return "compact";
+}
+ 
+/**
+ * Get limit from tool arguments with validation
+ */
+export function getLimitFromArgs(
+  args: ToolArgs,
+  defaultLimit: number = 100,
+  maxLimit: number = 10000,
+): number {
+  const limit = args.limit;
+  if (typeof limit === "number") {
+    return Math.max(1, Math.min(limit, maxLimit));
+  }
+  return defaultLimit;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/utils/exec-utils.ts.html b/coverage/lcov-report/src/utils/exec-utils.ts.html new file mode 100644 index 0000000..fed3a4a --- /dev/null +++ b/coverage/lcov-report/src/utils/exec-utils.ts.html @@ -0,0 +1,313 @@ + + + + + + Code coverage report for src/utils/exec-utils.ts + + + + + + + + + +
+
+

All files / src/utils exec-utils.ts

+
+ +
+ 100% + Statements + 15/15 +
+ + +
+ 84.61% + Branches + 11/13 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 15/15 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +7x +7x +  +  +  +  +  +  +7x +  +4x +4x +1x +  +  +  +  +3x +1x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +  +1x +1x +  +  + 
/**
+ * Command execution utilities with timeout and output size limits
+ * Phase 4: Security hardening
+ */
+ 
+import { execSync } from "child_process";
+import type { ExecSyncOptionsWithStringEncoding } from "child_process";
+import * as env from "../env.js";
+ 
+export interface SafeExecOptions extends Omit<ExecSyncOptionsWithStringEncoding, "encoding"> {
+  timeout?: number;
+  maxOutputBytes?: number;
+  encoding?: "utf-8";
+}
+ 
+/**
+ * Execute a command with timeout and output size limits
+ * @param command Command to execute
+ * @param options Execution options (timeout, maxOutputBytes, etc)
+ * @returns Command output
+ * @throws Error if timeout exceeded or output exceeds limit
+ */
+export function execWithTimeout(command: string, options: SafeExecOptions = {}): string {
+  const {
+    timeout = env.LXRAG_COMMAND_EXECUTION_TIMEOUT_MS,
+    maxOutputBytes = env.LXRAG_COMMAND_OUTPUT_SIZE_LIMIT_BYTES,
+    encoding = "utf-8",
+    ...execOptions
+  } = options;
+ 
+  try {
+    const output = execSync(command, {
+      ...execOptions,
+      encoding,
+      timeout,
+      maxBuffer: maxOutputBytes,
+    }) as string;
+ 
+    return output;
+  } catch (error) {
+    Eif (error instanceof Error) {
+      if (error.message.includes("ETIMEDOUT")) {
+        throw new Error(
+          `Command execution timeout exceeded (${timeout}ms): ${command.substring(0, 100)}`,
+          { cause: error },
+        );
+      }
+      if (error.message.includes("maxBuffer")) {
+        throw new Error(
+          `Command output exceeded size limit (${maxOutputBytes} bytes): ${command.substring(0, 100)}`,
+          { cause: error },
+        );
+      }
+    }
+    throw error;
+  }
+}
+ 
+/**
+ * Execute a command with timeout, catching all errors
+ * @param command Command to execute
+ * @param options Execution options
+ * @returns [success, output, error]
+ */
+export function execWithTimeoutSafe(
+  command: string,
+  options: SafeExecOptions = {},
+): [success: boolean, output: string, error: string | null] {
+  try {
+    const output = execWithTimeout(command, options);
+    return [true, output, null];
+  } catch (error) {
+    const errorMsg = error instanceof Error ? error.message : String(error);
+    return [false, "", errorMsg];
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/utils/index.html b/coverage/lcov-report/src/utils/index.html new file mode 100644 index 0000000..ecef609 --- /dev/null +++ b/coverage/lcov-report/src/utils/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/utils + + + + + + + + + +
+
+

All files src/utils

+
+ +
+ 92.38% + Statements + 97/105 +
+ + +
+ 87.17% + Branches + 102/117 +
+ + +
+ 100% + Functions + 20/20 +
+ + +
+ 92.07% + Lines + 93/101 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
exec-utils.ts +
+
100%15/1584.61%11/13100%2/2100%15/15
logger.ts +
+
90.32%28/3180.76%21/26100%7/788.88%24/27
validation.ts +
+
91.52%54/5989.74%70/78100%11/1191.52%54/59
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/utils/logger.ts.html b/coverage/lcov-report/src/utils/logger.ts.html new file mode 100644 index 0000000..12d3792 --- /dev/null +++ b/coverage/lcov-report/src/utils/logger.ts.html @@ -0,0 +1,481 @@ + + + + + + Code coverage report for src/utils/logger.ts + + + + + + + + + +
+
+

All files / src/utils logger.ts

+
+ +
+ 90.32% + Statements + 28/31 +
+ + +
+ 80.76% + Branches + 21/26 +
+ + +
+ 100% + Functions + 7/7 +
+ + +
+ 88.88% + Lines + 24/27 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +13x +  +  +  +  +  +  +  +  +13x +13x +  +  +  +  +13x +  +  +  +  +  +  +  +2945x +46x +36x +  +10x +  +  +10x +10x +  +  +  +  +  +  +  +  +  +  +2987x +  +2945x +2945x +2945x +  +2945x +  +  +  +  +  +2945x +2945x +46x +  +  +2945x +  +  +  +  +  +  +  +13x +  +  +  +  +42x +  +  +  +  +  +  +8x +  +  +  +  +  +  +135x +  +  +  +  +  +  +2802x +  +  + 
/**
+ * Lightweight structured logger for lxRAG-MCP.
+ *
+ * Design constraints:
+ *   - MCP servers use stdio transport — stdout is protocol data.
+ *     ALL log output MUST go to stderr to avoid corrupting the MCP stream.
+ *   - Zero runtime dependencies (no pino/winston).
+ *   - Output: newline-delimited JSON so log aggregators can ingest directly.
+ *   - Automatically includes `sessionId` from AsyncLocalStorage when available.
+ *   - Respects `LXRAG_LOG_LEVEL` env var (default "info").
+ *
+ * Log levels (numeric priority, lower = more verbose):
+ *   debug:0  info:1  warn:2  error:3
+ *
+ * Usage:
+ *   import { logger } from "../utils/logger.js";
+ *   logger.info("Graph rebuilt", { projectId, nodeCount });
+ *   logger.error("Connection failed", { url, cause: err.message });
+ */
+ 
+import { getRequestContext } from "../request-context.js";
+ 
+// ── Level priority map ────────────────────────────────────────────────────────
+ 
+type LogLevel = "debug" | "info" | "warn" | "error";
+ 
+/**
+ * Accepted context types for logger methods.
+ *
+ * - `Record<string, unknown>` — structured key-value pairs (preferred)
+ * - `Error` — automatically mapped to `{ cause: err.message, stack: err.stack }`
+ * - `string` — additional description, mapped to `{ detail: str }`
+ * - `unknown` — any value caught from a try/catch, coerced safely
+ */
+export type LogContext = Record<string, unknown> | Error | string | unknown;
+ 
+const LEVEL_PRIORITY: Record<LogLevel, number> = {
+  debug: 0,
+  info: 1,
+  warn: 2,
+  error: 3,
+};
+ 
+/** Resolves the configured minimum log level at startup. */
+function resolveMinLevel(): LogLevel {
+  const raw = (process.env.LXRAG_LOG_LEVEL ?? "info").toLowerCase();
+  Eif (raw in LEVEL_PRIORITY) return raw as LogLevel;
+  // Unknown value → fall back to "info" silently (avoid recursive logging).
+  return "info";
+}
+ 
+const MIN_LEVEL_PRIORITY: number = LEVEL_PRIORITY[resolveMinLevel()];
+ 
+// ── Core emitter ──────────────────────────────────────────────────────────────
+ 
+/**
+ * Normalises any accepted context type into a plain `Record<string, unknown>`.
+ */
+function normalizeContext(ctx: LogContext | undefined): Record<string, unknown> | undefined {
+  if (ctx === undefined || ctx === null) return undefined;
+  if (ctx instanceof Error) {
+    return { cause: ctx.message, stack: ctx.stack };
+  }
+  Iif (typeof ctx === "string") {
+    return ctx.length > 0 ? { detail: ctx } : undefined;
+  }
+  Eif (typeof ctx === "object" && !Array.isArray(ctx)) {
+    return ctx as Record<string, unknown>;
+  }
+  return { value: String(ctx) };
+}
+ 
+/**
+ * Writes a single structured log record to stderr.
+ * Never throws — log failures are silently swallowed to keep the MCP stream
+ * alive even if the log serialization encounters a circular reference.
+ */
+function emit(level: LogLevel, message: string, context?: LogContext): void {
+  if (LEVEL_PRIORITY[level] < MIN_LEVEL_PRIORITY) return;
+ 
+  try {
+    const { sessionId } = getRequestContext();
+    const normalized = normalizeContext(context);
+ 
+    const record: Record<string, unknown> = {
+      level,
+      msg: message,
+      ts: new Date().toISOString(),
+    };
+ 
+    if (sessionId) record.sessionId = sessionId;
+    if (normalized && Object.keys(normalized).length > 0) {
+      Object.assign(record, normalized);
+    }
+ 
+    process.stderr.write(JSON.stringify(record) + "\n");
+  } catch {
+    // Swallow serialization errors — a log failure must never crash the server.
+  }
+}
+ 
+// ── Public logger interface ───────────────────────────────────────────────────
+ 
+export const logger = {
+  /**
+   * Verbose diagnostic output — enabled only at LXRAG_LOG_LEVEL=debug.
+   */
+  debug(message: string, context?: LogContext): void {
+    emit("debug", message, context);
+  },
+ 
+  /**
+   * Normal operational events (startup, completion, counts).
+   */
+  info(message: string, context?: LogContext): void {
+    emit("info", message, context);
+  },
+ 
+  /**
+   * Recoverable anomalies — retryable errors, degraded operation, deprecated usage.
+   */
+  warn(message: string, context?: LogContext): void {
+    emit("warn", message, context);
+  },
+ 
+  /**
+   * Non-recoverable or unexpected errors that need attention.
+   */
+  error(message: string, context?: LogContext): void {
+    emit("error", message, context);
+  },
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/utils/validation.ts.html b/coverage/lcov-report/src/utils/validation.ts.html new file mode 100644 index 0000000..5e71f6d --- /dev/null +++ b/coverage/lcov-report/src/utils/validation.ts.html @@ -0,0 +1,796 @@ + + + + + + Code coverage report for src/utils/validation.ts + + + + + + + + + +
+
+

All files / src/utils validation.ts

+
+ +
+ 91.52% + Statements + 54/59 +
+ + +
+ 89.74% + Branches + 70/78 +
+ + +
+ 100% + Functions + 11/11 +
+ + +
+ 91.52% + Lines + 54/59 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +1x +  +  +3x +1x +  +  +2x +1x +  +  +1x +  +  +  +  +  +  +  +  +  +3x +  +  +  +3x +  +  +  +  +3x +2x +  +  +1x +  +  +  +  +  +  +  +  +  +  +3x +1x +  +  +2x +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +3x +1x +  +  +2x +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +3x +1x +  +  +2x +  +  +  +  +  +2x +2x +1x +  +  +1x +  +  +  +  +  +  +  +  +  +4x +  +  +  +4x +  +4x +2x +  +  +2x +  +  +  +  +  +  +  +  +  +3x +1x +  +  +2x +1x +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +18x +1x +  +  +17x +17x +  +  +  +17x +18x +1x +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +7x +  + 
/**
+ * Input validation and sanitization utilities
+ * Phase 4: Security hardening
+ */
+ 
+import { randomBytes } from "crypto";
+ 
+/**
+ * Validate a projectId string
+ * Must be alphanumeric with hyphens and underscores only
+ * @param projectId Project identifier to validate
+ * @throws Error if invalid
+ */
+export function validateProjectId(projectId: unknown): string {
+  if (typeof projectId !== "string") {
+    throw new Error("projectId must be a string");
+  }
+ 
+  if (projectId.length === 0 || projectId.length > 128) {
+    throw new Error("projectId must be between 1 and 128 characters");
+  }
+ 
+  if (!/^[a-zA-Z0-9_-]+$/.test(projectId)) {
+    throw new Error("projectId can only contain alphanumeric characters, hyphens, and underscores");
+  }
+ 
+  return projectId;
+}
+ 
+/**
+ * Validate a file path string
+ * Prevents path traversal attacks
+ * @param filePath File path to validate
+ * @throws Error if invalid
+ */
+export function validateFilePath(filePath: unknown): string {
+  Iif (typeof filePath !== "string") {
+    throw new Error("filePath must be a string");
+  }
+ 
+  Iif (filePath.length === 0 || filePath.length > 2048) {
+    throw new Error("filePath must be between 1 and 2048 characters");
+  }
+ 
+  // Prevent path traversal
+  if (filePath.includes("..") || filePath.startsWith("/")) {
+    throw new Error("filePath cannot contain .. or start with /");
+  }
+ 
+  return filePath;
+}
+ 
+/**
+ * Validate a query string (natural language or user input)
+ * Limits length and checks for potentially dangerous patterns
+ * @param query Query string to validate
+ * @param maxLength Maximum allowed length (default 10000)
+ * @throws Error if invalid
+ */
+export function validateQuery(query: unknown, maxLength: number = 10000): string {
+  if (typeof query !== "string") {
+    throw new Error("query must be a string");
+  }
+ 
+  if (query.length === 0 || query.length > maxLength) {
+    throw new Error(
+      `query must be between 1 and ${maxLength} characters (received ${query.length})`,
+    );
+  }
+ 
+  return query;
+}
+ 
+/**
+ * Validate a Cypher query string
+ * Basic validation to catch obvious injection attempts
+ * @param query Cypher query to validate
+ * @throws Error if potentially dangerous patterns detected
+ */
+export function validateCypherQuery(query: unknown): string {
+  if (typeof query !== "string") {
+    throw new Error("Cypher query must be a string");
+  }
+ 
+  if (query.length === 0 || query.length > 50000) {
+    throw new Error(
+      `Cypher query must be between 1 and 50000 characters (received ${query.length})`,
+    );
+  }
+ 
+  // Warn about raw string concatenation patterns (but don't block - parametrized queries should be used)
+  const upperQuery = query.toUpperCase();
+  Iif (
+    (upperQuery.includes("+ '") || upperQuery.includes('+ "') || upperQuery.includes("$")) &&
+    upperQuery.includes("MATCH")
+  ) {
+    // Note: This is a heuristic - legitimate queries may have these patterns
+    // The real protection is in using parameterized queries with $params
+  }
+ 
+  return query;
+}
+ 
+/**
+ * Validate a node ID (must follow scoped format: projectId:type:name)
+ * @param nodeId Node ID to validate
+ * @throws Error if invalid
+ */
+export function validateNodeId(nodeId: unknown): string {
+  if (typeof nodeId !== "string") {
+    throw new Error("nodeId must be a string");
+  }
+ 
+  Iif (nodeId.length === 0 || nodeId.length > 512) {
+    throw new Error("nodeId must be between 1 and 512 characters");
+  }
+ 
+  // Check for basic scoped format (optional validation)
+  // Format: projectId:type:name
+  const parts = nodeId.split(":");
+  if (parts.length < 1 || parts.length > 10) {
+    throw new Error("nodeId has invalid format (should be space-separated with colon delimiters)");
+  }
+ 
+  return nodeId;
+}
+ 
+/**
+ * Validate a limit parameter for queries
+ * @param limit Limit value to validate
+ * @param maxLimit Maximum allowed limit (default 10000)
+ * @throws Error if invalid
+ */
+export function validateLimit(limit: unknown, maxLimit: number = 10000): number {
+  Iif (typeof limit !== "number" && typeof limit !== "string") {
+    throw new Error("limit must be a number or string");
+  }
+ 
+  const numLimit = typeof limit === "string" ? parseInt(limit, 10) : limit;
+ 
+  if (!Number.isInteger(numLimit) || numLimit < 1 || numLimit > maxLimit) {
+    throw new Error(`limit must be an integer between 1 and ${maxLimit} (received ${numLimit})`);
+  }
+ 
+  return numLimit;
+}
+ 
+/**
+ * Validate a mode parameter
+ * @param mode Mode value to validate
+ * @param allowedModes List of allowed modes
+ * @throws Error if invalid
+ */
+export function validateMode(mode: unknown, allowedModes: string[]): string {
+  if (typeof mode !== "string") {
+    throw new Error("mode must be a string");
+  }
+ 
+  if (!allowedModes.includes(mode)) {
+    throw new Error(`mode must be one of: ${allowedModes.join(", ")} (received "${mode}")`);
+  }
+ 
+  return mode;
+}
+ 
+/**
+ * Create a validation error with helpful message
+ * @param field Field name
+ * @param value Value that failed validation
+ * @param reason Reason for validation failure
+ */
+export function createValidationError(field: string, value: unknown, reason: string): Error {
+  return new Error(
+    `Validation failed for ${field}: ${reason} (received ${JSON.stringify(value).substring(0, 100)})`,
+  );
+}
+ 
+/**
+ * Extract projectId from a scoped ID safely
+ * Format: projectId:type:name or projectId:name
+ * @param id Scoped ID string
+ * @param defaultProjectId Default projectId if extraction fails
+ * @returns Extracted projectId or default value
+ */
+export function extractProjectIdFromScopedId(
+  id: string,
+  defaultProjectId: string = "default",
+): string {
+  if (!id || typeof id !== "string") {
+    return defaultProjectId;
+  }
+ 
+  const parts = id.split(":");
+  Iif (parts.length < 1) {
+    return defaultProjectId;
+  }
+ 
+  const projectId = parts[0]?.trim();
+  if (!projectId || projectId.length === 0) {
+    return defaultProjectId;
+  }
+ 
+  return projectId;
+}
+ 
+/**
+ * Extract all parts of a scoped ID safely
+ * Format: projectId:type:name
+ * @param id Scoped ID string
+ * @returns Object with projectId, type (optional), and name (optional)
+ */
+export function parseScopedId(id: string): {
+  projectId: string;
+  type?: string;
+  name?: string;
+  raw: string;
+} {
+  const parts = id.split(":");
+  return {
+    projectId: parts[0] || "default",
+    type: parts[1],
+    name: parts[2],
+    raw: id,
+  };
+}
+ 
+/**
+ * Phase 4.2: Generate a cryptographically secure random ID
+ * Replaces weak Math.random() based generation
+ * @param prefix Prefix for the ID
+ * @param length Length of random part (bytes, default 8)
+ * @returns Secure random ID with format: prefix-randomHex
+ */
+export function generateSecureId(prefix: string = "id", length: number = 8): string {
+  const hex = randomBytes(length).toString("hex");
+  return `${prefix}-${hex}`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/vector/embedding-engine.ts.html b/coverage/lcov-report/src/vector/embedding-engine.ts.html new file mode 100644 index 0000000..f057856 --- /dev/null +++ b/coverage/lcov-report/src/vector/embedding-engine.ts.html @@ -0,0 +1,1003 @@ + + + + + + Code coverage report for src/vector/embedding-engine.ts + + + + + + + + + +
+
+

All files / src/vector embedding-engine.ts

+
+ +
+ 94.11% + Statements + 112/119 +
+ + +
+ 82.75% + Branches + 48/58 +
+ + +
+ 84.21% + Functions + 16/19 +
+ + +
+ 96% + Lines + 96/100 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +131x +131x +131x +  +  +  +  +  +  +  +  +  +  +10x +  +10x +10x +10x +  +  +10x +10x +8x +8x +8x +  +  +  +10x +10x +5x +5x +5x +  +  +  +10x +10x +5x +5x +5x +  +  +10x +10x +10x +10x +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +18x +18x +  +  +  +  +18x +  +  +  +18x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +18x +  +18x +18x +18x +18x +18x +18x +18x +  +18x +  +  +  +  +  +  +  +22x +  +  +22x +794x +794x +794x +  +  +  +2816x +2816x +  +  +  +  +  +  +4x +3x +3x +  +  +  +1x +1x +1x +  +  +1x +1x +1x +  +1x +3x +  +  +  +  +  +  +  +  +  +  +3x +1x +1x +  +  +  +1x +1x +  +1x +1x +  +1x +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +1x +  +  +  +1x +1x +  +2x +2x +  +  +2x +1x +1x +  +  +  +  +  +3x +6x +4x +1x +  +  +3x +1x +  +  +  +  +  +1x +  +  +  +1x +1x +1x +  +1x +1x +128x +128x +128x +  +  +1x +  +  +  +1x +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Embedding Engine
+ * Generates vector embeddings for code elements
+ */
+ 
+import type { GraphIndexManager } from "../graph/index.js";
+import type QdrantClient from "./qdrant-client.js";
+import type { VectorPoint } from "./qdrant-client.js";
+import { extractProjectIdFromScopedId } from "../utils/validation.js";
+import { logger } from "../utils/logger.js";
+ 
+export interface CodeEmbedding {
+  id: string;
+  type: "function" | "class" | "file";
+  name: string;
+  vector: number[];
+  text: string;
+  projectId?: string;
+  metadata: {
+    path?: string;
+    lines?: number;
+    imports?: string[];
+    exports?: string[];
+  };
+}
+ 
+/**
+ * Simple embedding generation (MVP)
+ * In production, use OpenAI API, Hugging Face, or local model
+ */
+export class EmbeddingEngine {
+  private index: GraphIndexManager;
+  private qdrant: QdrantClient;
+  private embeddings: Map<string, CodeEmbedding>;
+ 
+  constructor(index: GraphIndexManager, qdrant: QdrantClient) {
+    this.index = index;
+    this.qdrant = qdrant;
+    this.embeddings = new Map();
+  }
+ 
+  /**
+   * Generate embeddings for all code elements
+   */
+  async generateAllEmbeddings(): Promise<{
+    functions: number;
+    classes: number;
+    files: number;
+  }> {
+    logger.error("[EmbeddingEngine] Starting embedding generation...");
+ 
+    let functionCount = 0;
+    let classCount = 0;
+    let fileCount = 0;
+ 
+    // Generate embeddings for functions
+    const functions = this.index.getNodesByType("FUNCTION");
+    for (const func of functions) {
+      const embedding = this.generateEmbedding("function", func.id, func.properties);
+      this.embeddings.set(embedding.id, embedding);
+      functionCount++;
+    }
+ 
+    // Generate embeddings for classes
+    const classes = this.index.getNodesByType("CLASS");
+    for (const cls of classes) {
+      const embedding = this.generateEmbedding("class", cls.id, cls.properties);
+      this.embeddings.set(embedding.id, embedding);
+      classCount++;
+    }
+ 
+    // Generate embeddings for files
+    const files = this.index.getNodesByType("FILE");
+    for (const file of files) {
+      const embedding = this.generateEmbedding("file", file.id, file.properties);
+      this.embeddings.set(embedding.id, embedding);
+      fileCount++;
+    }
+ 
+    logger.error("[EmbeddingEngine] Generated embeddings:");
+    logger.error(`  Functions: ${functionCount}`);
+    logger.error(`  Classes: ${classCount}`);
+    logger.error(`  Files: ${fileCount}`);
+ 
+    return { functions: functionCount, classes: classCount, files: fileCount };
+  }
+ 
+  /**
+   * Generate embedding for a single element
+   */
+  private generateEmbedding(
+    type: "function" | "class" | "file",
+    id: string,
+    properties: Record<string, any>,
+  ): CodeEmbedding {
+    // MVP: Simple text-based embedding
+    // In production: Use sentence-transformers or OpenAI embeddings
+ 
+    const text = this.propertiesToText(properties);
+    const vector = this.textToVector(text);
+ 
+    // Use projectId from node properties when available; fall back to extracting
+    // from the scoped ID (properties.projectId is set when addToIndex is called
+    // with a projectId, which is the case for all full/incremental rebuilds).
+    const projectId = properties.projectId
+      ? String(properties.projectId)
+      : extractProjectIdFromScopedId(id, undefined);
+ 
+    return {
+      id,
+      type,
+      name: properties.name || properties.path || id,
+      vector,
+      text,
+      projectId,
+      metadata: {
+        path: properties.path,
+        lines: properties.LOC,
+        imports: properties.imports,
+        exports: properties.exports,
+      },
+    };
+  }
+ 
+  /**
+   * Convert properties to text for embedding
+   */
+  private propertiesToText(props: Record<string, any>): string {
+    const parts: string[] = [];
+ 
+    if (props.name) parts.push(props.name);
+    if (props.description) parts.push(props.description);
+    if (props.kind) parts.push(`kind:${props.kind}`);
+    if (props.parameters) parts.push(`params:${props.parameters.join(",")}`);
+    if (props.extends) parts.push(`extends:${props.extends}`);
+    Iif (props.implements) parts.push(`implements:${props.implements.join(",")}`);
+    if (props.path) parts.push(`path:${props.path}`);
+ 
+    return parts.join(" ");
+  }
+ 
+  /**
+   * Convert text to vector (simple hash-based for MVP)
+   * In production: use sentence-transformers or OpenAI API
+   */
+  private textToVector(text: string, dim = 128): number[] {
+    const vector: number[] = new Array(dim).fill(0);
+ 
+    // Simple deterministic hashing for MVP
+    for (let i = 0; i < text.length; i++) {
+      const charCode = text.charCodeAt(i);
+      const index = (i + charCode) % dim;
+      vector[index] += Math.sin(charCode * i) * 0.1;
+    }
+ 
+    // Normalize
+    const magnitude = Math.sqrt(vector.reduce((sum, v) => sum + v * v, 0));
+    return magnitude > 0 ? vector.map((v) => v / magnitude) : vector;
+  }
+ 
+  /**
+   * Store embeddings in Qdrant
+   */
+  async storeInQdrant(): Promise<void> {
+    if (!this.qdrant.isConnected()) {
+      logger.warn("[EmbeddingEngine] Qdrant not connected, skipping storage");
+      return;
+    }
+ 
+    // Create collections
+    await this.qdrant.createCollection("functions", 128);
+    await this.qdrant.createCollection("classes", 128);
+    await this.qdrant.createCollection("files", 128);
+ 
+    // Separate embeddings by type
+    const functionEmbeddings: VectorPoint[] = [];
+    const classEmbeddings: VectorPoint[] = [];
+    const fileEmbeddings: VectorPoint[] = [];
+ 
+    for (const embedding of this.embeddings.values()) {
+      const point: VectorPoint = {
+        id: embedding.id,
+        vector: embedding.vector,
+        payload: {
+          name: embedding.name,
+          text: embedding.text,
+          projectId: embedding.projectId,
+          metadata: embedding.metadata,
+        },
+      };
+ 
+      if (embedding.type === "function") functionEmbeddings.push(point);
+      else if (embedding.type === "class") classEmbeddings.push(pointE);
+      else if (embedding.type === "file") fileEmbeddings.push(point);
+    }
+ 
+    // Upsert to Qdrant
+    Eif (functionEmbeddings.length > 0) {
+      await this.qdrant.upsertPoints("functions", functionEmbeddings);
+    }
+    Eif (classEmbeddings.length > 0) {
+      await this.qdrant.upsertPoints("classes", classEmbeddings);
+    }
+    Eif (fileEmbeddings.length > 0) {
+      await this.qdrant.upsertPoints("files", fileEmbeddings);
+    }
+ 
+    logger.error("[EmbeddingEngine] Embeddings stored in Qdrant");
+  }
+ 
+  /**
+   * Search for similar code
+   * @param query - Search query text
+   * @param type - Entity type to search (function, class, or file)
+   * @param limit - Maximum number of results
+   * @param projectId - Optional project ID to scope search results
+   */
+  async findSimilar(
+    query: string,
+    type: "function" | "class" | "file" = "function",
+    limit = 5,
+    projectId?: string,
+  ): Promise<CodeEmbedding[]> {
+    const queryVector = this.textToVector(query);
+ 
+    if (this.qdrant.isConnected()) {
+      const results = await this.qdrant.search(`${type}s`, queryVector, limit * 2);
+      // Only return Qdrant results when it actually has data; otherwise fall
+      // through to in-memory cosine similarity (e.g. after a fresh rebuild
+      // before Qdrant has been populated).
+      Eif (results.length > 0) {
+        return results
+          .map((result) => {
+            const embedding = this.embeddings.get(result.id);
+            return embedding;
+          })
+          .filter((e) => {
+            if (!e) return false;
+            Iif (projectId && e.projectId !== projectId) return false;
+            return true;
+          })
+          .slice(0, limit) as CodeEmbedding[];
+      }
+    }
+ 
+    const candidates = Array.from(this.embeddings.values()).filter((entry) => {
+      if (entry.type !== type) return false;
+      if (projectId && entry.projectId !== projectId) return false;
+      return true;
+    });
+ 
+    return candidates
+      .map((candidate) => ({
+        candidate,
+        score: this.cosineSimilarity(queryVector, candidate.vector),
+      }))
+      .sort((a, b) => b.score - a.score)
+      .slice(0, limit)
+      .map((row) => row.candidate);
+  }
+ 
+  private cosineSimilarity(left: number[], right: number[]): number {
+    let dot = 0;
+    let leftMagnitude = 0;
+    let rightMagnitude = 0;
+ 
+    const size = Math.min(left.length, right.length);
+    for (let i = 0; i < size; i += 1) {
+      dot += left[i] * right[i];
+      leftMagnitude += left[i] * left[i];
+      rightMagnitude += right[i] * right[i];
+    }
+ 
+    Iif (leftMagnitude === 0 || rightMagnitude === 0) {
+      return 0;
+    }
+ 
+    return dot / (Math.sqrt(leftMagnitude) * Math.sqrt(rightMagnitude));
+  }
+ 
+  /**
+   * Get all embeddings
+   */
+  getAllEmbeddings(): CodeEmbedding[] {
+    return Array.from(this.embeddings.values());
+  }
+ 
+  /**
+   * Export embeddings as JSON
+   */
+  export(): string {
+    const data = Array.from(this.embeddings.values()).map((e) => ({
+      id: e.id,
+      type: e.type,
+      name: e.name,
+      text: e.text,
+      metadata: e.metadata,
+      vectorSize: e.vector.length,
+      // Don't export actual vectors (too verbose)
+    }));
+ 
+    return JSON.stringify(data, null, 2);
+  }
+}
+ 
+export default EmbeddingEngine;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/vector/index.html b/coverage/lcov-report/src/vector/index.html new file mode 100644 index 0000000..2491462 --- /dev/null +++ b/coverage/lcov-report/src/vector/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/vector + + + + + + + + + +
+
+

All files src/vector

+
+ +
+ 88.95% + Statements + 161/181 +
+ + +
+ 75.28% + Branches + 67/89 +
+ + +
+ 87.09% + Functions + 27/31 +
+ + +
+ 91.13% + Lines + 144/158 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
embedding-engine.ts +
+
94.11%112/11982.75%48/5884.21%16/1996%96/100
qdrant-client.ts +
+
79.03%49/6261.29%19/3191.66%11/1282.75%48/58
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/vector/qdrant-client.ts.html b/coverage/lcov-report/src/vector/qdrant-client.ts.html new file mode 100644 index 0000000..eb4bbd4 --- /dev/null +++ b/coverage/lcov-report/src/vector/qdrant-client.ts.html @@ -0,0 +1,724 @@ + + + + + + Code coverage report for src/vector/qdrant-client.ts + + + + + + + + + +
+
+

All files / src/vector qdrant-client.ts

+
+ +
+ 79.03% + Statements + 49/62 +
+ + +
+ 61.29% + Branches + 19/31 +
+ + +
+ 91.66% + Functions + 11/12 +
+ + +
+ 82.75% + Lines + 48/58 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +131x +  +  +131x +  +  +  +  +  +  +130x +  +130x +3x +3x +3x +  +  +1x +1x +  +  +  +  +  +  +  +1x +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +1x +1x +2x +  +1x +  +  +  +  +  +  +1x +  +  +  +  +1x +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +1x +1x +  +  +2x +2x +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +1x +  +1x +1x +1x +  +  +  +  +  +  +  +  +  +2x +  +2x +2x +1x +1x +1x +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +24x +  +  +  +  + 
import { logger } from "../utils/logger.js";
+/**
+ * Qdrant Vector Store Client
+ * Interface to Qdrant for semantic search and embeddings
+ */
+ 
+export interface VectorPoint {
+  id: string;
+  vector: number[];
+  payload: Record<string, any>;
+}
+ 
+export interface SearchResult {
+  id: string;
+  score: number;
+  payload: Record<string, any>;
+}
+ 
+export interface Collection {
+  name: string;
+  vectorSize: number;
+  pointCount: number;
+}
+ 
+/**
+ * Qdrant client for vector operations
+ */
+export class QdrantClient {
+  private baseUrl: string;
+  private connected = false;
+ 
+  constructor(host = "localhost", port = 6333) {
+    this.baseUrl = `http://${host}:${port}`;
+  }
+ 
+  /**
+   * Connect to Qdrant
+   */
+  async connect(): Promise<void> {
+    try {
+      // Use root endpoint instead of /health (which doesn't exist)
+      const response = await fetch(`${this.baseUrl}/`);
+      Eif (response.ok) {
+        this.connected = true;
+        logger.error("[QdrantClient] Connected successfully");
+      }
+    } catch (error) {
+      logger.warn("[QdrantClient] Connection failed (expected for MVP)", error);
+      this.connected = false;
+    }
+  }
+ 
+  /**
+   * Create a collection
+   */
+  async createCollection(name: string, vectorSize: number): Promise<void> {
+    Iif (!this.connected) {
+      logger.warn("[QdrantClient] Not connected");
+      return;
+    }
+ 
+    try {
+      const response = await fetch(`${this.baseUrl}/collections/${name}`, {
+        method: "PUT",
+        headers: { "Content-Type": "application/json" },
+        body: JSON.stringify({
+          vectors: {
+            size: vectorSize,
+            distance: "Cosine",
+          },
+        }),
+      });
+ 
+      Eif (response.ok) {
+        logger.error(`[QdrantClient] Collection '${name}' created`);
+      }
+    } catch (error) {
+      logger.error(`[QdrantClient] Failed to create collection: ${error}`);
+    }
+  }
+ 
+  /**
+   * Hash a string ID to a stable unsigned 32-bit integer for Qdrant.
+   * Qdrant REST API only accepts unsigned integers or UUID v4 as point IDs.
+   */
+  private stringToUint32(s: string): number {
+    let h = 5381;
+    for (let i = 0; i < s.length; i++) {
+      h = (((h * 33) >>> 0) ^ s.charCodeAt(i)) >>> 0;
+    }
+    return h;
+  }
+ 
+  /**
+   * Upsert points into collection
+   */
+  async upsertPoints(collectionName: string, points: VectorPoint[]): Promise<void> {
+    Iif (!this.connected) {
+      logger.warn("[QdrantClient] Not connected, skipping upsert");
+      return;
+    }
+ 
+    try {
+      const response = await fetch(
+        `${this.baseUrl}/collections/${collectionName}/points?wait=true`,
+        {
+          method: "PUT",
+          headers: { "Content-Type": "application/json" },
+          body: JSON.stringify({
+            points: points.map((p) => ({
+              id: this.stringToUint32(p.id),
+              vector: p.vector,
+              // Store original string ID in payload so we can recover it
+              payload: { ...p.payload, originalId: p.id },
+            })),
+          }),
+        },
+      );
+ 
+      if (response.ok) {
+        logger.error(`[QdrantClient] Upserted ${points.length} points to '${collectionName}'`);
+      } else E{
+        const text = await response.text().catch(() => "(unreadable)");
+        logger.error(`[QdrantClient] Upsert failed (${response.status}): ${text}`);
+      }
+    } catch (error) {
+      logger.error(`[QdrantClient] Failed to upsert points: ${error}`);
+    }
+  }
+ 
+  /**
+   * Search for similar vectors
+   */
+  async search(collectionName: string, vector: number[], limit = 10): Promise<SearchResult[]> {
+    if (!this.connected) {
+      logger.warn("[QdrantClient] Not connected");
+      return [];
+    }
+ 
+    try {
+      const response = await fetch(`${this.baseUrl}/collections/${collectionName}/points/search`, {
+        method: "POST",
+        headers: { "Content-Type": "application/json" },
+        body: JSON.stringify({
+          vector,
+          limit,
+          with_payload: true,
+        }),
+      });
+ 
+      Eif (response.ok) {
+        const data = (await response.json()) as any;
+        return (
+          data.result?.map((item: any) => ({
+            // Recover original string ID from payload (stored during upsert)
+            id: String(item.payload?.originalId ?? item.id),
+            score: item.score,
+            payload: item.payload,
+          })) || []
+        );
+      }
+      return [];
+    } catch (error) {
+      logger.error(`[QdrantClient] Search failed: ${error}`);
+      return [];
+    }
+  }
+ 
+  /**
+   * Delete collection
+   */
+  async deleteCollection(name: string): Promise<void> {
+    Iif (!this.connected) return;
+ 
+    try {
+      await fetch(`${this.baseUrl}/collections/${name}`, { method: "DELETE" });
+      logger.error(`[QdrantClient] Collection '${name}' deleted`);
+    } catch (error) {
+      logger.error(`[QdrantClient] Failed to delete collection: ${error}`);
+    }
+  }
+ 
+  /**
+   * Get collection info
+   */
+  async getCollection(name: string): Promise<Collection | null> {
+    Iif (!this.connected) return null;
+ 
+    try {
+      const response = await fetch(`${this.baseUrl}/collections/${name}`);
+      Eif (response.ok) {
+        const data = (await response.json()) as any;
+        return {
+          name,
+          vectorSize: data.result?.config?.params?.vectors?.size || 0,
+          pointCount: data.result?.points_count || 0,
+        };
+      }
+    } catch (error) {
+      logger.error(`[QdrantClient] Failed to get collection: ${error}`);
+    }
+    return null;
+  }
+ 
+  /**
+   * Check connection status
+   */
+  isConnected(): boolean {
+    return this.connected;
+  }
+}
+ 
+export default QdrantClient;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov.info b/coverage/lcov.info new file mode 100644 index 0000000..c6528b8 --- /dev/null +++ b/coverage/lcov.info @@ -0,0 +1,11181 @@ +TN: +SF:src/config.ts +FN:210,loadConfig +FN:225,saveConfig +FNF:2 +FNH:0 +FNDA:0,loadConfig +FNDA:0,saveConfig +DA:77,0 +DA:211,0 +DA:213,0 +DA:214,0 +DA:215,0 +DA:216,0 +DA:219,0 +DA:222,0 +DA:226,0 +DA:227,0 +DA:229,0 +DA:230,0 +DA:233,0 +LF:13 +LH:0 +BRDA:214,0,0,0 +BRDA:214,0,1,0 +BRDA:226,1,0,0 +BRDA:226,1,1,0 +BRDA:229,2,0,0 +BRDA:229,2,1,0 +BRF:6 +BRH:0 +end_of_record +TN: +SF:src/env.ts +FN:35,(anonymous_0) +FN:174,(anonymous_1) +FNF:2 +FNH:2 +FNDA:10,(anonymous_0) +FNDA:10,(anonymous_1) +DA:14,10 +DA:23,10 +DA:28,10 +DA:35,10 +DA:36,10 +DA:37,10 +DA:46,10 +DA:49,10 +DA:56,10 +DA:66,10 +DA:73,10 +DA:80,10 +DA:83,10 +DA:92,10 +DA:99,10 +DA:108,10 +DA:115,10 +DA:125,10 +DA:128,10 +DA:137,10 +DA:140,10 +DA:149,10 +DA:152,10 +DA:162,10 +DA:165,10 +DA:172,10 +DA:174,10 +DA:178,10 +DA:189,10 +DA:192,10 +DA:201,10 +DA:212,10 +DA:223,10 +DA:235,10 +DA:247,10 +DA:257,10 +DA:267,10 +DA:279,10 +DA:292,10 +LF:39 +LH:39 +BRDA:24,0,0,10 +BRDA:24,0,1,10 +BRDA:36,1,0,10 +BRDA:36,1,1,10 +BRDA:37,2,0,10 +BRDA:37,2,1,0 +BRDA:46,3,0,10 +BRDA:46,3,1,10 +BRDA:56,4,0,10 +BRDA:56,4,1,10 +BRDA:66,5,0,10 +BRDA:66,5,1,0 +BRDA:73,6,0,10 +BRDA:73,6,1,0 +BRDA:80,7,0,10 +BRDA:80,7,1,10 +BRDA:92,8,0,10 +BRDA:92,8,1,0 +BRDA:99,9,0,10 +BRDA:99,9,1,0 +BRDA:108,10,0,10 +BRDA:108,10,1,0 +BRDA:115,11,0,10 +BRDA:115,11,1,0 +BRDA:125,12,0,10 +BRDA:125,12,1,10 +BRDA:137,13,0,10 +BRDA:137,13,1,10 +BRDA:172,14,0,10 +BRDA:172,14,1,10 +BRDA:202,15,0,10 +BRDA:202,15,1,10 +BRDA:213,16,0,10 +BRDA:213,16,1,10 +BRDA:224,17,0,10 +BRDA:224,17,1,10 +BRDA:236,18,0,10 +BRDA:236,18,1,10 +BRDA:248,19,0,10 +BRDA:248,19,1,10 +BRDA:258,20,0,10 +BRDA:258,20,1,10 +BRDA:268,21,0,10 +BRDA:268,21,1,10 +BRDA:280,22,0,10 +BRDA:280,22,1,10 +BRDA:292,23,0,10 +BRDA:292,23,1,10 +BRF:48 +BRH:41 +end_of_record +TN: +SF:src/request-context.ts +FN:9,runWithRequestContext +FN:16,getRequestContext +FNF:2 +FNH:2 +FNDA:12,runWithRequestContext +FNDA:3110,getRequestContext +DA:7,13 +DA:13,12 +DA:17,3110 +LF:3 +LH:3 +BRDA:17,0,0,3110 +BRDA:17,0,1,3050 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/server.ts +FN:41,initialize +FN:82,createMcpServerInstance +FN:88,(anonymous_2) +FN:88,(anonymous_3) +FN:109,(anonymous_4) +FN:135,main +FN:148,(anonymous_6) +FN:162,(anonymous_7) +FN:163,(anonymous_8) +FN:171,(anonymous_9) +FN:180,(anonymous_10) +FN:191,(anonymous_11) +FN:210,(anonymous_12) +FN:231,(anonymous_13) +FN:238,(anonymous_14) +FN:261,(anonymous_15) +FN:283,(anonymous_16) +FNF:17 +FNH:0 +FNDA:0,initialize +FNDA:0,createMcpServerInstance +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,main +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:0,(anonymous_16) +DA:24,0 +DA:29,0 +DA:31,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:51,0 +DA:52,0 +DA:56,0 +DA:58,0 +DA:65,0 +DA:67,0 +DA:72,0 +DA:83,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:99,0 +DA:109,0 +DA:110,0 +DA:121,0 +DA:122,0 +DA:125,0 +DA:136,0 +DA:138,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:152,0 +DA:157,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:164,0 +DA:171,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:189,0 +DA:191,0 +DA:192,0 +DA:194,0 +DA:197,0 +DA:198,0 +DA:206,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:214,0 +DA:215,0 +DA:216,0 +DA:228,0 +DA:229,0 +DA:231,0 +DA:232,0 +DA:238,0 +DA:239,0 +DA:240,0 +DA:261,0 +DA:262,0 +DA:263,0 +DA:264,0 +DA:265,0 +DA:270,0 +DA:273,0 +DA:274,0 +DA:275,0 +DA:277,0 +DA:278,0 +DA:283,0 +DA:284,0 +DA:285,0 +LF:88 +LH:0 +BRDA:89,0,0,0 +BRDA:89,0,1,0 +BRDA:140,1,0,0 +BRDA:140,1,1,0 +BRDA:152,2,0,0 +BRDA:152,2,1,0 +BRDA:154,3,0,0 +BRDA:154,3,1,0 +BRDA:159,4,0,0 +BRDA:159,4,1,0 +BRDA:173,5,0,0 +BRDA:173,5,1,0 +BRDA:178,6,0,0 +BRDA:178,6,1,0 +BRDA:197,7,0,0 +BRDA:197,7,1,0 +BRDA:197,8,0,0 +BRDA:197,8,1,0 +BRDA:215,9,0,0 +BRDA:215,9,1,0 +BRDA:220,10,0,0 +BRDA:220,10,1,0 +BRF:22 +BRH:0 +end_of_record +TN: +SF:src/cli/build.ts +FN:20,main +FN:79,(anonymous_1) +FN:84,(anonymous_2) +FN:117,(anonymous_3) +FNF:4 +FNH:0 +FNDA:0,main +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:31,0 +DA:33,0 +DA:34,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:64,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:93,0 +DA:103,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:110,0 +DA:112,0 +DA:113,0 +DA:117,0 +DA:118,0 +DA:119,0 +LF:46 +LH:0 +BRDA:28,0,0,0 +BRDA:28,0,1,0 +BRDA:50,1,0,0 +BRDA:50,1,1,0 +BRDA:73,2,0,0 +BRDA:73,2,1,0 +BRDA:77,3,0,0 +BRDA:77,3,1,0 +BRDA:82,4,0,0 +BRDA:82,4,1,0 +BRDA:89,5,0,0 +BRDA:89,5,1,0 +BRDA:96,6,0,0 +BRDA:96,6,1,0 +BRDA:110,7,0,0 +BRDA:110,7,1,0 +BRF:16 +BRH:0 +end_of_record +TN: +SF:src/cli/query.ts +FN:16,main +FN:59,(anonymous_1) +FNF:2 +FNH:0 +FNDA:0,main +FNDA:0,(anonymous_1) +DA:17,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:26,0 +DA:27,0 +DA:29,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:44,0 +DA:45,0 +DA:47,0 +DA:48,0 +DA:51,0 +DA:52,0 +DA:54,0 +DA:55,0 +DA:59,0 +DA:60,0 +DA:61,0 +LF:25 +LH:0 +BRDA:20,0,0,0 +BRDA:20,0,1,0 +BRDA:38,1,0,0 +BRDA:38,1,1,0 +BRDA:44,2,0,0 +BRDA:44,2,1,0 +BRF:6 +BRH:0 +end_of_record +TN: +SF:src/cli/test-affected.ts +FN:18,main +FN:38,(anonymous_1) +FN:42,(anonymous_2) +FN:71,(anonymous_3) +FN:101,(anonymous_4) +FN:102,(anonymous_5) +FN:103,(anonymous_6) +FN:139,(anonymous_7) +FNF:8 +FNH:0 +FNDA:0,main +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +DA:19,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:42,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:57,0 +DA:58,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:66,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:80,0 +DA:81,0 +DA:84,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:95,0 +DA:97,0 +DA:98,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:112,0 +DA:116,0 +DA:117,0 +DA:121,0 +DA:122,0 +DA:124,0 +DA:125,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:134,0 +DA:135,0 +DA:139,0 +DA:140,0 +DA:141,0 +LF:78 +LH:0 +BRDA:21,0,0,0 +BRDA:21,0,1,0 +BRDA:39,1,0,0 +BRDA:39,1,1,0 +BRDA:42,2,0,0 +BRDA:42,2,1,0 +BRDA:47,3,0,0 +BRDA:47,3,1,0 +BRDA:61,4,0,0 +BRDA:61,4,1,0 +BRDA:82,5,0,0 +BRDA:82,5,1,0 +BRDA:87,6,0,0 +BRDA:87,6,1,0 +BRDA:95,7,0,0 +BRDA:95,7,1,0 +BRDA:97,8,0,0 +BRDA:97,8,1,0 +BRDA:104,9,0,0 +BRDA:104,9,1,0 +BRDA:106,10,0,0 +BRDA:106,10,1,0 +BRDA:108,11,0,0 +BRDA:108,11,1,0 +BRDA:134,12,0,0 +BRDA:134,12,1,0 +BRF:26 +BRH:0 +end_of_record +TN: +SF:src/cli/validate.ts +FN:19,main +FN:45,(anonymous_1) +FN:77,(anonymous_2) +FN:85,(anonymous_3) +FN:86,(anonymous_4) +FN:103,(anonymous_5) +FNF:6 +FNH:0 +FNDA:0,main +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:30,0 +DA:32,0 +DA:34,0 +DA:36,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:44,0 +DA:45,0 +DA:49,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:103,0 +DA:104,0 +DA:105,0 +LF:49 +LH:0 +BRDA:24,0,0,0 +BRDA:24,0,1,0 +BRDA:27,1,0,0 +BRDA:27,1,1,0 +BRDA:32,2,0,0 +BRDA:32,2,1,0 +BRDA:47,3,0,0 +BRDA:47,3,1,0 +BRDA:53,4,0,0 +BRDA:53,4,1,0 +BRDA:55,5,0,0 +BRDA:55,5,1,0 +BRDA:58,6,0,0 +BRDA:58,6,1,0 +BRDA:58,7,0,0 +BRDA:58,7,1,0 +BRDA:67,8,0,0 +BRDA:67,8,1,0 +BRDA:73,9,0,0 +BRDA:73,9,1,0 +BRDA:78,10,0,0 +BRDA:78,10,1,0 +BRDA:90,11,0,0 +BRDA:90,11,1,0 +BRDA:90,12,0,0 +BRDA:90,12,1,0 +BRF:26 +BRH:0 +end_of_record +TN: +SF:src/engines/architecture-engine.ts +FN:61,(anonymous_0) +FN:73,(anonymous_1) +FN:83,(anonymous_2) +FN:93,(anonymous_3) +FN:169,(anonymous_4) +FN:170,(anonymous_5) +FN:187,(anonymous_6) +FN:201,(anonymous_7) +FN:223,(anonymous_8) +FN:289,(anonymous_9) +FN:353,(anonymous_10) +FN:370,(anonymous_11) +FN:380,(anonymous_12) +FN:389,(anonymous_13) +FN:420,(anonymous_14) +FN:482,(anonymous_15) +FN:492,(anonymous_16) +FN:558,(anonymous_17) +FN:594,(anonymous_18) +FN:661,(anonymous_19) +FN:664,(anonymous_20) +FN:674,(anonymous_21) +FN:686,(anonymous_22) +FNF:23 +FNH:19 +FNDA:9,(anonymous_0) +FNDA:39,(anonymous_1) +FNDA:5,(anonymous_2) +FNDA:4,(anonymous_3) +FNDA:8,(anonymous_4) +FNDA:8,(anonymous_5) +FNDA:15,(anonymous_6) +FNDA:36,(anonymous_7) +FNDA:16,(anonymous_8) +FNDA:10,(anonymous_9) +FNDA:8,(anonymous_10) +FNDA:5,(anonymous_11) +FNDA:5,(anonymous_12) +FNDA:5,(anonymous_13) +FNDA:15,(anonymous_14) +FNDA:6,(anonymous_15) +FNDA:6,(anonymous_16) +FNDA:6,(anonymous_17) +FNDA:0,(anonymous_18) +FNDA:0,(anonymous_19) +FNDA:0,(anonymous_20) +FNDA:1,(anonymous_21) +FNDA:0,(anonymous_22) +DA:73,39 +DA:74,9 +DA:75,9 +DA:76,9 +DA:77,9 +DA:84,5 +DA:85,5 +DA:89,5 +DA:90,1 +DA:93,4 +DA:108,5 +DA:109,8 +DA:111,8 +DA:112,0 +DA:120,0 +DA:124,8 +DA:126,8 +DA:128,5 +DA:129,0 +DA:133,5 +DA:134,5 +DA:136,5 +DA:137,5 +DA:140,5 +DA:141,3 +DA:152,5 +DA:153,3 +DA:166,5 +DA:167,5 +DA:169,8 +DA:170,8 +DA:172,5 +DA:188,15 +DA:189,36 +DA:190,36 +DA:191,15 +DA:195,0 +DA:206,36 +DA:213,36 +DA:214,36 +DA:224,16 +DA:225,16 +DA:226,16 +DA:227,16 +DA:229,16 +DA:238,16 +DA:240,16 +DA:241,10 +DA:243,0 +DA:245,0 +DA:246,0 +DA:248,0 +DA:250,0 +DA:252,0 +DA:253,0 +DA:255,0 +DA:257,0 +DA:259,0 +DA:260,0 +DA:262,0 +DA:264,0 +DA:265,0 +DA:267,0 +DA:268,0 +DA:269,0 +DA:271,0 +DA:272,0 +DA:275,0 +DA:276,0 +DA:280,16 +DA:282,0 +DA:296,10 +DA:300,10 +DA:301,10 +DA:302,0 +DA:304,0 +DA:307,0 +DA:311,10 +DA:312,10 +DA:313,0 +DA:317,10 +DA:319,10 +DA:320,0 +DA:321,10 +DA:322,0 +DA:323,10 +DA:324,0 +DA:327,10 +DA:336,10 +DA:337,20 +DA:338,20 +DA:339,10 +DA:344,0 +DA:345,0 +DA:346,10 +DA:347,0 +DA:355,8 +DA:356,3 +DA:360,5 +DA:361,0 +DA:364,5 +DA:371,5 +DA:372,0 +DA:374,5 +DA:381,5 +DA:382,5 +DA:383,5 +DA:384,5 +DA:385,5 +DA:388,5 +DA:389,5 +DA:403,5 +DA:404,8 +DA:405,8 +DA:407,8 +DA:408,5 +DA:409,5 +DA:410,5 +DA:411,5 +DA:416,8 +DA:420,5 +DA:422,15 +DA:423,15 +DA:424,2 +DA:425,2 +DA:428,13 +DA:430,13 +DA:431,13 +DA:432,13 +DA:434,13 +DA:435,15 +DA:436,7 +DA:439,13 +DA:440,13 +DA:441,13 +DA:445,5 +DA:446,8 +DA:447,8 +DA:452,5 +DA:453,5 +DA:454,2 +DA:455,2 +DA:456,2 +DA:457,2 +DA:458,2 +DA:469,5 +DA:492,6 +DA:495,6 +DA:496,6 +DA:497,33 +DA:498,33 +DA:499,3 +DA:500,3 +DA:501,0 +DA:502,0 +DA:505,33 +DA:506,33 +DA:510,6 +DA:511,0 +DA:515,6 +DA:525,6 +DA:527,6 +DA:528,6 +DA:529,6 +DA:530,33 +DA:531,33 +DA:532,33 +DA:533,124 +DA:535,5 +DA:536,5 +DA:539,33 +DA:540,11 +DA:541,11 +DA:545,6 +DA:547,6 +DA:551,6 +DA:560,6 +DA:561,6 +DA:564,6 +DA:566,0 +DA:567,0 +DA:568,0 +DA:569,6 +DA:570,2 +DA:571,2 +DA:572,2 +DA:573,4 +DA:574,4 +DA:575,4 +DA:576,0 +DA:577,4 +DA:578,3 +DA:580,1 +DA:584,0 +DA:585,0 +DA:588,6 +DA:598,0 +DA:600,0 +DA:603,0 +DA:604,0 +DA:619,0 +DA:621,0 +DA:626,0 +DA:638,0 +DA:639,0 +DA:640,0 +DA:658,0 +DA:661,0 +DA:662,0 +DA:663,0 +DA:664,0 +DA:666,0 +DA:675,1 +DA:676,1 +DA:677,1 +DA:687,0 +DA:689,0 +DA:691,0 +DA:693,0 +DA:695,0 +DA:697,0 +LF:221 +LH:152 +BRDA:75,0,0,9 +BRDA:75,0,1,7 +BRDA:76,1,0,9 +BRDA:76,1,1,9 +BRDA:77,2,0,9 +BRDA:77,2,1,9 +BRDA:89,3,0,1 +BRDA:89,3,1,4 +BRDA:89,4,0,5 +BRDA:89,4,1,1 +BRDA:111,5,0,0 +BRDA:111,5,1,8 +BRDA:128,6,0,0 +BRDA:128,6,1,5 +BRDA:128,7,0,5 +BRDA:128,7,1,5 +BRDA:128,7,2,0 +BRDA:134,8,0,0 +BRDA:134,8,1,5 +BRDA:137,9,0,0 +BRDA:137,9,1,5 +BRDA:140,10,0,3 +BRDA:140,10,1,2 +BRDA:152,11,0,3 +BRDA:152,11,1,2 +BRDA:152,12,0,5 +BRDA:152,12,1,5 +BRDA:190,13,0,15 +BRDA:190,13,1,21 +BRDA:229,14,0,16 +BRDA:229,14,1,0 +BRDA:230,15,0,16 +BRDA:230,15,1,0 +BRDA:230,15,2,0 +BRDA:230,15,3,0 +BRDA:230,15,4,0 +BRDA:230,15,5,0 +BRDA:243,16,0,0 +BRDA:243,16,1,0 +BRDA:255,17,0,0 +BRDA:255,17,1,0 +BRDA:262,18,0,0 +BRDA:262,18,1,0 +BRDA:296,19,0,10 +BRDA:296,19,1,0 +BRDA:302,20,0,0 +BRDA:302,20,1,0 +BRDA:312,21,0,0 +BRDA:312,21,1,10 +BRDA:319,22,0,0 +BRDA:319,22,1,10 +BRDA:321,23,0,0 +BRDA:321,23,1,10 +BRDA:323,24,0,0 +BRDA:323,24,1,10 +BRDA:338,25,0,10 +BRDA:338,25,1,10 +BRDA:345,26,0,0 +BRDA:345,26,1,0 +BRDA:346,27,0,0 +BRDA:346,27,1,10 +BRDA:347,28,0,0 +BRDA:347,28,1,0 +BRDA:355,29,0,3 +BRDA:355,29,1,5 +BRDA:360,30,0,0 +BRDA:360,30,1,5 +BRDA:371,31,0,0 +BRDA:371,31,1,5 +BRDA:408,32,0,5 +BRDA:408,32,1,0 +BRDA:408,33,0,5 +BRDA:408,33,1,0 +BRDA:410,34,0,5 +BRDA:410,34,1,0 +BRDA:423,35,0,2 +BRDA:423,35,1,13 +BRDA:428,36,0,0 +BRDA:428,36,1,13 +BRDA:434,37,0,13 +BRDA:434,37,1,0 +BRDA:446,38,0,8 +BRDA:446,38,1,0 +BRDA:454,39,0,0 +BRDA:454,39,1,2 +BRDA:456,40,0,2 +BRDA:456,40,1,0 +BRDA:462,41,0,2 +BRDA:462,41,1,0 +BRDA:500,42,0,0 +BRDA:500,42,1,3 +BRDA:505,43,0,33 +BRDA:505,43,1,0 +BRDA:510,44,0,0 +BRDA:510,44,1,6 +BRDA:525,45,0,6 +BRDA:525,45,1,0 +BRDA:533,46,0,5 +BRDA:533,46,1,119 +BRDA:539,47,0,11 +BRDA:539,47,1,22 +BRDA:547,48,0,6 +BRDA:547,48,1,0 +BRDA:564,49,0,0 +BRDA:564,49,1,6 +BRDA:566,50,0,0 +BRDA:566,50,1,0 +BRDA:568,51,0,0 +BRDA:568,51,1,0 +BRDA:569,52,0,2 +BRDA:569,52,1,4 +BRDA:570,53,0,0 +BRDA:570,53,1,2 +BRDA:572,54,0,0 +BRDA:572,54,1,2 +BRDA:573,55,0,4 +BRDA:573,55,1,0 +BRDA:575,56,0,0 +BRDA:575,56,1,4 +BRDA:577,57,0,3 +BRDA:577,57,1,1 +BRDA:585,58,0,0 +BRDA:585,58,1,0 +BRDA:621,59,0,0 +BRDA:621,59,1,0 +BRDA:639,60,0,0 +BRDA:639,60,1,0 +BRDA:662,61,0,0 +BRDA:662,61,1,0 +BRDA:676,62,0,1 +BRDA:676,62,1,0 +BRDA:687,63,0,0 +BRDA:687,63,1,0 +BRDA:687,63,2,0 +BRDA:687,63,3,0 +BRDA:687,63,4,0 +BRF:136 +BRH:68 +end_of_record +TN: +SF:src/engines/community-detector.ts +FN:27,(anonymous_0) +FN:29,(anonymous_1) +FN:44,(anonymous_2) +FN:50,(anonymous_3) +FN:70,(anonymous_4) +FN:129,(anonymous_5) +FN:162,(anonymous_6) +FN:204,(anonymous_7) +FN:206,(anonymous_8) +FN:209,(anonymous_9) +FN:212,(anonymous_10) +FN:226,(anonymous_11) +FN:235,(anonymous_12) +FN:238,(anonymous_13) +FN:239,(anonymous_14) +FN:243,(anonymous_15) +FN:249,(anonymous_16) +FN:250,(anonymous_17) +FNF:18 +FNH:17 +FNDA:141,(anonymous_0) +FNDA:16,(anonymous_1) +FNDA:29,(anonymous_2) +FNDA:29,(anonymous_3) +FNDA:14,(anonymous_4) +FNDA:8,(anonymous_5) +FNDA:14,(anonymous_6) +FNDA:20,(anonymous_7) +FNDA:28,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:44,(anonymous_10) +FNDA:58,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:20,(anonymous_13) +FNDA:28,(anonymous_14) +FNDA:20,(anonymous_15) +FNDA:1,(anonymous_16) +FNDA:21,(anonymous_17) +DA:27,141 +DA:31,16 +DA:43,16 +DA:44,29 +DA:50,29 +DA:52,16 +DA:53,2 +DA:57,14 +DA:58,14 +DA:59,6 +DA:63,8 +DA:74,14 +DA:77,14 +DA:86,14 +DA:87,8 +DA:91,6 +DA:92,6 +DA:93,12 +DA:94,12 +DA:95,12 +DA:96,12 +DA:100,6 +DA:103,6 +DA:104,6 +DA:105,13 +DA:106,13 +DA:107,12 +DA:108,12 +DA:111,6 +DA:112,6 +DA:115,6 +DA:122,0 +DA:133,8 +DA:134,8 +DA:135,16 +DA:136,16 +DA:137,16 +DA:141,8 +DA:142,8 +DA:143,8 +DA:144,12 +DA:145,12 +DA:148,8 +DA:149,8 +DA:152,8 +DA:167,14 +DA:168,20 +DA:169,20 +DA:170,20 +DA:171,20 +DA:173,20 +DA:192,20 +DA:193,28 +DA:206,28 +DA:207,20 +DA:208,28 +DA:209,20 +DA:213,44 +DA:217,44 +DA:226,58 +DA:227,44 +DA:228,40 +DA:230,40 +DA:233,4 +DA:234,4 +DA:235,4 +DA:239,28 +DA:240,20 +DA:244,20 +DA:245,20 +DA:246,28 +DA:248,20 +DA:249,1 +DA:250,21 +DA:253,20 +LF:75 +LH:74 +BRDA:43,0,0,16 +BRDA:43,0,1,0 +BRDA:45,1,0,29 +BRDA:45,1,1,0 +BRDA:46,2,0,29 +BRDA:46,2,1,2 +BRDA:47,3,0,29 +BRDA:47,3,1,0 +BRDA:47,3,2,0 +BRDA:48,4,0,29 +BRDA:48,4,1,0 +BRDA:52,5,0,2 +BRDA:52,5,1,14 +BRDA:58,6,0,6 +BRDA:58,6,1,8 +BRDA:86,7,0,8 +BRDA:86,7,1,6 +BRDA:86,8,0,14 +BRDA:86,8,1,13 +BRDA:86,8,2,13 +BRDA:93,9,0,12 +BRDA:93,9,1,0 +BRDA:94,10,0,12 +BRDA:94,10,1,0 +BRDA:95,11,0,12 +BRDA:95,11,1,0 +BRDA:95,12,0,12 +BRDA:95,12,1,12 +BRDA:100,13,0,0 +BRDA:100,13,1,6 +BRDA:106,14,0,1 +BRDA:106,14,1,12 +BRDA:107,15,0,8 +BRDA:107,15,1,4 +BRDA:136,16,0,12 +BRDA:136,16,1,4 +BRDA:208,17,0,28 +BRDA:208,17,1,21 +BRDA:209,18,0,20 +BRDA:209,18,1,0 +BRDA:227,19,0,40 +BRDA:227,19,1,4 +BRDA:227,20,0,44 +BRDA:227,20,1,40 +BRDA:230,21,0,4 +BRDA:230,21,1,36 +BRDA:235,22,0,4 +BRDA:235,22,1,4 +BRDA:240,23,0,20 +BRDA:240,23,1,19 +BRDA:240,23,2,0 +BRDA:246,24,0,28 +BRDA:246,24,1,21 +BRF:53 +BRH:42 +end_of_record +TN: +SF:src/engines/coordination-engine.ts +FN:33,(anonymous_0) +FN:37,(anonymous_1) +FN:95,(anonymous_2) +FN:117,(anonymous_3) +FN:130,(anonymous_4) +FN:131,(anonymous_5) +FN:136,(anonymous_6) +FN:143,(anonymous_7) +FN:147,(anonymous_8) +FN:159,(anonymous_9) +FN:160,(anonymous_10) +FN:162,(anonymous_11) +FN:163,(anonymous_12) +FN:164,(anonymous_13) +FN:179,(anonymous_14) +FN:188,(anonymous_15) +FN:197,(anonymous_16) +FN:211,(anonymous_17) +FN:224,(anonymous_18) +FNF:19 +FNH:19 +FNDA:145,(anonymous_0) +FNDA:3,(anonymous_1) +FNDA:4,(anonymous_2) +FNDA:3,(anonymous_3) +FNDA:2,(anonymous_4) +FNDA:2,(anonymous_5) +FNDA:1,(anonymous_6) +FNDA:2,(anonymous_7) +FNDA:8,(anonymous_8) +FNDA:2,(anonymous_9) +FNDA:2,(anonymous_10) +FNDA:2,(anonymous_11) +FNDA:2,(anonymous_12) +FNDA:1,(anonymous_13) +FNDA:2,(anonymous_14) +FNDA:2,(anonymous_15) +FNDA:1,(anonymous_16) +FNDA:2,(anonymous_17) +FNDA:2,(anonymous_18) +DA:33,145 +DA:38,3 +DA:44,3 +DA:45,3 +DA:46,1 +DA:58,2 +DA:59,2 +DA:60,2 +DA:62,2 +DA:75,2 +DA:76,0 +DA:83,2 +DA:97,4 +DA:99,4 +DA:100,1 +DA:103,3 +DA:104,3 +DA:105,1 +DA:108,2 +DA:114,2 +DA:118,3 +DA:129,3 +DA:130,2 +DA:131,2 +DA:133,3 +DA:136,1 +DA:143,2 +DA:149,8 +DA:157,8 +DA:159,2 +DA:160,2 +DA:162,2 +DA:163,2 +DA:164,1 +DA:179,2 +DA:189,2 +DA:190,2 +DA:194,2 +DA:198,1 +DA:212,2 +DA:213,2 +DA:214,2 +DA:219,2 +DA:228,2 +DA:233,2 +DA:234,2 +DA:237,0 +DA:239,2 +DA:241,2 +LF:49 +LH:47 +BRDA:45,0,0,1 +BRDA:45,0,1,2 +BRDA:50,1,0,1 +BRDA:50,1,1,0 +BRDA:51,2,0,1 +BRDA:51,2,1,0 +BRDA:52,3,0,1 +BRDA:52,3,1,0 +BRDA:66,4,0,2 +BRDA:66,4,1,1 +BRDA:75,5,0,0 +BRDA:75,5,1,2 +BRDA:99,6,0,1 +BRDA:99,6,1,3 +BRDA:104,7,0,1 +BRDA:104,7,1,2 +BRDA:111,8,0,2 +BRDA:111,8,1,0 +BRDA:138,9,0,1 +BRDA:138,9,1,0 +BRDA:139,10,0,1 +BRDA:139,10,1,0 +BRDA:140,11,0,1 +BRDA:140,11,1,0 +BRDA:141,12,0,1 +BRDA:141,12,1,0 +BRDA:165,13,0,1 +BRDA:165,13,1,0 +BRDA:167,14,0,1 +BRDA:167,14,1,0 +BRDA:168,15,0,1 +BRDA:168,15,1,0 +BRDA:169,16,0,1 +BRDA:169,16,1,0 +BRDA:170,17,0,1 +BRDA:170,17,1,0 +BRDA:173,18,0,1 +BRDA:173,18,1,0 +BRDA:174,19,0,1 +BRDA:174,19,1,0 +BRDA:175,20,0,1 +BRDA:175,20,1,0 +BRDA:176,21,0,1 +BRDA:176,21,1,0 +BRDA:180,22,0,2 +BRDA:180,22,1,0 +BRDA:181,23,0,2 +BRDA:181,23,1,0 +BRDA:182,24,0,2 +BRDA:182,24,1,0 +BRDA:184,25,0,8 +BRDA:184,25,1,6 +BRDA:194,26,0,2 +BRDA:194,26,1,1 +BRDA:219,27,0,2 +BRDA:219,27,1,1 +BRDA:233,28,0,2 +BRDA:233,28,1,0 +BRDA:237,29,0,0 +BRDA:237,29,1,0 +BRDA:239,30,0,2 +BRDA:239,30,1,0 +BRDA:239,30,2,0 +BRDA:239,30,3,0 +BRDA:239,31,0,0 +BRDA:239,31,1,0 +BRF:66 +BRH:37 +end_of_record +TN: +SF:src/engines/coordination-queries.ts +FNF:0 +FNH:0 +DA:7,4 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/engines/coordination-types.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/engines/coordination-utils.ts +FN:13,rowToClaim +FN:45,makeClaimId +FNF:2 +FNH:2 +FNDA:11,rowToClaim +FNDA:6,makeClaimId +DA:14,11 +DA:16,11 +DA:17,2 +DA:20,9 +DA:46,6 +LF:5 +LH:5 +BRDA:14,0,0,11 +BRDA:14,0,1,7 +BRDA:14,0,2,7 +BRDA:16,1,0,2 +BRDA:16,1,1,9 +BRDA:16,2,0,11 +BRDA:16,2,1,11 +BRDA:16,2,2,11 +BRDA:22,3,0,9 +BRDA:22,3,1,1 +BRDA:23,4,0,11 +BRDA:23,4,1,1 +BRDA:24,5,0,5 +BRDA:24,5,1,4 +BRDA:25,6,0,11 +BRDA:25,6,1,1 +BRDA:26,7,0,11 +BRDA:26,7,1,1 +BRDA:27,8,0,11 +BRDA:27,8,1,1 +BRDA:28,9,0,11 +BRDA:28,9,1,1 +BRDA:29,10,0,4 +BRDA:29,10,1,5 +BRDA:30,11,0,8 +BRDA:30,11,1,1 +BRDA:31,12,0,0 +BRDA:31,12,1,9 +BRDA:34,13,0,0 +BRDA:34,13,1,9 +BRDA:35,14,0,11 +BRDA:35,14,1,0 +BRDA:45,15,0,6 +BRF:33 +BRH:30 +end_of_record +TN: +SF:src/engines/docs-engine.ts +FN:72,(anonymous_0) +FN:78,(anonymous_1) +FN:91,(anonymous_2) +FN:129,(anonymous_3) +FN:172,(anonymous_4) +FN:181,(anonymous_5) +FN:197,(anonymous_6) +FN:221,(anonymous_7) +FN:226,(anonymous_8) +FN:246,(anonymous_9) +FN:271,(anonymous_10) +FN:277,(anonymous_11) +FN:284,(anonymous_12) +FN:287,(anonymous_13) +FN:309,(anonymous_14) +FN:312,(anonymous_15) +FN:326,(anonymous_16) +FN:329,(anonymous_17) +FN:330,(anonymous_18) +FN:351,(anonymous_19) +FN:365,(anonymous_20) +FN:377,(anonymous_21) +FN:378,(anonymous_22) +FNF:23 +FNH:23 +FNDA:144,(anonymous_0) +FNDA:21,(anonymous_1) +FNDA:9,(anonymous_2) +FNDA:24,(anonymous_3) +FNDA:5,(anonymous_4) +FNDA:8,(anonymous_5) +FNDA:3,(anonymous_6) +FNDA:1,(anonymous_7) +FNDA:8,(anonymous_8) +FNDA:4,(anonymous_9) +FNDA:2,(anonymous_10) +FNDA:2,(anonymous_11) +FNDA:3,(anonymous_12) +FNDA:3,(anonymous_13) +FNDA:21,(anonymous_14) +FNDA:24,(anonymous_15) +FNDA:3,(anonymous_16) +FNDA:24,(anonymous_17) +FNDA:24,(anonymous_18) +FNDA:24,(anonymous_19) +FNDA:24,(anonymous_20) +FNDA:9216,(anonymous_21) +FNDA:9216,(anonymous_22) +DA:57,5 +DA:58,5 +DA:73,144 +DA:74,144 +DA:75,144 +DA:76,144 +DA:79,21 +DA:80,21 +DA:96,9 +DA:97,9 +DA:100,9 +DA:101,9 +DA:103,9 +DA:104,9 +DA:112,9 +DA:116,9 +DA:117,27 +DA:118,27 +DA:121,27 +DA:122,3 +DA:123,3 +DA:127,24 +DA:128,24 +DA:129,24 +DA:130,24 +DA:131,3 +DA:135,3 +DA:139,21 +DA:140,3 +DA:141,3 +DA:142,3 +DA:144,0 +DA:152,21 +DA:154,0 +DA:161,9 +DA:162,9 +DA:177,5 +DA:178,5 +DA:181,8 +DA:183,5 +DA:186,4 +DA:187,4 +DA:190,2 +DA:202,3 +DA:203,3 +DA:220,3 +DA:221,1 +DA:227,8 +DA:232,8 +DA:233,8 +DA:234,8 +DA:238,3 +DA:239,3 +DA:243,8 +DA:251,4 +DA:252,4 +DA:253,4 +DA:270,4 +DA:271,2 +DA:273,0 +DA:283,2 +DA:284,3 +DA:286,2 +DA:287,2 +DA:288,3 +DA:291,2 +DA:308,2 +DA:309,21 +DA:313,24 +DA:327,3 +DA:328,3 +DA:329,24 +DA:330,24 +DA:344,3 +DA:352,24 +DA:353,24 +DA:354,441 +DA:355,441 +DA:357,24 +DA:366,24 +DA:367,24 +DA:368,24 +DA:369,379 +DA:370,379 +DA:371,2235 +DA:373,379 +DA:374,379 +DA:377,9216 +DA:378,9216 +LF:89 +LH:86 +BRDA:72,0,0,144 +BRDA:75,1,0,144 +BRDA:75,1,1,143 +BRDA:77,2,0,144 +BRDA:77,2,1,21 +BRDA:94,3,0,9 +BRDA:97,4,0,9 +BRDA:97,4,1,7 +BRDA:100,5,0,9 +BRDA:100,5,1,7 +BRDA:101,6,0,9 +BRDA:101,6,1,9 +BRDA:112,7,0,8 +BRDA:112,7,1,1 +BRDA:121,8,0,3 +BRDA:121,8,1,24 +BRDA:121,9,0,27 +BRDA:121,9,1,24 +BRDA:130,10,0,3 +BRDA:130,10,1,21 +BRDA:139,11,0,3 +BRDA:139,11,1,18 +BRDA:139,12,0,21 +BRDA:139,12,1,6 +BRDA:156,13,0,0 +BRDA:156,13,1,0 +BRDA:175,14,0,5 +BRDA:177,15,0,5 +BRDA:177,15,1,4 +BRDA:183,16,0,1 +BRDA:183,16,1,4 +BRDA:187,17,0,2 +BRDA:187,17,1,2 +BRDA:200,18,0,3 +BRDA:202,19,0,3 +BRDA:202,19,1,3 +BRDA:220,20,0,2 +BRDA:220,20,1,1 +BRDA:220,21,0,3 +BRDA:220,21,1,3 +BRDA:233,22,0,8 +BRDA:233,22,1,0 +BRDA:238,23,0,3 +BRDA:238,23,1,0 +BRDA:238,24,0,3 +BRDA:238,24,1,3 +BRDA:251,25,0,0 +BRDA:251,25,1,4 +BRDA:270,26,0,2 +BRDA:270,26,1,2 +BRDA:270,27,0,4 +BRDA:270,27,1,2 +BRDA:308,28,0,0 +BRDA:308,28,1,2 +BRDA:308,29,0,2 +BRDA:308,29,1,2 +BRDA:314,30,0,24 +BRDA:314,30,1,0 +BRDA:315,31,0,24 +BRDA:315,31,1,0 +BRDA:316,32,0,24 +BRDA:316,32,1,0 +BRDA:317,33,0,24 +BRDA:317,33,1,0 +BRDA:318,34,0,24 +BRDA:318,34,1,0 +BRDA:319,35,0,24 +BRDA:319,35,1,0 +BRDA:320,36,0,24 +BRDA:320,36,1,0 +BRDA:327,37,0,0 +BRDA:327,37,1,3 +BRDA:367,38,0,24 +BRDA:367,38,1,0 +BRDA:377,39,0,24 +BRDA:377,39,1,0 +BRF:76 +BRH:60 +end_of_record +TN: +SF:src/engines/episode-engine.ts +FN:56,(anonymous_0) +FN:58,(anonymous_1) +FN:111,(anonymous_2) +FN:145,(anonymous_3) +FN:146,(anonymous_4) +FN:152,(anonymous_5) +FN:168,(anonymous_6) +FN:172,(anonymous_7) +FN:176,(anonymous_8) +FN:198,(anonymous_9) +FN:200,(anonymous_10) +FN:205,(anonymous_11) +FN:216,(anonymous_12) +FN:269,(anonymous_13) +FN:300,(anonymous_14) +FN:317,(anonymous_15) +FN:327,(anonymous_16) +FN:339,(anonymous_17) +FN:344,(anonymous_18) +FN:348,(anonymous_19) +FN:366,(anonymous_20) +FNF:21 +FNH:21 +FNDA:157,(anonymous_0) +FNDA:15,(anonymous_1) +FNDA:28,(anonymous_2) +FNDA:28,(anonymous_3) +FNDA:28,(anonymous_4) +FNDA:26,(anonymous_5) +FNDA:11,(anonymous_6) +FNDA:2,(anonymous_7) +FNDA:6,(anonymous_8) +FNDA:4,(anonymous_9) +FNDA:7,(anonymous_10) +FNDA:6,(anonymous_11) +FNDA:7,(anonymous_12) +FNDA:15,(anonymous_13) +FNDA:28,(anonymous_14) +FNDA:23,(anonymous_15) +FNDA:26,(anonymous_16) +FNDA:54,(anonymous_17) +FNDA:143,(anonymous_18) +FNDA:28,(anonymous_19) +FNDA:21,(anonymous_20) +DA:56,157 +DA:59,15 +DA:60,15 +DA:61,15 +DA:63,15 +DA:94,15 +DA:95,110 +DA:107,15 +DA:108,15 +DA:112,28 +DA:113,28 +DA:118,28 +DA:119,2 +DA:120,2 +DA:122,28 +DA:123,1 +DA:124,1 +DA:126,28 +DA:127,3 +DA:128,3 +DA:130,28 +DA:131,1 +DA:132,1 +DA:135,28 +DA:144,28 +DA:145,28 +DA:146,28 +DA:148,28 +DA:149,28 +DA:150,28 +DA:152,28 +DA:153,26 +DA:154,26 +DA:156,26 +DA:157,26 +DA:159,26 +DA:160,26 +DA:162,26 +DA:164,26 +DA:167,28 +DA:168,11 +DA:173,2 +DA:182,6 +DA:190,6 +DA:191,6 +DA:192,11 +DA:193,11 +DA:197,6 +DA:198,4 +DA:200,7 +DA:202,6 +DA:205,6 +DA:209,6 +DA:216,7 +DA:223,6 +DA:224,6 +DA:225,6 +DA:226,6 +DA:228,6 +DA:247,6 +DA:258,6 +DA:261,6 +DA:275,15 +DA:287,15 +DA:288,15 +DA:289,14 +DA:292,1 +DA:301,28 +DA:302,26 +DA:304,28 +DA:305,28 +DA:306,0 +DA:309,26 +DA:317,23 +DA:328,26 +DA:329,2 +DA:332,24 +DA:333,24 +DA:335,1 +DA:340,54 +DA:344,143 +DA:349,28 +DA:350,0 +DA:352,28 +DA:353,4 +DA:356,24 +DA:357,24 +DA:358,44 +DA:359,17 +DA:362,24 +DA:363,24 +DA:367,21 +LF:92 +LH:90 +BRDA:61,0,0,15 +BRDA:61,0,1,4 +BRDA:82,1,0,15 +BRDA:82,1,1,15 +BRDA:86,2,0,15 +BRDA:86,2,1,6 +BRDA:87,3,0,15 +BRDA:87,3,1,7 +BRDA:115,4,0,28 +BRDA:115,4,1,18 +BRDA:118,5,0,2 +BRDA:118,5,1,26 +BRDA:122,6,0,1 +BRDA:122,6,1,27 +BRDA:126,7,0,3 +BRDA:126,7,1,25 +BRDA:130,8,0,1 +BRDA:130,8,1,27 +BRDA:149,9,0,28 +BRDA:149,9,1,26 +BRDA:159,10,0,26 +BRDA:159,10,1,0 +BRDA:160,11,0,2 +BRDA:160,11,1,24 +BRDA:168,12,0,11 +BRDA:168,12,1,0 +BRDA:168,13,0,11 +BRDA:168,13,1,0 +BRDA:183,14,0,6 +BRDA:183,14,1,6 +BRDA:183,14,2,5 +BRDA:187,15,0,6 +BRDA:187,15,1,5 +BRDA:192,16,0,11 +BRDA:192,16,1,0 +BRDA:193,17,0,11 +BRDA:193,17,1,7 +BRDA:202,18,0,3 +BRDA:202,18,1,3 +BRDA:211,19,0,6 +BRDA:211,19,1,5 +BRDA:288,20,0,14 +BRDA:288,20,1,1 +BRDA:301,21,0,2 +BRDA:301,21,1,26 +BRDA:301,22,0,28 +BRDA:301,22,1,26 +BRDA:302,23,0,26 +BRDA:302,23,1,2 +BRDA:302,23,2,2 +BRDA:304,24,0,24 +BRDA:304,24,1,2 +BRDA:304,25,0,28 +BRDA:304,25,1,26 +BRDA:304,25,2,26 +BRDA:305,26,0,0 +BRDA:305,26,1,28 +BRDA:305,27,0,28 +BRDA:305,27,1,26 +BRDA:311,28,0,26 +BRDA:311,28,1,0 +BRDA:312,29,0,28 +BRDA:312,29,1,1 +BRDA:313,30,0,24 +BRDA:313,30,1,2 +BRDA:314,31,0,28 +BRDA:314,31,1,0 +BRDA:315,32,0,28 +BRDA:315,32,1,0 +BRDA:316,33,0,25 +BRDA:316,33,1,1 +BRDA:319,34,0,28 +BRDA:319,34,1,1 +BRDA:322,35,0,28 +BRDA:322,35,1,0 +BRDA:328,36,0,2 +BRDA:328,36,1,24 +BRDA:328,37,0,26 +BRDA:328,37,1,24 +BRDA:349,38,0,0 +BRDA:349,38,1,28 +BRDA:349,39,0,28 +BRDA:349,39,1,3 +BRDA:352,40,0,4 +BRDA:352,40,1,24 +BRDA:352,41,0,28 +BRDA:352,41,1,25 +BRDA:358,42,0,17 +BRDA:358,42,1,27 +BRDA:363,43,0,24 +BRDA:363,43,1,0 +BRF:91 +BRH:80 +end_of_record +TN: +SF:src/engines/migration-engine.ts +FN:23,(anonymous_0) +FN:57,(anonymous_1) +FN:108,(anonymous_2) +FN:159,(anonymous_3) +FN:160,(anonymous_4) +FN:161,(anonymous_5) +FN:162,(anonymous_6) +FN:175,(anonymous_7) +FN:181,(anonymous_8) +FN:182,(anonymous_9) +FN:182,(anonymous_10) +FN:198,(anonymous_11) +FN:213,(anonymous_12) +FNF:13 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +DA:24,0 +DA:27,0 +DA:49,0 +DA:51,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:73,0 +DA:76,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:86,0 +DA:94,0 +DA:95,0 +DA:119,0 +DA:122,0 +DA:123,0 +DA:125,0 +DA:126,0 +DA:128,0 +DA:132,0 +DA:134,0 +DA:138,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:153,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:164,0 +DA:175,0 +DA:181,0 +DA:182,0 +DA:199,0 +DA:214,0 +LF:43 +LH:0 +BRDA:63,0,0,0 +BRDA:63,0,1,0 +BRDA:79,1,0,0 +BRDA:79,1,1,0 +BRDA:81,2,0,0 +BRDA:81,2,1,0 +BRDA:126,3,0,0 +BRDA:126,3,1,0 +BRDA:132,4,0,0 +BRDA:132,4,1,0 +BRDA:138,5,0,0 +BRDA:138,5,1,0 +BRDA:138,6,0,0 +BRDA:138,6,1,0 +BRDA:142,7,0,0 +BRDA:142,7,1,0 +BRDA:179,8,0,0 +BRDA:179,8,1,0 +BRF:18 +BRH:0 +end_of_record +TN: +SF:src/engines/progress-engine.ts +FN:68,(anonymous_0) +FN:79,(anonymous_1) +FN:127,(anonymous_2) +FN:152,(anonymous_3) +FN:153,(anonymous_4) +FN:154,(anonymous_5) +FN:168,(anonymous_6) +FN:186,(anonymous_7) +FN:191,(anonymous_8) +FN:197,(anonymous_9) +FN:211,(anonymous_10) +FN:216,(anonymous_11) +FN:226,(anonymous_12) +FN:227,(anonymous_13) +FN:228,(anonymous_14) +FN:234,(anonymous_15) +FN:235,(anonymous_16) +FN:236,(anonymous_17) +FN:243,(anonymous_18) +FN:246,(anonymous_19) +FN:269,(anonymous_20) +FN:270,(anonymous_21) +FN:273,(anonymous_22) +FN:277,(anonymous_23) +FN:290,(anonymous_24) +FN:336,(anonymous_25) +FN:382,(anonymous_26) +FN:417,(anonymous_27) +FN:453,(anonymous_28) +FN:484,(anonymous_29) +FN:492,(anonymous_30) +FN:495,(anonymous_31) +FN:497,(anonymous_32) +FNF:33 +FNH:24 +FNDA:131,(anonymous_0) +FNDA:151,(anonymous_1) +FNDA:2,(anonymous_2) +FNDA:3,(anonymous_3) +FNDA:3,(anonymous_4) +FNDA:3,(anonymous_5) +FNDA:2,(anonymous_6) +FNDA:1,(anonymous_7) +FNDA:2,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:1,(anonymous_10) +FNDA:2,(anonymous_11) +FNDA:1,(anonymous_12) +FNDA:1,(anonymous_13) +FNDA:1,(anonymous_14) +FNDA:1,(anonymous_15) +FNDA:1,(anonymous_16) +FNDA:1,(anonymous_17) +FNDA:2,(anonymous_18) +FNDA:2,(anonymous_19) +FNDA:1,(anonymous_20) +FNDA:0,(anonymous_21) +FNDA:0,(anonymous_22) +FNDA:0,(anonymous_23) +FNDA:1,(anonymous_24) +FNDA:0,(anonymous_25) +FNDA:1,(anonymous_26) +FNDA:0,(anonymous_27) +FNDA:20,(anonymous_28) +FNDA:0,(anonymous_29) +FNDA:0,(anonymous_30) +FNDA:0,(anonymous_31) +FNDA:0,(anonymous_32) +DA:69,131 +DA:70,131 +DA:71,131 +DA:72,131 +DA:73,131 +DA:81,151 +DA:82,151 +DA:83,8 +DA:97,151 +DA:98,151 +DA:99,14 +DA:114,151 +DA:115,14 +DA:116,14 +DA:117,14 +DA:118,0 +DA:135,2 +DA:137,2 +DA:138,1 +DA:139,1 +DA:140,1 +DA:142,1 +DA:143,1 +DA:144,2 +DA:145,2 +DA:146,2 +DA:147,2 +DA:152,3 +DA:153,3 +DA:154,3 +DA:156,2 +DA:169,2 +DA:170,2 +DA:172,2 +DA:174,2 +DA:175,1 +DA:176,1 +DA:177,1 +DA:180,2 +DA:187,1 +DA:188,1 +DA:191,2 +DA:194,1 +DA:195,1 +DA:197,1 +DA:198,1 +DA:199,1 +DA:200,1 +DA:201,1 +DA:206,1 +DA:207,1 +DA:209,1 +DA:210,1 +DA:211,1 +DA:212,1 +DA:214,1 +DA:216,2 +DA:217,1 +DA:218,2 +DA:219,2 +DA:220,2 +DA:221,2 +DA:226,1 +DA:227,1 +DA:228,1 +DA:229,1 +DA:230,1 +DA:234,1 +DA:235,1 +DA:236,1 +DA:237,1 +DA:238,1 +DA:243,2 +DA:246,2 +DA:247,1 +DA:249,1 +DA:270,1 +DA:272,1 +DA:273,0 +DA:276,1 +DA:277,0 +DA:278,0 +DA:279,0 +DA:283,1 +DA:291,1 +DA:292,1 +DA:297,0 +DA:299,0 +DA:300,0 +DA:316,0 +DA:317,0 +DA:321,0 +DA:322,0 +DA:323,0 +DA:325,0 +DA:337,0 +DA:338,0 +DA:343,0 +DA:344,0 +DA:363,0 +DA:364,0 +DA:368,0 +DA:369,0 +DA:370,0 +DA:372,0 +DA:383,1 +DA:384,0 +DA:387,1 +DA:388,1 +DA:406,1 +DA:407,1 +DA:409,0 +DA:410,0 +DA:418,0 +DA:419,0 +DA:422,0 +DA:423,0 +DA:441,0 +DA:442,0 +DA:444,0 +DA:445,0 +DA:454,20 +DA:456,20 +DA:457,20 +DA:458,20 +DA:459,20 +DA:462,20 +DA:463,20 +DA:464,2 +DA:465,1 +DA:469,20 +DA:470,3 +DA:471,1 +DA:476,20 +DA:477,20 +DA:478,20 +DA:485,0 +DA:492,0 +DA:495,0 +DA:497,0 +LF:140 +LH:101 +BRDA:86,0,0,8 +BRDA:86,0,1,0 +BRDA:103,1,0,14 +BRDA:103,1,1,0 +BRDA:109,2,0,14 +BRDA:109,2,1,8 +BRDA:115,3,0,14 +BRDA:115,3,1,0 +BRDA:117,4,0,0 +BRDA:117,4,1,14 +BRDA:117,5,0,14 +BRDA:117,5,1,14 +BRDA:137,6,0,1 +BRDA:137,6,1,1 +BRDA:139,7,0,0 +BRDA:139,7,1,1 +BRDA:139,8,0,1 +BRDA:139,8,1,0 +BRDA:142,9,0,1 +BRDA:142,9,1,0 +BRDA:144,10,0,0 +BRDA:144,10,1,2 +BRDA:144,11,0,2 +BRDA:144,11,1,0 +BRDA:145,12,0,0 +BRDA:145,12,1,2 +BRDA:145,13,0,2 +BRDA:145,13,1,0 +BRDA:146,14,0,0 +BRDA:146,14,1,2 +BRDA:146,15,0,2 +BRDA:146,15,1,0 +BRDA:170,16,0,0 +BRDA:170,16,1,2 +BRDA:174,17,0,1 +BRDA:174,17,1,1 +BRDA:176,18,0,1 +BRDA:176,18,1,0 +BRDA:176,19,0,1 +BRDA:176,19,1,1 +BRDA:188,20,0,0 +BRDA:188,20,1,1 +BRDA:200,21,0,1 +BRDA:200,21,1,0 +BRDA:200,22,0,1 +BRDA:200,22,1,1 +BRDA:212,23,0,0 +BRDA:212,23,1,1 +BRDA:219,24,0,0 +BRDA:219,24,1,2 +BRDA:220,25,0,1 +BRDA:220,25,1,1 +BRDA:221,26,0,1 +BRDA:221,26,1,1 +BRDA:230,27,0,1 +BRDA:230,27,1,1 +BRDA:230,28,0,1 +BRDA:230,28,1,0 +BRDA:238,29,0,1 +BRDA:238,29,1,1 +BRDA:238,30,0,1 +BRDA:238,30,1,0 +BRDA:247,31,0,1 +BRDA:247,31,1,0 +BRDA:272,32,0,0 +BRDA:272,32,1,1 +BRDA:273,33,0,0 +BRDA:273,33,1,0 +BRDA:276,34,0,0 +BRDA:276,34,1,1 +BRDA:278,35,0,0 +BRDA:278,35,1,0 +BRDA:279,36,0,0 +BRDA:279,36,1,0 +BRDA:291,37,0,1 +BRDA:291,37,1,0 +BRDA:291,38,0,1 +BRDA:291,38,1,1 +BRDA:309,39,0,0 +BRDA:309,39,1,0 +BRDA:316,40,0,0 +BRDA:316,40,1,0 +BRDA:326,41,0,0 +BRDA:326,41,1,0 +BRDA:337,42,0,0 +BRDA:337,42,1,0 +BRDA:337,43,0,0 +BRDA:337,43,1,0 +BRDA:354,44,0,0 +BRDA:354,44,1,0 +BRDA:356,45,0,0 +BRDA:356,45,1,0 +BRDA:357,46,0,0 +BRDA:357,46,1,0 +BRDA:358,47,0,0 +BRDA:358,47,1,0 +BRDA:363,48,0,0 +BRDA:363,48,1,0 +BRDA:373,49,0,0 +BRDA:373,49,1,0 +BRDA:383,50,0,0 +BRDA:383,50,1,1 +BRDA:383,51,0,1 +BRDA:383,51,1,1 +BRDA:393,52,0,0 +BRDA:393,52,1,1 +BRDA:394,53,0,0 +BRDA:394,53,1,1 +BRDA:395,54,0,0 +BRDA:395,54,1,1 +BRDA:418,55,0,0 +BRDA:418,55,1,0 +BRDA:418,56,0,0 +BRDA:418,56,1,0 +BRDA:428,57,0,0 +BRDA:428,57,1,0 +BRDA:429,58,0,0 +BRDA:429,58,1,0 +BRDA:430,59,0,0 +BRDA:430,59,1,0 +BRDA:462,60,0,20 +BRDA:462,60,1,0 +BRDA:464,61,0,1 +BRDA:464,61,1,1 +BRDA:470,62,0,1 +BRDA:470,62,1,2 +BRF:126 +BRH:58 +end_of_record +TN: +SF:src/engines/test-engine.ts +FN:43,(anonymous_0) +FN:53,(anonymous_1) +FN:64,(anonymous_2) +FN:70,(anonymous_3) +FN:84,(anonymous_4) +FN:96,(anonymous_5) +FN:97,(anonymous_6) +FN:98,(anonymous_7) +FN:104,(anonymous_8) +FN:129,(anonymous_9) +FN:162,(anonymous_10) +FN:171,(anonymous_11) +FN:203,(anonymous_12) +FN:214,(anonymous_13) +FN:235,(anonymous_14) +FN:260,(anonymous_15) +FN:295,(anonymous_16) +FN:322,(anonymous_17) +FN:332,(anonymous_18) +FN:359,(anonymous_19) +FN:367,(anonymous_20) +FN:382,(anonymous_21) +FNF:22 +FNH:19 +FNDA:151,(anonymous_0) +FNDA:172,(anonymous_1) +FNDA:48,(anonymous_2) +FNDA:24,(anonymous_3) +FNDA:12,(anonymous_4) +FNDA:72,(anonymous_5) +FNDA:24,(anonymous_6) +FNDA:24,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:35,(anonymous_9) +FNDA:12,(anonymous_10) +FNDA:15,(anonymous_11) +FNDA:1,(anonymous_12) +FNDA:12,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:3,(anonymous_16) +FNDA:3,(anonymous_17) +FNDA:12,(anonymous_18) +FNDA:15,(anonymous_19) +FNDA:21,(anonymous_20) +FNDA:13,(anonymous_21) +DA:44,151 +DA:45,151 +DA:46,151 +DA:47,151 +DA:54,172 +DA:56,172 +DA:57,35 +DA:58,35 +DA:59,35 +DA:62,35 +DA:64,48 +DA:67,35 +DA:68,24 +DA:70,24 +DA:72,24 +DA:73,24 +DA:74,24 +DA:77,24 +DA:78,24 +DA:82,24 +DA:84,12 +DA:85,24 +DA:86,12 +DA:87,12 +DA:88,12 +DA:96,35 +DA:97,72 +DA:98,72 +DA:99,24 +DA:100,24 +DA:104,35 +DA:106,35 +DA:113,35 +DA:114,35 +DA:130,35 +DA:132,35 +DA:140,14 +DA:143,21 +DA:150,3 +DA:153,18 +DA:154,3 +DA:156,15 +DA:167,12 +DA:168,12 +DA:171,15 +DA:174,12 +DA:175,15 +DA:176,27 +DA:177,27 +DA:180,27 +DA:183,25 +DA:184,11 +DA:185,11 +DA:186,11 +DA:190,14 +DA:191,0 +DA:192,0 +DA:193,0 +DA:200,12 +DA:201,3 +DA:202,3 +DA:203,3 +DA:208,12 +DA:209,12 +DA:210,12 +DA:213,12 +DA:214,12 +DA:215,12 +DA:216,12 +DA:219,12 +DA:240,0 +DA:241,0 +DA:244,0 +DA:245,0 +DA:249,0 +DA:250,0 +DA:254,0 +DA:266,0 +DA:268,0 +DA:273,0 +DA:277,0 +DA:281,0 +DA:282,0 +DA:283,0 +DA:289,0 +DA:296,3 +DA:300,3 +DA:301,3 +DA:302,1 +DA:306,3 +DA:307,3 +DA:308,3 +DA:309,1 +DA:313,3 +DA:323,3 +DA:324,3 +DA:325,3 +DA:326,3 +DA:333,12 +DA:334,12 +DA:335,12 +DA:337,12 +DA:338,12 +DA:339,12 +DA:341,12 +DA:342,12 +DA:343,12 +DA:346,12 +DA:350,2 +DA:353,10 +DA:360,15 +DA:368,21 +DA:370,21 +DA:371,21 +DA:372,21 +DA:373,21 +DA:375,21 +DA:376,21 +DA:390,13 +DA:391,13 +DA:392,13 +DA:393,13 +DA:394,13 +DA:396,13 +DA:397,14 +DA:399,4 +DA:400,4 +DA:402,4 +DA:403,4 +DA:405,3 +DA:406,3 +DA:408,3 +DA:409,3 +DA:411,14 +DA:414,13 +LF:135 +LH:117 +BRDA:74,0,0,0 +BRDA:74,0,1,24 +BRDA:77,1,0,24 +BRDA:77,1,1,0 +BRDA:87,2,0,12 +BRDA:87,2,1,0 +BRDA:87,3,0,12 +BRDA:87,3,1,12 +BRDA:100,4,0,24 +BRDA:100,4,1,24 +BRDA:117,5,0,35 +BRDA:117,5,1,7 +BRDA:118,6,0,35 +BRDA:118,6,1,10 +BRDA:132,7,0,14 +BRDA:132,7,1,21 +BRDA:133,8,0,35 +BRDA:133,8,1,22 +BRDA:133,8,2,22 +BRDA:133,8,3,22 +BRDA:133,8,4,21 +BRDA:133,8,5,21 +BRDA:143,9,0,3 +BRDA:143,9,1,18 +BRDA:144,10,0,21 +BRDA:144,10,1,21 +BRDA:144,10,2,21 +BRDA:144,10,3,20 +BRDA:144,10,4,18 +BRDA:153,11,0,3 +BRDA:153,11,1,15 +BRDA:153,12,0,18 +BRDA:153,12,1,16 +BRDA:153,12,2,15 +BRDA:164,13,0,12 +BRDA:165,14,0,12 +BRDA:177,15,0,0 +BRDA:177,15,1,27 +BRDA:180,16,0,2 +BRDA:180,16,1,25 +BRDA:180,17,0,27 +BRDA:180,17,1,4 +BRDA:183,18,0,11 +BRDA:183,18,1,14 +BRDA:190,19,0,0 +BRDA:190,19,1,14 +BRDA:190,20,0,14 +BRDA:190,20,1,0 +BRDA:200,21,0,3 +BRDA:200,21,1,9 +BRDA:210,22,0,11 +BRDA:210,22,1,1 +BRDA:216,23,0,12 +BRDA:216,23,1,0 +BRDA:241,24,0,0 +BRDA:241,24,1,0 +BRDA:245,25,0,0 +BRDA:245,25,1,0 +BRDA:249,26,0,0 +BRDA:249,26,1,0 +BRDA:249,27,0,0 +BRDA:249,27,1,0 +BRDA:268,28,0,0 +BRDA:268,28,1,0 +BRDA:269,29,0,0 +BRDA:269,29,1,0 +BRDA:273,30,0,0 +BRDA:273,30,1,0 +BRDA:274,31,0,0 +BRDA:274,31,1,0 +BRDA:281,32,0,0 +BRDA:281,32,1,0 +BRDA:282,33,0,0 +BRDA:282,33,1,0 +BRDA:301,34,0,1 +BRDA:301,34,1,2 +BRDA:308,35,0,1 +BRDA:308,35,1,2 +BRDA:308,36,0,3 +BRDA:308,36,1,1 +BRDA:339,37,0,0 +BRDA:339,37,1,12 +BRDA:341,38,0,8 +BRDA:341,38,1,4 +BRDA:342,39,0,4 +BRDA:342,39,1,8 +BRDA:343,40,0,0 +BRDA:343,40,1,12 +BRDA:346,41,0,2 +BRDA:346,41,1,10 +BRDA:346,42,0,12 +BRDA:346,42,1,4 +BRDA:346,42,2,2 +BRDA:346,42,3,10 +BRDA:348,43,0,8 +BRDA:348,43,1,2 +BRDA:348,44,0,4 +BRDA:348,44,1,6 +BRDA:348,45,0,0 +BRDA:348,45,1,10 +BRDA:353,46,0,2 +BRDA:353,46,1,8 +BRDA:397,47,0,4 +BRDA:397,47,1,4 +BRDA:397,47,2,3 +BRDA:397,47,3,3 +BRDA:420,48,0,12 +BRDA:420,48,1,1 +BRF:108 +BRH:78 +end_of_record +TN: +SF:src/graph/builder.ts +FN:87,(anonymous_0) +FN:94,(anonymous_1) +FN:106,(anonymous_2) +FN:120,(anonymous_3) +FN:126,(anonymous_4) +FN:130,(anonymous_5) +FN:134,(anonymous_6) +FN:142,(anonymous_7) +FN:145,(anonymous_8) +FN:148,(anonymous_9) +FN:151,(anonymous_10) +FN:154,(anonymous_11) +FN:162,(anonymous_12) +FN:228,(anonymous_13) +FN:267,(anonymous_14) +FN:344,(anonymous_15) +FN:422,(anonymous_16) +FN:452,(anonymous_17) +FN:490,(anonymous_18) +FN:561,(anonymous_19) +FN:597,(anonymous_20) +FN:606,(anonymous_21) +FN:650,(anonymous_22) +FN:706,(anonymous_23) +FNF:24 +FNH:20 +FNDA:133,(anonymous_0) +FNDA:144,(anonymous_1) +FNDA:14,(anonymous_2) +FNDA:22,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:110,(anonymous_5) +FNDA:10,(anonymous_6) +FNDA:3,(anonymous_7) +FNDA:1,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:4,(anonymous_10) +FNDA:3,(anonymous_11) +FNDA:10,(anonymous_12) +FNDA:40,(anonymous_13) +FNDA:3,(anonymous_14) +FNDA:1,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:1,(anonymous_17) +FNDA:4,(anonymous_18) +FNDA:3,(anonymous_19) +FNDA:10,(anonymous_20) +FNDA:0,(anonymous_21) +FNDA:0,(anonymous_22) +FNDA:4,(anonymous_23) +DA:80,133 +DA:81,133 +DA:88,133 +DA:89,133 +DA:90,133 +DA:91,133 +DA:95,144 +DA:112,14 +DA:113,14 +DA:114,4 +DA:116,3 +DA:117,3 +DA:122,22 +DA:123,22 +DA:127,0 +DA:131,110 +DA:135,10 +DA:136,10 +DA:139,10 +DA:142,10 +DA:145,10 +DA:148,10 +DA:151,10 +DA:154,10 +DA:157,10 +DA:159,10 +DA:164,10 +DA:165,10 +DA:166,10 +DA:167,10 +DA:169,10 +DA:204,10 +DA:207,10 +DA:208,10 +DA:211,10 +DA:229,40 +DA:230,40 +DA:231,40 +DA:233,40 +DA:248,40 +DA:249,40 +DA:250,30 +DA:253,30 +DA:268,3 +DA:269,3 +DA:270,3 +DA:272,3 +DA:320,3 +DA:333,3 +DA:334,3 +DA:345,1 +DA:346,1 +DA:347,1 +DA:349,1 +DA:389,1 +DA:402,1 +DA:403,0 +DA:421,1 +DA:422,0 +DA:423,0 +DA:441,1 +DA:442,1 +DA:453,1 +DA:454,1 +DA:455,1 +DA:457,1 +DA:477,1 +DA:491,4 +DA:492,4 +DA:493,4 +DA:495,4 +DA:523,4 +DA:536,4 +DA:537,4 +DA:540,0 +DA:541,0 +DA:562,3 +DA:563,3 +DA:564,3 +DA:566,3 +DA:584,3 +DA:598,10 +DA:599,10 +DA:600,10 +DA:603,0 +DA:606,10 +DA:607,0 +DA:608,0 +DA:609,0 +DA:612,0 +DA:636,0 +DA:650,10 +DA:651,0 +DA:652,0 +DA:653,0 +DA:656,0 +DA:676,0 +DA:677,0 +DA:678,0 +DA:692,0 +DA:707,4 +DA:710,4 +DA:711,4 +DA:712,4 +DA:719,4 +DA:720,20 +DA:721,0 +DA:724,4 +LF:108 +LH:87 +BRDA:88,0,0,133 +BRDA:88,0,1,123 +BRDA:88,0,2,0 +BRDA:89,1,0,133 +BRDA:89,1,1,123 +BRDA:89,1,2,0 +BRDA:90,2,0,133 +BRDA:90,2,1,126 +BRDA:90,2,2,126 +BRDA:91,3,0,133 +BRDA:91,3,1,126 +BRDA:113,4,0,10 +BRDA:113,4,1,4 +BRDA:114,5,0,1 +BRDA:114,5,1,3 +BRDA:116,6,0,0 +BRDA:116,6,1,3 +BRDA:122,7,0,22 +BRDA:122,7,1,0 +BRDA:164,8,0,10 +BRDA:164,8,1,0 +BRDA:166,9,0,0 +BRDA:166,9,1,10 +BRDA:191,10,0,10 +BRDA:191,10,1,0 +BRDA:192,11,0,10 +BRDA:192,11,1,0 +BRDA:193,12,0,10 +BRDA:193,12,1,7 +BRDA:194,13,0,10 +BRDA:194,13,1,0 +BRDA:230,14,0,0 +BRDA:230,14,1,40 +BRDA:249,15,0,30 +BRDA:249,15,1,10 +BRDA:268,16,0,3 +BRDA:268,16,1,0 +BRDA:269,17,0,0 +BRDA:269,17,1,3 +BRDA:295,18,0,3 +BRDA:295,18,1,0 +BRDA:298,19,0,3 +BRDA:298,19,1,0 +BRDA:299,20,0,3 +BRDA:299,20,1,0 +BRDA:299,20,2,0 +BRDA:300,21,0,3 +BRDA:300,21,1,0 +BRDA:300,21,2,0 +BRDA:301,22,0,3 +BRDA:301,22,1,0 +BRDA:302,23,0,3 +BRDA:302,23,1,1 +BRDA:307,24,0,3 +BRDA:307,24,1,0 +BRDA:333,25,0,3 +BRDA:333,25,1,0 +BRDA:346,26,0,0 +BRDA:346,26,1,1 +BRDA:371,27,0,1 +BRDA:371,27,1,0 +BRDA:374,28,0,1 +BRDA:374,28,1,0 +BRDA:375,29,0,1 +BRDA:375,29,1,0 +BRDA:376,30,0,1 +BRDA:376,30,1,0 +BRDA:377,31,0,1 +BRDA:377,31,1,0 +BRDA:378,32,0,1 +BRDA:378,32,1,1 +BRDA:379,33,0,1 +BRDA:379,33,1,0 +BRDA:402,34,0,0 +BRDA:402,34,1,1 +BRDA:421,35,0,0 +BRDA:421,35,1,1 +BRDA:441,36,0,1 +BRDA:441,36,1,0 +BRDA:454,37,0,0 +BRDA:454,37,1,1 +BRDA:471,38,0,1 +BRDA:471,38,1,1 +BRDA:492,39,0,0 +BRDA:492,39,1,4 +BRDA:513,40,0,4 +BRDA:513,40,1,4 +BRDA:537,41,0,0 +BRDA:537,41,1,4 +BRDA:563,42,0,0 +BRDA:563,42,1,3 +BRDA:598,43,0,10 +BRDA:598,43,1,10 +BRDA:599,44,0,10 +BRDA:599,44,1,10 +BRDA:600,45,0,10 +BRDA:600,45,1,0 +BRDA:600,46,0,10 +BRDA:600,46,1,10 +BRDA:603,47,0,0 +BRDA:603,47,1,0 +BRDA:608,48,0,0 +BRDA:608,48,1,0 +BRDA:627,49,0,0 +BRDA:627,49,1,0 +BRDA:629,50,0,0 +BRDA:629,50,1,0 +BRDA:652,51,0,0 +BRDA:652,51,1,0 +BRDA:669,52,0,0 +BRDA:669,52,1,0 +BRDA:676,53,0,0 +BRDA:676,53,1,0 +BRDA:707,54,0,0 +BRDA:707,54,1,4 +BRDA:720,55,0,0 +BRDA:720,55,1,20 +BRF:117 +BRH:65 +end_of_record +TN: +SF:src/graph/cache.ts +FN:32,(anonymous_0) +FN:37,(anonymous_1) +FN:57,(anonymous_2) +FN:73,(anonymous_3) +FN:86,(anonymous_4) +FN:94,(anonymous_5) +FN:102,(anonymous_6) +FN:117,(anonymous_7) +FN:128,(anonymous_8) +FN:143,(anonymous_9) +FNF:10 +FNH:7 +FNDA:123,(anonymous_0) +FNDA:123,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:3,(anonymous_3) +FNDA:2,(anonymous_4) +FNDA:2,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:1,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +DA:33,123 +DA:34,123 +DA:38,123 +DA:39,123 +DA:40,123 +DA:41,123 +DA:44,0 +DA:47,0 +DA:58,3 +DA:59,3 +DA:60,3 +DA:61,0 +DA:63,3 +DA:64,3 +DA:66,0 +DA:74,3 +DA:75,3 +DA:87,2 +DA:88,2 +DA:95,2 +DA:96,2 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:111,0 +DA:118,1 +DA:133,0 +DA:144,0 +LF:30 +LH:18 +BRDA:32,0,0,123 +BRDA:39,1,0,123 +BRDA:39,1,1,0 +BRDA:60,2,0,0 +BRDA:60,2,1,3 +BRDA:96,3,0,2 +BRDA:96,3,1,0 +BRDA:106,4,0,0 +BRDA:106,4,1,0 +BRDA:106,5,0,0 +BRDA:106,5,1,0 +BRF:11 +BRH:4 +end_of_record +TN: +SF:src/graph/client.ts +FN:42,sleep +FN:43,(anonymous_1) +FN:74,(anonymous_2) +FN:88,(anonymous_3) +FN:124,(anonymous_4) +FN:138,(anonymous_5) +FN:149,(anonymous_6) +FN:159,(anonymous_7) +FN:171,(anonymous_8) +FN:176,(anonymous_9) +FN:190,(anonymous_10) +FN:192,(anonymous_11) +FN:212,(anonymous_12) +FN:221,(anonymous_13) +FN:230,(anonymous_14) +FN:254,(anonymous_15) +FN:272,(anonymous_16) +FN:304,(anonymous_17) +FN:315,(anonymous_18) +FN:338,(anonymous_19) +FN:349,(anonymous_20) +FN:389,(anonymous_21) +FN:411,(anonymous_22) +FN:424,(anonymous_23) +FN:442,(anonymous_24) +FNF:25 +FNH:20 +FNDA:1,sleep +FNDA:1,(anonymous_1) +FNDA:7,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:7,(anonymous_4) +FNDA:1,(anonymous_5) +FNDA:1,(anonymous_6) +FNDA:4,(anonymous_7) +FNDA:2,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:1,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:4,(anonymous_14) +FNDA:2,(anonymous_15) +FNDA:2,(anonymous_16) +FNDA:2,(anonymous_17) +FNDA:1,(anonymous_18) +FNDA:0,(anonymous_19) +FNDA:0,(anonymous_20) +FNDA:2,(anonymous_21) +FNDA:1,(anonymous_22) +FNDA:1,(anonymous_23) +FNDA:1,(anonymous_24) +DA:27,5 +DA:33,5 +DA:36,5 +DA:39,5 +DA:43,1 +DA:61,7 +DA:62,7 +DA:66,7 +DA:67,7 +DA:68,7 +DA:72,7 +DA:75,7 +DA:82,7 +DA:84,7 +DA:85,7 +DA:89,1 +DA:91,1 +DA:92,1 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:99,1 +DA:100,1 +DA:104,1 +DA:105,1 +DA:106,1 +DA:108,1 +DA:109,1 +DA:110,1 +DA:111,1 +DA:112,1 +DA:113,1 +DA:114,1 +DA:115,1 +DA:118,0 +DA:119,0 +DA:120,0 +DA:125,7 +DA:126,7 +DA:131,7 +DA:139,1 +DA:140,0 +DA:143,1 +DA:144,1 +DA:150,1 +DA:151,1 +DA:152,1 +DA:160,4 +DA:161,0 +DA:162,0 +DA:164,0 +DA:165,0 +DA:166,0 +DA:168,0 +DA:172,2 +DA:173,2 +DA:177,1 +DA:178,1 +DA:179,0 +DA:180,0 +DA:181,0 +DA:191,1 +DA:192,1 +DA:193,0 +DA:194,0 +DA:195,0 +DA:196,0 +DA:199,0 +DA:200,0 +DA:201,0 +DA:202,0 +DA:207,1 +DA:208,1 +DA:213,0 +DA:214,0 +DA:215,0 +DA:222,0 +DA:223,0 +DA:224,0 +DA:225,0 +DA:226,0 +DA:232,4 +DA:233,0 +DA:240,4 +DA:241,1 +DA:242,1 +DA:243,1 +DA:245,1 +DA:253,3 +DA:254,2 +DA:258,3 +DA:259,4 +DA:260,1 +DA:261,1 +DA:266,1 +DA:269,4 +DA:270,4 +DA:271,4 +DA:272,2 +DA:274,2 +DA:275,2 +DA:277,2 +DA:278,2 +DA:280,2 +DA:281,1 +DA:286,1 +DA:289,1 +DA:290,1 +DA:294,1 +DA:296,4 +DA:300,1 +DA:301,1 +DA:305,2 +DA:306,2 +DA:307,2 +DA:316,1 +DA:318,1 +DA:319,2 +DA:320,2 +DA:323,2 +DA:324,1 +DA:328,1 +DA:339,0 +DA:340,0 +DA:350,0 +DA:353,0 +DA:354,0 +DA:358,0 +DA:359,0 +DA:360,0 +DA:361,0 +DA:365,0 +DA:366,0 +DA:367,0 +DA:368,0 +DA:372,0 +DA:373,0 +DA:377,0 +DA:378,0 +DA:382,0 +DA:399,2 +DA:400,1 +DA:403,1 +DA:405,1 +DA:411,1 +DA:418,1 +DA:424,1 +DA:432,1 +DA:434,0 +DA:435,0 +DA:443,1 +LF:153 +LH:98 +BRDA:74,0,0,7 +BRDA:76,1,0,7 +BRDA:76,1,1,6 +BRDA:77,2,0,7 +BRDA:77,2,1,6 +BRDA:78,3,0,7 +BRDA:78,3,1,7 +BRDA:79,4,0,7 +BRDA:79,4,1,7 +BRDA:99,5,0,1 +BRDA:99,5,1,0 +BRDA:127,6,0,7 +BRDA:127,6,1,0 +BRDA:128,7,0,7 +BRDA:128,7,1,7 +BRDA:139,8,0,0 +BRDA:139,8,1,1 +BRDA:139,9,0,1 +BRDA:139,9,1,1 +BRDA:143,10,0,1 +BRDA:143,10,1,0 +BRDA:160,11,0,4 +BRDA:160,11,1,0 +BRDA:162,12,0,0 +BRDA:162,12,1,0 +BRDA:173,13,0,0 +BRDA:173,13,1,2 +BRDA:178,14,0,0 +BRDA:178,14,1,1 +BRDA:191,15,0,0 +BRDA:191,15,1,1 +BRDA:199,16,0,0 +BRDA:199,16,1,0 +BRDA:207,17,0,1 +BRDA:207,17,1,0 +BRDA:213,18,0,0 +BRDA:213,18,1,0 +BRDA:223,19,0,0 +BRDA:223,19,1,0 +BRDA:230,20,0,4 +BRDA:232,21,0,0 +BRDA:232,21,1,4 +BRDA:240,22,0,1 +BRDA:240,22,1,3 +BRDA:247,23,0,1 +BRDA:247,23,1,0 +BRDA:254,24,0,1 +BRDA:254,24,1,1 +BRDA:259,25,0,1 +BRDA:259,25,1,3 +BRDA:260,26,0,1 +BRDA:260,26,1,0 +BRDA:277,27,0,2 +BRDA:277,27,1,0 +BRDA:278,28,0,2 +BRDA:278,28,1,2 +BRDA:280,29,0,1 +BRDA:280,29,1,1 +BRDA:305,30,0,2 +BRDA:305,30,1,0 +BRDA:308,31,0,2 +BRDA:308,31,1,1 +BRDA:308,31,2,1 +BRDA:308,31,3,1 +BRDA:323,32,0,1 +BRDA:323,32,1,1 +BRDA:353,33,0,0 +BRDA:353,33,1,0 +BRDA:353,34,0,0 +BRDA:353,34,1,0 +BRDA:358,35,0,0 +BRDA:358,35,1,0 +BRDA:358,36,0,0 +BRDA:358,36,1,0 +BRDA:360,37,0,0 +BRDA:360,37,1,0 +BRDA:365,38,0,0 +BRDA:365,38,1,0 +BRDA:367,39,0,0 +BRDA:367,39,1,0 +BRDA:372,40,0,0 +BRDA:372,40,1,0 +BRDA:372,41,0,0 +BRDA:372,41,1,0 +BRDA:377,42,0,0 +BRDA:377,42,1,0 +BRDA:399,43,0,1 +BRDA:399,43,1,1 +BRDA:414,44,0,1 +BRDA:414,44,1,0 +BRDA:429,45,0,1 +BRDA:429,45,1,0 +BRF:92 +BRH:48 +end_of_record +TN: +SF:src/graph/docs-builder.ts +FN:21,(anonymous_0) +FN:43,(anonymous_1) +FN:75,(anonymous_2) +FN:104,(anonymous_3) +FN:138,(anonymous_4) +FN:149,(anonymous_5) +FN:169,(anonymous_6) +FN:210,(anonymous_7) +FN:214,(anonymous_8) +FNF:9 +FNH:9 +FNDA:51,(anonymous_0) +FNDA:54,(anonymous_1) +FNDA:54,(anonymous_2) +FNDA:204,(anonymous_3) +FNDA:204,(anonymous_4) +FNDA:151,(anonymous_5) +FNDA:315,(anonymous_6) +FNDA:54,(anonymous_7) +FNDA:408,(anonymous_8) +DA:22,51 +DA:23,51 +DA:24,51 +DA:25,51 +DA:44,54 +DA:45,54 +DA:47,54 +DA:49,54 +DA:50,54 +DA:51,204 +DA:52,204 +DA:53,204 +DA:54,204 +DA:58,54 +DA:59,151 +DA:63,54 +DA:64,204 +DA:65,204 +DA:66,315 +DA:70,54 +DA:76,54 +DA:110,204 +DA:139,204 +DA:150,151 +DA:170,315 +DA:173,315 +DA:190,315 +DA:205,315 +DA:211,54 +DA:215,408 +LF:30 +LH:30 +BRDA:22,0,0,51 +BRDA:22,0,1,21 +BRDA:22,0,2,0 +BRDA:23,1,0,51 +BRDA:23,1,1,0 +BRDA:23,1,2,0 +BRDA:24,2,0,51 +BRDA:24,2,1,0 +BRDA:24,2,2,0 +BRDA:25,3,0,51 +BRDA:25,3,1,0 +BRF:11 +BRH:5 +end_of_record +TN: +SF:src/graph/hybrid-retriever.ts +FN:51,(anonymous_0) +FN:43,(anonymous_1) +FN:47,(anonymous_2) +FN:57,(anonymous_3) +FN:72,(anonymous_4) +FN:88,(anonymous_5) +FN:101,(anonymous_6) +FN:120,(anonymous_7) +FN:145,(anonymous_8) +FN:150,(anonymous_9) +FN:162,(anonymous_10) +FN:179,(anonymous_11) +FN:215,(anonymous_12) +FN:248,(anonymous_13) +FN:250,(anonymous_14) +FN:257,(anonymous_15) +FN:261,(anonymous_16) +FN:262,(anonymous_17) +FN:274,(anonymous_18) +FN:275,(anonymous_19) +FN:288,(anonymous_20) +FN:297,(anonymous_21) +FN:306,(anonymous_22) +FN:307,(anonymous_23) +FN:312,(anonymous_24) +FN:313,(anonymous_25) +FN:317,(anonymous_26) +FN:320,(anonymous_27) +FN:323,(anonymous_28) +FN:344,(anonymous_29) +FN:349,(anonymous_30) +FN:350,(anonymous_31) +FN:353,(anonymous_32) +FN:354,(anonymous_33) +FNF:34 +FNH:27 +FNDA:133,(anonymous_0) +FNDA:9,(anonymous_1) +FNDA:11,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:3,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:2,(anonymous_7) +FNDA:1,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:75,(anonymous_10) +FNDA:287,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:2,(anonymous_15) +FNDA:6,(anonymous_16) +FNDA:3,(anonymous_17) +FNDA:1,(anonymous_18) +FNDA:3,(anonymous_19) +FNDA:1,(anonymous_20) +FNDA:1,(anonymous_21) +FNDA:3,(anonymous_22) +FNDA:2,(anonymous_23) +FNDA:2,(anonymous_24) +FNDA:1,(anonymous_25) +FNDA:2,(anonymous_26) +FNDA:2,(anonymous_27) +FNDA:3,(anonymous_28) +FNDA:2,(anonymous_29) +FNDA:0,(anonymous_30) +FNDA:0,(anonymous_31) +FNDA:2,(anonymous_32) +FNDA:3,(anonymous_33) +DA:36,133 +DA:41,133 +DA:44,9 +DA:48,11 +DA:52,133 +DA:53,133 +DA:54,133 +DA:58,2 +DA:59,2 +DA:60,2 +DA:63,2 +DA:67,2 +DA:71,2 +DA:72,3 +DA:77,2 +DA:81,2 +DA:82,2 +DA:83,2 +DA:85,2 +DA:89,0 +DA:90,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:113,0 +DA:114,0 +DA:117,0 +DA:121,2 +DA:123,2 +DA:124,2 +DA:125,2 +DA:142,1 +DA:143,1 +DA:144,1 +DA:145,1 +DA:150,1 +DA:158,1 +DA:159,1 +DA:167,75 +DA:168,0 +DA:174,75 +DA:175,75 +DA:179,74 +DA:180,287 +DA:182,75 +DA:184,2 +DA:185,0 +DA:190,2 +DA:191,2 +DA:193,72 +DA:198,72 +DA:199,72 +DA:204,72 +DA:205,72 +DA:207,1 +DA:216,0 +DA:217,0 +DA:218,0 +DA:221,0 +DA:230,0 +DA:232,0 +DA:233,0 +DA:234,0 +DA:236,0 +DA:237,0 +DA:238,0 +DA:239,0 +DA:243,0 +DA:244,0 +DA:247,0 +DA:248,0 +DA:250,0 +DA:258,2 +DA:259,2 +DA:261,2 +DA:262,6 +DA:263,3 +DA:264,3 +DA:265,3 +DA:267,3 +DA:268,3 +DA:269,3 +DA:273,2 +DA:274,1 +DA:276,3 +DA:277,3 +DA:294,1 +DA:297,1 +DA:299,1 +DA:305,1 +DA:306,3 +DA:307,2 +DA:312,2 +DA:313,1 +DA:319,2 +DA:320,2 +DA:328,3 +DA:329,3 +DA:330,0 +DA:337,3 +DA:345,2 +DA:346,2 +DA:349,0 +DA:350,0 +DA:354,2 +DA:355,3 +DA:356,3 +LF:110 +LH:77 +BRDA:58,0,0,2 +BRDA:58,0,1,0 +BRDA:59,1,0,2 +BRDA:59,1,1,0 +BRDA:60,2,0,2 +BRDA:60,2,1,2 +BRDA:63,3,0,0 +BRDA:63,3,1,2 +BRDA:63,4,0,2 +BRDA:63,4,1,2 +BRDA:67,5,0,2 +BRDA:67,5,1,0 +BRDA:67,6,0,2 +BRDA:67,6,1,0 +BRDA:77,7,0,0 +BRDA:77,7,1,2 +BRDA:77,8,0,2 +BRDA:77,8,1,2 +BRDA:89,9,0,0 +BRDA:89,9,1,0 +BRDA:92,10,0,0 +BRDA:92,10,1,0 +BRDA:113,11,0,0 +BRDA:113,11,1,0 +BRDA:121,12,0,2 +BRDA:121,12,1,0 +BRDA:123,13,0,2 +BRDA:123,13,1,0 +BRDA:142,14,0,1 +BRDA:142,14,1,0 +BRDA:142,15,0,1 +BRDA:142,15,1,1 +BRDA:146,16,0,1 +BRDA:146,16,1,0 +BRDA:147,17,0,1 +BRDA:147,17,1,0 +BRDA:150,18,0,1 +BRDA:150,18,1,1 +BRDA:167,19,0,0 +BRDA:167,19,1,75 +BRDA:179,20,0,74 +BRDA:179,20,1,0 +BRDA:180,21,0,287 +BRDA:180,21,1,283 +BRDA:182,22,0,2 +BRDA:182,22,1,73 +BRDA:184,23,0,0 +BRDA:184,23,1,2 +BRDA:198,24,0,72 +BRDA:198,24,1,0 +BRDA:210,25,0,1 +BRDA:210,25,1,0 +BRDA:216,26,0,0 +BRDA:216,26,1,0 +BRDA:217,27,0,0 +BRDA:217,27,1,0 +BRDA:237,28,0,0 +BRDA:237,28,1,0 +BRDA:238,29,0,0 +BRDA:238,29,1,0 +BRDA:239,30,0,0 +BRDA:239,30,1,0 +BRDA:243,31,0,0 +BRDA:243,31,1,0 +BRDA:265,32,0,3 +BRDA:265,32,1,3 +BRDA:267,33,0,3 +BRDA:267,33,1,3 +BRDA:283,34,0,3 +BRDA:283,34,1,0 +BRDA:306,35,0,3 +BRDA:306,35,1,0 +BRDA:319,36,0,2 +BRDA:319,36,1,0 +BRDA:319,37,0,2 +BRDA:319,37,1,0 +BRDA:319,38,0,2 +BRDA:319,38,1,0 +BRDA:320,39,0,2 +BRDA:320,39,1,0 +BRDA:329,40,0,0 +BRDA:329,40,1,3 +BRDA:338,41,0,3 +BRDA:338,41,1,0 +BRDA:338,41,2,0 +BRDA:339,42,0,3 +BRDA:339,42,1,0 +BRDA:339,42,2,0 +BRDA:340,43,0,3 +BRDA:340,43,1,0 +BRDA:345,44,0,2 +BRDA:345,44,1,0 +BRDA:356,45,0,3 +BRDA:356,45,1,0 +BRF:94 +BRH:46 +end_of_record +TN: +SF:src/graph/index.ts +FN:53,(anonymous_0) +FN:72,(anonymous_1) +FN:110,(anonymous_2) +FN:142,(anonymous_3) +FN:149,(anonymous_4) +FN:156,(anonymous_5) +FN:163,(anonymous_6) +FN:170,(anonymous_7) +FN:177,(anonymous_8) +FN:184,(anonymous_9) +FN:201,(anonymous_10) +FN:208,(anonymous_11) +FN:216,(anonymous_12) +FN:245,(anonymous_13) +FNF:14 +FNH:11 +FNDA:220,(anonymous_0) +FNDA:2,(anonymous_1) +FNDA:75,(anonymous_2) +FNDA:643,(anonymous_3) +FNDA:103,(anonymous_4) +FNDA:136,(anonymous_5) +FNDA:4,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:9,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:2,(anonymous_10) +FNDA:2,(anonymous_11) +FNDA:2,(anonymous_12) +FNDA:0,(anonymous_13) +DA:36,307 +DA:54,220 +DA:55,220 +DA:56,3 +DA:57,1 +DA:60,2 +DA:69,2 +DA:71,2 +DA:72,3 +DA:73,3 +DA:74,2 +DA:77,2 +DA:78,1 +DA:80,2 +DA:82,2 +DA:83,1 +DA:87,1 +DA:91,2 +DA:94,217 +DA:96,217 +DA:98,217 +DA:99,149 +DA:101,217 +DA:103,217 +DA:104,217 +DA:117,75 +DA:119,75 +DA:120,70 +DA:122,75 +DA:124,75 +DA:125,65 +DA:127,75 +DA:129,75 +DA:130,49 +DA:132,75 +DA:134,75 +DA:135,75 +DA:143,643 +DA:150,103 +DA:157,136 +DA:164,4 +DA:171,0 +DA:178,9 +DA:185,0 +DA:186,0 +DA:187,0 +DA:188,0 +DA:189,0 +DA:190,0 +DA:202,2 +DA:209,2 +DA:220,2 +DA:221,2 +DA:224,2 +DA:225,3 +DA:226,3 +DA:230,2 +DA:231,1 +DA:232,1 +DA:233,1 +DA:239,2 +DA:246,0 +LF:62 +LH:54 +BRDA:53,0,0,220 +BRDA:55,1,0,3 +BRDA:55,1,1,217 +BRDA:56,2,0,1 +BRDA:56,2,1,2 +BRDA:71,3,0,2 +BRDA:71,3,1,0 +BRDA:73,4,0,2 +BRDA:73,4,1,1 +BRDA:77,5,0,1 +BRDA:77,5,1,1 +BRDA:82,6,0,1 +BRDA:82,6,1,1 +BRDA:84,7,0,1 +BRDA:84,7,1,0 +BRDA:88,8,0,1 +BRDA:88,8,1,1 +BRDA:98,9,0,149 +BRDA:98,9,1,68 +BRDA:104,10,0,217 +BRDA:104,10,1,149 +BRDA:119,11,0,70 +BRDA:119,11,1,5 +BRDA:124,12,0,65 +BRDA:124,12,1,10 +BRDA:129,13,0,49 +BRDA:129,13,1,26 +BRDA:136,14,0,75 +BRDA:136,14,1,49 +BRDA:143,15,0,643 +BRDA:143,15,1,524 +BRDA:157,16,0,136 +BRDA:157,16,1,63 +BRDA:164,17,0,4 +BRDA:164,17,1,2 +BRDA:171,18,0,0 +BRDA:171,18,1,0 +BRF:37 +BRH:33 +end_of_record +TN: +SF:src/graph/orchestrator.ts +FN:87,(anonymous_0) +FN:128,(anonymous_1) +FN:176,(anonymous_2) +FN:220,(anonymous_3) +FN:231,(anonymous_4) +FN:239,(anonymous_5) +FN:240,(anonymous_6) +FN:318,(anonymous_7) +FN:425,(anonymous_8) +FN:443,(anonymous_9) +FN:445,(anonymous_10) +FN:448,(anonymous_11) +FN:473,(anonymous_12) +FN:485,(anonymous_13) +FN:487,(anonymous_14) +FN:490,(anonymous_15) +FN:494,(anonymous_16) +FN:495,(anonymous_17) +FN:504,(anonymous_18) +FN:559,(anonymous_19) +FN:613,(anonymous_20) +FN:624,(anonymous_21) +FN:625,(anonymous_22) +FN:639,(anonymous_23) +FN:640,(anonymous_24) +FN:656,(anonymous_25) +FN:663,(anonymous_26) +FN:699,(anonymous_27) +FN:718,(anonymous_28) +FN:723,(anonymous_29) +FN:736,(anonymous_30) +FN:749,(anonymous_31) +FN:771,(anonymous_32) +FN:793,(anonymous_33) +FN:811,(anonymous_34) +FN:825,(anonymous_35) +FN:834,(anonymous_36) +FN:837,(anonymous_37) +FN:841,(anonymous_38) +FN:848,(anonymous_39) +FN:852,(anonymous_40) +FN:862,(anonymous_41) +FN:885,(anonymous_42) +FN:893,(anonymous_43) +FN:935,(anonymous_44) +FN:947,(anonymous_45) +FN:981,(anonymous_46) +FN:993,(anonymous_47) +FN:1064,(anonymous_48) +FN:1065,(anonymous_49) +FN:1071,(anonymous_50) +FNF:51 +FNH:25 +FNDA:123,(anonymous_0) +FNDA:492,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:2,(anonymous_4) +FNDA:2,(anonymous_5) +FNDA:2,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:3,(anonymous_8) +FNDA:4,(anonymous_9) +FNDA:16,(anonymous_10) +FNDA:3,(anonymous_11) +FNDA:2,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:3,(anonymous_18) +FNDA:3,(anonymous_19) +FNDA:0,(anonymous_20) +FNDA:0,(anonymous_21) +FNDA:0,(anonymous_22) +FNDA:0,(anonymous_23) +FNDA:0,(anonymous_24) +FNDA:0,(anonymous_25) +FNDA:0,(anonymous_26) +FNDA:0,(anonymous_27) +FNDA:2,(anonymous_28) +FNDA:2,(anonymous_29) +FNDA:3,(anonymous_30) +FNDA:2,(anonymous_31) +FNDA:0,(anonymous_32) +FNDA:0,(anonymous_33) +FNDA:3,(anonymous_34) +FNDA:3,(anonymous_35) +FNDA:0,(anonymous_36) +FNDA:0,(anonymous_37) +FNDA:3,(anonymous_38) +FNDA:2,(anonymous_39) +FNDA:0,(anonymous_40) +FNDA:0,(anonymous_41) +FNDA:3,(anonymous_42) +FNDA:3,(anonymous_43) +FNDA:3,(anonymous_44) +FNDA:0,(anonymous_45) +FNDA:0,(anonymous_46) +FNDA:3,(anonymous_47) +FNDA:0,(anonymous_48) +FNDA:0,(anonymous_49) +FNDA:0,(anonymous_50) +DA:72,123 +DA:73,123 +DA:74,123 +DA:75,123 +DA:88,123 +DA:89,123 +DA:90,123 +DA:94,123 +DA:95,123 +DA:96,123 +DA:97,123 +DA:98,0 +DA:99,0 +DA:101,0 +DA:102,0 +DA:104,0 +DA:109,123 +DA:110,123 +DA:111,123 +DA:112,0 +DA:113,0 +DA:115,0 +DA:116,0 +DA:118,0 +DA:124,123 +DA:125,123 +DA:126,123 +DA:128,492 +DA:129,123 +DA:130,492 +DA:131,492 +DA:132,0 +DA:134,492 +DA:139,123 +DA:140,123 +DA:141,123 +DA:142,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:150,123 +DA:152,123 +DA:153,492 +DA:154,492 +DA:156,123 +DA:157,0 +DA:159,123 +DA:160,123 +DA:165,123 +DA:166,123 +DA:167,123 +DA:168,123 +DA:169,123 +DA:170,123 +DA:177,3 +DA:178,3 +DA:192,3 +DA:193,3 +DA:195,3 +DA:196,3 +DA:197,0 +DA:198,0 +DA:202,3 +DA:204,3 +DA:205,0 +DA:209,3 +DA:210,3 +DA:212,3 +DA:213,2 +DA:218,2 +DA:219,0 +DA:220,0 +DA:222,0 +DA:224,0 +DA:225,0 +DA:230,2 +DA:231,2 +DA:238,2 +DA:239,2 +DA:240,2 +DA:241,2 +DA:243,2 +DA:244,0 +DA:251,1 +DA:252,1 +DA:256,3 +DA:257,3 +DA:258,3 +DA:259,3 +DA:266,3 +DA:267,3 +DA:268,3 +DA:269,3 +DA:270,3 +DA:271,3 +DA:272,3 +DA:274,3 +DA:277,3 +DA:280,3 +DA:281,3 +DA:283,3 +DA:284,0 +DA:289,0 +DA:294,3 +DA:299,3 +DA:302,3 +DA:303,0 +DA:305,3 +DA:306,3 +DA:309,3 +DA:311,3 +DA:312,0 +DA:313,0 +DA:317,0 +DA:318,0 +DA:319,0 +DA:320,0 +DA:323,3 +DA:324,0 +DA:331,3 +DA:333,3 +DA:334,0 +DA:335,0 +DA:337,0 +DA:338,0 +DA:339,0 +DA:343,0 +DA:344,0 +DA:349,0 +DA:350,0 +DA:351,0 +DA:355,0 +DA:362,3 +DA:365,3 +DA:366,1 +DA:367,1 +DA:368,1 +DA:369,0 +DA:374,0 +DA:380,3 +DA:382,3 +DA:383,0 +DA:384,0 +DA:385,0 +DA:386,0 +DA:387,0 +DA:388,0 +DA:389,0 +DA:392,3 +DA:405,0 +DA:406,0 +DA:407,0 +DA:430,3 +DA:432,3 +DA:436,3 +DA:437,3 +DA:439,0 +DA:440,0 +DA:443,3 +DA:444,4 +DA:445,16 +DA:448,3 +DA:449,3 +DA:450,3 +DA:451,3 +DA:452,4 +DA:453,4 +DA:455,4 +DA:456,0 +DA:457,4 +DA:461,3 +DA:465,0 +DA:469,3 +DA:470,3 +DA:477,2 +DA:478,2 +DA:481,0 +DA:482,0 +DA:484,0 +DA:485,0 +DA:488,0 +DA:491,0 +DA:492,0 +DA:494,0 +DA:496,0 +DA:497,0 +DA:499,0 +DA:500,0 +DA:505,3 +DA:506,3 +DA:508,3 +DA:509,0 +DA:510,0 +DA:511,0 +DA:512,0 +DA:513,0 +DA:514,0 +DA:518,3 +DA:521,0 +DA:527,0 +DA:528,0 +DA:529,0 +DA:530,0 +DA:531,0 +DA:532,0 +DA:533,0 +DA:538,0 +DA:539,0 +DA:546,0 +DA:547,0 +DA:548,0 +DA:549,0 +DA:552,0 +DA:560,3 +DA:561,3 +DA:563,3 +DA:577,3 +DA:578,2 +DA:589,3 +DA:590,0 +DA:601,3 +DA:602,0 +DA:619,0 +DA:620,0 +DA:621,0 +DA:623,0 +DA:624,0 +DA:625,0 +DA:638,0 +DA:639,0 +DA:640,0 +DA:654,0 +DA:657,0 +DA:663,0 +DA:676,0 +DA:700,0 +DA:712,0 +DA:719,2 +DA:720,2 +DA:724,2 +DA:725,2 +DA:726,70 +DA:727,70 +DA:728,70 +DA:730,2 +DA:738,3 +DA:749,3 +DA:750,2 +DA:762,2 +DA:771,3 +DA:772,0 +DA:784,0 +DA:793,3 +DA:794,0 +DA:799,0 +DA:812,3 +DA:813,3 +DA:815,41 +DA:816,39 +DA:819,3 +DA:826,3 +DA:834,0 +DA:837,0 +DA:841,3 +DA:848,2 +DA:852,0 +DA:862,0 +DA:890,3 +DA:893,3 +DA:895,3 +DA:896,0 +DA:897,0 +DA:900,0 +DA:902,0 +DA:904,0 +DA:910,0 +DA:913,0 +DA:914,0 +DA:929,3 +DA:936,3 +DA:954,0 +DA:955,0 +DA:960,0 +DA:962,0 +DA:963,0 +DA:964,0 +DA:966,0 +DA:968,0 +DA:972,0 +DA:980,0 +DA:981,0 +DA:982,0 +DA:983,0 +DA:987,0 +DA:994,3 +DA:997,3 +DA:998,3 +DA:1003,0 +DA:1036,0 +DA:1037,0 +DA:1058,0 +DA:1065,0 +DA:1072,0 +DA:1077,0 +LF:306 +LH:155 +BRDA:87,0,0,123 +BRDA:97,1,0,0 +BRDA:97,1,1,123 +BRDA:98,2,0,0 +BRDA:98,2,1,0 +BRDA:101,3,0,0 +BRDA:101,3,1,0 +BRDA:104,4,0,0 +BRDA:104,4,1,0 +BRDA:111,5,0,0 +BRDA:111,5,1,123 +BRDA:112,6,0,0 +BRDA:112,6,1,0 +BRDA:115,7,0,0 +BRDA:115,7,1,0 +BRDA:131,8,0,0 +BRDA:131,8,1,492 +BRDA:131,9,0,492 +BRDA:131,9,1,492 +BRDA:141,10,0,0 +BRDA:141,10,1,123 +BRDA:142,11,0,0 +BRDA:142,11,1,0 +BRDA:144,12,0,0 +BRDA:144,12,1,0 +BRDA:146,13,0,0 +BRDA:146,13,1,0 +BRDA:153,14,0,0 +BRDA:153,14,1,492 +BRDA:156,15,0,0 +BRDA:156,15,1,123 +BRDA:159,16,0,123 +BRDA:159,16,1,0 +BRDA:168,17,0,123 +BRDA:168,17,1,0 +BRDA:176,18,0,3 +BRDA:179,19,0,3 +BRDA:179,19,1,0 +BRDA:180,20,0,3 +BRDA:180,20,1,3 +BRDA:181,21,0,3 +BRDA:181,21,1,0 +BRDA:183,22,0,3 +BRDA:183,22,1,0 +BRDA:183,22,2,0 +BRDA:185,23,0,0 +BRDA:185,23,1,0 +BRDA:186,24,0,3 +BRDA:186,24,1,0 +BRDA:187,25,0,3 +BRDA:187,25,1,3 +BRDA:196,26,0,0 +BRDA:196,26,1,3 +BRDA:204,27,0,0 +BRDA:204,27,1,3 +BRDA:212,28,0,2 +BRDA:212,28,1,1 +BRDA:218,29,0,0 +BRDA:218,29,1,2 +BRDA:220,30,0,0 +BRDA:220,30,1,0 +BRDA:224,31,0,0 +BRDA:224,31,1,0 +BRDA:234,32,0,2 +BRDA:234,32,1,0 +BRDA:243,33,0,0 +BRDA:243,33,1,2 +BRDA:283,34,0,0 +BRDA:283,34,1,3 +BRDA:283,35,0,3 +BRDA:283,35,1,0 +BRDA:302,36,0,0 +BRDA:302,36,1,3 +BRDA:311,37,0,0 +BRDA:311,37,1,3 +BRDA:312,38,0,0 +BRDA:312,38,1,0 +BRDA:319,39,0,0 +BRDA:319,39,1,0 +BRDA:323,40,0,0 +BRDA:323,40,1,3 +BRDA:331,41,0,3 +BRDA:331,41,1,3 +BRDA:331,41,2,3 +BRDA:331,41,3,1 +BRDA:333,42,0,0 +BRDA:333,42,1,3 +BRDA:334,43,0,0 +BRDA:334,43,1,0 +BRDA:343,44,0,0 +BRDA:343,44,1,0 +BRDA:349,45,0,0 +BRDA:349,45,1,0 +BRDA:356,46,0,0 +BRDA:356,46,1,0 +BRDA:365,47,0,1 +BRDA:365,47,1,2 +BRDA:368,48,0,0 +BRDA:368,48,1,1 +BRDA:375,49,0,0 +BRDA:375,49,1,0 +BRDA:382,50,0,0 +BRDA:382,50,1,3 +BRDA:432,51,0,0 +BRDA:432,51,1,3 +BRDA:436,52,0,3 +BRDA:436,52,1,0 +BRDA:453,53,0,0 +BRDA:453,53,1,4 +BRDA:455,54,0,0 +BRDA:455,54,1,4 +BRDA:457,55,0,3 +BRDA:457,55,1,1 +BRDA:458,56,0,4 +BRDA:458,56,1,4 +BRDA:477,57,0,2 +BRDA:477,57,1,0 +BRDA:477,58,0,2 +BRDA:477,58,1,0 +BRDA:485,59,0,0 +BRDA:485,59,1,0 +BRDA:488,60,0,0 +BRDA:488,60,1,0 +BRDA:492,61,0,0 +BRDA:492,61,1,0 +BRDA:492,61,2,0 +BRDA:496,62,0,0 +BRDA:496,62,1,0 +BRDA:506,63,0,3 +BRDA:506,63,1,0 +BRDA:506,64,0,3 +BRDA:506,64,1,0 +BRDA:508,65,0,0 +BRDA:508,65,1,3 +BRDA:509,66,0,0 +BRDA:509,66,1,0 +BRDA:510,67,0,0 +BRDA:510,67,1,0 +BRDA:513,68,0,0 +BRDA:513,68,1,0 +BRDA:521,69,0,0 +BRDA:521,69,1,0 +BRDA:522,70,0,0 +BRDA:522,70,1,0 +BRDA:522,70,2,0 +BRDA:522,70,3,0 +BRDA:527,71,0,0 +BRDA:527,71,1,0 +BRDA:528,72,0,0 +BRDA:528,72,1,0 +BRDA:529,73,0,0 +BRDA:529,73,1,0 +BRDA:532,74,0,0 +BRDA:532,74,1,0 +BRDA:548,75,0,0 +BRDA:548,75,1,0 +BRDA:560,76,0,3 +BRDA:560,76,1,0 +BRDA:561,77,0,3 +BRDA:561,77,1,0 +BRDA:639,78,0,0 +BRDA:639,78,1,0 +BRDA:644,79,0,0 +BRDA:644,79,1,0 +BRDA:657,80,0,0 +BRDA:657,80,1,0 +BRDA:657,80,2,0 +BRDA:657,80,3,0 +BRDA:657,80,4,0 +BRDA:667,81,0,0 +BRDA:667,81,1,0 +BRDA:667,82,0,0 +BRDA:667,82,1,0 +BRDA:712,83,0,0 +BRDA:712,83,1,0 +BRDA:745,84,0,3 +BRDA:745,84,1,0 +BRDA:760,85,0,2 +BRDA:760,85,1,0 +BRDA:782,86,0,0 +BRDA:782,86,1,0 +BRDA:815,87,0,39 +BRDA:815,87,1,2 +BRDA:815,88,0,41 +BRDA:815,88,1,2 +BRDA:837,89,0,0 +BRDA:837,89,1,0 +BRDA:844,90,0,0 +BRDA:844,90,1,3 +BRDA:876,91,0,3 +BRDA:876,91,1,0 +BRDA:896,92,0,0 +BRDA:896,92,1,0 +BRDA:897,93,0,0 +BRDA:897,93,1,0 +BRDA:900,94,0,0 +BRDA:900,94,1,0 +BRDA:910,95,0,0 +BRDA:910,95,1,0 +BRDA:937,96,0,3 +BRDA:937,96,1,3 +BRDA:937,96,2,3 +BRDA:937,96,3,3 +BRDA:954,97,0,0 +BRDA:954,97,1,0 +BRDA:954,98,0,0 +BRDA:954,98,1,0 +BRDA:960,99,0,0 +BRDA:960,99,1,0 +BRDA:964,100,0,0 +BRDA:964,100,1,0 +BRDA:982,101,0,0 +BRDA:982,101,1,0 +BRDA:997,102,0,3 +BRDA:997,102,1,0 +BRDA:997,103,0,3 +BRDA:997,103,1,3 +BRF:217 +BRH:71 +end_of_record +TN: +SF:src/graph/ppr.ts +FN:47,runPPR +FN:64,tryMagePPR +FN:145,(anonymous_2) +FN:155,runJsPPR +FN:249,(anonymous_4) +FN:259,(anonymous_5) +FN:274,(anonymous_6) +FNF:7 +FNH:7 +FNDA:23,runPPR +FNDA:20,tryMagePPR +FNDA:35,(anonymous_2) +FNDA:11,runJsPPR +FNDA:2245,(anonymous_4) +FNDA:34,(anonymous_5) +FNDA:23,(anonymous_6) +DA:27,4 +DA:48,23 +DA:49,23 +DA:51,20 +DA:52,23 +DA:53,23 +DA:55,23 +DA:56,20 +DA:58,11 +DA:71,20 +DA:73,20 +DA:86,19 +DA:87,10 +DA:90,9 +DA:91,9 +DA:92,9 +DA:93,42 +DA:94,42 +DA:95,42 +DA:96,42 +DA:104,9 +DA:116,9 +DA:117,9 +DA:118,9 +DA:119,9 +DA:120,3 +DA:121,3 +DA:122,3 +DA:123,3 +DA:124,3 +DA:128,9 +DA:129,9 +DA:130,9 +DA:131,42 +DA:132,42 +DA:133,42 +DA:134,42 +DA:135,42 +DA:145,35 +DA:148,1 +DA:163,11 +DA:165,11 +DA:181,11 +DA:182,11 +DA:183,11 +DA:185,11 +DA:186,23 +DA:187,23 +DA:188,23 +DA:190,23 +DA:191,23 +DA:193,23 +DA:194,23 +DA:196,23 +DA:197,10 +DA:203,23 +DA:204,23 +DA:211,23 +DA:212,23 +DA:215,11 +DA:216,11 +DA:217,1 +DA:221,11 +DA:222,11 +DA:223,11 +DA:224,11 +DA:225,11 +DA:226,34 +DA:229,11 +DA:230,11 +DA:231,34 +DA:233,11 +DA:234,11 +DA:235,12 +DA:236,23 +DA:237,23 +DA:241,11 +DA:242,180 +DA:243,180 +DA:244,575 +DA:245,575 +DA:246,575 +DA:247,395 +DA:248,395 +DA:249,2245 +DA:250,395 +DA:252,575 +DA:253,575 +DA:255,180 +DA:258,180 +DA:260,34 +DA:265,34 +DA:274,23 +LF:93 +LH:93 +BRDA:48,0,0,23 +BRDA:48,0,1,0 +BRDA:49,1,0,3 +BRDA:49,1,1,20 +BRDA:51,2,0,20 +BRDA:51,2,1,17 +BRDA:52,3,0,0 +BRDA:52,3,1,20 +BRDA:53,4,0,23 +BRDA:53,4,1,16 +BRDA:56,5,0,9 +BRDA:56,5,1,11 +BRDA:86,6,0,10 +BRDA:86,6,1,9 +BRDA:86,7,0,19 +BRDA:86,7,1,18 +BRDA:86,7,2,18 +BRDA:93,8,0,42 +BRDA:93,8,1,0 +BRDA:94,9,0,0 +BRDA:94,9,1,42 +BRDA:95,10,0,42 +BRDA:95,10,1,0 +BRDA:97,11,0,42 +BRDA:97,11,1,0 +BRDA:98,12,0,42 +BRDA:98,12,1,0 +BRDA:99,13,0,42 +BRDA:99,13,1,0 +BRDA:119,14,0,9 +BRDA:119,14,1,0 +BRDA:120,15,0,3 +BRDA:120,15,1,0 +BRDA:121,16,0,0 +BRDA:121,16,1,3 +BRDA:122,17,0,3 +BRDA:122,17,1,2 +BRDA:123,18,0,3 +BRDA:123,18,1,0 +BRDA:124,19,0,3 +BRDA:124,19,1,0 +BRDA:131,20,0,42 +BRDA:131,20,1,0 +BRDA:132,21,0,42 +BRDA:132,21,1,31 +BRDA:138,22,0,42 +BRDA:138,22,1,0 +BRDA:139,23,0,42 +BRDA:139,23,1,0 +BRDA:140,24,0,42 +BRDA:140,24,1,0 +BRDA:163,25,0,11 +BRDA:163,25,1,10 +BRDA:185,26,0,11 +BRDA:185,26,1,0 +BRDA:186,27,0,23 +BRDA:186,27,1,0 +BRDA:187,28,0,23 +BRDA:187,28,1,0 +BRDA:188,29,0,0 +BRDA:188,29,1,23 +BRDA:188,30,0,23 +BRDA:188,30,1,23 +BRDA:190,31,0,23 +BRDA:190,31,1,0 +BRDA:191,32,0,23 +BRDA:191,32,1,0 +BRDA:196,33,0,10 +BRDA:196,33,1,13 +BRDA:198,34,0,10 +BRDA:198,34,1,0 +BRDA:199,35,0,10 +BRDA:199,35,1,0 +BRDA:200,36,0,10 +BRDA:200,36,1,0 +BRDA:203,37,0,23 +BRDA:203,37,1,0 +BRDA:205,38,0,23 +BRDA:205,38,1,0 +BRDA:206,39,0,23 +BRDA:206,39,1,0 +BRDA:207,40,0,23 +BRDA:207,40,1,0 +BRDA:211,41,0,12 +BRDA:211,41,1,11 +BRDA:216,42,0,1 +BRDA:216,42,1,10 +BRDA:222,43,0,11 +BRDA:222,43,1,0 +BRDA:226,44,0,11 +BRDA:226,44,1,23 +BRDA:236,45,0,23 +BRDA:236,45,1,0 +BRDA:244,46,0,575 +BRDA:244,46,1,180 +BRDA:247,47,0,395 +BRDA:247,47,1,0 +BRDA:248,48,0,395 +BRDA:248,48,1,0 +BRDA:250,49,0,395 +BRDA:250,49,1,0 +BRDA:252,50,0,575 +BRDA:252,50,1,395 +BRDA:260,51,0,34 +BRDA:260,51,1,0 +BRDA:267,52,0,34 +BRDA:267,52,1,0 +BRF:107 +BRH:70 +end_of_record +TN: +SF:src/graph/sync-state.ts +FN:31,(anonymous_0) +FN:38,(anonymous_1) +FN:52,(anonymous_2) +FN:59,(anonymous_3) +FN:66,(anonymous_4) +FN:67,(anonymous_5) +FN:73,(anonymous_6) +FN:74,(anonymous_7) +FN:80,(anonymous_8) +FN:92,(anonymous_9) +FN:94,(anonymous_10) +FN:95,(anonymous_11) +FN:101,(anonymous_12) +FN:112,(anonymous_13) +FN:123,(anonymous_14) +FN:132,(anonymous_15) +FN:141,(anonymous_16) +FN:156,(anonymous_17) +FN:163,(anonymous_18) +FN:188,(anonymous_19) +FN:189,(anonymous_20) +FN:214,(anonymous_21) +FNF:22 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:0,(anonymous_18) +FNDA:0,(anonymous_19) +FNDA:0,(anonymous_20) +FNDA:0,(anonymous_21) +DA:20,0 +DA:27,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:46,0 +DA:53,0 +DA:60,0 +DA:67,0 +DA:74,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:86,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:142,0 +DA:148,0 +DA:149,0 +DA:157,0 +DA:171,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:187,0 +DA:188,0 +DA:189,0 +DA:191,0 +DA:192,0 +DA:197,0 +DA:198,0 +DA:201,0 +DA:215,0 +DA:216,0 +DA:222,0 +LF:60 +LH:0 +BRDA:40,0,0,0 +BRDA:40,0,1,0 +BRDA:82,1,0,0 +BRDA:82,1,1,0 +BRDA:82,2,0,0 +BRDA:82,2,1,0 +BRDA:148,3,0,0 +BRDA:148,3,1,0 +BRDA:156,4,0,0 +BRDA:173,5,0,0 +BRDA:173,5,1,0 +BRDA:175,6,0,0 +BRDA:175,6,1,0 +BRDA:182,7,0,0 +BRDA:182,7,1,0 +BRDA:191,8,0,0 +BRDA:191,8,1,0 +BRDA:197,9,0,0 +BRDA:197,9,1,0 +BRF:19 +BRH:0 +end_of_record +TN: +SF:src/graph/types.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/graph/watcher.ts +FN:33,(anonymous_0) +FN:38,(anonymous_1) +FN:42,(anonymous_2) +FN:46,(anonymous_3) +FN:70,(anonymous_4) +FN:71,(anonymous_5) +FN:72,(anonymous_6) +FN:75,(anonymous_7) +FN:91,(anonymous_8) +FN:100,(anonymous_9) +FN:106,(anonymous_10) +FN:131,(anonymous_11) +FNF:12 +FNH:8 +FNDA:2,(anonymous_0) +FNDA:3,(anonymous_1) +FNDA:5,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:2,(anonymous_7) +FNDA:5,(anonymous_8) +FNDA:3,(anonymous_9) +FNDA:4,(anonymous_10) +FNDA:1,(anonymous_11) +DA:28,2 +DA:30,2 +DA:31,2 +DA:34,2 +DA:35,2 +DA:39,3 +DA:43,5 +DA:47,0 +DA:48,0 +DA:51,0 +DA:59,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:76,2 +DA:77,0 +DA:78,0 +DA:81,2 +DA:82,0 +DA:83,0 +DA:86,2 +DA:87,2 +DA:88,2 +DA:92,5 +DA:93,5 +DA:95,5 +DA:96,2 +DA:99,5 +DA:100,5 +DA:101,3 +DA:102,3 +DA:107,4 +DA:108,1 +DA:109,1 +DA:111,1 +DA:114,3 +DA:115,3 +DA:117,3 +DA:118,3 +DA:120,3 +DA:121,3 +DA:128,3 +DA:129,3 +DA:130,1 +DA:131,1 +DA:132,1 +DA:133,1 +DA:136,2 +LF:49 +LH:37 +BRDA:47,0,0,0 +BRDA:47,0,1,0 +BRDA:56,1,0,0 +BRDA:56,1,1,0 +BRDA:76,2,0,0 +BRDA:76,2,1,2 +BRDA:81,3,0,0 +BRDA:81,3,1,2 +BRDA:95,4,0,2 +BRDA:95,4,1,3 +BRDA:103,5,0,5 +BRDA:103,5,1,0 +BRDA:107,6,0,1 +BRDA:107,6,1,3 +BRDA:107,7,0,4 +BRDA:107,7,1,4 +BRDA:108,8,0,1 +BRDA:108,8,1,0 +BRDA:108,9,0,1 +BRDA:108,9,1,1 +BRDA:129,10,0,1 +BRDA:129,10,1,2 +BRDA:134,11,0,1 +BRDA:134,11,1,0 +BRF:24 +BRH:15 +end_of_record +TN: +SF:src/parsers/docs-parser.ts +FN:68,(anonymous_0) +FN:79,(anonymous_1) +FN:88,(anonymous_2) +FN:96,(anonymous_3) +FN:118,(anonymous_4) +FN:138,(anonymous_5) +FN:147,(anonymous_6) +FN:235,(anonymous_7) +FN:261,(anonymous_8) +FN:302,(anonymous_9) +FN:306,(anonymous_10) +FN:317,(anonymous_11) +FN:323,(anonymous_12) +FN:324,(anonymous_13) +FN:338,findMarkdownFiles +FN:350,(anonymous_15) +FNF:16 +FNH:16 +FNDA:43,(anonymous_0) +FNDA:64,(anonymous_1) +FNDA:358,(anonymous_2) +FNDA:81,(anonymous_3) +FNDA:363,(anonymous_4) +FNDA:64,(anonymous_5) +FNDA:414,(anonymous_6) +FNDA:358,(anonymous_7) +FNDA:358,(anonymous_8) +FNDA:358,(anonymous_9) +FNDA:358,(anonymous_10) +FNDA:358,(anonymous_11) +FNDA:64,(anonymous_12) +FNDA:64,(anonymous_13) +FNDA:14,findMarkdownFiles +FNDA:25,(anonymous_15) +DA:69,43 +DA:70,43 +DA:80,64 +DA:82,64 +DA:84,64 +DA:85,64 +DA:86,64 +DA:87,64 +DA:88,358 +DA:90,64 +DA:97,81 +DA:98,81 +DA:100,81 +DA:101,61 +DA:102,58 +DA:103,56 +DA:108,5 +DA:109,51 +DA:111,48 +DA:119,363 +DA:120,363 +DA:122,363 +DA:123,550 +DA:124,550 +DA:125,549 +DA:128,363 +DA:139,64 +DA:140,64 +DA:141,64 +DA:142,64 +DA:143,64 +DA:144,64 +DA:145,64 +DA:147,64 +DA:148,414 +DA:149,414 +DA:150,357 +DA:154,414 +DA:155,414 +DA:158,64 +DA:159,1973 +DA:160,1973 +DA:163,1973 +DA:164,1973 +DA:165,96 +DA:166,48 +DA:167,48 +DA:168,48 +DA:169,48 +DA:170,48 +DA:172,96 +DA:173,96 +DA:176,1877 +DA:177,92 +DA:178,92 +DA:182,1785 +DA:183,1785 +DA:184,349 +DA:185,349 +DA:188,349 +DA:189,348 +DA:190,348 +DA:191,348 +DA:192,348 +DA:193,348 +DA:198,1437 +DA:199,1429 +DA:200,1429 +DA:202,1 +DA:203,1 +DA:204,1 +DA:205,1 +DA:206,1 +DA:207,1 +DA:209,1428 +DA:210,1 +DA:211,1 +DA:212,1 +DA:213,1 +DA:214,1 +DA:215,1 +DA:219,1435 +DA:223,64 +DA:226,64 +DA:227,1 +DA:230,64 +DA:242,358 +DA:244,358 +DA:246,358 +DA:262,358 +DA:263,358 +DA:264,358 +DA:265,358 +DA:266,358 +DA:267,358 +DA:268,358 +DA:270,358 +DA:271,1622 +DA:272,1622 +DA:274,1622 +DA:275,48 +DA:276,48 +DA:277,48 +DA:278,48 +DA:279,48 +DA:280,48 +DA:283,1574 +DA:284,140 +DA:285,48 +DA:290,48 +DA:291,48 +DA:292,48 +DA:294,92 +DA:299,358 +DA:303,358 +DA:307,358 +DA:309,358 +DA:311,358 +DA:312,32 +DA:314,358 +DA:318,358 +DA:324,64 +DA:325,64 +DA:327,13 +DA:339,14 +DA:340,14 +DA:350,14 +DA:351,25 +DA:353,25 +DA:354,25 +DA:356,0 +DA:359,25 +DA:360,111 +DA:362,111 +DA:364,111 +DA:367,20 +DA:369,20 +DA:377,20 +DA:378,11 +DA:380,91 +DA:381,34 +DA:386,14 +DA:387,14 +LF:143 +LH:142 +BRDA:100,0,0,20 +BRDA:100,0,1,61 +BRDA:101,1,0,3 +BRDA:101,1,1,58 +BRDA:102,2,0,2 +BRDA:102,2,1,56 +BRDA:103,3,0,5 +BRDA:103,3,1,51 +BRDA:104,4,0,56 +BRDA:104,4,1,53 +BRDA:104,4,2,52 +BRDA:109,5,0,3 +BRDA:109,5,1,48 +BRDA:109,6,0,51 +BRDA:109,6,1,48 +BRDA:124,7,0,549 +BRDA:124,7,1,1 +BRDA:124,8,0,550 +BRDA:124,8,1,550 +BRDA:149,9,0,357 +BRDA:149,9,1,57 +BRDA:149,10,0,414 +BRDA:149,10,1,64 +BRDA:164,11,0,96 +BRDA:164,11,1,1877 +BRDA:165,12,0,48 +BRDA:165,12,1,48 +BRDA:168,13,0,48 +BRDA:168,13,1,0 +BRDA:176,14,0,92 +BRDA:176,14,1,1785 +BRDA:183,15,0,349 +BRDA:183,15,1,1436 +BRDA:188,16,0,348 +BRDA:188,16,1,1 +BRDA:198,17,0,1429 +BRDA:198,17,1,8 +BRDA:198,18,0,1437 +BRDA:198,18,1,1429 +BRDA:199,19,0,1429 +BRDA:199,19,1,349 +BRDA:200,20,0,1 +BRDA:200,20,1,1428 +BRDA:200,21,0,1429 +BRDA:200,21,1,1 +BRDA:202,22,0,1 +BRDA:202,22,1,0 +BRDA:209,23,0,1 +BRDA:209,23,1,1427 +BRDA:209,24,0,1428 +BRDA:209,24,1,1 +BRDA:209,24,2,1 +BRDA:210,25,0,1 +BRDA:210,25,1,0 +BRDA:226,26,0,1 +BRDA:226,26,1,63 +BRDA:274,27,0,48 +BRDA:274,27,1,1574 +BRDA:274,28,0,1622 +BRDA:274,28,1,1482 +BRDA:277,29,0,48 +BRDA:277,29,1,0 +BRDA:283,30,0,140 +BRDA:283,30,1,1434 +BRDA:284,31,0,48 +BRDA:284,31,1,92 +BRDA:318,32,0,358 +BRDA:318,32,1,1 +BRDA:324,33,0,64 +BRDA:324,33,1,59 +BRDA:325,34,0,51 +BRDA:325,34,1,13 +BRDA:351,35,0,0 +BRDA:351,35,1,25 +BRDA:360,36,0,0 +BRDA:360,36,1,111 +BRDA:364,37,0,20 +BRDA:364,37,1,91 +BRDA:369,38,0,20 +BRDA:369,38,1,20 +BRDA:369,38,2,20 +BRDA:369,38,3,20 +BRDA:369,38,4,20 +BRDA:369,38,5,20 +BRDA:369,38,6,20 +BRDA:369,38,7,20 +BRDA:377,39,0,11 +BRDA:377,39,1,9 +BRDA:377,40,0,20 +BRDA:377,40,1,9 +BRDA:380,41,0,34 +BRDA:380,41,1,57 +BRDA:380,42,0,91 +BRDA:380,42,1,91 +BRF:94 +BRH:88 +end_of_record +TN: +SF:src/parsers/parser-interface.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/parsers/parser-registry.ts +FN:7,(anonymous_0) +FN:13,(anonymous_1) +FN:18,(anonymous_2) +FNF:3 +FNH:3 +FNDA:494,(anonymous_0) +FNDA:5,(anonymous_1) +FNDA:2,(anonymous_2) +DA:5,127 +DA:8,494 +DA:9,495 +DA:14,5 +DA:15,5 +DA:19,2 +DA:20,2 +DA:21,1 +DA:23,1 +LF:9 +LH:9 +BRDA:15,0,0,5 +BRDA:15,0,1,2 +BRDA:20,1,0,1 +BRDA:20,1,1,1 +BRF:4 +BRH:4 +end_of_record +TN: +SF:src/parsers/regex-language-parsers.ts +FN:8,(anonymous_0) +FN:27,(anonymous_1) +FN:49,(anonymous_2) +FN:72,(anonymous_3) +FN:75,(anonymous_4) +FN:100,(anonymous_5) +FN:103,(anonymous_6) +FN:120,(anonymous_7) +FN:123,(anonymous_8) +FN:145,(anonymous_9) +FN:148,(anonymous_10) +FN:173,(anonymous_11) +FN:176,(anonymous_12) +FN:193,(anonymous_13) +FN:196,(anonymous_14) +FN:218,(anonymous_15) +FN:221,(anonymous_16) +FN:238,(anonymous_17) +FN:241,(anonymous_18) +FN:258,(anonymous_19) +FN:261,(anonymous_20) +FN:283,(anonymous_21) +FN:286,(anonymous_22) +FN:303,(anonymous_23) +FN:306,(anonymous_24) +FN:326,(anonymous_25) +FN:330,(anonymous_26) +FNF:27 +FNH:27 +FNDA:38,(anonymous_0) +FNDA:32,(anonymous_1) +FNDA:9,(anonymous_2) +FNDA:9,(anonymous_3) +FNDA:38,(anonymous_4) +FNDA:9,(anonymous_5) +FNDA:38,(anonymous_6) +FNDA:9,(anonymous_7) +FNDA:38,(anonymous_8) +FNDA:9,(anonymous_9) +FNDA:37,(anonymous_10) +FNDA:9,(anonymous_11) +FNDA:37,(anonymous_12) +FNDA:9,(anonymous_13) +FNDA:37,(anonymous_14) +FNDA:9,(anonymous_15) +FNDA:44,(anonymous_16) +FNDA:9,(anonymous_17) +FNDA:44,(anonymous_18) +FNDA:9,(anonymous_19) +FNDA:44,(anonymous_20) +FNDA:11,(anonymous_21) +FNDA:55,(anonymous_22) +FNDA:11,(anonymous_23) +FNDA:55,(anonymous_24) +FNDA:11,(anonymous_25) +FNDA:55,(anonymous_26) +DA:9,38 +DA:10,38 +DA:16,38 +DA:28,32 +DA:29,32 +DA:31,32 +DA:32,123 +DA:33,123 +DA:34,1764 +DA:35,42 +DA:36,42 +DA:37,1722 +DA:38,45 +DA:39,45 +DA:40,30 +DA:46,2 +DA:50,9 +DA:51,9 +DA:53,9 +DA:54,21 +DA:55,21 +DA:56,8 +DA:58,13 +DA:59,21 +DA:60,3 +DA:64,6 +DA:69,124 +DA:70,124 +DA:73,9 +DA:75,9 +DA:76,38 +DA:77,38 +DA:78,3 +DA:86,38 +DA:87,38 +DA:88,3 +DA:97,9 +DA:101,9 +DA:103,9 +DA:104,38 +DA:105,38 +DA:106,33 +DA:109,5 +DA:117,9 +DA:121,9 +DA:123,9 +DA:124,38 +DA:125,38 +DA:126,34 +DA:129,4 +DA:137,9 +DA:142,124 +DA:143,124 +DA:146,9 +DA:148,9 +DA:149,37 +DA:150,37 +DA:151,2 +DA:159,37 +DA:160,37 +DA:161,1 +DA:170,9 +DA:174,9 +DA:176,9 +DA:177,37 +DA:178,37 +DA:179,33 +DA:182,4 +DA:190,9 +DA:194,9 +DA:196,9 +DA:197,37 +DA:198,37 +DA:199,34 +DA:202,3 +DA:210,9 +DA:215,124 +DA:216,124 +DA:219,9 +DA:221,9 +DA:222,44 +DA:223,44 +DA:224,41 +DA:227,3 +DA:235,9 +DA:239,9 +DA:241,9 +DA:242,44 +DA:243,44 +DA:244,38 +DA:247,6 +DA:255,9 +DA:259,9 +DA:261,9 +DA:262,44 +DA:263,44 +DA:264,39 +DA:267,5 +DA:275,9 +DA:280,124 +DA:281,124 +DA:284,11 +DA:286,11 +DA:287,55 +DA:288,55 +DA:289,50 +DA:292,5 +DA:300,11 +DA:304,11 +DA:306,11 +DA:308,55 +DA:311,55 +DA:312,47 +DA:315,8 +DA:323,11 +DA:327,11 +DA:328,11 +DA:330,11 +DA:332,55 +DA:335,55 +DA:336,49 +DA:339,6 +DA:347,11 +LF:123 +LH:123 +BRDA:34,0,0,42 +BRDA:34,0,1,1722 +BRDA:37,1,0,45 +BRDA:37,1,1,1677 +BRDA:39,2,0,30 +BRDA:39,2,1,15 +BRDA:39,3,0,45 +BRDA:39,3,1,42 +BRDA:50,4,0,9 +BRDA:50,4,1,0 +BRDA:51,5,0,9 +BRDA:51,5,1,9 +BRDA:55,6,0,8 +BRDA:55,6,1,13 +BRDA:58,7,0,13 +BRDA:58,7,1,3 +BRDA:59,8,0,3 +BRDA:59,8,1,18 +BRDA:77,9,0,3 +BRDA:77,9,1,35 +BRDA:87,10,0,3 +BRDA:87,10,1,35 +BRDA:105,11,0,33 +BRDA:105,11,1,5 +BRDA:125,12,0,34 +BRDA:125,12,1,4 +BRDA:150,13,0,2 +BRDA:150,13,1,35 +BRDA:160,14,0,1 +BRDA:160,14,1,36 +BRDA:160,15,0,37 +BRDA:160,15,1,2 +BRDA:160,15,2,2 +BRDA:178,16,0,33 +BRDA:178,16,1,4 +BRDA:183,17,0,1 +BRDA:183,17,1,3 +BRDA:198,18,0,34 +BRDA:198,18,1,3 +BRDA:223,19,0,41 +BRDA:223,19,1,3 +BRDA:243,20,0,38 +BRDA:243,20,1,6 +BRDA:248,21,0,2 +BRDA:248,21,1,4 +BRDA:263,22,0,39 +BRDA:263,22,1,5 +BRDA:288,23,0,50 +BRDA:288,23,1,5 +BRDA:311,24,0,47 +BRDA:311,24,1,8 +BRDA:316,25,0,1 +BRDA:316,25,1,7 +BRDA:335,26,0,49 +BRDA:335,26,1,6 +BRDA:335,27,0,55 +BRDA:335,27,1,9 +BRF:57 +BRH:56 +end_of_record +TN: +SF:src/parsers/tree-sitter-parser.ts +FN:23,tryRequire +FN:36,resolveLanguage +FN:60,walk +FN:69,fieldText +FN:89,(anonymous_4) +FN:110,(anonymous_5) +FN:114,(anonymous_6) +FN:144,(anonymous_7) +FN:146,(anonymous_8) +FN:161,(anonymous_9) +FN:164,(anonymous_10) +FN:191,(anonymous_11) +FN:194,(anonymous_12) +FN:233,(anonymous_13) +FN:236,(anonymous_14) +FN:295,(anonymous_15) +FN:298,(anonymous_16) +FN:375,(anonymous_17) +FN:378,(anonymous_18) +FN:437,getTreeSitterParsers +FN:452,checkTreeSitterAvailability +FNF:21 +FNH:5 +FNDA:16,tryRequire +FNDA:0,resolveLanguage +FNDA:0,walk +FNDA:0,fieldText +FNDA:492,(anonymous_4) +FNDA:492,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:0,(anonymous_18) +FNDA:246,getTreeSitterParsers +FNDA:123,checkTreeSitterAvailability +DA:18,4 +DA:24,16 +DA:25,16 +DA:27,16 +DA:37,0 +DA:38,0 +DA:39,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:70,0 +DA:84,16 +DA:86,16 +DA:90,492 +DA:91,16 +DA:93,16 +DA:94,16 +DA:96,0 +DA:97,0 +DA:98,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:106,0 +DA:111,492 +DA:115,0 +DA:117,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:133,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:149,0 +DA:157,4 +DA:158,4 +DA:159,4 +DA:162,0 +DA:164,0 +DA:165,0 +DA:168,0 +DA:169,0 +DA:170,0 +DA:176,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:187,0 +DA:191,0 +DA:192,0 +DA:193,0 +DA:194,0 +DA:195,0 +DA:204,0 +DA:207,0 +DA:208,0 +DA:209,0 +DA:216,0 +DA:221,0 +DA:229,4 +DA:230,4 +DA:231,4 +DA:234,0 +DA:236,0 +DA:237,0 +DA:240,0 +DA:241,0 +DA:242,0 +DA:243,0 +DA:249,0 +DA:252,0 +DA:253,0 +DA:254,0 +DA:255,0 +DA:256,0 +DA:257,0 +DA:263,0 +DA:267,0 +DA:268,0 +DA:269,0 +DA:270,0 +DA:271,0 +DA:278,0 +DA:283,0 +DA:291,4 +DA:292,4 +DA:293,4 +DA:296,0 +DA:298,0 +DA:299,0 +DA:301,0 +DA:302,0 +DA:303,0 +DA:309,0 +DA:313,0 +DA:314,0 +DA:315,0 +DA:321,0 +DA:324,0 +DA:325,0 +DA:326,0 +DA:332,0 +DA:336,0 +DA:337,0 +DA:338,0 +DA:339,0 +DA:340,0 +DA:348,0 +DA:353,0 +DA:361,8 +DA:362,8 +DA:363,8 +DA:365,8 +DA:376,0 +DA:378,0 +DA:379,0 +DA:384,0 +DA:385,0 +DA:386,0 +DA:392,0 +DA:396,0 +DA:397,0 +DA:398,0 +DA:399,0 +DA:405,0 +DA:409,0 +DA:413,0 +DA:414,0 +DA:421,0 +DA:426,0 +DA:435,4 +DA:438,246 +DA:439,4 +DA:445,4 +DA:453,123 +DA:454,123 +DA:455,123 +DA:456,492 +DA:458,123 +LF:144 +LH:33 +BRDA:37,0,0,0 +BRDA:37,0,1,0 +BRDA:38,1,0,0 +BRDA:38,1,1,0 +BRDA:64,2,0,0 +BRDA:64,2,1,0 +BRDA:70,3,0,0 +BRDA:70,3,1,0 +BRDA:90,4,0,476 +BRDA:90,4,1,16 +BRDA:94,5,0,16 +BRDA:94,5,1,0 +BRDA:98,6,0,0 +BRDA:98,6,1,0 +BRDA:115,7,0,0 +BRDA:115,7,1,0 +BRDA:115,8,0,0 +BRDA:115,8,1,0 +BRDA:147,9,0,0 +BRDA:147,9,1,0 +BRDA:165,10,0,0 +BRDA:165,10,1,0 +BRDA:165,10,2,0 +BRDA:165,10,3,0 +BRDA:165,10,4,0 +BRDA:169,11,0,0 +BRDA:169,11,1,0 +BRDA:180,12,0,0 +BRDA:180,12,1,0 +BRDA:192,13,0,0 +BRDA:192,13,1,0 +BRDA:192,14,0,0 +BRDA:192,14,1,0 +BRDA:193,15,0,0 +BRDA:193,15,1,0 +BRDA:194,16,0,0 +BRDA:194,16,1,0 +BRDA:194,17,0,0 +BRDA:194,17,1,0 +BRDA:194,18,0,0 +BRDA:194,18,1,0 +BRDA:208,19,0,0 +BRDA:208,19,1,0 +BRDA:237,20,0,0 +BRDA:237,20,1,0 +BRDA:237,20,2,0 +BRDA:237,20,3,0 +BRDA:241,21,0,0 +BRDA:241,21,1,0 +BRDA:242,22,0,0 +BRDA:242,22,1,0 +BRDA:254,23,0,0 +BRDA:254,23,1,0 +BRDA:256,24,0,0 +BRDA:256,24,1,0 +BRDA:267,25,0,0 +BRDA:267,25,1,0 +BRDA:268,26,0,0 +BRDA:268,26,1,0 +BRDA:270,27,0,0 +BRDA:270,27,1,0 +BRDA:299,28,0,0 +BRDA:299,28,1,0 +BRDA:299,28,2,0 +BRDA:299,28,3,0 +BRDA:299,28,4,0 +BRDA:302,29,0,0 +BRDA:302,29,1,0 +BRDA:314,30,0,0 +BRDA:314,30,1,0 +BRDA:325,31,0,0 +BRDA:325,31,1,0 +BRDA:337,32,0,0 +BRDA:337,32,1,0 +BRDA:339,33,0,0 +BRDA:339,33,1,0 +BRDA:379,34,0,0 +BRDA:379,34,1,0 +BRDA:379,34,2,0 +BRDA:379,34,3,0 +BRDA:379,34,4,0 +BRDA:379,34,5,0 +BRDA:379,34,6,0 +BRDA:385,35,0,0 +BRDA:385,35,1,0 +BRDA:387,36,0,0 +BRDA:387,36,1,0 +BRDA:397,37,0,0 +BRDA:397,37,1,0 +BRDA:398,38,0,0 +BRDA:398,38,1,0 +BRDA:413,39,0,0 +BRDA:413,39,1,0 +BRDA:438,40,0,242 +BRDA:438,40,1,4 +BRF:95 +BRH:5 +end_of_record +TN: +SF:src/parsers/tree-sitter-typescript-parser.ts +FN:33,tryRequire +FN:45,loadJsGrammar +FN:58,loadTsGrammar +FN:87,walkWithScope +FN:114,extractSymbols +FN:117,(anonymous_5) +FN:275,(anonymous_6) +FN:295,(anonymous_7) +FN:299,(anonymous_8) +FN:349,getTreeSitterTypeScriptParser +FN:354,getTreeSitterTSXParser +FN:360,checkTsTreeSitterAvailability +FN:385,(anonymous_12) +FN:405,(anonymous_13) +FN:409,(anonymous_14) +FN:449,getTreeSitterJavaScriptParser +FN:454,getTreeSitterJSXParser +FN:460,checkJsTreeSitterAvailability +FNF:18 +FNH:10 +FNDA:12,tryRequire +FNDA:0,loadJsGrammar +FNDA:0,loadTsGrammar +FNDA:0,walkWithScope +FNDA:0,extractSymbols +FNDA:0,(anonymous_5) +FNDA:246,(anonymous_6) +FNDA:246,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:123,getTreeSitterTypeScriptParser +FNDA:123,getTreeSitterTSXParser +FNDA:123,checkTsTreeSitterAvailability +FNDA:123,(anonymous_12) +FNDA:123,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:123,getTreeSitterJavaScriptParser +FNDA:0,getTreeSitterJSXParser +FNDA:123,checkJsTreeSitterAvailability +DA:28,4 +DA:34,12 +DA:35,12 +DA:37,12 +DA:46,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:93,0 +DA:94,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:115,0 +DA:117,0 +DA:118,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:132,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:149,0 +DA:159,0 +DA:165,0 +DA:166,0 +DA:167,0 +DA:169,0 +DA:170,0 +DA:179,0 +DA:185,0 +DA:186,0 +DA:187,0 +DA:194,0 +DA:199,0 +DA:200,0 +DA:201,0 +DA:208,0 +DA:213,0 +DA:214,0 +DA:215,0 +DA:222,0 +DA:227,0 +DA:228,0 +DA:229,0 +DA:236,0 +DA:242,0 +DA:243,0 +DA:244,0 +DA:245,0 +DA:252,0 +DA:257,0 +DA:271,8 +DA:273,8 +DA:276,246 +DA:277,8 +DA:279,8 +DA:280,8 +DA:282,0 +DA:283,0 +DA:285,0 +DA:286,0 +DA:287,0 +DA:288,0 +DA:289,0 +DA:291,0 +DA:296,246 +DA:300,0 +DA:301,0 +DA:307,0 +DA:308,0 +DA:309,0 +DA:315,0 +DA:328,4 +DA:329,4 +DA:330,4 +DA:337,4 +DA:338,4 +DA:339,4 +DA:346,4 +DA:347,4 +DA:350,123 +DA:351,123 +DA:355,123 +DA:356,123 +DA:364,123 +DA:381,4 +DA:383,4 +DA:386,123 +DA:387,4 +DA:389,4 +DA:390,4 +DA:392,0 +DA:393,0 +DA:395,0 +DA:396,0 +DA:397,0 +DA:398,0 +DA:399,0 +DA:401,0 +DA:406,123 +DA:410,0 +DA:411,0 +DA:417,0 +DA:418,0 +DA:419,0 +DA:426,0 +DA:436,4 +DA:437,4 +DA:441,0 +DA:442,0 +DA:446,4 +DA:447,4 +DA:450,123 +DA:451,123 +DA:455,0 +DA:456,0 +DA:465,123 +DA:466,123 +LF:135 +LH:39 +BRDA:47,0,0,0 +BRDA:47,0,1,0 +BRDA:48,1,0,0 +BRDA:48,1,1,0 +BRDA:61,2,0,0 +BRDA:61,2,1,0 +BRDA:62,3,0,0 +BRDA:62,3,1,0 +BRDA:66,4,0,0 +BRDA:66,4,1,0 +BRDA:68,5,0,0 +BRDA:68,5,1,0 +BRDA:69,6,0,0 +BRDA:69,6,1,0 +BRDA:90,7,0,0 +BRDA:94,8,0,0 +BRDA:94,8,1,0 +BRDA:95,9,0,0 +BRDA:95,9,1,0 +BRDA:95,9,2,0 +BRDA:100,10,0,0 +BRDA:100,10,1,0 +BRDA:107,11,0,0 +BRDA:107,11,1,0 +BRDA:118,12,0,0 +BRDA:118,12,1,0 +BRDA:118,12,2,0 +BRDA:118,12,3,0 +BRDA:118,12,4,0 +BRDA:118,12,5,0 +BRDA:118,12,6,0 +BRDA:118,12,7,0 +BRDA:118,12,8,0 +BRDA:118,12,9,0 +BRDA:118,12,10,0 +BRDA:118,12,11,0 +BRDA:123,13,0,0 +BRDA:123,13,1,0 +BRDA:127,14,0,0 +BRDA:127,14,1,0 +BRDA:140,15,0,0 +BRDA:140,15,1,0 +BRDA:143,16,0,0 +BRDA:143,16,1,0 +BRDA:143,17,0,0 +BRDA:143,17,1,0 +BRDA:144,18,0,0 +BRDA:144,18,1,0 +BRDA:145,19,0,0 +BRDA:145,19,1,0 +BRDA:145,19,2,0 +BRDA:166,20,0,0 +BRDA:166,20,1,0 +BRDA:169,21,0,0 +BRDA:169,21,1,0 +BRDA:186,22,0,0 +BRDA:186,22,1,0 +BRDA:190,23,0,0 +BRDA:190,23,1,0 +BRDA:200,24,0,0 +BRDA:200,24,1,0 +BRDA:214,25,0,0 +BRDA:214,25,1,0 +BRDA:228,26,0,0 +BRDA:228,26,1,0 +BRDA:243,27,0,0 +BRDA:243,27,1,0 +BRDA:276,28,0,238 +BRDA:276,28,1,8 +BRDA:280,29,0,8 +BRDA:280,29,1,0 +BRDA:283,30,0,0 +BRDA:283,30,1,0 +BRDA:300,31,0,0 +BRDA:300,31,1,0 +BRDA:300,32,0,0 +BRDA:300,32,1,0 +BRDA:350,33,0,4 +BRDA:350,33,1,119 +BRDA:355,34,0,4 +BRDA:355,34,1,119 +BRDA:386,35,0,119 +BRDA:386,35,1,4 +BRDA:390,36,0,4 +BRDA:390,36,1,0 +BRDA:393,37,0,0 +BRDA:393,37,1,0 +BRDA:410,38,0,0 +BRDA:410,38,1,0 +BRDA:410,39,0,0 +BRDA:410,39,1,0 +BRDA:450,40,0,4 +BRDA:450,40,1,119 +BRDA:455,41,0,0 +BRDA:455,41,1,0 +BRF:95 +BRH:12 +end_of_record +TN: +SF:src/parsers/typescript-parser.ts +FN:112,(anonymous_0) +FN:118,(anonymous_1) +FN:159,(anonymous_2) +FN:182,(anonymous_3) +FN:196,(anonymous_4) +FN:217,(anonymous_5) +FN:221,(anonymous_6) +FN:273,(anonymous_7) +FN:277,(anonymous_8) +FN:296,(anonymous_9) +FN:300,(anonymous_10) +FN:314,(anonymous_11) +FN:316,(anonymous_12) +FN:318,(anonymous_13) +FN:336,(anonymous_14) +FN:340,(anonymous_15) +FN:366,(anonymous_16) +FN:367,(anonymous_17) +FN:382,(anonymous_18) +FN:404,(anonymous_19) +FN:408,(anonymous_20) +FN:447,(anonymous_21) +FN:452,(anonymous_22) +FN:483,(anonymous_23) +FNF:24 +FNH:18 +FNDA:0,(anonymous_0) +FNDA:3,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:6,(anonymous_3) +FNDA:2,(anonymous_4) +FNDA:3,(anonymous_5) +FNDA:6,(anonymous_6) +FNDA:3,(anonymous_7) +FNDA:6,(anonymous_8) +FNDA:3,(anonymous_9) +FNDA:6,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:3,(anonymous_14) +FNDA:6,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:4,(anonymous_18) +FNDA:3,(anonymous_19) +FNDA:6,(anonymous_20) +FNDA:3,(anonymous_21) +FNDA:6,(anonymous_22) +FNDA:3,(anonymous_23) +DA:115,0 +DA:119,3 +DA:120,3 +DA:121,3 +DA:122,3 +DA:123,3 +DA:124,3 +DA:127,3 +DA:128,3 +DA:129,3 +DA:130,3 +DA:131,3 +DA:132,3 +DA:133,3 +DA:135,3 +DA:160,3 +DA:161,3 +DA:164,3 +DA:176,3 +DA:182,3 +DA:183,6 +DA:185,18 +DA:186,2 +DA:189,2 +DA:190,0 +DA:194,2 +DA:196,2 +DA:198,2 +DA:200,2 +DA:214,3 +DA:218,3 +DA:219,3 +DA:221,3 +DA:223,6 +DA:226,6 +DA:227,0 +DA:242,6 +DA:243,6 +DA:244,0 +DA:256,6 +DA:257,6 +DA:258,0 +DA:270,3 +DA:274,3 +DA:275,3 +DA:277,3 +DA:278,6 +DA:279,6 +DA:281,1 +DA:293,3 +DA:297,3 +DA:298,3 +DA:300,3 +DA:302,6 +DA:305,6 +DA:306,0 +DA:307,0 +DA:308,0 +DA:310,0 +DA:314,0 +DA:317,0 +DA:318,0 +DA:320,0 +DA:324,0 +DA:333,3 +DA:337,3 +DA:338,3 +DA:340,3 +DA:342,6 +DA:343,6 +DA:344,0 +DA:353,6 +DA:354,6 +DA:355,3 +DA:364,6 +DA:365,6 +DA:366,0 +DA:367,0 +DA:368,0 +DA:379,3 +DA:383,4 +DA:384,4 +DA:386,4 +DA:387,4 +DA:388,4 +DA:389,198 +DA:390,4 +DA:391,4 +DA:392,194 +DA:393,4 +DA:394,4 +DA:395,4 +DA:401,0 +DA:405,3 +DA:406,3 +DA:408,3 +DA:410,6 +DA:411,6 +DA:413,6 +DA:414,0 +DA:415,0 +DA:418,0 +DA:419,0 +DA:420,0 +DA:421,0 +DA:422,0 +DA:423,0 +DA:424,0 +DA:425,0 +DA:426,0 +DA:429,0 +DA:441,3 +DA:448,3 +DA:449,3 +DA:452,3 +DA:454,6 +DA:455,6 +DA:457,6 +DA:458,0 +DA:462,0 +DA:463,0 +DA:464,0 +DA:465,0 +DA:466,0 +DA:470,0 +DA:480,3 +DA:485,3 +DA:486,3 +DA:487,125 +DA:488,125 +DA:489,125 +DA:491,3 +LF:132 +LH:94 +BRDA:120,0,0,3 +BRDA:120,0,1,0 +BRDA:189,1,0,0 +BRDA:189,1,1,2 +BRDA:194,2,0,2 +BRDA:194,2,1,0 +BRDA:203,3,0,0 +BRDA:203,3,1,2 +BRDA:226,4,0,0 +BRDA:226,4,1,6 +BRDA:235,5,0,0 +BRDA:235,5,1,0 +BRDA:243,6,0,0 +BRDA:243,6,1,6 +BRDA:257,7,0,0 +BRDA:257,7,1,6 +BRDA:279,8,0,1 +BRDA:279,8,1,5 +BRDA:279,9,0,6 +BRDA:279,9,1,1 +BRDA:284,10,0,1 +BRDA:284,10,1,0 +BRDA:284,11,0,0 +BRDA:284,11,1,0 +BRDA:305,12,0,0 +BRDA:305,12,1,6 +BRDA:307,13,0,0 +BRDA:307,13,1,0 +BRDA:307,13,2,0 +BRDA:308,14,0,0 +BRDA:308,14,1,0 +BRDA:308,15,0,0 +BRDA:308,15,1,0 +BRDA:311,16,0,0 +BRDA:311,16,1,0 +BRDA:317,17,0,0 +BRDA:317,17,1,0 +BRDA:343,18,0,0 +BRDA:343,18,1,6 +BRDA:354,19,0,3 +BRDA:354,19,1,3 +BRDA:365,20,0,0 +BRDA:365,20,1,6 +BRDA:366,21,0,0 +BRDA:366,21,1,0 +BRDA:389,22,0,4 +BRDA:389,22,1,194 +BRDA:392,23,0,4 +BRDA:392,23,1,190 +BRDA:394,24,0,4 +BRDA:394,24,1,0 +BRDA:394,25,0,4 +BRDA:394,25,1,4 +BRDA:413,26,0,0 +BRDA:413,26,1,6 +BRDA:419,27,0,0 +BRDA:419,27,1,0 +BRDA:421,28,0,0 +BRDA:421,28,1,0 +BRDA:423,29,0,0 +BRDA:423,29,1,0 +BRDA:425,30,0,0 +BRDA:425,30,1,0 +BRDA:457,31,0,0 +BRDA:457,31,1,6 +BRDA:464,32,0,0 +BRDA:464,32,1,0 +BRF:67 +BRH:26 +end_of_record +TN: +SF:src/response/budget.ts +FN:31,makeBudget +FN:42,estimateTokens +FN:47,fillSlot +FNF:3 +FNH:3 +FNDA:137,makeBudget +FNDA:158,estimateTokens +FNDA:3,fillSlot +DA:3,4 +DA:23,4 +DA:35,137 +DA:43,158 +DA:44,158 +DA:52,3 +DA:53,3 +DA:55,3 +DA:56,10 +DA:57,10 +DA:58,5 +DA:61,5 +DA:62,5 +DA:65,3 +LF:14 +LH:14 +BRDA:36,0,0,137 +BRDA:36,0,1,136 +BRDA:38,1,0,137 +BRDA:38,1,1,136 +BRDA:43,2,0,23 +BRDA:43,2,1,135 +BRDA:57,3,0,5 +BRDA:57,3,1,5 +BRF:8 +BRH:8 +end_of_record +TN: +SF:src/response/schemas.ts +FN:389,applyFieldPriority +FN:396,(anonymous_1) +FN:396,(anonymous_2) +FN:405,(anonymous_3) +FN:406,(anonymous_4) +FNF:5 +FNH:5 +FNDA:16,applyFieldPriority +FNDA:80,(anonymous_1) +FNDA:42,(anonymous_2) +FNDA:23,(anonymous_3) +FNDA:5,(anonymous_4) +DA:9,4 +DA:387,4 +DA:394,16 +DA:395,16 +DA:396,80 +DA:399,16 +DA:400,22 +DA:401,14 +DA:404,8 +DA:405,23 +DA:406,5 +DA:408,8 +DA:409,5 +DA:410,0 +DA:412,5 +DA:413,0 +DA:415,5 +DA:416,4 +DA:421,16 +LF:19 +LH:17 +BRDA:400,0,0,14 +BRDA:400,0,1,8 +BRDA:409,1,0,0 +BRDA:409,1,1,5 +BRDA:412,2,0,0 +BRDA:412,2,1,5 +BRDA:415,3,0,4 +BRDA:415,3,1,1 +BRF:8 +BRH:6 +end_of_record +TN: +SF:src/response/shaper.ts +FN:30,truncateString +FN:45,shapeValue +FN:63,(anonymous_2) +FN:73,(anonymous_3) +FN:95,formatResponse +FN:137,errorResponse +FNF:6 +FNH:6 +FNDA:919,truncateString +FNDA:2206,shapeValue +FNDA:291,(anonymous_2) +FNDA:1783,(anonymous_3) +FNDA:132,formatResponse +FNDA:21,errorResponse +DA:31,919 +DA:32,919 +DA:34,0 +DA:46,2206 +DA:48,2206 +DA:49,2206 +DA:51,2206 +DA:53,2206 +DA:54,1 +DA:57,2205 +DA:58,919 +DA:61,1286 +DA:62,201 +DA:63,291 +DA:64,201 +DA:65,0 +DA:67,201 +DA:70,1085 +DA:71,449 +DA:72,449 +DA:73,1783 +DA:75,449 +DA:76,449 +DA:77,0 +DA:79,449 +DA:82,636 +DA:102,132 +DA:103,132 +DA:105,132 +DA:112,17 +DA:113,17 +DA:114,12 +DA:118,132 +DA:143,21 +LF:34 +LH:31 +BRDA:31,0,0,919 +BRDA:31,0,1,0 +BRDA:31,1,0,919 +BRDA:31,1,1,373 +BRDA:45,2,0,2206 +BRDA:46,3,0,1301 +BRDA:46,3,1,905 +BRDA:48,4,0,5 +BRDA:48,4,1,2201 +BRDA:48,5,0,1301 +BRDA:48,5,1,900 +BRDA:49,6,0,5 +BRDA:49,6,1,2201 +BRDA:49,7,0,1301 +BRDA:49,7,1,900 +BRDA:51,8,0,5 +BRDA:51,8,1,2201 +BRDA:51,9,0,1301 +BRDA:51,9,1,900 +BRDA:53,10,0,1 +BRDA:53,10,1,2205 +BRDA:57,11,0,919 +BRDA:57,11,1,1286 +BRDA:61,12,0,201 +BRDA:61,12,1,1085 +BRDA:64,13,0,0 +BRDA:64,13,1,201 +BRDA:70,14,0,449 +BRDA:70,14,1,636 +BRDA:70,15,0,1085 +BRDA:70,15,1,1012 +BRDA:76,16,0,0 +BRDA:76,16,1,449 +BRDA:98,17,0,132 +BRDA:105,18,0,17 +BRDA:105,18,1,115 +BRDA:106,19,0,132 +BRDA:106,19,1,75 +BRDA:106,19,2,17 +BRDA:106,19,3,17 +BRDA:106,19,4,17 +BRDA:113,20,0,12 +BRDA:113,20,1,5 +BRDA:124,21,0,0 +BRDA:124,21,1,132 +BRDA:141,22,0,21 +BRF:46 +BRH:42 +end_of_record +TN: +SF:src/response/summarizer.ts +FN:16,(anonymous_0) +FN:18,(anonymous_1) +FN:22,(anonymous_2) +FN:34,(anonymous_3) +FN:40,(anonymous_4) +FN:88,(anonymous_5) +FNF:6 +FNH:4 +FNDA:123,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:5,(anonymous_2) +FNDA:5,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:5,(anonymous_5) +DA:14,123 +DA:16,123 +DA:19,0 +DA:23,5 +DA:24,5 +DA:25,0 +DA:28,5 +DA:29,5 +DA:30,5 +DA:31,5 +DA:35,5 +DA:36,5 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:57,0 +DA:58,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:71,0 +DA:76,0 +DA:80,0 +DA:82,0 +DA:84,0 +DA:89,5 +DA:90,5 +DA:91,5 +DA:93,5 +DA:94,3 +DA:95,3 +DA:96,3 +DA:97,3 +DA:100,2 +DA:101,2 +DA:104,0 +DA:105,0 +DA:108,0 +LF:43 +LH:20 +BRDA:24,0,0,0 +BRDA:24,0,1,5 +BRDA:29,1,0,5 +BRDA:29,1,1,5 +BRDA:35,2,0,5 +BRDA:35,2,1,0 +BRDA:52,3,0,0 +BRDA:52,3,1,0 +BRDA:57,4,0,0 +BRDA:57,4,1,0 +BRDA:62,5,0,0 +BRDA:62,5,1,0 +BRDA:66,6,0,0 +BRDA:66,6,1,0 +BRDA:66,7,0,0 +BRDA:66,7,1,0 +BRDA:68,8,0,0 +BRDA:68,8,1,0 +BRDA:71,9,0,0 +BRDA:71,9,1,0 +BRDA:72,10,0,0 +BRDA:72,10,1,0 +BRDA:72,10,2,0 +BRDA:89,11,0,5 +BRDA:89,11,1,0 +BRDA:90,12,0,5 +BRDA:90,12,1,0 +BRDA:91,13,0,5 +BRDA:91,13,1,0 +BRDA:93,14,0,3 +BRDA:93,14,1,2 +BRDA:94,15,0,3 +BRDA:94,15,1,1 +BRDA:95,16,0,3 +BRDA:95,16,1,3 +BRDA:96,17,0,3 +BRDA:96,17,1,3 +BRDA:97,18,0,3 +BRDA:97,18,1,0 +BRDA:97,19,0,3 +BRDA:97,19,1,0 +BRDA:100,20,0,2 +BRDA:100,20,1,0 +BRDA:101,21,0,2 +BRDA:101,21,1,0 +BRDA:104,22,0,0 +BRDA:104,22,1,0 +BRDA:105,23,0,0 +BRDA:105,23,1,0 +BRF:49 +BRH:19 +end_of_record +TN: +SF:src/tools/contract-validator.ts +FN:63,validateToolArgs +FN:80,(anonymous_1) +FN:82,(anonymous_2) +FN:102,(anonymous_3) +FN:114,(anonymous_4) +FN:119,(anonymous_5) +FN:120,(anonymous_6) +FNF:7 +FNH:7 +FNDA:3,validateToolArgs +FNDA:6,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:3,(anonymous_3) +FNDA:3,(anonymous_4) +FNDA:3,(anonymous_5) +FNDA:3,(anonymous_6) +DA:64,3 +DA:66,3 +DA:67,0 +DA:77,3 +DA:79,3 +DA:80,6 +DA:81,3 +DA:83,3 +DA:89,3 +DA:90,3 +DA:92,3 +DA:93,1 +DA:102,2 +DA:103,3 +DA:104,3 +DA:111,2 +DA:113,3 +DA:115,3 +DA:116,3 +DA:117,3 +DA:119,3 +DA:120,3 +DA:122,3 +LF:23 +LH:22 +BRDA:66,0,0,0 +BRDA:66,0,1,3 +BRDA:77,1,0,3 +BRDA:77,1,1,0 +BRDA:77,2,0,3 +BRDA:77,2,1,3 +BRDA:90,3,0,3 +BRDA:90,3,1,0 +BRDA:92,4,0,1 +BRDA:92,4,1,2 +BRDA:103,5,0,3 +BRDA:103,5,1,0 +BRDA:111,6,0,2 +BRDA:111,6,1,0 +BRDA:111,7,0,2 +BRDA:111,7,1,2 +BRDA:115,8,0,0 +BRDA:115,8,1,3 +BRF:18 +BRH:12 +end_of_record +TN: +SF:src/tools/registry.ts +FN:41,(anonymous_0) +FNF:1 +FNH:1 +FNDA:156,(anonymous_0) +DA:23,4 +DA:40,4 +DA:41,156 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/tools/tool-handler-base.ts +FN:84,(anonymous_0) +FN:91,(anonymous_1) +FN:111,(anonymous_2) +FN:120,(anonymous_3) +FN:129,(anonymous_4) +FN:141,(anonymous_5) +FN:158,(anonymous_6) +FN:170,(anonymous_7) +FN:192,(anonymous_8) +FN:224,(anonymous_9) +FN:228,(anonymous_10) +FN:236,(anonymous_11) +FN:240,(anonymous_12) +FN:244,(anonymous_13) +FN:255,(anonymous_14) +FN:270,(anonymous_15) +FN:292,(anonymous_16) +FN:319,(anonymous_17) +FN:344,(anonymous_18) +FN:398,(anonymous_19) +FN:421,(anonymous_20) +FN:424,(anonymous_21) +FN:432,(anonymous_22) +FN:438,(anonymous_23) +FN:445,(anonymous_24) +FN:465,(anonymous_25) +FN:510,(anonymous_26) +FN:525,(anonymous_27) +FN:532,(anonymous_28) +FN:539,(anonymous_29) +FN:544,(anonymous_30) +FN:550,(anonymous_31) +FN:561,(anonymous_32) +FN:570,(anonymous_33) +FN:594,(anonymous_34) +FN:655,(anonymous_35) +FN:665,(anonymous_36) +FN:669,(anonymous_37) +FN:681,(anonymous_38) +FN:728,(anonymous_39) +FN:742,(anonymous_40) +FN:773,(anonymous_41) +FN:821,(anonymous_42) +FN:837,(anonymous_43) +FN:849,(anonymous_44) +FN:911,(anonymous_45) +FN:955,(anonymous_46) +FN:959,(anonymous_47) +FN:963,(anonymous_48) +FN:971,(anonymous_49) +FN:989,(anonymous_50) +FN:1001,(anonymous_51) +FN:1061,(anonymous_52) +FN:1079,(anonymous_53) +FN:1083,(anonymous_54) +FN:1089,(anonymous_55) +FN:1099,(anonymous_56) +FN:1104,(anonymous_57) +FN:1146,(anonymous_58) +FNF:59 +FNH:49 +FNDA:126,(anonymous_0) +FNDA:135,(anonymous_1) +FNDA:165,(anonymous_2) +FNDA:117,(anonymous_3) +FNDA:19,(anonymous_4) +FNDA:19,(anonymous_5) +FNDA:126,(anonymous_6) +FNDA:34,(anonymous_7) +FNDA:19,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:28,(anonymous_10) +FNDA:20,(anonymous_11) +FNDA:20,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:14,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:126,(anonymous_18) +FNDA:126,(anonymous_19) +FNDA:0,(anonymous_20) +FNDA:0,(anonymous_21) +FNDA:126,(anonymous_22) +FNDA:68,(anonymous_23) +FNDA:0,(anonymous_24) +FNDA:126,(anonymous_25) +FNDA:21,(anonymous_26) +FNDA:374,(anonymous_27) +FNDA:906,(anonymous_28) +FNDA:64,(anonymous_29) +FNDA:767,(anonymous_30) +FNDA:132,(anonymous_31) +FNDA:2866,(anonymous_32) +FNDA:3,(anonymous_33) +FNDA:111,(anonymous_34) +FNDA:5,(anonymous_35) +FNDA:3,(anonymous_36) +FNDA:106,(anonymous_37) +FNDA:0,(anonymous_38) +FNDA:16,(anonymous_39) +FNDA:56,(anonymous_40) +FNDA:7,(anonymous_41) +FNDA:2,(anonymous_42) +FNDA:0,(anonymous_43) +FNDA:3,(anonymous_44) +FNDA:6,(anonymous_45) +FNDA:21,(anonymous_46) +FNDA:8,(anonymous_47) +FNDA:19,(anonymous_48) +FNDA:1,(anonymous_49) +FNDA:6,(anonymous_50) +FNDA:6,(anonymous_51) +FNDA:0,(anonymous_52) +FNDA:1,(anonymous_53) +FNDA:1,(anonymous_54) +FNDA:1,(anonymous_55) +FNDA:1,(anonymous_56) +FNDA:1,(anonymous_57) +FNDA:2,(anonymous_58) +DA:69,126 +DA:74,126 +DA:78,126 +DA:81,126 +DA:82,126 +DA:84,126 +DA:85,126 +DA:86,126 +DA:88,126 +DA:92,135 +DA:112,165 +DA:113,165 +DA:114,131 +DA:117,34 +DA:121,117 +DA:122,117 +DA:123,99 +DA:126,18 +DA:130,19 +DA:131,19 +DA:132,13 +DA:134,6 +DA:138,19 +DA:142,19 +DA:144,19 +DA:145,19 +DA:146,19 +DA:147,19 +DA:148,0 +DA:152,19 +DA:154,0 +DA:159,126 +DA:160,126 +DA:161,126 +DA:163,126 +DA:171,34 +DA:173,34 +DA:174,34 +DA:175,34 +DA:176,34 +DA:177,34 +DA:181,34 +DA:185,34 +DA:197,19 +DA:198,18 +DA:201,1 +DA:202,1 +DA:203,0 +DA:206,1 +DA:207,1 +DA:208,1 +DA:209,1 +DA:212,1 +DA:225,1 +DA:229,28 +DA:237,20 +DA:241,20 +DA:245,0 +DA:246,0 +DA:247,0 +DA:248,0 +DA:251,0 +DA:252,0 +DA:256,14 +DA:257,14 +DA:260,0 +DA:262,0 +DA:271,0 +DA:280,0 +DA:281,0 +DA:293,0 +DA:295,0 +DA:297,0 +DA:298,0 +DA:299,0 +DA:300,0 +DA:301,0 +DA:302,0 +DA:306,0 +DA:307,0 +DA:308,0 +DA:311,0 +DA:320,0 +DA:321,0 +DA:324,0 +DA:325,0 +DA:326,0 +DA:327,0 +DA:328,0 +DA:331,0 +DA:335,0 +DA:336,0 +DA:337,0 +DA:345,126 +DA:346,126 +DA:349,126 +DA:353,126 +DA:354,0 +DA:364,0 +DA:368,126 +DA:371,126 +DA:372,126 +DA:374,126 +DA:375,126 +DA:377,126 +DA:378,126 +DA:380,126 +DA:381,126 +DA:383,126 +DA:384,126 +DA:387,126 +DA:390,126 +DA:394,126 +DA:395,126 +DA:399,126 +DA:400,126 +DA:401,126 +DA:402,126 +DA:405,126 +DA:406,126 +DA:407,126 +DA:408,126 +DA:413,126 +DA:414,126 +DA:417,126 +DA:419,126 +DA:422,0 +DA:425,0 +DA:432,126 +DA:433,126 +DA:434,126 +DA:435,70 +DA:436,68 +DA:439,68 +DA:440,68 +DA:441,0 +DA:442,0 +DA:450,126 +DA:451,126 +DA:466,126 +DA:467,126 +DA:468,24 +DA:471,24 +DA:474,70 +DA:475,70 +DA:477,70 +DA:478,67 +DA:480,67 +DA:481,67 +DA:484,67 +DA:488,0 +DA:489,0 +DA:493,0 +DA:494,0 +DA:497,0 +DA:501,35 +DA:511,21 +DA:516,21 +DA:522,21 +DA:526,374 +DA:533,906 +DA:534,374 +DA:535,374 +DA:538,532 +DA:539,93 +DA:542,439 +DA:543,166 +DA:544,767 +DA:547,273 +DA:556,132 +DA:557,132 +DA:558,132 +DA:561,2866 +DA:573,3 +DA:575,3 +DA:576,0 +DA:579,3 +DA:580,0 +DA:583,3 +DA:584,0 +DA:587,3 +DA:588,2 +DA:591,1 +DA:598,111 +DA:599,111 +DA:601,111 +DA:602,5 +DA:608,5 +DA:609,2 +DA:612,5 +DA:613,5 +DA:616,111 +DA:617,1 +DA:618,1 +DA:619,1 +DA:620,1 +DA:623,1 +DA:624,0 +DA:625,0 +DA:628,1 +DA:629,0 +DA:630,0 +DA:634,111 +DA:635,1 +DA:636,0 +DA:637,0 +DA:641,111 +DA:642,17 +DA:646,2 +DA:647,2 +DA:649,17 +DA:652,111 +DA:656,5 +DA:666,3 +DA:670,106 +DA:673,106 +DA:674,106 +DA:676,106 +DA:677,0 +DA:680,0 +DA:681,0 +DA:683,0 +DA:684,0 +DA:692,106 +DA:693,106 +DA:695,0 +DA:696,0 +DA:699,106 +DA:700,106 +DA:701,106 +DA:702,106 +DA:703,106 +DA:705,0 +DA:708,106 +DA:709,102 +DA:712,4 +DA:713,4 +DA:714,4 +DA:715,4 +DA:716,4 +DA:718,0 +DA:720,0 +DA:729,16 +DA:730,14 +DA:733,2 +DA:734,2 +DA:735,2 +DA:738,0 +DA:739,0 +DA:743,56 +DA:744,8 +DA:747,48 +DA:748,7 +DA:751,41 +DA:752,4 +DA:753,4 +DA:756,37 +DA:757,0 +DA:758,0 +DA:759,0 +DA:761,0 +DA:762,0 +DA:766,37 +DA:779,7 +DA:780,7 +DA:781,7 +DA:782,7 +DA:786,7 +DA:787,5 +DA:788,5 +DA:789,0 +DA:791,5 +DA:792,2 +DA:796,5 +DA:797,0 +DA:798,0 +DA:802,5 +DA:803,0 +DA:804,0 +DA:805,0 +DA:807,0 +DA:808,0 +DA:812,5 +DA:813,0 +DA:814,0 +DA:818,5 +DA:822,2 +DA:823,0 +DA:826,2 +DA:827,2 +DA:828,0 +DA:829,0 +DA:830,0 +DA:836,0 +DA:837,0 +DA:841,2 +DA:857,3 +DA:858,3 +DA:859,0 +DA:863,3 +DA:864,3 +DA:865,2 +DA:869,2 +DA:870,2 +DA:871,1 +DA:873,1 +DA:876,1 +DA:877,1 +DA:878,1 +DA:881,0 +DA:882,0 +DA:886,0 +DA:887,0 +DA:888,0 +DA:890,0 +DA:893,0 +DA:897,0 +DA:898,3 +DA:899,0 +DA:902,0 +DA:912,6 +DA:914,6 +DA:918,6 +DA:919,2 +DA:922,2 +DA:925,4 +DA:926,4 +DA:927,4 +DA:928,2 +DA:931,2 +DA:932,2 +DA:934,0 +DA:935,0 +DA:940,0 +DA:945,2 +DA:947,2 +DA:948,2 +DA:951,2 +DA:956,21 +DA:960,8 +DA:964,19 +DA:972,1 +DA:973,1 +DA:975,1 +DA:982,1 +DA:983,0 +DA:986,1 +DA:993,6 +DA:994,6 +DA:1002,6 +DA:1003,6 +DA:1004,0 +DA:1010,6 +DA:1012,6 +DA:1016,6 +DA:1017,2 +DA:1020,4 +DA:1021,4 +DA:1025,4 +DA:1026,4 +DA:1029,6 +DA:1030,6 +DA:1032,6 +DA:1033,6 +DA:1034,6 +DA:1036,6 +DA:1062,0 +DA:1063,0 +DA:1080,1 +DA:1081,1 +DA:1084,1 +DA:1090,1 +DA:1091,1 +DA:1093,1 +DA:1094,1 +DA:1096,1 +DA:1101,1 +DA:1103,1 +DA:1104,1 +DA:1105,1 +DA:1106,1 +DA:1107,0 +DA:1110,1 +DA:1111,1 +DA:1112,0 +DA:1115,1 +DA:1117,1 +DA:1118,1 +DA:1119,1 +DA:1121,1 +DA:1122,0 +DA:1123,0 +DA:1124,0 +DA:1125,0 +DA:1127,0 +DA:1130,1 +DA:1131,1 +DA:1132,1 +DA:1133,1 +DA:1136,0 +DA:1139,1 +DA:1149,2 +DA:1150,0 +DA:1154,2 +DA:1155,2 +DA:1157,2 +DA:1158,1 +DA:1171,2 +DA:1184,2 +DA:1185,2 +DA:1189,2 +DA:1190,2 +LF:412 +LH:295 +BRDA:113,0,0,131 +BRDA:113,0,1,34 +BRDA:113,1,0,165 +BRDA:113,1,1,34 +BRDA:122,2,0,99 +BRDA:122,2,1,18 +BRDA:126,3,0,18 +BRDA:126,3,1,6 +BRDA:131,4,0,13 +BRDA:131,4,1,6 +BRDA:147,5,0,0 +BRDA:147,5,1,19 +BRDA:170,6,0,34 +BRDA:171,7,0,34 +BRDA:171,7,1,0 +BRDA:173,8,0,34 +BRDA:173,8,1,21 +BRDA:174,9,0,21 +BRDA:174,9,1,13 +BRDA:176,10,0,34 +BRDA:176,10,1,16 +BRDA:177,11,0,16 +BRDA:177,11,1,18 +BRDA:181,12,0,34 +BRDA:181,12,1,15 +BRDA:181,12,2,0 +BRDA:197,13,0,18 +BRDA:197,13,1,1 +BRDA:202,14,0,0 +BRDA:202,14,1,1 +BRDA:202,15,0,1 +BRDA:202,15,1,1 +BRDA:207,16,0,1 +BRDA:207,16,1,0 +BRDA:207,17,0,1 +BRDA:207,17,1,1 +BRDA:229,18,0,28 +BRDA:229,18,1,28 +BRDA:237,19,0,20 +BRDA:237,19,1,10 +BRDA:247,20,0,0 +BRDA:247,20,1,0 +BRDA:256,21,0,14 +BRDA:256,21,1,0 +BRDA:293,22,0,0 +BRDA:293,22,1,0 +BRDA:299,23,0,0 +BRDA:299,23,1,0 +BRDA:306,24,0,0 +BRDA:306,24,1,0 +BRDA:327,25,0,0 +BRDA:327,25,1,0 +BRDA:350,26,0,126 +BRDA:350,26,1,32 +BRDA:353,27,0,0 +BRDA:353,27,1,126 +BRDA:365,28,0,0 +BRDA:365,28,1,0 +BRDA:388,29,0,126 +BRDA:388,29,1,120 +BRDA:391,30,0,6 +BRDA:391,30,1,120 +BRDA:403,31,0,126 +BRDA:403,31,1,126 +BRDA:433,32,0,0 +BRDA:433,32,1,126 +BRDA:434,33,0,56 +BRDA:434,33,1,70 +BRDA:435,34,0,2 +BRDA:435,34,1,68 +BRDA:439,35,0,68 +BRDA:439,35,1,0 +BRDA:441,36,0,0 +BRDA:441,36,1,0 +BRDA:450,37,0,126 +BRDA:450,37,1,0 +BRDA:467,38,0,24 +BRDA:467,38,1,102 +BRDA:480,39,0,67 +BRDA:480,39,1,0 +BRDA:480,40,0,67 +BRDA:480,40,1,67 +BRDA:510,41,0,21 +BRDA:514,42,0,21 +BRDA:514,42,1,14 +BRDA:533,43,0,374 +BRDA:533,43,1,532 +BRDA:535,44,0,2 +BRDA:535,44,1,372 +BRDA:538,45,0,93 +BRDA:538,45,1,439 +BRDA:542,46,0,166 +BRDA:542,46,1,273 +BRDA:542,47,0,439 +BRDA:542,47,1,300 +BRDA:552,48,0,132 +BRDA:556,49,0,57 +BRDA:556,49,1,75 +BRDA:557,50,0,58 +BRDA:557,50,1,74 +BRDA:557,51,0,132 +BRDA:557,51,1,131 +BRDA:559,52,0,132 +BRDA:559,52,1,74 +BRDA:561,53,0,0 +BRDA:561,53,1,2866 +BRDA:575,54,0,0 +BRDA:575,54,1,3 +BRDA:579,55,0,0 +BRDA:579,55,1,3 +BRDA:583,56,0,0 +BRDA:583,56,1,3 +BRDA:587,57,0,2 +BRDA:587,57,1,1 +BRDA:599,58,0,111 +BRDA:599,58,1,0 +BRDA:601,59,0,5 +BRDA:601,59,1,106 +BRDA:602,60,0,2 +BRDA:602,60,1,3 +BRDA:604,61,0,2 +BRDA:604,61,1,1 +BRDA:608,62,0,2 +BRDA:608,62,1,3 +BRDA:608,63,0,5 +BRDA:608,63,1,2 +BRDA:616,64,0,1 +BRDA:616,64,1,110 +BRDA:617,65,0,1 +BRDA:617,65,1,0 +BRDA:618,66,0,1 +BRDA:618,66,1,0 +BRDA:619,67,0,0 +BRDA:619,67,1,1 +BRDA:623,68,0,0 +BRDA:623,68,1,1 +BRDA:628,69,0,0 +BRDA:628,69,1,1 +BRDA:634,70,0,1 +BRDA:634,70,1,110 +BRDA:635,71,0,0 +BRDA:635,71,1,1 +BRDA:641,72,0,17 +BRDA:641,72,1,94 +BRDA:641,73,0,111 +BRDA:641,73,1,98 +BRDA:642,74,0,2 +BRDA:642,74,1,15 +BRDA:643,75,0,17 +BRDA:643,75,1,2 +BRDA:671,76,0,106 +BRDA:671,76,1,0 +BRDA:676,77,0,0 +BRDA:676,77,1,106 +BRDA:681,78,0,0 +BRDA:681,78,1,0 +BRDA:701,79,0,106 +BRDA:701,79,1,0 +BRDA:702,80,0,106 +BRDA:702,80,1,88 +BRDA:702,81,0,88 +BRDA:702,81,1,0 +BRDA:708,82,0,102 +BRDA:708,82,1,4 +BRDA:714,83,0,4 +BRDA:714,83,1,0 +BRDA:714,84,0,4 +BRDA:714,84,1,4 +BRDA:729,85,0,14 +BRDA:729,85,1,2 +BRDA:729,86,0,16 +BRDA:729,86,1,2 +BRDA:733,87,0,2 +BRDA:733,87,1,0 +BRDA:735,88,0,2 +BRDA:735,88,1,0 +BRDA:739,89,0,0 +BRDA:739,89,1,0 +BRDA:743,90,0,8 +BRDA:743,90,1,48 +BRDA:744,91,0,8 +BRDA:744,91,1,0 +BRDA:747,92,0,7 +BRDA:747,92,1,41 +BRDA:751,93,0,4 +BRDA:751,93,1,37 +BRDA:751,94,0,41 +BRDA:751,94,1,4 +BRDA:753,95,0,4 +BRDA:753,95,1,0 +BRDA:756,96,0,0 +BRDA:756,96,1,37 +BRDA:756,97,0,37 +BRDA:756,97,1,0 +BRDA:756,97,2,0 +BRDA:759,98,0,0 +BRDA:759,98,1,0 +BRDA:759,99,0,0 +BRDA:759,99,1,0 +BRDA:761,100,0,0 +BRDA:761,100,1,0 +BRDA:761,101,0,0 +BRDA:761,101,1,0 +BRDA:779,102,0,7 +BRDA:779,102,1,0 +BRDA:780,103,0,7 +BRDA:780,103,1,0 +BRDA:781,104,0,7 +BRDA:781,104,1,4 +BRDA:783,105,0,7 +BRDA:783,105,1,1 +BRDA:783,106,0,7 +BRDA:783,106,1,4 +BRDA:786,107,0,5 +BRDA:786,107,1,2 +BRDA:787,108,0,5 +BRDA:787,108,1,0 +BRDA:788,109,0,0 +BRDA:788,109,1,5 +BRDA:788,110,0,5 +BRDA:788,110,1,5 +BRDA:791,111,0,2 +BRDA:791,111,1,3 +BRDA:791,112,0,5 +BRDA:791,112,1,2 +BRDA:796,113,0,0 +BRDA:796,113,1,5 +BRDA:797,114,0,0 +BRDA:797,114,1,0 +BRDA:802,115,0,0 +BRDA:802,115,1,5 +BRDA:803,116,0,0 +BRDA:803,116,1,0 +BRDA:804,117,0,0 +BRDA:804,117,1,0 +BRDA:804,118,0,0 +BRDA:804,118,1,0 +BRDA:807,119,0,0 +BRDA:807,119,1,0 +BRDA:807,120,0,0 +BRDA:807,120,1,0 +BRDA:812,121,0,0 +BRDA:812,121,1,5 +BRDA:813,122,0,0 +BRDA:813,122,1,0 +BRDA:813,123,0,0 +BRDA:813,123,1,0 +BRDA:822,124,0,0 +BRDA:822,124,1,2 +BRDA:822,125,0,2 +BRDA:822,125,1,2 +BRDA:837,126,0,0 +BRDA:837,126,1,0 +BRDA:858,127,0,0 +BRDA:858,127,1,3 +BRDA:864,128,0,2 +BRDA:864,128,1,1 +BRDA:864,129,0,3 +BRDA:864,129,1,3 +BRDA:870,130,0,1 +BRDA:870,130,1,1 +BRDA:877,131,0,1 +BRDA:877,131,1,0 +BRDA:881,132,0,0 +BRDA:881,132,1,0 +BRDA:887,133,0,0 +BRDA:887,133,1,0 +BRDA:898,134,0,0 +BRDA:898,134,1,3 +BRDA:912,135,0,6 +BRDA:912,135,1,6 +BRDA:915,136,0,6 +BRDA:915,136,1,0 +BRDA:918,137,0,2 +BRDA:918,137,1,4 +BRDA:918,138,0,6 +BRDA:918,138,1,4 +BRDA:927,139,0,2 +BRDA:927,139,1,2 +BRDA:934,140,0,0 +BRDA:934,140,1,0 +BRDA:947,141,0,2 +BRDA:947,141,1,0 +BRDA:956,142,0,21 +BRDA:956,142,1,14 +BRDA:972,143,0,1 +BRDA:972,143,1,0 +BRDA:973,144,0,1 +BRDA:973,144,1,1 +BRDA:982,145,0,0 +BRDA:982,145,1,1 +BRDA:991,146,0,6 +BRDA:993,147,0,6 +BRDA:993,147,1,6 +BRDA:1002,148,0,6 +BRDA:1002,148,1,0 +BRDA:1003,149,0,0 +BRDA:1003,149,1,6 +BRDA:1012,150,0,6 +BRDA:1012,150,1,4 +BRDA:1013,151,0,4 +BRDA:1013,151,1,0 +BRDA:1013,152,0,4 +BRDA:1013,152,1,4 +BRDA:1013,152,2,4 +BRDA:1016,153,0,2 +BRDA:1016,153,1,4 +BRDA:1026,154,0,3 +BRDA:1026,154,1,1 +BRDA:1029,155,0,3 +BRDA:1029,155,1,1 +BRDA:1029,156,0,6 +BRDA:1029,156,1,3 +BRDA:1030,157,0,0 +BRDA:1030,157,1,4 +BRDA:1037,158,0,6 +BRDA:1037,158,1,4 +BRDA:1037,158,2,4 +BRDA:1062,159,0,0 +BRDA:1062,159,1,0 +BRDA:1064,160,0,0 +BRDA:1064,160,1,0 +BRDA:1064,160,2,0 +BRDA:1064,160,3,0 +BRDA:1064,160,4,0 +BRDA:1064,160,5,0 +BRDA:1106,161,0,0 +BRDA:1106,161,1,1 +BRDA:1111,162,0,0 +BRDA:1111,162,1,1 +BRDA:1121,163,0,0 +BRDA:1121,163,1,1 +BRDA:1122,164,0,0 +BRDA:1122,164,1,0 +BRDA:1130,165,0,1 +BRDA:1130,165,1,0 +BRDA:1139,166,0,1 +BRDA:1139,166,1,0 +BRDA:1149,167,0,0 +BRDA:1149,167,1,2 +BRDA:1157,168,0,1 +BRDA:1157,168,1,1 +BRF:342 +BRH:223 +end_of_record +TN: +SF:src/tools/tool-handlers.ts +FN:33,(anonymous_0) +FN:40,(anonymous_1) +FN:49,(anonymous_2) +FN:79,(anonymous_3) +FN:84,(anonymous_4) +FN:105,(anonymous_5) +FN:106,(anonymous_6) +FN:111,(anonymous_7) +FN:130,(anonymous_8) +FN:146,(anonymous_9) +FN:189,(anonymous_10) +FN:191,(anonymous_11) +FN:201,(anonymous_12) +FN:203,(anonymous_13) +FN:239,(anonymous_14) +FN:243,(anonymous_15) +FN:252,(anonymous_16) +FN:255,(anonymous_17) +FN:258,(anonymous_18) +FN:260,(anonymous_19) +FN:262,(anonymous_20) +FN:265,(anonymous_21) +FN:268,(anonymous_22) +FN:295,(anonymous_23) +FN:317,(anonymous_24) +FN:319,(anonymous_25) +FN:322,(anonymous_26) +FN:324,(anonymous_27) +FN:345,(anonymous_28) +FN:360,(anonymous_29) +FN:362,(anonymous_30) +FN:363,(anonymous_31) +FN:382,(anonymous_32) +FN:402,(anonymous_33) +FN:424,(anonymous_34) +FN:433,(anonymous_35) +FN:447,(anonymous_36) +FN:454,(anonymous_37) +FN:468,(anonymous_38) +FN:475,(anonymous_39) +FN:500,(anonymous_40) +FN:508,(anonymous_41) +FN:513,(anonymous_42) +FN:553,(anonymous_43) +FN:570,(anonymous_44) +FN:584,(anonymous_45) +FN:585,(anonymous_46) +FN:588,(anonymous_47) +FN:589,(anonymous_48) +FN:602,(anonymous_49) +FN:620,(anonymous_50) +FN:638,(anonymous_51) +FN:649,(anonymous_52) +FNF:53 +FNH:18 +FNDA:126,(anonymous_0) +FNDA:153,(anonymous_1) +FNDA:2,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:2,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:1,(anonymous_14) +FNDA:4,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:0,(anonymous_18) +FNDA:0,(anonymous_19) +FNDA:0,(anonymous_20) +FNDA:0,(anonymous_21) +FNDA:1,(anonymous_22) +FNDA:1,(anonymous_23) +FNDA:0,(anonymous_24) +FNDA:0,(anonymous_25) +FNDA:0,(anonymous_26) +FNDA:0,(anonymous_27) +FNDA:2,(anonymous_28) +FNDA:0,(anonymous_29) +FNDA:0,(anonymous_30) +FNDA:0,(anonymous_31) +FNDA:0,(anonymous_32) +FNDA:1,(anonymous_33) +FNDA:0,(anonymous_34) +FNDA:1,(anonymous_35) +FNDA:0,(anonymous_36) +FNDA:1,(anonymous_37) +FNDA:0,(anonymous_38) +FNDA:1,(anonymous_39) +FNDA:0,(anonymous_40) +FNDA:1,(anonymous_41) +FNDA:0,(anonymous_42) +FNDA:2,(anonymous_43) +FNDA:0,(anonymous_44) +FNDA:0,(anonymous_45) +FNDA:0,(anonymous_46) +FNDA:0,(anonymous_47) +FNDA:0,(anonymous_48) +FNDA:2,(anonymous_49) +FNDA:0,(anonymous_50) +FNDA:2,(anonymous_51) +FNDA:2,(anonymous_52) +DA:34,126 +DA:36,126 +DA:37,4914 +DA:38,0 +DA:40,4914 +DA:58,2 +DA:60,2 +DA:61,1 +DA:64,1 +DA:65,1 +DA:66,2 +DA:68,2 +DA:69,2 +DA:70,1 +DA:79,1 +DA:80,0 +DA:82,1 +DA:84,1 +DA:85,1 +DA:86,1 +DA:89,2 +DA:90,2 +DA:95,2 +DA:96,2 +DA:98,2 +DA:105,0 +DA:106,0 +DA:111,0 +DA:130,0 +DA:135,2 +DA:136,2 +DA:137,2 +DA:138,2 +DA:140,2 +DA:142,0 +DA:147,2 +DA:149,2 +DA:150,0 +DA:157,2 +DA:158,2 +DA:159,2 +DA:160,2 +DA:161,0 +DA:169,2 +DA:170,2 +DA:175,2 +DA:182,2 +DA:183,2 +DA:186,2 +DA:189,0 +DA:191,0 +DA:198,2 +DA:201,0 +DA:203,0 +DA:209,2 +DA:210,2 +DA:213,2 +DA:215,2 +DA:231,2 +DA:233,2 +DA:235,0 +DA:240,1 +DA:243,4 +DA:245,1 +DA:251,1 +DA:254,0 +DA:255,0 +DA:256,0 +DA:258,0 +DA:260,1 +DA:261,1 +DA:262,0 +DA:265,1 +DA:269,1 +DA:270,1 +DA:273,0 +DA:274,0 +DA:283,0 +DA:284,1 +DA:285,0 +DA:286,0 +DA:287,0 +DA:292,0 +DA:299,1 +DA:300,1 +DA:301,1 +DA:303,1 +DA:304,0 +DA:305,0 +DA:306,0 +DA:309,0 +DA:310,0 +DA:314,0 +DA:315,0 +DA:317,0 +DA:319,0 +DA:320,0 +DA:322,0 +DA:324,0 +DA:326,0 +DA:342,1 +DA:351,2 +DA:352,2 +DA:353,0 +DA:356,2 +DA:357,2 +DA:358,0 +DA:360,0 +DA:361,0 +DA:362,0 +DA:363,0 +DA:364,0 +DA:367,2 +DA:368,0 +DA:371,2 +DA:372,2 +DA:374,2 +DA:388,0 +DA:389,0 +DA:390,0 +DA:392,0 +DA:393,0 +DA:396,0 +DA:398,0 +DA:407,1 +DA:408,1 +DA:411,0 +DA:424,0 +DA:434,1 +DA:435,1 +DA:438,0 +DA:447,0 +DA:455,1 +DA:456,1 +DA:459,0 +DA:468,0 +DA:480,1 +DA:481,1 +DA:483,1 +DA:484,1 +DA:485,1 +DA:487,0 +DA:488,0 +DA:491,1 +DA:500,1 +DA:509,1 +DA:510,0 +DA:513,1 +DA:514,0 +DA:515,0 +DA:516,0 +DA:518,0 +DA:519,0 +DA:520,0 +DA:522,0 +DA:523,0 +DA:524,0 +DA:526,0 +DA:527,0 +DA:528,0 +DA:530,0 +DA:531,0 +DA:532,0 +DA:533,0 +DA:534,0 +DA:538,0 +DA:541,1 +DA:542,1 +DA:543,1 +DA:544,0 +DA:545,0 +DA:546,0 +DA:548,0 +DA:549,0 +DA:559,2 +DA:560,2 +DA:562,2 +DA:563,0 +DA:564,0 +DA:565,0 +DA:569,2 +DA:570,0 +DA:571,0 +DA:574,0 +DA:581,0 +DA:582,0 +DA:584,0 +DA:585,0 +DA:586,0 +DA:587,0 +DA:588,0 +DA:589,0 +DA:590,0 +DA:591,0 +DA:596,2 +DA:597,2 +DA:598,2 +DA:603,2 +DA:604,2 +DA:607,2 +DA:608,2 +DA:612,0 +DA:613,0 +DA:614,0 +DA:615,0 +DA:619,0 +DA:620,0 +DA:621,0 +DA:624,0 +DA:630,0 +DA:631,0 +DA:635,0 +DA:643,2 +DA:644,0 +DA:646,2 +DA:650,2 +DA:651,1 +DA:653,1 +DA:654,1 +LF:219 +LH:105 +BRDA:37,0,0,0 +BRDA:37,0,1,4914 +BRDA:54,1,0,2 +BRDA:55,2,0,2 +BRDA:56,3,0,2 +BRDA:57,4,0,2 +BRDA:58,5,0,2 +BRDA:58,5,1,0 +BRDA:60,6,0,1 +BRDA:60,6,1,1 +BRDA:60,7,0,2 +BRDA:60,7,1,1 +BRDA:65,8,0,1 +BRDA:65,8,1,0 +BRDA:73,9,0,0 +BRDA:73,9,1,1 +BRDA:80,10,0,0 +BRDA:80,10,1,0 +BRDA:86,11,0,1 +BRDA:86,11,1,0 +BRDA:89,12,0,1 +BRDA:89,12,1,0 +BRDA:90,13,0,1 +BRDA:90,13,1,0 +BRDA:95,14,0,2 +BRDA:95,14,1,1 +BRDA:95,14,2,1 +BRDA:102,15,0,2 +BRDA:102,15,1,0 +BRDA:121,16,0,1 +BRDA:121,16,1,0 +BRDA:129,17,0,0 +BRDA:129,17,1,1 +BRDA:135,18,0,0 +BRDA:135,18,1,1 +BRDA:135,19,0,2 +BRDA:135,19,1,1 +BRDA:147,20,0,2 +BRDA:147,21,0,2 +BRDA:147,22,0,2 +BRDA:147,22,1,0 +BRDA:149,23,0,0 +BRDA:149,23,1,2 +BRDA:149,24,0,2 +BRDA:149,24,1,0 +BRDA:149,24,2,0 +BRDA:160,25,0,0 +BRDA:160,25,1,2 +BRDA:170,26,0,1 +BRDA:170,26,1,1 +BRDA:175,27,0,2 +BRDA:175,27,1,0 +BRDA:175,28,0,2 +BRDA:175,28,1,2 +BRDA:175,28,2,0 +BRDA:175,28,3,0 +BRDA:186,29,0,0 +BRDA:186,29,1,2 +BRDA:186,30,0,2 +BRDA:186,30,1,2 +BRDA:193,31,0,0 +BRDA:193,31,1,0 +BRDA:198,32,0,0 +BRDA:198,32,1,2 +BRDA:198,33,0,2 +BRDA:198,33,1,2 +BRDA:205,34,0,0 +BRDA:205,34,1,0 +BRDA:210,35,0,0 +BRDA:210,35,1,2 +BRDA:213,36,0,0 +BRDA:213,36,1,2 +BRDA:220,37,0,2 +BRDA:220,37,1,0 +BRDA:221,38,0,0 +BRDA:221,38,1,2 +BRDA:226,39,0,2 +BRDA:226,39,1,2 +BRDA:254,40,0,0 +BRDA:254,40,1,0 +BRDA:254,41,0,0 +BRDA:254,41,1,0 +BRDA:255,42,0,0 +BRDA:255,42,1,0 +BRDA:261,43,0,0 +BRDA:261,43,1,1 +BRDA:269,44,0,1 +BRDA:269,44,1,0 +BRDA:284,45,0,0 +BRDA:284,45,1,1 +BRDA:286,46,0,0 +BRDA:286,46,1,0 +BRDA:305,47,0,0 +BRDA:305,47,1,0 +BRDA:310,48,0,0 +BRDA:310,48,1,0 +BRDA:332,49,0,0 +BRDA:332,49,1,0 +BRDA:336,50,0,0 +BRDA:336,50,1,0 +BRDA:352,51,0,0 +BRDA:352,51,1,2 +BRDA:356,52,0,2 +BRDA:356,52,1,1 +BRDA:356,52,2,0 +BRDA:357,53,0,0 +BRDA:357,53,1,2 +BRDA:364,54,0,0 +BRDA:364,54,1,0 +BRDA:364,54,2,0 +BRDA:367,55,0,0 +BRDA:367,55,1,2 +BRDA:371,56,0,2 +BRDA:371,56,1,0 +BRDA:371,56,2,0 +BRDA:372,57,0,2 +BRDA:372,57,1,0 +BRDA:389,58,0,0 +BRDA:389,58,1,0 +BRDA:396,59,0,0 +BRDA:396,59,1,0 +BRDA:407,60,0,1 +BRDA:407,60,1,0 +BRDA:424,61,0,0 +BRDA:424,61,1,0 +BRDA:425,62,0,0 +BRDA:425,62,1,0 +BRDA:426,63,0,0 +BRDA:426,63,1,0 +BRDA:427,64,0,0 +BRDA:427,64,1,0 +BRDA:428,65,0,0 +BRDA:428,65,1,0 +BRDA:429,66,0,0 +BRDA:429,66,1,0 +BRDA:434,67,0,1 +BRDA:434,67,1,0 +BRDA:447,68,0,0 +BRDA:447,68,1,0 +BRDA:448,69,0,0 +BRDA:448,69,1,0 +BRDA:449,70,0,0 +BRDA:449,70,1,0 +BRDA:450,71,0,0 +BRDA:450,71,1,0 +BRDA:455,72,0,1 +BRDA:455,72,1,0 +BRDA:468,73,0,0 +BRDA:468,73,1,0 +BRDA:469,74,0,0 +BRDA:469,74,1,0 +BRDA:470,75,0,0 +BRDA:470,75,1,0 +BRDA:471,76,0,0 +BRDA:471,76,1,0 +BRDA:483,77,0,1 +BRDA:483,77,1,0 +BRDA:500,78,0,1 +BRDA:500,78,1,0 +BRDA:501,79,0,0 +BRDA:501,79,1,0 +BRDA:502,80,0,0 +BRDA:502,80,1,0 +BRDA:503,81,0,0 +BRDA:503,81,1,0 +BRDA:504,82,0,0 +BRDA:504,82,1,0 +BRDA:509,83,0,0 +BRDA:509,83,1,1 +BRDA:514,84,0,0 +BRDA:514,84,1,0 +BRDA:514,85,0,0 +BRDA:514,85,1,0 +BRDA:518,86,0,0 +BRDA:518,86,1,0 +BRDA:518,87,0,0 +BRDA:518,87,1,0 +BRDA:522,88,0,0 +BRDA:522,88,1,0 +BRDA:522,89,0,0 +BRDA:522,89,1,0 +BRDA:526,90,0,0 +BRDA:526,90,1,0 +BRDA:526,91,0,0 +BRDA:526,91,1,0 +BRDA:530,92,0,0 +BRDA:530,92,1,0 +BRDA:532,93,0,0 +BRDA:532,93,1,0 +BRDA:532,94,0,0 +BRDA:532,94,1,0 +BRDA:543,95,0,1 +BRDA:543,95,1,0 +BRDA:545,96,0,0 +BRDA:545,96,1,0 +BRDA:559,97,0,0 +BRDA:559,97,1,2 +BRDA:560,98,0,2 +BRDA:560,98,1,0 +BRDA:562,99,0,0 +BRDA:562,99,1,2 +BRDA:564,100,0,0 +BRDA:564,100,1,0 +BRDA:569,101,0,0 +BRDA:569,101,1,2 +BRDA:569,102,0,2 +BRDA:569,102,1,2 +BRDA:572,103,0,0 +BRDA:572,103,1,0 +BRDA:572,103,2,0 +BRDA:575,104,0,0 +BRDA:575,104,1,0 +BRDA:575,104,2,0 +BRDA:581,105,0,0 +BRDA:581,105,1,0 +BRDA:586,106,0,0 +BRDA:586,106,1,0 +BRDA:590,107,0,0 +BRDA:590,107,1,0 +BRDA:596,108,0,2 +BRDA:596,108,1,0 +BRDA:597,109,0,2 +BRDA:597,109,1,0 +BRDA:603,110,0,2 +BRDA:603,110,1,0 +BRDA:603,110,2,0 +BRDA:604,111,0,2 +BRDA:604,111,1,0 +BRDA:607,112,0,2 +BRDA:607,112,1,0 +BRDA:612,113,0,0 +BRDA:612,113,1,0 +BRDA:614,114,0,0 +BRDA:614,114,1,0 +BRDA:619,115,0,0 +BRDA:619,115,1,0 +BRDA:622,116,0,0 +BRDA:622,116,1,0 +BRDA:622,116,2,0 +BRDA:625,117,0,0 +BRDA:625,117,1,0 +BRDA:625,117,2,0 +BRDA:630,118,0,0 +BRDA:630,118,1,0 +BRDA:643,119,0,0 +BRDA:643,119,1,2 +BRDA:650,120,0,1 +BRDA:650,120,1,1 +BRF:248 +BRH:78 +end_of_record +TN: +SF:src/tools/types.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/tools/vector-tools.ts +FN:22,(anonymous_0) +FN:30,(anonymous_1) +FN:43,(anonymous_2) +FN:70,(anonymous_3) +FN:115,(anonymous_4) +FN:147,(anonymous_5) +FN:166,(anonymous_6) +FN:200,(anonymous_7) +FN:218,(anonymous_8) +FN:226,(anonymous_9) +FN:239,(anonymous_10) +FN:241,(anonymous_11) +FN:254,(anonymous_12) +FN:255,(anonymous_13) +FN:268,(anonymous_14) +FNF:15 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +DA:23,0 +DA:24,0 +DA:31,0 +DA:32,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:51,0 +DA:63,0 +DA:71,0 +DA:72,0 +DA:77,0 +DA:79,0 +DA:80,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:93,0 +DA:108,0 +DA:116,0 +DA:117,0 +DA:122,0 +DA:124,0 +DA:126,0 +DA:131,0 +DA:136,0 +DA:142,0 +DA:144,0 +DA:147,0 +DA:159,0 +DA:167,0 +DA:168,0 +DA:173,0 +DA:175,0 +DA:176,0 +DA:178,0 +DA:179,0 +DA:186,0 +DA:187,0 +DA:188,0 +DA:191,0 +DA:192,0 +DA:195,0 +DA:200,0 +DA:211,0 +DA:219,0 +DA:221,0 +DA:223,0 +DA:224,0 +DA:225,0 +DA:226,0 +DA:235,0 +DA:236,0 +DA:237,0 +DA:238,0 +DA:239,0 +DA:242,0 +DA:252,0 +DA:253,0 +DA:255,0 +DA:256,0 +DA:257,0 +DA:258,0 +DA:260,0 +DA:266,0 +DA:268,0 +DA:271,0 +DA:283,0 +LF:71 +LH:0 +BRDA:31,0,0,0 +BRDA:31,0,1,0 +BRDA:38,1,0,0 +BRDA:38,2,0,0 +BRDA:71,3,0,0 +BRDA:71,3,1,0 +BRDA:77,4,0,0 +BRDA:84,5,0,0 +BRDA:84,5,1,0 +BRDA:85,6,0,0 +BRDA:85,6,1,0 +BRDA:100,7,0,0 +BRDA:100,7,1,0 +BRDA:116,8,0,0 +BRDA:116,8,1,0 +BRDA:122,9,0,0 +BRDA:167,10,0,0 +BRDA:167,10,1,0 +BRDA:173,11,0,0 +BRDA:178,12,0,0 +BRDA:178,12,1,0 +BRDA:187,13,0,0 +BRDA:187,13,1,0 +BRDA:205,14,0,0 +BRDA:205,14,1,0 +BRDA:219,15,0,0 +BRDA:224,16,0,0 +BRDA:224,16,1,0 +BRDA:236,17,0,0 +BRDA:236,17,1,0 +BRDA:239,18,0,0 +BRDA:239,18,1,0 +BRDA:256,19,0,0 +BRDA:256,19,1,0 +BRF:34 +BRH:0 +end_of_record +TN: +SF:src/tools/handlers/arch-tools.ts +FN:22,(anonymous_0) +FN:66,(anonymous_1) +FNF:2 +FNH:2 +FNDA:5,(anonymous_0) +FNDA:3,(anonymous_1) +DA:13,4 +DA:23,5 +DA:25,5 +DA:31,5 +DA:32,3 +DA:39,2 +DA:40,2 +DA:42,2 +DA:49,5 +DA:51,0 +DA:67,3 +DA:69,3 +DA:85,3 +DA:86,0 +DA:93,3 +DA:94,3 +DA:96,3 +DA:97,2 +DA:107,1 +DA:117,0 +LF:20 +LH:17 +BRDA:23,0,0,5 +BRDA:23,1,0,5 +BRDA:31,2,0,3 +BRDA:31,2,1,2 +BRDA:46,3,0,1 +BRDA:46,3,1,1 +BRDA:67,4,0,3 +BRDA:67,5,0,3 +BRDA:85,6,0,0 +BRDA:85,6,1,3 +BRDA:96,7,0,2 +BRDA:96,7,1,1 +BRF:12 +BRH:11 +end_of_record +TN: +SF:src/tools/handlers/core-analysis-tools.ts +FN:18,(anonymous_0) +FN:29,(anonymous_1) +FN:87,(anonymous_2) +FN:123,(anonymous_3) +FN:139,(anonymous_4) +FN:146,(anonymous_5) +FN:160,(anonymous_6) +FN:182,(anonymous_7) +FN:195,(anonymous_8) +FN:231,(anonymous_9) +FN:232,(anonymous_10) +FN:253,(anonymous_11) +FN:286,(anonymous_12) +FN:299,(anonymous_13) +FN:304,(anonymous_14) +FNF:15 +FNH:11 +FNDA:5,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:4,(anonymous_3) +FNDA:4,(anonymous_4) +FNDA:4,(anonymous_5) +FNDA:4,(anonymous_6) +FNDA:2,(anonymous_7) +FNDA:4,(anonymous_8) +FNDA:2,(anonymous_9) +FNDA:6,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +DA:9,4 +DA:19,5 +DA:21,5 +DA:22,5 +DA:23,5 +DA:24,5 +DA:27,5 +DA:29,1 +DA:31,5 +DA:32,1 +DA:40,4 +DA:48,5 +DA:49,5 +DA:50,1 +DA:51,1 +DA:52,1 +DA:59,4 +DA:60,4 +DA:61,2 +DA:62,2 +DA:63,2 +DA:70,4 +DA:72,0 +DA:88,3 +DA:90,3 +DA:96,3 +DA:97,3 +DA:103,3 +DA:104,0 +DA:105,0 +DA:107,0 +DA:108,0 +DA:109,3 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:120,3 +DA:121,2 +DA:122,2 +DA:123,2 +DA:124,4 +DA:125,4 +DA:126,4 +DA:127,0 +DA:128,0 +DA:130,0 +DA:132,4 +DA:135,2 +DA:136,2 +DA:139,4 +DA:140,2 +DA:142,2 +DA:143,4 +DA:144,4 +DA:146,4 +DA:148,4 +DA:149,4 +DA:150,4 +DA:155,0 +DA:158,4 +DA:160,4 +DA:161,4 +DA:162,4 +DA:163,4 +DA:168,4 +DA:173,4 +DA:176,2 +DA:177,2 +DA:178,2 +DA:179,2 +DA:180,2 +DA:182,2 +DA:183,2 +DA:184,2 +DA:185,2 +DA:186,2 +DA:187,2 +DA:188,2 +DA:189,0 +DA:192,2 +DA:195,2 +DA:196,4 +DA:197,4 +DA:198,4 +DA:200,4 +DA:201,4 +DA:202,4 +DA:203,2 +DA:204,2 +DA:207,2 +DA:208,2 +DA:209,2 +DA:210,2 +DA:211,2 +DA:212,2 +DA:213,2 +DA:214,2 +DA:220,4 +DA:221,4 +DA:222,4 +DA:225,2 +DA:226,4 +DA:227,2 +DA:231,2 +DA:233,6 +DA:234,6 +DA:239,2 +DA:240,0 +DA:241,0 +DA:252,0 +DA:253,0 +DA:261,2 +DA:262,0 +DA:270,1 +DA:271,1 +DA:272,1 +DA:286,1 +DA:292,0 +DA:297,0 +DA:298,0 +DA:300,0 +DA:301,0 +DA:304,0 +DA:312,3 +DA:314,0 +LF:127 +LH:100 +BRDA:19,0,0,5 +BRDA:19,1,0,5 +BRDA:27,2,0,5 +BRDA:27,2,1,3 +BRDA:27,2,2,2 +BRDA:31,3,0,1 +BRDA:31,3,1,4 +BRDA:41,4,0,4 +BRDA:41,4,1,1 +BRDA:51,5,0,1 +BRDA:51,5,1,0 +BRDA:54,6,0,1 +BRDA:54,6,1,0 +BRDA:54,6,2,0 +BRDA:62,7,0,2 +BRDA:62,7,1,0 +BRDA:65,8,0,2 +BRDA:65,8,1,1 +BRDA:65,8,2,0 +BRDA:88,9,0,3 +BRDA:88,10,0,3 +BRDA:103,11,0,0 +BRDA:103,11,1,3 +BRDA:104,12,0,0 +BRDA:104,12,1,0 +BRDA:109,13,0,0 +BRDA:109,13,1,3 +BRDA:113,14,0,0 +BRDA:113,14,1,0 +BRDA:120,15,0,2 +BRDA:120,15,1,1 +BRDA:124,16,0,4 +BRDA:124,16,1,0 +BRDA:125,17,0,0 +BRDA:125,17,1,4 +BRDA:126,18,0,0 +BRDA:126,18,1,4 +BRDA:127,19,0,0 +BRDA:127,19,1,0 +BRDA:135,20,0,2 +BRDA:135,20,1,0 +BRDA:150,21,0,0 +BRDA:150,21,1,4 +BRDA:151,22,0,4 +BRDA:151,22,1,0 +BRDA:151,22,2,0 +BRDA:163,23,0,4 +BRDA:163,23,1,0 +BRDA:164,24,0,4 +BRDA:164,24,1,4 +BRDA:164,24,2,4 +BRDA:184,25,0,0 +BRDA:184,25,1,2 +BRDA:188,26,0,0 +BRDA:188,26,1,2 +BRDA:196,27,0,0 +BRDA:196,27,1,4 +BRDA:200,28,0,4 +BRDA:200,28,1,0 +BRDA:202,29,0,2 +BRDA:202,29,1,2 +BRDA:202,30,0,4 +BRDA:202,30,1,2 +BRDA:207,31,0,2 +BRDA:207,31,1,0 +BRDA:209,32,0,2 +BRDA:209,32,1,0 +BRDA:212,33,0,2 +BRDA:212,33,1,0 +BRDA:212,34,0,2 +BRDA:212,34,1,2 +BRDA:226,35,0,2 +BRDA:226,35,1,2 +BRDA:234,36,0,6 +BRDA:234,36,1,0 +BRDA:239,37,0,0 +BRDA:239,37,1,2 +BRDA:239,38,0,2 +BRDA:239,38,1,0 +BRDA:239,38,2,0 +BRDA:252,39,0,0 +BRDA:252,39,1,0 +BRDA:261,40,0,0 +BRDA:261,40,1,2 +BRDA:264,41,0,0 +BRDA:264,41,1,0 +BRDA:270,42,0,1 +BRDA:270,42,1,0 +BRDA:284,43,0,1 +BRDA:284,43,1,0 +BRDA:286,44,0,1 +BRDA:286,44,1,0 +BRDA:287,45,0,0 +BRDA:287,45,1,0 +BRDA:288,46,0,0 +BRDA:288,46,1,0 +BRDA:289,47,0,0 +BRDA:289,47,1,0 +BRDA:297,48,0,0 +BRDA:297,48,1,0 +BRDA:300,49,0,0 +BRDA:300,49,1,0 +BRDA:300,49,2,0 +BRDA:306,50,0,0 +BRDA:306,50,1,0 +BRDA:306,50,2,0 +BRDA:307,51,0,0 +BRDA:307,51,1,0 +BRDA:307,51,2,0 +BRF:109 +BRH:52 +end_of_record +TN: +SF:src/tools/handlers/core-graph-tools.ts +FN:16,deriveLabelHints +FN:19,(anonymous_1) +FN:25,filterTemporalRows +FN:34,(anonymous_3) +FN:59,fetchGlobalCommunityRows +FN:68,(anonymous_5) +FN:124,(anonymous_6) +FN:254,(anonymous_7) +FN:370,(anonymous_8) +FN:442,(anonymous_9) +FN:461,(anonymous_10) +FN:465,(anonymous_11) +FN:466,(anonymous_12) +FN:502,(anonymous_13) +FN:558,(anonymous_14) +FN:638,(anonymous_15) +FN:701,(anonymous_16) +FN:834,(anonymous_17) +FN:855,(anonymous_18) +FN:856,(anonymous_19) +FN:884,(anonymous_20) +FN:943,(anonymous_21) +FN:944,(anonymous_22) +FNF:23 +FNH:19 +FNDA:1,deriveLabelHints +FNDA:6,(anonymous_1) +FNDA:3,filterTemporalRows +FNDA:0,(anonymous_3) +FNDA:1,fetchGlobalCommunityRows +FNDA:1,(anonymous_5) +FNDA:13,(anonymous_6) +FNDA:4,(anonymous_7) +FNDA:4,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:3,(anonymous_10) +FNDA:4,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:15,(anonymous_14) +FNDA:6,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:3,(anonymous_17) +FNDA:9,(anonymous_18) +FNDA:9,(anonymous_19) +FNDA:2,(anonymous_20) +FNDA:6,(anonymous_21) +FNDA:3,(anonymous_22) +DA:17,1 +DA:18,1 +DA:19,6 +DA:30,3 +DA:31,3 +DA:34,0 +DA:35,0 +DA:36,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:49,0 +DA:65,1 +DA:68,1 +DA:70,1 +DA:77,1 +DA:87,1 +DA:88,1 +DA:91,0 +DA:99,0 +DA:106,4 +DA:132,13 +DA:134,13 +DA:145,13 +DA:147,13 +DA:148,13 +DA:149,13 +DA:151,13 +DA:153,10 +DA:155,10 +DA:162,3 +DA:163,1 +DA:165,1 +DA:166,0 +DA:168,1 +DA:174,1 +DA:175,1 +DA:189,2 +DA:195,2 +DA:196,2 +DA:200,13 +DA:201,0 +DA:209,13 +DA:210,13 +DA:225,0 +DA:255,4 +DA:257,4 +DA:272,4 +DA:278,4 +DA:289,4 +DA:299,4 +DA:305,4 +DA:306,4 +DA:307,0 +DA:314,4 +DA:315,4 +DA:317,4 +DA:319,4 +DA:324,0 +DA:332,4 +DA:333,4 +DA:334,4 +DA:335,4 +DA:336,4 +DA:338,4 +DA:339,3 +DA:352,4 +DA:353,0 +DA:361,4 +DA:362,0 +DA:370,4 +DA:380,4 +DA:384,4 +DA:385,3 +DA:386,0 +DA:391,3 +DA:392,2 +DA:393,2 +DA:396,1 +DA:397,1 +DA:398,1 +DA:399,1 +DA:400,0 +DA:401,0 +DA:402,0 +DA:407,0 +DA:413,1 +DA:414,1 +DA:419,3 +DA:420,3 +DA:421,3 +DA:422,0 +DA:423,0 +DA:426,3 +DA:429,4 +DA:443,1 +DA:444,1 +DA:446,1 +DA:447,1 +DA:448,1 +DA:451,1 +DA:452,1 +DA:455,1 +DA:458,4 +DA:460,4 +DA:461,3 +DA:466,4 +DA:470,3 +DA:471,3 +DA:473,3 +DA:474,3 +DA:502,0 +DA:506,0 +DA:533,1 +DA:559,15 +DA:561,15 +DA:562,15 +DA:563,15 +DA:565,15 +DA:567,15 +DA:572,1 +DA:580,14 +DA:582,14 +DA:583,0 +DA:591,14 +DA:592,0 +DA:600,14 +DA:601,14 +DA:603,14 +DA:605,14 +DA:619,0 +DA:639,6 +DA:641,6 +DA:648,6 +DA:649,6 +DA:651,6 +DA:667,6 +DA:668,6 +DA:669,6 +DA:670,6 +DA:671,6 +DA:672,6 +DA:673,6 +DA:675,6 +DA:677,6 +DA:678,6 +DA:679,6 +DA:680,6 +DA:681,6 +DA:683,6 +DA:684,6 +DA:685,0 +DA:686,0 +DA:691,0 +DA:697,6 +DA:698,6 +DA:701,0 +DA:704,6 +DA:713,6 +DA:714,6 +DA:716,6 +DA:723,6 +DA:724,6 +DA:725,6 +DA:728,6 +DA:730,6 +DA:731,6 +DA:732,2 +DA:736,6 +DA:737,0 +DA:742,6 +DA:811,0 +DA:835,3 +DA:837,3 +DA:838,0 +DA:846,3 +DA:847,3 +DA:849,3 +DA:853,3 +DA:855,9 +DA:856,9 +DA:859,3 +DA:860,0 +DA:867,3 +DA:868,3 +DA:869,1 +DA:877,2 +DA:884,2 +DA:886,3 +DA:903,2 +DA:920,2 +DA:943,6 +DA:944,3 +DA:953,2 +DA:954,3 +DA:955,3 +DA:957,3 +DA:959,3 +DA:978,0 +LF:202 +LH:162 +BRDA:30,0,0,3 +BRDA:30,0,1,0 +BRDA:30,1,0,3 +BRDA:30,1,1,0 +BRDA:35,2,0,0 +BRDA:35,2,1,0 +BRDA:43,3,0,0 +BRDA:43,3,1,0 +BRDA:43,4,0,0 +BRDA:43,4,1,0 +BRDA:45,5,0,0 +BRDA:45,5,1,0 +BRDA:50,6,0,0 +BRDA:50,6,1,0 +BRDA:50,6,2,0 +BRDA:50,6,3,0 +BRDA:73,7,0,1 +BRDA:73,7,1,0 +BRDA:87,8,0,1 +BRDA:87,8,1,0 +BRDA:127,9,0,13 +BRDA:128,10,0,13 +BRDA:129,11,0,13 +BRDA:131,12,0,13 +BRDA:149,13,0,1 +BRDA:149,13,1,12 +BRDA:149,14,0,13 +BRDA:149,14,1,13 +BRDA:151,15,0,10 +BRDA:151,15,1,3 +BRDA:153,16,0,1 +BRDA:153,16,1,9 +BRDA:156,17,0,1 +BRDA:156,17,1,9 +BRDA:162,18,0,1 +BRDA:162,18,1,2 +BRDA:162,19,0,3 +BRDA:162,19,1,3 +BRDA:165,20,0,0 +BRDA:165,20,1,1 +BRDA:200,21,0,0 +BRDA:200,21,1,13 +BRDA:212,22,0,3 +BRDA:212,22,1,10 +BRDA:255,23,0,4 +BRDA:255,24,0,4 +BRDA:255,25,0,4 +BRDA:255,26,0,4 +BRDA:306,27,0,0 +BRDA:306,27,1,4 +BRDA:314,28,0,4 +BRDA:314,28,1,0 +BRDA:317,29,0,4 +BRDA:317,29,1,4 +BRDA:319,30,0,0 +BRDA:319,30,1,4 +BRDA:320,31,0,4 +BRDA:320,31,1,0 +BRDA:320,31,2,0 +BRDA:338,32,0,3 +BRDA:338,32,1,1 +BRDA:344,33,0,1 +BRDA:344,33,1,2 +BRDA:352,34,0,0 +BRDA:352,34,1,4 +BRDA:361,35,0,0 +BRDA:361,35,1,4 +BRDA:385,36,0,0 +BRDA:385,36,1,3 +BRDA:391,37,0,2 +BRDA:391,37,1,1 +BRDA:396,38,0,1 +BRDA:396,38,1,0 +BRDA:399,39,0,0 +BRDA:399,39,1,1 +BRDA:399,40,0,1 +BRDA:399,40,1,1 +BRDA:420,41,0,3 +BRDA:420,41,1,0 +BRDA:422,42,0,0 +BRDA:422,42,1,0 +BRDA:446,43,0,1 +BRDA:446,43,1,0 +BRDA:447,44,0,1 +BRDA:447,44,1,0 +BRDA:451,45,0,1 +BRDA:451,45,1,0 +BRDA:473,46,0,3 +BRDA:473,46,1,0 +BRDA:493,47,0,3 +BRDA:493,47,1,3 +BRDA:524,48,0,0 +BRDA:524,48,1,0 +BRDA:525,49,0,0 +BRDA:525,49,1,0 +BRDA:559,50,0,15 +BRDA:559,51,0,15 +BRDA:559,51,1,0 +BRDA:562,52,0,15 +BRDA:562,52,1,0 +BRDA:565,53,0,15 +BRDA:565,53,1,15 +BRDA:567,54,0,1 +BRDA:567,54,1,14 +BRDA:568,55,0,15 +BRDA:568,55,1,1 +BRDA:568,55,2,1 +BRDA:582,56,0,0 +BRDA:582,56,1,14 +BRDA:591,57,0,0 +BRDA:591,57,1,14 +BRDA:610,58,0,14 +BRDA:610,58,1,14 +BRDA:611,59,0,15 +BRDA:611,59,1,14 +BRDA:613,60,0,15 +BRDA:613,60,1,14 +BRDA:639,61,0,6 +BRDA:639,61,1,0 +BRDA:667,62,0,6 +BRDA:667,62,1,4 +BRDA:668,63,0,6 +BRDA:668,63,1,4 +BRDA:669,64,0,6 +BRDA:669,64,1,4 +BRDA:670,65,0,6 +BRDA:670,65,1,4 +BRDA:671,66,0,6 +BRDA:671,66,1,4 +BRDA:672,67,0,6 +BRDA:672,67,1,4 +BRDA:673,68,0,6 +BRDA:673,68,1,6 +BRDA:684,69,0,0 +BRDA:684,69,1,6 +BRDA:692,70,0,0 +BRDA:692,70,1,0 +BRDA:692,71,0,0 +BRDA:692,71,1,0 +BRDA:692,72,0,0 +BRDA:692,72,1,0 +BRDA:697,73,0,6 +BRDA:697,73,1,0 +BRDA:699,74,0,6 +BRDA:699,74,1,6 +BRDA:704,75,0,2 +BRDA:704,75,1,4 +BRDA:723,76,0,6 +BRDA:723,76,1,4 +BRDA:724,77,0,6 +BRDA:724,77,1,4 +BRDA:726,78,0,6 +BRDA:726,78,1,4 +BRDA:731,79,0,2 +BRDA:731,79,1,4 +BRDA:736,80,0,0 +BRDA:736,80,1,6 +BRDA:736,81,0,6 +BRDA:736,81,1,0 +BRDA:744,82,0,2 +BRDA:744,82,1,4 +BRDA:749,83,0,6 +BRDA:749,83,1,6 +BRDA:764,84,0,2 +BRDA:764,84,1,4 +BRDA:774,85,0,2 +BRDA:774,85,1,4 +BRDA:774,86,0,6 +BRDA:774,86,1,6 +BRDA:777,87,0,0 +BRDA:777,87,1,4 +BRDA:782,88,0,6 +BRDA:782,88,1,0 +BRDA:783,89,0,6 +BRDA:783,89,1,0 +BRDA:787,90,0,0 +BRDA:787,90,1,6 +BRDA:790,91,0,6 +BRDA:790,91,1,6 +BRDA:791,92,0,6 +BRDA:791,92,1,6 +BRDA:792,93,0,6 +BRDA:792,93,1,4 +BRDA:794,94,0,6 +BRDA:794,94,1,4 +BRDA:794,94,2,4 +BRDA:795,95,0,6 +BRDA:795,95,1,0 +BRDA:802,96,0,6 +BRDA:802,96,1,6 +BRDA:803,97,0,6 +BRDA:803,97,1,6 +BRDA:807,98,0,2 +BRDA:807,98,1,4 +BRDA:835,99,0,3 +BRDA:835,100,0,3 +BRDA:835,101,0,3 +BRDA:835,101,1,0 +BRDA:837,102,0,0 +BRDA:837,102,1,3 +BRDA:837,103,0,3 +BRDA:837,103,1,3 +BRDA:849,104,0,2 +BRDA:849,104,1,1 +BRDA:849,105,0,3 +BRDA:849,105,1,2 +BRDA:853,106,0,3 +BRDA:853,106,1,0 +BRDA:859,107,0,0 +BRDA:859,107,1,3 +BRDA:868,108,0,1 +BRDA:868,108,1,2 +BRDA:884,109,0,2 +BRDA:884,109,1,0 +BRDA:884,110,0,2 +BRDA:884,110,1,0 +BRDA:944,111,0,6 +BRDA:944,111,1,0 +BRDA:945,112,0,3 +BRDA:945,112,1,0 +BRDA:946,113,0,3 +BRDA:946,113,1,0 +BRDA:947,114,0,3 +BRDA:947,114,1,0 +BRDA:948,115,0,2 +BRDA:948,115,1,1 +BRDA:950,116,0,3 +BRDA:950,116,1,2 +BRDA:953,117,0,2 +BRDA:953,117,1,0 +BRDA:954,118,0,3 +BRDA:954,118,1,0 +BRDA:955,119,0,3 +BRDA:955,119,1,0 +BRF:234 +BRH:162 +end_of_record +TN: +SF:src/tools/handlers/core-semantic-tools.ts +FN:23,(anonymous_0) +FN:54,(anonymous_1) +FN:81,(anonymous_2) +FN:113,(anonymous_3) +FN:139,(anonymous_4) +FN:158,(anonymous_5) +FN:172,(anonymous_6) +FN:177,(anonymous_7) +FN:201,(anonymous_8) +FN:220,(anonymous_9) +FN:223,(anonymous_10) +FN:233,(anonymous_11) +FN:234,(anonymous_12) +FN:255,(anonymous_13) +FN:323,(anonymous_14) +FN:353,(anonymous_15) +FNF:16 +FNH:15 +FNDA:2,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:4,(anonymous_5) +FNDA:2,(anonymous_6) +FNDA:1,(anonymous_7) +FNDA:2,(anonymous_8) +FNDA:6,(anonymous_9) +FNDA:6,(anonymous_10) +FNDA:6,(anonymous_11) +FNDA:6,(anonymous_12) +FNDA:2,(anonymous_13) +FNDA:2,(anonymous_14) +FNDA:2,(anonymous_15) +DA:9,4 +DA:24,2 +DA:26,2 +DA:44,2 +DA:45,2 +DA:46,2 +DA:47,2 +DA:49,2 +DA:54,1 +DA:64,0 +DA:82,1 +DA:84,1 +DA:102,1 +DA:103,1 +DA:104,1 +DA:105,1 +DA:106,1 +DA:108,1 +DA:113,0 +DA:123,0 +DA:140,1 +DA:142,1 +DA:153,1 +DA:154,1 +DA:155,1 +DA:156,1 +DA:158,4 +DA:161,1 +DA:162,1 +DA:163,4 +DA:164,4 +DA:165,4 +DA:166,2 +DA:168,4 +DA:171,1 +DA:172,2 +DA:177,1 +DA:180,1 +DA:185,0 +DA:202,2 +DA:204,2 +DA:205,2 +DA:206,2 +DA:208,2 +DA:209,1 +DA:216,1 +DA:217,2 +DA:218,2 +DA:219,2 +DA:220,6 +DA:222,2 +DA:223,6 +DA:226,2 +DA:233,6 +DA:234,6 +DA:239,0 +DA:256,2 +DA:258,2 +DA:272,2 +DA:273,2 +DA:275,2 +DA:280,2 +DA:281,0 +DA:288,2 +DA:289,2 +DA:291,2 +DA:302,0 +DA:324,2 +DA:325,2 +DA:326,0 +DA:332,2 +DA:354,2 +DA:355,2 +DA:356,0 +DA:362,2 +LF:75 +LH:66 +BRDA:24,0,0,2 +BRDA:24,1,0,2 +BRDA:24,2,0,2 +BRDA:82,3,0,1 +BRDA:82,4,0,1 +BRDA:82,5,0,1 +BRDA:140,6,0,1 +BRDA:140,7,0,1 +BRDA:158,8,0,4 +BRDA:158,8,1,4 +BRDA:163,9,0,4 +BRDA:163,9,1,0 +BRDA:164,10,0,4 +BRDA:164,10,1,0 +BRDA:165,11,0,2 +BRDA:165,11,1,2 +BRDA:202,12,0,2 +BRDA:208,13,0,1 +BRDA:208,13,1,1 +BRDA:208,14,0,2 +BRDA:208,14,1,1 +BRDA:216,15,0,1 +BRDA:216,15,1,0 +BRDA:217,16,0,2 +BRDA:217,16,1,0 +BRDA:228,17,0,2 +BRDA:228,17,1,0 +BRDA:228,17,2,0 +BRDA:229,18,0,2 +BRDA:229,18,1,0 +BRDA:229,18,2,0 +BRDA:256,19,0,2 +BRDA:256,20,0,2 +BRDA:275,21,0,2 +BRDA:275,21,1,2 +BRDA:275,21,2,2 +BRDA:275,21,3,2 +BRDA:278,22,0,2 +BRDA:278,22,1,0 +BRDA:278,23,0,2 +BRDA:278,23,1,2 +BRDA:280,24,0,0 +BRDA:280,24,1,2 +BRDA:325,25,0,0 +BRDA:325,25,1,2 +BRDA:355,26,0,0 +BRDA:355,26,1,2 +BRF:47 +BRH:35 +end_of_record +TN: +SF:src/tools/handlers/core-setup-tools.ts +FN:37,(anonymous_0) +FN:221,(anonymous_1) +FN:307,(anonymous_2) +FN:313,(anonymous_3) +FN:321,(anonymous_4) +FN:322,(anonymous_5) +FN:351,(anonymous_6) +FNF:7 +FNH:4 +FNDA:3,(anonymous_0) +FNDA:6,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:9,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +DA:11,4 +DA:45,3 +DA:47,3 +DA:48,1 +DA:56,2 +DA:57,2 +DA:58,0 +DA:66,2 +DA:68,2 +DA:69,2 +DA:70,2 +DA:71,2 +DA:74,2 +DA:75,2 +DA:76,2 +DA:77,2 +DA:78,0 +DA:83,0 +DA:90,2 +DA:91,3 +DA:97,0 +DA:102,0 +DA:110,2 +DA:116,2 +DA:117,2 +DA:119,2 +DA:120,2 +DA:121,2 +DA:122,2 +DA:123,1 +DA:129,1 +DA:136,0 +DA:143,2 +DA:144,2 +DA:145,2 +DA:146,2 +DA:152,2 +DA:158,0 +DA:165,0 +DA:172,2 +DA:178,3 +DA:192,0 +DA:228,6 +DA:231,6 +DA:232,6 +DA:234,0 +DA:235,0 +DA:238,6 +DA:239,1 +DA:247,5 +DA:248,5 +DA:249,0 +DA:261,5 +DA:262,5 +DA:263,6 +DA:264,6 +DA:268,6 +DA:269,6 +DA:270,6 +DA:275,6 +DA:277,6 +DA:278,6 +DA:280,6 +DA:283,6 +DA:284,6 +DA:286,6 +DA:288,6 +DA:289,6 +DA:291,6 +DA:294,6 +DA:295,1 +DA:296,5 +DA:297,5 +DA:298,5 +DA:299,5 +DA:300,5 +DA:301,0 +DA:302,5 +DA:304,5 +DA:307,1 +DA:311,6 +DA:313,9 +DA:315,6 +DA:316,6 +DA:317,6 +DA:318,4 +DA:319,4 +DA:321,0 +DA:322,0 +DA:330,5 +DA:334,6 +DA:335,6 +DA:336,0 +DA:339,5 +DA:340,5 +DA:345,5 +DA:346,1 +DA:347,1 +DA:348,1 +DA:349,1 +DA:350,0 +DA:351,0 +DA:355,5 +DA:356,1 +DA:359,5 +DA:360,0 +DA:378,5 +DA:388,5 +DA:405,5 +DA:440,5 +DA:457,5 +DA:492,5 +DA:499,5 +DA:501,5 +DA:502,1 +DA:514,4 +DA:515,4 +DA:516,4 +DA:518,4 +DA:520,4 +DA:533,0 +LF:121 +LH:101 +BRDA:42,0,0,3 +BRDA:43,1,0,3 +BRDA:44,2,0,3 +BRDA:45,3,0,3 +BRDA:45,3,1,0 +BRDA:47,4,0,1 +BRDA:47,4,1,2 +BRDA:47,5,0,3 +BRDA:47,5,1,2 +BRDA:57,6,0,0 +BRDA:57,6,1,2 +BRDA:70,7,0,1 +BRDA:70,7,1,1 +BRDA:71,8,0,1 +BRDA:71,8,1,1 +BRDA:77,9,0,0 +BRDA:77,9,1,2 +BRDA:90,10,0,2 +BRDA:90,10,1,0 +BRDA:90,10,2,0 +BRDA:94,11,0,3 +BRDA:94,11,1,0 +BRDA:94,12,0,3 +BRDA:94,12,1,0 +BRDA:116,13,0,1 +BRDA:116,13,1,1 +BRDA:117,14,0,1 +BRDA:117,14,1,1 +BRDA:122,15,0,1 +BRDA:122,15,1,1 +BRDA:144,16,0,2 +BRDA:144,16,1,0 +BRDA:174,17,0,1 +BRDA:174,17,1,1 +BRDA:175,18,0,1 +BRDA:175,18,1,1 +BRDA:194,19,0,0 +BRDA:194,19,1,0 +BRDA:225,20,0,6 +BRDA:226,21,0,6 +BRDA:227,22,0,6 +BRDA:228,23,0,6 +BRDA:228,23,1,0 +BRDA:231,24,0,6 +BRDA:231,24,1,0 +BRDA:231,25,0,6 +BRDA:231,25,1,6 +BRDA:238,26,0,1 +BRDA:238,26,1,5 +BRDA:248,27,0,0 +BRDA:248,27,1,5 +BRDA:248,28,0,5 +BRDA:248,28,1,0 +BRDA:248,28,2,0 +BRDA:262,29,0,5 +BRDA:262,29,1,4 +BRDA:264,30,0,1 +BRDA:264,30,1,4 +BRDA:268,31,0,6 +BRDA:268,31,1,4 +BRDA:268,31,2,3 +BRDA:269,32,0,6 +BRDA:269,32,1,5 +BRDA:271,33,0,6 +BRDA:271,33,1,5 +BRDA:272,34,0,6 +BRDA:272,34,1,5 +BRDA:277,35,0,6 +BRDA:277,35,1,5 +BRDA:278,36,0,6 +BRDA:278,36,1,4 +BRDA:280,37,0,6 +BRDA:280,37,1,5 +BRDA:280,37,2,5 +BRDA:286,38,0,6 +BRDA:286,38,1,5 +BRDA:291,39,0,6 +BRDA:291,39,1,5 +BRDA:294,40,0,0 +BRDA:294,40,1,5 +BRDA:294,41,0,1 +BRDA:294,41,1,4 +BRDA:296,42,0,0 +BRDA:296,42,1,5 +BRDA:297,43,0,0 +BRDA:297,43,1,5 +BRDA:298,44,0,0 +BRDA:298,44,1,5 +BRDA:299,45,0,0 +BRDA:299,45,1,5 +BRDA:300,46,0,0 +BRDA:300,46,1,5 +BRDA:300,47,0,0 +BRDA:300,47,1,5 +BRDA:302,48,0,0 +BRDA:302,48,1,5 +BRDA:304,49,0,1 +BRDA:304,49,1,4 +BRDA:313,50,0,6 +BRDA:313,50,1,1 +BRDA:317,51,0,4 +BRDA:317,51,1,2 +BRDA:330,52,0,5 +BRDA:330,52,1,5 +BRDA:330,52,2,5 +BRDA:335,53,0,0 +BRDA:335,53,1,6 +BRDA:345,54,0,1 +BRDA:345,54,1,4 +BRDA:349,55,0,0 +BRDA:349,55,1,1 +BRDA:355,56,0,1 +BRDA:355,56,1,4 +BRDA:359,57,0,0 +BRDA:359,57,1,5 +BRDA:501,58,0,1 +BRDA:501,58,1,4 +BRDA:515,59,0,4 +BRDA:515,59,1,0 +BRDA:526,60,0,4 +BRDA:526,60,1,0 +BRDA:535,61,0,0 +BRDA:535,61,1,0 +BRF:123 +BRH:93 +end_of_record +TN: +SF:src/tools/handlers/core-utility-tools.ts +FN:21,(anonymous_0) +FN:74,(anonymous_1) +FN:78,(anonymous_2) +FN:104,(anonymous_3) +FNF:4 +FNH:4 +FNDA:2,(anonymous_0) +FNDA:16,(anonymous_1) +FNDA:16,(anonymous_2) +FNDA:3,(anonymous_3) +DA:9,4 +DA:22,2 +DA:24,2 +DA:57,2 +DA:59,2 +DA:60,16 +DA:61,16 +DA:62,16 +DA:63,72 +DA:64,72 +DA:65,72 +DA:67,0 +DA:70,16 +DA:73,2 +DA:74,16 +DA:77,2 +DA:78,16 +DA:82,2 +DA:105,3 +DA:107,3 +DA:108,0 +DA:115,3 +DA:117,3 +DA:120,3 +DA:122,3 +DA:136,0 +LF:26 +LH:23 +BRDA:22,0,0,2 +BRDA:22,0,1,0 +BRDA:64,1,0,72 +BRDA:64,1,1,0 +BRDA:105,2,0,3 +BRDA:105,3,0,3 +BRDA:105,4,0,3 +BRDA:105,4,1,0 +BRDA:107,5,0,0 +BRDA:107,5,1,3 +BRDA:107,6,0,3 +BRDA:107,6,1,3 +BRF:12 +BRH:8 +end_of_record +TN: +SF:src/tools/handlers/docs-tools.ts +FN:34,(anonymous_0) +FN:118,(anonymous_1) +FN:165,(anonymous_2) +FNF:3 +FNH:3 +FNDA:6,(anonymous_0) +FNDA:7,(anonymous_1) +FNDA:4,(anonymous_2) +DA:13,4 +DA:40,6 +DA:41,6 +DA:42,6 +DA:47,6 +DA:62,6 +DA:63,1 +DA:66,5 +DA:71,5 +DA:85,0 +DA:119,7 +DA:120,7 +DA:121,7 +DA:125,7 +DA:140,7 +DA:141,1 +DA:145,6 +DA:146,1 +DA:149,5 +DA:150,4 +DA:154,1 +DA:161,5 +DA:165,4 +DA:178,0 +LF:24 +LH:22 +BRDA:38,0,0,6 +BRDA:39,1,0,6 +BRDA:40,2,0,6 +BRDA:40,2,1,0 +BRDA:62,3,0,1 +BRDA:62,3,1,5 +BRDA:87,4,0,0 +BRDA:87,4,1,0 +BRDA:119,5,0,7 +BRDA:119,6,0,7 +BRDA:119,6,1,0 +BRDA:140,7,0,1 +BRDA:140,7,1,6 +BRDA:145,8,0,1 +BRDA:145,8,1,5 +BRDA:145,9,0,6 +BRDA:145,9,1,1 +BRDA:149,10,0,4 +BRDA:149,10,1,1 +BRDA:149,11,0,5 +BRDA:149,11,1,4 +BRDA:180,12,0,0 +BRDA:180,12,1,0 +BRF:23 +BRH:17 +end_of_record +TN: +SF:src/tools/handlers/memory-coordination-tools.ts +FN:42,(anonymous_0) +FN:72,(anonymous_1) +FN:156,(anonymous_2) +FN:195,(anonymous_3) +FN:205,(anonymous_4) +FN:243,(anonymous_5) +FN:282,(anonymous_6) +FN:315,(anonymous_7) +FN:367,(anonymous_8) +FN:442,(anonymous_9) +FN:492,(anonymous_10) +FN:549,(anonymous_11) +FNF:12 +FNH:9 +FNDA:8,(anonymous_0) +FNDA:2,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:2,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:2,(anonymous_7) +FNDA:4,(anonymous_8) +FNDA:2,(anonymous_9) +FNDA:4,(anonymous_10) +FNDA:2,(anonymous_11) +DA:17,4 +DA:54,8 +DA:56,8 +DA:59,8 +DA:60,1 +DA:61,1 +DA:69,7 +DA:70,7 +DA:71,7 +DA:72,2 +DA:74,8 +DA:75,8 +DA:81,8 +DA:82,2 +DA:85,5 +DA:104,5 +DA:105,5 +DA:106,8 +DA:107,8 +DA:109,8 +DA:124,5 +DA:135,0 +DA:166,3 +DA:168,3 +DA:169,1 +DA:176,2 +DA:191,2 +DA:192,2 +DA:193,2 +DA:194,2 +DA:195,0 +DA:197,3 +DA:198,2 +DA:199,2 +DA:205,0 +DA:212,2 +DA:224,0 +DA:251,2 +DA:253,2 +DA:254,0 +DA:261,2 +DA:274,2 +DA:275,2 +DA:276,2 +DA:282,0 +DA:287,2 +DA:298,0 +DA:316,2 +DA:318,2 +DA:329,2 +DA:330,2 +DA:331,2 +DA:338,2 +DA:344,0 +DA:376,4 +DA:378,4 +DA:379,1 +DA:386,3 +DA:400,3 +DA:401,3 +DA:402,4 +DA:403,4 +DA:405,4 +DA:415,3 +DA:426,0 +DA:443,2 +DA:445,2 +DA:446,0 +DA:453,2 +DA:462,2 +DA:463,2 +DA:465,2 +DA:477,0 +DA:493,4 +DA:495,4 +DA:508,4 +DA:509,4 +DA:511,4 +DA:512,2 +DA:513,2 +DA:524,2 +DA:526,2 +DA:535,0 +DA:550,2 +DA:552,2 +DA:561,2 +DA:562,2 +DA:563,2 +DA:565,2 +DA:574,0 +LF:90 +LH:77 +BRDA:46,0,0,8 +BRDA:50,1,0,8 +BRDA:51,2,0,8 +BRDA:54,3,0,8 +BRDA:54,3,1,0 +BRDA:57,4,0,8 +BRDA:57,4,1,1 +BRDA:57,5,0,8 +BRDA:57,5,1,7 +BRDA:59,6,0,1 +BRDA:59,6,1,7 +BRDA:59,7,0,8 +BRDA:59,7,1,8 +BRDA:71,8,0,7 +BRDA:71,8,1,0 +BRDA:74,9,0,3 +BRDA:74,9,1,4 +BRDA:74,10,0,8 +BRDA:74,10,1,3 +BRDA:81,11,0,2 +BRDA:81,11,1,6 +BRDA:105,12,0,5 +BRDA:105,12,1,5 +BRDA:106,13,0,8 +BRDA:106,13,1,4 +BRDA:114,14,0,0 +BRDA:114,14,1,5 +BRDA:119,15,0,8 +BRDA:119,15,1,4 +BRDA:129,16,0,5 +BRDA:129,16,1,5 +BRDA:163,17,0,3 +BRDA:165,18,0,3 +BRDA:166,19,0,3 +BRDA:166,19,1,0 +BRDA:168,20,0,1 +BRDA:168,20,1,2 +BRDA:168,21,0,3 +BRDA:168,21,1,2 +BRDA:194,22,0,0 +BRDA:194,22,1,2 +BRDA:204,23,0,0 +BRDA:204,23,1,2 +BRDA:207,24,0,0 +BRDA:207,24,1,2 +BRDA:209,25,0,3 +BRDA:209,25,1,2 +BRDA:216,26,0,1 +BRDA:216,26,1,1 +BRDA:246,27,0,2 +BRDA:247,28,0,2 +BRDA:250,29,0,2 +BRDA:251,30,0,2 +BRDA:251,30,1,0 +BRDA:253,31,0,0 +BRDA:253,31,1,2 +BRDA:253,32,0,2 +BRDA:253,32,1,2 +BRDA:281,33,0,2 +BRDA:281,33,1,0 +BRDA:316,34,0,2 +BRDA:316,35,0,2 +BRDA:316,36,0,2 +BRDA:316,36,1,0 +BRDA:370,37,0,4 +BRDA:375,38,0,4 +BRDA:376,39,0,4 +BRDA:376,39,1,0 +BRDA:378,40,0,1 +BRDA:378,40,1,3 +BRDA:378,41,0,4 +BRDA:378,41,1,4 +BRDA:401,42,0,3 +BRDA:401,42,1,3 +BRDA:402,43,0,4 +BRDA:402,43,1,1 +BRDA:409,44,0,1 +BRDA:409,44,1,2 +BRDA:411,45,0,4 +BRDA:411,45,1,1 +BRDA:421,46,0,1 +BRDA:421,46,1,2 +BRDA:443,47,0,2 +BRDA:443,48,0,2 +BRDA:443,48,1,0 +BRDA:445,49,0,0 +BRDA:445,49,1,2 +BRDA:468,50,0,2 +BRDA:468,50,1,2 +BRDA:471,51,0,2 +BRDA:471,51,1,0 +BRDA:474,52,0,2 +BRDA:474,52,1,0 +BRDA:493,53,0,4 +BRDA:493,54,0,4 +BRDA:493,54,1,0 +BRDA:511,55,0,2 +BRDA:511,55,1,2 +BRDA:511,56,0,4 +BRDA:511,56,1,2 +BRDA:550,57,0,2 +BRDA:550,58,0,2 +BRDA:550,58,1,0 +BRF:103 +BRH:85 +end_of_record +TN: +SF:src/tools/handlers/ref-tools.ts +FN:50,(anonymous_0) +FN:95,(anonymous_1) +FN:138,(anonymous_2) +FN:166,(anonymous_3) +FN:205,inferRefMode +FN:225,scoreRefSection +FN:237,(anonymous_6) +FN:246,scoreRefCode +FN:274,extractRefExcerpt +FN:304,scanRefSourceFiles +FN:319,(anonymous_10) +FN:347,buildRefDirTree +FN:361,(anonymous_12) +FNF:13 +FNH:12 +FNDA:3,(anonymous_0) +FNDA:4,(anonymous_1) +FNDA:4,(anonymous_2) +FNDA:3,(anonymous_3) +FNDA:1,inferRefMode +FNDA:1,scoreRefSection +FNDA:0,(anonymous_6) +FNDA:2,scoreRefCode +FNDA:2,extractRefExcerpt +FNDA:2,scanRefSourceFiles +FNDA:4,(anonymous_10) +FNDA:2,buildRefDirTree +FNDA:4,(anonymous_12) +DA:18,4 +DA:58,3 +DA:60,3 +DA:61,1 +DA:69,2 +DA:70,2 +DA:71,0 +DA:79,2 +DA:80,2 +DA:81,2 +DA:83,2 +DA:85,3 +DA:90,2 +DA:91,2 +DA:92,2 +DA:95,4 +DA:97,2 +DA:98,1 +DA:99,1 +DA:100,1 +DA:101,1 +DA:102,1 +DA:103,1 +DA:120,2 +DA:121,2 +DA:134,2 +DA:135,2 +DA:138,4 +DA:140,2 +DA:141,2 +DA:142,2 +DA:143,2 +DA:144,2 +DA:145,2 +DA:146,2 +DA:147,2 +DA:160,2 +DA:161,2 +DA:162,2 +DA:165,2 +DA:167,3 +DA:168,1 +DA:169,1 +DA:173,2 +DA:188,0 +DA:209,1 +DA:210,1 +DA:211,1 +DA:216,0 +DA:217,1 +DA:218,1 +DA:219,1 +DA:226,1 +DA:227,1 +DA:228,1 +DA:229,2 +DA:230,2 +DA:231,2 +DA:232,2 +DA:235,1 +DA:236,0 +DA:237,0 +DA:238,0 +DA:240,1 +DA:252,2 +DA:253,2 +DA:254,2 +DA:255,2 +DA:256,4 +DA:257,4 +DA:258,4 +DA:259,4 +DA:261,2 +DA:262,0 +DA:263,0 +DA:266,0 +DA:268,2 +DA:280,2 +DA:281,2 +DA:282,2 +DA:283,2 +DA:284,3 +DA:285,3 +DA:286,3 +DA:287,3 +DA:288,6 +DA:290,3 +DA:291,1 +DA:292,1 +DA:295,2 +DA:296,1 +DA:297,1 +DA:298,1 +DA:305,2 +DA:306,2 +DA:319,2 +DA:320,4 +DA:321,4 +DA:322,4 +DA:323,4 +DA:324,5 +DA:325,2 +DA:326,2 +DA:328,3 +DA:329,3 +DA:330,3 +DA:331,2 +DA:340,2 +DA:341,2 +DA:348,2 +DA:361,2 +DA:362,4 +DA:363,4 +DA:364,4 +DA:365,4 +DA:366,4 +DA:367,4 +DA:368,5 +DA:369,2 +DA:370,2 +DA:371,3 +DA:372,3 +DA:378,4 +DA:381,2 +LF:124 +LH:115 +BRDA:53,0,0,3 +BRDA:54,1,0,3 +BRDA:56,2,0,3 +BRDA:57,3,0,3 +BRDA:58,4,0,3 +BRDA:58,4,1,0 +BRDA:60,5,0,1 +BRDA:60,5,1,2 +BRDA:60,6,0,3 +BRDA:60,6,1,2 +BRDA:70,7,0,0 +BRDA:70,7,1,2 +BRDA:83,8,0,1 +BRDA:83,8,1,1 +BRDA:85,9,0,2 +BRDA:85,9,1,1 +BRDA:86,10,0,3 +BRDA:86,10,1,2 +BRDA:86,10,2,2 +BRDA:102,11,0,1 +BRDA:102,11,1,0 +BRDA:102,12,0,1 +BRDA:102,12,1,0 +BRDA:107,13,0,1 +BRDA:107,13,1,0 +BRDA:120,14,0,2 +BRDA:120,14,1,0 +BRDA:120,15,0,2 +BRDA:120,15,1,2 +BRDA:120,15,2,2 +BRDA:145,16,0,2 +BRDA:145,16,1,0 +BRDA:151,17,0,2 +BRDA:151,17,1,0 +BRDA:160,18,0,2 +BRDA:160,18,1,0 +BRDA:160,19,0,2 +BRDA:160,19,1,0 +BRDA:167,20,0,2 +BRDA:167,20,1,1 +BRDA:168,21,0,0 +BRDA:168,21,1,1 +BRDA:169,22,0,1 +BRDA:169,22,1,0 +BRDA:169,23,0,3 +BRDA:169,23,1,0 +BRDA:178,24,0,2 +BRDA:178,24,1,2 +BRDA:190,25,0,0 +BRDA:190,25,1,0 +BRDA:209,26,0,0 +BRDA:209,26,1,1 +BRDA:210,27,0,1 +BRDA:210,27,1,0 +BRDA:211,28,0,0 +BRDA:211,28,1,1 +BRDA:217,29,0,0 +BRDA:217,29,1,1 +BRDA:218,30,0,0 +BRDA:218,30,1,1 +BRDA:230,31,0,2 +BRDA:230,31,1,0 +BRDA:231,32,0,2 +BRDA:231,32,1,0 +BRDA:232,33,0,1 +BRDA:232,33,1,1 +BRDA:235,34,0,0 +BRDA:235,34,1,1 +BRDA:237,35,0,0 +BRDA:237,35,1,0 +BRDA:237,36,0,0 +BRDA:237,36,1,0 +BRDA:257,37,0,4 +BRDA:257,37,1,2 +BRDA:259,38,0,1 +BRDA:259,38,1,3 +BRDA:261,39,0,0 +BRDA:261,39,1,2 +BRDA:264,40,0,0 +BRDA:264,40,1,0 +BRDA:286,41,0,0 +BRDA:286,41,1,3 +BRDA:286,42,0,3 +BRDA:286,42,1,0 +BRDA:288,43,0,2 +BRDA:288,43,1,4 +BRDA:290,44,0,1 +BRDA:290,44,1,2 +BRDA:295,45,0,1 +BRDA:295,45,1,1 +BRDA:320,46,0,0 +BRDA:320,46,1,4 +BRDA:324,47,0,2 +BRDA:324,47,1,3 +BRDA:325,48,0,2 +BRDA:325,48,1,0 +BRDA:325,49,0,2 +BRDA:325,49,1,2 +BRDA:328,50,0,3 +BRDA:328,50,1,0 +BRDA:330,51,0,2 +BRDA:330,51,1,1 +BRDA:362,52,0,0 +BRDA:362,52,1,4 +BRDA:368,53,0,2 +BRDA:368,53,1,3 +BRDA:368,54,0,5 +BRDA:368,54,1,2 +BRDA:368,54,2,2 +BRDA:370,55,0,2 +BRDA:370,55,1,0 +BRDA:371,56,0,3 +BRDA:371,56,1,0 +BRDA:378,57,0,4 +BRDA:378,57,1,0 +BRF:115 +BRH:76 +end_of_record +TN: +SF:src/tools/handlers/task-tools.ts +FN:32,(anonymous_0) +FN:76,(anonymous_1) +FN:218,(anonymous_2) +FN:239,(anonymous_3) +FN:254,(anonymous_4) +FN:275,(anonymous_5) +FN:306,(anonymous_6) +FNF:7 +FNH:6 +FNDA:3,(anonymous_0) +FNDA:2,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:3,(anonymous_6) +DA:15,4 +DA:33,3 +DA:34,3 +DA:35,3 +DA:36,3 +DA:39,3 +DA:41,3 +DA:46,3 +DA:52,3 +DA:53,3 +DA:54,3 +DA:56,0 +DA:77,2 +DA:79,2 +DA:92,2 +DA:98,2 +DA:121,2 +DA:122,2 +DA:128,2 +DA:129,0 +DA:137,1 +DA:138,1 +DA:143,1 +DA:144,0 +DA:148,1 +DA:149,1 +DA:150,1 +DA:151,1 +DA:152,1 +DA:154,1 +DA:155,1 +DA:156,1 +DA:158,0 +DA:159,0 +DA:162,1 +DA:163,1 +DA:169,1 +DA:174,0 +DA:177,1 +DA:178,1 +DA:195,1 +DA:197,0 +DA:201,1 +DA:203,1 +DA:219,3 +DA:221,3 +DA:230,3 +DA:231,3 +DA:233,3 +DA:234,3 +DA:235,2 +DA:239,2 +DA:249,1 +DA:250,1 +DA:252,1 +DA:253,1 +DA:254,1 +DA:255,1 +DA:256,1 +DA:264,1 +DA:265,1 +DA:266,1 +DA:270,1 +DA:271,0 +DA:275,0 +DA:282,1 +DA:290,0 +DA:307,3 +DA:308,3 +DA:310,3 +DA:316,3 +DA:317,3 +DA:319,3 +DA:332,0 +LF:74 +LH:63 +BRDA:33,0,0,3 +BRDA:33,0,1,2 +BRDA:34,1,0,3 +BRDA:34,1,1,1 +BRDA:35,2,0,3 +BRDA:35,2,1,0 +BRDA:35,2,2,0 +BRDA:36,3,0,0 +BRDA:36,3,1,3 +BRDA:39,4,0,1 +BRDA:39,4,1,2 +BRDA:39,5,0,1 +BRDA:39,5,1,1 +BRDA:42,6,0,3 +BRDA:42,6,1,3 +BRDA:43,7,0,1 +BRDA:43,7,1,2 +BRDA:77,8,0,2 +BRDA:128,9,0,0 +BRDA:128,9,1,2 +BRDA:137,10,0,1 +BRDA:137,10,1,0 +BRDA:137,11,0,1 +BRDA:137,11,1,0 +BRDA:137,11,2,0 +BRDA:143,12,0,0 +BRDA:143,12,1,1 +BRDA:149,13,0,1 +BRDA:149,13,1,0 +BRDA:149,14,0,1 +BRDA:149,14,1,0 +BRDA:150,15,0,1 +BRDA:150,15,1,1 +BRDA:151,16,0,1 +BRDA:151,16,1,1 +BRDA:151,16,2,1 +BRDA:182,17,0,1 +BRDA:182,17,1,0 +BRDA:190,18,0,1 +BRDA:190,18,1,0 +BRDA:219,19,0,3 +BRDA:233,20,0,3 +BRDA:233,20,1,0 +BRDA:234,21,0,2 +BRDA:234,21,1,1 +BRDA:234,22,0,3 +BRDA:234,22,1,3 +BRDA:234,22,2,3 +BRDA:241,23,0,2 +BRDA:241,23,1,0 +BRDA:242,24,0,2 +BRDA:242,24,1,0 +BRDA:252,25,0,1 +BRDA:252,25,1,0 +BRDA:255,26,0,1 +BRDA:255,26,1,0 +BRDA:257,27,0,1 +BRDA:257,27,1,1 +BRDA:257,27,2,0 +BRDA:257,27,3,0 +BRDA:264,28,0,1 +BRDA:264,28,1,0 +BRDA:270,29,0,0 +BRDA:270,29,1,1 +BRDA:307,30,0,3 +BRDA:307,30,1,2 +BRDA:308,31,0,3 +BRDA:308,31,1,3 +BRDA:325,32,0,0 +BRDA:325,32,1,3 +BRF:70 +BRH:48 +end_of_record +TN: +SF:src/tools/handlers/test-tools.ts +FN:25,resolveTestRunner +FN:37,(anonymous_1) +FN:38,(anonymous_2) +FN:39,(anonymous_3) +FN:70,resolveDirectImpact +FN:100,(anonymous_5) +FN:123,(anonymous_6) +FN:166,(anonymous_7) +FN:195,(anonymous_8) +FN:217,(anonymous_9) +FN:219,(anonymous_10) +FN:268,(anonymous_11) +FN:349,(anonymous_12) +FNF:13 +FNH:11 +FNDA:2,resolveTestRunner +FNDA:2,(anonymous_1) +FNDA:2,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:6,resolveDirectImpact +FNDA:2,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:2,(anonymous_7) +FNDA:3,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:12,(anonymous_10) +FNDA:7,(anonymous_11) +FNDA:4,(anonymous_12) +DA:31,2 +DA:32,0 +DA:33,0 +DA:37,2 +DA:38,2 +DA:39,2 +DA:41,2 +DA:42,0 +DA:44,2 +DA:45,0 +DA:47,2 +DA:48,0 +DA:52,2 +DA:53,2 +DA:57,2 +DA:71,6 +DA:74,6 +DA:75,3 +DA:76,3 +DA:79,3 +DA:100,3 +DA:102,3 +DA:103,1 +DA:111,5 +DA:112,6 +DA:113,0 +DA:116,5 +DA:117,5 +DA:118,5 +DA:120,6 +DA:122,5 +DA:124,0 +DA:129,5 +DA:132,0 +DA:133,5 +DA:134,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:142,0 +DA:143,0 +DA:151,5 +DA:154,4 +DA:167,2 +DA:169,2 +DA:179,2 +DA:180,2 +DA:182,2 +DA:184,0 +DA:196,3 +DA:198,3 +DA:209,3 +DA:210,3 +DA:211,3 +DA:216,3 +DA:217,3 +DA:219,3 +DA:220,12 +DA:222,3 +DA:251,0 +DA:269,7 +DA:270,7 +DA:271,7 +DA:277,7 +DA:278,1 +DA:301,6 +DA:315,6 +DA:316,6 +DA:317,6 +DA:319,6 +DA:337,0 +DA:350,4 +DA:352,4 +DA:353,4 +DA:354,2 +DA:366,2 +DA:369,2 +DA:375,4 +DA:377,4 +DA:378,4 +DA:379,4 +DA:386,4 +DA:396,1 +DA:408,0 +LF:86 +LH:66 +BRDA:31,0,0,0 +BRDA:31,0,1,2 +BRDA:32,1,0,0 +BRDA:41,2,0,0 +BRDA:41,2,1,2 +BRDA:44,3,0,0 +BRDA:44,3,1,2 +BRDA:47,4,0,0 +BRDA:47,4,1,2 +BRDA:54,5,0,2 +BRDA:54,5,1,0 +BRDA:74,6,0,3 +BRDA:74,6,1,3 +BRDA:76,7,0,3 +BRDA:76,7,1,0 +BRDA:100,8,0,2 +BRDA:100,8,1,0 +BRDA:102,9,0,1 +BRDA:102,9,1,2 +BRDA:112,10,0,0 +BRDA:112,10,1,6 +BRDA:118,11,0,5 +BRDA:118,11,1,0 +BRDA:124,12,0,0 +BRDA:124,12,1,0 +BRDA:124,12,2,0 +BRDA:124,12,3,0 +BRDA:129,13,0,5 +BRDA:129,13,1,0 +BRDA:132,14,0,0 +BRDA:132,14,1,0 +BRDA:134,15,0,0 +BRDA:134,15,1,0 +BRDA:136,16,0,0 +BRDA:136,16,1,0 +BRDA:138,17,0,0 +BRDA:138,17,1,0 +BRDA:140,18,0,0 +BRDA:140,18,1,0 +BRDA:142,19,0,0 +BRDA:142,19,1,0 +BRDA:142,19,2,0 +BRDA:143,20,0,0 +BRDA:143,20,1,0 +BRDA:143,21,0,0 +BRDA:143,21,1,0 +BRDA:167,22,0,2 +BRDA:167,23,0,2 +BRDA:196,24,0,3 +BRDA:196,25,0,3 +BRDA:216,26,0,3 +BRDA:216,26,1,3 +BRDA:220,27,0,12 +BRDA:220,27,1,12 +BRDA:269,28,0,7 +BRDA:269,28,1,5 +BRDA:270,29,0,5 +BRDA:270,29,1,2 +BRDA:271,30,0,6 +BRDA:271,30,1,1 +BRDA:273,31,0,1 +BRDA:273,31,1,0 +BRDA:277,32,0,1 +BRDA:277,32,1,6 +BRDA:330,33,0,0 +BRDA:330,33,1,6 +BRDA:350,34,0,4 +BRDA:350,35,0,4 +BRDA:350,36,0,4 +BRDA:353,37,0,2 +BRDA:353,37,1,2 +BRDA:353,38,0,4 +BRDA:353,38,1,4 +BRDA:378,39,0,4 +BRDA:378,39,1,0 +BRDA:401,40,0,1 +BRDA:401,40,1,0 +BRDA:410,41,0,0 +BRDA:410,41,1,0 +BRF:79 +BRH:41 +end_of_record +TN: +SF:src/types/config.ts +FN:94,isValidArchitectureConfig +FN:103,isValidApplicationConfig +FNF:2 +FNH:0 +FNDA:0,isValidArchitectureConfig +FNDA:0,isValidApplicationConfig +DA:95,0 +DA:96,0 +DA:97,0 +DA:104,0 +DA:105,0 +DA:106,0 +LF:6 +LH:0 +BRDA:95,0,0,0 +BRDA:95,0,1,0 +BRDA:95,1,0,0 +BRDA:95,1,1,0 +BRDA:97,2,0,0 +BRDA:97,2,1,0 +BRDA:104,3,0,0 +BRDA:104,3,1,0 +BRDA:104,4,0,0 +BRDA:104,4,1,0 +BRF:10 +BRH:0 +end_of_record +TN: +SF:src/types/tool-args.ts +FN:124,extractToolArgs +FN:146,getProfileFromArgs +FN:157,getLimitFromArgs +FNF:3 +FNH:0 +FNDA:0,extractToolArgs +FNDA:0,getProfileFromArgs +FNDA:0,getLimitFromArgs +DA:128,0 +DA:129,0 +DA:132,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:140,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:151,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:166,0 +LF:15 +LH:0 +BRDA:126,0,0,0 +BRDA:128,1,0,0 +BRDA:128,1,1,0 +BRDA:128,2,0,0 +BRDA:128,2,1,0 +BRDA:135,3,0,0 +BRDA:135,3,1,0 +BRDA:148,4,0,0 +BRDA:148,4,1,0 +BRDA:148,5,0,0 +BRDA:148,5,1,0 +BRDA:159,6,0,0 +BRDA:160,7,0,0 +BRDA:163,8,0,0 +BRDA:163,8,1,0 +BRF:15 +BRH:0 +end_of_record +TN: +SF:src/utils/exec-utils.ts +FN:23,execWithTimeout +FN:65,execWithTimeoutSafe +FNF:2 +FNH:2 +FNDA:7,execWithTimeout +FNDA:2,execWithTimeoutSafe +DA:29,7 +DA:31,7 +DA:32,7 +DA:39,7 +DA:41,4 +DA:42,4 +DA:43,1 +DA:48,3 +DA:49,1 +DA:55,2 +DA:69,2 +DA:70,2 +DA:71,2 +DA:73,1 +DA:74,1 +LF:15 +LH:15 +BRDA:23,0,0,7 +BRDA:25,1,0,7 +BRDA:26,2,0,7 +BRDA:27,3,0,7 +BRDA:41,4,0,4 +BRDA:41,4,1,0 +BRDA:42,5,0,1 +BRDA:42,5,1,3 +BRDA:48,6,0,1 +BRDA:48,6,1,2 +BRDA:67,7,0,2 +BRDA:73,8,0,1 +BRDA:73,8,1,0 +BRF:13 +BRH:11 +end_of_record +TN: +SF:src/utils/logger.ts +FN:45,resolveMinLevel +FN:59,normalizeContext +FN:78,emit +FN:108,(anonymous_3) +FN:115,(anonymous_4) +FN:122,(anonymous_5) +FN:129,(anonymous_6) +FNF:7 +FNH:7 +FNDA:13,resolveMinLevel +FNDA:2945,normalizeContext +FNDA:2987,emit +FNDA:42,(anonymous_3) +FNDA:8,(anonymous_4) +FNDA:135,(anonymous_5) +FNDA:2802,(anonymous_6) +DA:37,13 +DA:46,13 +DA:47,13 +DA:49,0 +DA:52,13 +DA:60,2945 +DA:61,46 +DA:62,36 +DA:64,10 +DA:65,0 +DA:67,10 +DA:68,10 +DA:70,0 +DA:79,2987 +DA:81,2945 +DA:82,2945 +DA:83,2945 +DA:85,2945 +DA:91,2945 +DA:92,2945 +DA:93,46 +DA:96,2945 +DA:104,13 +DA:109,42 +DA:116,8 +DA:123,135 +DA:130,2802 +LF:27 +LH:24 +BRDA:46,0,0,13 +BRDA:46,0,1,13 +BRDA:47,1,0,13 +BRDA:47,1,1,0 +BRDA:60,2,0,2899 +BRDA:60,2,1,46 +BRDA:60,3,0,2945 +BRDA:60,3,1,46 +BRDA:61,4,0,36 +BRDA:61,4,1,10 +BRDA:64,5,0,0 +BRDA:64,5,1,10 +BRDA:65,6,0,0 +BRDA:65,6,1,0 +BRDA:67,7,0,10 +BRDA:67,7,1,0 +BRDA:67,8,0,10 +BRDA:67,8,1,10 +BRDA:79,9,0,42 +BRDA:79,9,1,2945 +BRDA:91,10,0,26 +BRDA:91,10,1,2919 +BRDA:92,11,0,46 +BRDA:92,11,1,2899 +BRDA:92,12,0,2945 +BRDA:92,12,1,46 +BRF:26 +BRH:21 +end_of_record +TN: +SF:src/utils/validation.ts +FN:14,validateProjectId +FN:36,validateFilePath +FN:60,validateQuery +FN:80,validateCypherQuery +FN:109,validateNodeId +FN:134,validateLimit +FN:154,validateMode +FN:172,createValidationError +FN:185,extractProjectIdFromScopedId +FN:212,parseScopedId +FN:234,generateSecureId +FNF:11 +FNH:11 +FNDA:4,validateProjectId +FNDA:3,validateFilePath +FNDA:3,validateQuery +FNDA:3,validateCypherQuery +FNDA:3,validateNodeId +FNDA:4,validateLimit +FNDA:3,validateMode +FNDA:1,createValidationError +FNDA:18,extractProjectIdFromScopedId +FNDA:2,parseScopedId +FNDA:7,generateSecureId +DA:15,4 +DA:16,1 +DA:19,3 +DA:20,1 +DA:23,2 +DA:24,1 +DA:27,1 +DA:37,3 +DA:38,0 +DA:41,3 +DA:42,0 +DA:46,3 +DA:47,2 +DA:50,1 +DA:61,3 +DA:62,1 +DA:65,2 +DA:66,1 +DA:71,1 +DA:81,3 +DA:82,1 +DA:85,2 +DA:86,1 +DA:92,1 +DA:93,1 +DA:101,1 +DA:110,3 +DA:111,1 +DA:114,2 +DA:115,0 +DA:120,2 +DA:121,2 +DA:122,1 +DA:125,1 +DA:135,4 +DA:136,0 +DA:139,4 +DA:141,4 +DA:142,2 +DA:145,2 +DA:155,3 +DA:156,1 +DA:159,2 +DA:160,1 +DA:163,1 +DA:173,1 +DA:189,18 +DA:190,1 +DA:193,17 +DA:194,17 +DA:195,0 +DA:198,17 +DA:199,18 +DA:200,1 +DA:203,16 +DA:218,2 +DA:219,2 +DA:235,7 +DA:236,7 +LF:59 +LH:54 +BRDA:15,0,0,1 +BRDA:15,0,1,3 +BRDA:19,1,0,1 +BRDA:19,1,1,2 +BRDA:19,2,0,3 +BRDA:19,2,1,2 +BRDA:23,3,0,1 +BRDA:23,3,1,1 +BRDA:37,4,0,0 +BRDA:37,4,1,3 +BRDA:41,5,0,0 +BRDA:41,5,1,3 +BRDA:41,6,0,3 +BRDA:41,6,1,3 +BRDA:46,7,0,2 +BRDA:46,7,1,1 +BRDA:46,8,0,3 +BRDA:46,8,1,2 +BRDA:60,9,0,3 +BRDA:61,10,0,1 +BRDA:61,10,1,2 +BRDA:65,11,0,1 +BRDA:65,11,1,1 +BRDA:65,12,0,2 +BRDA:65,12,1,2 +BRDA:81,13,0,1 +BRDA:81,13,1,2 +BRDA:85,14,0,1 +BRDA:85,14,1,1 +BRDA:85,15,0,2 +BRDA:85,15,1,1 +BRDA:93,16,0,0 +BRDA:93,16,1,1 +BRDA:93,17,0,1 +BRDA:93,17,1,1 +BRDA:93,17,2,1 +BRDA:93,17,3,0 +BRDA:110,18,0,1 +BRDA:110,18,1,2 +BRDA:114,19,0,0 +BRDA:114,19,1,2 +BRDA:114,20,0,2 +BRDA:114,20,1,2 +BRDA:121,21,0,1 +BRDA:121,21,1,1 +BRDA:121,22,0,2 +BRDA:121,22,1,2 +BRDA:134,23,0,4 +BRDA:135,24,0,0 +BRDA:135,24,1,4 +BRDA:135,25,0,4 +BRDA:135,25,1,3 +BRDA:139,26,0,3 +BRDA:139,26,1,1 +BRDA:141,27,0,2 +BRDA:141,27,1,2 +BRDA:141,28,0,4 +BRDA:141,28,1,3 +BRDA:141,28,2,2 +BRDA:155,29,0,1 +BRDA:155,29,1,2 +BRDA:159,30,0,1 +BRDA:159,30,1,1 +BRDA:187,31,0,18 +BRDA:189,32,0,1 +BRDA:189,32,1,17 +BRDA:189,33,0,18 +BRDA:189,33,1,17 +BRDA:194,34,0,0 +BRDA:194,34,1,17 +BRDA:199,35,0,1 +BRDA:199,35,1,17 +BRDA:199,36,0,18 +BRDA:199,36,1,16 +BRDA:220,37,0,2 +BRDA:220,37,1,0 +BRDA:234,38,0,7 +BRDA:234,39,0,7 +BRF:78 +BRH:70 +end_of_record +TN: +SF:src/vector/embedding-engine.ts +FN:36,(anonymous_0) +FN:45,(anonymous_1) +FN:91,(anonymous_2) +FN:128,(anonymous_3) +FN:146,(anonymous_4) +FN:157,(anonymous_5) +FN:158,(anonymous_6) +FN:164,(anonymous_7) +FN:218,(anonymous_8) +FN:233,(anonymous_9) +FN:237,(anonymous_10) +FN:246,(anonymous_11) +FN:253,(anonymous_12) +FN:257,(anonymous_13) +FN:259,(anonymous_14) +FN:262,(anonymous_15) +FN:284,(anonymous_16) +FN:291,(anonymous_17) +FN:292,(anonymous_18) +FNF:19 +FNH:16 +FNDA:131,(anonymous_0) +FNDA:10,(anonymous_1) +FNDA:18,(anonymous_2) +FNDA:18,(anonymous_3) +FNDA:22,(anonymous_4) +FNDA:2816,(anonymous_5) +FNDA:2816,(anonymous_6) +FNDA:4,(anonymous_7) +FNDA:4,(anonymous_8) +FNDA:2,(anonymous_9) +FNDA:2,(anonymous_10) +FNDA:6,(anonymous_11) +FNDA:1,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:1,(anonymous_14) +FNDA:1,(anonymous_15) +FNDA:7,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:0,(anonymous_18) +DA:37,131 +DA:38,131 +DA:39,131 +DA:50,10 +DA:52,10 +DA:53,10 +DA:54,10 +DA:57,10 +DA:58,10 +DA:59,8 +DA:60,8 +DA:61,8 +DA:65,10 +DA:66,10 +DA:67,5 +DA:68,5 +DA:69,5 +DA:73,10 +DA:74,10 +DA:75,5 +DA:76,5 +DA:77,5 +DA:80,10 +DA:81,10 +DA:82,10 +DA:83,10 +DA:85,10 +DA:99,18 +DA:100,18 +DA:105,18 +DA:109,18 +DA:129,18 +DA:131,18 +DA:132,18 +DA:133,18 +DA:134,18 +DA:135,18 +DA:136,18 +DA:137,18 +DA:139,18 +DA:147,22 +DA:150,22 +DA:151,794 +DA:152,794 +DA:153,794 +DA:157,2816 +DA:158,2816 +DA:165,4 +DA:166,3 +DA:167,3 +DA:171,1 +DA:172,1 +DA:173,1 +DA:176,1 +DA:177,1 +DA:178,1 +DA:180,1 +DA:181,3 +DA:192,3 +DA:193,1 +DA:194,1 +DA:198,1 +DA:199,1 +DA:201,1 +DA:202,1 +DA:204,1 +DA:205,1 +DA:208,1 +DA:224,4 +DA:226,4 +DA:227,1 +DA:231,1 +DA:232,1 +DA:234,2 +DA:235,2 +DA:238,2 +DA:239,1 +DA:240,1 +DA:246,3 +DA:247,6 +DA:248,4 +DA:249,1 +DA:252,3 +DA:253,1 +DA:257,0 +DA:259,1 +DA:263,1 +DA:264,1 +DA:265,1 +DA:267,1 +DA:268,1 +DA:269,128 +DA:270,128 +DA:271,128 +DA:274,1 +DA:275,0 +DA:278,1 +DA:285,7 +DA:292,0 +DA:302,0 +LF:100 +LH:96 +BRDA:105,0,0,3 +BRDA:105,0,1,15 +BRDA:112,1,0,18 +BRDA:112,1,1,5 +BRDA:112,1,2,0 +BRDA:131,2,0,13 +BRDA:131,2,1,5 +BRDA:132,3,0,10 +BRDA:132,3,1,8 +BRDA:133,4,0,5 +BRDA:133,4,1,13 +BRDA:134,5,0,5 +BRDA:134,5,1,13 +BRDA:135,6,0,5 +BRDA:135,6,1,13 +BRDA:136,7,0,0 +BRDA:136,7,1,18 +BRDA:137,8,0,15 +BRDA:137,8,1,3 +BRDA:146,9,0,22 +BRDA:158,10,0,22 +BRDA:158,10,1,0 +BRDA:165,11,0,3 +BRDA:165,11,1,1 +BRDA:192,12,0,1 +BRDA:192,12,1,2 +BRDA:192,13,0,1 +BRDA:192,13,1,1 +BRDA:193,14,0,1 +BRDA:193,14,1,0 +BRDA:198,15,0,1 +BRDA:198,15,1,0 +BRDA:201,16,0,1 +BRDA:201,16,1,0 +BRDA:204,17,0,1 +BRDA:204,17,1,0 +BRDA:220,18,0,4 +BRDA:221,19,0,4 +BRDA:226,20,0,1 +BRDA:226,20,1,3 +BRDA:231,21,0,1 +BRDA:231,21,1,0 +BRDA:238,22,0,1 +BRDA:238,22,1,1 +BRDA:239,23,0,0 +BRDA:239,23,1,1 +BRDA:239,24,0,1 +BRDA:239,24,1,1 +BRDA:247,25,0,2 +BRDA:247,25,1,4 +BRDA:248,26,0,3 +BRDA:248,26,1,1 +BRDA:248,27,0,4 +BRDA:248,27,1,4 +BRDA:274,28,0,0 +BRDA:274,28,1,1 +BRDA:274,29,0,1 +BRDA:274,29,1,1 +BRF:58 +BRH:48 +end_of_record +TN: +SF:src/vector/qdrant-client.ts +FN:32,(anonymous_0) +FN:39,(anonymous_1) +FN:56,(anonymous_2) +FN:86,(anonymous_3) +FN:97,(anonymous_4) +FN:110,(anonymous_5) +FN:123,(anonymous_6) +FN:134,(anonymous_7) +FN:154,(anonymous_8) +FN:172,(anonymous_9) +FN:186,(anonymous_10) +FN:208,(anonymous_11) +FNF:12 +FNH:11 +FNDA:131,(anonymous_0) +FNDA:130,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:3,(anonymous_7) +FNDA:1,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:2,(anonymous_10) +FNDA:24,(anonymous_11) +DA:30,131 +DA:33,131 +DA:40,130 +DA:42,130 +DA:43,3 +DA:44,3 +DA:45,3 +DA:48,1 +DA:49,1 +DA:57,1 +DA:58,0 +DA:59,0 +DA:62,1 +DA:63,1 +DA:74,1 +DA:75,1 +DA:78,0 +DA:87,1 +DA:88,1 +DA:89,2 +DA:91,1 +DA:98,1 +DA:99,0 +DA:100,0 +DA:103,1 +DA:104,1 +DA:110,1 +DA:120,1 +DA:121,1 +DA:123,0 +DA:124,0 +DA:127,0 +DA:135,3 +DA:136,1 +DA:137,1 +DA:140,2 +DA:141,2 +DA:151,1 +DA:152,1 +DA:153,1 +DA:154,1 +DA:162,0 +DA:164,1 +DA:165,1 +DA:173,1 +DA:175,1 +DA:176,1 +DA:177,1 +DA:179,0 +DA:187,2 +DA:189,2 +DA:190,2 +DA:191,1 +DA:192,1 +DA:193,1 +DA:200,1 +DA:202,1 +DA:209,24 +LF:58 +LH:48 +BRDA:32,0,0,131 +BRDA:32,1,0,131 +BRDA:43,2,0,3 +BRDA:43,2,1,0 +BRDA:57,3,0,0 +BRDA:57,3,1,1 +BRDA:74,4,0,1 +BRDA:74,4,1,0 +BRDA:98,5,0,0 +BRDA:98,5,1,1 +BRDA:120,6,0,1 +BRDA:120,6,1,0 +BRDA:134,7,0,3 +BRDA:135,8,0,1 +BRDA:135,8,1,2 +BRDA:151,9,0,1 +BRDA:151,9,1,0 +BRDA:154,10,0,1 +BRDA:154,10,1,0 +BRDA:156,11,0,1 +BRDA:156,11,1,1 +BRDA:173,12,0,0 +BRDA:173,12,1,1 +BRDA:187,13,0,0 +BRDA:187,13,1,2 +BRDA:191,14,0,1 +BRDA:191,14,1,0 +BRDA:195,15,0,1 +BRDA:195,15,1,0 +BRDA:196,16,0,1 +BRDA:196,16,1,0 +BRF:31 +BRH:19 +end_of_record diff --git a/coverage/src/cli/build.ts.html b/coverage/src/cli/build.ts.html new file mode 100644 index 0000000..86e62fc --- /dev/null +++ b/coverage/src/cli/build.ts.html @@ -0,0 +1,445 @@ + + + + + + Code coverage report for src/cli/build.ts + + + + + + + + + +
+
+

All files / src/cli build.ts

+
+ +
+ 0% + Statements + 0/48 +
+ + +
+ 0% + Branches + 0/16 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 0% + Lines + 0/46 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
#!/usr/bin/env node
+ 
+/**
+ * Graph Build CLI
+ * Builds the code graph from a workspace's source files.
+ *
+ * Usage:
+ *   npm run graph:build
+ *   npm run graph:build -- --full
+ *   npm run graph:build -- --verbose
+ */
+ 
+import * as path from "path";
+import * as fs from "fs";
+import { GraphOrchestrator } from "../graph/orchestrator.js";
+import MemgraphClient from "../graph/client.js";
+import * as env from "../env.js";
+import { logger } from "../utils/logger.js";
+ 
+async function main() {
+  const args = process.argv.slice(2);
+  const isFullBuild = args.includes("--full");
+  const isVerbose = args.includes("--verbose");
+  const projectRoot = path.resolve(process.cwd());
+ 
+  logger.error("🔨 Code Graph Builder");
+  logger.error(`📁 Project root: ${projectRoot}`);
+  logger.error(`🔄 Build mode: ${isFullBuild ? "FULL" : "INCREMENTAL"}`);
+  logger.error("");
+ 
+  try {
+    // Initialize Memgraph client
+    logger.error("🔌 Connecting to Memgraph...");
+    const memgraph = new MemgraphClient({
+      host: env.MEMGRAPH_HOST,
+      port: env.MEMGRAPH_PORT,
+    });
+ 
+    await memgraph.connect();
+    logger.error("✅ Connected to Memgraph\n");
+ 
+    // Create orchestrator
+    const orchestrator = new GraphOrchestrator(memgraph, isVerbose);
+ 
+    // Build the graph
+    logger.error("📊 Building code graph...\n");
+    const startTime = Date.now();
+ 
+    const result = await orchestrator.build({
+      mode: isFullBuild ? "full" : "incremental",
+      verbose: isVerbose,
+      sourceDir: path.join(projectRoot, "src"),
+      exclude: [
+        "node_modules/**",
+        "dist/**",
+        "build/**",
+        ".lxrag/**",
+        "**/*.test.ts",
+        "**/*.test.tsx",
+        "**/__tests__/**",
+      ],
+    });
+ 
+    const duration = Date.now() - startTime;
+ 
+    // Display results
+    logger.error("\n📈 Build Results:");
+    logger.error(`   ✅ Success: ${result.success}`);
+    logger.error(`   ⏱️  Duration: ${(duration / 1000).toFixed(2)}s`);
+    logger.error(`   📄 Files processed: ${result.filesProcessed}`);
+    logger.error(`   📍 Nodes created: ${result.nodesCreated}`);
+    logger.error(`   🔗 Relationships created: ${result.relationshipsCreated}`);
+    if (result.filesChanged > 0) {
+      logger.error(`   🔄 Files changed: ${result.filesChanged}`);
+    }
+ 
+    if (result.errors.length > 0) {
+      logger.error(`\n❌ Errors (${result.errors.length}):`);
+      result.errors.forEach((err) => logger.error(`   - ${err}`));
+    }
+ 
+    if (result.warnings.length > 0) {
+      logger.error(`\n⚠️  Warnings (${result.warnings.length}):`);
+      result.warnings.forEach((warn) => logger.error(`   - ${warn}`));
+    }
+ 
+    // Save build metadata
+    const codeGraphDir = path.join(projectRoot, ".lxrag");
+    if (!fs.existsSync(codeGraphDir)) {
+      fs.mkdirSync(codeGraphDir, { recursive: true });
+    }
+ 
+    const metadata = {
+      timestamp: new Date().toISOString(),
+      duration,
+      mode: isFullBuild ? "full" : "incremental",
+      success: result.success,
+      filesProcessed: result.filesProcessed,
+      nodesCreated: result.nodesCreated,
+      relationshipsCreated: result.relationshipsCreated,
+    };
+ 
+    fs.writeFileSync(path.join(codeGraphDir, "build.log.json"), JSON.stringify(metadata, null, 2));
+ 
+    logger.error("\n✨ Build complete!");
+    logger.error("   View graph at: http://localhost:3000 (Memgraph Lab)");
+    logger.error('   Query graph: npm run graph:query "MATCH (f:FILE) RETURN count(f)"');
+ 
+    // Exit with appropriate code
+    process.exit(result.success ? 0 : 1);
+  } catch (error) {
+    logger.error("❌ Build failed:", error);
+    process.exit(1);
+  }
+}
+ 
+main().catch((error) => {
+  logger.error("Fatal error:", error);
+  process.exit(1);
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/cli/index.html b/coverage/src/cli/index.html new file mode 100644 index 0000000..0f87729 --- /dev/null +++ b/coverage/src/cli/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/cli + + + + + + + + + +
+
+

All files src/cli

+
+ +
+ 0% + Statements + 0/208 +
+ + +
+ 0% + Branches + 0/74 +
+ + +
+ 0% + Functions + 0/20 +
+ + +
+ 0% + Lines + 0/198 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
build.ts +
+
0%0/480%0/160%0/40%0/46
query.ts +
+
0%0/250%0/60%0/20%0/25
test-affected.ts +
+
0%0/830%0/260%0/80%0/78
validate.ts +
+
0%0/520%0/260%0/60%0/49
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/cli/query.ts.html b/coverage/src/cli/query.ts.html new file mode 100644 index 0000000..85e68fa --- /dev/null +++ b/coverage/src/cli/query.ts.html @@ -0,0 +1,271 @@ + + + + + + Code coverage report for src/cli/query.ts + + + + + + + + + +
+
+

All files / src/cli query.ts

+
+ +
+ 0% + Statements + 0/25 +
+ + +
+ 0% + Branches + 0/6 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/25 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
#!/usr/bin/env node
+ 
+/**
+ * Graph Query CLI
+ * Execute Cypher queries against the code graph
+ *
+ * Usage:
+ *   npm run graph:query "MATCH (f:FILE) RETURN count(f)"
+ *   npm run graph:query "find all functions named create*"
+ */
+ 
+import MemgraphClient from "../graph/client.js";
+import * as env from "../env.js";
+import { logger } from "../utils/logger.js";
+ 
+async function main() {
+  const args = process.argv.slice(2);
+  const query = args.join(" ");
+ 
+  if (!query) {
+    logger.error("❌ No query provided");
+    logger.error('Usage: npm run graph:query "MATCH (n) RETURN n LIMIT 5"');
+    process.exit(1);
+  }
+ 
+  try {
+    logger.error("🔍 Executing query...\n");
+ 
+    const memgraph = new MemgraphClient({
+      host: env.MEMGRAPH_HOST,
+      port: env.MEMGRAPH_PORT,
+    });
+ 
+    await memgraph.connect();
+ 
+    const result = await memgraph.executeCypher(query);
+ 
+    if (result.error) {
+      logger.error("❌ Query error:", result.error);
+      process.exit(1);
+    }
+ 
+    // Display results
+    if (result.data.length === 0) {
+      logger.error("📭 No results found");
+    } else {
+      logger.error(`📊 Results (${result.data.length} rows):\n`);
+      console.table(result.data);
+    }
+ 
+    await memgraph.disconnect();
+    process.exit(0);
+  } catch (error) {
+    logger.error("❌ Query failed:", error);
+    process.exit(1);
+  }
+}
+ 
+main().catch((error) => {
+  logger.error("Fatal error:", error);
+  process.exit(1);
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/cli/test-affected.ts.html b/coverage/src/cli/test-affected.ts.html new file mode 100644 index 0000000..7d504c5 --- /dev/null +++ b/coverage/src/cli/test-affected.ts.html @@ -0,0 +1,511 @@ + + + + + + Code coverage report for src/cli/test-affected.ts + + + + + + + + + +
+
+

All files / src/cli test-affected.ts

+
+ +
+ 0% + Statements + 0/83 +
+ + +
+ 0% + Branches + 0/26 +
+ + +
+ 0% + Functions + 0/8 +
+ + +
+ 0% + Lines + 0/78 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
#!/usr/bin/env node
+ 
+/**
+ * Test Affected CLI
+ * Selects and optionally runs tests affected by changed files
+ *
+ * Usage:
+ *   npm run test:affected src/engine/calculations/columns.ts
+ *   npm run test:affected src/utils/units.ts --run
+ *   npm run test:affected src/engine/**\/*.ts --depth=2
+ */
+ 
+import { execSync } from "child_process";
+import GraphIndexManager from "../graph/index.js";
+import { loadConfig } from "../config.js";
+import TestEngine from "../engines/test-engine.js";
+ 
+async function main() {
+  const args = process.argv.slice(2);
+ 
+  if (args.length === 0) {
+    console.error("🧪 Test Affected Selector");
+    console.error("");
+    console.error("Usage: npm run test:affected <files> [--run] [--depth=N]");
+    console.error("");
+    console.error("Options:");
+    console.error("  --run         Run tests after selection (requires Vitest)");
+    console.error("  --depth=N     Set transitive dependency depth (default: 1)");
+    console.error("");
+    console.error("Examples:");
+    console.error("  npm run test:affected src/utils/units.ts");
+    console.error("  npm run test:affected src/engine/calculations/\\*.ts --run");
+    console.error("  npm run test:affected src/context/BuildingContext.tsx --depth=2 --run");
+    process.exit(0);
+  }
+ 
+  const runTests = args.includes("--run");
+  const depthArg = args.find((a) => a.startsWith("--depth="));
+  const depth = depthArg ? parseInt(depthArg.split("=")[1]) : 1;
+ 
+  // Filter out flag arguments
+  const changedFiles = args.filter((a) => !a.startsWith("--run") && !a.startsWith("--depth="));
+ 
+  console.error("🧪 Test Affected Selector");
+  console.error(`📁 Changed files: ${changedFiles.length}`);
+  console.error(`🔄 Dependency depth: ${depth}`);
+  console.error(`▶️  Auto-run: ${runTests ? "YES" : "NO"}\n`);
+ 
+  try {
+    // Create in-memory graph index
+    console.error("📊 Building test dependency map...");
+    const index = new GraphIndexManager();
+    const testEngine = new TestEngine(index);
+    console.error("✅ Ready\n");
+ 
+    // Select affected tests
+    console.error("🔍 Analyzing dependencies...\n");
+    const result = testEngine.selectAffectedTests(changedFiles, true, depth);
+ 
+    // Display results
+    if (result.selectedTests.length === 0) {
+      console.error("ℹ️  No tests directly affected by these changes");
+      console.error(
+        "   (Possibly: new file, not imported by tests, or test dependencies not built)",
+      );
+      process.exit(0);
+    }
+ 
+    console.error(`✅ Selected ${result.selectedTests.length} test(s):`);
+    console.error("");
+    result.selectedTests.forEach((test) => {
+      console.error(`   📄 ${test}`);
+    });
+ 
+    console.error("");
+    console.error("📊 Statistics:");
+    console.error(
+      `   Coverage: ${result.coverage.percentage}% (${result.coverage.testsSelected}/${result.coverage.totalTests})`,
+    );
+    console.error(`   Category: ${result.category}`);
+    console.error(
+      `   Est. time: ${result.estimatedTime > 0 ? result.estimatedTime + "ms" : "unknown"}`,
+    );
+    console.error("");
+ 
+    // Optionally run tests
+    if (runTests) {
+      console.error("\u25b6\ufe0f  Running selected tests...\n");
+      try {
+        const config = await loadConfig();
+        const runner = config.testing?.testRunner;
+        const testList = result.selectedTests.join(" ");
+ 
+        let runCmd: string;
+        if (runner) {
+          // Explicit runner from .lxrag/config.json
+          const runnerArgs = [...(runner.args ?? []), ...result.selectedTests].join(" ");
+          runCmd = `${runner.command} ${runnerArgs}`;
+        } else {
+          // Auto-detect from test file extensions
+          const hasPy = result.selectedTests.some((f) => f.endsWith(".py"));
+          const hasRb = result.selectedTests.some((f) => f.endsWith(".rb"));
+          const hasGo = result.selectedTests.some((f) => f.endsWith(".go"));
+          if (hasPy) {
+            runCmd = `pytest ${testList}`;
+          } else if (hasRb) {
+            runCmd = `bundle exec rspec ${testList}`;
+          } else if (hasGo) {
+            runCmd = `go test ${testList}`;
+          } else {
+            // Default: vitest (JS/TS)
+            runCmd = `npx vitest run ${testList}`;
+          }
+        }
+ 
+        console.error(`\u25b6\ufe0f  ${runCmd}`);
+        execSync(runCmd, {
+          cwd: process.cwd(),
+          stdio: "inherit",
+        });
+        console.error("\n\u2705 Tests completed successfully");
+        process.exit(0);
+      } catch (_error) {
+        console.error("\n\u274c Some tests failed");
+        process.exit(1);
+      }
+    } else {
+      console.error("💡 To run these tests, add --run flag:");
+      console.error(`   npm run test:affected ${changedFiles.join(" ")} --run`);
+      console.error("");
+      process.exit(0);
+    }
+  } catch (error) {
+    console.error("❌ Error:", error instanceof Error ? error.message : String(error));
+    process.exit(1);
+  }
+}
+ 
+main().catch((error) => {
+  console.error("Fatal error:", error);
+  process.exit(1);
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/cli/validate.ts.html b/coverage/src/cli/validate.ts.html new file mode 100644 index 0000000..936dca3 --- /dev/null +++ b/coverage/src/cli/validate.ts.html @@ -0,0 +1,403 @@ + + + + + + Code coverage report for src/cli/validate.ts + + + + + + + + + +
+
+

All files / src/cli validate.ts

+
+ +
+ 0% + Statements + 0/52 +
+ + +
+ 0% + Branches + 0/26 +
+ + +
+ 0% + Functions + 0/6 +
+ + +
+ 0% + Lines + 0/49 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
#!/usr/bin/env node
+ 
+/**
+ * Graph Validate CLI
+ * Validates architecture constraints against the code graph
+ *
+ * Usage:
+ *   npm run graph:validate
+ *   npm run graph:validate -- --strict
+ *   npm run graph:validate -- --file src/engine/calculations/columns.ts
+ */
+ 
+import { ArchitectureEngine } from "../engines/architecture-engine.js";
+import { loadConfig } from "../config.js";
+import GraphIndexManager from "../graph/index.js";
+import { MemgraphClient } from "../graph/client.js";
+import { logger } from "../utils/logger.js";
+ 
+async function main() {
+  const args = process.argv.slice(2);
+  const isStrict = args.includes("--strict");
+  const writeViolations = args.includes("--write");
+  const fileIndex = args.indexOf("--file");
+  const targetFile = fileIndex >= 0 ? args[fileIndex + 1] : undefined;
+ 
+  logger.error("🏗️  Architecture Validator");
+  if (targetFile) {
+    logger.error(`📄 Validating: ${targetFile}`);
+  } else {
+    logger.error("📄 Validating all files");
+  }
+  logger.error(`🔒 Strict mode: ${isStrict ? "ON" : "OFF"}\n`);
+ 
+  try {
+    // Load configuration
+    const config = await loadConfig();
+ 
+    // Create in-memory graph index (MVP - no Memgraph connection needed for validation)
+    logger.error("📊 Preparing validation engine...");
+    const index = new GraphIndexManager();
+    logger.error("✅ Ready\n");
+ 
+    // Run validation
+    logger.error("🔍 Checking architecture constraints...\n");
+    const layers = config.architecture.layers.map((layer) => ({
+      ...layer,
+      description: layer.description || layer.name,
+    }));
+    const engine = new ArchitectureEngine(layers, config.architecture.rules, index, undefined, {
+      sourceGlobs: config.testing?.sourceGlobs,
+      defaultExtension: config.testing?.defaultExtension,
+    });
+    const filesToValidate = targetFile ? [targetFile] : undefined;
+    const result = await engine.validate(filesToValidate);
+    const violations = result.violations || [];
+ 
+    // Write violations to Memgraph if --write flag is set
+    if (writeViolations && violations.length > 0) {
+      try {
+        const client = new MemgraphClient();
+        await client.connect();
+        await engine.writeViolationsToMemgraph(client, violations);
+        await client.disconnect();
+      } catch (error) {
+        logger.warn(
+          "⚠️  Could not write violations to Memgraph:",
+          error instanceof Error ? error.message : String(error),
+        );
+      }
+    }
+ 
+    // Display results
+    if (violations.length === 0) {
+      logger.error("✅ No violations found!");
+    } else {
+      logger.error(`⚠️  Found ${violations.length} violation(s):\n`);
+      violations.forEach((violation, index) => {
+        const icon = violation.severity === "error" ? "❌" : "⚠️";
+        logger.error(`${icon} ${index + 1}. ${violation.message}`);
+        logger.error(`   File: ${violation.file}`);
+        logger.error(`   Layer: ${violation.layer}`);
+        logger.error("");
+      });
+ 
+      const errorCount = violations.filter((v) => v.severity === "error").length;
+      const warningCount = violations.filter((v) => v.severity === "warn").length;
+ 
+      logger.error(`Summary: ${errorCount} error(s), ${warningCount} warning(s)`);
+ 
+      if (isStrict && errorCount > 0) {
+        logger.error("\n🛑 Strict mode: exiting with error code 1");
+        process.exit(1);
+      }
+    }
+ 
+    process.exit(0);
+  } catch (error) {
+    logger.error("❌ Validation failed:", error);
+    process.exit(1);
+  }
+}
+ 
+main().catch((error) => {
+  logger.error("Fatal error:", error);
+  process.exit(1);
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/config.ts.html b/coverage/src/config.ts.html new file mode 100644 index 0000000..6258e69 --- /dev/null +++ b/coverage/src/config.ts.html @@ -0,0 +1,787 @@ + + + + + + Code coverage report for src/config.ts + + + + + + + + + +
+
+

All files / src config.ts

+
+ +
+ 0% + Statements + 0/13 +
+ + +
+ 0% + Branches + 0/6 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Configuration loader
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import { logger } from "./utils/logger.js";
+ 
+export interface ArchitectureConfig {
+  layers: LayerConfig[];
+  rules: RuleConfig[];
+}
+ 
+export interface LayerConfig {
+  id: string;
+  name: string;
+  paths: string[];
+  canImport: string[];
+  description?: string;
+}
+ 
+export interface RuleConfig {
+  id: string;
+  severity: "error" | "warn";
+  pattern: string;
+  description: string;
+}
+ 
+export interface ProgressConfig {
+  features: Array<{
+    id: string;
+    name: string;
+    status: "not-started" | "in-progress" | "blocked" | "completed";
+    priority: "low" | "medium" | "high";
+    description?: string;
+    tasks?: string[];
+  }>;
+}
+ 
+export interface Config {
+  architecture: ArchitectureConfig;
+  testing?: {
+    categories: Array<{
+      id: string;
+      patterns: string[];
+    }>;
+    /**
+     * Explicit test runner to invoke via `test_run` and `test:affected`.
+     * When omitted the runner is auto-detected from the test file extensions
+     * (e.g. .py → pytest, .rb → bundle exec rspec, .ts/.js → vitest).
+     * @example { "command": "pytest", "args": ["--tb=short"] }
+     */
+    testRunner?: {
+      command: string;
+      args?: string[];
+    };
+    /**
+     * Glob patterns used by the architecture engine to discover source files.
+     * Defaults to ["src/**\/*.{ts,tsx}"] when not specified.
+     * @example ["src/**\/*.py", "lib/**\/*.py"]
+     */
+    sourceGlobs?: string[];
+    /**
+     * Default file extension appended when generating new file paths (e.g. via
+     * arch_suggest). Defaults to ".ts". Use ".py", ".rb", ".go", etc. for
+     * non-TypeScript projects.
+     */
+    defaultExtension?: string;
+  };
+  progress?: ProgressConfig;
+}
+ 
+// Generic TypeScript server defaults — create .lxrag/config.json at your project root
+// to override with project-specific layers and rules.
+// Tip: run arch_suggest to get placement guidance; update this file if suggestions
+// look wrong (e.g. always "src/types/").
+const DEFAULT_CONFIG: Config = {
+  architecture: {
+    layers: [
+      {
+        id: "types",
+        name: "Types",
+        paths: ["src/types/**"],
+        canImport: [],
+        description: "Shared type definitions — no runtime dependencies",
+      },
+      {
+        id: "utils",
+        name: "Utilities",
+        paths: ["src/utils/**", "src/lib/**", "src/helpers/**"],
+        canImport: ["types"],
+        description: "Stateless utility and helper functions",
+      },
+      {
+        id: "parsers",
+        name: "Parsers",
+        paths: ["src/parsers/**"],
+        canImport: ["types", "utils"],
+        description: "File parsers and language-specific analysis",
+      },
+      {
+        id: "graph",
+        name: "Graph",
+        paths: ["src/graph/**"],
+        canImport: ["types", "utils", "parsers"],
+        description: "Graph building, caching and Memgraph client",
+      },
+      {
+        id: "vector",
+        name: "Vector",
+        paths: ["src/vector/**"],
+        canImport: ["types", "utils", "graph"],
+        description: "Embedding engine and Qdrant client",
+      },
+      {
+        id: "engines",
+        name: "Engines",
+        paths: ["src/engines/**"],
+        canImport: ["types", "utils", "parsers", "graph", "vector"],
+        description: "Feature engines — architecture, community, docs, test, progress",
+      },
+      {
+        id: "tools",
+        name: "Tools",
+        paths: ["src/tools/**"],
+        canImport: ["types", "utils", "parsers", "graph", "vector", "engines"],
+        description: "MCP tool handlers — highest-level layer, may use all lower layers",
+      },
+      {
+        id: "server",
+        name: "Server",
+        paths: ["src/*.ts"],
+        canImport: ["types", "utils", "graph", "vector", "engines", "tools"],
+        description: "Server entry points — wires all layers together",
+      },
+    ],
+    rules: [
+      {
+        id: "no-tools-in-engines",
+        severity: "error",
+        pattern: "engines imports from tools",
+        description: "Engines must not import from tool handlers",
+      },
+      {
+        id: "no-graph-in-parsers",
+        severity: "warn",
+        pattern: "parsers imports from graph",
+        description: "Parsers should be graph-agnostic for reuse and testability",
+      },
+    ],
+  },
+  testing: {
+    categories: [
+      {
+        id: "unit",
+        patterns: ["**/__tests__/**/*.test.ts", "!**/*.integration.test.ts"],
+      },
+      {
+        id: "integration",
+        patterns: ["**/__tests__/**/*.integration.test.ts"],
+      },
+    ],
+  },
+  progress: {
+    features: [
+      {
+        id: "phase-1",
+        name: "Code Graph MVP",
+        status: "completed",
+        priority: "high",
+        description: "Parse codebase and build graph",
+        tasks: ["parse-files", "build-graph", "validate-output"],
+      },
+      {
+        id: "phase-2",
+        name: "Architecture Validation",
+        status: "completed",
+        priority: "high",
+        description: "Layer validation and constraint checking",
+        tasks: ["layer-rules", "circular-detection", "pre-commit-hook"],
+      },
+      {
+        id: "phase-3",
+        name: "Test Intelligence",
+        status: "completed",
+        priority: "high",
+        description: "Test selection and execution",
+        tasks: ["test-extraction", "test-selection", "vitest-integration"],
+      },
+      {
+        id: "phase-4",
+        name: "MCP Tools",
+        status: "completed",
+        priority: "high",
+        description: "Wire all 14 MCP tools",
+        tasks: ["tool-schemas", "tool-handlers", "claude-integration"],
+      },
+      {
+        id: "phase-5",
+        name: "Progress Tracking",
+        status: "in-progress",
+        priority: "medium",
+        description: "Track features and tasks",
+        tasks: ["config-progress", "seed-nodes", "persistence"],
+      },
+    ],
+  },
+};
+ 
+export async function loadConfig(): Promise<Config> {
+  const configPath = path.join(process.cwd(), ".lxrag", "config.json");
+ 
+  try {
+    if (fs.existsSync(configPath)) {
+      const data = fs.readFileSync(configPath, "utf-8");
+      return JSON.parse(data);
+    }
+  } catch (error) {
+    logger.warn("[Config] Error loading config file:", error);
+  }
+ 
+  return DEFAULT_CONFIG;
+}
+ 
+export function saveConfig(config: Config, configPath?: string): void {
+  const targetPath = configPath || path.join(process.cwd(), ".lxrag", "config.json");
+  const dir = path.dirname(targetPath);
+ 
+  if (!fs.existsSync(dir)) {
+    fs.mkdirSync(dir, { recursive: true });
+  }
+ 
+  fs.writeFileSync(targetPath, JSON.stringify(config, null, 2));
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/engines/architecture-engine.ts.html b/coverage/src/engines/architecture-engine.ts.html index e3618c5..6bd2605 100644 --- a/coverage/src/engines/architecture-engine.ts.html +++ b/coverage/src/engines/architecture-engine.ts.html @@ -23,30 +23,30 @@

All files / src/engines<
- 71.77% + 67.65% Statements - 117/163 + 159/235
50% Branches - 45/90 + 68/136
- 75% + 82.6% Functions - 15/20 + 19/23
- 74.02% + 68.77% Lines - 114/154 + 152/221
@@ -627,7 +627,145 @@

All files / src/engines< 562 563 564 -565  +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703        @@ -685,34 +823,48 @@

All files / src/engines<       +  +  +  +  +  +  +  +  +  +  +  +  +  +  +39x +9x +9x +9x 9x -3x             -2x -2x +5x +5x       -2x +5x 1x     -1x +4x +            -2x -4x   -4x -        @@ -720,34 +872,40 @@

All files / src/engines<       +5x +8x   +8x         -4x       -4x   -3x +        +8x +  +8x +  +5x         -3x -3x +5x +5x   -3x -3x +5x +5x     +5x 3x -1x       @@ -758,11 +916,11 @@

All files / src/engines<       +5x 3x       -1x       @@ -772,16 +930,16 @@

All files / src/engines<       +5x +5x   +8x +8x   +5x   -2x -2x   -4x -4x   -2x       @@ -794,17 +952,17 @@

All files / src/engines<       +15x +36x +36x +15x       -9x -20x -20x -9x +        -        @@ -812,73 +970,86 @@

All files / src/engines<       +36x       -20x       +36x +36x       -20x -20x             -8x -8x -8x -  +16x +16x +16x +16x   +16x   -8x     -8x -6x     -8x   -      +16x   +16x +10x   +    +  +    +    +    +  +    +    +    +  +    +    -6x +  +    -6x -6x +  +        +        +        -6x -6x +16x +          -6x       @@ -886,120 +1057,167 @@

All files / src/engines<       -6x -12x -12x -6x       +10x +    +  +10x +10x     +      +        +10x +10x +        +10x   +10x +  +10x +  +10x +      -4x -3x +10x       -1x -      -1x       +10x +20x +20x +10x +  +  +  +  +  +  +10x +              +  +8x 3x +  +  +  +5x     -3x   +5x           -2x -2x -2x -2x -2x   +5x +    -2x -2x +5x         -2x -4x -4x   -4x -3x -3x -3x -3x +  +5x +5x +5x +5x +5x +  +  +5x +5x +          -4x       -2x   -9x -9x -2x -2x     -7x   -7x -7x -7x   -7x -9x 5x +8x +8x   +8x +5x +5x +5x +5x   -7x -7x -7x       -2x -4x -4x +8x       +5x   +15x +15x 2x 2x +  +  +13x +  +13x +13x +13x +  +13x +15x +7x +  +  +13x +13x +13x +  +  +  +5x +8x +8x +  +  +  +  +5x +5x 2x 2x 2x @@ -1015,8 +1233,8 @@

All files / src/engines<       +5x   -2x       @@ -1032,55 +1250,109 @@

All files / src/engines<       -1x -1x   -1x     -1x -1x +  +  +  +6x +  +  +6x +6x +33x +33x +3x +3x         +33x +33x   -1x   -1x -1x   +6x +        +6x       -              +6x   +6x +6x +6x +33x +33x +33x +124x   -1x -1x +5x +5x +  +  +33x +11x +11x +  +  +  +6x +  +6x +  +  +  +6x +  +  +  +  +  +  +  +  +6x +6x +  +  +6x   -1x -1x   -1x     -1x +6x +2x +2x +2x +4x +4x +4x +  +4x +3x +  1x       +  +    -1x +  +6x       @@ -1118,6 +1390,11 @@

All files / src/engines<       +  +  +  +  +        @@ -1162,10 +1439,9 @@

All files / src/engines<       -  -  -  -  +1x +1x +1x       @@ -1192,8 +1468,9 @@

All files / src/engines<      
/**
- * Architecture Validation Engine
- * Validates code against layer constraints and architectural rules
+ * @file engines/architecture-engine
+ * @description Validates source dependencies against configured architecture layers and rules.
+ * @remarks Supports filesystem scanning and explicit file-list validation modes.
  */
  
 import * as path from "path";
@@ -1202,6 +1479,7 @@ 

All files / src/engines< import type { GraphIndexManager } from "../graph/index.js"; import type { MemgraphClient } from "../graph/client.js"; import type { CypherStatement } from "../graph/types.js"; +import { logger } from "../utils/logger.js";   export interface LayerDefinition { id: string; @@ -1243,14 +1521,29 @@

All files / src/engines< export class ArchitectureEngine { private layers: Map<string, LayerDefinition>; private rules: ArchitectureRule[]; + private workspaceRoot: string; + /** Glob patterns used to discover source files (e.g. for validation/circular-dep scan). */ + private sourceGlobs: string[]; + /** Default file extension used when generating suggested paths. */ + private defaultExtension: string;   constructor( layers: LayerDefinition[], rules: ArchitectureRule[], _index: GraphIndexManager, + workspaceRoot?: string, + options?: { + /** Override the glob patterns used to scan source files. Defaults to ["src/**\/*.{ts,tsx}"]. */ + sourceGlobs?: string[]; + /** Default extension for generated file paths. Defaults to ".ts". */ + defaultExtension?: string; + }, ) { this.layers = new Map(layers.map((l) => [l.id, l])); this.rules = rules; + this.workspaceRoot = workspaceRoot ?? process.cwd(); + this.sourceGlobs = options?.sourceGlobs ?? ["src/**/*.{ts,tsx}"]; + this.defaultExtension = options?.defaultExtension ?? ".ts"; }   /** @@ -1258,18 +1551,27 @@

All files / src/engines< */ async validate(files?: string[]): Promise<ValidationResult> { const violations: ValidationViolation[] = []; - const projectRoot = process.cwd(); + const projectRoot = this.workspaceRoot;   // Get source files to validate let filesToCheck: string[]; if (files && files.length > 0) { filesToCheck = files; } else { - // Scan all TS/TSX files in src/ - filesToCheck = globSync("src/**/*.{ts,tsx}", { - cwd: projectRoot, - ignore: ["**/node_modules/**", "**/*.test.ts", "**/*.test.tsx"], - }); + // Scan source files using configured globs (language-agnostic) + filesToCheck = this.sourceGlobs.flatMap((pattern) => + globSync(pattern, { + cwd: projectRoot, + ignore: [ + "**/node_modules/**", + "**/*.test.*", + "**/*.spec.*", + "**/test_*.py", + "**/*_test.go", + "**/*_spec.rb", + ], + }), + ); }   for (const filePath of filesToCheck) { @@ -1282,23 +1584,17 @@

All files / src/engines< file: filePath, layer: "unknown", message: `File not assigned to any layer: ${filePath}`, - suggestion: - "Update .lxrag/config.json with appropriate layer path pattern", + suggestion: "Update .lxrag/config.json with appropriate layer path pattern", }); continue; }   // Extract imports from file - const imports = this.extractImportsFromFile( - path.join(projectRoot, filePath), - ); + const imports = this.extractImportsFromFile(path.join(projectRoot, filePath));   for (const imp of imports) { // Skip external imports - Iif ( - imp.startsWith("@") || - (imp.startsWith(".") === false && !imp.startsWith("src")) - ) { + Iif (imp.startsWith("@") || (imp.startsWith(".") === false && !imp.startsWith("src"))) { continue; }   @@ -1322,10 +1618,7 @@

All files / src/engines< }   // Check forbidden imports - if ( - layer.cannotImport && - this.isForbiddenImport(layer, importedLayer) - ) { + if (layer.cannotImport && this.isForbiddenImport(layer, importedLayer)) { violations.push({ type: "layer-violation", severity: "error", @@ -1391,20 +1684,66 @@

All files / src/engines< }   /** - * Extract import statements from a source file + * Extract import statements from a source file. + * Dispatches to language-specific logic based on the file extension. + * Supported: TypeScript/JavaScript (.ts, .tsx, .js, .jsx, .mjs, .cjs), + * Python (.py), Ruby (.rb), Go (.go). */ private extractImportsFromFile(filePath: string): string[] { + const ext = path.extname(filePath).toLowerCase(); try { const content = fs.readFileSync(filePath, "utf-8"); const imports: Set<string> = new Set();   - // Match: import/export from 'path' or "path" - const importRegex = - /(?:import|export)\s+(?:[^"']*\s+)?from\s+['"]([^'"]+)['"]/g; - let match; -  - while ((match = importRegex.exec(content)) !== null) { - imports.add(match[1]); + if ( + ext === ".ts" || + ext === ".tsx" || + ext === ".js" || + ext === ".jsx" || + ext === ".mjs" || + ext === ".cjs" + ) { + // ES module: import/export ... from '...' + const importRegex = /(?:import|export)\s+(?:[^"']*\s+)?from\s+['"]([^'"]+)['"]/g; + let match; + while ((match = importRegex.exec(content)) !== null) { + imports.add(match[1]); + } + E} else if (ext === ".py") { + // Python: from module.path import ... / import module.path + const fromRegex = /^from\s+([\w.]+)\s+import\s+/gm; + const importRegex = /^import\s+([\w.]+)/gm; + let match; + while ((match = fromRegex.exec(content)) !== null) { + // Convert dotted module path to slash-separated path + imports.add(match[1].replace(/\./g, "/")); + } + while ((match = importRegex.exec(content)) !== null) { + imports.add(match[1].replace(/\./g, "/")); + } + } else if (ext === ".rb") { + // Ruby: require 'path' / require_relative 'path' + const reqRegex = /require(?:_relative)?\s+['"]([^'"]+)['"]/g; + let match; + while ((match = reqRegex.exec(content)) !== null) { + imports.add(match[1]); + } + } else if (ext === ".go") { + // Go: import "path" (single or block) + const blockRegex = /import\s*\(([\s\S]*?)\)/g; + const singleRegex = /import\s+"([^"]+)"/g; + let match; + while ((match = blockRegex.exec(content)) !== null) { + const block = match[1]; + const lineRegex = /"([^"]+)"/g; + let lineMatch; + while ((lineMatch = lineRegex.exec(block)) !== null) { + imports.add(lineMatch[1]); + } + } + while ((match = singleRegex.exec(content)) !== null) { + imports.add(match[1]); + } }   return Array.from(imports); @@ -1424,9 +1763,11 @@

All files / src/engines< let resolvedPath: string;   if (importPath.startsWith(".")) { - // Relative import: resolve from importing file's directory - const dir = path.dirname(fromPath); - resolvedPath = path.resolve(dir, importPath); + // Relative import: resolve from importing file's directory within projectRoot. + // path.join(projectRoot, fromPath) gives an absolute base so that + // path.resolve() anchors to projectRoot instead of process.cwd(). + const absoluteFromDir = path.dirname(path.join(projectRoot, fromPath)); + resolvedPath = path.resolve(absoluteFromDir, importPath); E} else if (importPath.startsWith("src/")) { // Absolute src import resolvedPath = importPath; @@ -1441,14 +1782,25 @@

All files / src/engines< relPath = path.relative(projectRoot, resolvedPath).replace(/\\/g, "/"); }   - // Try different extensions - const candidates = [ - relPath, - `${relPath}.ts`, - `${relPath}.tsx`, - `${relPath}/index.ts`, - `${relPath}/index.tsx`, - ]; + // Try different extensions based on the source file's language + const fromExt = path.extname(fromPath).toLowerCase(); + let candidates: string[]; + Iif (fromExt === ".py") { + candidates = [relPath, `${relPath}.py`, `${relPath}/__init__.py`]; + I} else if (fromExt === ".rb") { + candidates = [relPath, `${relPath}.rb`]; + I} else if (fromExt === ".go") { + candidates = [relPath]; + } else { + // JS/TS (default) + candidates = [ + relPath, + `${relPath}.ts`, + `${relPath}.tsx`, + `${relPath}/index.ts`, + `${relPath}/index.tsx`, + ]; + }   for (const candidate of candidates) { const fullPath = path.join(projectRoot, candidate); @@ -1457,19 +1809,17 @@

All files / src/engines< } }   - // Return best guess if file doesn't exist yet - return relPath.endsWith(".ts") || relPath.endsWith(".tsx") - ? relPath - : `${relPath}.ts`; + // Return best guess if file doesn't exist yet (use source extension or configured default) + const fromExt2 = path.extname(fromPath).toLowerCase(); + const bestExt = fromExt2 || this.defaultExtension; + Iif (relPath.includes(".")) return relPath; + return relPath.endsWith(bestExt) ? relPath : `${relPath}${bestExt}`; }   /** * Check if import from one layer to another is allowed */ - private isImportAllowed( - fromLayer: LayerDefinition, - toLayer: LayerDefinition, - ): boolean { + private isImportAllowed(fromLayer: LayerDefinition, toLayer: LayerDefinition): boolean { // Can always import from same layer if (fromLayer.id === toLayer.id) { return true; @@ -1486,10 +1836,7 @@

All files / src/engines< /** * Check if import is explicitly forbidden */ - private isForbiddenImport( - fromLayer: LayerDefinition, - toLayer: LayerDefinition, - ): boolean { + private isForbiddenImport(fromLayer: LayerDefinition, toLayer: LayerDefinition): boolean { Iif (!fromLayer.cannotImport) { return false; } @@ -1501,17 +1848,26 @@

All files / src/engines< */ private detectCircularDependencies(): ValidationViolation[] { const violations: ValidationViolation[] = []; - const projectRoot = process.cwd(); + const projectRoot = this.workspaceRoot; const visited = new Set<string>(); const recursionStack = new Set<string>(); const cycles: string[][] = [];   // Build import graph const importGraph = new Map<string, string[]>(); - const sourceFiles = globSync("src/**/*.{ts,tsx}", { - cwd: projectRoot, - ignore: ["**/node_modules/**", "**/*.test.ts", "**/*.test.tsx"], - }); + const sourceFiles = this.sourceGlobs.flatMap((pattern) => + globSync(pattern, { + cwd: projectRoot, + ignore: [ + "**/node_modules/**", + "**/*.test.*", + "**/*.spec.*", + "**/test_*.py", + "**/*_test.go", + "**/*_spec.rb", + ], + }), + );   for (const file of sourceFiles) { const imports = this.extractImportsFromFile(path.join(projectRoot, file)); @@ -1574,8 +1930,7 @@

All files / src/engines< file: cycle[0], layer: this.determineLayer(cycle[0])?.id || "unknown", message: `Circular dependency detected: ${cycle.slice(0, 3).join(" -> ")}...`, - suggestion: - "Break the circular dependency by moving code to a shared utility module", + suggestion: "Break the circular dependency by moving code to a shared utility module", }); } } @@ -1584,64 +1939,119 @@

All files / src/engines< }   /** - * Get suggestion for placing new code + * Get suggestion for placing new code. + * + * Layer selection strategy: + * 1. Filter to layers that can import from all dependency layer IDs. + * External package names (e.g. "react", "zustand") are not layer IDs and + * are skipped; they do not constrain layer selection. + * 2. Among eligible layers, rank by affinity with codeType to pick the + * semantically best match (e.g. "service" → services/lib layer, not types). */ getSuggestion( codeName: string, - codeType: "component" | "hook" | "service" | "context" | "utility", + codeType: string, dependencies: string[], ): { suggestedLayer: LayerDefinition; suggestedPath: string; reasoning: string; } | null { - // Find layer that can satisfy all dependencies + // Only use deps that are recognized layer IDs; external packages are ignored + const layerDeps = dependencies.filter((dep) => this.layers.has(dep)); +  + // Find all layers that can import from every required layer dependency + const eligibleLayers: LayerDefinition[] = []; for (const layer of this.layers.values()) { let canImportAll = true; -  - for (const dep of dependencies) { - // Find which layer the dependency is in - // For now, assume dependency is a module name we can look up - const depLayer = this.layers.get(dep); - Iif (depLayer && !this.isImportAllowed(layer, depLayer)) { + for (const dep of layerDeps) { + const depLayer = this.layers.get(dep)!; + Iif (!this.isImportAllowed(layer, depLayer)) { canImportAll = false; break; } } -  Eif (canImportAll) { - // Suggest first matching path pattern - const suggestedPath = this.getSuggestedPath(layer, codeName, codeType); - return { - suggestedLayer: layer, - suggestedPath, - reasoning: `Layer '${layer.name}' can import from ${layer.canImport.join(", ")}`, - }; + eligibleLayers.push(layer); } }   - return null; + Iif (eligibleLayers.length === 0) { + return null; + } +  + // Rank eligible layers by codeType affinity (higher-priority terms first) + const affinityMap: Record<string, string[]> = { + component: ["component", "ui", "view", "page", "widget", "presentation"], + hook: ["hook", "custom"], + service: ["service", "api", "engine", "lib", "utils"], + context: ["context", "store", "state", "provider"], + utility: ["util", "lib", "common", "shared", "helper"], + engine: ["engine", "service", "lib"], + class: ["engine", "service", "lib", "model"], + module: ["lib", "util", "common", "shared"], + }; + const affinityTerms: string[] = affinityMap[codeType] ?? []; +  + let bestLayer = eligibleLayers[0]; + let bestScore = -1; + for (const layer of eligibleLayers) { + const layerIdLower = layer.id.toLowerCase(); + let score = 0; + for (let i = 0; i < affinityTerms.length; i++) { + if (layerIdLower.includes(affinityTerms[i])) { + // Earlier terms carry higher weight + score = affinityTerms.length - i; + break; + } + } + if (score > bestScore) { + bestScore = score; + bestLayer = layer; + } + } +  + const suggestedPath = this.getSuggestedPath(bestLayer, codeName, codeType); + const importableFrom = + bestLayer.canImport.length > 0 + ? bestLayer.canImport.join(", ") + : "no other layers (foundational layer)"; +  + return { + suggestedLayer: bestLayer, + suggestedPath, + reasoning: `Layer '${bestLayer.name}' best matches '${codeType}' and can import from: ${importableFrom}`, + }; }   - private getSuggestedPath( - layer: LayerDefinition, - codeName: string, - codeType: string, - ): string { + private getSuggestedPath(layer: LayerDefinition, codeName: string, codeType: string): string { // Use first path pattern and apply naming convention const basePattern = layer.paths[0]; - const basePath = basePattern.replace("/**", ""); + const basePath = basePattern.replace("/**", "").replace(/\/\*$/, "");   - let fileName = codeName; + let fileName: string; Iif (codeType === "component") { - fileName = codeName.endsWith(".tsx") ? codeName : `${codeName}.tsx`; - I} else if (codeType === "hook") { - fileName = codeName.startsWith("use") ? codeName : `use${codeName}`; - fileName = fileName.endsWith(".ts") ? fileName : `${fileName}.ts`; - E} else if (codeType === "service") { - fileName = codeName.endsWith("Service.ts") - ? codeName - : `${codeName}Service.ts`; + // Components typically use .tsx (React) — honour configured extension if it differs + const compExt = this.defaultExtension === ".tsx" ? ".tsx" : `${this.defaultExtension}`; + const hasExt = /\.[^/\\]+$/.test(codeName); + fileName = hasExt ? codeName : `${codeName}${compExt}`; + } else if (codeType === "hook") { + fileName = codeName.startsWith("use") ? codeName : `use${codeName}`; + const hasExt = /\.[^/\\]+$/.test(fileName); + fileName = hasExt ? fileName : `${fileName}${this.defaultExtension}`; + } else if (codeType === "service") { + const hasExt = /\.[^/\\]+$/.test(codeName); + Iif (hasExt) { + fileName = codeName; + } else if (codeName.endsWith("Service")) { + fileName = `${codeName}${this.defaultExtension}`; + } else { + fileName = `${codeName}Service${this.defaultExtension}`; + } + } else E{ + // Default: ensure configured extension + const hasExt = /\.[^/\\]+$/.test(codeName); + fileName = hasExt ? codeName : `${codeName}${this.defaultExtension}`; }   return `${basePath}/${fileName}`; @@ -1654,7 +2064,7 @@

All files / src/engines< client: MemgraphClient, violations: ValidationViolation[], ): Promise<void> { - console.log(`\n📝 Writing ${violations.length} violations to Memgraph...`); + logger.error(`\n📝 Writing ${violations.length} violations to Memgraph...`);   const statements: CypherStatement[] = [];   @@ -1676,6 +2086,11 @@

All files / src/engines<   // Create FILE nodes and VIOLATES_RULE relationships for (const violation of violations) { + // Resolve to absolute path to match FILE nodes created by the graph builder + const absoluteFilePath = path.isAbsolute(violation.file) + ? violation.file + : path.resolve(this.workspaceRoot, violation.file); +  // Create or update FILE node statements.push({ query: ` @@ -1683,7 +2098,7 @@

All files / src/engines< SET f.lastViolationCheck = timestamp() `, params: { - filePath: violation.file, + filePath: absoluteFilePath, }, });   @@ -1699,7 +2114,7 @@

All files / src/engines< SET vr.severity = $severity, vr.message = $message, vr.timestamp = timestamp() `, params: { - filePath: violation.file, + filePath: absoluteFilePath, ruleId: ruleId, severity: violation.severity, message: violation.message, @@ -1714,12 +2129,10 @@

All files / src/engines< // Check for errors const errors = results.filter((r) => r.error); if (errors.length > 0) { - console.error(`⚠️ ${errors.length} Cypher statements failed:`); - errors.slice(0, 3).forEach((e) => console.error(` - ${e.error}`)); + logger.error(`⚠️ ${errors.length} Cypher statements failed:`); + errors.slice(0, 3).forEach((e) => logger.error(` - ${e.error}`)); } else { - console.log( - `✅ Successfully wrote ${violations.length} violations to graph`, - ); + logger.error(`✅ Successfully wrote ${violations.length} violations to graph`); } }   @@ -1727,11 +2140,12 @@

All files / src/engines< * Reload engine state from updated graph index * Called when project context changes */ - reload(_index: GraphIndexManager, projectId?: string): void { - console.log( - `[ArchitectureEngine] Reloading architecture validation (projectId=${projectId})`, - ); - // ArchitectureEngine doesn't hold project-specific state in index + reload(_index: GraphIndexManager, projectId?: string, workspaceRoot?: string): void { + logger.error(`[ArchitectureEngine] Reloading architecture validation (projectId=${projectId})`); + Eif (workspaceRoot) { + this.workspaceRoot = workspaceRoot; + } + // ArchitectureEngine doesn't hold other project-specific state in index // so reload is mainly for consistency with other engines }   @@ -1762,7 +2176,7 @@

All files / src/engines< + + + + + + \ No newline at end of file diff --git a/coverage/src/engines/coordination-types.ts.html b/coverage/src/engines/coordination-types.ts.html new file mode 100644 index 0000000..23fa04c --- /dev/null +++ b/coverage/src/engines/coordination-types.ts.html @@ -0,0 +1,322 @@ + + + + + + Code coverage report for src/engines/coordination-types.ts + + + + + + + + + +
+
+

All files / src/engines coordination-types.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file engines/coordination-types
+ * @description Public type contracts for coordination workflows.
+ * @remarks Kept separate so callers can import types without importing engine runtime code.
+ */
+ 
+export type ClaimType = "task" | "file" | "function" | "feature";
+ 
+export type InvalidationReason = "released" | "code_changed" | "task_completed" | "expired";
+ 
+export interface AgentClaim {
+  id: string;
+  agentId: string;
+  sessionId: string;
+  taskId?: string;
+  claimType: ClaimType;
+  targetId: string;
+  intent: string;
+  validFrom: number;
+  targetVersionSHA?: string;
+  validTo: number | null;
+  invalidationReason?: InvalidationReason;
+  outcome?: string;
+  projectId: string;
+}
+ 
+export interface ClaimInput {
+  agentId: string;
+  sessionId: string;
+  projectId: string;
+  targetId: string;
+  claimType: ClaimType;
+  intent: string;
+  taskId?: string;
+}
+ 
+export interface ClaimResult {
+  claimId: string;
+  status: "ok" | "CONFLICT";
+  conflict?: { agentId: string; intent: string; since: number };
+  targetVersionSHA: string;
+}
+ 
+/** Typed result for the release() method — replaces the original void return. */
+export interface ReleaseFeedback {
+  /** true if the claim existed and was open when release was called */
+  found: boolean;
+  /** true if the claim existed but was already closed before this call */
+  alreadyClosed: boolean;
+}
+ 
+export interface AgentStatus {
+  agentId: string;
+  activeClaims: AgentClaim[];
+  recentEpisodes: Array<{
+    id: string;
+    type: string;
+    content: string;
+    timestamp: number;
+    taskId?: string;
+  }>;
+  currentTask?: string;
+}
+ 
+export interface CoordinationOverview {
+  activeClaims: AgentClaim[];
+  staleClaims: AgentClaim[];
+  conflicts: Array<{
+    targetId: string;
+    claimA: { claimId: string; agentId: string; intent: string; since: number };
+    claimB: { claimId: string; agentId: string; intent: string; since: number };
+  }>;
+  agentSummary: Array<{
+    agentId: string;
+    claimCount: number;
+    lastSeen: number;
+  }>;
+  totalClaims: number;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/engines/coordination-utils.ts.html b/coverage/src/engines/coordination-utils.ts.html new file mode 100644 index 0000000..2d22caa --- /dev/null +++ b/coverage/src/engines/coordination-utils.ts.html @@ -0,0 +1,226 @@ + + + + + + Code coverage report for src/engines/coordination-utils.ts + + + + + + + + + +
+
+

All files / src/engines coordination-utils.ts

+
+ +
+ 100% + Statements + 5/5 +
+ + +
+ 90.9% + Branches + 30/33 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 5/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +11x +2x +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  + 
/**
+ * @file engines/coordination-utils
+ * @description Pure helper functions for coordination IDs, mapping, and normalization.
+ * @remarks Utility functions are side-effect free and independently testable.
+ */
+ 
+import type { AgentClaim, ClaimType, InvalidationReason } from "./coordination-types.js";
+ 
+/**
+ * Maps a raw Memgraph row (or the nested `c` property) to an AgentClaim.
+ * Returns null if the row lacks a required `id` field.
+ */
+export function rowToClaim(row: Record<string, unknown>): AgentClaim | null {
+  const claim = (row.c as Record<string, unknown>) || (row.claim as Record<string, unknown>) || row;
+ 
+  if (!claim || typeof claim !== "object" || !claim.id) {
+    return null;
+  }
+ 
+  return {
+    id: String(claim.id),
+    agentId: String(claim.agentId ?? "unknown"),
+    sessionId: String(claim.sessionId ?? "unknown"),
+    taskId: claim.taskId ? String(claim.taskId) : undefined,
+    claimType: (claim.claimType ?? "task") as ClaimType,
+    targetId: String(claim.targetId ?? ""),
+    intent: String(claim.intent ?? ""),
+    validFrom: Number(claim.validFrom ?? Date.now()),
+    targetVersionSHA: claim.targetVersionSHA ? String(claim.targetVersionSHA) : undefined,
+    validTo: claim.validTo == null ? null : Number(claim.validTo),
+    invalidationReason: claim.invalidationReason
+      ? (String(claim.invalidationReason) as InvalidationReason)
+      : undefined,
+    outcome: claim.outcome ? String(claim.outcome) : undefined,
+    projectId: String(claim.projectId ?? "unknown"),
+  };
+}
+ 
+/**
+ * Generate a time-prefixed pseudo-unique ID.
+ * @param prefix  e.g. "claim"
+ * @param now     injectable timestamp (ms) — defaults to Date.now(); pass a
+ *                fixed value in tests to get deterministic IDs.
+ */
+export function makeClaimId(prefix: string, now: number = Date.now()): string {
+  return `${prefix}-${now}-${Math.random().toString(36).slice(2, 10)}`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/engines/docs-engine.ts.html b/coverage/src/engines/docs-engine.ts.html index d09251a..101a46c 100644 --- a/coverage/src/engines/docs-engine.ts.html +++ b/coverage/src/engines/docs-engine.ts.html @@ -44,9 +44,9 @@

All files / src/engines<
- 96.73% + 96.62% Lines - 89/92 + 86/89
@@ -443,19 +443,7 @@

All files / src/engines< 378 379 380 -381 -382 -383 -384 -385 -386 -387 -388 -389 -390 -391 -392 -393  +381        @@ -510,9 +498,9 @@

All files / src/engines<       -4x -4x   +5x +5x       @@ -526,10 +514,11 @@

All files / src/engines<       -75x -75x -75x -75x +  +144x +144x +144x +144x     21x @@ -552,6 +541,7 @@

All files / src/engines< 9x 9x   +  9x 9x   @@ -596,8 +586,6 @@

All files / src/engines< 3x 3x   -  -        @@ -676,10 +664,6 @@

All files / src/engines<   3x 1x -1x -  -  -        @@ -697,9 +681,6 @@

All files / src/engines<     3x -  -  -  3x     @@ -733,8 +714,6 @@

All files / src/engines<   4x 2x -2x -        @@ -747,7 +726,6 @@

All files / src/engines<     2x -  3x   2x @@ -773,12 +751,10 @@

All files / src/engines<     2x -2x 21x       -  24x     @@ -848,9 +824,9 @@

All files / src/engines<      
/**
- * Docs Engine
- * Orchestrates markdown file discovery, parsing, and graph indexing.
- * Supports incremental updates (hash-based), vector embedding, and search.
+ * @file engines/docs-engine
+ * @description Indexes markdown docs into graph sections and supports documentation search.
+ * @remarks Supports incremental hashing and optional Qdrant embeddings.
  */
  
 import type { MemgraphClient } from "../graph/client.js";
@@ -858,6 +834,7 @@ 

All files / src/engines< import { DocsBuilder } from "../graph/docs-builder.js"; import { DocsParser, findMarkdownFiles } from "../parsers/docs-parser.js"; import type { ParsedDoc } from "../parsers/docs-parser.js"; +import { logger } from "../utils/logger.js";   // ─── Public types ─────────────────────────────────────────────────────────────   @@ -943,8 +920,9 @@

All files / src/engines< ): Promise<DocsIndexResult> { const t0 = Date.now(); const incremental = opts.incremental ?? true; - // Phase 3.2: Enable doc embeddings by default - const withEmbeddings = opts.withEmbeddings ?? true; + // withEmbeddings defaults to false — callers that want Qdrant embedding must opt in explicitly. + // (The orchestrator path does not supply a Qdrant client and must not attempt to embed.) + const withEmbeddings = opts.withEmbeddings ?? false; const txId = opts.txId ?? `doc-tx-${Date.now()}`;   const files = findMarkdownFiles(workspaceRoot); @@ -986,11 +964,9 @@

All files / src/engines< if (withEmbeddings && this.qdrant?.isConnected()) { try { await this.embedDoc(doc, projectId); - console.log( - `[Phase3.2] Generated embeddings for documentation: ${doc.relativePath}`, - ); + logger.error(`[Phase3.2] Generated embeddings for documentation: ${doc.relativePath}`); } catch (embeddingError) { - console.error( + logger.error( `[Phase3.2] Failed to embed documentation ${doc.relativePath}:`, embeddingError, ); @@ -1061,22 +1037,18 @@

All files / src/engines< s.startLine AS startLine, r.strength AS score ORDER BY score DESC -LIMIT $limit +LIMIT ${limit} `, - { projectId, name: symbolName, limit }, + { projectId, name: symbolName }, );   if (res.error || !res.data.length) return []; - return res.data.map((row: Record<string, unknown>) => - this.rowToResult(row), - ); + return res.data.map((row: Record<string, unknown>) => this.rowToResult(row)); }   // ── Private helpers ──────────────────────────────────────────────────────────   - private async fetchExistingHashes( - projectId: string, - ): Promise<Map<string, string>> { + private async fetchExistingHashes(projectId: string): Promise<Map<string, string>> { const res = await this.memgraph.executeCypher( `MATCH (d:DOCUMENT { projectId: $projectId }) RETURN d.relativePath AS relativePath, d.hash AS hash`, @@ -1088,10 +1060,7 @@

All files / src/engines< relativePath: unknown; hash: unknown; }>) { - Eif ( - typeof row.relativePath === "string" && - typeof row.hash === "string" - ) { + Eif (typeof row.relativePath === "string" && typeof row.hash === "string") { map.set(row.relativePath, row.hash); } } @@ -1119,14 +1088,12 @@

All files / src/engines< node.startLine AS startLine, score ORDER BY score DESC -LIMIT $limit +LIMIT ${limit} `, - { query, projectId, limit }, + { query, projectId }, ); if (res.error || res.data.length === 0) return null; - return res.data.map((row: Record<string, unknown>) => - this.rowToResult(row), - ); + return res.data.map((row: Record<string, unknown>) => this.rowToResult(row)); } catch { return null; } @@ -1139,10 +1106,9 @@

All files / src/engines< ): Promise<DocsSearchResult[]> { // Build a simple WHERE clause that checks heading and content const whereClauses = terms.map( - (_, i) => - `(toLower(s.heading) CONTAINS $term${i} OR toLower(s.content) CONTAINS $term${i})`, + (_, i) => `(toLower(s.heading) CONTAINS $term${i} OR toLower(s.content) CONTAINS $term${i})`, ); - const params: Record<string, unknown> = { projectId, limit }; + const params: Record<string, unknown> = { projectId }; terms.forEach((t, i) => { params[`term${i}`] = t; }); @@ -1159,15 +1125,13 @@

All files / src/engines< s.startLine AS startLine, 1.0 AS score ORDER BY s.heading -LIMIT $limit +LIMIT ${limit} `, params, );   Iif (res.error || !res.data.length) return []; - return res.data.map((row: Record<string, unknown>) => - this.rowToResult(row), - ); + return res.data.map((row: Record<string, unknown>) => this.rowToResult(row)); }   private rowToResult(row: Record<string, unknown>): DocsSearchResult { @@ -1246,7 +1210,7 @@

All files / src/engines< + + + + + + \ No newline at end of file diff --git a/coverage/src/engines/progress-engine.ts.html b/coverage/src/engines/progress-engine.ts.html index cc0bdfa..04e3d26 100644 --- a/coverage/src/engines/progress-engine.ts.html +++ b/coverage/src/engines/progress-engine.ts.html @@ -23,30 +23,30 @@

All files / src/engines<
- 67.08% + 69.56% Statements - 108/161 + 112/161
- 44.44% + 46.03% Branches - 56/126 + 58/126
- 69.69% + 72.72% Functions - 23/33 + 24/33
- 69.44% + 72.14% Lines - 100/144 + 101/140
@@ -570,39 +570,7 @@

All files / src/engines< 505 506 507 -508 -509 -510 -511 -512 -513 -514 -515 -516 -517 -518 -519 -520 -521 -522 -523 -524 -525 -526 -527 -528 -529 -530 -531 -532 -533 -534 -535 -536 -537 -538 -539 -540  +508        @@ -668,20 +636,22 @@

All files / src/engines<       -62x -62x -62x -62x -62x     +131x +131x +131x +131x +131x           -72x -72x +  +  +151x +151x 8x     @@ -696,8 +666,8 @@

All files / src/engines<       -72x -72x +151x +151x 14x     @@ -713,7 +683,7 @@

All files / src/engines<       -72x +151x 14x 14x 14x @@ -790,11 +760,9 @@

All files / src/engines< 1x     -1x 2x     -  1x 1x   @@ -829,19 +797,13 @@

All files / src/engines<   1x 1x -  -1x 1x 1x 1x       -  -  -1x 1x -  1x 1x 1x @@ -850,13 +812,10 @@

All files / src/engines<       -  -  2x     2x -  1x   1x @@ -880,22 +839,20 @@

All files / src/engines<       -  -  -  +1x   -  +1x       -  +1x             -  +1x       @@ -933,12 +890,8 @@

All files / src/engines<       -  -      -  -        @@ -952,6 +905,7 @@

All files / src/engines<       +        @@ -983,8 +937,6 @@

All files / src/engines<       -  -        @@ -1000,8 +952,6 @@

All files / src/engines<       -  -  1x     @@ -1026,9 +976,6 @@

All files / src/engines<     1x -  -  -  1x     @@ -1040,9 +987,6 @@

All files / src/engines<       -  -  -        @@ -1067,15 +1011,9 @@

All files / src/engines<       -  -  -        -  -  -        @@ -1085,31 +1023,31 @@

All files / src/engines<       -10x +20x   -10x -10x -10x -10x +20x +20x +20x +20x     -10x -10x +20x +20x 2x 1x       -10x +20x 3x 1x         -10x -10x -10x +20x +20x +20x       @@ -1126,10 +1064,8 @@

All files / src/engines<       -      -        @@ -1142,14 +1078,16 @@

All files / src/engines<      
/**
- * Progress Tracking Engine
- * Manages features, tasks, and milestones in the code graph
+ * @file engines/progress-engine
+ * @description Manages feature/task status and progress queries backed by graph state.
+ * @remarks Provides both in-memory and Memgraph persistence pathways.
  */
  
 import type { GraphIndexManager } from "../graph/index.js";
 import type { MemgraphClient } from "../graph/client.js";
 import type { CypherStatement } from "../graph/types.js";
 import { extractProjectIdFromScopedId } from "../utils/validation.js";
+import { logger } from "../utils/logger.js";
  
 export interface Feature {
   id: string;
@@ -1329,9 +1267,7 @@ 

All files / src/engines< Iif (!feature) return null;   // Get tasks for this feature - const tasks = Array.from(this.tasks.values()).filter( - (t) => t.featureId === featureId, - ); + const tasks = Array.from(this.tasks.values()).filter((t) => t.featureId === featureId);   // Get implementing files (linked via IMPLEMENTS relationship in graph) const implementingFiles: string[] = []; @@ -1367,26 +1303,18 @@

All files / src/engines<   // Get test coverage const testSuites = this.index.getNodesByType("TEST_SUITE").filter((n) => { - const testsRels = this.index - .getRelationshipsFrom(n.id) - .filter((r) => r.type === "TESTS"); + const testsRels = this.index.getRelationshipsFrom(n.id).filter((r) => r.type === "TESTS"); return testsRels.some((r) => { const tested = this.index.getNode(r.to); - return ( - tested && implementingFiles.includes(tested.properties.path || "") - ); + return tested && implementingFiles.includes(tested.properties.path || ""); }); });   const testCases = this.index.getNodesByType("TEST_CASE").filter((n) => { - const testRels = this.index - .getRelationshipsFrom(n.id) - .filter((r) => r.type === "TESTS"); + const testRels = this.index.getRelationshipsFrom(n.id).filter((r) => r.type === "TESTS"); return testRels.some((r) => { const tested = this.index.getNode(r.to); - return ( - tested && implementingFiles.includes(tested.properties.path || "") - ); + return tested && implementingFiles.includes(tested.properties.path || ""); }); });   @@ -1395,8 +1323,7 @@

All files / src/engines<   // Calculate progress const completedTasks = tasks.filter((t) => t.status === "completed").length; - const progressPercentage = - tasks.length > 0 ? (completedTasks / tasks.length) * 100 : 0; + const progressPercentage = tasks.length > 0 ? (completedTasks / tasks.length) * 100 : 0;   return { feature, @@ -1418,23 +1345,21 @@

All files / src/engines< /** * Find all blocking issues */ - getBlockingIssues(type?: "all" | "critical" | "features" | "tests"): Task[] { - const blocked = Array.from(this.tasks.values()).filter( - (t) => t.status === "blocked", - ); + getBlockingIssues(type?: "all" | "critical" | "features" | "tests"): Task[] { + const blocked = Array.from(this.tasks.values()).filter((t) => t.status === "blocked");   - if (type === "critical") { + Iif (type === "critical") { return blocked.filter((t) => t.blockedBy && t.blockedBy.length > 2); }   - if (type === "features") { + Iif (type === "features") { return blocked.filter((t) => { const feature = this.features.get(t.featureId || ""); return feature && feature.status !== "completed"; }); }   - return blocked; + return blocked; }   /** @@ -1468,20 +1393,17 @@

All files / src/engines< );   if (result.error) { - throw new Error( - `[ProgressEngine] Failed to persist feature to Memgraph: ${result.error}`, - ); + throw new Error(`[ProgressEngine] Failed to persist feature to Memgraph: ${result.error}`); }   // Only add to in-memory map after successful persistence this.features.set(feature.id, feature); - console.log( - `[Phase2d] Feature ${feature.id} created and persisted to Memgraph`, - ); + logger.error(`[Phase2d] Feature ${feature.id} created and persisted to Memgraph`); return feature; } catch (err) { throw new Error( `[ProgressEngine] Failed to create feature: ${err instanceof Error ? err.message : String(err)}`, + { cause: err }, ); } } @@ -1518,18 +1440,17 @@

All files / src/engines< );   if (result.error) { - throw new Error( - `[ProgressEngine] Failed to persist task to Memgraph: ${result.error}`, - ); + throw new Error(`[ProgressEngine] Failed to persist task to Memgraph: ${result.error}`); }   // Only add to in-memory map after successful persistence this.tasks.set(task.id, task); - console.log(`[Phase2d] Task ${task.id} created and persisted to Memgraph`); + logger.error(`[Phase2d] Task ${task.id} created and persisted to Memgraph`); return task; } catch (err) { throw new Error( `[ProgressEngine] Failed to create task: ${err instanceof Error ? err.message : String(err)}`, + { cause: err }, ); } } @@ -1537,10 +1458,7 @@

All files / src/engines< /** * Persist task update to Memgraph (Phase 5.3) */ - async persistTaskUpdate( - taskId: string, - updates: Partial<Task>, - ): Promise<boolean> { + async persistTaskUpdate(taskId: string, updates: Partial<Task>): Promise<boolean> { Iif (!this.memgraph || !this.memgraph.isConnected()) { return false; } @@ -1564,13 +1482,10 @@

All files / src/engines< }, };   - const result = await this.memgraph.executeCypher( - statement.query, - statement.params, - ); + const result = await this.memgraph.executeCypher(statement.query, statement.params); return !result.error; } catch (error) { - console.error("[ProgressEngine] Failed to persist task update:", error); + logger.error("[ProgressEngine] Failed to persist task update:", error); return false; } } @@ -1578,10 +1493,7 @@

All files / src/engines< /** * Persist feature update to Memgraph (Phase 5.3) */ - async persistFeatureUpdate( - featureId: string, - updates: Partial<Feature>, - ): Promise<boolean> { + async persistFeatureUpdate(featureId: string, updates: Partial<Feature>): Promise<boolean> { if (!this.memgraph || !this.memgraph.isConnected()) { return false; } @@ -1605,16 +1517,10 @@

All files / src/engines< }, };   - const result = await this.memgraph.executeCypher( - statement.query, - statement.params, - ); + const result = await this.memgraph.executeCypher(statement.query, statement.params); return !result.error; } catch (error) { - console.error( - "[ProgressEngine] Failed to persist feature update:", - error, - ); + logger.error("[ProgressEngine] Failed to persist feature update:", error); return false; } } @@ -1624,7 +1530,7 @@

All files / src/engines< * Called when project context changes to refresh feature/task data */ reload(index: GraphIndexManager, projectId?: string): void { - console.log(`[ProgressEngine] Reloading features and tasks (projectId=${projectId})`); + logger.error(`[ProgressEngine] Reloading features and tasks (projectId=${projectId})`);   this.index = index; this.features.clear(); @@ -1648,7 +1554,7 @@

All files / src/engines<   const featureCount = this.features.size; const taskCount = this.tasks.size; - console.log(`[ProgressEngine] Reloaded ${featureCount} features and ${taskCount} tasks`); + logger.error(`[ProgressEngine] Reloaded ${featureCount} features and ${taskCount} tasks`); }   /** @@ -1665,12 +1571,10 @@

All files / src/engines< (f) => f.status === "completed", ).length, totalTasks: this.tasks.size, - completedTasks: Array.from(this.tasks.values()).filter( - (t) => t.status === "completed", - ).length, - blockedTasks: Array.from(this.tasks.values()).filter( - (t) => t.status === "blocked", - ).length, + completedTasks: Array.from(this.tasks.values()).filter((t) => t.status === "completed") + .length, + blockedTasks: Array.from(this.tasks.values()).filter((t) => t.status === "blocked") + .length, }, }, null, @@ -1687,7 +1591,7 @@

All files / src/engines< + + + + + + \ No newline at end of file diff --git a/coverage/src/graph/types.ts.html b/coverage/src/graph/types.ts.html new file mode 100644 index 0000000..11500b2 --- /dev/null +++ b/coverage/src/graph/types.ts.html @@ -0,0 +1,112 @@ + + + + + + Code coverage report for src/graph/types.ts + + + + + + + + + +
+
+

All files / src/graph types.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10  +  +  +  +  +  +  +  +  + 
/**
+ * @file graph/types
+ * @description Shared low-level graph write/query type contracts.
+ */
+ 
+export interface CypherStatement {
+  query: string;
+  params: Record<string, any>;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/graph/watcher.ts.html b/coverage/src/graph/watcher.ts.html index 466ba02..695fa79 100644 --- a/coverage/src/graph/watcher.ts.html +++ b/coverage/src/graph/watcher.ts.html @@ -199,7 +199,19 @@

All files / src/graph134 135 136 -137  +137 +138 +139 +140 +141 +142 +143  +  +  +  +  +  +        @@ -335,7 +347,13 @@

All files / src/graph      - 
import chokidar from "chokidar";
+ 
/**
+ * @file graph/watcher
+ * @description Filesystem watcher for incremental rebuild triggering and change batching.
+ * @remarks Debounces events and emits normalized change sets per project context.
+ */
+ 
+import chokidar from "chokidar";
  
 export interface WatcherOptions {
   workspaceRoot: string;
@@ -478,7 +496,7 @@ 

All files / src/graph Code coverage generated by istanbul - at 2026-02-24T01:13:58.055Z + at 2026-02-27T23:25:35.933Z

+ + + + + + \ No newline at end of file diff --git a/coverage/src/parsers/parser-registry.ts.html b/coverage/src/parsers/parser-registry.ts.html index f9deddb..e1e98a8 100644 --- a/coverage/src/parsers/parser-registry.ts.html +++ b/coverage/src/parsers/parser-registry.ts.html @@ -94,11 +94,11 @@

All files / src/parsers<       -59x +127x     -222x -223x +494x +495x       @@ -151,7 +151,7 @@

All files / src/parsers< + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/contract-validator.ts.html b/coverage/src/tools/contract-validator.ts.html new file mode 100644 index 0000000..beff6a5 --- /dev/null +++ b/coverage/src/tools/contract-validator.ts.html @@ -0,0 +1,472 @@ + + + + + + Code coverage report for src/tools/contract-validator.ts + + + + + + + + + +
+
+

All files / src/tools contract-validator.ts

+
+ +
+ 92% + Statements + 23/25 +
+ + +
+ 66.66% + Branches + 12/18 +
+ + +
+ 100% + Functions + 7/7 +
+ + +
+ 95.65% + Lines + 22/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +3x +  +3x +6x +3x +  +3x +  +  +  +  +  +3x +3x +  +3x +1x +  +  +  +  +  +  +  +  +2x +3x +3x +  +  +  +  +  +  +2x +  +3x +  +3x +3x +3x +  +3x +3x +  +3x +  +  +  +  +  +  +  + 
/**
+ * @file tools/contract-validator
+ * @description Zod-based schema validation for tool arguments.
+ *
+ * Provides a standalone `validateToolArgs` function that validates a raw
+ * argument object against a tool's declared `inputShape`.  This module
+ * statically imports `registry.ts` — that is safe because the import graph
+ * only goes in one direction:
+ *
+ *   tool-handler-base → contract-validator → registry → handlers → types
+ *
+ * The handler files do NOT import
+ * `tool-handler-base` or `contract-validator`, so there is no cycle.
+ */
+ 
+import * as z from "zod";
+import { toolRegistryMap } from "./registry.js";
+ 
+// ─── Public contract ────────────────────────────────────────────────────────
+ 
+/**
+ * The result of validating tool arguments against the declared schema.
+ */
+export interface ContractValidation {
+  /** True when all required fields are present and have correct types. */
+  valid: boolean;
+ 
+  /**
+   * Zod validation errors describing incorrect or missing fields.
+   * Empty when `valid` is true.
+   */
+  errors: string[];
+ 
+  /**
+   * Fields present in the raw args that are not part of the tool's schema.
+   * These can indicate typos in parameter names (e.g. `codeType` instead
+   * of `type`) and are surfaced as warnings even when `valid` is true.
+   */
+  extraFields: string[];
+ 
+  /**
+   * Required schema fields that were absent from the raw args.
+   * Derived from Zod issues with `received: "undefined"`.
+   */
+  missingRequired: string[];
+ 
+  /**
+   * Human-readable advisory messages (e.g. unknown field hints).
+   * Does NOT indicate a validation failure on its own.
+   */
+  warnings: string[];
+}
+ 
+// ─── Implementation ─────────────────────────────────────────────────────────
+ 
+/**
+ * Validate `args` against the Zod `inputShape` registered for `toolName`.
+ *
+ * @param toolName - Canonical tool name as registered (e.g. `"semantic_diff"`).
+ * @param args     - Raw unvalidated arguments object (may be `null` / `undefined`).
+ * @returns        A {@link ContractValidation} describing the result.
+ */
+export function validateToolArgs(toolName: string, args: unknown): ContractValidation {
+  const def = toolRegistryMap.get(toolName);
+ 
+  Iif (!def) {
+    return {
+      valid: false,
+      errors: [`Unknown tool: '${toolName}'. Use tools_list to see valid names.`],
+      extraFields: [],
+      missingRequired: [],
+      warnings: [],
+    };
+  }
+ 
+  const inputKeys =
+    args !== null && typeof args === "object" ? Object.keys(args as Record<string, unknown>) : [];
+ 
+  const knownKeys = new Set(Object.keys(def.inputShape));
+  const extraFields = inputKeys.filter((k) => !knownKeys.has(k));
+  const warnings = extraFields.map(
+    (k) =>
+      `Unknown field '${k}' is not part of '${toolName}' schema — possible typo? Known fields: ${[...knownKeys].join(", ")}`,
+  );
+ 
+  // Build a strict Zod object schema to validate required/optional fields.
+  // We intentionally do NOT use .strict() here so that pass-through of extra
+  // fields does not cause a Zod error — we report them separately as warnings.
+  const schema = z.object(def.inputShape as z.ZodRawShape);
+  const result = schema.safeParse(args ?? {});
+ 
+  if (result.success) {
+    return {
+      valid: true,
+      errors: [],
+      extraFields,
+      missingRequired: [],
+      warnings,
+    };
+  }
+ 
+  const errors = result.error.issues.map((issue) => {
+    const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
+    return `${path}: ${issue.message}`;
+  });
+ 
+  // A field is "missing required" when the error references a top-level key
+  // that was not supplied in the input at all.  This handles both string/number
+  // (`invalid_type`) and enum (`invalid_value`) Zod v4 error codes.
+  const argsObj: Record<string, unknown> =
+    args !== null && typeof args === "object" ? (args as Record<string, unknown>) : {};
+ 
+  const missingRequired = result.error.issues
+    .filter((issue) => {
+      Iif (issue.path.length === 0) return false;
+      const topKey = String(issue.path[0]);
+      return !(topKey in argsObj);
+    })
+    .map((issue) => String(issue.path[0]))
+    .filter((key, idx, arr) => arr.indexOf(key) === idx); // deduplicate
+ 
+  return {
+    valid: false,
+    errors,
+    extraFields,
+    missingRequired,
+    warnings,
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/handlers/arch-tools.ts.html b/coverage/src/tools/handlers/arch-tools.ts.html index 54492fe..2b41986 100644 --- a/coverage/src/tools/handlers/arch-tools.ts.html +++ b/coverage/src/tools/handlers/arch-tools.ts.html @@ -23,30 +23,30 @@

All files / src/tools

-
+
1 2 @@ -180,7 +180,11 @@

All files / src/tools 115 116 117 -118

  +118 +119 +120 +121 +122        @@ -192,6 +196,7 @@

All files / src/tools       +4x       @@ -201,51 +206,53 @@

All files / src/tools       +5x   +5x           +5x +3x             +2x +2x   +2x   -57x         -2x   -2x -1x +5x   +            -1x -1x   -1x             -2x   -      +3x   +3x       @@ -254,27 +261,26 @@

All files / src/tools       -1x   -1x -              -1x -1x +3x +            -1x -1x   +3x +3x   +3x +2x       @@ -282,7 +288,9 @@

All files / src/tools       -  +  +  +1x       @@ -299,121 +307,125 @@

All files / src/tools    

/**
  * Architecture Validation Tools
- * Phase 5 Step 3: Extract architecture validation tools
+ * Registry-backed architecture tool definitions.
  *
  * Tools:
  * - arch_validate: validate code against architecture rules
  * - arch_suggest: suggest appropriate layer for code
- *
- * These tools delegate entirely to the ArchitectureEngine.
  */
  
-/**
- * Minimal context interface required by arch tools
- */
-interface ArchToolContext {
-  archEngine?: any; // ArchitectureEngine
-  errorEnvelope(
-    code: string,
-    reason: string,
-    recoverable?: boolean,
-    hint?: string
-  ): string;
-  formatSuccess(
-    data: unknown,
-    profile?: string,
-    summary?: string,
-    toolName?: string
-  ): string;
-}
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
  
-/**
- * Create architecture validation tools
- * @param ctx - Context object providing archEngine and formatting methods
- */
-export function createArchTools(ctx: ArchToolContext) {
-  return {
-    /**
-     * Validate code files against architecture rules
-     */
-    async arch_validate(args: any): Promise<string> {
+export const archToolDefinitions: ToolDefinition[] = [
+  {
+    name: "arch_validate",
+    category: "arch",
+    description: "Validate code against layer rules",
+    inputShape: {
+      files: z.array(z.string()).optional().describe("Files to validate"),
+      strict: z.boolean().default(false).describe("Strict validation mode"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
       const { files, strict = false, profile = "compact" } = args;
  
-      if (!ctx.archEngine) {
+      const archEngine = ctx.engines.arch as
+        | {
+            validate: (files?: string[]) => Promise<any>;
+          }
+        | undefined;
+ 
+      if (!archEngine) {
         return ctx.errorEnvelope(
           "ARCH_ENGINE_UNAVAILABLE",
           "Architecture engine not initialized",
-          true
+          true,
         );
       }
  
       try {
-        const result = await ctx.archEngine.validate(files);
+        const result = await archEngine.validate(files);
  
         const output = {
           success: result.success,
-          violations: result.violations.slice(0, 20), // Top 20 violations
+          violations: result.violations.slice(0, 20),
           statistics: result.statistics,
-          severity: strict ? "error" : "warning",
+          severity: strict ? "error" : "warning",
         };
  
         return ctx.formatSuccess(output, profile);
       } catch (error) {
-        return ctx.errorEnvelope(
-          "ARCH_VALIDATE_FAILED",
-          String(error),
-          true
-        );
+        return ctx.errorEnvelope("ARCH_VALIDATE_FAILED", String(error), true);
       }
     },
- 
-    /**
-     * Suggest appropriate layer for given code
-     */
-    async arch_suggest(args: any): Promise<string> {
+  },
+  {
+    name: "arch_suggest",
+    category: "arch",
+    description: "Suggest best location for new code",
+    inputShape: {
+      name: z.string().describe("Code name/identifier"),
+      type: z
+        .enum(["component", "hook", "service", "context", "utility", "engine", "class", "module"])
+        .describe("Code type"),
+      dependencies: z.array(z.string()).optional().describe("Required dependencies"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
       const { name, type, dependencies = [], profile = "compact" } = args;
  
-      Iif (!ctx.archEngine) {
+      const archEngine = ctx.engines.arch as
+        | {
+            getSuggestion: (
+              name: string,
+              type: string,
+              dependencies: string[],
+            ) =>
+              | {
+                  suggestedLayer: string;
+                  suggestedPath: string;
+                  reasoning: string;
+                }
+              | undefined;
+          }
+        | undefined;
+ 
+      Iif (!archEngine) {
         return ctx.errorEnvelope(
           "ARCH_ENGINE_UNAVAILABLE",
           "Architecture engine not initialized",
-          true
+          true,
         );
       }
  
       try {
-        const suggestion = ctx.archEngine.getSuggestion(
-          name,
-          type,
-          dependencies
-        );
+        const suggestion = archEngine.getSuggestion(name, type, dependencies);
  
-        Eif (!suggestion) {
+        if (!suggestion) {
           return ctx.formatSuccess(
             {
               success: false,
               message: "No suitable layer found for this code",
               reason: `No layer can import from all dependencies: ${dependencies.join(", ")}`,
             },
-            profile
+            profile,
           );
         }
  
-        return ctx.formatSuccess(
+        return ctx.formatSuccess(
           {
             success: true,
             suggestedLayer: suggestion.suggestedLayer,
             suggestedPath: suggestion.suggestedPath,
             reasoning: suggestion.reasoning,
           },
-          profile
+          profile,
         );
       } catch (error) {
         return ctx.errorEnvelope("ARCH_SUGGEST_FAILED", String(error), true);
       }
     },
-  };
-}
+  },
+];
  
@@ -421,7 +433,7 @@

All files / src/tools + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/handlers/core-graph-tools.ts.html b/coverage/src/tools/handlers/core-graph-tools.ts.html new file mode 100644 index 0000000..0e01302 --- /dev/null +++ b/coverage/src/tools/handlers/core-graph-tools.ts.html @@ -0,0 +1,3031 @@ + + + + + + Code coverage report for src/tools/handlers/core-graph-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers core-graph-tools.ts

+
+ +
+ 80.09% + Statements + 165/206 +
+ + +
+ 69.23% + Branches + 162/234 +
+ + +
+ 82.6% + Functions + 19/23 +
+ + +
+ 80.19% + Lines + 162/202 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +6x +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +1x +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +13x +  +13x +  +  +  +  +  +  +  +  +  +  +13x +  +13x +13x +13x +  +13x +  +10x +  +10x +  +  +  +  +  +  +3x +1x +  +1x +  +  +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +2x +2x +  +  +  +13x +  +  +  +  +  +  +  +  +13x +13x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +4x +4x +  +  +  +  +  +  +  +4x +4x +  +4x +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +4x +4x +  +4x +3x +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +4x +  +  +  +4x +3x +  +  +  +  +  +3x +2x +2x +  +  +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +3x +3x +3x +  +  +  +  +3x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +1x +1x +1x +  +  +1x +1x +  +  +1x +  +  +4x +  +4x +3x +  +  +  +  +4x +  +  +  +3x +3x +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +15x +15x +15x +  +15x +  +15x +  +  +  +  +1x +  +  +  +  +  +  +  +14x +  +14x +  +  +  +  +  +  +  +  +14x +  +  +  +  +  +  +  +  +14x +14x +  +14x +  +14x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +6x +  +  +  +  +  +  +6x +6x +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +6x +6x +6x +6x +6x +  +6x +  +6x +6x +6x +6x +6x +  +6x +6x +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +6x +6x +  +6x +  +  +  +  +  +  +6x +6x +6x +  +  +6x +  +6x +6x +2x +  +  +  +6x +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +3x +3x +  +3x +  +  +  +3x +  +9x +9x +  +  +3x +  +  +  +  +  +  +  +3x +3x +1x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +2x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +3x +  +  +  +  +  +  +  +  +2x +3x +3x +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file tools/handlers/core-graph-tools
+ * @description Graph tool definitions — graph_query, graph_rebuild, graph_set_workspace, graph_health, diff_since.
+ */
+ 
+import * as fs from "fs";
+import * as z from "zod";
+import * as env from "../../env.js";
+import { generateSecureId } from "../../utils/validation.js";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+import { logger } from "../../utils/logger.js";
+ 
+/**
+ * Derives coarse label hints for global community search fallback queries.
+ */
+function deriveLabelHints(query: string): string[] {
+  const raw = query.toLowerCase();
+  const hints = ["tools", "engines", "graph", "parsers", "vector", "config"];
+  return hints.filter((hint) => raw.includes(hint));
+}
+ 
+/**
+ * Filters retrieval rows using temporal validity windows.
+ */
+function filterTemporalRows(
+  ctx: HandlerBridge,
+  rows: Array<{ nodeId?: string }>,
+  asOfTs?: number | null,
+): Array<{ nodeId?: string }> {
+  Eif (asOfTs === null || asOfTs === undefined) {
+    return rows;
+  }
+ 
+  return rows.filter((row) => {
+    if (!row.nodeId) {
+      return true;
+    }
+ 
+    const node = ctx.context.index.getNode(row.nodeId);
+    const validFrom = Number(node?.properties?.validFrom);
+    const validToRaw = node?.properties?.validTo;
+    const validTo =
+      validToRaw === null || validToRaw === undefined ? undefined : Number(validToRaw);
+ 
+    if (!Number.isFinite(validFrom)) {
+      return true;
+    }
+ 
+    return (
+      validFrom <= asOfTs &&
+      (!Number.isFinite(validTo) || (validTo !== undefined && validTo > asOfTs))
+    );
+  });
+}
+ 
+/**
+ * Resolves global community candidates used by graph query hybrid/global modes.
+ */
+async function fetchGlobalCommunityRows(
+  ctx: HandlerBridge,
+  query: string,
+  projectId: string,
+  limit: number,
+): Promise<any[]> {
+  const keywordHint = query
+    .toLowerCase()
+    .split(/[^a-z0-9_]+/)
+    .find((token) => token.length >= 4);
+ 
+  const params: Record<string, unknown> = {
+    projectId,
+    limit,
+    keywordHint: keywordHint || null,
+    labels: deriveLabelHints(query),
+  };
+ 
+  const scoped = await ctx.context.memgraph.executeCypher(
+    `MATCH (c:COMMUNITY {projectId: $projectId})
+     WHERE ($keywordHint IS NOT NULL AND toLower(c.summary) CONTAINS $keywordHint)
+        OR toLower(c.label) IN $labels
+     RETURN c.id AS id, c.label AS label, c.summary AS summary, c.memberCount AS memberCount
+     ORDER BY c.memberCount DESC
+     LIMIT $limit`,
+    params,
+  );
+ 
+  Eif (scoped.data.length > 0) {
+    return scoped.data;
+  }
+ 
+  const fallback = await ctx.context.memgraph.executeCypher(
+    `MATCH (c:COMMUNITY {projectId: $projectId})
+     RETURN c.id AS id, c.label AS label, c.summary AS summary, c.memberCount AS memberCount
+     ORDER BY c.memberCount DESC
+     LIMIT $limit`,
+    { projectId, limit },
+  );
+ 
+  return fallback.data;
+}
+ 
+/**
+ * Canonical list of core tool definitions consumed by split category modules.
+ */
+ 
+export const coreGraphToolDefinitions: ToolDefinition[] = [
+  {
+    name: "graph_query",
+    category: "graph",
+    description: "Execute Cypher or natural language query against the code graph",
+    inputShape: {
+      query: z.string().describe("Cypher or natural language query"),
+      language: z.enum(["cypher", "natural"]).default("natural").describe("Query language"),
+      mode: z
+        .enum(["local", "global", "hybrid"])
+        .default("local")
+        .describe("Query mode for natural language"),
+      limit: z.number().default(100).describe("Result limit"),
+      asOf: z
+        .string()
+        .optional()
+        .describe("Optional ISO timestamp or epoch ms for temporal query mode"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        query,
+        language = "natural",
+        limit = 100,
+        profile = "compact",
+        asOf,
+        mode = "local",
+      } = args;
+ 
+      const hybridRetriever = ctx.engines.hybrid as
+        | {
+            retrieve: (args: {
+              query: string;
+              projectId: string;
+              limit: number;
+              mode: "hybrid";
+            }) => Promise<Array<{ nodeId?: string }>>;
+          }
+        | undefined;
+ 
+      try {
+        let result;
+        const { projectId, workspaceRoot } = ctx.getActiveProjectContext();
+        const asOfTs = ctx.toEpochMillis(asOf);
+        const queryMode = mode === "global" || mode === "hybrid" ? mode : "local";
+ 
+        if (language === "cypher") {
+          const cypherQuery =
+            asOfTs !== null ? (ctx as any).applyTemporalFilterToCypher(query) : query;
+ 
+          result =
+            asOfTs !== null
+              ? await ctx.context.memgraph.executeCypher(cypherQuery, {
+                  asOfTs,
+                })
+              : await ctx.context.memgraph.executeCypher(cypherQuery);
+        } else {
+          if (queryMode === "global" || queryMode === "hybrid") {
+            const globalRows = await fetchGlobalCommunityRows(ctx, query, projectId, limit);
+ 
+            Iif (queryMode === "global") {
+              result = { data: globalRows };
+            } else {
+              const localResults = await hybridRetriever!.retrieve({
+                query,
+                projectId,
+                limit,
+                mode: "hybrid",
+              });
+              const filteredLocal = filterTemporalRows(ctx, localResults, asOfTs);
+              result = {
+                data: [
+                  {
+                    section: "global",
+                    communities: globalRows,
+                  },
+                  {
+                    section: "local",
+                    results: filteredLocal,
+                  },
+                ],
+              };
+            }
+          } else {
+            const localResults = await hybridRetriever!.retrieve({
+              query,
+              projectId,
+              limit,
+              mode: "hybrid",
+            });
+            const filteredLocal = filterTemporalRows(ctx, localResults, asOfTs);
+            result = { data: filteredLocal };
+          }
+        }
+ 
+        Iif (result.error) {
+          return ctx.errorEnvelope(
+            "GRAPH_QUERY_FAILED",
+            result.error,
+            true,
+            "Try using language='cypher' with an explicit query.",
+          );
+        }
+ 
+        const limited = result.data.slice(0, limit);
+        return ctx.formatSuccess(
+          {
+            intent: language === "natural" ? (ctx as any).classifyIntent(query) : "cypher",
+            mode: queryMode,
+            projectId,
+            workspaceRoot,
+            asOf: asOfTs,
+            count: limited.length,
+            results: limited,
+          },
+          profile,
+          `Query returned ${limited.length} row(s).`,
+          "graph_query",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("GRAPH_QUERY_EXCEPTION", String(error), true);
+      }
+    },
+  },
+  {
+    name: "graph_rebuild",
+    category: "graph",
+    description: "Rebuild code graph from source",
+    inputShape: {
+      mode: z.enum(["full", "incremental"]).default("incremental").describe("Build mode"),
+      verbose: z.boolean().default(false).describe("Verbose output"),
+      workspaceRoot: z.string().optional().describe("Workspace root path (absolute preferred)"),
+      workspacePath: z.string().optional().describe("Alias for workspaceRoot"),
+      sourceDir: z
+        .string()
+        .optional()
+        .describe("Source directory path (absolute or relative to workspace root)"),
+      projectId: z.string().optional().describe("Project namespace for graph isolation"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+      indexDocs: z
+        .boolean()
+        .default(true)
+        .describe(
+          "Index markdown documentation files (READMEs, ADRs) during rebuild (default: true). Set false to skip docs indexing.",
+        ),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { mode = "incremental", verbose = false, profile = "compact", indexDocs = true } = args;
+ 
+      const orchestrator = ctx.engines.orchestrator as
+        | {
+            build: (args: Record<string, unknown>) => Promise<{
+              success: boolean;
+              duration: number;
+              filesProcessed: number;
+              nodesCreated: number;
+              relationshipsCreated: number;
+              filesChanged: number;
+              warnings: string[];
+              errors: string[];
+            }>;
+          }
+        | undefined;
+ 
+      const coordinationEngine = ctx.engines.coordination as
+        | {
+            invalidateStaleClaims: (projectId: string) => Promise<number>;
+          }
+        | undefined;
+ 
+      const embeddingEngine = ctx.engines.embedding as
+        | {
+            generateAllEmbeddings: () => Promise<{
+              functions: number;
+              classes: number;
+              files: number;
+            }>;
+            storeInQdrant: () => Promise<void>;
+          }
+        | undefined;
+ 
+      const communityDetector = ctx.engines.community as
+        | {
+            run: (projectId: string) => Promise<{
+              mode: string;
+              communities: number;
+              members: number;
+            }>;
+          }
+        | undefined;
+ 
+      const hybridRetriever = ctx.engines.hybrid as
+        | {
+            ensureBM25Index: () => Promise<{ created?: boolean; error?: string } | undefined>;
+          }
+        | undefined;
+ 
+      try {
+        Iif (!orchestrator) {
+          return ctx.errorEnvelope(
+            "GRAPH_ORCHESTRATOR_UNAVAILABLE",
+            "Graph orchestrator not initialized",
+            true,
+          );
+        }
+ 
+        let resolvedContext = ctx.resolveProjectContext(args || {});
+        const adapted = (ctx as any).adaptWorkspaceForRuntime(resolvedContext);
+        const explicitWorkspaceProvided =
+          typeof args?.workspaceRoot === "string" && args.workspaceRoot.trim().length > 0;
+ 
+        Iif (
+          adapted.usedFallback &&
+          explicitWorkspaceProvided &&
+          !(ctx as any).runtimePathFallbackAllowed()
+        ) {
+          return ctx.errorEnvelope(
+            "WORKSPACE_PATH_SANDBOXED",
+            `Requested workspaceRoot is not accessible from this runtime: ${resolvedContext.workspaceRoot}`,
+            true,
+            "Mount the target project into the container (e.g. LXRAG_TARGET_WORKSPACE) and restart docker-compose, or set LXRAG_ALLOW_RUNTIME_PATH_FALLBACK=true to force fallback to mounted workspace.",
+          );
+        }
+ 
+        resolvedContext = adapted.context;
+        (ctx as any).setActiveProjectContext(resolvedContext);
+        const { workspaceRoot, sourceDir, projectId } = resolvedContext;
+        const txTimestamp = Date.now();
+        const txId = generateSecureId("tx", 4);
+ 
+        if (ctx.context.memgraph.isConnected()) {
+          await ctx.context.memgraph.executeCypher(
+            `CREATE (tx:GRAPH_TX {id: $id, projectId: $projectId, type: $type, timestamp: $timestamp, mode: $mode, sourceDir: $sourceDir})`,
+            {
+              id: txId,
+              projectId,
+              type: mode === "full" ? "full_rebuild" : "incremental_rebuild",
+              timestamp: txTimestamp,
+              mode,
+              sourceDir,
+            },
+          );
+        }
+ 
+        Iif (!fs.existsSync(workspaceRoot)) {
+          return ctx.errorEnvelope(
+            "WORKSPACE_NOT_FOUND",
+            `Workspace root does not exist: ${workspaceRoot}`,
+            true,
+            "Call graph_set_workspace first with a valid path.",
+          );
+        }
+ 
+        Iif (!fs.existsSync(sourceDir)) {
+          return ctx.errorEnvelope(
+            "SOURCE_DIR_NOT_FOUND",
+            `Source directory does not exist: ${sourceDir}`,
+            true,
+            "Provide sourceDir in graph_rebuild or graph_set_workspace.",
+          );
+        }
+ 
+        const postBuild = async (result: {
+          success: boolean;
+          duration: number;
+          filesProcessed: number;
+          nodesCreated: number;
+          relationshipsCreated: number;
+          filesChanged: number;
+          warnings: string[];
+          errors: string[];
+        }) => {
+          logger.error(
+            `[graph_rebuild] ${mode} build completed in ${result.duration}ms (${result.filesProcessed} files, ${result.nodesCreated} nodes, ${result.errors.length} errors, ${result.warnings.length} warnings) for project ${projectId}`,
+          );
+ 
+          const invalidated = await coordinationEngine!.invalidateStaleClaims(projectId);
+          Iif (invalidated > 0) {
+            logger.error(
+              `[coordination] Invalidated ${invalidated} stale claim(s) post-rebuild for project ${projectId}`,
+            );
+          }
+ 
+          if (mode === "incremental") {
+            (ctx as any).setProjectEmbeddingsReady(projectId, false);
+            logger.error(
+              `[Phase2a] Embeddings flag reset for incremental rebuild of project ${projectId}`,
+            );
+          E} else if (mode === "full") {
+            try {
+              const generated = await embeddingEngine?.generateAllEmbeddings();
+              Iif (generated && generated.functions + generated.classes + generated.files > 0) {
+                await embeddingEngine?.storeInQdrant();
+                (ctx as any).setProjectEmbeddingsReady(projectId, true);
+                logger.error(
+                  `[Phase2b] Embeddings auto-generated for full rebuild: ${generated.functions} functions, ${generated.classes} classes, ${generated.files} files for project ${projectId}`,
+                );
+              }
+            } catch (embeddingError) {
+              logger.error(
+                `[Phase2b] Embedding generation failed during full rebuild for project ${projectId}:`,
+                embeddingError,
+              );
+            }
+ 
+            const communityRun = await communityDetector!.run(projectId);
+            logger.error(
+              `[community] ${communityRun.mode}: ${communityRun.communities} communities across ${communityRun.members} member node(s) for project ${projectId}`,
+            );
+          }
+ 
+          const bm25Result = await hybridRetriever?.ensureBM25Index();
+          if (bm25Result?.created) {
+            logger.error(`[bm25] Created text_search symbol_index for project ${projectId}`);
+          E} else if (bm25Result?.error) {
+            logger.error(`[bm25] symbol_index unavailable: ${bm25Result.error}`);
+          }
+ 
+          return result;
+        };
+ 
+        const buildPromise = orchestrator
+          .build({
+            mode,
+            verbose,
+            workspaceRoot,
+            projectId,
+            sourceDir,
+            txId,
+            txTimestamp,
+            indexDocs,
+            exclude: ["node_modules", "dist", ".next", ".lxrag", "__tests__", "coverage", ".git"],
+          })
+          .then(postBuild)
+          .catch((err) => {
+            const context = `mode=${mode}, projectId=${projectId}`;
+            (ctx as any).recordBuildError(projectId, err, context);
+ 
+            const errorMsg = err instanceof Error ? err.message : String(err);
+            const stack = err instanceof Error ? err.stack : "";
+            logger.error(
+              `[Phase4.5] Background build failed for project ${projectId} (${mode}): ${errorMsg}`,
+            );
+            Eif (stack) {
+              logger.error(`[Phase4.5] Stack trace: ${stack.substring(0, 500)}`);
+            }
+ 
+            throw err;
+          });
+ 
+        const thresholdMs = Math.max(1000, env.LXRAG_SYNC_REBUILD_THRESHOLD_MS);
+ 
+        const raceResult = await Promise.race([
+          buildPromise.then((result) => ({
+            status: "completed" as const,
+            result,
+          })),
+          new Promise<{ status: "queued" }>((resolve) =>
+            setTimeout(() => resolve({ status: "queued" }), thresholdMs),
+          ),
+        ]);
+ 
+        (ctx as any).lastGraphRebuildAt = new Date().toISOString();
+        (ctx as any).lastGraphRebuildMode = mode;
+ 
+        Eif (raceResult.status === "completed") {
+          return ctx.formatSuccess(
+            {
+              success: raceResult.result.success,
+              status: "COMPLETED",
+              mode,
+              verbose,
+              sourceDir,
+              workspaceRoot,
+              projectId,
+              txId,
+              txTimestamp,
+              durationMs: raceResult.result.duration,
+              filesProcessed: raceResult.result.filesProcessed,
+              nodesCreated: raceResult.result.nodesCreated,
+              relationshipsCreated: raceResult.result.relationshipsCreated,
+              filesChanged: raceResult.result.filesChanged,
+              warnings: raceResult.result.warnings,
+              errors: raceResult.result.errors,
+              runtimePathFallback: adapted.usedFallback,
+              runtimePathFallbackReason: adapted.fallbackReason || null,
+              message: `Graph rebuild ${mode} mode completed in ${raceResult.result.duration}ms.`,
+            },
+            profile,
+            `Graph rebuild completed in ${raceResult.result.duration}ms for project ${projectId}.`,
+            "graph_rebuild",
+          );
+        }
+ 
+        buildPromise.catch(() => {
+          // Background errors are already captured above.
+        });
+ 
+        return ctx.formatSuccess(
+          {
+            success: true,
+            status: "QUEUED",
+            mode,
+            verbose,
+            sourceDir,
+            workspaceRoot,
+            projectId,
+            txId,
+            txTimestamp,
+            syncThresholdMs: thresholdMs,
+            pollIntervalMs: 2000,
+            completionCriteria: {
+              driftDetected: false,
+              embeddingsGeneratedGreaterThan: 0,
+            },
+            runtimePathFallback: adapted.usedFallback,
+            runtimePathFallbackReason: adapted.fallbackReason || null,
+            message: `Graph rebuild ${mode} mode initiated. Processing ${mode === "full" ? "all" : "changed"} files in background...`,
+            note: "Use graph_health to poll until cache.driftDetected=false and embeddings.generated>0.",
+          },
+          profile,
+          `Graph rebuild queued in ${mode} mode for project ${projectId}.`,
+          "graph_rebuild",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "GRAPH_REBUILD_FAILED",
+          `Graph rebuild failed to start: ${String(error)}`,
+          true,
+        );
+      }
+    },
+  },
+  {
+    name: "graph_set_workspace",
+    category: "graph",
+    description: "Set active workspace/project context for subsequent graph tools",
+    inputShape: {
+      workspaceRoot: z.string().optional().describe("Workspace root path (absolute preferred)"),
+      workspacePath: z.string().optional().describe("Alias for workspaceRoot"),
+      sourceDir: z
+        .string()
+        .optional()
+        .describe("Source directory path (absolute or relative to workspace root)"),
+      projectId: z.string().optional().describe("Project namespace for graph isolation"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { profile = "compact" } = args || {};
+ 
+      try {
+        let nextContext = ctx.resolveProjectContext(args || {});
+        const adapted = (ctx as any).adaptWorkspaceForRuntime(nextContext);
+        const explicitWorkspaceProvided =
+          typeof args?.workspaceRoot === "string" && args.workspaceRoot.trim().length > 0;
+ 
+        if (
+          adapted.usedFallback &&
+          explicitWorkspaceProvided &&
+          !(ctx as any).runtimePathFallbackAllowed()
+        ) {
+          return ctx.errorEnvelope(
+            "WORKSPACE_PATH_SANDBOXED",
+            `Requested workspaceRoot is not accessible from this runtime: ${nextContext.workspaceRoot}`,
+            true,
+            "Mount the target project into the container (e.g. LXRAG_TARGET_WORKSPACE) and restart docker-compose, or set LXRAG_ALLOW_RUNTIME_PATH_FALLBACK=true to force fallback to mounted workspace.",
+          );
+        }
+ 
+        nextContext = adapted.context;
+ 
+        Iif (!fs.existsSync(nextContext.workspaceRoot)) {
+          return ctx.errorEnvelope(
+            "WORKSPACE_NOT_FOUND",
+            `Workspace root does not exist: ${nextContext.workspaceRoot}`,
+            true,
+            "Pass an existing absolute path as workspaceRoot (or workspacePath).",
+          );
+        }
+ 
+        Iif (!fs.existsSync(nextContext.sourceDir)) {
+          return ctx.errorEnvelope(
+            "SOURCE_DIR_NOT_FOUND",
+            `Source directory does not exist: ${nextContext.sourceDir}`,
+            true,
+            "Pass sourceDir explicitly if your source folder is not <workspaceRoot>/src.",
+          );
+        }
+ 
+        (ctx as any).setActiveProjectContext(nextContext);
+        await (ctx as any).startActiveWatcher(nextContext);
+ 
+        const watcher = (ctx as any).getActiveWatcher();
+ 
+        return ctx.formatSuccess(
+          {
+            success: true,
+            projectContext: ctx.getActiveProjectContext(),
+            watcherEnabled: (ctx as any).watcherEnabledForRuntime(),
+            watcherState: watcher?.state || "not_started",
+            pendingChanges: watcher?.pendingChanges ?? 0,
+            runtimePathFallback: adapted.usedFallback,
+            runtimePathFallbackReason: adapted.fallbackReason || null,
+            message: "Workspace context updated. Subsequent graph tools will use this project.",
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "SET_WORKSPACE_FAILED",
+          String(error),
+          true,
+          "Retry with workspaceRoot and sourceDir values.",
+        );
+      }
+    },
+  },
+  {
+    name: "graph_health",
+    category: "graph",
+    description: "Report graph/index/vector health and freshness status",
+    inputShape: {
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const profile = args?.profile || "compact";
+ 
+      const hybridRetriever = ctx.engines.hybrid as
+        | {
+            bm25IndexKnownToExist?: boolean;
+            bm25Mode?: string;
+          }
+        | undefined;
+ 
+      try {
+        const { workspaceRoot, sourceDir, projectId } = ctx.getActiveProjectContext();
+ 
+        const healthStatsResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (n {projectId: $projectId})
+           WITH count(n) AS totalNodes
+           MATCH (n1 {projectId: $projectId})-[r]->(n2 {projectId: $projectId})
+           WITH totalNodes, count(r) AS totalRels
+           MATCH (f:FILE {projectId: $projectId})
+           WITH totalNodes, totalRels, count(f) AS fileCount
+           MATCH (fc:FUNCTION {projectId: $projectId})
+           WITH totalNodes, totalRels, fileCount, count(fc) AS funcCount
+           MATCH (c:CLASS {projectId: $projectId})
+           WITH totalNodes, totalRels, fileCount, funcCount, count(c) AS classCount
+           MATCH (imp:IMPORT {projectId: $projectId})
+           RETURN totalNodes, totalRels, fileCount, funcCount, classCount, count(imp) AS importCount`,
+          { projectId },
+        );
+ 
+        const stats = healthStatsResult.data?.[0] || {};
+        const memgraphNodeCount = (ctx as any).toSafeNumber(stats.totalNodes) ?? 0;
+        const memgraphRelCount = (ctx as any).toSafeNumber(stats.totalRels) ?? 0;
+        const memgraphFileCount = (ctx as any).toSafeNumber(stats.fileCount) ?? 0;
+        const memgraphFuncCount = (ctx as any).toSafeNumber(stats.funcCount) ?? 0;
+        const memgraphClassCount = (ctx as any).toSafeNumber(stats.classCount) ?? 0;
+        const memgraphImportCount = (ctx as any).toSafeNumber(stats.importCount) ?? 0;
+        const memgraphIndexableCount =
+          memgraphFileCount + memgraphFuncCount + memgraphClassCount + memgraphImportCount;
+ 
+        const indexStats = ctx.context.index.getStatistics();
+        const indexFileCount = ctx.context.index.getNodesByType("FILE").length;
+        const indexFuncCount = ctx.context.index.getNodesByType("FUNCTION").length;
+        const indexClassCount = ctx.context.index.getNodesByType("CLASS").length;
+        const indexedSymbols = indexFileCount + indexFuncCount + indexClassCount;
+ 
+        let embeddingCount = 0;
+        Iif ((ctx.engines.qdrant as any)?.isConnected?.()) {
+          try {
+            const [fnColl, clsColl, fileColl] = await Promise.all([
+              (ctx.engines.qdrant as any).getCollection("functions"),
+              (ctx.engines.qdrant as any).getCollection("classes"),
+              (ctx.engines.qdrant as any).getCollection("files"),
+            ]);
+            embeddingCount =
+              (fnColl?.pointCount ?? 0) + (clsColl?.pointCount ?? 0) + (fileColl?.pointCount ?? 0);
+          } catch {
+            // Fall back to in-memory count below.
+          }
+        }
+        Eif (embeddingCount === 0) {
+          embeddingCount =
+            ((ctx.engines.embedding as any)
+              ?.getAllEmbeddings()
+              .filter((e: any) => e.projectId === projectId).length as number) || 0;
+        }
+        const embeddingCoverage =
+          memgraphFuncCount + memgraphClassCount + memgraphFileCount > 0
+            ? Number(
+                (
+                  embeddingCount /
+                  (memgraphFuncCount + memgraphClassCount + memgraphFileCount)
+                ).toFixed(3),
+              )
+            : 0;
+ 
+        const indexDrift = Math.abs(indexStats.totalNodes - memgraphIndexableCount) > 3;
+        const embeddingDrift = embeddingCount < indexedSymbols;
+ 
+        const txMetadataResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (tx:GRAPH_TX {projectId: $projectId})
+           WITH tx ORDER BY tx.timestamp DESC
+           WITH collect({id: tx.id, timestamp: tx.timestamp})[0] AS latestTx, count(*) AS txCount
+           RETURN latestTx, txCount`,
+          { projectId },
+        );
+        const txMetadata = txMetadataResult.data?.[0] || {};
+        const latestTxRow = txMetadata.latestTx || {};
+        const txCountRow = {
+          txCount: (ctx as any).toSafeNumber(txMetadata.txCount) ?? 0,
+        };
+        const watcher = (ctx as any).getActiveWatcher();
+ 
+        const recommendations: string[] = [];
+        if (indexDrift) {
+          recommendations.push(
+            "Index is out of sync with Memgraph - run graph_rebuild to synchronize",
+          );
+        }
+        Iif (embeddingDrift && (ctx as any).isProjectEmbeddingsReady(projectId)) {
+          recommendations.push(
+            "Some entities don't have embeddings - run semantic_search or graph_rebuild to generate them",
+          );
+        }
+ 
+        return ctx.formatSuccess(
+          {
+            status: indexDrift ? "drift_detected" : "ok",
+            projectId,
+            workspaceRoot,
+            sourceDir,
+            memgraphConnected: ctx.context.memgraph.isConnected(),
+            qdrantConnected: (ctx.engines.qdrant as any)?.isConnected() || false,
+            graphIndex: {
+              totalNodes: memgraphNodeCount,
+              totalRelationships: memgraphRelCount,
+              indexedFiles: memgraphFileCount,
+              indexedFunctions: memgraphFuncCount,
+              indexedClasses: memgraphClassCount,
+            },
+            indexHealth: {
+              driftDetected: indexDrift,
+              memgraphNodes: memgraphNodeCount,
+              memgraphIndexableNodes: memgraphIndexableCount,
+              cachedNodes: indexStats.totalNodes,
+              memgraphRels: memgraphRelCount,
+              cachedRels: indexStats.totalRelationships,
+              recommendation: indexDrift
+                ? "Index out of sync - run graph_rebuild to refresh"
+                : "Index synchronized",
+            },
+            embeddings: {
+              ready: (ctx as any).isProjectEmbeddingsReady(projectId),
+              generated: embeddingCount,
+              coverage: embeddingCoverage,
+              driftDetected: embeddingDrift,
+              recommendation:
+                embeddingCount === 0 &&
+                memgraphFuncCount + memgraphClassCount + memgraphFileCount > 0
+                  ? "No embeddings generated — run graph_rebuild (full mode) to enable semantic search"
+                  : embeddingDrift
+                    ? "Embeddings incomplete - run semantic_search or rebuild to regenerate"
+                    : "Embeddings complete",
+            },
+            retrieval: {
+              bm25IndexExists: hybridRetriever?.bm25IndexKnownToExist ?? false,
+              mode: hybridRetriever?.bm25Mode ?? "not_initialized",
+            },
+            summarizer: {
+              configured: !!env.LXRAG_SUMMARIZER_URL,
+              endpoint: env.LXRAG_SUMMARIZER_URL ? "[configured]" : null,
+            },
+            rebuild: {
+              lastRequestedAt: (ctx as any).lastGraphRebuildAt || null,
+              lastMode: (ctx as any).lastGraphRebuildMode || null,
+              latestTxId: latestTxRow.id ?? null,
+              latestTxTimestamp:
+                (ctx as any).toSafeNumber(latestTxRow.timestamp) ?? latestTxRow.timestamp ?? null,
+              txCount: txCountRow.txCount ?? 0,
+              recentErrors: (ctx as any).getRecentBuildErrors(projectId, 3),
+            },
+            freshness: {
+              staleFileEstimate: null,
+              note: "Use graph_rebuild incremental to refresh changed files.",
+            },
+            pendingChanges: watcher?.pendingChanges ?? 0,
+            watcherState: watcher?.state || "not_started",
+            recommendations,
+          },
+          profile,
+          indexDrift ? "Graph drift detected - see recommendations" : "Graph health is OK.",
+          "graph_health",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("GRAPH_HEALTH_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "diff_since",
+    category: "utility",
+    description: "Summarize temporal graph changes since txId, timestamp, git commit, or agentId",
+    inputShape: {
+      since: z.string().describe("Anchor value: txId, ISO timestamp, git commit SHA, or agentId"),
+      projectId: z
+        .string()
+        .optional()
+        .describe("Optional project override (defaults to active context)"),
+      types: z
+        .array(z.enum(["FILE", "FUNCTION", "CLASS"]))
+        .optional()
+        .describe("Optional node types to include"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { since, types = ["FILE", "FUNCTION", "CLASS"], profile = "compact" } = args || {};
+ 
+      Iif (!since || typeof since !== "string") {
+        return ctx.errorEnvelope(
+          "DIFF_SINCE_INVALID_INPUT",
+          "Field 'since' is required and must be a string.",
+          true,
+          "Provide txId, ISO timestamp, git commit SHA, or agentId.",
+        );
+      }
+ 
+      try {
+        const active = ctx.getActiveProjectContext();
+        const projectId =
+          typeof args?.projectId === "string" && args.projectId.trim().length > 0
+            ? args.projectId
+            : active.projectId;
+ 
+        const normalizedTypes = Array.isArray(types)
+          ? types
+              .map((item) => String(item).toUpperCase())
+              .filter((item) => ["FILE", "FUNCTION", "CLASS"].includes(item))
+          : ["FILE", "FUNCTION", "CLASS"];
+ 
+        Iif (!normalizedTypes.length) {
+          return ctx.errorEnvelope(
+            "DIFF_SINCE_INVALID_TYPES",
+            "Field 'types' must include at least one of FILE, FUNCTION, CLASS.",
+            true,
+          );
+        }
+ 
+        const anchor = await (ctx as any).resolveSinceAnchor(since, projectId);
+        if (!anchor) {
+          return ctx.errorEnvelope(
+            "DIFF_SINCE_ANCHOR_NOT_FOUND",
+            `Unable to resolve 'since' anchor: ${since}`,
+            true,
+            "Use a known txId, ISO timestamp, git commit SHA, or agentId with recorded GRAPH_TX entries.",
+          );
+        }
+ 
+        const txResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (tx:GRAPH_TX {projectId: $projectId})
+           WHERE tx.timestamp >= $sinceTs
+           RETURN tx.id AS id
+           ORDER BY tx.timestamp ASC`,
+          { projectId, sinceTs: anchor.sinceTs },
+        );
+        const txIds = (txResult.data || []).map((row: any) => String(row.id || "")).filter(Boolean);
+ 
+        const addedResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (n)
+           WHERE n.projectId = $projectId
+             AND labels(n)[0] IN $types
+             AND n.validFrom IS NOT NULL
+             AND n.validFrom >= $sinceTs
+           RETURN labels(n)[0] AS type,
+                  n.id AS scip_id,
+                  coalesce(n.path, n.relativePath, '') AS path,
+                  n.name AS symbolName,
+                  n.validFrom AS validFrom,
+                  n.validTo AS validTo
+           ORDER BY n.validFrom DESC
+           LIMIT 500`,
+          { projectId, sinceTs: anchor.sinceTs, types: normalizedTypes },
+        );
+ 
+        const removedResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (n)
+           WHERE n.projectId = $projectId
+             AND labels(n)[0] IN $types
+             AND n.validTo IS NOT NULL
+             AND n.validTo >= $sinceTs
+           RETURN labels(n)[0] AS type,
+                  n.id AS scip_id,
+                  coalesce(n.path, n.relativePath, '') AS path,
+                  n.name AS symbolName,
+                  n.validFrom AS validFrom,
+                  n.validTo AS validTo
+           ORDER BY n.validTo DESC
+           LIMIT 500`,
+          { projectId, sinceTs: anchor.sinceTs, types: normalizedTypes },
+        );
+ 
+        const modifiedResult = await ctx.context.memgraph.executeCypher(
+          `MATCH (newer)
+           WHERE newer.projectId = $projectId
+             AND labels(newer)[0] IN $types
+             AND newer.validFrom IS NOT NULL
+             AND newer.validFrom >= $sinceTs
+           MATCH (older)
+           WHERE older.projectId = $projectId
+             AND labels(older)[0] IN $types
+             AND older.id = newer.id
+             AND older.validTo IS NOT NULL
+             AND older.validTo >= $sinceTs
+           RETURN DISTINCT labels(newer)[0] AS type,
+                  newer.id AS scip_id,
+                  coalesce(newer.path, newer.relativePath, '') AS path,
+                  newer.name AS symbolName,
+                  newer.validFrom AS validFrom,
+                  newer.validTo AS validTo
+           ORDER BY validFrom DESC
+           LIMIT 500`,
+          { projectId, sinceTs: anchor.sinceTs, types: normalizedTypes },
+        );
+ 
+        const mapDelta = (rows: any[]) =>
+          (rows || []).map((row) => ({
+            scip_id: String(row.scip_id || ""),
+            type: String(row.type || "UNKNOWN"),
+            path: String(row.path || ""),
+            symbolName: row.symbolName ? String(row.symbolName) : undefined,
+            validFrom: (ctx as any).toSafeNumber(row.validFrom),
+            validTo: (ctx as any).toSafeNumber(row.validTo) ?? undefined,
+          }));
+ 
+        const added = mapDelta(addedResult.data || []);
+        const removed = mapDelta(removedResult.data || []);
+        const modified = mapDelta(modifiedResult.data || []);
+ 
+        const summary = `${added.length} added, ${removed.length} removed, ${modified.length} modified since ${anchor.anchorValue}.`;
+ 
+        return ctx.formatSuccess(
+          {
+            summary,
+            projectId,
+            since: {
+              input: since,
+              resolvedMode: anchor.mode,
+              resolvedTimestamp: anchor.sinceTs,
+            },
+            added,
+            removed,
+            modified,
+            txIds,
+          },
+          profile,
+          summary,
+          "diff_since",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("DIFF_SINCE_FAILED", String(error), true);
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/handlers/core-semantic-tools.ts.html b/coverage/src/tools/handlers/core-semantic-tools.ts.html new file mode 100644 index 0000000..cdcf3bb --- /dev/null +++ b/coverage/src/tools/handlers/core-semantic-tools.ts.html @@ -0,0 +1,1180 @@ + + + + + + Code coverage report for src/tools/handlers/core-semantic-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers core-semantic-tools.ts

+
+ +
+ 88.15% + Statements + 67/76 +
+ + +
+ 74.46% + Branches + 35/47 +
+ + +
+ 93.75% + Functions + 15/16 +
+ + +
+ 88% + Lines + 66/75 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +2x +  +2x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +4x +  +  +1x +1x +4x +4x +4x +2x +  +4x +  +  +1x +2x +  +  +  +  +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +2x +2x +  +2x +1x +  +  +  +  +  +  +1x +2x +2x +2x +6x +  +2x +6x +  +  +2x +  +  +  +  +  +  +6x +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +2x +  +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +2x +  +  +  + 
/**
+ * @file tools/handlers/core-semantic-tools
+ * @description Semantic/code-intelligence tool definitions — semantic_search, find_similar_code, code_clusters, semantic_diff, suggest_tests, context_pack, semantic_slice.
+ */
+ 
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const coreSemanticToolDefinitions: ToolDefinition[] = [
+  {
+    name: "semantic_search",
+    category: "code",
+    description: "Search code semantically using vector similarity",
+    inputShape: {
+      query: z.string().describe("Search query"),
+      type: z.enum(["function", "class", "file"]).optional().describe("Code type to search"),
+      limit: z.number().default(5).describe("Result limit"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { query, type = "function", limit = 5, profile = "compact" } = args;
+ 
+      const embeddingEngine = ctx.engines.embedding as
+        | {
+            findSimilar: (
+              query: string,
+              type: string,
+              limit: number,
+              projectId: string,
+            ) => Promise<
+              Array<{
+                id: string;
+                name: string;
+                type: string;
+                metadata: { path?: string };
+              }>
+            >;
+          }
+        | undefined;
+ 
+      try {
+        await ctx.ensureEmbeddings();
+        const { projectId } = ctx.getActiveProjectContext();
+        const results = await embeddingEngine!.findSimilar(query, type, limit, projectId);
+ 
+        return ctx.formatSuccess(
+          {
+            query,
+            type,
+            count: results.length,
+            results: results.map((item) => ({
+              id: item.id,
+              name: item.name,
+              type: item.type,
+              path: item.metadata.path,
+            })),
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("SEMANTIC_SEARCH_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "find_similar_code",
+    category: "code",
+    description: "Find code similar to a given function or class",
+    inputShape: {
+      elementId: z.string().describe("Code element ID"),
+      threshold: z.number().default(0.7).describe("Similarity threshold (0-1)"),
+      limit: z.number().default(10).describe("Result limit"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { elementId, threshold = 0.7, limit = 10, profile = "compact" } = args;
+ 
+      const embeddingEngine = ctx.engines.embedding as
+        | {
+            findSimilar: (
+              query: string,
+              type: string,
+              limit: number,
+              projectId: string,
+            ) => Promise<
+              Array<{
+                id: string;
+                name: string;
+                type: string;
+                metadata: { path?: string };
+              }>
+            >;
+          }
+        | undefined;
+ 
+      try {
+        await ctx.ensureEmbeddings();
+        const { projectId } = ctx.getActiveProjectContext();
+        const results = await embeddingEngine!.findSimilar(elementId, "function", limit, projectId);
+        const filtered = results.slice(0, limit);
+ 
+        return ctx.formatSuccess(
+          {
+            elementId,
+            threshold,
+            count: filtered.length,
+            similar: filtered.map((item) => ({
+              id: item.id,
+              name: item.name,
+              type: item.type,
+              path: item.metadata.path,
+            })),
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("FIND_SIMILAR_CODE_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "code_clusters",
+    category: "code",
+    description: "Find clusters of related code",
+    inputShape: {
+      type: z.enum(["function", "class", "file"]).describe("Code type to cluster"),
+      count: z.number().default(5).describe("Number of clusters"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { type, count = 5, profile = "compact" } = args;
+ 
+      const embeddingEngine = ctx.engines.embedding as
+        | {
+            getAllEmbeddings: () => Array<{
+              type: string;
+              projectId: string;
+              name: string;
+              metadata: { path?: string };
+            }>;
+          }
+        | undefined;
+ 
+      try {
+        await ctx.ensureEmbeddings();
+        const { projectId } = ctx.getActiveProjectContext();
+        const embeddings = embeddingEngine!
+          .getAllEmbeddings()
+          .filter((item) => item.type === type && item.projectId === projectId)
+          .slice(0, 200);
+ 
+        const clusters: Record<string, string[]> = {};
+        for (const item of embeddings) {
+          const itemPath = item.metadata.path || "unknown";
+          const key = itemPath.split("/").slice(0, 2).join("/") || "root";
+          if (!clusters[key]) {
+            clusters[key] = [];
+          }
+          clusters[key].push(item.name);
+        }
+ 
+        const clusterRows = Object.entries(clusters)
+          .map(([clusterId, names]) => ({
+            clusterId,
+            size: names.length,
+            sample: names.slice(0, 5),
+          }))
+          .sort((a, b) => b.size - a.size)
+          .slice(0, count);
+ 
+        return ctx.formatSuccess(
+          { type, count: clusterRows.length, clusters: clusterRows },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("CODE_CLUSTERS_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "semantic_diff",
+    category: "code",
+    description: "Find semantic differences between code elements",
+    inputShape: {
+      elementId1: z.string().describe("First code element ID"),
+      elementId2: z.string().describe("Second code element ID"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { elementId1, elementId2, profile = "compact" } = args;
+ 
+      try {
+        const left = ctx.resolveElement(elementId1);
+        const right = ctx.resolveElement(elementId2);
+ 
+        if (!left || !right) {
+          return ctx.errorEnvelope(
+            "SEMANTIC_DIFF_ELEMENT_NOT_FOUND",
+            `Could not resolve one or both elements: ${elementId1}, ${elementId2}`,
+            true,
+          );
+        }
+ 
+        const leftProps = left.properties || {};
+        const rightProps = right.properties || {};
+        const leftKeys = new Set(Object.keys(leftProps));
+        const rightKeys = new Set(Object.keys(rightProps));
+        const commonKeys = [...leftKeys].filter((key) => rightKeys.has(key));
+ 
+        const changedKeys = commonKeys.filter(
+          (key) => JSON.stringify(leftProps[key]) !== JSON.stringify(rightProps[key]),
+        );
+ 
+        return ctx.formatSuccess(
+          {
+            left: left.properties.name || left.properties.path || left.id,
+            right: right.properties.name || right.properties.path || right.id,
+            leftType: left.type,
+            rightType: right.type,
+            changedKeys,
+            leftOnlyKeys: [...leftKeys].filter((key) => !rightKeys.has(key)),
+            rightOnlyKeys: [...rightKeys].filter((key) => !leftKeys.has(key)),
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("SEMANTIC_DIFF_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "suggest_tests",
+    category: "test",
+    description: "Suggest tests for a code element based on semantics",
+    inputShape: {
+      elementId: z.string().describe("Code element ID"),
+      limit: z.number().default(5).describe("Number of suggestions"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { elementId, limit = 5, profile = "compact" } = args;
+ 
+      const testEngine = ctx.engines.test as
+        | {
+            selectAffectedTests: (
+              changedFiles: string[],
+              includeIntegration?: boolean,
+              depth?: number,
+            ) => {
+              selectedTests: string[];
+              estimatedTime: number;
+              coverage: unknown;
+            };
+          }
+        | undefined;
+ 
+      try {
+        const resolved = ctx.resolveElement(elementId);
+        const candidatePath =
+          resolved?.properties.path ||
+          resolved?.properties.filePath ||
+          resolved?.properties.relativePath ||
+          (typeof elementId === "string" && elementId.includes("/") ? elementId : undefined);
+ 
+        Iif (!candidatePath) {
+          return ctx.errorEnvelope(
+            "SUGGEST_TESTS_ELEMENT_NOT_FOUND",
+            `Unable to resolve file path for element: ${elementId}`,
+            true,
+          );
+        }
+ 
+        const selection = testEngine!.selectAffectedTests([candidatePath], true, 2);
+        const suggested = selection.selectedTests.slice(0, limit);
+ 
+        return ctx.formatSuccess(
+          {
+            elementId,
+            file: candidatePath,
+            suggestedTests: suggested,
+            estimatedTime: selection.estimatedTime,
+            coverage: selection.coverage,
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("SUGGEST_TESTS_FAILED", String(error), true);
+      }
+    },
+  },
+  {
+    name: "context_pack",
+    category: "coordination",
+    description:
+      "Build a single-call task briefing using PPR-ranked retrieval across code, decisions, learnings, and blockers",
+    inputShape: {
+      task: z.string().describe("Task description"),
+      taskId: z.string().optional().describe("Optional task id"),
+      agentId: z.string().optional().describe("Agent identifier"),
+      includeDecisions: z.boolean().default(true).describe("Include decision episodes"),
+      includeEpisodes: z.boolean().default(true).describe("Include recent episodes"),
+      includeLearnings: z.boolean().default(true).describe("Include learnings"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const impl = (ctx as any).core_context_pack_impl;
+      Iif (typeof impl !== "function") {
+        return ctx.errorEnvelope(
+          "TOOL_NOT_IMPLEMENTED",
+          "context_pack implementation is unavailable",
+          true,
+        );
+      }
+      return impl.call(ctx, args);
+    },
+  },
+  {
+    name: "semantic_slice",
+    category: "code",
+    description: "Return relevant exact source lines with optional dependency and memory context",
+    inputShape: {
+      file: z.string().optional().describe("Relative or absolute source file path"),
+      symbol: z.string().optional().describe("Symbol id/name (e.g. ToolHandlers.callTool)"),
+      query: z.string().optional().describe("Natural-language fallback query"),
+      context: z
+        .enum(["signature", "body", "with-deps", "full"])
+        .default("body")
+        .describe("Slice detail mode"),
+      pprScore: z.number().optional().describe("Optional PPR score from context_pack pipeline"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const impl = (ctx as any).core_semantic_slice_impl;
+      Iif (typeof impl !== "function") {
+        return ctx.errorEnvelope(
+          "TOOL_NOT_IMPLEMENTED",
+          "semantic_slice implementation is unavailable",
+          true,
+        );
+      }
+      return impl.call(ctx, args);
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/handlers/core-setup-tools.ts.html b/coverage/src/tools/handlers/core-setup-tools.ts.html new file mode 100644 index 0000000..8461b50 --- /dev/null +++ b/coverage/src/tools/handlers/core-setup-tools.ts.html @@ -0,0 +1,1708 @@ + + + + + + Code coverage report for src/tools/handlers/core-setup-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers core-setup-tools.ts

+
+ +
+ 80% + Statements + 108/135 +
+ + +
+ 75.6% + Branches + 93/123 +
+ + +
+ 57.14% + Functions + 4/7 +
+ + +
+ 83.47% + Lines + 101/121 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +1x +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +2x +  +2x +2x +2x +2x +  +  +2x +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +2x +2x +  +2x +2x +2x +2x +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +2x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +  +6x +6x +  +  +  +  +  +6x +1x +  +  +  +  +  +  +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +5x +5x +6x +6x +  +  +  +6x +6x +6x +  +  +  +  +6x +  +6x +6x +  +6x +  +  +6x +6x +  +6x +  +6x +6x +  +6x +  +  +6x +1x +5x +5x +5x +5x +5x +  +5x +  +5x +  +  +1x +  +  +  +6x +  +9x +  +6x +6x +6x +4x +4x +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +6x +6x +  +  +  +5x +5x +  +  +  +  +5x +1x +1x +1x +1x +  +  +  +  +  +5x +1x +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +5x +  +5x +1x +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +  +4x +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file tools/handlers/core-setup-tools
+ * @description Project setup/onboarding tool definitions — init_project_setup, setup_copilot_instructions.
+ */
+ 
+import * as fs from "fs";
+import * as path from "path";
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const coreSetupToolDefinitions: ToolDefinition[] = [
+  {
+    name: "init_project_setup",
+    category: "setup",
+    description:
+      "One-shot project initialization: sets workspace context, triggers graph rebuild, and generates .github/copilot-instructions.md if not present. Use this as the first step when onboarding a new project or starting a fresh session.",
+    inputShape: {
+      workspaceRoot: z.string().describe("Absolute path to the project root to initialize"),
+      sourceDir: z
+        .string()
+        .optional()
+        .describe("Source directory relative to workspaceRoot (default: src)"),
+      projectId: z
+        .string()
+        .optional()
+        .describe("Project identifier (default: basename of workspaceRoot)"),
+      rebuildMode: z
+        .enum(["incremental", "full"])
+        .default("incremental")
+        .describe("incremental = changed files only; full = rebuild entire graph"),
+      withDocs: z.boolean().default(true).describe("Also index markdown docs during rebuild"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        workspaceRoot,
+        sourceDir,
+        projectId,
+        rebuildMode = "incremental",
+        withDocs = true,
+        profile = "compact",
+      } = args ?? {};
+ 
+      if (!workspaceRoot || typeof workspaceRoot !== "string") {
+        return ctx.errorEnvelope(
+          "INIT_MISSING_WORKSPACE",
+          "workspaceRoot is required",
+          false,
+          "Provide the absolute path to the project you want to initialize.",
+        );
+      }
+ 
+      const resolvedRoot = path.resolve(workspaceRoot);
+      Iif (!fs.existsSync(resolvedRoot)) {
+        return ctx.errorEnvelope(
+          "INIT_WORKSPACE_NOT_FOUND",
+          `Workspace path does not exist: ${resolvedRoot}`,
+          false,
+          "Ensure the project is accessible from this machine/container.",
+        );
+      }
+ 
+      const steps: Array<{ step: string; status: string; detail?: string }> = [];
+ 
+      try {
+        const setArgs: any = { workspaceRoot: resolvedRoot, profile };
+        if (sourceDir) setArgs.sourceDir = sourceDir;
+        if (projectId) setArgs.projectId = projectId;
+ 
+        let setResult: string;
+        try {
+          setResult = await ctx.callTool("graph_set_workspace", setArgs);
+          const setJson = JSON.parse(setResult);
+          Iif (setJson?.error) {
+            steps.push({
+              step: "graph_set_workspace",
+              status: "failed",
+              detail: setJson.error,
+            });
+            return ctx.formatSuccess(
+              { steps, abortedAt: "graph_set_workspace" },
+              profile,
+              "Initialization aborted at workspace setup",
+              "init_project_setup",
+            );
+          }
+          const setCtx = setJson?.data?.projectContext ?? setJson?.data ?? {};
+          steps.push({
+            step: "graph_set_workspace",
+            status: "ok",
+            detail: `projectId=${setCtx.projectId ?? "?"}, sourceDir=${setCtx.sourceDir ?? "?"}`,
+          });
+        } catch (err) {
+          steps.push({
+            step: "graph_set_workspace",
+            status: "failed",
+            detail: String(err),
+          });
+          return ctx.formatSuccess(
+            { steps, abortedAt: "graph_set_workspace" },
+            profile,
+            "Initialization aborted at workspace setup",
+            "init_project_setup",
+          );
+        }
+ 
+        const rebuildArgs: any = {
+          workspaceRoot: resolvedRoot,
+          mode: rebuildMode,
+          indexDocs: withDocs,
+          profile,
+        };
+        if (sourceDir) rebuildArgs.sourceDir = sourceDir;
+        if (projectId) rebuildArgs.projectId = projectId;
+ 
+        try {
+          const rebuildResult = await ctx.callTool("graph_rebuild", rebuildArgs);
+          const rebuildJson = JSON.parse(rebuildResult);
+          if (rebuildJson?.error) {
+            steps.push({
+              step: "graph_rebuild",
+              status: "failed",
+              detail: rebuildJson.error,
+            });
+          } else {
+            steps.push({
+              step: "graph_rebuild",
+              status: "queued",
+              detail: `mode=${rebuildMode}, indexDocs=${withDocs}`,
+            });
+          }
+        } catch (err) {
+          steps.push({
+            step: "graph_rebuild",
+            status: "failed",
+            detail: String(err),
+          });
+        }
+ 
+        const copilotPath = path.join(resolvedRoot, ".github", "copilot-instructions.md");
+        if (!fs.existsSync(copilotPath)) {
+          try {
+            await ctx.callTool("setup_copilot_instructions", {
+              targetPath: resolvedRoot,
+              dryRun: false,
+              overwrite: false,
+              profile: "compact",
+            });
+            steps.push({
+              step: "setup_copilot_instructions",
+              status: "created",
+              detail: ".github/copilot-instructions.md",
+            });
+          } catch (err) {
+            steps.push({
+              step: "setup_copilot_instructions",
+              status: "skipped",
+              detail: String(err),
+            });
+          }
+        } else E{
+          steps.push({
+            step: "setup_copilot_instructions",
+            status: "exists",
+            detail: "File already present — skipped",
+          });
+        }
+ 
+        const projCtx = ctx.resolveProjectContext({
+          workspaceRoot: resolvedRoot,
+          ...(sourceDir ? { sourceDir } : {}),
+          ...(projectId ? { projectId } : {}),
+        });
+ 
+        return ctx.formatSuccess(
+          {
+            projectId: projCtx.projectId,
+            workspaceRoot: projCtx.workspaceRoot,
+            sourceDir: projCtx.sourceDir,
+            steps,
+            nextAction:
+              "Call graph_health to confirm the rebuild completed, then graph_query to start exploring.",
+          },
+          profile,
+          `Project ${projCtx.projectId} initialized — graph rebuild queued`,
+          "init_project_setup",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "INIT_PROJECT_FAILED",
+          error instanceof Error ? error.message : String(error),
+          true,
+        );
+      }
+    },
+  },
+  {
+    name: "setup_copilot_instructions",
+    category: "setup",
+    description:
+      "Analyze a repository and generate a tailored .github/copilot-instructions.md file with tech-stack detection, key commands, required session flow, and tool-usage guidance. Makes it immediately efficient to work with the repo via Copilot or any AI assistant.",
+    inputShape: {
+      targetPath: z
+        .string()
+        .optional()
+        .describe("Absolute path to the target repository (defaults to the active workspace)"),
+      projectName: z.string().optional().describe("Override the detected project name"),
+      dryRun: z
+        .boolean()
+        .default(false)
+        .describe("Return the generated content without writing the file"),
+      overwrite: z.boolean().default(false).describe("Replace an existing copilot-instructions.md"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const {
+        targetPath,
+        projectName: forceProjectName,
+        dryRun = false,
+        overwrite = false,
+        profile = "compact",
+      } = args ?? {};
+ 
+      let resolvedTarget: string;
+      if (targetPath && typeof targetPath === "string") {
+        resolvedTarget = path.resolve(targetPath);
+      } else E{
+        const active = ctx.resolveProjectContext({});
+        resolvedTarget = active.workspaceRoot;
+      }
+ 
+      if (!fs.existsSync(resolvedTarget)) {
+        return ctx.errorEnvelope(
+          "COPILOT_INSTR_TARGET_NOT_FOUND",
+          `Target path does not exist: ${resolvedTarget}`,
+          false,
+          "Provide an accessible absolute path via targetPath parameter.",
+        );
+      }
+ 
+      const destFile = path.join(resolvedTarget, ".github", "copilot-instructions.md");
+      Iif (fs.existsSync(destFile) && !overwrite && !dryRun) {
+        return ctx.formatSuccess(
+          {
+            status: "already_exists",
+            path: destFile,
+            hint: "Pass overwrite=true to replace it.",
+          },
+          profile,
+          ".github/copilot-instructions.md already exists — skipped",
+          "setup_copilot_instructions",
+        );
+      }
+ 
+      try {
+        const repoName = forceProjectName || path.basename(resolvedTarget);
+        const pkgPath = path.join(resolvedTarget, "package.json");
+        const pkgJson: any = fs.existsSync(pkgPath)
+          ? JSON.parse(fs.readFileSync(pkgPath, "utf-8"))
+          : null;
+ 
+        const name = forceProjectName || pkgJson?.name || repoName;
+        const description = pkgJson?.description || "";
+        const deps: Record<string, string> = {
+          ...(pkgJson?.dependencies ?? {}),
+          ...(pkgJson?.devDependencies ?? {}),
+        };
+ 
+        const stack: string[] = [];
+        const isTypeScript =
+          fs.existsSync(path.join(resolvedTarget, "tsconfig.json")) || !!deps["typescript"];
+        const isNode = !!pkgJson || fs.existsSync(path.join(resolvedTarget, "package.json"));
+        const isPython =
+          fs.existsSync(path.join(resolvedTarget, "pyproject.toml")) ||
+          fs.existsSync(path.join(resolvedTarget, "setup.py")) ||
+          fs.existsSync(path.join(resolvedTarget, "requirements.txt"));
+        const isGo = fs.existsSync(path.join(resolvedTarget, "go.mod"));
+        const isRust = fs.existsSync(path.join(resolvedTarget, "Cargo.toml"));
+        const isJava =
+          fs.existsSync(path.join(resolvedTarget, "pom.xml")) ||
+          fs.existsSync(path.join(resolvedTarget, "build.gradle"));
+        const isReact = !!deps["react"];
+        const isNextJs = !!deps["next"];
+        const isDocker =
+          fs.existsSync(path.join(resolvedTarget, "Dockerfile")) ||
+          fs.existsSync(path.join(resolvedTarget, "docker-compose.yml"));
+ 
+        Iif (isTypeScript) stack.push("TypeScript");
+        else if (isNode) stack.push("JavaScript / Node.js");
+        Iif (isPython) stack.push("Python");
+        Iif (isGo) stack.push("Go");
+        Iif (isRust) stack.push("Rust");
+        Iif (isJava) stack.push("Java");
+        Iif (isNextJs) stack.push("Next.js"I);
+        else if (isReact) stack.push("React");
+        Iif (isDocker) stack.push("Docker");
+ 
+        const scripts = pkgJson?.scripts
+          ? Object.entries(pkgJson.scripts)
+              .slice(0, 10)
+              .map(([k, v]) => `- \`${k}\`: \`${v}\``)
+              .join("\n")
+          : "";
+ 
+        const candidateSrcDirs = ["src", "lib", "app", "packages", "source"];
+        const srcDir =
+          candidateSrcDirs.find((d) => fs.existsSync(path.join(resolvedTarget, d))) ?? "src";
+ 
+        const srcPath = path.join(resolvedTarget, srcDir);
+        let subDirs: string[] = [];
+        if (fs.existsSync(srcPath)) {
+          try {
+            subDirs = fs
+              .readdirSync(srcPath, { withFileTypes: true })
+              .filter((e) => e.isDirectory())
+              .map((e) => e.name)
+              .slice(0, 10);
+          } catch {
+            // ignore
+          }
+        }
+ 
+        const isMcpServer =
+          !!deps["@modelcontextprotocol/sdk"] ||
+          fs.existsSync(path.join(resolvedTarget, "src", "mcp-server.ts")) ||
+          fs.existsSync(path.join(resolvedTarget, "src", "server.ts"));
+ 
+        const lines: string[] = [`# Copilot Instructions for ${name}`, ""];
+        Iif (description) {
+          lines.push(description, "");
+        }
+ 
+        lines.push("## Primary Goal", "");
+        lines.push(
+          "Understand the codebase before making changes. Use graph-backed tools first for code intelligence, then fall back to file reads only when needed.",
+          "",
+        );
+ 
+        if (stack.length > 0) {
+          lines.push("## Runtime Truths", "");
+          lines.push(`- **Stack**: ${stack.join(", ")}`);
+          lines.push(`- **Source root**: \`${srcDir}/\``);
+          Iif (subDirs.length > 0) {
+            lines.push(
+              `- **Key directories**: ${subDirs.map((d) => `\`${srcDir}/${d}\``).join(", ")}`,
+            );
+          }
+        }
+        if (scripts) {
+          lines.push("", "## Available Commands", "", scripts);
+        }
+ 
+        Iif (isMcpServer) {
+          lines.push(
+            "",
+            "## Required Session Flow",
+            "",
+            "**One-shot (recommended):**",
+            "```",
+            'init_project_setup({ projectId: "my-proj", workspaceRoot: "/abs/path" })',
+            "```",
+            "",
+            "**Manual:**",
+            "1. `graph_set_workspace({ projectId, workspaceRoot })` — anchor the session",
+            '2. `graph_rebuild({ projectId, mode: "full", workspaceRoot })` — capture `txId` from response',
+            '3. `graph_health({ profile: "balanced" })` — verify nodes > 0',
+            '4. `graph_query({ query: "MATCH (n) RETURN labels(n)[0], count(n) LIMIT 8", projectId })` — confirm data',
+            "",
+            "**HTTP transport only:** capture `mcp-session-id` from `initialize` response and include on every request.",
+          );
+        } else {
+          lines.push(
+            "",
+            "## Required Session Flow",
+            "",
+            "1. Call `init_project_setup({ projectId, workspaceRoot })` — sets context, triggers graph rebuild, writes copilot instructions.",
+            '2. Validate with `graph_health({ profile: "balanced" })`',
+            '3. Explore with `graph_query({ query: "MATCH (n) RETURN labels(n)[0], count(n) DESC LIMIT 10" })`',
+          );
+        }
+ 
+        lines.push(
+          "",
+          "## Tool Decision Guide",
+          "",
+          "| Goal | First choice | Fallback |",
+          "|---|---|---|",
+          "| Count/list nodes | `graph_query` (Cypher) | `graph_health` |",
+          "| Understand a symbol | `code_explain` (symbol name) | `semantic_slice` |",
+          "| Find related code | `find_similar_code` | `semantic_search` |",
+          "| Check arch violations | `arch_validate` | `blocking_issues` |",
+          "| Place new code | `arch_suggest` | — |",
+          "| Docs lookup | `search_docs` → `index_docs` if empty | file read |",
+          "| Tests after change | `test_select` → `test_run` | `suggest_tests` |",
+          "| Track decisions | `episode_add` (DECISION) | — |",
+          "| Release agent lock | `agent_release` with `claimId` | — |",
+        );
+ 
+        lines.push(
+          "",
+          "## Correct Tool Signatures (verified)",
+          "",
+          "```jsonc",
+          `// graph — capture txId from graph_rebuild response for diff_since`,
+          `graph_rebuild({ "projectId": "proj", "mode": "full" })  // → { txId }`,
+          `diff_since({ "since": "<txId | ISO-8601>" })            // NOT git refs like HEAD~3`,
+          "",
+          `// semantic`,
+          `code_explain({ "element": "SymbolName", "depth": 2 })   // symbol name, NOT qualified ID`,
+          `semantic_diff({ "elementId1": "...", "elementId2": "..." })  // NOT elementA/elementB`,
+          `semantic_slice({ "symbol": "MyClass" })                 // NOT entryPoint`,
+          "",
+          `// clustering`,
+          `code_clusters({ "type": "file" })  // type: "function"|"class"|"file"  NOT granularity`,
+          `arch_suggest({ "name": "NewEngine", "codeType": "engine" })  // NOT codeName`,
+          "",
+          `// memory — DECISION requires metadata.rationale, type is uppercase`,
+          `episode_add({ "type": "DECISION", "content": "...", "outcome": "success",`,
+          `             "metadata": { "rationale": "because..." } })`,
+          `episode_add({ "type": "LEARNING", "content": "..." })`,
+          `decision_query({ "query": "..." })   // NOT topic`,
+          `progress_query({ "query": "..." })   // query is required, NOT status`,
+          "",
+          `// coordination — capture claimId from agent_claim for release`,
+          `agent_claim({ "agentId": "a1", "targetId": "src/file.ts", "intent": "..." })  // NOT target`,
+          `agent_release({ "claimId": "claim-xxx" })   // NOT agentId/taskId`,
+          `context_pack({ "task": "Description..." }) // task string is REQUIRED`,
+          "",
+          `// tests — suggest_tests needs fully-qualified element ID`,
+          `suggest_tests({ "elementId": "proj:file.ts:symbolName:line" })`,
+          "```",
+        );
+ 
+        lines.push(
+          "",
+          "## Common Pitfalls",
+          "",
+          "| Wrong | Correct |",
+          "|---|---|",
+          '| `code_explain({ elementId: ... })` | `code_explain({ element: "SymbolName" })` |',
+          "| `semantic_diff({ elementA, elementB })` | `semantic_diff({ elementId1, elementId2 })` |",
+          '| `code_clusters({ granularity: "module" })` | `code_clusters({ type: "file" })` |',
+          '| `arch_suggest({ codeName: "X" })` | `arch_suggest({ name: "X" })` |',
+          '| `episode_add({ type: "decision" })` | `episode_add({ type: "DECISION" })` (uppercase) |',
+          '| DECISION without `metadata.rationale` | always include `metadata: { rationale: "..." }` |',
+          '| `decision_query({ topic: "X" })` | `decision_query({ query: "X" })` |',
+          '| `agent_claim({ target: "f.ts" })` | `agent_claim({ targetId: "f.ts" })` |',
+          '| `agent_release({ agentId, taskId })` | `agent_release({ claimId: "claim-xxx" })` |',
+        );
+ 
+        lines.push(
+          "",
+          "## Copilot Skills — Usage Patterns",
+          "",
+          "### Explore unfamiliar codebase",
+          "```",
+          "1. init_project_setup({ projectId, workspaceRoot })",
+          '2. graph_query("MATCH (n) RETURN labels(n)[0], count(n) ORDER BY count(n) DESC LIMIT 10")',
+          '3. code_explain({ element: "MainEntryPoint" })',
+          "```",
+          "",
+          "### Safe refactor + test impact",
+          "```",
+          '1. impact_analyze({ changedFiles: ["src/x.ts"] })',
+          '2. test_select({ changedFiles: ["src/x.ts"] })',
+          '3. arch_validate({ files: ["src/x.ts"] })',
+          "4. test_run({ testFiles: [...from test_select...] })",
+          '5. episode_add({ type: "DECISION", content: "...", metadata: { rationale: "..." } })',
+          "```",
+          "",
+          "### Multi-agent safe edit",
+          "```",
+          '1. agent_claim({ agentId, targetId: "src/file.ts", intent: "..." })  → save claimId',
+          "2. ... make changes ...",
+          '3. agent_release({ claimId, outcome: "done" })',
+          "```",
+          "",
+          "### Docs cold start",
+          "```",
+          '1. search_docs({ query: "topic" })           — if count=0:',
+          '2. index_docs({ paths: ["/abs/README.md"] })',
+          '3. search_docs({ query: "topic" })           — now returns results',
+          "```",
+        );
+ 
+        lines.push(
+          "",
+          "## Source of Truth",
+          "",
+          "`README.md`, `QUICK_START.md`, `ARCHITECTURE.md`.",
+        );
+ 
+        const content = lines.join("\n") + "\n";
+ 
+        if (dryRun) {
+          return ctx.formatSuccess(
+            {
+              dryRun: true,
+              targetPath: destFile,
+              content,
+            },
+            profile,
+            "Dry run — copilot-instructions.md content generated (not written)",
+            "setup_copilot_instructions",
+          );
+        }
+ 
+        const githubDir = path.join(resolvedTarget, ".github");
+        Eif (!fs.existsSync(githubDir)) {
+          fs.mkdirSync(githubDir, { recursive: true });
+        }
+        fs.writeFileSync(destFile, content, "utf-8");
+ 
+        return ctx.formatSuccess(
+          {
+            status: "created",
+            path: destFile,
+            projectName: name,
+            stackDetected: stack,
+            overwritten: overwrite && fs.existsSync(destFile),
+          },
+          profile,
+          `Copilot instructions written to ${path.relative(resolvedTarget, destFile)}`,
+          "setup_copilot_instructions",
+        );
+      } catch (error) {
+        return ctx.errorEnvelope(
+          "SETUP_COPILOT_FAILED",
+          error instanceof Error ? error.message : String(error),
+          true,
+        );
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/handlers/core-utility-tools.ts.html b/coverage/src/tools/handlers/core-utility-tools.ts.html new file mode 100644 index 0000000..fee7aee --- /dev/null +++ b/coverage/src/tools/handlers/core-utility-tools.ts.html @@ -0,0 +1,505 @@ + + + + + + Code coverage report for src/tools/handlers/core-utility-tools.ts + + + + + + + + + +
+
+

All files / src/tools/handlers core-utility-tools.ts

+
+ +
+ 88.46% + Statements + 23/26 +
+ + +
+ 66.66% + Branches + 8/12 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 88.46% + Lines + 23/26 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +2x +16x +16x +16x +72x +72x +72x +  +  +  +  +16x +  +  +2x +16x +  +  +2x +16x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +3x +  +3x +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @file tools/handlers/core-utility-tools
+ * @description Utility tool definitions — tools_list, contract_validate.
+ */
+ 
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
+ 
+export const coreUtilityToolDefinitions: ToolDefinition[] = [
+  {
+    name: "tools_list",
+    category: "utility",
+    description:
+      "List all MCP tools and their availability in the current session, grouped by category",
+    inputShape: {
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const profile = args?.profile ?? "compact";
+ 
+      const KNOWN_CATEGORIES: Record<string, string[]> = {
+        graph: [
+          "graph_set_workspace",
+          "graph_rebuild",
+          "graph_query",
+          "graph_health",
+          "tools_list",
+          "ref_query",
+        ],
+        architecture: ["arch_validate", "arch_suggest"],
+        semantic: [
+          "semantic_search",
+          "find_similar_code",
+          "code_explain",
+          "semantic_slice",
+          "semantic_diff",
+          "code_clusters",
+          "find_pattern",
+          "blocking_issues",
+        ],
+        docs: ["index_docs", "search_docs"],
+        test: ["test_select", "test_categorize", "test_run", "suggest_tests", "impact_analyze"],
+        memory: ["episode_add", "episode_recall", "decision_query", "reflect", "context_pack"],
+        progress: ["progress_query", "task_update", "feature_status"],
+        coordination: [
+          "agent_claim",
+          "agent_release",
+          "coordination_overview",
+          "contract_validate",
+          "diff_since",
+        ],
+      };
+ 
+      const result: Record<string, { available: string[]; unavailable: string[] }> = {};
+ 
+      for (const [category, tools] of Object.entries(KNOWN_CATEGORIES)) {
+        const available: string[] = [];
+        const unavailable: string[] = [];
+        for (const toolName of tools) {
+          const bound = (ctx as any)[toolName];
+          if (typeof bound === "function") {
+            available.push(toolName);
+          } else E{
+            unavailable.push(toolName);
+          }
+        }
+        result[category] = { available, unavailable };
+      }
+ 
+      const totalAvailable = Object.values(result).reduce(
+        (sum, cat) => sum + cat.available.length,
+        0,
+      );
+      const totalUnavailable = Object.values(result).reduce(
+        (sum, cat) => sum + cat.unavailable.length,
+        0,
+      );
+ 
+      return ctx.formatSuccess(
+        {
+          summary: `${totalAvailable} tools available, ${totalUnavailable} unavailable in this session`,
+          categories: result,
+          note: "Unavailable tools may require missing configuration, a running engine, or a different server entrypoint.",
+        },
+        profile,
+      );
+    },
+  },
+  {
+    name: "contract_validate",
+    category: "utility",
+    description: "Normalize and validate tool argument contracts before execution",
+    inputShape: {
+      tool: z.string().describe("Target tool name"),
+      arguments: z.record(z.string(), z.any()).optional().describe("Raw arguments to normalize"),
+      profile: z
+        .enum(["compact", "balanced", "debug"])
+        .default("compact")
+        .describe("Response profile"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { tool, arguments: inputArgs = {}, profile = "compact" } = args || {};
+ 
+      Iif (!tool || typeof tool !== "string") {
+        return ctx.errorEnvelope(
+          "CONTRACT_VALIDATE_INVALID_INPUT",
+          "Field 'tool' is required and must be a string",
+          true,
+        );
+      }
+ 
+      try {
+        // Step 1: normalise field aliases (e.g. changedFiles → files)
+        const { normalized, warnings: normWarnings } = ctx.normalizeForDispatch(tool, inputArgs);
+ 
+        // Step 2: validate normalised args against the tool's Zod schema
+        const validation = ctx.validateToolArgs(tool, normalized);
+ 
+        return ctx.formatSuccess(
+          {
+            tool,
+            input: inputArgs,
+            normalized,
+            valid: validation.valid,
+            errors: validation.errors,
+            missingRequired: validation.missingRequired,
+            extraFields: validation.extraFields,
+            warnings: [...normWarnings, ...validation.warnings],
+          },
+          profile,
+        );
+      } catch (error) {
+        return ctx.errorEnvelope("CONTRACT_VALIDATE_FAILED", String(error), true);
+      }
+    },
+  },
+];
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/handlers/docs-tools.ts.html b/coverage/src/tools/handlers/docs-tools.ts.html index 23a197d..34c6f3b 100644 --- a/coverage/src/tools/handlers/docs-tools.ts.html +++ b/coverage/src/tools/handlers/docs-tools.ts.html @@ -23,9 +23,9 @@

All files / src/tools
- 90.9% + 91.66% Statements - 20/22 + 22/24
@@ -39,14 +39,14 @@

All files / src/tools
100% Functions - 4/4 + 3/3
- 90.9% + 91.66% Lines - 20/22 + 22/24
@@ -221,7 +221,35 @@

All files / src/tools 156 157 158 -159  +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187        @@ -233,6 +261,7 @@

All files / src/tools       +4x       @@ -257,30 +286,45 @@

All files / src/tools       -57x     +6x +6x +6x         +6x       -5x -5x +  +  +  +  +  +  +  +  +  +  +  +6x +1x +  +  5x       +  5x -1x           -4x       @@ -288,8 +332,8 @@

All files / src/tools       -4x   +        @@ -302,7 +346,6 @@

All files / src/tools       -        @@ -319,27 +362,24 @@

All files / src/tools       -6x -6x -6x     -6x -1x       +7x +7x +7x       -5x -1x +7x +  +          -4x -3x       @@ -347,17 +387,33 @@

All files / src/tools       +  +7x 1x       +6x +1x     +5x 4x       -3x +1x +  +  +  +  +  +  +5x +  +  +  +4x       @@ -381,45 +437,38 @@

All files / src/tools    
/**
  * Documentation Tools
- * Phase 5 Step 4: Extract documentation indexing and search tools
+ * Registry-backed documentation tool definitions.
  *
  * Tools:
  * - index_docs: index documentation files in workspace
  * - search_docs: search indexed documentation
- *
- * These tools delegate entirely to the DocsEngine.
  */
  
-/**
- * Minimal context interface required by docs tools
- */
-interface DocsToolContext {
-  docsEngine?: any; // DocsEngine
-  resolveProjectContext(overrides?: any): { workspaceRoot: string; projectId: string };
-  errorEnvelope(
-    code: string,
-    reason: string,
-    recoverable?: boolean,
-    hint?: string
-  ): string;
-  formatSuccess(
-    data: unknown,
-    profile?: string,
-    summary?: string,
-    toolName?: string
-  ): string;
-}
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
  
-/**
- * Create documentation tools
- * @param ctx - Context object providing docsEngine and helper methods
- */
-export function createDocsTools(ctx: DocsToolContext) {
-  return {
-    /**
-     * Index documentation files in a workspace
-     */
-    async index_docs(args: any): Promise<string> {
+export const docsToolDefinitions: ToolDefinition[] = [
+  {
+    name: "index_docs",
+    category: "docs",
+    description:
+      "Discover and index all markdown documentation files (README, ADRs, guides, CHANGELOG, ARCHITECTURE) under the workspace root into DOCUMENT and SECTION graph nodes. Supports incremental mode (skips unchanged files). Emits DOC_DESCRIBES edges linking sections to the code symbols they mention.",
+    inputShape: {
+      workspaceRoot: z
+        .string()
+        .optional()
+        .describe("Workspace root path (defaults to active session context)"),
+      projectId: z.string().optional().describe("Project ID (defaults to active session context)"),
+      incremental: z
+        .boolean()
+        .default(true)
+        .describe("Skip files whose hash has not changed (default: true)"),
+      withEmbeddings: z
+        .boolean()
+        .default(false)
+        .describe("Also embed section content into Qdrant vector store"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
       const {
         workspaceRoot: argsRoot,
         projectId: argsProject,
@@ -431,21 +480,31 @@ 

All files / src/tools workspaceRoot: argsRoot, projectId: argsProject, }); - if (!ctx.docsEngine) { - return ctx.errorEnvelope( - "ENGINE_UNAVAILABLE", - "DocsEngine not initialised", - false - ); +  + const docsEngine = ctx.engines.docs as + | { + indexWorkspace: ( + workspaceRoot: string, + projectId: string, + options: { incremental: boolean; withEmbeddings: boolean }, + ) => Promise<{ + indexed: number; + skipped: number; + errors: unknown[]; + durationMs: number; + }>; + } + | undefined; +  + if (!docsEngine) { + return ctx.errorEnvelope("ENGINE_UNAVAILABLE", "DocsEngine not initialised", false); } - const result = await ctx.docsEngine.indexWorkspace( - workspaceRoot, - projectId, - { - incremental, - withEmbeddings, - } - ); +  + const result = await docsEngine.indexWorkspace(workspaceRoot, projectId, { + incremental, + withEmbeddings, + }); +  return ctx.formatSuccess( { ok: true, @@ -457,60 +516,85 @@

All files / src/tools projectId, workspaceRoot, }, - "compact" + "compact", ); } catch (err) { return ctx.errorEnvelope( "INDEX_DOCS_ERROR", err instanceof Error ? err.message : String(err), - true + true, ); } }, -  - /** - * Search indexed documentation - */ - async search_docs(args: any): Promise<string> { - const { - query, - symbol, - limit = 10, - projectId: argsProject, - } = args ?? {}; + }, + { + name: "search_docs", + category: "docs", + description: + "Search indexed documentation sections by full-text query or by code symbol name. Returns matching SECTION nodes with heading, source document, kind (readme/adr/guide/…), line number, relevance score, and a short content excerpt. Run index_docs first to populate the index.", + inputShape: { + query: z + .string() + .optional() + .describe("Full-text search query (cannot be combined with symbol)"), + symbol: z + .string() + .optional() + .describe( + "Symbol name to look up (finds Sections that document this function/class/file via DOC_DESCRIBES edges)", + ), + limit: z + .number() + .int() + .min(1) + .max(50) + .default(10) + .describe("Maximum number of results to return"), + projectId: z.string().optional().describe("Project ID (defaults to active session context)"), + }, + async impl(args: any, ctx: HandlerBridge): Promise<string> { + const { query, symbol, limit = 10, projectId: argsProject } = args ?? {}; try { const { projectId } = ctx.resolveProjectContext({ projectId: argsProject, }); - if (!ctx.docsEngine) { - return ctx.errorEnvelope( - "ENGINE_UNAVAILABLE", - "DocsEngine not initialised", - false - ); +  + const docsEngine = ctx.engines.docs as + | { + getDocsBySymbol: ( + symbol: string, + projectId: string, + options: { limit: number }, + ) => Promise<any[]>; + searchDocs: ( + query: string, + projectId: string, + options: { limit: number }, + ) => Promise<any[]>; + } + | undefined; +  + if (!docsEngine) { + return ctx.errorEnvelope("ENGINE_UNAVAILABLE", "DocsEngine not initialised", false); } +  let results; if (typeof symbol === "string" && symbol.trim().length > 0) { - results = await ctx.docsEngine.getDocsBySymbol( - symbol.trim(), - projectId, - { limit } - ); + results = await docsEngine.getDocsBySymbol(symbol.trim(), projectId, { + limit, + }); } else if (typeof query === "string" && query.trim().length > 0) { - results = await ctx.docsEngine.searchDocs( - query.trim(), - projectId, - { - limit, - } - ); + results = await docsEngine.searchDocs(query.trim(), projectId, { + limit, + }); } else { return ctx.errorEnvelope( "MISSING_PARAM", "Provide either `query` (full-text search) or `symbol` (symbol lookup)", - true + true, ); } +  return ctx.formatSuccess( { ok: true, @@ -525,18 +609,18 @@

All files / src/tools })), projectId, }, - "compact" + "compact", ); } catch (err) { return ctx.errorEnvelope( "SEARCH_DOCS_ERROR", err instanceof Error ? err.message : String(err), - true + true, ); } }, - }; -} + }, +];  

@@ -544,7 +628,7 @@

All files / src/tools + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/handlers/ref-tools.ts.html b/coverage/src/tools/handlers/ref-tools.ts.html index 3aed254..7ee2569 100644 --- a/coverage/src/tools/handlers/ref-tools.ts.html +++ b/coverage/src/tools/handlers/ref-tools.ts.html @@ -23,30 +23,30 @@

All files / src/tools

-
+
1 2 @@ -445,46 +445,7 @@

All files / src/tools 380 381 382 -383 -384 -385 -386 -387 -388 -389 -390 -391 -392 -393 -394 -395 -396 -397 -398 -399 -400 -401 -402 -403 -404 -405 -406 -407 -408 -409 -410 -411 -412 -413 -414 -415 -416 -417 -418 -419 -420 -421 -422

  +383        @@ -501,6 +462,7 @@

All files / src/tools       +4x       @@ -526,7 +488,6 @@

All files / src/tools       -57x       @@ -538,61 +499,55 @@

All files / src/tools       -2x -  -2x -1x -        +3x   +3x +1x     -1x -1x -            +2x +2x +      -1x -1x -1x       -1x     2x +2x +2x   +2x   +3x     -1x -1x -1x     2x +2x +2x   +  +4x +  +2x 1x 1x 1x 1x 1x 1x -1x -  -  -  -  -  -        @@ -604,14 +559,13 @@

All files / src/tools       -1x -        -1x     +2x +2x       @@ -622,30 +576,24 @@

All files / src/tools       -1x -1x     2x -  -1x -1x -1x -1x -1x -  -  -  -  -  -1x -1x +2x     +4x   +2x +2x +2x +2x +2x +2x +2x +2x     -1x       @@ -656,24 +604,20 @@

All files / src/tools       +2x +2x +2x     +2x   -1x +3x 1x 1x       -1x -  2x -1x -1x -  -  -  -1x       @@ -709,27 +653,17 @@

All files / src/tools       -  -  -  -  -  -  -  -  -  -  -  +1x +1x +1x           -  -  -  -  -  +1x +1x +1x       @@ -749,7 +683,6 @@

All files / src/tools       -    1x   @@ -763,25 +696,23 @@

All files / src/tools       -1x -1x -1x -1x 2x 2x 2x 2x +4x +4x +4x +4x   -1x +2x         -  -      -1x +2x       @@ -793,36 +724,33 @@

All files / src/tools       -1x -1x -1x -1x -1x -1x -1x -1x 2x +2x +2x +2x +3x +3x +3x +3x +6x   +3x 1x -  -  -  -  1x -  -  -  -      +2x +1x +1x +1x             -1x -1x +2x +2x       @@ -835,19 +763,19 @@

All files / src/tools       -1x 2x +4x +4x +4x +4x +5x 2x 2x -2x -3x -1x -1x   +3x +3x +3x 2x -2x -2x -1x       @@ -856,15 +784,15 @@

All files / src/tools       -1x -1x +2x +2x             -1x +2x       @@ -877,37 +805,31 @@

All files / src/tools       -1x -2x -2x 2x +4x +4x +4x +4x +4x +4x +5x 2x 2x -  -  -2x +3x 3x         -1x -1x -2x -2x -  -    +4x     2x   -  -1x -   

/**
  * Reference Query Tools
- * Phase 5 Step 2: Extract self-contained ref_query tool and helpers
+ * Registry-backed reference query tool definitions.
  *
  * Tools:
  * - ref_query: search external reference repositories for documentation and code patterns
@@ -918,40 +840,43 @@ 

All files / src/tools   import * as fs from "fs"; import * as path from "path"; -import { - DocsParser, - findMarkdownFiles, - type ParsedSection, -} from "../../parsers/docs-parser.js"; -  -/** - * Minimal context interface required by ref tools - */ -interface RefToolContext { - errorEnvelope( - code: string, - reason: string, - recoverable?: boolean, - hint?: string - ): string; - formatSuccess( - data: unknown, - profile?: string, - summary?: string, - toolName?: string - ): string; -} +import { DocsParser, findMarkdownFiles, type ParsedSection } from "../../parsers/docs-parser.js"; +import * as z from "zod"; +import type { HandlerBridge, ToolDefinition } from "../types.js";   -/** - * Create reference query tools - * @param ctx - Context object providing errorEnvelope and formatSuccess methods - */ -export function createRefTools(ctx: RefToolContext) { - return { - /** - * Query external reference repositories for documentation and code patterns - */ - async ref_query(args: any): Promise<string> { +export const refToolDefinitions: ToolDefinition[] = [ + { + name: "ref_query", + category: "ref", + description: + "Query a reference repository on the same machine for architecture insights, design patterns, conventions, or code examples. Useful for borrowing context from a well-structured sibling repo when working on the current workspace.", + inputShape: { + repoPath: z.string().describe("Absolute path to the reference repository on this machine"), + query: z + .string() + .default("") + .describe( + "What to look for — architecture patterns, conventions, a specific concept, or a code example", + ), + mode: z + .enum(["auto", "docs", "architecture", "code", "patterns", "all", "structure"]) + .default("auto") + .describe( + "auto = infer from query; docs/architecture = markdown only; code/patterns = source files only; structure = dir tree only; all = everything", + ), + symbol: z + .string() + .optional() + .describe( + "Specific symbol name (function/class/interface) to locate in the reference repo", + ), + limit: z.number().int().min(1).max(20).default(10).describe("Max results to return"), + profile: z + .enum(["compact", "balanced", "debug"]) + .default("compact") + .describe("Response profile"), + }, + async impl(args: any, ctx: HandlerBridge): Promise<string> { const { repoPath, query = "", @@ -966,7 +891,7 @@

All files / src/tools "REF_REPO_MISSING", "repoPath is required", false, - "Provide the absolute path to the reference repository on this machine." + "Provide the absolute path to the reference repository on this machine.", ); }   @@ -976,7 +901,7 @@

All files / src/tools "REF_REPO_NOT_FOUND", `Path does not exist: ${resolvedRepo}`, false, - "Ensure the repository is cloned and the path is accessible from this machine/container." + "Ensure the repository is cloned and the path is accessible from this machine/container.", ); }   @@ -984,11 +909,8 @@

All files / src/tools const repoName = path.basename(resolvedRepo); const findings: any[] = [];   - // Determine effective mode - const effectiveMode = - mode === "auto" ? inferRefMode(query, symbol) : mode; + const effectiveMode = mode === "auto" ? inferRefMode(query, symbol) : mode;   - // --- DOCS / ARCHITECTURE: parse markdown files --- if ( effectiveMode === "docs" || effectiveMode === "architecture" || @@ -1024,12 +946,7 @@

All files / src/tools } }   - // --- CODE / PATTERNS: scan source files --- - Eif ( - effectiveMode === "code" || - effectiveMode === "patterns" || - effectiveMode === "all" - ) { + Eif (effectiveMode === "code" || effectiveMode === "patterns" || effectiveMode === "all") { const sourceExts = [ ".ts", ".tsx", @@ -1053,19 +970,9 @@

All files / src/tools try { const content = fs.readFileSync(filePath, "utf-8"); const relPath = path.relative(resolvedRepo, filePath); - const score = scoreRefCode( - content, - queryTerms, - symbol, - relPath - ); + const score = scoreRefCode(content, queryTerms, symbol, relPath); Eif (score > 0) { - const excerpt = extractRefExcerpt( - content, - queryTerms, - symbol, - 6 - ); + const excerpt = extractRefExcerpt(content, queryTerms, symbol, 6); findings.push({ type: "code", file: relPath, @@ -1079,13 +986,11 @@

All files / src/tools } }   - // --- STRUCTURE: always included for mode "all" or when no query --- Eif (effectiveMode === "all" || effectiveMode === "structure") { const tree = buildRefDirTree(resolvedRepo, 3); findings.push({ type: "structure", file: ".", score: 0, tree }); }   - // Sort by score (structure last), slice to limit const sorted = findings .sort((a, b) => { if (a.type === "structure") return 1; @@ -1106,18 +1011,18 @@

All files / src/tools }, profile, `${sorted.length} result(s) from reference repo ${repoName}`, - "ref_query" + "ref_query", ); } catch (error) { return ctx.errorEnvelope( "REF_QUERY_FAILED", error instanceof Error ? error.message : String(error), - true + true, ); } }, - }; -} + }, +];   // ────────────────────────────────────────────────────────────────────────────── // Private Helpers (internal to this module) @@ -1126,37 +1031,27 @@

All files / src/tools /** * Infer the search mode based on query content */ -function inferRefMode( +function inferRefMode( query: string, - symbol?: string + symbol?: string, ): "docs" | "code" | "architecture" | "patterns" | "all" { - if (symbol) return "code"; - const lower = (query || "").toLowerCase(); - if ( + Iif (symbol) return "code"; + const lower = (query || "").toLowerCase(); + Iif ( /(architect|structure|pattern|design|layer|module|overview|convention|best.?practice)/.test( - lower + lower, ) ) return "architecture"; - if (/(how to|example|guide|decision|adr|changelog)/.test(lower)) - return "docs"; - if ( - /(function|class|method|import|export|interface|type|impl|usage)/.test( - lower - ) - ) - return "code"; - return "all"; + Iif (/(how to|example|guide|decision|adr|changelog)/.test(lower)) return "docs"; + Iif (/(function|class|method|import|export|interface|type|impl|usage)/.test(lower)) return "code"; + return "all"; }   /** * Score a documentation section based on query terms */ -function scoreRefSection( - section: ParsedSection, - queryTerms: string[], - symbol?: string -): number { +function scoreRefSection(section: ParsedSection, queryTerms: string[], symbol?: string): number { let score = 0; const text = `${section.heading} ${section.content}`.toLowerCase(); for (const term of queryTerms) { @@ -1168,8 +1063,7 @@

All files / src/tools } Iif (symbol) { const symLower = symbol.toLowerCase(); - if (section.backtickRefs.some((r) => r.toLowerCase().includes(symLower))) - score += 10; + if (section.backtickRefs.some((r) => r.toLowerCase().includes(symLower))) score += 10; else if (text.includes(symLower)) score += 5; } return score; @@ -1182,7 +1076,7 @@

All files / src/tools content: string, queryTerms: string[], symbol: string | undefined, - relPath: string + relPath: string, ): number { let score = 0; const lower = content.toLowerCase(); @@ -1196,9 +1090,7 @@

All files / src/tools Iif (symbol) { const symLower = symbol.toLowerCase(); const symCount = ( - lower.match( - new RegExp(symLower.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g") - ) ?? [] + lower.match(new RegExp(symLower.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g")) ?? [] ).length; score += symCount * 5; } @@ -1212,7 +1104,7 @@

All files / src/tools content: string, queryTerms: string[], symbol: string | undefined, - contextLines: number + contextLines: number, ): string { const lines = content.split("\n"); let bestLine = 0; @@ -1222,26 +1114,23 @@

All files / src/tools let score = 0; Iif (symbol && lower.includes(symbol.toLowerCase())) score += 10; for (const term of queryTerms) { - Iif (lower.includes(term)) score++; + if (lower.includes(term)) score++; } - Iif (score > bestScore) { - bestScore = score; - bestLine = i; + if (score > bestScore) { + bestScore = score; + bestLine = i; } } - Eif (bestScore === 0) return lines.slice(0, contextLines * 2).join("\n"); - const start = Math.max(0, bestLine - contextLines); - const end = Math.min(lines.length, bestLine + contextLines + 1); - return lines.slice(start, end).join("\n"); + if (bestScore === 0) return lines.slice(0, contextLines * 2).join("\n"); + const start = Math.max(0, bestLine - contextLines); + const end = Math.min(lines.length, bestLine + contextLines + 1); + return lines.slice(start, end).join("\n"); }   /** * Recursively scan for source files matching given extensions */ -function scanRefSourceFiles( - rootPath: string, - extensions: string[] -): string[] { +function scanRefSourceFiles(rootPath: string, extensions: string[]): string[] { const results: string[] = []; const ignoreDirs = new Set([ "node_modules", @@ -1303,15 +1192,9 @@

All files / src/tools const name = path.basename(dir); const children: any[] = []; try { - const entries = fs - .readdirSync(dir, { withFileTypes: true }) - .slice(0, 40); + const entries = fs.readdirSync(dir, { withFileTypes: true }).slice(0, 40); for (const entry of entries) { - if ( - entry.isDirectory() && - !ignoreDirs.has(entry.name) && - !entry.name.startsWith(".") - ) { + if (entry.isDirectory() && !ignoreDirs.has(entry.name) && !entry.name.startsWith(".")) { const child = walk(path.join(dir, entry.name), depth + 1); Eif (child) children.push(child); E} else if (entry.isFile()) { @@ -1333,7 +1216,7 @@

All files / src/tools + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/handlers/test-tools.ts.html b/coverage/src/tools/handlers/test-tools.ts.html index aaff404..8a57f35 100644 --- a/coverage/src/tools/handlers/test-tools.ts.html +++ b/coverage/src/tools/handlers/test-tools.ts.html @@ -23,30 +23,30 @@

All files / src/tools -
+
1 2 @@ -307,7 +307,190 @@

All files / src/tools 242 243 244 -245

  +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417  +  +  +  +  +  +  +  +  +  +  +        @@ -326,18 +509,33 @@

All files / src/tools       +2x +  +        +2x +2x +2x   +2x +    +2x +    +2x +        +2x +2x       +2x       @@ -347,26 +545,25 @@

All files / src/tools       -57x         +6x     +6x +3x +3x     -1x +3x   -1x -1x         -1x   -        @@ -374,19 +571,17 @@

All files / src/tools       -1x   -1x -1x -1x   -1x           +3x   +3x +1x       @@ -394,39 +589,55 @@

All files / src/tools       +5x +6x +      +5x +5x +5x   +6x   +5x   +          +5x     +  +5x +    +  +  +  +  +    +  +      -            +5x     4x -4x -4x           -4x -1x       @@ -434,12 +645,38 @@

All files / src/tools       +2x +  +2x +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +  +            +3x   +3x       @@ -449,12 +686,19 @@

All files / src/tools       +  +3x 3x 3x         +3x +3x +  +3x +12x   3x   @@ -476,6 +720,15 @@

All files / src/tools       +  +  +  +  +  +  +  +  +        @@ -484,10 +737,25 @@

All files / src/tools       -1x   -1x -1x +  +  +  +  +  +  +  +  +  +7x +7x +7x +  +  +  +  +  +7x 1x     @@ -501,7 +769,6 @@

All files / src/tools       -        @@ -509,17 +776,35 @@

All files / src/tools       -1x     -1x -1x +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +6x +  +6x +  +            -1x       @@ -542,6 +827,65 @@

All files / src/tools       +  +4x +  +4x +4x +2x +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +2x +  +  +  +  +  +4x +  +4x +4x +4x +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +        @@ -553,76 +897,224 @@

All files / src/tools    

/**
  * Test Intelligence Tools
- * Phase 5 Step 5: Extract test-related tools
+ * Registry-backed test tool definitions.
  *
  * Tools:
  * - test_select: select affected tests for changed files
  * - test_categorize: categorize tests by type
  * - impact_analyze: analyze blast radius of changes
  * - test_run: execute tests with vitest
- *
- * These tools delegate to TestEngine and use execWithTimeout for execution.
  */
  
+import * as path from "path";
 import { execWithTimeout } from "../../utils/exec-utils.js";
+import * as z from "zod";
+import type { HandlerBridge, ToolDefinition } from "../types.js";
  
 /**
- * Minimal context interface required by test tools
+ * Determine the command and arguments used to execute tests.
+ *
+ * Priority:
+ * 1. `config.testing.testRunner` — explicit override in .lxrag/config.json
+ * 2. Auto-detect from file extension of the first test file:
+ *    .py → pytest, .rb → bundle exec rspec, .go → go test, else → vitest
  */
-interface TestToolContext {
-  testEngine?: any; // TestEngine
-  execWithTimeout?: typeof execWithTimeout;
-  errorEnvelope(
-    code: string,
-    reason: string,
-    recoverable?: boolean,
-    hint?: string
-  ): string;
-  formatSuccess(
-    data: unknown,
-    profile?: string,
-    summary?: string,
-    toolName?: string
-  ): string;
+function resolveTestRunner(
+  testFiles: string[],
+  cwd: string,
+  config?: { testRunner?: { command: string; args?: string[] } },
+): { cmd: string; env?: Record<string, string> } {
+  // 1. Explicit config override
+  Iif (config?.testRunner) {
+    const { command, args = [] } = config.testRunner;
+    return { cmd: [command, ...args, ...testFiles].join(" ") };
+  }
+ 
+  // 2. Auto-detect from file extensions
+  const hasPy = testFiles.some((f) => f.endsWith(".py"));
+  const hasRb = testFiles.some((f) => f.endsWith(".rb"));
+  const hasGo = testFiles.some((f) => f.endsWith(".go"));
+ 
+  Iif (hasPy) {
+    return { cmd: ["pytest", ...testFiles].join(" ") };
+  }
+  Iif (hasRb) {
+    return { cmd: ["bundle", "exec", "rspec", ...testFiles].join(" ") };
+  }
+  Iif (hasGo) {
+    return { cmd: ["go", "test", ...testFiles].join(" ") };
+  }
+ 
+  // 3. Default: vitest for JS/TS
+  const vitestBin = path.resolve(cwd, "node_modules", ".bin", "vitest");
+  const env: Record<string, string> = {
+    PATH: `${path.resolve(cwd, "node_modules", ".bin")}:${path.dirname(process.execPath)}:${process.env.PATH ?? ""}`,
+    NODE: process.execPath,
+  };
+  return {
+    cmd: `"${process.execPath}" "${vitestBin}" run --reporter=verbose ${testFiles.join(" ")}`,
+    env,
+  };
 }
  
 /**
- * Create test intelligence tools
- * @param ctx - Context object providing testEngine and formatting methods
+ * Resolve which source files directly import the given changed files by
+ * traversing IMPORTS → REFERENCES edges in Memgraph.
+ *
+ * Falls back to the in-memory index if Memgraph is not connected.
+ * Returns at most 50 paths, sorted alphabetically.
  */
-export function createTestTools(ctx: TestToolContext) {
-  return {
-    /**
-     * Select affected tests for changed files
-     */
-    async test_select(args: any): Promise<string> {
-      const {
-        changedFiles,
-        includeIntegration = true,
-        profile = "compact",
-      } = args;
+async function resolveDirectImpact(ctx: HandlerBridge, changedFiles: string[]): Promise<string[]> {
+  const memgraph = ctx.context?.memgraph;
+ 
+  // Try Memgraph graph traversal first (most accurate, uses persisted graph)
+  if (memgraph?.isConnected?.()) {
+    try {
+      const projectId = ctx.getActiveProjectContext?.()?.projectId ?? "";
+ 
+      // Normalize input: accept both relative and absolute paths as search keys
+      const result = await memgraph.executeCypher(
+        `MATCH (changed:FILE)
+         WHERE changed.projectId = $projectId
+           AND (changed.relativePath IN $changedPaths
+                OR changed.path IN $changedPaths
+                OR any(cp IN $changedPaths WHERE changed.relativePath = cp
+                                              OR changed.path = cp
+                                              OR changed.relativePath ENDS WITH cp
+                                              OR changed.path ENDS WITH cp))
+         WITH collect(DISTINCT changed) AS changedFiles
+         UNWIND changedFiles AS changed
+         MATCH (changed)<-[:REFERENCES]-(imp:IMPORT)<-[:IMPORTS]-(importer:FILE)
+         WHERE importer.projectId = $projectId
+           AND importer.id <> changed.id
+         RETURN DISTINCT
+           coalesce(importer.relativePath, importer.path) AS path
+         ORDER BY path
+         LIMIT 50`,
+        { projectId, changedPaths: changedFiles },
+      );
+ 
+      const paths: string[] = result.data.map((row: any) => String(row.path ?? "")).filter(Boolean);
+ 
+      if (paths.length > 0) {
+        return paths;
+      }
+    } catch {
+      // Fall through to index-based fallback
+    }
+  }
+ 
+  // Fallback: traverse in-memory index (less accurate, no projectId scoping)
+  const index = ctx.context?.index;
+  Iif (!index?.getRelationshipsTo) {
+    return [];
+  }
+ 
+  const importers = new Set<string>();
+  try {
+    const fileNodes: any[] = index.getNodesByType("FILE") ?? [];
+ 
+    for (const changed of changedFiles) {
+      // Find FILE node whose relativePath or path matches the changed file
+      const targetNode = fileNodes.find(
+        (n: any) =>
+          n.properties?.relativePath === changed ||
+          n.properties?.path === changed ||
+          n.properties?.relativePath?.endsWith(changed) ||
+          n.properties?.path?.endsWith(changed),
+      );
+      Eif (!targetNode) continue;
+ 
+      // incoming REFERENCES edges → IMPORT nodes
+      const refsToTarget: any[] = index.getRelationshipsTo(targetNode.id) ?? [];
+      for (const ref of refsToTarget) {
+        if (ref.type !== "REFERENCES") continue;
+        // incoming IMPORTS edges → source FILE nodes
+        const importsToImp: any[] = index.getRelationshipsTo(ref.from) ?? [];
+        for (const imp of importsToImp) {
+          if (imp.type !== "IMPORTS") continue;
+          const sourceNode = index.getNode(imp.from);
+          if (!sourceNode) continue;
+          const p =
+            sourceNode.properties?.relativePath || sourceNode.properties?.path || sourceNode.id;
+          if (p && p !== changed) importers.add(p);
+        }
+      }
+    }
+  } catch {
+    // best-effort
+  }
+ 
+  return Array.from(importers).sort().slice(0, 50);
+}
+ 
+export const testToolDefinitions: ToolDefinition[] = [
+  {
+    name: "test_select",
+    category: "test",
+    description: "Select tests affected by changed files",
+    inputShape: {
+      changedFiles: z.array(z.string()).describe("Files that changed"),
+      mode: z
+        .enum(["direct", "transitive", "full"])
+        .default("transitive")
+        .describe("Selection mode"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
+      const { changedFiles, includeIntegration = true, profile = "compact" } = args;
+ 
+      const testEngine = ctx.engines.test as
+        | {
+            selectAffectedTests: (
+              changedFiles: string[],
+              includeIntegration?: boolean,
+              depth?: number,
+            ) => any;
+          }
+        | undefined;
  
       try {
-        const result = ctx.testEngine!.selectAffectedTests(
-          changedFiles,
-          includeIntegration
-        );
+        const result = testEngine!.selectAffectedTests(changedFiles, includeIntegration);
  
         return ctx.formatSuccess(result, profile);
       } catch (error) {
         return ctx.errorEnvelope("TEST_SELECT_FAILED", String(error), true);
       }
     },
- 
-    /**
-     * Categorize tests by type
-     */
-    async test_categorize(args: any): Promise<string> {
+  },
+  {
+    name: "test_categorize",
+    category: "test",
+    description: "Categorize tests by type",
+    inputShape: {
+      testFiles: z.array(z.string()).optional().describe("Test files to categorize"),
+    },
+    async impl(args: any, ctx: HandlerBridge): Promise<string> {
       const { testFiles = [], profile = "compact" } = args;
+ 
+      const testEngine = ctx.engines.test as
+        | {
+            getStatistics: () => {
+              unitTests: number;
+              integrationTests: number;
+              performanceTests: number;
+              e2eTests: number;
+            };
+          }
+        | undefined;
  
       try {
-        console.log(`[Test] Categorizing ${testFiles.length} test files...`);
-        const stats = ctx.testEngine!.getStatistics();
+        console.error(`[Test] Categorizing ${testFiles.length} test files...`);
+        const stats = testEngine!.getStatistics();
+ 
+        // Use config-supplied patterns when available; fall back to
+        // language-agnostic wildcard patterns (no hardcoded .ts extension).
+        const cfgCategories: Array<{ id: string; patterns: string[] }> =
+          ctx.context.config?.testing?.categories ?? [];
+        const cfgById = Object.fromEntries(cfgCategories.map((c) => [c.id, c]));
+ 
+        const buildPattern = (id: string, fallback: string): string =>
+          cfgById[id]?.patterns?.[0] ?? fallback;
  
         return ctx.formatSuccess(
           {
@@ -630,37 +1122,47 @@ 

All files / src/tools categorization: { unit: { count: stats.unitTests, - pattern: "**/__tests__/**/*.test.ts", + pattern: buildPattern("unit", "**/__tests__/**/*.test.*"), timeout: 5000, }, integration: { count: stats.integrationTests, - pattern: "**/__tests__/**/*.integration.test.ts", + pattern: buildPattern("integration", "**/__tests__/**/*.integration.test.*"), timeout: 15000, }, performance: { count: stats.performanceTests, - pattern: "**/*.performance.test.ts", + pattern: buildPattern("performance", "**/*.performance.test.*"), timeout: 30000, }, e2e: { count: stats.e2eTests, - pattern: "**/e2e/**/*.test.ts", + pattern: buildPattern("e2e", "**/e2e/**/*.test.*"), timeout: 60000, }, }, }, - profile + profile, ); } catch (error) { return ctx.errorEnvelope("TEST_CATEGORIZE_FAILED", String(error), true); } }, -  - /** - * Analyze blast radius of changes - */ - async impact_analyze(args: any): Promise<string> { + }, + { + name: "impact_analyze", + category: "test", + description: "Analyze impact of changes", + inputShape: { + files: z.array(z.string()).optional().describe("Changed files"), + changedFiles: z.array(z.string()).optional().describe("Changed files (alternate contract)"), + depth: z.number().default(3).describe("Analysis depth"), + profile: z + .enum(["compact", "balanced", "debug"]) + .default("compact") + .describe("Response profile"), + }, + async impl(args: any, ctx: HandlerBridge): Promise<string> { const profile = args?.profile || "compact"; const depth = typeof args?.depth === "number" ? args.depth : 2; const changedFiles: string[] = Array.isArray(args?.files) @@ -689,49 +1191,63 @@

All files / src/tools }, warning: "No changed files were provided", }, - profile + profile, ); } +  + const testEngine = ctx.engines.test as + | { + selectAffectedTests: ( + changedFiles: string[], + includeIntegration?: boolean, + depth?: number, + ) => { + estimatedTime: number; + coverage: { percentage: number }; + selectedTests: string[]; + }; + } + | undefined;   try { - const result = ctx.testEngine!.selectAffectedTests( - changedFiles, - true, - depth - ); + const result = testEngine!.selectAffectedTests(changedFiles, true, depth); + const directImpact = await resolveDirectImpact(ctx, changedFiles);   return ctx.formatSuccess( { changedFiles, analysis: { - directImpact: result.selectedTests.slice(0, 10), + directImpact, estimatedTestTime: result.estimatedTime, coverage: result.coverage, blastRadius: { testsAffected: result.selectedTests.length, percentage: result.coverage.percentage, recommendation: - result.coverage.percentage > 50 - ? "Run full suite" - : "Run affected tests", + result.coverage.percentage > 50 ? "Run full suite" : "Run affected tests", }, }, }, - profile + profile, ); } catch (error) { return ctx.errorEnvelope("IMPACT_ANALYZE_FAILED", String(error), true); } }, -  - /** - * Execute tests using vitest - */ - async test_run(args: any): Promise<string> { - const { testFiles = [], parallel = true, profile = "compact" } = args; + }, + { + name: "test_run", + category: "test", + description: "Execute test suite", + inputShape: { + testFiles: z.array(z.string()).describe("Test files to run"), + parallel: z.boolean().default(true).describe("Run tests in parallel"), + }, + async impl(args: any, ctx: HandlerBridge): Promise<string> { + const { testFiles = [], parallel: _parallel = true, profile = "compact" } = args;   try { - Eif (!testFiles || testFiles.length === 0) { + if (!testFiles || testFiles.length === 0) { return ctx.formatSuccess( { status: "error", @@ -740,61 +1256,61 @@

All files / src/tools passed: 0, failed: 0, }, - profile + profile, ); }   - // Build vitest command (Phase 3.5 - actual execution) - const cmd = [ - "npx vitest run", - parallel - ? "--reporter=verbose" - : "--reporter=verbose --no-coverage", - ...testFiles, - ].join(" "); + const cwd = process.cwd();   - console.log(`[ToolHandlers] Executing: ${cmd}`); + // Resolve runner: config > auto-detect by extension > vitest fallback + const { cmd, env: runnerEnv } = resolveTestRunner( + testFiles, + cwd, + ctx.context.config?.testing, + ); +  + console.error(`[ToolHandlers] Executing: ${cmd}`);   - // Execute vitest with timeout and output limits try { + const augmentedEnv = { ...process.env, ...(runnerEnv ?? {}) }; const output = execWithTimeout(cmd, { cwd: process.cwd(), encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], + env: augmentedEnv, });   return ctx.formatSuccess( { status: "passed", message: "All tests passed", - output: output.substring(0, 1000), // First 1000 chars + output: output.substring(0, 1000), testsRun: testFiles.length, }, - profile + profile, ); } catch (execError: any) { - // Tests failed but command executed - return ctx.formatSuccess( + return ctx.formatSuccess( { status: "failed", message: "Some tests failed", error: execError.message.substring(0, 500), - output: execError.stdout?.toString().substring(0, 500) || "", + output: execError.stdout?.toString().substring(0, 500) || "", testsRun: testFiles.length, }, - profile + profile, ); } } catch (error) { return ctx.errorEnvelope( "TEST_RUN_FAILED", `Test execution failed: ${error instanceof Error ? error.message : String(error)}`, - true + true, ); } }, - }; -} + }, +];  

@@ -802,7 +1318,7 @@

All files / src/tools + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/tool-handler-base.ts.html b/coverage/src/tools/tool-handler-base.ts.html index 7587ac6..88922a3 100644 --- a/coverage/src/tools/tool-handler-base.ts.html +++ b/coverage/src/tools/tool-handler-base.ts.html @@ -23,30 +23,30 @@

All files / src/tools
- 64.65% + 71.53% Statements - 236/365 + 299/418
- 57.14% + 65.2% Branches - 168/294 + 223/342
- 84.31% + 83.05% Functions - 43/51 + 49/59
- 64.73% + 71.6% Lines - 235/363 + 295/412
@@ -1210,7 +1210,52 @@

All files / src/tools1145 1146 1147 -1148

  +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +1157 +1158 +1159 +1160 +1161 +1162 +1163 +1164 +1165 +1166 +1167 +1168 +1169 +1170 +1171 +1172 +1173 +1174 +1175 +1176 +1177 +1178 +1179 +1180 +1181 +1182 +1183 +1184 +1185 +1186 +1187 +1188 +1189 +1190 +1191 +1192 +1193        @@ -1272,146 +1317,152 @@

All files / src/tools      -57x         -57x     +126x   -57x     -57x -57x   -57x -57x -57x +126x   -57x     +126x     +126x +126x   +126x +126x +126x   +126x   -72x -72x -50x     -22x +135x       -50x -50x -38x     -12x             -9x -9x -5x   -4x       -9x       -9x   +165x +165x +131x     -9x -9x -9x -9x -  +34x       -9x +117x +117x +99x   -    +18x       -57x -57x -57x +19x +19x +13x   -57x +6x       +19x       +19x   -21x +19x +19x +19x +19x +    -21x   -21x   +19x   -21x -21x -21x +        -21x   +126x +126x +126x   +126x       -21x         +34x   +34x +34x +34x +34x +34x       +34x       -9x -8x +34x     -1x -1x -      -1x -1x       -1x       +  +19x +18x +  +  +1x +1x +  +  +  +1x +1x +1x 1x     @@ -1432,7 +1483,7 @@

All files / src/tools      -12x +28x       @@ -1440,11 +1491,11 @@

All files / src/tools      -9x +20x       -9x +20x       @@ -1459,8 +1510,8 @@

All files / src/tools      -6x -6x +14x +14x       @@ -1509,15 +1560,11 @@

All files / src/tools      -  -            -  -        @@ -1527,9 +1574,6 @@

All files / src/tools      -  -  -        @@ -1555,111 +1599,120 @@

All files / src/tools      +126x +126x     -57x -  +126x       +126x +        -57x -57x       -57x -57x -57x     -57x   +      -57x   +126x     -57x -57x -57x -57x -57x +126x +126x   +126x +126x   +126x +126x   +126x +126x   -57x +126x +126x     +126x   -57x -    +126x   -57x -57x     +126x +126x       +126x +126x +126x +126x     +126x +126x +126x +126x         +126x +126x     +126x   -57x -57x -18x +126x     -18x +      -7x -7x -  +      -7x -5x   -5x -5x     -5x   +126x +126x +126x +70x +68x     +68x +68x           -  -          +126x +126x         -        -34x       @@ -1667,73 +1720,88 @@

All files / src/tools      +126x +126x +24x     +24x     +70x +70x   +70x +67x   +67x +67x     +67x     -15x   +  +        -15x +  +      +        -15x +35x       -74x             -211x -74x -74x +21x         -137x -18x +21x     -119x -37x       -37x -181x +21x +  +    +374x     -82x         +906x +374x +374x     +532x +93x     -57x +439x +166x +767x   -57x -57x   +273x       @@ -1742,6 +1810,14 @@

All files / src/tools      +132x +132x +132x +  +  +2866x +  +        @@ -1776,96 +1852,125 @@

All files / src/tools      -42x -42x +111x +111x   -42x -2x +111x +5x           +5x 2x     -  -1x -  -  -2x -2x +5x +5x     -42x -  -  -  -  +111x +1x +1x +1x +1x     -  +1x         -  +1x           -42x -  +111x +1x           -42x -5x +111x +17x       2x 2x   +17x +  +  +111x +  +  +  5x     -42x             -1x +  +3x       -41x -41x +106x   -41x +  +106x +106x +  +106x       +  +    +  +        -41x   -41x -39x     -2x -2x -2x -2x -2x +  +106x +106x +  +  +  +  +  +106x +106x +106x +106x +106x +  +  +  +  +106x +102x +  +  +4x +4x +4x +4x +4x       @@ -1878,8 +1983,8 @@

All files / src/tools      -6x -4x +16x +14x     2x @@ -1892,24 +1997,20 @@

All files / src/tools      -27x -  +56x +8x     -27x +48x 7x     -20x +41x 4x 4x     -16x -  -  -  -  +37x       @@ -1919,8 +2020,7 @@

All files / src/tools      -16x -  +37x       @@ -1932,64 +2032,56 @@

All files / src/tools      -3x -3x -3x   -3x -2x -2x -  +7x +7x +7x +7x   -2x     +7x +5x +5x +    -1x +5x +2x       -2x +5x           -2x +5x           -  -  -          -2x +5x   -  -  -          -2x -  -  -  +5x       -1x +2x       -1x -1x +2x +2x       @@ -2003,7 +2095,7 @@

All files / src/tools      -1x +2x       @@ -2019,23 +2111,23 @@

All files / src/tools      -1x -1x +3x +3x         -1x -1x -  +3x +3x +2x       -  -  -  +2x +2x +1x   -  +1x     1x @@ -2060,7 +2152,7 @@

All files / src/tools      -1x +3x       @@ -2074,27 +2166,32 @@

All files / src/tools      +6x +  +6x +    -2x   +6x 2x     +2x   -1x   +4x +4x +4x +2x   -1x -1x -1x -1x   +2x +2x           -        @@ -2102,98 +2199,98 @@

All files / src/tools      -  -  +2x   +2x +2x     -  +2x   -1x -1x     -1x   +21x       -6x +8x       -6x +19x       -9x         +1x +1x   +1x             -  +1x     -    +1x           -  -    +6x +6x   -              -3x -3x +6x +6x +            +6x   +6x   -1x -1x -      -1x -1x -  +6x +2x     -1x -1x -1x -  +4x +4x   -1x     +4x +4x   -1x -1x -1x   -1x +6x +6x   +6x +6x +6x   +6x       @@ -2236,6 +2333,7 @@

All files / src/tools      +  1x 1x   @@ -2340,14 +2438,6 @@

All files / src/tools      -  -  -  -  -  -  -  -  2x 2x   @@ -2384,6 +2474,12 @@

All files / src/toolsAll files / src/toolsAll files / src/toolsAll files / src/toolsAll files / src/toolsIif (this.archEngine) { - this.archEngine.reload(this.context.index, context.projectId); + this.archEngine.reload(this.context.index, context.projectId, context.workspaceRoot); }   // Phase 4.3: Reset embedding flag per-project to prevent race conditions this.clearProjectEmbeddingsReady(context.projectId); } catch (error) { - console.error("[ToolHandlers] Failed to reload engines:", error); + logger.error("[ToolHandlers] Failed to reload engines:", error); } }   @@ -2509,14 +2616,11 @@

All files / src/toolsthis.defaultProjectContext(); const workspaceProvided = - typeof overrides.workspaceRoot === "string" && - overrides.workspaceRoot.trim().length > 0; - const workspaceInput = workspaceProvided - ? overrides.workspaceRoot - : base.workspaceRoot; + typeof overrides.workspaceRoot === "string" && overrides.workspaceRoot.trim().length > 0; + const workspaceInput = workspaceProvided ? overrides.workspaceRoot : base.workspaceRoot; const workspaceRoot = path.resolve(workspaceInput); const sourceInput = overrides.sourceDir || path.join(workspaceRoot, "src"); const sourceDir = path.isAbsolute(sourceInput) @@ -2524,9 +2628,7 @@

All files / src/tools path.basename(workspaceRoot);   return { @@ -2536,7 +2638,7 @@

All files / src/toolsAll files / src/toolsEif ( - path.isAbsolute(context.sourceDir) && - context.sourceDir.startsWith(context.workspaceRoot) - ) { - const relativeSource = path.relative( - context.workspaceRoot, - context.sourceDir, - ); + Eif (path.isAbsolute(context.sourceDir) && context.sourceDir.startsWith(context.workspaceRoot)) { + const relativeSource = path.relative(context.workspaceRoot, context.sourceDir); mappedSourceDir = path.resolve(fallbackRoot, relativeSource); }   @@ -2574,11 +2670,11 @@

All files / src/toolsAll files / src/toolsstopActiveWatcher(): Promise<void> { + public async stopActiveWatcher(): Promise<void> { const key = this.watcherKey(); const existing = this.sessionWatchers.get(key); if (!existing) { @@ -2605,7 +2701,7 @@

All files / src/tools this.sessionWatchers.delete(key); }   - protected async startActiveWatcher(context: ProjectContext): Promise<void> { + public async startActiveWatcher(context: ProjectContext): Promise<void> { Eif (!this.watcherEnabledForRuntime()) { return; } @@ -2652,23 +2748,16 @@

All files / src/tools if (watcher) { await watcher.stop(); this.sessionWatchers.delete(watcherKey); - console.log( - `[ToolHandlers] Session cleanup: stopped watcher for ${sessionId}`, - ); + logger.error(`[ToolHandlers] Session cleanup: stopped watcher for ${sessionId}`); }   // Remove project context for this session if (this.sessionProjectContexts.has(sessionId)) { this.sessionProjectContexts.delete(sessionId); - console.log( - `[ToolHandlers] Session cleanup: removed project context for ${sessionId}`, - ); + logger.error(`[ToolHandlers] Session cleanup: removed project context for ${sessionId}`); } } catch (error) { - console.error( - `[ToolHandlers] Error cleaning up session ${sessionId}:`, - error, - ); + logger.error(`[ToolHandlers] Error cleaning up session ${sessionId}:`, error); } }   @@ -2688,15 +2777,13 @@

All files / src/tools await watcher.stop(); } } catch (error) { - console.error(`[ToolHandlers] Error stopping watcher ${key}:`, error); + logger.error(`[ToolHandlers] Error stopping watcher ${key}:`, error); } }   this.sessionWatchers.clear(); this.sessionProjectContexts.clear(); - console.log( - `[ToolHandlers] Cleaned up all ${sessionIds.length} session contexts`, - ); + logger.error(`[ToolHandlers] Cleaned up all ${sessionIds.length} session contexts`); }   // ────────────────────────────────────────────────────────────────────────────── @@ -2704,51 +2791,113 @@

All files / src/toolsIif (this.context.config.architecture) { this.archEngine = new ArchitectureEngine( this.context.config.architecture.layers, this.context.config.architecture.rules, this.context.index, + this.defaultActiveProjectContext.workspaceRoot, + { + sourceGlobs: this.context.config.testing?.sourceGlobs, + defaultExtension: this.context.config.testing?.defaultExtension, + }, + ); + logger.error( + `[initializeEngines] archEngine=ready layers=${this.context.config.architecture.layers?.length ?? 0}`, ); + } else { + logger.error("[initializeEngines] archEngine=skipped (no architecture config)"); }   this.testEngine = new TestEngine(this.context.index); - this.progressEngine = new ProgressEngine( - this.context.index, - this.context.memgraph, - ); + logger.error("[initializeEngines] testEngine=ready"); +  + this.progressEngine = new ProgressEngine(this.context.index, this.context.memgraph); + logger.error("[initializeEngines] progressEngine=ready"); +  this.episodeEngine = new EpisodeEngine(this.context.memgraph); + logger.error("[initializeEngines] episodeEngine=ready"); +  this.coordinationEngine = new CoordinationEngine(this.context.memgraph); + logger.error("[initializeEngines] coordinationEngine=ready"); +  this.communityDetector = new CommunityDetector(this.context.memgraph); + logger.error("[initializeEngines] communityDetector=ready");   // Initialize GraphOrchestrator if not provided this.orchestrator = this.context.orchestrator || new GraphOrchestrator(this.context.memgraph, false, this.context.index); + logger.error( + `[initializeEngines] orchestrator=${this.context.orchestrator ? "provided" : "created"}`, + );   this.initializeVectorEngine(); + logger.error("[initializeEngines] All engines initialized."); }   protected initializeVectorEngine(): void { const host = env.QDRANT_HOST; const port = env.QDRANT_PORT; + logger.error(`[initializeVectorEngine] qdrant=${host}:${port}`); + logger.error( + `[initializeVectorEngine] summarizerUrl=${env.LXRAG_SUMMARIZER_URL ?? "(not set)"}`, + ); this.qdrant = new QdrantClient(host, port); this.embeddingEngine = new EmbeddingEngine(this.context.index, this.qdrant); + logger.error("[initializeVectorEngine] embeddingEngine=created"); this.hybridRetriever = new HybridRetriever( this.context.index, this.embeddingEngine, this.context.memgraph, ); + logger.error("[initializeVectorEngine] hybridRetriever=created"); this.docsEngine = new DocsEngine(this.context.memgraph, { qdrant: this.qdrant, }); + logger.error("[initializeVectorEngine] docsEngine=created");   - void this.qdrant.connect().catch((error) => { - console.warn("[ToolHandlers] Qdrant connection skipped:", error); + void this.qdrant + .connect() + .then(() => { + logger.error("[initializeVectorEngine] qdrant=CONNECTED"); + }) + .catch((error: unknown) => { + logger.warn("[initializeVectorEngine] qdrant=FAILED:", String(error)); + }); +  + // Ensure the Memgraph text_search BM25 index exists at startup. + // Fire-and-forget: failure is non-fatal; retrieval falls back to lexical mode. + // Deferred with setImmediate so it runs after the current microtask queue + // (important for test isolation — avoids polluting executeCypher call counts). + setImmediate(() => { + Iif (!this.hybridRetriever) return; + if (!this.context.memgraph.isConnected?.()) return; + if (typeof (this.hybridRetriever as any).ensureBM25Index !== "function") return; + void this.hybridRetriever + .ensureBM25Index() + .then((result) => { + if (result.created) { + logger.error("[bm25] Created text_search symbol_index at startup"); + E} else if (result.error) { + logger.warn(`[bm25] BM25 index unavailable at startup: ${result.error}`); + } + }) + .catch(() => { + // Memgraph not yet connected at startup — index will be created on next rebuild + }); });   Eif (!env.LXRAG_SUMMARIZER_URL) { - console.warn( + logger.warn( "[summarizer] LXRAG_SUMMARIZER_URL is not set. " + "Heuristic local summaries will be used, reducing vector search quality and " + "compact-profile accuracy. " + @@ -2765,22 +2914,20 @@

All files / src/toolsEif (nodes.length === 0 && relationships.length === 0) { - console.log( + logger.error( `[Phase2c] No data found in Memgraph for project ${projectId}, index remains empty`, ); return; @@ -2793,23 +2940,14 @@

All files / src/tools for (const rel of relationships) { - this.context.index.addRelationship( - rel.id, - rel.from, - rel.to, - rel.type, - rel.properties, - ); + this.context.index.addRelationship(rel.id, rel.from, rel.to, rel.type, rel.properties); }   - console.log( + logger.error( `[Phase2c] Index loaded from Memgraph: ${nodes.length} nodes, ${relationships.length} relationships for project ${projectId}`, ); } catch (error) { - console.error( - "[Phase2c] Failed to initialize index from Memgraph:", - error, - ); + logger.error("[Phase2c] Failed to initialize index from Memgraph:", error); // Continue regardless - index is optional for startup } } @@ -2818,12 +2956,7 @@

All files / src/toolsAll files / src/toolsAll files / src/tools`${normalized.slice(0, 317)}...` - : normalized; + return normalized.length > 320 ? `${normalized.slice(0, 317)}...` : normalized; }   if (Array.isArray(value)) { @@ -2858,35 +2989,25 @@

All files / src/toolsNumber(value) : value), 2, ); } @@ -2895,7 +3016,7 @@

All files / src/toolsAll files / src/toolsnormalized.files + ? normalized.files : Array.isArray(normalized.changedFiles) ? normalized.changedFiles : [];   - if ( - Array.isArray(normalized.changedFiles) && - !Array.isArray(normalized.files) - ) { + if (Array.isArray(normalized.changedFiles) && !Array.isArray(normalized.files)) { warnings.push("mapped changedFiles -> files"); }   @@ -2944,26 +3062,26 @@

All files / src/toolsIif (toolName === "progress_query") { - if (typeof normalized.type !== "string") { - const queryText = String(normalized.query || "task").toLowerCase(); - normalized.type = queryText.includes("feature") ? "feature" : "task"; - warnings.push("derived type from query text"); + if (toolName === "progress_query") { + Eif (typeof normalized.type !== "string") { + const queryText = String(normalized.query || "task").toLowerCase(); + normalized.type = queryText.includes("feature") ? "feature" : "task"; + warnings.push("derived type from query text"); }   - if (normalized.status === "active") { + Iif (normalized.status === "active") { normalized.status = "in-progress"; warnings.push("mapped status active -> in-progress"); }   - if (normalized.status === "all") { + Iif (normalized.status === "all") { delete normalized.status; warnings.push("mapped status all -> undefined"); } }   - Iif (toolName === "task_update") { - if (normalized.status === "active") { + if (toolName === "task_update") { + Iif (normalized.status === "active") { normalized.status = "in-progress"; warnings.push("mapped status active -> in-progress"); } @@ -2983,18 +3101,35 @@

All files / src/tools{}).slice(0, 256)}`, + ); const { normalized, warnings } = this.normalizeToolArgs(toolName, rawArgs); const target = (this as any)[toolName];   Iif (typeof target !== "function") { + logger.error( + `[callTool] TOOL_NOT_FOUND tool=${toolName} — method does not exist on ToolHandlers`, + ); + const registered = Object.getOwnPropertyNames(Object.getPrototypeOf(this)) + .filter((k) => typeof (this as any)[k] === "function" && !k.startsWith("_")) + .join(", "); + logger.error(`[callTool] Registered methods: ${registered}`); return this.errorEnvelope( "TOOL_NOT_FOUND", `Tool not found in handler registry: ${toolName}`, @@ -3002,7 +3137,22 @@

All files / src/tools logger.error(`[callTool] UNCAUGHT_EXCEPTION tool=${toolName} error=${String(err)}`); + throw err; + } +  + try { + const parsed = JSON.parse(result); + const ok = parsed?.ok ?? true; + const code = parsed?.error?.code ?? (ok ? "ok" : "error"); + logger.error(`[callTool] EXIT tool=${toolName} status=${ok} code=${code}`); + } catch { + logger.error(`[callTool] EXIT tool=${toolName} result-length=${result.length}`); + }   if (!warnings.length) { return result; @@ -3024,7 +3174,7 @@

All files / src/toolsAll files / src/tools return Number.isNaN(parsed) ? null : parsed; }   - protected toSafeNumber(value: unknown): number | null { - Iif (typeof value === "number") { - return Number.isFinite(value) ? value : null; + public toSafeNumber(value: unknown): number | null { + if (typeof value === "number") { + return Number.isFinite(value) ? value : null; }   if (typeof value === "bigint") { @@ -3052,11 +3202,7 @@

All files / src/toolsnull; }   - Iif ( - value && - typeof value === "object" && - "low" in (value as Record<string, unknown>) - ) { + Iif (value && typeof value === "object" && "low" in (value as Record<string, unknown>)) { const low = Number((value as Record<string, unknown>).low); const highRaw = (value as Record<string, unknown>).high; const high = typeof highRaw === "number" ? highRaw : Number(highRaw || 0); @@ -3073,7 +3219,7 @@

All files / src/toolsAll files / src/tools"").toUpperCase(); const entities = Array.isArray(args.entities) ? args.entities : []; const metadata = args.metadata || {}; + logger.error( + `[validateEpisodeInput] type=${type} outcome=${String(args.outcome ?? "")} entities=${entities.length} metadataKeys=${Object.keys(metadata).join(",") || "none"}`, + );   if (type === "DECISION") { const outcome = String(args.outcome || "").toLowerCase(); Iif (!outcome || !["success", "failure", "partial"].includes(outcome)) { return "DECISION episodes require outcome: success | failure | partial."; } - if ( - typeof metadata.rationale !== "string" && - typeof metadata.reason !== "string" - ) { + if (typeof metadata.rationale !== "string" && typeof metadata.reason !== "string") { return "DECISION episodes require metadata.rationale (or metadata.reason)."; } } @@ -3107,19 +3253,13 @@

All files / src/tools if (!outcome || !["success", "failure", "partial"].includes(outcome)) { return "TEST_RESULT episodes require outcome: success | failure | partial."; } - if ( - typeof metadata.testName !== "string" && - typeof metadata.testFile !== "string" - ) { + if (typeof metadata.testName !== "string" && typeof metadata.testFile !== "string") { return "TEST_RESULT episodes require metadata.testName or metadata.testFile."; } }   Iif (type === "ERROR") { - if ( - typeof metadata.errorCode !== "string" && - typeof metadata.stack !== "string" - ) { + if (typeof metadata.errorCode !== "string" && typeof metadata.stack !== "string") { return "ERROR episodes require metadata.errorCode or metadata.stack."; } } @@ -3127,10 +3267,7 @@

All files / src/toolsIif (!this.embeddingEngine || !query.trim()) { return []; } @@ -3158,7 +3295,7 @@

All files / src/toolsAll files / src/toolsIif (txIdPattern.test(trimmed) || trimmed.startsWith("tx-")) { - const txLookup = await this.context.memgraph.executeCypher( + if (txIdPattern.test(trimmed) || trimmed.startsWith("tx-")) { + const txLookup = await this.context.memgraph.executeCypher( "MATCH (tx:GRAPH_TX {projectId: $projectId, id: $id}) RETURN tx.timestamp AS timestamp ORDER BY tx.timestamp DESC LIMIT 1", { projectId, id: trimmed }, ); - const ts = this.toSafeNumber(txLookup.data?.[0]?.timestamp); - if (ts !== null) { - return { sinceTs: ts, mode: "txId", anchorValue: trimmed }; + const ts = this.toSafeNumber(txLookup.data?.[0]?.timestamp); + if (ts !== null) { + return { sinceTs: ts, mode: "txId", anchorValue: trimmed }; } - return null; + return null; }   const timestamp = this.toEpochMillis(trimmed); @@ -3220,44 +3357,44 @@

All files / src/tools"unknown"}`, + ); +  + if (this.isProjectEmbeddingsReady(activeProjectId) || !this.embeddingEngine) { + logger.error( + `[ensureEmbeddings] SKIP — embeddingEngine=${!!this.embeddingEngine} alreadyReady=${this.isProjectEmbeddingsReady(activeProjectId)}`, + ); return; }   try { const generated = await this.embeddingEngine.generateAllEmbeddings(); - Eif (generated.functions + generated.classes + generated.files === 0) { + if (generated.functions + generated.classes + generated.files === 0) { throw new Error("No indexed symbols found. Run graph_rebuild first."); }   - try { - await this.embeddingEngine.storeInQdrant(); + try { + await this.embeddingEngine.storeInQdrant(); } catch (qdrantError) { - const errorMsg = - qdrantError instanceof Error - ? qdrantError.message - : String(qdrantError); - console.error( + const errorMsg = qdrantError instanceof Error ? qdrantError.message : String(qdrantError); + logger.error( `[Phase4.5] Qdrant storage failed for project ${activeProjectId}: ${errorMsg}`, ); // Don't throw - continue with embeddings ready flag set locally // Qdrant failures are non-critical for indexing functionality - console.warn( + logger.warn( `[Phase4.5] Continuing without Qdrant - semantic search may be unavailable for project ${activeProjectId}`, ); }   - this.setProjectEmbeddingsReady(activeProjectId, true); + this.setProjectEmbeddingsReady(activeProjectId, true); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); - console.error( + logger.error( `[Phase4.5] Embedding generation failed for project ${activeProjectId}: ${errorMsg}`, ); throw error; @@ -3280,26 +3417,22 @@

All files / src/toolsrecordBuildError( - projectId: string, - error: unknown, - context?: string, - ): void { - const errorMsg = error instanceof Error ? error.message : String(error); - const errors = this.backgroundBuildErrors.get(projectId) || []; + public recordBuildError(projectId: string, error: unknown, context?: string): void { + const errorMsg = error instanceof Error ? error.message : String(error); + const errors = this.backgroundBuildErrors.get(projectId) || [];   - errors.push({ + errors.push({ timestamp: Date.now(), error: errorMsg, context, });   // Keep history bounded - if (errors.length > this.maxBuildErrorsPerProject) { + Iif (errors.length > this.maxBuildErrorsPerProject) { errors.shift(); }   - this.backgroundBuildErrors.set(projectId, errors); + this.backgroundBuildErrors.set(projectId, errors); }   protected getRecentBuildErrors( @@ -3314,25 +3447,36 @@

All files / src/tools"").trim(); Iif (!requested) { return undefined; }   - const exact = this.context.index.getNode(requested); - Iif (exact) { - return exact; + // Try exact match first, then also try with the active projectId prefix + // (Memgraph nodes use "projectId:file:name:line" while the in-memory index + // built during a rebuild uses the raw "file:name:line" format) + const { projectId } = this.getActiveProjectContext(); + const exact = + this.context.index.getNode(requested) || + (projectId && requested && !requested.startsWith(`${projectId}:`) + ? this.context.index.getNode(`${projectId}:${requested}`) + : undefined); + if (exact) { + return exact; }   const normalizedPath = requested.replace(/\\/g, "/"); const basename = path.basename(normalizedPath); - const scopedTail = requested.includes(":") - ? requested.split(":").slice(-1)[0] - : requested; - const symbolTail = requested.includes("::") - ? requested.split("::").slice(-1)[0] - : scopedTail; +  + // For IDs in format "file.ts:symbolName:lineNum" (parser output), the last + // segment is a line number — use the second-to-last as the symbol name. + const parts = requested.split(":"); + const scopedTail = parts.length > 1 ? parts[parts.length - 1] : requested; + // If last segment is a number, treat the preceding segment as the name + const scopedName = + parts.length > 2 && /^\d+$/.test(scopedTail) ? parts[parts.length - 2] : scopedTail; + const symbolTail = requested.includes("::") ? requested.split("::").slice(-1)[0] : scopedName;   const files = this.context.index.getNodesByType("FILE"); const functions = this.context.index.getNodesByType("FUNCTION"); @@ -3341,10 +3485,7 @@

All files / src/toolsAll files / src/toolsAll files / src/tools return ( name === requested || name === scopedTail || + name === scopedName || name === symbolTail || node.id === requested || node.id.endsWith(`:${requested}`) @@ -3483,20 +3626,12 @@

All files / src/toolsAll files / src/tools Code coverage generated by istanbul - at 2026-02-24T01:13:58.055Z + at 2026-02-27T23:25:35.933Z + + + + + + \ No newline at end of file diff --git a/coverage/src/tools/vector-tools.ts.html b/coverage/src/tools/vector-tools.ts.html new file mode 100644 index 0000000..a379534 --- /dev/null +++ b/coverage/src/tools/vector-tools.ts.html @@ -0,0 +1,949 @@ + + + + + + Code coverage report for src/tools/vector-tools.ts + + + + + + + + + +
+
+

All files / src/tools vector-tools.ts

+
+ +
+ 0% + Statements + 0/75 +
+ + +
+ 0% + Branches + 0/34 +
+ + +
+ 0% + Functions + 0/15 +
+ + +
+ 0% + Lines + 0/71 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Vector Search Tools
+ * Semantic code search capabilities
+ */
+ 
+import type EmbeddingEngine from "../vector/embedding-engine.js";
+import type { GraphIndexManager } from "../graph/index.js";
+ 
+export interface SemanticSearchResult {
+  id: string;
+  name: string;
+  type: "function" | "class" | "file";
+  similarity: number;
+  path?: string;
+  description?: string;
+}
+ 
+/**
+ * Vector search tools for semantic code analysis
+ */
+export class VectorTools {
+  constructor(
+    private embeddingEngine: EmbeddingEngine | null,
+    private index: GraphIndexManager,
+  ) {}
+ 
+  /**
+   * Find similar code to a query
+   */
+  async code_search_semantic(args: any): Promise<string> {
+    if (!this.embeddingEngine) {
+      return JSON.stringify({
+        error: "Embedding engine not initialized",
+        suggestion: "Run graph:build with embeddings enabled",
+      });
+    }
+ 
+    const { query, type = "function", limit = 5 } = args;
+ 
+    try {
+      const results = await this.embeddingEngine.findSimilar(query, type, limit);
+ 
+      const formatted = results.map((r) => ({
+        id: r.id,
+        name: r.name,
+        type: r.type,
+        path: r.metadata.path,
+        relevance: "high",
+      }));
+ 
+      return JSON.stringify(
+        {
+          query,
+          type,
+          results: formatted,
+          count: formatted.length,
+          note: "Results ranked by semantic similarity",
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Search failed: ${error}` });
+    }
+  }
+ 
+  /**
+   * Find duplicate or similar implementations
+   */
+  async code_find_duplicates(args: any): Promise<string> {
+    if (!this.embeddingEngine) {
+      return JSON.stringify({
+        error: "Embedding engine not initialized",
+      });
+    }
+ 
+    const { name, type = "function" } = args;
+ 
+    try {
+      const similar = await this.embeddingEngine.findSimilar(name, type, 10);
+ 
+      const grouped: Record<string, any[]> = {};
+      for (const result of similar) {
+        const group = result.metadata.path?.split("/")[1] || "other";
+        if (!grouped[group]) grouped[group] = [];
+        grouped[group].push({
+          name: result.name,
+          path: result.metadata.path,
+          type: result.type,
+        });
+      }
+ 
+      return JSON.stringify(
+        {
+          query: name,
+          searchType: type,
+          duplicatesByArea: grouped,
+          totalFound: similar.length,
+          recommendation:
+            similar.length > 3
+              ? "Consider refactoring to shared utility"
+              : "No significant duplicates",
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Duplicate search failed: ${error}` });
+    }
+  }
+ 
+  /**
+   * Find code by semantic meaning
+   */
+  async code_search_meaning(args: any): Promise<string> {
+    if (!this.embeddingEngine) {
+      return JSON.stringify({
+        error: "Embedding engine not initialized",
+      });
+    }
+ 
+    const { meaning, limit = 10 } = args;
+ 
+    try {
+      // Search across all types
+      const functionResults = await this.embeddingEngine.findSimilar(
+        meaning,
+        "function",
+        Math.ceil(limit / 3),
+      );
+      const classResults = await this.embeddingEngine.findSimilar(
+        meaning,
+        "class",
+        Math.ceil(limit / 3),
+      );
+      const fileResults = await this.embeddingEngine.findSimilar(
+        meaning,
+        "file",
+        Math.ceil(limit / 3),
+      );
+ 
+      const allResults = [...functionResults, ...classResults, ...fileResults].slice(0, limit);
+ 
+      return JSON.stringify(
+        {
+          query: meaning,
+          results: allResults.map((r) => ({
+            name: r.name,
+            type: r.type,
+            path: r.metadata.path,
+            description: `${r.type} matching: ${meaning}`,
+          })),
+          count: allResults.length,
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Semantic search failed: ${error}` });
+    }
+  }
+ 
+  /**
+   * Suggest refactoring opportunities based on similarity
+   */
+  async code_suggest_refactor(args: any): Promise<string> {
+    if (!this.embeddingEngine) {
+      return JSON.stringify({
+        error: "Embedding engine not initialized",
+      });
+    }
+ 
+    const { element, type = "function" } = args;
+ 
+    try {
+      const similar = await this.embeddingEngine.findSimilar(element, type, 5);
+ 
+      if (similar.length < 2) {
+        return JSON.stringify({
+          element,
+          status: "unique",
+          suggestion: "No similar code found - this is a unique implementation",
+        });
+      }
+ 
+      const suggestions: string[] = [];
+      if (similar.length >= 3) {
+        suggestions.push(
+          `Found ${similar.length} similar implementations - consider extracting common logic`,
+        );
+        suggestions.push("Create a shared utility or service class");
+        suggestions.push("Document the pattern for team consistency");
+      }
+ 
+      return JSON.stringify(
+        {
+          element,
+          type,
+          similarCount: similar.length,
+          similar: similar.map((s) => ({
+            name: s.name,
+            path: s.metadata.path,
+          })),
+          suggestions,
+          priority: similar.length >= 3 ? "high" : "medium",
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Refactor suggestion failed: ${error}` });
+    }
+  }
+ 
+  /**
+   * Hybrid search combining graph and vector queries
+   */
+  async code_hybrid_search(args: any): Promise<string> {
+    const { query, type = "function" } = args;
+ 
+    try {
+      // Vector search (semantic)
+      let vectorResults: any[] = [];
+      if (this.embeddingEngine) {
+        const embedResults = await this.embeddingEngine.findSimilar(query, type, 5);
+        vectorResults = embedResults.map((r) => ({
+          id: r.id,
+          name: r.name,
+          source: "vector",
+          score: 0.8,
+        }));
+      }
+ 
+      // Graph search (structural)
+      const graphResults: any[] = [];
+      if (type === "function") {
+        const nodes = this.index.getNodesByType("FUNCTION");
+        nodes
+          .filter((n) => n.properties.name?.includes(query) || n.properties.name === query)
+          .slice(0, 5)
+          .forEach((n) => {
+            graphResults.push({
+              id: n.id,
+              name: n.properties.name,
+              source: "graph",
+              score: 1.0, // Exact match
+            });
+          });
+      }
+ 
+      // Combine and rank
+      const combined = [...graphResults, ...vectorResults];
+      const ranked = combined
+        .reduce((acc, item) => {
+          const existing = acc.find((a: any) => a.id === item.id);
+          if (existing) {
+            existing.combinedScore = Math.max(existing.combinedScore, item.score);
+            existing.sources.push(item.source);
+          } else {
+            acc.push({
+              ...item,
+              combinedScore: item.score,
+              sources: [item.source],
+            });
+          }
+          return acc;
+        }, [] as any[])
+        .sort((a: any, b: any) => b.combinedScore - a.combinedScore)
+        .slice(0, 10);
+ 
+      return JSON.stringify(
+        {
+          query,
+          type,
+          results: ranked,
+          totalFound: ranked.length,
+          method: "hybrid (graph + vector)",
+        },
+        null,
+        2,
+      );
+    } catch (error) {
+      return JSON.stringify({ error: `Hybrid search failed: ${error}` });
+    }
+  }
+}
+ 
+export default VectorTools;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/types/config.ts.html b/coverage/src/types/config.ts.html new file mode 100644 index 0000000..e3dd8fa --- /dev/null +++ b/coverage/src/types/config.ts.html @@ -0,0 +1,406 @@ + + + + + + Code coverage report for src/types/config.ts + + + + + + + + + +
+
+

All files / src/types config.ts

+
+ +
+ 0% + Statements + 0/8 +
+ + +
+ 0% + Branches + 0/10 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Configuration type definitions
+ * Phase 4.6: Type safety improvements
+ */
+ 
+/**
+ * Architecture layer configuration
+ */
+export interface ArchitectureLayer {
+  id: string;
+  name: string;
+  description?: string;
+  contains?: string[];
+  canDependOn?: string[];
+}
+ 
+/**
+ * Architecture rule configuration
+ */
+export interface ArchitectureRule {
+  id: string;
+  type: "dependency" | "file-pattern" | "custom";
+  severity: "error" | "warning" | "info";
+  description: string;
+  pattern?: string;
+  from?: string;
+  to?: string;
+}
+ 
+/**
+ * Architecture configuration
+ */
+export interface ArchitectureConfig {
+  layers: ArchitectureLayer[];
+  rules: ArchitectureRule[];
+  projectStructure?: {
+    src?: string;
+    tests?: string;
+    docs?: string;
+  };
+}
+ 
+/**
+ * Full configuration object
+ */
+export interface ApplicationConfig {
+  architecture: ArchitectureConfig;
+  version?: string;
+  name?: string;
+}
+ 
+/**
+ * Memgraph connection config
+ */
+export interface MemgraphConfig {
+  host: string;
+  port: number;
+  username?: string;
+  password?: string;
+}
+ 
+/**
+ * Qdrant connection config
+ */
+export interface QdrantConfig {
+  host: string;
+  port: number;
+  apiKey?: string;
+}
+ 
+/**
+ * MCP server config
+ */
+export interface MCPServerConfig {
+  transport: "stdio" | "http";
+  port?: number;
+  name?: string;
+  version?: string;
+}
+ 
+/**
+ * System configuration combining all sub-configs
+ */
+export interface SystemConfig {
+  application: ApplicationConfig;
+  memgraph: MemgraphConfig;
+  qdrant: QdrantConfig;
+  mcp: MCPServerConfig;
+}
+ 
+/**
+ * Type guard to check if value is valid architecture config
+ */
+export function isValidArchitectureConfig(obj: unknown): obj is ArchitectureConfig {
+  if (!obj || typeof obj !== "object") return false;
+  const config = obj as Record<string, unknown>;
+  return Array.isArray(config.layers) && Array.isArray(config.rules);
+}
+ 
+/**
+ * Type guard for application config
+ */
+export function isValidApplicationConfig(obj: unknown): obj is ApplicationConfig {
+  if (!obj || typeof obj !== "object") return false;
+  const config = obj as Record<string, unknown>;
+  return isValidArchitectureConfig(config.architecture);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/types/index.html b/coverage/src/types/index.html new file mode 100644 index 0000000..af77db0 --- /dev/null +++ b/coverage/src/types/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/types + + + + + + + + + +
+
+

All files src/types

+
+ +
+ 0% + Statements + 0/23 +
+ + +
+ 0% + Branches + 0/25 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 0% + Lines + 0/21 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
config.ts +
+
0%0/80%0/100%0/20%0/6
tool-args.ts +
+
0%0/150%0/150%0/30%0/15
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/types/tool-args.ts.html b/coverage/src/types/tool-args.ts.html new file mode 100644 index 0000000..55f17cc --- /dev/null +++ b/coverage/src/types/tool-args.ts.html @@ -0,0 +1,586 @@ + + + + + + Code coverage report for src/types/tool-args.ts + + + + + + + + + +
+
+

All files / src/types tool-args.ts

+
+ +
+ 0% + Statements + 0/15 +
+ + +
+ 0% + Branches + 0/15 +
+ + +
+ 0% + Functions + 0/3 +
+ + +
+ 0% + Lines + 0/15 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Type definitions for MCP tool arguments
+ * Phase 4.6: Type safety improvements
+ */
+ 
+/**
+ * Generic tool arguments with required and optional fields
+ */
+export interface ToolArgs {
+  [key: string]: unknown;
+}
+ 
+/**
+ * Graph query tool arguments
+ */
+export interface GraphQueryArgs extends ToolArgs {
+  query: string;
+  language?: "cypher" | "natural";
+  mode?: "local" | "global" | "hybrid";
+  limit?: number;
+  asOf?: string;
+}
+ 
+/**
+ * Graph set workspace arguments
+ */
+export interface GraphSetWorkspaceArgs extends ToolArgs {
+  workspaceRoot: string;
+  sourceDir?: string;
+  projectId?: string;
+}
+ 
+/**
+ * Graph rebuild arguments
+ */
+export interface GraphRebuildArgs extends ToolArgs {
+  mode?: "full" | "incremental";
+  verbose?: boolean;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Graph health arguments
+ */
+export interface GraphHealthArgs extends ToolArgs {
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Semantic search arguments
+ */
+export interface SemanticSearchArgs extends ToolArgs {
+  query: string;
+  type?: "function" | "class" | "file";
+  limit?: number;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Find similar arguments
+ */
+export interface FindSimilarArgs extends ToolArgs {
+  elementId: string;
+  limit?: number;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Code clusters arguments
+ */
+export interface CodeClustersArgs extends ToolArgs {
+  type?: "function" | "class" | "file";
+  count?: number;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Create feature arguments
+ */
+export interface CreateFeatureArgs extends ToolArgs {
+  name: string;
+  description?: string;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Create task arguments
+ */
+export interface CreateTaskArgs extends ToolArgs {
+  name: string;
+  featureId?: string;
+  description?: string;
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Update task arguments
+ */
+export interface UpdateTaskArgs extends ToolArgs {
+  taskId: string;
+  status?: "pending" | "in-progress" | "completed" | "blocked";
+  profile?: "compact" | "balanced" | "debug";
+}
+ 
+/**
+ * Union type for all tool arguments
+ */
+export type AnyToolArgs =
+  | GraphQueryArgs
+  | GraphSetWorkspaceArgs
+  | GraphRebuildArgs
+  | GraphHealthArgs
+  | SemanticSearchArgs
+  | FindSimilarArgs
+  | CodeClustersArgs
+  | CreateFeatureArgs
+  | CreateTaskArgs
+  | UpdateTaskArgs
+  | ToolArgs;
+ 
+/**
+ * Type guard to safely extract typed arguments
+ */
+export function extractToolArgs<T extends ToolArgs>(
+  args: unknown,
+  requiredFields: string[] = [],
+): T {
+  if (!args || typeof args !== "object") {
+    throw new Error(`Invalid tool arguments: expected object, got ${typeof args}`);
+  }
+ 
+  const obj = args as Record<string, unknown>;
+ 
+  for (const field of requiredFields) {
+    if (!(field in obj)) {
+      throw new Error(`Missing required field: ${field}`);
+    }
+  }
+ 
+  return obj as T;
+}
+ 
+/**
+ * Get profile from tool arguments (safely)
+ */
+export function getProfileFromArgs(args: ToolArgs): "compact" | "balanced" | "debug" {
+  const profile = args.profile;
+  if (typeof profile === "string" && ["compact", "balanced", "debug"].includes(profile)) {
+    return profile as "compact" | "balanced" | "debug";
+  }
+  return "compact";
+}
+ 
+/**
+ * Get limit from tool arguments with validation
+ */
+export function getLimitFromArgs(
+  args: ToolArgs,
+  defaultLimit: number = 100,
+  maxLimit: number = 10000,
+): number {
+  const limit = args.limit;
+  if (typeof limit === "number") {
+    return Math.max(1, Math.min(limit, maxLimit));
+  }
+  return defaultLimit;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/utils/exec-utils.ts.html b/coverage/src/utils/exec-utils.ts.html index eeabf1f..22b6980 100644 --- a/coverage/src/utils/exec-utils.ts.html +++ b/coverage/src/utils/exec-utils.ts.html @@ -139,8 +139,7 @@

All files / src/utils74 75 76 -77 -78

  +77        @@ -168,34 +167,33 @@

All files / src/utils      +7x   +7x +7x     -5x   -5x -5x       +7x +  +4x +4x +1x       -5x   -3x 3x 1x       -2x -1x -      -  -1x +2x       @@ -226,7 +224,7 @@

All files / src/utilsAll files / src/utilsAll files / src/utilsAll files / src/utils Code coverage generated by istanbul - at 2026-02-24T01:13:58.055Z + at 2026-02-27T23:25:35.933Z + + + + + + \ No newline at end of file diff --git a/coverage/src/utils/validation.ts.html b/coverage/src/utils/validation.ts.html index e135ba5..1ec34a7 100644 --- a/coverage/src/utils/validation.ts.html +++ b/coverage/src/utils/validation.ts.html @@ -300,35 +300,7 @@

All files / src/utils235 236 237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266

  +238        @@ -354,8 +326,6 @@

All files / src/utils1x     -  -  1x     @@ -390,9 +360,6 @@

All files / src/utils      -  -  -  3x 1x   @@ -433,8 +400,6 @@

All files / src/utils      -  -  1x     @@ -459,8 +424,6 @@

All files / src/utils1x     -  -  1x     @@ -471,9 +434,6 @@

All files / src/utils      -  -  -  4x     @@ -484,8 +444,6 @@

All files / src/utils2x     -  -  2x     @@ -496,9 +454,6 @@

All files / src/utils      -  -  -  3x 1x   @@ -507,8 +462,6 @@

All files / src/utils1x     -  -  1x     @@ -519,10 +472,6 @@

All files / src/utils      -  -  -  -  1x     @@ -568,8 +517,6 @@

All files / src/utils      -  -  2x 2x   @@ -587,11 +534,8 @@

All files / src/utils      -  -  -  -5x -5x +7x +7x    

/**
  * Input validation and sanitization utilities
@@ -616,9 +560,7 @@ 

All files / src/utilsAll files / src/utilsAll files / src/utilsIif ( - (upperQuery.includes("+ '") || - upperQuery.includes("+ \"") || - upperQuery.includes("$")) && + (upperQuery.includes("+ '") || upperQuery.includes('+ "') || upperQuery.includes("$")) && upperQuery.includes("MATCH") ) { // Note: This is a heuristic - legitimate queries may have these patterns @@ -721,9 +658,7 @@

All files / src/utilsAll files / src/utilsIif (typeof limit !== "number" && typeof limit !== "string") { throw new Error("limit must be a number or string"); } @@ -746,9 +678,7 @@

All files / src/utilsAll files / src/utilsAll files / src/utilsAll files / src/utilsAll files / src/utilsAll files / src/utils Code coverage generated by istanbul - at 2026-02-24T01:13:58.055Z + at 2026-02-27T23:25:35.933Z