120 Commits
Author SHA1 Message Date
test 2c8be91757 Merge branch 'worktree-add-new-languages'
# Conflicts:
#	internal/cbm/lang_specs.c
2026-04-16 10:47:10 +02:00
test 5eca425072 Fix JS lang spec: correct stale case_clause, add do_statement
- branch_types: case_clause → switch_case + switch_default (correct
  grammar node names)
- branch_types: add do_statement (do-while loops)
- import_types: remove 'require' (not a grammar node type)

Verified: TypeScript, Python, C, C++ specs are all correct — every
node type in the spec exists in the grammar's ts_symbol_names.
2026-04-16 00:45:41 +02:00
test e4c1e93a8e Fix Go lang spec: correct stale node types, add func_literal
- func_types: add func_literal (anonymous functions/closures)
- branch_types: fix 3 stale names:
  switch_expression → expression_switch_statement
  case_clause → expression_case
  default_clause → default_case
- branch_types: add type_switch_statement, type_case,
  communication_case, defer_statement, go_statement
2026-04-16 00:37:57 +02:00
test 67b6c97a3f Fill remaining lang spec gaps: shared arrays + C#/JS/Python imports
- C#: add record_declaration, type_declaration to class types;
  add namespace_declaration to import types
- JavaScript: add new_expression to call types; add import, extends,
  require to import types (also used by TS/TSX)
- Python: add import to import_types
- TypeScript: add function_signature to func types
- Makefile: add recipe to func, call to calls, include to imports

All 153 grammars now have maximally complete extraction specs.
2797 tests pass with zero regressions.
2026-04-16 00:26:25 +02:00
test e7893a2390 Add gRPC stub detection in call resolution and chained call extraction
- pass_parallel.c: detect gRPC calls when resolved QN contains
  ServiceClient/ServiceGrpc/Servicer — emits GRPC_CALLS edges for
  calls resolved to generated protobuf client interfaces
- pass_parallel.c: emit_grpc_edge falls back to resolved QN when
  callee_name alone doesn't contain service.method pattern
- extract_calls.c: add resolve_chained_selector() for iterative
  extraction of chained method calls (NewClient(conn).GetBar →
  "NewClient.GetBar") without recursion

Known limitation: Go receiver-method chained calls like
pb.NewCartServiceClient(conn).GetCart() in rpc.go are not yet
extracted as CALLS edges — the Go grammar's AST structure for
these patterns needs dedicated investigation.
2026-04-16 00:23:06 +02:00
test 7f436b552e Complete lang specs: add all missing node types across 114 languages
Systematic audit of every grammar's parser.c against the current
lang_specs.c entries. For each language, identified all primary
extraction-relevant node types (function/class/call/import) present
in the grammar but missing from the spec.

Changes:
- 44 new node type arrays created for languages that had empty_types
  where the grammar provides extractable constructs
- 121 existing arrays extended with additional node types
- Covers all 153 vendored grammars

Examples of additions:
- Go: import, import_declaration added to import_types
- Python: import, import_from_statement, import_statement added
- JavaScript: new_expression, call_expression added to call_types
- PHP: namespace_use_declaration added (was completely missing)
- Rust: macro_invocation added to call_types
- C/C++: struct_specifier, enum_specifier, union_specifier added

All 2797 tests pass with zero regressions.
2026-04-16 00:07:32 +02:00
testandDustin Obrecht a8406bd4c9 fix: implement overflow pages in sqlite_writer to prevent SIGBUS on large records
When a single record payload exceeds 65KB (max_local=65501), the writer
now splits it across overflow pages per SQLite's B-tree spec instead of
underflowing the content_offset and corrupting memory.

Closes #139, closes #187.
Based on #175 by dLo999.

Co-Authored-By: Dustin Obrecht <dustin@kurtnoble.com>
2026-04-15 23:56:03 +02:00
test 8babe67bea feat: add persistent artifact storage for team sharing
Add .codebase-memory/graph.db.zst — a zstd-compressed knowledge graph
artifact that can be committed to the repo. Teammates bootstrap from
the artifact instead of running a full reindex from scratch.

- Vendor zstd 1.5.7 (amalgamated build) for 8-13:1 compression
- Two-tier export: zstd -9 + index stripping for explicit index,
  zstd -3 for watcher/incremental auto-updates
- Import: decompress → integrity check → auto-recreate indexes
- Bootstrap in handle_index_repository: when no local DB exists but
  artifact is present, import first then run incremental
- Auto-create .gitattributes with merge=ours to prevent conflicts
- Fix: add missing idx_edges_url_path to create_user_indexes and
  url_path_gen generated column to init_schema
- 13 new tests (5 zstd wrapper + 8 artifact round-trip/edge cases)
2026-04-15 23:56:03 +02:00
test 81385d08eb Add gRPC/GraphQL/tRPC service detection with protobuf Route extraction
Pipeline: gRPC/GraphQL/tRPC client libs in service_patterns, edge emitters
in pass_parallel, __grpc__ Route nodes from .proto service defs in
pass_route_nodes, cross-repo matchers in pass_cross_repo. Also adds MQTT,
NATS, Dapr async patterns.

Protobuf extraction: service as Class, rpc as Function with rpc_name
fallback in func_name_node. Route nodes created by line-range matching
rpc Functions to enclosing service Classes.

Tested: Online Boutique protos produce 16 gRPC Route nodes.
2026-04-15 23:53:42 +02:00
Martin Vogel d5c493ca0a Expand channel detection from JS/TS to 8 languages
Extend extract_channels.c from JS/TS/TSX-only to Python, Go, Java/Kotlin,
C#, Ruby, Elixir, and Rust with language-specific extractors:

- JS/TS: add Kafka (producer.send/consumer.subscribe), RabbitMQ
  (channel.publish/consume) on top of existing Socket.IO + EventEmitter
- Python: python-socketio (sio.emit/@sio.on), Django Channels
  (channel_layer.send/group_send), FastAPI WebSocket, kafka-python
- Go: gorilla/nhooyr websocket (WriteMessage/ReadMessage/WriteJSON/ReadJSON)
- Java/Kotlin: JSR 356 WebSocket (@OnMessage/@ServerEndpoint),
  Spring STOMP (convertAndSend/@MessageMapping)
- C#: SignalR (Clients.All.SendAsync/Hub.On)
- Ruby: ActionCable (broadcast/stream_from)
- Elixir: Phoenix.PubSub (broadcast/subscribe), Phoenix.Channel
  (push/handle_in)
- Rust: tokio-tungstenite (sink.send/stream.next)

Refactored entry point from language gate to switch dispatch. Python
direction classification uses table-driven lookup for linter compliance.
2026-04-15 23:53:42 +02:00
Martin VogelandTommy f71fded895 Cherry-pick extraction and Cypher improvements from PR #162
- Enum member extraction: C#/Java/TS/C++ enum values as Variable nodes
- JS/TS destructured variable splitting: const { A, B, C } = require()
  emits individual Variable nodes instead of one blob
- Cypher -- SQL-style single-line comments
- Cypher in_degree/out_degree virtual node properties (thread-safe
  via binding store pointer, enables dead code detection via Cypher)
- Cypher regex matching in inline property filters
- Resolution tiebreaking: test/mock QN deprioritization and C# field
  type hint resolution for obj.Method() disambiguation

Co-Authored-By: Tommy <Koolerx@users.noreply.github.com>
2026-04-15 23:53:42 +02:00
test 8c7f61c795 Populate lang specs with proper node types for all 89 new languages
Fill in function, class, field, call, import, branch, variable,
assignment, throw, and decorator node types for all new languages
based on per-grammar AST analysis. Previously all 89 new languages
had empty_types (module detection only, no extraction).

Programming languages with full specs (31):
  Solidity, Typst, GDScript, Gleam, PowerShell, Pascal, D, Nim,
  Crystal, Odin, Ada, Sway, Cairo, Move, Hare, Pony, AWK, Fish,
  Zsh, Tcl, Fennel, ReScript, PureScript, Nickel, Teal, Luau,
  Squirrel, ISPC, Starlark, Puppet, LLVM IR

IDL/config with type/field specs (12):
  Prisma, Thrift, Cap'n Proto, Smithy, WIT, Bicep, WGSL, HLSL,
  VHDL, SystemVerilog, Apex, Kconfig

Remaining languages have module_types only (config/data formats
where function/class extraction is not applicable).
2026-04-15 23:34:09 +02:00
test b2b48f8b0d Add 89 new tree-sitter grammars (66 to 155 languages)
Vendor, wire up, and compile 89 new tree-sitter grammars, expanding
language support from 66 to 155 languages. All grammars pass security
audit (no dangerous patterns in scanner.c files).

New programming languages (31):
  Solidity, Typst, GDScript, Gleam, PowerShell, Pascal, D, Nim, Scheme,
  Fennel, Fish, AWK, Zsh, Tcl, Ada, Agda, Racket, Odin, ReScript,
  PureScript, Nickel, Crystal, Teal, Hare, Pony, Luau, Janet, Sway,
  NASM, Assembly, TLA+, Pkl, Cairo, Move, Squirrel, ISPC, FunC, Smali

New config/data/IDL formats (31):
  Just, Astro, Blade, Go Template, Templ, Liquid, Jinja2, Prisma,
  Hyprlang, DotEnv, Diff, WGSL, KDL, JSON5, Jsonnet, RON, Thrift,
  Cap'n Proto, Properties, SSH Config, BibTeX, Starlark, Bicep, CSV,
  Requirements, HLSL, VHDL, SystemVerilog, DeviceTree, Linker Script,
  GN, Kconfig, BitBake, TableGen, Slang, LLVM IR, Smithy, WIT,
  Go Mod, Mermaid, RST, Beancount, Puppet, PO, Regex, JSDoc,
  gitattributes, gitignore, Apex, SOQL, SOSL

Infrastructure:
  - scripts/new-languages.json: manifest for all new languages
  - scripts/generate-lang-code.py: generates boilerplate from manifest
  - scripts/audit-grammar-security.sh: pre-vendoring security scanner
  - Fixed angle-bracket includes in 18 grammars
  - Fixed PureScript scanner const mismatch
  - Fixed VHDL scanner void* API signatures
  - Fixed RST tree_sitter_rst/ subdirectory include paths
  - Copied crystal unicode.c (extra scanner dependency)

All new languages start with minimal lang specs (module_types only).
Function/class/call extraction specs to be refined incrementally.
2026-04-15 21:28:51 +02:00
test c6fc68ff77 Update C#, Rust, Scala grammars to latest upstream
- C#: v0.23.5 — adds C# 12 collection expression support
- Rust: v0.24.2 — fixes string literal parse errors, bad error recovery
- Scala: v0.25.0 — adds into/tracked soft modifiers, applied constructor
  types, given with type parameters, anonymous using parameters (Scala 3)

Kotlin and Swift updates deferred: Kotlin grammar restructured AST
(breaks extraction), Swift repo no longer ships parser.c.
2026-04-15 20:37:22 +02:00
test 240b277410 Refactor lang_specs to designated initializers with factory pointer
Migrate the lang_specs[] array from implicit positional indexing to
C99 designated initializers ([CBM_LANG_X] = {...}), eliminating a
class of silent ordering bugs when adding new languages.

Changes:
- Add ts_factory function pointer to CBMLangSpec struct
- Convert all 66 entries to designated initializer syntax
- Add _Static_assert guard: array size must match CBM_LANG_COUNT
- Replace 140-line cbm_ts_language() switch with 3-line factory dispatch
- Net reduction: 127 lines removed

This is prerequisite infrastructure for the ~90 new language expansion.
2026-04-15 20:05:00 +02:00
Martin VogelandKoolerx a0715ff1eb Add JS/TS IMPORTS resolution, Channel schema, lint cleanup
Features:
- Relative import resolution for JS/TS/Python/Ruby (./foo, ../bar,
  leading dots) via cbm_pipeline_resolve_relative_import in fqn.c
- Generic Channel detection: Socket.IO emit/on, EventEmitter patterns
  produce Channel nodes with EMITS/LISTENS_ON edges and transport
  property (extract_channels.c)
- Constant resolution trick: `const EVENT = "foo"; emit(EVENT)` resolves
  the channel name through a per-file constant table

Lint fixes (337 errors across 16 files):
- Named constants replacing all magic numbers (enums/defines)
- Cognitive complexity reduced via helper extraction (table-driven
  sqlite_writer, pipeline predump passes, graph_buffer dump phases)
- SQLITE_TRANSIENT int-to-ptr workaround in store.c + mcp.c
- clang-format + cppcheck clean

Co-Authored-By: Koolerx <tommy@koolerx.com>
2026-04-06 12:41:31 +02:00
Martin VogelandKoolerx 647af0b57c Add BM25 full-text search + C# Interface extraction fixes
Ports four targeted improvements from #162 (Koolerx):

- FTS5 BM25 ranked search via a new `query` parameter on search_graph.
  Uses a contentless nodes_fts virtual table populated at dump time with
  a cbm_camel_split() SQL function that splits camelCase identifiers
  (updateCloudClient -> update Cloud Client) so tokenized word queries
  match identifier internals. BM25 rank is boosted by node label
  (Function/Method +10, Route +8, Class/Interface/Type/Enum +5) and
  noise labels (File/Folder/Module/Variable) are filtered out. The new
  path is opt-in via the query parameter; regex name_pattern and vector
  semantic_query paths are untouched.

- Enable SQLITE_ENABLE_FTS5 in the vendored sqlite3 build flags.

- Rebuild nodes_fts after incremental reindex. The btree dump path
  bypasses any FTS5 triggers, so the index is wiped and repopulated via
  delete-all + INSERT .. SELECT after each incremental merge.

- Add Interface to the label filter on cbm_registry_add in both the
  parallel and sequential definition passes, so C#/Java class
  declarations like Foo : IBar can resolve IBar to an INHERITS edge
  target during enrichment.

- Add an explicit C# base_list handler to extract_base_classes() that
  iterates named children directly instead of returning the raw node
  text. Without this the fallback path returned ": IExamService" (with
  the leading separator) and registry lookup always failed, so C#
  INHERITS edges to interfaces never resolved.

Co-Authored-By: Koolerx <Koolerx@users.noreply.github.com>
2026-04-06 12:41:30 +02:00
Martin Vogel 8a06d78ac7 Parallelize post-passes, fix mode filtering + semantic edge quality
- Parallelize pass_similarity and pass_semantic_edges via worker pool with
  thread-local edge buffers; sequential final merge since gbuf is not
  thread-safe. Adds cbm_lsh_query_into() as a thread-safe variant with
  caller-provided candidate buffer.

- Add activatable profiling subsystem (CBM_PROFILE=1 env or --profile flag)
  for step-level timing of extract, resolve, corpus build, vector phases,
  and sqlite dump. Zero overhead when disabled.

- Fix cbm_index_mode_t enum mismatch between pipeline.h (FULL=0, MODERATE=1,
  FAST=2) and discover.h (FULL=0, FAST=1). mode=fast silently no-op'd
  fast-discovery filtering because discover.c compared against the wrong
  value. Linux kernel fast mode went 1:40 -> 3:11 as a result; now back to
  1:40. Broaden the filter guard to mode != CBM_MODE_FULL so MODERATE and
  FAST both get aggressive discovery.

- Clamp cbm_sem_combined_score output to [0, 1]. The proximity multiplier
  returns up to 1.10 as a same-file boost which could push the final
  cosine score above 1.0.

- Short-circuit semantic scoring when MinHash jaccard >= 0.95. Exact
  near-clones are already emitted as SIMILAR_TO edges; returning 0 here
  avoids flooding SEMANTICALLY_RELATED with cross-service copy-paste
  boilerplate and frees the edge budget for genuine vocabulary-bridged
  relations.

- Validate search_graph semantic_query as an array of strings and return
  a clear error for a single-string input. Update the tool description
  to spell out the requirement explicitly with an example.

- JSON-escape user-controlled strings (callee names, call arguments,
  URL paths, import local_name) in call/argument properties. Introduces
  cbm_json_escape() in foundation/str_util.

- Skip SQLite pending_byte_page (file offset 0x40000000) during raw page
  writes in sqlite_writer to avoid corrupting databases that cross the
  1 GiB boundary.

- Migrate pretrained vector blob from UniXcoder (51K tokens) to
  nomic-embed-code (40856 tokens x 768d int8). Includes the extraction
  script under scripts/extract_nomic_vectors.py.
2026-04-06 12:41:30 +02:00
Martin Vogel e81a796fe6 Embed Nomic nomic-embed-code pretrained vectors (40K tokens × 768d) for semantic search quality
Major quality improvement: replace random index vectors with pre-trained
Nomic nomic-embed-code token embeddings. Tokens like 'error' and 'exception' now start
with similar vectors (learned from millions of code repos) instead of
arbitrary random projections. Co-occurrence enrichment adds project-specific
context on top.

Architecture:
- vendored/nomic/code_vectors.bin: 37.7MB raw int8 vectors
- vendored/nomic/code_vectors_blob.S: assembler .incbin (instant build)
- vendored/nomic/code_vectors.h: extern declarations + pretrained_vec_at()
- vendored/nomic/code_tokens.h: 40856 token strings (575KB)
- semantic.c: cbm_sem_random_index() now looks up pretrained vectors first,
  falls back to sparse random for unknown tokens
- CBM_SEM_DIM raised from 256 to 768 to match Nomic nomic-embed-code

Also: RRI (Reflective Random Indexing), code pattern vocabulary injection,
120+ abbreviation expansions, callee/caller/body token enrichment,
label filter (Function/Method/Class only) in vector search SQL.

Binary size: 136MB → 169MB (+33MB from embedded vectors).
Search quality: keyword queries return relevant error-handling functions.
Domain-specific keyword queries return the expected functions.
2026-04-06 12:41:29 +02:00
Martin Vogel 7a9b7db830 Add semantic_query to search_graph: vector search via cbm_cosine_i8 SQL function
Vector search pipeline (end-to-end):
- store.c: cbm_cosine_i8 custom SQLite function (int8 dot product with
  sqrt magnitude), registered at store open time
- store.c: cbm_store_vector_search() builds merged query vector from
  keywords via base RI vectors (xxHash), int8-quantizes, runs SQL query
  with JOIN nodes ON node_id = id for metadata
- mcp.c: search_graph gains semantic_query param (array of strings),
  returns semantic_results alongside regular results
- sqlite_writer.c: fixed build_vector_record to include node_id in
  record body (matches build_node_record pattern)
- mcp.c: use yyjson_mut_obj_add_strcpy (not add_str) to avoid
  use-after-free when vector results are freed before JSON serialization

Quality note: base RI vectors at query time don't capture co-occurrence
enrichment — results are moderate quality. Storing enriched token vectors
would improve this significantly (future work).
2026-04-04 17:14:47 +02:00
Martin Vogel 8a0ad0489b WIP: Algorithmic semantic embeddings + indexing modes (checkpoint before vector storage) 2026-04-04 16:17:58 +02:00
Martin Vogel 09ce20afc8 Improve MinHash quality: leaf-only tokens, structural weighting, unique trigram gate
Four changes to reduce false positives from 382K to 58K SIMILAR_TO edges
on the Linux kernel while maintaining ~98% precision:

1. MIN_NODES raised to 30 (leaf tokens) — aligns with BigCloneBench
   standard of 50 raw source tokens / 6 lines minimum clone size

2. collect_ast_tokens now records LEAF nodes only, not internal grammar
   nodes. Leaf-only counting is language-agnostic: leaves correspond to
   actual source tokens regardless of grammar verbosity (C tree-sitter
   produces 2x more internal nodes than Python for the same logic)

3. hash_trigrams tracks unique structural trigram count via hash set.
   Functions with < 32 unique structural trigrams are skipped — too few
   distinct features for K=64 MinHash to produce reliable estimates

4. Structural-weighted MinHash via repetition: each trigram gets weight
   0-3 based on count of non-normalised tokens (I/S/N/T = normalised).
   Weight-0 trigrams (all-normalised, e.g. I|I|I) are pure noise and
   skipped entirely. Weight 1-3 trigrams use repetition-based weighted
   MinHash — higher weight = more hash attempts per seed = more likely
   to dominate the signature. Achieves IDF-like effect without needing
   corpus-wide statistics.

Also adds O(1) hash-set dedup in LSH query (replacing O(n) linear scan)
and bucket size cap of 200 to skip oversized buckets.

Linux kernel: 1:41, similarity 7.7s, 395K fp, 58K edges, ~98% precision.
Tests updated with larger Go functions to meet new thresholds.
2026-04-03 22:35:01 +02:00
Martin Vogel 452f5a7b1f Add MinHash fingerprinting and SIMILAR_TO edges for near-clone detection
Compute K=64 MinHash signatures from normalized AST node-type trigrams
during function extraction, then generate SIMILAR_TO edges via LSH
(b=32, r=2) for function pairs with Jaccard >= 0.95.

- src/simhash/minhash.{h,c}: MinHash compute, Jaccard, hex encode/decode,
  LSH index with band hashing for O(n) candidate generation
- src/pipeline/pass_similarity.c: post-pass reads fingerprints from node
  properties, builds LSH index, emits SIMILAR_TO edges with jaccard and
  same_file metadata. Same-language only, max 10 edges per node.
- internal/cbm/cbm.h: fingerprint fields on CBMDefinition
- internal/cbm/extract_defs.c: compute_fingerprint() hook at 3 extraction
  sites after complexity, skip functions with < 10 AST body nodes
- pass_definitions.c + pass_parallel.c: serialize fingerprint to "fp" hex
  in properties_json for both sequential and parallel pipeline paths
- pipeline.c + pipeline_incremental.c: register pass_similarity in both
  full and incremental post-pass lists
- tests/test_simhash.c: 28 tests across 4 suites (core, LSH, edge gen,
  pipeline integration with generated Go project + incremental)
2026-04-03 20:06:33 +02:00
Martin Vogel 0eba6dff38 Fix portable Linux build: gcc -static on Ubuntu, no Docker
- Portable build uses gcc -static on native Ubuntu runner
- Rename PAGE_SIZE -> CBM_PAGE_SIZE (conflicts with musl limits.h)
2026-04-02 21:39:04 +02:00
Martin Vogel d9bd071e77 Fix lint: magic numbers in cypher/sqlite_writer/configlink/gitignore, extract URL-in-args helpers 2026-04-02 01:08:51 +02:00
Martin Vogel 7fa3acd0c6 WIP: strict linting + RAM-first pipeline (lint fixes pending) 2026-04-01 23:22:44 +02:00
Martin Vogel b523116ef2 Achieve zero clang-tidy errors at CC<=25 threshold
Split all remaining pipeline functions. Extract 40+ helpers.
Add lint-no-suppress quality gate. Add clang-tidy to lint.sh.
Zero NOLINTNEXTLINE, zero clang-tidy errors, 2741 tests pass.
2026-03-31 20:04:12 +02:00
Martin Vogel 6e4ca93cf0 Split 168 functions to cognitive complexity 25, zero lint errors
Lower thresholds to industry defaults:
  cognitive-complexity: 25 (was 250)
  statements: 200 (was 400)
  lines: 400 (was 800)

All 168 functions split into smaller helpers across 44 files.
Zero NOLINTNEXTLINE suppressions remain. Zero clang-tidy errors.

Add clang-tidy to scripts/lint.sh (--ci to skip where unavailable).
Fix sqlite_writer B-tree PageRef initialization. Fix Terraform struct
parsing, Louvain null guards, const qualifiers, shadow variables.

2741 tests pass.
2026-03-31 20:04:12 +02:00
Martin Vogel 87c2e144c0 Set cognitive complexity to industry default (25), tag 168 functions
Lower thresholds to best-practice values:
  cognitive-complexity: 250 -> 25 (industry default)
  statements: 400 -> 200
  lines: 800 -> 400

Add NOLINTNEXTLINE to 168 functions that currently exceed these thresholds.
Each suppression will be removed as the function is split in subsequent
commits. Zero net behavioral changes.

Also: extract execute_with_clause from cypher execute_single.
2026-03-31 20:04:12 +02:00
Martin Vogel a6fbb9bd14 Split cbm_write_db god-function (569 -> 325 lines)
Replace index-building macros with function-pointer helpers:
build_node_index_sorted + build_edge_index_sorted with callbacks.
Extract write_data_tables and write_metadata_tables phases.
2026-03-31 20:04:12 +02:00
Martin Vogel 71f110a0c3 Split 2 god-functions, fix remaining Phase 4 items (3/4 done)
Phase 3 (partial):
- extract_defs.c: split extract_var_names (509 lines) into 4 helpers by
  language group: extract_vars_mainstream, extract_vars_dynamic,
  extract_vars_jvm, extract_vars_config. Dispatcher is ~40 lines.
- pass_httplinks.c: extract apply_prefix_to_func_routes helper, reducing
  resolve_cross_file_group_prefixes cognitive complexity.

494 -> 2 NOLINTs remaining (cypher.c execute_single + sqlite_writer.c
cbm_write_db — the two largest functions in the codebase).
2026-03-31 20:04:11 +02:00
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