Commit Graph
89 Commits
Author SHA1 Message Date
Martin Vogel bdfdda67c4 Fix 10 mechanical NOLINTNEXTLINE suppressions (Phase 4)
- pass_infrascan.c: split assign-in-if for 5 secret detection patterns
- compat_fs.c: remove dead NOLINTNEXTLINE (check globally disabled)
- cli.c: add 10MB safety cap on tainted allocation size
- lz4_store.c: keep unity build, disable check globally
- sqlite_writer.c: rename confusable identifier vl -> vlen

494 -> 4 NOLINTs remaining (all god-function complexity/size).
2026-03-31 20:04:11 +02:00
Martin Vogel f26acd4ced Eliminate NOLINTNEXTLINE suppressions + iterative AST walkers
Remove ~480 dead per-line NOLINTNEXTLINE comments. Update .clang-tidy with
documented upstream bug references for disabled checks.

Convert key AST walkers to iterative with explicit stacks: walk_defs (with
context-aware stack frames for class nesting), walk_throws, walk_readwrites,
walk_calls, walk_usages, walk_env_accesses, extract_elixir_call, glob_match,
cbm_yaml_free, rmdir_recursive, resolve_func_name, walk_variables_iter,
count_branching. Reversed child push for left-to-right traversal.

Disable readability-implicit-bool-conversion globally — designed for C++,
flags all idiomatic C patterns (bool = x && y) with no config to allow them.

Fix clang-format, implicit-bool edge cases, add test_helpers.h.
2026-03-31 20:04:11 +02:00
Martin Vogel 88fea661bc Fix prefix-decorator false positives + HCL infra binding extraction
Prefix-to-decorator bridge now matches by file path segments: prefix
"/bq/bulk/ranked" only connects to handlers in paths containing
"bq/bulk/ranked", not all handlers in the service.

HCL infra binding extraction: scan resource blocks for attribute pairs
with source keys (topic, queue_name) and target keys (uri, push_endpoint).
Handles nested blocks (push_config { push_endpoint = "..." }).
2026-03-31 20:04:11 +02:00
Martin Vogel 1c7b0a4d6c Pure AST decorator route extraction + end-to-end DATA_FLOWS
Extract route_path and route_method directly from decorator AST nodes
during tree-sitter walk. Route + HANDLES edges created during
definition node creation. ensure_decorator_routes pass recreates
Route+HANDLES for existing nodes in incremental mode.

Prefix Routes bridged to handler Functions by service directory matching.
2026-03-31 20:04:11 +02:00
Martin Vogel afba50e018 Generalized route registration + infra binding bridge
Route registration detection now works for unresolved local variables
(app.include_router, app.mount) by matching callee name suffix when
QN resolution fails. Scans ALL arguments for URL paths — handles
prefix=, path=, route= keyword args across frameworks.

New route_reg_suffixes: include_router, mount, add_url_rule,
register_blueprint, use, register, add_route, add_api_route.

Infrastructure bindings: YAML/JSON extraction captures topic→URL
pairs from subscription configs (push_endpoint, uri). Creates
INFRA_MAPS edges linking async topic Routes to endpoint URLs.

Improved match_infra_routes: matches prefix Routes from include_router,
supports service-only matching for generic "/" handlers, correct
Cloud Run hostname parsing for new project-number format.
2026-03-28 18:36:14 +01:00
Martin Vogel 85c6c6f00c Fix B-tree sep_cell leak in sqlite_writer + CI test timing
sqlite_writer.c pb_build_interior: final root-level sep_cell
allocations were not freed. Each cbm_write_db call leaked 84 bytes.
Detected by ASan on Linux CI with 155 incremental test iterations.

Also fix CI timing: use MAX_TOOL_MS (15s) for perf assertions,
skip timing on full re-index operations (CI runners are slower).
2026-03-28 16:15:25 +01:00
Martin Vogel 17db27adfa Schema properties, DATA_FLOWS, YAML nested extraction, trace_path tool
- Serialize return_type, parent_class, base_classes on definition nodes
- DATA_FLOWS edges link callers through Route nodes to handlers
- YAML nested field extraction with dotted key paths (key_path property)
- Rename trace_call_path → trace_path with mode parameter:
  calls (default), data_flow, cross_service
- Backward compatible: trace_call_path alias still accepted
- Updated CLI help text and all tests
2026-03-28 13:59:42 +01:00
Martin Vogel b5e288a640 Argument-to-parameter mapping + field access chains (Phase B2+B3)
CBMCallArg struct captures up to 8 arguments per call with expression
text, resolved constant values, keyword names, and positional index.
Member expressions produce dotted chain expressions automatically.

Serialized as "args" array on CALLS, HTTP_CALLS, ASYNC_CALLS, and
CONFIGURES edge properties. Enables data flow tracing across function
and service boundaries.
2026-03-28 13:59:42 +01:00
Martin Vogel ec70bfd76f Serialize param_names/param_types to graph properties (Phase B1)
Function/Method nodes now include param_names and param_types arrays
in their properties JSON. Data was already extracted by tree-sitter
but not serialized.

- append_json_str_array helper replaces inline decorator serialization
- build_def_props in both pass_parallel.c and pass_definitions.c
- extract_param_names: add Python default_parameter, typed_default_parameter,
  bare identifier node types
- Sample project: 114 Python functions now have param_names
- Zero extraction overhead, ~3MB more in properties for large projects
2026-03-28 13:59:42 +01:00
Martin Vogel b00e1f74c2 AST-based route registration + remove prescan infrastructure
Route registration detection during AST extraction: callee QN matched
against router frameworks (gin, chi, Express, Laravel, Ktor, etc.),
handler reference captured as second_arg_name, Route + HANDLES edges
created during resolution. Replaces disk-reading route discovery for
non-decorator frameworks.

Remove prescan infrastructure entirely (-350 net lines):
- cbm_prescan_t, cbm_prescan_http_site_t, cbm_prescan_route_t,
  cbm_prescan_config_ref_t structs removed from pipeline_internal.h
- prescan_http_sites, prescan_routes, prescan_config_refs,
  prescan_add_route removed from pass_parallel.c
- prescan fast-paths removed from pass_httplinks.c and pass_configlink.c
- prescan allocation/cleanup removed from pipeline.c

All post-passes now work without prescan:
- HTTP/async edges: service_patterns during resolution
- Route registration: CBM_SVC_ROUTE_REG during resolution
- Decorator routes: gbuf properties (no disk reads)
- Config file refs: disk fallback (few files)
2026-03-28 13:59:42 +01:00
Martin Vogel 80680ea367 Cross-service communication discovery + RAM-first incremental indexing
AST-based detection of HTTP calls, async dispatch (Pub/Sub, Cloud Tasks,
Kafka, SQS, etc.), and config accesses via resolved qualified names.
Route nodes as cross-service rendezvous points with infra→handler matching.
Constant propagation for module-level string assignments. YAML infrastructure
URL extraction from Cloud Scheduler configs.

RAM-first incremental pipeline: load DB into graph buffer, purge changed
file nodes, extract directly into existing buffer (resolver sees all nodes),
dump back to disk. Zero edge gap on kubernetes/django/meilisearch/neovim.

- service_patterns.c: ~170 library patterns (90 HTTP, 50 async, 30 config)
- pass_route_nodes.c: Route node creation + infra URL matching
- extract_unified.c: string constant collection + string ref classification
- extract_calls.c: first_string_arg + keyword argument extraction
- pipeline_incremental.c: RAM-first load→purge→extract→resolve→dump
- graph_buffer.c: load_from_db, delete_by_file, foreach visitors
- C++ LSP crash fix: NULL guard in cbm_type_substitute
2026-03-28 13:59:42 +01:00
Martin Vogel 007980c0eb Fix C++ SEGV: NULL deref in LSP type resolver on large header files
Root cause: c_eval_expr_type_inner has 42 places accessing ptr->kind
on CBMType* pointers. Some code paths (cbm_type_substitute, internal
lookups) return NULL on unusual C++ AST shapes (deeply nested
templates, 300+ defs per file). NULL->kind = SIGSEGV.

Fix: safe_kind() inline returns CBM_TYPE_UNKNOWN for NULL pointers.
All 42 ->kind accesses in c_eval_expr_type_inner replaced.
Also: recursion depth guard (256), cbm_type_substitute returns
cbm_type_unknown() for NULL input, walk_usages/walk_env depth limits.

Verified: spdlog (previously crashed) now indexes 2526 nodes, 5518 edges.
All 2586 tests pass.
2026-03-26 16:19:10 +01:00
Shane McCarron 178bea2cd8 fix(cbm): convert 7 O(N²) import extractors to O(N) TSTreeCursor iteration (#131)
Fixes #130
2026-03-24 23:12:18 +01:00
Martin Vogel 605cd92c77 Merge branch 'main' into fix/parse-imports-quadratic 2026-03-23 16:03:17 +01:00
Shane McCarronandClaude Sonnet 4.6 2af9e60738 fix(cbm): replace O(N²) indexed loop with O(N) cursor in parse_generic_imports
ts_node_child(root, i) and ts_node_next_sibling() both call
ts_node_child_with_descendant() internally, making sibling iteration
O(N²) total on roots with many children (e.g. generated TypeScript
.d.ts files or large Perl files with 5,000–50,000 top-level nodes).

Replace with TSTreeCursor: ts_tree_cursor_goto_next_sibling() maintains
traversal state across calls and is O(1) per step, reducing total
complexity from O(N²) to O(N).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 13:10:51 -05:00
Shane McCarronandClaude Sonnet 4.6 94841e0542 fix(k8s): address QA round 1 findings
- [Major 1+2] pass_k8s: always re-extract K8s manifests with CBM_LANG_K8S,
  discarding any cached YAML result; pass already-read source buffer to
  handle_k8s_manifest to eliminate the double file read
- [Minor 3] CONTRIBUTING.md: fix extractor path to internal/cbm/extract_k8s.c
  and clarify tree-sitter YAML grammar usage
- [Minor 4] language.c: add comment documenting intentional case-sensitive
  FILENAME_TABLE and case-insensitive cbm_is_kustomize_file() split behaviour
- [Minor 5] test_pipeline.c: add k8s_extract_manifest_multidoc test pinning
  single-document-per-file extraction behaviour
- [Minor 6] pass_infrascan: replace strlen with strnlen(content, 4096) in
  cbm_is_k8s_manifest to bound the scan
- [Minor 7] extract_k8s: add "crds" to is_kustomize_list_key
- [Nit 8] extract_k8s: remove dead second block_node unwrap in
  extract_k8s_scalars metadata descent
- [Nit 10] extract_k8s: use cbm_arena_strdup for def.label "Resource"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 09:29:22 -05:00
Shane McCarronandClaude Sonnet 4.6 e696fcdf80 style(k8s): apply clang-format to k8s and infra-pass source files
- Fix alignment violations in extract_k8s.c, pass_k8s.c, pass_infrascan.c
- Fix spacing in language.c filename table rows (kustomization.yml entry)
- Fix alignment in cbm.h CBMLanguage enum comments
- Fix pipeline.c empty-body brace style

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 09:29:22 -05:00
Shane McCarronandClaude Sonnet 4.6 337694dc65 test(k8s): tests for detection helpers, extractors, and pipeline pass
- Add TEST(infra_is_kustomize_file): positive/negative/NULL cases
- Add TEST(infra_is_k8s_manifest): apiVersion present/absent, kustomize
  file returns false, NULL guards
- Add TEST(k8s_extract_kustomize): asserts 2 imports (deployment.yaml,
  service.yaml) from Kustomization resources list
- Add TEST(k8s_extract_manifest): asserts Resource def with label
  "Resource" and name containing "Deployment"
- Add TEST(k8s_extract_manifest_no_name): no crash, has_error==false
- Fix extract_k8s.c get_scalar_text() to unwrap flow_node wrappers
  (tree-sitter YAML grammar wraps plain_scalar in flow_node)
- Fix pass_k8s.c missing #include "foundation/compat.h" for CBM_TLS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 09:29:22 -05:00
Shane McCarronandClaude Sonnet 4.6 88ddb63e8b feat(k8s): K8s and Kustomize YAML extractors in the CBM layer
- lang_specs.c: add LangSpec entries for CBM_LANG_KUSTOMIZE and CBM_LANG_K8S
  (both reuse tree_sitter_yaml()); add cbm_ts_language() switch cases
- extract_k8s.c: new file implementing cbm_extract_k8s(); kustomize path
  walks block_sequence items under resources/bases/patches/components/
  patchesStrategicMerge and emits CBMImport per scalar; k8s path extracts
  apiVersion/kind/metadata.name and emits CBMDefinition with label "Resource"
  and name "Kind/metadata-name"; malformed manifests (missing kind or name)
  produce zero definitions
- cbm.h: declare cbm_extract_k8s() alongside other sub-extractor entry points
- cbm.c: call cbm_extract_k8s() after unified extraction for the two new langs
- Makefile.cbm: add extract_k8s.c to EXTRACTION_SRCS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 09:29:22 -05:00
Shane McCarronandClaude Sonnet 4.6 ee769d5806 feat(k8s): detection helpers, CBMLanguage enum, and language table entries
- Add CBM_LANG_KUSTOMIZE and CBM_LANG_K8S to CBMLanguage enum (before CBM_LANG_COUNT)
- Add kustomization.yaml/yml to FILENAME_TABLE mapped to CBM_LANG_KUSTOMIZE
- Add Kustomize and Kubernetes entries to LANG_NAMES
- Implement cbm_is_kustomize_file() with to_lower+strcmp pattern
- Implement cbm_is_k8s_manifest() scanning first 4KB for apiVersion: via ci_strstr()
- Declare both helpers in pipeline_internal.h Infrascan helpers section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 09:29:22 -05:00
Martin VogelandJay Sync c66d88745d Fix Swift call extraction: 0 CALLS edges (#43)
Swift tree-sitter grammar uses positional children (not named fields) for
call_expression, so extract_callee_name() returned NULL for every call.

- extract_calls.c: Swift-specific callee extraction via first named child
  for call_expression and constructor_expression nodes
- lang_specs.c: add constructor_expression to swift_call_types
- 4 new C tests: simple calls, method calls, constructors, chained calls

Co-Authored-By: Jay Sync <63868998+jay-sync@users.noreply.github.com>
2026-03-20 14:46:46 +01:00
Martin Vogel 85fc74fc31 Full Windows portability: proper implementations, not stubs
- handle_processes: GetProcessMemoryInfo + GetProcessTimes (Windows),
  getrusage (POSIX) — real process metrics on both platforms
- handle_process_kill: TerminateProcess via OpenProcess (Windows),
  kill(SIGTERM) (POSIX)
- index_thread_fn: CreateProcess + WaitForSingleObject (Windows),
  fork+exec+waitpid (POSIX)
- cbm_clock_gettime: QueryPerformanceCounter (Windows) — replaces
  all bare clock_gettime calls across 6 files
- cbm_nanosleep, cbm_strcasestr, cbm_mkdir: compat shims
- CBM_TLS: _Thread_local (C11 standard, works on all compilers)
- Replace bare strndup with cbm_strndup, guard POSIX headers
- Add mingw-w64 cross-compile to Docker test infrastructure
2026-03-18 18:47:43 +01:00
Martin Vogel a1d849aaaa Fix all memory leaks, vendor sqlite3, add Docker test infrastructure
Leak fixes (13 sources, 1.4MB → 0 bytes):
- Cypher: free col_names after rb_set_columns, free rejected inline
  prop nodes, store WITH aliases in qualified_name for auto-cleanup
- Store: add cbm_project_free_fields, fix find_node_ids_by_qns leak
- Graph buffer: free strdup'd hash keys during delete operations
- SQL scanner: free old start_tag before reassignment in deserialize

Platform independence:
- Vendor sqlite3 amalgamation (3.49.1) — eliminates system libsqlite3
  dependency, enables full ASan/LeakSanitizer instrumentation
- Add -I for vendored tree-sitter unicode headers — eliminates hidden
  dependency on system libicu-dev
- Add test-infrastructure/ with Docker Compose for local GCC+ASan
  testing that mirrors CI exactly
2026-03-18 16:28:27 +01:00
Martin Vogel c9ec1d1eb4 Fix Ubuntu CI: stack-use-after-return, L2 cache detection, memory leaks
- Arena-allocate pair_field_types in cpp_stdlib_data.c (was stack array
  escaping scope via registry pointer — caught by GCC ASan)
- Add sysfs fallback for L2 cache on Linux ARM (sysconf returns 0)
- Expose cbm_node_free_fields() and fix 12+ leak sites in tests where
  find_node_by_id/qn results were never freed (caught by LeakSanitizer)
2026-03-18 14:23:46 +01:00
Martin Vogel 4f3f2f4b22 Fix UBSan: guard cbm_type_is_unknown against misaligned dangling pointers 2026-03-18 00:42:12 +01:00
Martin Vogel 18fa9979ee Replace vmem with mimalloc global allocator, add extraction-phase prescan, fix __init__.py QN collision
Memory management:
- Vendor mimalloc v2.1.9 as global allocator (MI_OVERRIDE=1 in prod)
- New mem.h/mem.c: RSS-based budget tracking via mi_process_info()
- Remove vmem.c/vmem.h (mmap-based budget tracking)
- Remove slab tier2 bump allocator (~300 LOC); >64B goes to mimalloc
- Slab tier1 pages from malloc (= mimalloc) instead of vmem
- Arena blocks from malloc instead of vmem
- Budget raised from 35% to 50% RAM (no more untracked C++ heap)

Extraction-phase prescan (eliminates disk re-reads):
- HTTP call sites: keyword check + URL extraction during extraction
- HTTP routes: decorator + source-based extraction during extraction
- Config file refs: regex scan during extraction
- httplinks: 41.8s → 13ms on Linux kernel (3,212x faster)
- configlink: 41.4s → 0.8s on Linux kernel (54x faster)
- Linux kernel fast-mode total: 2m38s → 1m18s

Bug fixes:
- __init__.py Module QN no longer collides with Folder QN
- index.ts same fix for JS/TS packages
- 13 regression tests for QN collision at FQN + extraction layers
- search_graph/search_code default limit raised from 10 to 500k
- Resolve all clang-tidy, cppcheck, and clang-format warnings

Repo cleanup:
- tree-sitter-form, tree-sitter-magma moved to tools/
- .gitignore: build/, node_modules/, graph-ui/dist/, TEST_PLAN.md
2026-03-17 22:05:57 +01:00
Martin Vogel 0d216c7936 Resolve all clang-tidy, cppcheck, and clang-format warnings across 94 files
Enforce WarningsAsErrors: '*' with zero suppressions of entire check categories.
All non-FP warnings fixed at source; true false positives get per-instance NOLINT
with reasoning. Fixes include: braces around statements (1679), isolate declarations
(75), explicit casts for multilevel pointer conversions, missing includes, function
parameter documentation via NOLINT, and proper NOLINTBEGIN/NOLINTEND nesting.
2026-03-15 22:37:34 +01:00
Martin Vogel 6f0910278b Remove all Go code — project is now pure C
Delete Go MCP server, CGo bridges, Go pipeline, store, tools, watcher,
cypher engine, language specs, and all Go tests. Replace Go pre-commit
hook with C-only linting (clang-tidy, cppcheck, clang-format, tests).
Tree-sitter extraction engine (internal/cbm/*.c) retained for C pipeline.
2026-03-15 20:32:19 +01:00
Martin Vogel 94a9a92f83 Add C-native pipeline with blocking clang-tidy, cppcheck, clang-format linting
Complete C implementation of the indexing pipeline (src/), parallel worker
pool, graph buffer with merge support, SQLite writer, and 1893-test suite.

Linter setup: zero warnings from clang-tidy (all checks enabled, no NOLINT
suppressions), cppcheck, and clang-format. All issues fixed at source —
proper headers for external linkage, GROW_ARRAY macro restructured to
eliminate type parameter, null-deref paths guarded, named intermediates
for suspicious-argument checks.
2026-03-15 19:26:12 +01:00
Martin Vogel f85a4e1c14 RAM-first pipeline with fused C LZ4 + Aho-Corasick multi-pattern matching
Full indexing now runs entirely in RAM:
- One filepath.Walk, one bulk file read (LZ4 HC compressed sourceStore)
- In-memory SQLite for all passes, single Backup API dump at end
- Source access via C LZ4 decompression (~3μs per file, 5.7 GB/s)

Aho-Corasick engine (internal/cbm/ac.c):
- Custom ACISM automaton with bitmask output (≤64 patterns)
- Fused LZ4 decompress + AC scan in C-side thread-local buffer
- Batch API: single CGo call scans all files (ScanLZ4Batch)
- Compact alphabet mode for configlinker (38-char table)

Pipeline optimizations:
- httplinks: AC pre-screens files for HTTP client + route keywords
- configlinker: AC batch scan replaces O(n×m) substring matching
- Infrascan/envscan: iterate sourceStore keys instead of walking disk
- All source reads via getSource() (LZ4 decompress from RAM)
- File hashes pre-computed during bulk load (zero re-reads)
2026-03-14 10:42:34 +01:00
Martin Vogel 522bd5b1fd Expand C/C++ LSP resolver: template substitution, smart pointer chains, 700+ tests
Major improvements to the C/C++ type-aware call resolver:

- Template argument substitution for qualified calls (std::get<T>, std::any_cast<T>,
  std::make_shared<T>) — strip template args from AST, substitute TYPE_PARAMs in
  return types, wrap NAMED→TEMPLATE for downstream smart pointer deduction
- Smart pointer deref uses suffix matching (handles module-prefixed QNs like
  "test.main.std.shared_ptr")
- Fix storage_class_specifier/type_qualifier skipping in c_parse_declaration_type
  (static/const/virtual methods now get correct return types)
- Scope-aware alias resolution in c_resolve_name_to_type (typedef/using)
- Template namespace fallback in c_parse_type_node (resolve types within
  current namespace during template class pre-pass)
- Pending template call resolution emits with correct caller QN
- Add ~330 new tests covering C++17 (structured bindings, if-init, CTAD, optional),
  C++20 (coroutines, concepts, ranges), heavy templates, real-world patterns
  (smart pointers, iterators, RAII, factories), STL completeness, and C patterns
2026-03-13 19:47:36 +01:00
Martin Vogel d201a5faa6 Close C/C++ LSP gaps: overload scoring, lambda/decltype inference, virtual dispatch
Type system improvements:
- Overload resolution by parameter type (score_overload_match with type compatibility)
- Lambda return type inference (trailing return type + shallow body walk)
- Inline namespace normalization (strip __1, __cxx11, __gnu_cxx)
- Implicit conversions in overload scoring (const char* → string, numeric promotions)
- Virtual dispatch: prefer derived override over base method
- CRTP detection: template param → derived class mapping
- Range-for iterator protocol: map element fix + begin()/operator*() fallback
- Default argument support via min_params range matching
- Free function auto deduction: identifier eval order fix (function before type)
- decltype() return type parsing in c_parse_return_type_text
- Trailing return type syncs both return_type and return_types array
2026-03-13 00:49:42 +01:00
Martin Vogel a8daedf759 Add C/C++ hybrid LSP resolver with type-aware call resolution
Implement a tree-sitter-based type evaluator for C/C++ that resolves
method calls, template instantiations, and cross-file references without
requiring a full compiler. Covers ~95% of C and ~93% of moderate C++.

Key features:
- Type-aware overload resolution scoring by parameter types
- Lambda return type inference (trailing return + body deduction)
- Inline namespace normalization (__1, __cxx11, __gnu_cxx)
- Implicit conversions (char*->string, numeric promotions)
- Virtual dispatch with override preference
- CRTP detection and self-type resolution
- Range-for iterator protocol (maps, custom containers)
- Smart pointer arrow dispatch (unique_ptr, shared_ptr)
- Dependent member calls in templates via pending call resolution
- Explicit template argument substitution (make_shared<T>)
- Nested class scope resolution
- C/C++ stdlib type stubs (containers, strings, I/O, smart ptrs)
- Cross-file LSP with compile_commands.json support
- C/C++ parameter extraction via declarator chain traversal

63+ test cases covering all resolution strategies.
2026-03-13 00:07:28 +01:00
Martin Vogel 0c80a37b08 Replace scan-all watcher with explicit watch list to fix #49 OOM
Watcher no longer polls every indexed project via ListProjects(). Instead,
projects are added to an explicit watch list on index/auto-index and removed
on delete. Cross-project tool calls (search_graph, trace_call_path, etc.)
touch the watch list so referenced projects stay fresh.
2026-03-12 16:18:44 +01:00
Martin Vogel fac0c57359 Fix stability: SQLite lock race, stale SHM recovery, OOM guard, CPU reduction
- Fix ref counting race in ListProjects and watcher pollAll: use AcquireStore
  instead of ForProject to prevent evictor from closing stores mid-query (#52)
- Add recoverStaleSHM: remove stale SHM files after SIGKILL to prevent
  deadlock on next connection (#52)
- Increase busy_timeout from 5s to 10s for large databases (#52)
- Default GOMEMLIMIT to 2GB when not configured, preventing unbounded
  memory growth and OOM kills (#49, #46)
- Reduce mmap_size from 256MB to 64MB per database (#49, #46)
- Increase watcher base interval from 1s to 5s and poll interval base
  from 1s to 5s, reducing CPU usage by ~5x (#45)
- Normalize Windows drive letter to lowercase in ProjectNameFromPath,
  preventing duplicate databases for same path (#50)
2026-03-12 15:06:20 +01:00
Martin Vogel 74546edb18 Fix heap-buffer-overflow in Swift tree-sitter scanner
The Swift external scanner called calloc(0, sizeof(ScannerState)) which
returns a 0-or-1-byte allocation per the C standard. The scanner then
writes a uint32_t (4 bytes) to this region via state->ongoing_raw_str_hash_count,
causing a heap-buffer-overflow detected by AddressSanitizer.

Fix: calloc(0, ...) → calloc(1, ...).
2026-03-12 14:03:39 +01:00
Martin Vogel 4fe90cabd8 Fix file handle leak in gitignore loading for Windows compatibility
Replace the go-gitignore library's NewRepository (which opens .gitignore
files via os.Open but never closes the handles) with a custom repoMatcher
that reads files via os.ReadFile and passes strings.NewReader to the
library's New() function. This ensures all file handles are closed
immediately after reading.

The library's ignore.Relative() pattern matching is preserved — only the
hierarchy walker and file loading are reimplemented. The matching algorithm
follows standard git precedence: child .gitignore overrides parent,
negation patterns in child override matching patterns in parent, and
.git/info/exclude is checked last.

Fixes Windows CI where leaked handles prevented t.TempDir() cleanup.
2026-03-12 13:47:51 +01:00
Martin Vogel bd6bbc2ab1 Add Go LSP hybrid type resolver, config store, and supporting infrastructure
- Go LSP cross-file type resolution engine (internal/cbm/lsp/) with C-based
  type registry, scope tracking, and Go stdlib data (30K+ definitions)
- lsp_bridge.go: CrossFileDef struct and RunGoLSPCrossFile CGo bridge
- config.go: persistent ConfigStore (SQLite) for auto_index, mem_limit settings
- CLI config subcommand for get/set/list/delete operations
- Store: edge batch upsert, project config columns, goleak test harness
- Pipeline: prefetch parallelism, resolver improvements, memleak tests
- CI: dry-run workflow improvements, vendor-grammar.sh enhancements
2026-03-12 13:26:13 +01:00
Martin VogelandHarry Chan c4848a89aa Fix: respect explicit LIMIT in Cypher query_graph
applyLimit() silently capped all results to maxRows (default 200), even
when the user specified a higher LIMIT clause. This caused queries like
MATCH (f:Function) RETURN f.name LIMIT 500 to return only 200 rows,
and COUNT() aggregations to silently undercount on large datasets.

Now explicit LIMIT values from Cypher are respected as-is. The 200-row
default still applies when no LIMIT clause is provided.

Incorporates the fix from PR #40 by @re-thc.

Co-authored-by: Harry Chan <38070640+re-thc@users.noreply.github.com>
2026-03-12 13:05:53 +01:00
Martin Vogelandwassertim 342ff5a27f Skip .worktrees directory during indexing
Git worktrees (stored in .worktrees/) duplicate the entire source tree,
causing the knowledge graph to contain duplicate nodes and edges for
every function, class, and route. Add .worktrees to IGNORE_PATTERNS
alongside .git and .svn.

Incorporates the fix from PR #37 by @wassertim. Closes #31 (partial).

Co-authored-by: wassertim <wassertim@gmail.com>
2026-03-12 13:02:02 +01:00
Martin Vogel d8df2be5dc Respect .gitignore, add .cbmignore support, skip symlinks, expand ignore list
- Parse full .gitignore hierarchy (nested files + .git/info/exclude) via
  boyter/gocodewalker go-gitignore library for git repos
- Add .cbmignore as repo-root gitignore-style file that stacks on top of
  .gitignore for indexer-specific exclusions (e.g. generated code in git)
- Skip symlinked files and directories to prevent duplicate indexing
- Move bin/, build/, out/ from always-on IGNORE_PATTERNS to fast-mode-only
  (prevents false exclusions in Go, CMake, Maven projects)
- Add 28 ecosystem-specific cache/artifact dirs to IGNORE_PATTERNS:
  .next, .nuxt, .svelte-kit, .angular, .turbo, .terraform, bazel-bin,
  zig-cache, .cargo, .stack-work, elm-stuff, .metals, .bloop, etc.
- Keep .cgrignore for backward compatibility
- 17 new tests: gitignore patterns, negation, globstar, nested, exclude file,
  non-git repos, dir-only, cbmignore stacking, symlinks, pattern changes
2026-03-12 12:57:55 +01:00
Martin Vogel a208b34c8b Fix all golangci-lint issues across the codebase
- watcher_test.go: add mustWriteFile/mustMkdirAll helpers for errcheck (26 fixes),
  use exec.CommandContext for noctx
- watcher.go: remove unused projectsCacheTTLValue, fix nilerr in WalkDir callbacks,
  name return values on checkSentinel, fix gofmt
- executor.go: rename shadowed builtin 'cap' to bindingCap/stepCap
- pipeline.go: extract runPostFlushPasses (funlen), extract collectEdgeQNs/
  createLSPStubNodes/buildEdgesFromResults from flushResolvedEdges (gocognit)
- pipeline_cbm.go: extract runGoLSPCrossFileResolution/collectLSPResolvedEdges/
  resolveCallEdge (gocognit, nestif), fix gofmt
- go_dep_registry.go: extract extractFuncDef/extractTypeDefs/extractStructEmbeds
  (gocognit), preallocate retTypes, nolint for deprecated parser.ParseDir
- go_lsp_cross.go: extract enrichStructFieldsFromGenDecl/enrichIfaceMethodsFromGenDecl
  (gocognit), fix rangeValCopy for 152-byte structs
- memleak_test.go: change file permissions to 0o600 (gosec G306)
- router.go, tools.go: fix gofmt formatting
2026-03-12 12:57:20 +01:00
Martin Vogel f9945e75a4 Fix Windows linker: --allow-multiple-definition for GCC 15.2.0 UCRT64 regression 2026-03-07 18:12:33 +01:00
Martin Vogel 497dd6e61a Add Wolfram Language support (64 languages) + fix caller attribution
- Vendor LumaKernel/tree-sitter-wolfram grammar (ABI 13, parser.c + scanner.c)
- Register Wolfram language: .wl/.wls extensions, set_delayed_top/set_top/
  set_delayed/set as function types, apply as call type, get_top + Needs[]
  as import types
- Add CBM_LANG_WOLFRAM enum, lang spec entry, and grammar bridge
- Extract defs: resolve function name from apply(user_symbol("f"), ...) LHS
  of set/set_delayed definitions; recurse into function bodies for nested defs
- Extract calls: skip apply nodes that are definition LHS (not a call)
- Extract imports: handle << "file.wl" (get_top) and Needs["Package`"]
- Fix caller attribution: add func_kinds_wolfram to func_kinds_for_lang and
  add Wolfram name extraction in compute_func_qn (extract_unified.c) so the
  scope stack correctly tracks enclosing function for all call sites
- Add MATLAB function_call + command call extraction (63 -> 64 with Wolfram)
- Add Lean 4 apply call extraction with type-position filter
- Add regression tests for Wolfram, MATLAB, Lean calls + FORM pipeline test
2026-03-07 18:01:27 +01:00
Martin Vogel ced21194ac Fix Magma import/call extraction, resolve file-path imports in linker
- Add field('path', ...) to Magma load_statement grammar rule so
  parse_generic_imports() finds the import path via field lookup
  instead of the broken text fallback (which only extracted 1 per file)
- Fix passImports() to resolve file-path imports (e.g. "utils.mag",
  "lib/helpers.h") via fqn.ModuleQN() when raw path doesn't match
  any node QN — general fix benefiting any file-path-based import
- Add TestMagmaImport_Regression and TestMagmaCall_Regression
- Update language count 59 → 63 in README, docs/index.html, marketing
2026-03-07 12:55:56 +01:00
Martin Vogel 0474a5c78e Add MATLAB, Lean 4, FORM, and Magma language support (59 -> 63)
- MATLAB: vendored from acristoffers/tree-sitter-matlab, definitions-only
  (no call graph due to A(1) indexing ambiguity), .m file disambiguation
  via GitHub Linguist heuristics in discover.go
- Lean 4: vendored from Julian/tree-sitter-lean, definitions-only
  (Lean 4 syntax is runtime-extensible), ABI 13 backward-compatible
- FORM: custom tree-sitter grammar written from scratch for symbolic
  manipulation language used in particle physics (CERN/Nikhef)
- Magma: custom tree-sitter grammar written from scratch for computer
  algebra system (Univ. Sydney)

Integration touchpoints per language: cbm.h enum, cbm.go map, lang.go
constants, lang_specs.c (extern + arrays + table + switch), helpers.c
(func_kinds + module_parents + test detection), extract_defs.c
(resolve_func_name for MATLAB/Lean), extract_imports.c, lang/<name>.go
spec, discover.go (.m heuristic), regression_test.go (9 new tests).
2026-03-07 10:46:21 +01:00
Martin Vogel fcff5b8dc9 Unify version management via build-injected ldflags
tools.Version was a hardcoded const that needed manual bumping.
Now it defaults to "dev" and is set from main.version (injected
via -ldflags during release builds) through tools.SetVersion().
2026-03-07 00:07:43 +01:00
Martin Vogel f7574a3622 Fix Windows file URI path parsing in watcher
parseFileURI returned /C:/Users/... (with leading /) for Windows
file:///C:/... URIs, causing watcher.root_gone loop because os.Stat
fails on that path. Strip the leading / before drive letters and
normalize with filepath.FromSlash.

Fixes the remaining watcher bug from #20.
2026-03-06 22:20:47 +01:00
Martin Vogel e292f875a9 Fix community issues #15, #17, #20 and add editor support #19
- Fix Continue.dev invalid_type error: add properties:{} to list_projects schema (#15)
- Fix Windows paths: sanitize colons and backslashes in ProjectNameFromPath (#20)
- Fix update double-v prefix: strip v from version before display (#17)
- Fix update context canceled: DownloadAsset returns []byte, not ReadCloser (#17)
- Strip v prefix in release workflow ldflags (Unix + Windows builds)
- Add Gemini CLI, VS Code Copilot, and Zed to install/uninstall commands (#19)
- Add tests for new editor configs and Windows path cases
2026-03-06 19:51:47 +01:00
Martin Vogel c34a2da178 Fix Windows build: add ts_runtime/src to include path for unicode headers
The vendored ICU-subset headers use "unicode/umachine.h" includes.
Adding src/ to CFLAGS lets the compiler resolve these on Windows
where no system ICU is available.
2026-03-06 18:53:02 +01:00