Commit Graph
161 Commits
Author SHA1 Message Date
Martin Vogel d33b9e45d9 Fix RSS not dropping after delete_project: add mem_collect + immediate purge
- delete_project now calls cbm_mem_collect() after closing the database
  to return freed pages to OS immediately
- Set purge_delay=0 (was 1000ms) so mimalloc purges freed pages without delay
- Set purge_decommits=1 explicitly so macOS uses MADV_FREE_REUSABLE
  (immediate RSS accounting) instead of MADV_FREE (lazy, RSS stays high)

Before: deleting Linux kernel index left 8.1G RSS (2.1G dirty pages)
After: dirty pages purged immediately, RSS reflects actual usage
2026-04-07 00:53:39 +02:00
Martin VogelanddLo999 6f268d0f91 Respect nested .gitignore files during indexing, security audit all variants
Nested .gitignore support (fixes #178):
- Load per-subdirectory .gitignore during walk, match paths relative to
  the gitignore's directory via local_rel_path()
- Root and nested gitignores stack independently
- Owned gitignores collected and freed at walk end (avoids use-after-free
  from borrowed pointers on the iterative stack)

Security:
- Run security-strings/install/network + ClamAV + Windows Defender on
  ALL binary variants (standard + UI), not just standard
- Whitelist UI bundle URLs (React, Three.js, Google Fonts, Tailwind, W3C)

Co-Authored-By: dLo999 <dLo999@users.noreply.github.com>
2026-04-06 19:44:16 +02:00
Martin Vogel 64179b8888 Fix tool descriptions: add moderate mode to index_repository, since param to detect_changes 2026-04-06 18:08:47 +02:00
Martin Vogel a515fec7bd Fix update --dry-run: skip version check so dry-run output is shown
check_already_latest() exits early before printing dry-run info when
the running version matches the latest release. Skip this check in
dry-run mode so the user sees what would happen.
2026-04-06 17:34:35 +02:00
Martin Vogel 616a4307df Fix Windows agent detection paths to use home_dir consistently
Zed: AppData/Local/Zed, Kilocode/VSCode: AppData/Roaming/Code/...
Tests now have #ifdef _WIN32 branches matching the detection paths.
2026-04-06 14:01:03 +02:00
Martin Vogel 74c5697d20 Fix ASan leak in corpus token_map and Windows/Linux vector blob assembly
- semantic.c: free strdup'd keys+values in token_map via cbm_ht_foreach
  before cbm_ht_free (44KB leak in 7920 allocations)
- code_vectors_blob.S: add Windows COFF branch (.rdata,"dr") alongside
  macOS Mach-O and Linux ELF sections
2026-04-06 13:43:48 +02:00
Martin Vogel 2350240c1d Decouple security gate from pipeline, fix clang-format-20 and Linux agent detection
Workflow:
- Split _lint.yml (cppcheck + clang-format) from _security.yml
  (security-static + codeql-gate)
- Dry Run: security runs as independent island, not blocking
  lint → test → build → smoke/soak
- Release: security only blocks final verify step

Fixes:
- pass_semantic_edges.c: typedef hyperplane_row_t avoids function-returning-
  array-pointer syntax that clang-format-20 rejects
- cli.c: Linux agent detection uses home_dir-relative .config/ paths
  instead of cbm_app_config_dir() which ignores the test home_dir
2026-04-06 13:27:43 +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 bf700780cc Fix scoring: per-keyword min-cosine replaces merged vector averaging 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 1d30971ff0 Bump vendored deps: Mongoose 7.21, SQLite 3.51.3, mimalloc 3.2.8
Mongoose 7.20 → 7.21:
  Fixes 3 CVEs disclosed 2026-04-02:
  - CVE-2026-5244: preauth RCE via TLS heap buffer overflow
  - CVE-2026-5245: mDNS stack overflow RCE (34-byte UDP packet)
  - CVE-2026-5246: mTLS bypass with P-384 certificates

SQLite 3.49.1 → 3.51.3:
  Fixes WAL-reset database corruption bug (we use WAL mode).
  Also fixes nested EXISTS query errors, POSIX lock deadlock,
  and FTS5 memory error.

mimalloc 2.1.9 → 3.2.8 (v2 → v3):
  Eliminated thread-local segments for better cross-thread sharing,
  lower fragmentation, faster TLS on Windows, improved calloc.
  API change: mi_option_eager_commit → mi_option_arena_eager_commit.

Linux kernel benchmark: 1:42 (no regression). All 2718 tests pass.
2026-04-03 23:01:06 +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 VogelanddLo999 e07443b75f Add configurable database directory via CBM_CACHE_DIR env var
All hardcoded ~/.cache/codebase-memory-mcp paths now route through
cbm_resolve_cache_dir() in platform.c. Priority: CBM_CACHE_DIR env
var > default ~/.cache/codebase-memory-mcp.

Added db_path_for_project() helper in http_server.c to eliminate 5
copies of the same path construction pattern.

Fixes #154

Co-Authored-By: dLo999 <dLo999@users.noreply.github.com>
2026-04-03 18:06:52 +02:00
Martin VogelanddLo999 54c032528d Skip update when already on latest version
Check GitHub releases/latest redirect header before downloading.
Saves bandwidth and avoids unnecessary index rebuilds.

- "Already up to date" when version matches or is ahead
- --force flag to bypass the check
- Graceful degradation when network is unavailable
- Uses same curl dependency as the download itself

Fixes #142

Co-Authored-By: dLo999 <dLo999@users.noreply.github.com>
2026-04-03 17:41:27 +02:00
Martin VogelandSelene29 3463987728 Replace O(n*e) edge mapping with binary search in layout endpoint
Build sorted node-ID array, binary search each edge's endpoints.
O(n log n + e log n) instead of O(n * e) — eliminates multi-second
hangs on large projects. Rejected edges freed immediately to reduce
peak memory.

Fixes #169

Co-Authored-By: Selene29 <Selene29@users.noreply.github.com>
2026-04-03 17:21:23 +02:00
Martin VogelandSelene29 0dc3d67279 Fix layout JSON: handle invalid UTF-8 and NaN in serialization
One non-UTF-8 node name crashed the entire /api/layout endpoint
(HTTP 500). Force layout can also produce NaN/Inf positions.

- Use YYJSON_WRITE_ALLOW_INVALID_UNICODE (matches MCP serializer)
- Sanitize NaN/Inf: positions default to 0.0, size to 1.0
- Log yyjson error code on serialization failure

Co-Authored-By: Selene29 <Selene29@users.noreply.github.com>
2026-04-03 17:06:39 +02:00
Martin Vogelandslvnlrt b2915b4c32 Fix cbm_find_cli PATH delimiter and S_IXUSR check on Windows
PATH uses ; on Windows, not : — strtok with : splits C:\Users at
the drive letter colon, producing garbage paths. Also skip S_IXUSR
check on Windows since stat() doesn't set Unix permission bits.

Fixes #159

Co-Authored-By: slvnlrt <slvnlrt@users.noreply.github.com>
2026-04-03 16:49:46 +02:00
Martin Vogelandslvnlrt a250ad27f5 Detect actual binary path at runtime in install command
Replaces hardcoded ~/.local/bin/ with OS-native runtime detection:
- Windows: GetModuleFileNameA()
- macOS: _NSGetExecutablePath()
- Linux: readlink("/proc/self/exe")
Falls back to ~/.local/bin/ if detection fails.

Fixes install.ps1 placing binary in $LOCALAPPDATA/Programs/ while
configs point to non-existent ~/.local/bin/ path.

Fixes #158

Co-Authored-By: slvnlrt <slvnlrt@users.noreply.github.com>
2026-04-03 16:41:44 +02:00
Martin Vogel 80e2752c09 Fix KiloCode config paths on Windows and macOS
KiloCode is a VS Code extension — uses the same base config dir.
Apply same platform-aware paths as Zed/VS Code: macOS uses
$HOME/Library/Application Support/Code/, Windows uses %APPDATA%/Code/.
2026-04-03 16:23:36 +02:00
Martin Vogelandjimpark 9b302eeb80 Fix Zed and VS Code config paths on Windows
Add cbm_app_config_dir() and cbm_app_local_dir() platform helpers:
- Windows: %APPDATA% / %LOCALAPPDATA%
- macOS: $HOME for Library/Application Support paths
- Linux: $XDG_CONFIG_HOME or ~/.config

Update all 6 Zed/VS Code path locations (detect, install, uninstall).
macOS uses $HOME directly for Library paths; Windows/Linux use the
new helpers. Consolidates userconfig.c XDG logic into platform.c.

Co-Authored-By: jimpark <jimpark@users.noreply.github.com>
2026-04-03 15:20:49 +02:00
Martin Vogel 05aeb64802 Fix include_connected: run BFS inbound+outbound separately
cbm_store_bfs doesn't support direction="both" — it silently falls
through to outbound only. Run two BFS passes (inbound + outbound)
and merge results, matching how handle_trace_call_path works.

Also fix use-after-free: use strcpy for BFS node names that get
freed before JSON serialization.
2026-04-03 14:52:29 +02:00
9412f0905a Wire up 6 silently-ignored search_graph/architecture/detect_changes params
search_graph: qn_pattern (regex on qualified_name), relationship
(EXISTS filter on edges), exclude_entry_points (filter nodes with
no inbound CALLS but outbound CALLS), include_connected (1-hop
neighbor names in response).

get_architecture: aspects array filters which sections are returned
(structure, dependencies, routes, or all).

detect_changes: scope param ("files" = just changed files, "symbols"
= files + impacted symbols).

Split functions to stay under CC=25 threshold.

Co-Authored-By: ahundt <ahundt@users.noreply.github.com>
Co-Authored-By: maplenk <maplenk@users.noreply.github.com>
2026-04-03 14:36:06 +02:00
Martin Vogelandmaplenk f25dafadff Add include_tests param to trace_path, mark test files in BFS results
When include_tests=false (default), test files are filtered from trace
results. When true, test nodes appear with is_test=true marker. Helps
answer "which tests cover this function's blast radius?"

Also adds tests for include_tests and risk_labels params.

Co-Authored-By: maplenk <maplenk@users.noreply.github.com>
2026-04-03 01:51:32 +02:00
Martin Vogelandhalindrome 7f79ce53a1 Fix watcher: detect dirty state inside git submodules
The watcher's git_is_dirty() only ran git status on the parent repo,
missing uncommitted changes inside submodules. Add a second check via
git submodule foreach --recursive (portable, works on Apple Git which
lacks --recurse-submodules).

Fixes #71

Co-Authored-By: halindrome <halindrome@users.noreply.github.com>
2026-04-03 01:22:51 +02:00
dbab4d372f Wire up risk_labels on trace_path, add --progress CLI flag
risk_labels: adds CRITICAL/HIGH/MEDIUM/LOW classification to BFS
results based on hop distance. Opt-in via risk_labels=true.

--progress: human-readable indexing progress on stderr. Log sink
replaces default output, maps pipeline events to [1/9]..[9/9] phases.

Co-Authored-By: halindrome <halindrome@users.noreply.github.com>
Co-Authored-By: gdilla <gdilla@users.noreply.github.com>
2026-04-02 23:47:40 +02:00
Martin Vogel 129334ae94 Add missing edge types to consolidated skill: OVERRIDE, USAGE, FILE_CHANGES_WITH 2026-04-02 23:22:15 +02:00
Martin Vogelandgdilla 191428557b Consolidate 4 skills into 1 with progressive disclosure
Merge codebase-memory-exploring, codebase-memory-tracing,
codebase-memory-quality, codebase-memory-reference into single
codebase-memory skill with decision matrix, workflows, and gotchas.

Old skill directories are cleaned up automatically during install.

Factual corrections vs original PR: trace_call_path -> trace_path,
removed non-existent tools (read_file, list_directory) and edge types
(OVERRIDE, USAGE, FILE_CHANGES_WITH), removed risk_labels parameter.

Co-Authored-By: gdilla <gdilla@users.noreply.github.com>
2026-04-02 23:15:43 +02:00
Martin Vogel 9662063090 Add Alpine portable as 4th local test platform, fix musl compat
Local test infra now covers 4 platforms:
- Linux arm64 (Ubuntu, ASan+LeakSan)
- Linux portable (Alpine musl, static binary)
- Windows (mingw cross-compile)
- macOS (native)

Fixes:
- Remove sys/unistd.h and sys/poll.h (glibc-only, musl lacks them)
- Add STATIC=1 support to Makefile (appends -static to LDFLAGS)
- CI portable build uses docker run alpine instead of container directive
  (GitHub Actions JS actions break in Alpine containers on ARM64)
2026-04-02 20:28:20 +02:00
Martin Vogel 1b84943000 Separate perf tests from CI, fix cross-platform build issues
- Add CBM_SKIP_PERF=1 env var to skip incremental/perf test suite
- CI and Docker test targets skip perf by default (run.sh perf for manual)
- Convert all perf assertions to warnings (log timing, never block)
- Fix store.h anonymous enum in struct (GCC rejects, clang accepts)
- Fix test_store_search.c mkstemp on non-template path
- Add ca-certificates to Docker test image for git HTTPS
- Add cbm_gmtime_r shim in compat.h (Windows gmtime_s wrapper)
- Fix compat.c missing constants.h include (Windows build)
- Fix platform.c _environ redeclaration on mingw
- Rename trace_call_path -> trace_path in smoke/soak/fuzz scripts
2026-04-02 14:52:14 +02:00
Martin Vogel 3908624fad Fix remaining lint: cppcheck variableScope, dead code, const correctness
- platform.c: move nlen into if(env) block (variableScope)
- userconfig.c: move home into else block (variableScope)
- pipeline.c: remove dead rc!=0 check after httplinks removal
- cli.c: rmdir_recursive propagates cbm_rmdir errors, remove redundant local
- clang-tidy: whitelist cosmetic-only checks, enable all safety checks
- Thread-safe getenv via environ iteration (concurrency-mt-unsafe fix)
- Multiple files: add constants.h includes for named constants
2026-04-02 12:46:39 +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 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 d4a05f2d0a Enrich DATA_FLOWS with caller args + handler params mapping
DATA_FLOWS edges now carry actual value propagation data:
- caller_args: argument expressions from the HTTP/ASYNC call
- handler_params: parameter names from the handler function
- edge_type: HTTP_CALLS or ASYNC_CALLS (how the data crosses)
- via/route: the Route node connecting caller to handler

Skip creating DATA_FLOWS when a direct CALLS edge already exists
between caller and handler (avoids redundancy).
2026-03-28 16:38:51 +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