Dart was added as the 14th supported language in PR #204 but the README
was not updated. Adds Dart row to the supported languages table and
updates the language count from 13 to 14.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(web): enable Cypher queries when connected to backend server
Route queries through HTTP API in backend mode instead of checking local WASM database.
Made-with: Cursor
* chore: add Maven/Gradle wrapper files to default ignore list
Add build wrapper scripts and directories to hardcoded ignore lists:
- Directories: .mvn, .gradle, gradle
- Files: mvnw, mvnw.cmd, gradlew, gradlew.bat
These are build infrastructure files, not source code.
Made-with: Cursor
* ci: re-trigger CI (Windows flaky timeout)
Made-with: Cursor
* feat: add more node types in filter panel
* feat: add more node types in filter panel
* revert additional changes
* test(web): add unit tests for filter panel node types
- FILTERABLE_LABELS: verify new types (Enum, Type, Decorator, Variable)
have colors, sizes, and no duplicates
- Filter panel icons: verify every filterable label has an icon mapped
and all icons are exported from lucide-icons
- Color legend: verify new types are included, ordered correctly, and
are a subset of FILTERABLE_LABELS
Made-with: Cursor
The shape-check-regression test uses withTestLbugDB but was running in
the default vitest project with parallel forks, causing LadybugDB
file-lock conflicts on Windows CI. Move it to the lbug-db project
(sequential execution) and exclude from default.
Follows up on #501.
* feat: add PHP response shape extraction for json_encode patterns
Adds extractPHPResponseShapes() to detect response keys from PHP
json_encode() calls with associative array literals. Supports:
- Short array syntax: json_encode(['key' => value])
- Long array syntax: json_encode(array('key' => value))
- Error classification via http_response_code() and header() status
- exit;/die; boundary detection to prevent cross-block status leaking
- Nested array filtering (only top-level keys extracted)
Pipeline integration dispatches PHP files to the new extractor.
Verified on collector project: 10 PHP routes now show responseKeys.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address review — exit boundary, die; offset, CGI Status header
- Replace lastIndexOf('exit;')/lastIndexOf('die;') with regex that
matches exit(N), exit(0), die('msg'), die($var) as boundaries
- Fixes die; off-by-one (was slicing at +5 for a 4-char keyword)
- Add header('Status: NNN') CGI/FastCGI format detection
- Add 3 regression tests for the fixed bugs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: extract shared helpers, remove duplicate test block
- Extract lastMatchGroup() and buildShapeResult() to eliminate repeated
patterns in both JS/TS and PHP extractors
- Simplify detectPHPStatusCode to use ?? chaining with lastMatchGroup
- Remove duplicate 9-test PHP describe block (kept the 12-test version)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add PHP response shape integration tests
Adds a PHP fixture (api/items.php, api/submit.php) with multiple
json_encode patterns and a pipeline integration test verifying:
- Route nodes created for PHP endpoints
- responseKeys/errorKeys correctly extracted and separated
- exit(N)/die() boundaries respected
- HANDLES_ROUTE edges point to correct PHP handler files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ci: E2E workflow, web typecheck job, pre-commit hook, test suite
CI:
- ci.yml consolidated to reference ci-tests.yml
- ci-quality.yml: add typecheck-web job for gitnexus-web/
- ci-e2e.yml: E2E workflow with dorny/paths-filter (web changes only)
- ci-report.yml: remove dead integration-reports references
- CI gate allows skipped E2E status
- .gitignore: playwright artifacts, eval test artifacts
Pre-commit hook:
- .githooks/pre-commit: typecheck + unit tests for both packages
- Activated via git config core.hooksPath in prepare script
Test infrastructure:
- Vitest + React Testing Library: 58 unit tests
(graph, server-connection, mermaid, settings, constants, utils, paths)
- Playwright E2E: 5 tests + manual recording harness
- vitest.config from vitest/config, engines.node >= 20
- Playwright artifacts retain-on-failure
- wait-on in devDependencies
- vitest/coverage-v8 aligned with vitest 4.x
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update gitnexus-web package-lock.json
Reflects devDependency additions (vitest, playwright, wait-on,
@testing-library, etc.) from package.json changes in this PR.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(e2e): add missing process-list-loaded testid, increase CI timeouts
- Add data-testid="process-list-loaded" to ProcessesPanel (E2E tests
were waiting for an element that didn't exist)
- Increase server connect timeouts from 5s to 10s for slower CI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ci): run gitnexus-web unit tests in CI, remove unused variable
- Add gitnexus-web npm ci + vitest run to ci-tests.yml so web unit
tests are gated by the CI status check (were only running locally)
- Remove unused IS_PLAYWRIGHT_AUTOMATION variable from E2E spec
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(e2e): add process-row testid, wait for networkidle on page load
- Add data-testid="process-row" to ProcessItem component (E2E tests
referenced it but it didn't exist in the source)
- Use waitUntil: 'networkidle' on page.goto to ensure Vite dev server
is fully ready before interacting (fixes first-test timeout in CI)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(e2e): add process-view-button and process-highlight-button testids
E2E tests referenced these data-testid attributes but they didn't
exist in ProcessItem. All 6 E2E testids now have matching source
elements: status-ready, process-list-loaded, process-row,
process-view-button, process-highlight-button, server-url-input.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(e2e): remove networkidle — Vite HMR WebSocket prevents it from resolving
networkidle waits for zero network activity for 500ms, but Vite's HMR
WebSocket stays open permanently, causing page.goto to timeout at 60s
on all tests after the first. The explicit toBeVisible waits on UI
elements are sufficient and deterministic.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(e2e): wait for Server button visibility, add CI retry, all 5 tests pass locally
Root cause: test 1 clicked the Server button before React hydrated,
so the tab content never rendered and the input wasn't found.
Fixes:
- Wait for Server button toBeVisible before clicking
- Increase input wait to 15s
- Remove networkidle (Vite HMR WebSocket prevents it from resolving)
- Add retries: 1 in CI for transient cold-start flakiness
Verified locally: all 5 E2E tests pass, 198 unit tests pass, typecheck clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ci): tolerate LadybugDB native crash during analyze step
gitnexus analyze can crash with "double free or corruption" (known
issue #273) during the LadybugDB native addon shutdown. The index is
usually written successfully before the crash. The workflow now:
1. Allows analyze to exit non-zero with a warning
2. Verifies .gitnexus index was actually created
3. Only fails if no index exists (real failure)
All tests verified locally: 198 unit, 5 E2E pass, typecheck clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ci): fix shell quoting in analyze step, simplify to || true
The previous echo string had special characters that broke bash
quoting in GitHub Actions. Simplified to: analyze || true, then
check if .gitnexus exists.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add agent development framework, GitHub templates, eval refactor
Agent framework (layered docs for AI-assisted contributions):
- AGENTS.md: canonical instructions, impact analysis, MCP tools
- CLAUDE.md: Claude Code-specific deltas and hooks
- GUARDRAILS.md: safety boundaries, non-negotiables, escalation
- ARCHITECTURE.md: monorepo layout, data flow map
- TESTING.md: test structure, commands, categories
- RUNBOOK.md: copy-paste operations for dev/CI/MCP
- llms.txt: minimal LLM context pointer
Editor integration:
- .cursor/index.mdc + rules/100-monorepo.mdc
GitHub templates:
- PR template with areas-touched checkboxes
- Bug report + feature request issue forms
Eval harness:
- Refactored mcp_bridge, tool_registry, constants
- Error sanitization utilities
- Property-based tests via Hypothesis
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(eval): use format_exception instead of format_exc in sanitize_exception
format_exc() returns the currently handled exception traceback, which
may be unrelated if called outside an active except block. Using
format_exception(type(exc), exc, exc.__traceback__) reliably captures
the passed exception's traceback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: update CONTRIBUTING.md and TESTING.md for current CI/hook setup
- CONTRIBUTING.md: add gitnexus-web typecheck command, pre-commit hook
checklist item
- TESTING.md: add gitnexus-web typecheck command, pre-commit hook
section (husky), update CI integration to list actual workflow files
(ci-quality, ci-tests, ci-e2e)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: update testing docs to reflect CI/E2E changes from PR #486
- AGENTS.md: update test counts (CLI ~2000 unit, ~1850 integration),
add gitnexus-web testing section (198 unit, 5 E2E with commands)
- RUNBOOK.md: fix Node requirement to >=20, fix E2E local repro command
- TESTING.md: E2E uses data-testid selectors + real servers, not mocks
- .cursor/rules/100-monorepo.mdc: add web test/E2E commands
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: address context engineering review — deduplicate tokens, expand Cursor rules
- Remove ~100-line gitnexus:start block from CLAUDE.md (was duplicated from AGENTS.md)
- Fix gitnexus:start block inlined inside AGENTS.md Reference Docs bullet (doubled)
- Replace CLAUDE.md scope table with pointer to AGENTS.md (single source of truth)
- Expand .cursor/index.mdc with 5 non-negotiable safety rules for always-on context
- Add .cursor/rules/200-eval.mdc with Python/eval commands (glob-scoped to eval/**)
- Improve llms.txt with priority annotations and descriptions
- Bump version headers to 1.2.0, last-reviewed to 2026-03-24
Saves ~1,400 tokens/session with zero information loss.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
- Add process.stdin.isTTY guard before --review prompt to prevent CI hangs
- Rename misleading --verbose e2e test to reflect it checks help output
- Replace DEBUG with GITNEXUS_VERBOSE for error stack traces
Made-with: Cursor
Spawn actual CLI process to verify:
- wiki --help surfaces all new flags
- wiki on non-git directory exits with code 1
- wiki on non-indexed repo fails with "No GitNexus index"
- --provider cursor skips API key prompt in non-TTY mode
- --verbose is accepted as valid flag
Made-with: Cursor
- Cache detectCursorCLI() result to avoid spawning `agent --version`
on every LLM call
- Fix stale JSDoc in cursor-client.ts (no longer uses stdin or
stream-json)
- Remove unused WikiOptions fields (model, baseUrl, apiKey) that were
passed but never read by WikiGenerator
- Fix inconsistent progress callback phase tracking in --review
continuation path
- Add wiki CLI help test covering --provider, --review, --verbose flags
Made-with: Cursor
Add Cursor headless CLI as a 4th provider option for wiki generation,
allowing users to leverage their Cursor subscription for wiki pages.
- Add --provider cursor flag and cursor-client.ts
- Add --review flag for interactive module tree editing
- Add --verbose flag for debugging
- Improve module tree generation (flatten single-child, unique slugs)
- Prevent DB timeout during long LLM calls
Usage: gitnexus wiki --provider cursor --model claude-4.5-opus-high
Made-with: Cursor
* refactor: SICP-informed LanguageProvider architecture for ingestion pipeline
Consolidate 16 scattered dispatch surfaces into a single LanguageProvider
Strategy interface per language. Processors are now fully language-agnostic —
zero SupportedLanguages.X enum access, zero dispatch table imports.
Architecture (5-layer DAG, zero circular dependencies):
L0: Capability modules (dispatch tables, single source of truth)
L1: LanguageProvider interface + createLanguageProvider factory
L2: 13 per-language provider files (Strategy objects)
L3: Registry with satisfies Record<SL, LP> + pre-built lookup maps
L4: Processors (language-agnostic, all behavior via provider.*)
Key changes:
- Add LanguageProvider interface with 15 properties (6 required, 9 optional)
- Create 13 provider files in languages/ + php-helpers.ts
- Migrate all processors to getProvider(language) — cached once per scope
- Replace heritage if-checks with provider.interfaceNamePattern/heritageDefaultEdge
- Replace MRO switch(language) with switch(provider.mroStrategy)
- Replace isNodeExported with provider.exportChecker
- Move PHP description extraction behind provider.descriptionExtractor
- Move Swift implicit imports behind provider.implicitImportWirer
- Move PHP route detection behind provider.isRouteFile
- Move Kotlin wildcard append behind provider.importPathPreprocessor
- Remove deprecated TypeEnvironment.env, add fileScope()/allScopes()
- De-export TypeEnv type (module-private)
- Pre-build extensionMap, WILDCARD_LANGUAGES, SYNTHESIS_LANGUAGES at load
- Remove dead entryPointPatterns/frameworkPatterns from interface
- Derive createLanguageProvider config type via Pick/Partial/Omit
- Tighten callback types from any to SyntaxNode
- Migrate 270+ test call sites from .env to TypeEnvironment API
Adding a new language: 3 files (enum + provider + registry line).
No processor file touched. Ever.
* refactor: clean architecture for LanguageProvider with O(1) AST cache
Address all PR #488 review comments and achieve pristine SICP layer separation:
Interface redesign:
- Split LanguageProvider into Config (input) + Provider (runtime with defaults)
- Rename createLanguageProvider → defineLanguage with explicit DEFAULTS constant
- Add MroStrategy, ImportSemantics named type aliases for better IDE tooltips
- Tighten labelOverride signature: string|null → NodeLabel|null (compile-time safety)
- Tighten descriptionExtractor nodeLabel: string → NodeLabel
- Un-export LanguageProviderConfig (internal to defineLanguage)
CI fixes (all 4 failures resolved):
- isNodeExported: add null guard for unknown languages
- preprocessImportPath tests: pass getProvider() instead of raw enum
- MRO tests: update expected strings to match language-agnostic prefixes
Code deduplication:
- Extract findDescendant/extractStringContent to ast-helpers.ts (single source of truth)
- Unify Kotlin method detection: remove duplicate from extractFunctionName,
use provider.labelOverride as single source of truth via findEnclosingFunctionId
- extractFunctionName return type: string → NodeLabel
Performance (O(1) AST node access):
- Add per-file Map-based memoization in parse-worker for parent-chain walks
- Cache enclosingClassId, enclosingFunctionId, exportStatus per SyntaxNode
- Clear caches before each file parse (not after — handles parse failures)
Architecture (pristine languages/ folder):
- Move php-helpers.ts → helpers/php.ts (L0 capability, not L2 config)
- Create helpers/swift.ts from extracted Swift provider logic
- Extract cppLabelOverride AST walk → isCppInsideClassOrStruct in ast-helpers.ts
- Extract isPhpRouteFile → helpers/php.ts
- All 13 provider files are now pure configuration — zero implementation logic
- Ruby: remove no-op namedBindingExtractor assignment (undefined from dispatch table)
* refactor: eliminate LANGUAGE_QUERIES, typeConfigs, namedBindingExtractors dispatch tables
Phase 1 of L0 dispatch table elimination. Providers now import capabilities
directly instead of indexing into redundant Record<SL, T> dispatch tables:
- LANGUAGE_QUERIES: providers import named query constants directly
(TYPESCRIPT_QUERIES, PYTHON_QUERIES, etc.). Table kept in tree-sitter-queries.ts
for call-processor.ts dynamic lookup + test consumers.
- typeConfigs: providers import from individual type-extractor files
(typescriptConfig from typescript.ts, javaTypeConfig from jvm.ts, etc.).
Dispatch table fully removed from type-extractors/index.ts.
- namedBindingExtractors: providers import extractors directly from
named-binding-extraction.ts (extractTsNamedBindings, etc.).
Dispatch table fully removed from import-resolution.ts.
Net: -48 LOC of dispatch table indirection. L3 satisfies Record<SL, LP>
remains the single exhaustiveness check.
* refactor: eliminate exportCheckers, callRouters, importResolvers dispatch tables
Phase 2 of L0 dispatch table elimination. All 6 dispatch tables are now gone:
- exportCheckers: individual checkers exported directly (tsExportChecker,
pythonExportChecker, etc.). isNodeExported uses a local checkersByLanguage
map to avoid circular dependency with languages/index.ts.
- callRouters: table removed. Providers import noRouting or routeRubyCall
directly. noRouting now exported. Dead import removed from call-processor.ts.
- importResolvers: resolver functions exported with clean names
(resolveTypescriptImport, resolveJavaImport, etc.). Inline lambdas
extracted to named exports. Dispatch functions renamed from *Dispatch
suffix to clean resolve*Import pattern.
Combined with Phase 1, all 6 L0 dispatch tables have been eliminated.
L3 satisfies Record<SL, LanguageProvider> is the single exhaustiveness check.
Providers are now fully self-contained — each imports its capabilities directly.
* perf+refactor: type-env caching, sequential fallback caching, utils.ts split
Phase 3 — performance optimizations and barrel cleanup:
Type-env parent-walk caching:
- Memoize findEnclosingClassName and findEnclosingParentClassName with
per-file Map<SyntaxNode, string|undefined> caches
- Eliminates O(n*m) repeated child scanning in extractParentClassFromNode
- Caches cleared in buildTypeEnv before each file's walk phase
Sequential fallback caching:
- Add classIdCache + exportCache Maps to parsing-processor.ts
- Mirrors the O(1) memoization pattern from parse-worker.ts
- Both paths now have identical caching for parent-chain walks
Split utils.ts barrel into focused modules:
- noise-filter.ts: BUILT_IN_NAMES + isBuiltInOrNoise (167 LOC)
- language-detection.ts: getLanguageFromFilename (58 LOC)
- utils.ts slimmed to re-exports + yieldToEventLoop + isVerboseIngestionEnabled
- Backward compatible — existing imports from utils.ts still work
* refactor: rename resolvers/ → import-resolvers/, restructure tests per-concern
Directory renames (git mv — history preserved):
- src/core/ingestion/resolvers/ → import-resolvers/ (10 files)
- test/unit/call-routing.test.ts → call-routing/ruby.test.ts
- test/unit/named-binding-extraction.test.ts → named-bindings/csharp.test.ts
- test/unit/import-resolution.test.ts → import-resolution/preprocessing.test.ts
All 11 import paths updated to reference new import-resolvers/ location.
Test imports updated for new subdirectory depth.
Note: test/integration/resolvers/ NOT renamed — those tests cover the full
ingestion pipeline per-language, not just import resolution.
* refactor: eliminate utils.ts barrel — all 33 consumers now import directly
Migrated 65 import sites across 33 files to import from the focused source
module instead of the utils.ts barrel:
- ast-helpers.js: SyntaxNode, extractFunctionName, findEnclosingClassId, etc.
- call-analysis.js: inferCallForm, extractReceiverName, countCallArguments, etc.
- noise-filter.js: BUILT_IN_NAMES, isBuiltInOrNoise
- language-detection.js: getLanguageFromFilename
utils.ts reduced to 2 original functions only:
- yieldToEventLoop
- isVerboseIngestionEnabled
Zero re-exports remain. Every import is now direct to its source module.
* refactor: create utils/ folder, move all shared utilities, delete utils.ts barrel
Final phase of module structure migration:
- git mv ast-helpers.ts, call-analysis.ts, noise-filter.ts,
language-detection.ts → utils/ subdirectory (history preserved)
- Extract yieldToEventLoop → utils/event-loop.ts
- Extract isVerboseIngestionEnabled → utils/verbose.ts
- Delete utils.ts (zero re-exports, zero functions remain)
- Update 38 import paths across source and test files
The ingestion/ root is now clean — only processors, capability modules,
and the pipeline orchestrator live at the top level. All shared utilities
are in utils/, all language-specific helpers in helpers/, all import
resolvers in import-resolvers/.
* refactor: move findChild from import-resolvers/utils.ts to utils/ast-helpers.ts
findChild is a generic AST helper (find first named child by type) — it
belongs with the other AST traversal utilities, not in the import resolver
module. 4 consumers updated to import from utils/ast-helpers.js.
* refactor: split named-binding-extraction.ts into per-language files
Rename named-binding-extraction.ts → named-binding-processor.ts (git mv,
history preserved), keeping only walkBindingChain for re-export chain resolution.
7 per-language extractor functions moved to named-bindings/ subdirectory:
- named-bindings/typescript.ts (extractTsNamedBindings — TS + JS)
- named-bindings/python.ts (extractPythonNamedBindings)
- named-bindings/kotlin.ts (extractKotlinNamedBindings)
- named-bindings/rust.ts (extractRustNamedBindings + collectRustBindings)
- named-bindings/php.ts (extractPhpNamedBindings)
- named-bindings/csharp.ts (extractCsharpNamedBindings)
- named-bindings/java.ts (extractJavaNamedBindings)
Each provider now imports its binding extractor from the per-language file.
* refactor: eliminate import-resolution.ts — distribute to natural homes
Split per-language resolvers into import-resolvers/ per-language files and
eliminate the import-resolution.ts catch-all module entirely:
Per-language resolvers moved to import-resolvers/:
- standard.ts: resolveStandard, resolveJavascriptImport, resolveTypescriptImport,
resolveCImport, resolveCppImport
- jvm.ts: resolveJavaImport, resolveKotlinImport
- go.ts: resolveGoImport
- csharp.ts: resolveCSharpImport (helper renamed to Internal)
- php.ts, python.ts, ruby.ts, rust.ts: same pattern
- swift.ts: new file for resolveSwiftImport
Types distributed to their concern directories:
- import-resolvers/types.ts: ImportResult, ImportConfigs, ResolveCtx, ImportResolverFn
- named-bindings/types.ts: NamedBinding, NamedBindingExtractorFn
preprocessImportPath moved to import-processor.ts (its primary consumer).
import-resolution.ts deleted — zero catch-all modules remain.
* refactor: tighten SPR — eliminate re-exports, dead code, type holes, and redundant patterns
12 review findings resolved across the ingestion layer:
Type safety:
- CallRouter callNode: any → SyntaxNode (closes type hole)
- CaptureMap type alias replaces Record<string, any>
- providersWithImplicitWiring filter now type-narrowed (removes ! assertions)
- Ruby exportChecker: unnecessary as-cast removed, named export created
Architecture:
- Circular type dependency eliminated (ImportResolutionContext moved to types.ts)
- LANGUAGE_QUERIES residual dispatch replaced with provider.treeSitterQueries
- noRouting sentinel deleted — callRouter now properly optional on 12 providers
- All 6 re-exports from import-processor/pipeline/languages eliminated
Pattern cleanup:
- Dead checkersByLanguage table + isNodeExported removed from export-detection
- 4 duplicated config interfaces consolidated to language-config.ts
- extractCsharpNamedBindings → extractCSharpNamedBindings (casing consistency)
Simplification:
- import-resolvers/index.ts barrel deleted (dead re-exports)
- helpers/ inlined into languages/ (php.ts, swift.ts) — 1 directory removed
Verified: tsc --noEmit clean, 3837 tests pass, 0 failures.
* refactor: address review — remove LANGUAGE_QUERIES table, type-extractors barrel, fix Windows timeout
Review comment fixes (github.com/abhigyanpatwari/GitNexus/pull/488#issuecomment-4117817648):
1. LANGUAGE_QUERIES dispatch table removed from tree-sitter-queries.ts
— 5 test files migrated to getProvider(lang).treeSitterQueries
— eliminates last parallel dispatch surface
2. type-extractors/index.ts barrel deleted
— type-env.ts now imports TYPED_PARAMETER_TYPES from shared.js directly
3. Windows CI timeout fix: afterAll cleanup hook in test-indexed-db.ts
now passes explicit 120s timeout to prevent KuzuDB C++ destructor
hang from hitting vitest's default 30s testTimeout on Windows
Verified: tsc --noEmit clean, 3835 tests pass, 0 failures.
* refactor: eliminate chained getProvider property access — assign to variable first
All getProvider(lang).property calls now follow the pattern:
const provider = getProvider(language);
const x = provider.property;
5 source files + 4 test files updated (~35 occurrences).
This ensures consistent provider variable usage and avoids
repeated lookups in hot paths.
* refactor: remove last 4 re-exports from import-resolvers, fix stale CaptureMap comment
- Remove `export type { TsconfigPaths }` from standard.ts
- Remove `export type { GoModuleConfig }` from go.ts
- Remove `export type { ComposerConfig }` from php.ts
- Remove `export type { CSharpProjectConfig }` from csharp.ts
All 4 types are canonically defined in language-config.ts;
zero consumers imported via the resolver re-exports.
- Fix stale CaptureMap JSDoc: said "Uses any" but type is SyntaxNode | undefined
Add GLM support using OpenAI-compatible API via ChatOpenAI from LangChain.
Defaults to the Z.AI coding endpoint (https://api.z.ai/api/coding/paas/v4)
with configurable base URL. Supported models: GLM-5, GLM-5-Turbo, GLM-4.7, GLM-4.5.
- Add ADD_TAGS: ['foreignObject'] to all DOMPurify.sanitize calls —
Mermaid uses foreignObject for HTML text labels inside flowchart
nodes. The SVG profile was stripping them, causing empty boxes.
- Remove leftover sub-batch loop lines from prepared statement hoist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- MarkdownRenderer: wrap handleLinkClick in useCallback, add to
markdownComponents useMemo deps (fixes stale closure)
- GraphCanvas: remove sigmaRef from useEffect deps (ref identity
never changes), extract handleToggleAIHighlights to useCallback
- CodeReferencesPanel: add nodeById Map for O(1) focus-in-graph
lookup (was O(N) graph.nodes.find on every click)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deep imports from lucide-react/dist/esm/icons/*.js are internal paths
that broke the Vercel production build. Replaced with standard named
re-exports from lucide-react — keeps the centralized module pattern
without relying on fragile internal paths.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hoists conn.prepare(cypher) outside the sub-batch loop so it's called
once per (fromLabel, toLabel) pair instead of ceil(N/4) times. The
statement is reused for all rows in the group, then closed in finally.
Yields to event loop every 500 relations instead of every sub-batch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- BackendRepoSelector, EmbeddingStatus, Header, MermaidDiagram,
QueryFAB, RightPanel, ToolCallCard, WebGPUFallbackDialog: switch
from lucide-react barrel imports to @/lib/lucide-icons deep imports
- MermaidDiagram: lazy-load ProcessFlowModal via React.lazy
- Extract ProviderConfigCard from SettingsPanel for cleaner separation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Performance:
- nodeById Map in GraphCanvas for O(1) click/hover lookups
- fileNodeByPath Map in useAppState for O(1) file path lookups
- Set.has() for HIGHLIGHT_NODES/IMPACT matching (was O(N²))
- useMemo for primaryLanguage in StatusBar
- useCallback on toggleLabelVisibility/toggleEdgeVisibility
- Recursive FileTreePanel search (full subtree, not 1 level)
React fixes:
- Remove stale queryResult dep from clearAICodeReferences
- Cancel RAF chains in CodeReferencesPanel on cleanup
- Clean up timeouts in SettingsPanel and MarkdownRenderer on unmount
- try/catch on localStorage in DropZone (private browsing)
- Await handleServerConnect in App.tsx auto-connect
- pendingToolCalls counter replaces allToolsDone boolean in agent.ts
- JSON.parse try/catch in agent streaming
- sessionStorage JSDoc fix in settings-service
Bundle:
- Centralized lucide icon deep imports
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mermaid uses foreignObject for HTML text labels inside flowchart
nodes. The SVG profile strips them by default, causing empty boxes.
ADD_TAGS: ['foreignObject'] preserves text while still sanitizing
against XSS.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add NODE_COLORS and NODE_SIZES entries for all 15 multi-language labels
(Struct, Trait, Impl, TypeAlias, Const, Static, Namespace, Union,
Typedef, Macro, Property, Record, Delegate, Annotation, Constructor,
Template) — fixes Record<NodeLabel, ...> completeness
- Escape table names in count/lookup queries with escapeTableName() to
prevent silent failures for backtick-required tables
- Add HAS_PROPERTY and ACCESSES to RelationshipType union
- Update initPromise after db recreation in loadGraphToLbug so subsequent
initLbug() calls return fresh db/conn refs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ProcessFlowModal: revert import from non-existent @/lib/lucide-icons back to lucide-react
- embedding-pipeline: remove extra argument in executeQuery call (signature only accepts 1 arg)
Both issues were introduced in PR #475 (web-security-hardening).
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- empty graph produces header-only CSVs (no data rows)
- empty graph relCSV has only header
- double quotes in node names are RFC 4180 escaped
- file node without fileContents gets empty content (no crash)
- community with empty keywords array produces valid CSV
- unknown node labels are silently skipped
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>