Commit Graph

970 Commits

Author SHA1 Message Date
Martin Vogel d8a7dc252f test(smoke): parse escaped-JSON tool results (index-cli/index-status)
Smoke (all platforms) / smoke-unix (cc, c++, macos-14) (push) Has been cancelled
Smoke (all platforms) / smoke-unix (cc, c++, macos-15) (push) Has been cancelled
Smoke (all platforms) / smoke-unix (cc, c++, macos-15-intel) (push) Has been cancelled
Smoke (all platforms) / smoke-unix (gcc, g++, ubuntu-22.04) (push) Has been cancelled
Smoke (all platforms) / smoke-unix (gcc, g++, ubuntu-22.04-arm) (push) Has been cancelled
Smoke (all platforms) / smoke-unix (gcc, g++, ubuntu-24.04) (push) Has been cancelled
Smoke (all platforms) / smoke-unix (gcc, g++, ubuntu-24.04-arm) (push) Has been cancelled
Smoke (all platforms) / smoke-windows-x64 (windows-2022) (push) Has been cancelled
Smoke (all platforms) / smoke-windows-x64 (windows-2025) (push) Has been cancelled
Smoke (all platforms) / smoke-windows-arm (push) Has been cancelled
Soak (multi-hour / soak-unix (cc, c++, macos-14) (push) Has been cancelled
Soak (multi-hour / soak-unix (cc, c++, macos-15-intel) (push) Has been cancelled
Soak (multi-hour / soak-unix (gcc, g++, ubuntu-24.04-arm) (push) Has been cancelled
Soak (multi-hour / soak-unix (gcc, g++, ubuntu-latest) (push) Has been cancelled
Soak (multi-hour / soak-windows (push) Has been cancelled
Bug Repro Board / repro-unix (cc, c++, macos, macos-14) (push) Has been cancelled
DCO / dco (push) Has been cancelled
Bug Repro Board / repro-unix (cc, c++, macos, macos-15-intel) (push) Has been cancelled
Bug Repro Board / repro-unix (gcc, g++, linux, ubuntu-latest) (push) Has been cancelled
Bug Repro Board / repro-unix (gcc, g++, linux, ubuntu-24.04-arm) (push) Has been cancelled
Bug Repro Board / repro-windows (push) Has been cancelled
The multi-platform smoke run flagged index-cli + index-status as empty/not-ready
even though the binary indexed fine (nodes>0, status ready) — the MCP tool result
wraps its payload as a JSON STRING with escaped quotes (\"nodes\":N), but the
checks grepped for unescaped "nodes":N. Strip backslashes/quotes before matching
and tolerate the nodes= log form. (Binary was healthy; this was a script-parsing
gap the wide-matrix smoke surfaced.)

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 13:51:05 +02:00
Martin Vogel 0b232ba14a test(repro): grammar batteries (scripting, functional) + Go/Python LSP passes
- repro_grammar_scripting: Python/Ruby/PHP/JS/TS/TSX/Lua/Perl/R/Julia/Groovy/Dart
  full invariant battery (Perl/R/Julia/Groovy/Dart callable-sourcing RED).
- repro_grammar_functional: Haskell/OCaml/F#/Elixir/Erlang/Elm/Clojure/Scheme/
  Racket/CommonLisp/EmacsLisp/Lean/Gleam (Elm calls-extraction RED; all dim-7 RED
  via enclosing-func drift).
- repro_lsp_go_py: 7 Go strategies (direct/type/embed/interface_resolve+dispatch/
  cross_file/unresolved) + 14 Python strategies (method/super/super_init/
  module_attr/dict_dispatch/operator_dunder/builtin*/generic_method/method_union),
  each asserting callable-sourcing + strategy-presence.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 13:46:46 +02:00
Martin Vogel cee59ee2fd test(smoke): binary-doesn't-fail invariants across all GitHub platforms
- scripts/smoke-invariants.sh: 30-check battery against the PROD binary —
  --version/--help, MCP initialize handshake with stdin OPEN (#513), tools/list
  (all 14), EVERY tool invocable with valid JSON-RPC + no crash, index→non-empty
  graph, malformed-input resilience (bad JSON / empty / huge line / binary /
  non-UTF8 / missing path), clean EOF exit, shared-lib resolution, install
  dry-run. Bounded waits (read -t / timeout), no sleep loops; msys2-safe.
- .github/workflows/smoke.yml: runs it on the WIDEST runner matrix — ubuntu
  22.04+24.04 (x64+arm64; 22.04 = older glibc / AlmaLinux class), macos
  14/15/15-intel, windows 2022/2025 + windows-11-arm (experimental). A FAIL on
  any platform is a binary a user would receive. workflow_dispatch + qa/smoke-**.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 13:39:43 +02:00
Martin Vogel daa554b08c test(repro): C/C++ LSP-pass invariants (18 resolution strategies)
Per-pass resolution contract for the C/C++ hybrid LSP: one fixture per lsp_*
strategy c_lsp.c emits (lsp_direct, implicit_this, scoped, type/virtual/base/
smart_ptr dispatch, template[_instantiation], func_ptr, dll_resolve, operator,
constructor/destructor/copy_constructor, conversion, adl, unresolved). Each
asserts the inner call is callable-sourced AND properties_json carries that
strategy. Ties to repro_invariant_lsp_rescue (the exact-QN join can suppress a
correctly-emitted strategy).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 13:39:43 +02:00
Martin Vogel 64b7a1af38 test(repro): invariant lib + per-grammar battery (core compiled/OOP langs)
Foundation for the exhaustive all-grammar/all-LSP invariant suite:
- repro_invariant_lib.h: shared invariant helpers (extract-clean, label-valid,
  fqn-wellformed, range-valid, callable-sourcing split, dangling-edge count,
  lsp-strategy presence, target-QN-suffix).
- repro_grammar_core.c: full invariant battery for C/C++/CUDA/Rust/Go/Java/C#/
  Kotlin/Scala/Swift/ObjC/D — one TEST per language asserting extract-clean +
  valid labels/FQNs/ranges + defs-present + calls-extracted + callable-sourcing
  (Module-sourced==0) + no-dangling. Callable-sourcing reds are the known gap.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 13:15:21 +02:00
Martin Vogel b897d5db1e test(repro): deep invariant dives — enclosing-func drift, LSP rescue, discovery/FQN
Comprehensively reproduce the remaining QUALITY_ANALYSIS gaps:

- repro_invariant_enclosing_parity (gap #3): cbm_find_enclosing_func's hardcoded
  func_kinds_for_lang switch has drifted from lang_specs.function_node_types.
  Languages absent from the switch whose function nodes aren't in func_kinds_generic
  silently attribute every in-function call to Module. Full drift table +
  per-language reproductions (fortran/scss/sql/verilog/julia/nix RED via Module
  source; commonlisp/emacslisp/dart/cobol RED, some compounded by a callee-
  extraction gap).
- repro_invariant_lsp_rescue (gap #5/#5a): cbm_pipeline_find_lsp_resolution
  (lsp_resolve.h:65) joins LSP results to tree-sitter calls by EXACT
  caller_qn==enclosing_func_qn; when tree-sitter says Module, the LSP rescue is
  discarded. C++ out-of-line fixture asserts the edge is LSP-callable-sourced AND
  that properties_json preserves the lsp_* strategy/confidence (both RED today).
- repro_invariant_discovery_fqn (gaps #1,#4): comprehensive 50+ skip-dir table
  (.claude-worktrees RED, the rest GREEN guards) + 6 FQN same-stem collision cases
  (api.h/api.c + svc.h/svc.cpp RED; cross-dir/.d.ts/cross-package GREEN guards).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 12:59:54 +02:00
Martin Vogel 010318e4d5 ci(soak): run #581 soak on ALL platforms incl. Windows
#581 explicitly crashes Windows (50+ GB virtual memory → crash), so Windows is
the most important soak target — the earlier 2-platform cap (ubuntu+macos) missed
exactly where the bug manifests. Expand to the full matrix: linux amd64+arm64,
darwin arm64+amd64, and a windows-latest msys2 job (mirrors _soak.yml's windows
build + .exe binary-path detection). All legs run the query-leak mode, 320-min
budget.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 12:59:54 +02:00
Martin Vogel 3b3df03b3d ci(soak): fix soak.yml startup failure — literal timeout-minutes
timeout-minutes is evaluated at workflow setup, where the inputs context is null
on push events; fromJSON(inputs.duration_minutes || '240') + 60 was a startup
failure (0 jobs), so the soak never ran on qa/soak-** either. Use a fixed 320-min
budget (covers the 240-min default soak + build + analysis).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 12:21:21 +02:00
Martin Vogel 23333bc7f3 test(soak): real multi-hour #581 soak (query-leak mode) + fix soak timeout cap
- _soak.yml: timeout-minutes was 30 (soak-quick) / 45 (asan) while nightly passes
  duration_minutes=240 — every 'nightly 4h soak' was silently KILLED at 30 min and
  never ran multi-hour. Raise to 300/60 so the soak can actually complete.
- soak-test.sh: add CBM_SOAK_MODE=query-leak (default unchanged). It indexes once
  then hammers read-only tools (search_graph/query_graph/trace_path/
  get_code_snippet/search_code) with NO reindex/mutation — so index_repository's
  cbm_mem_collect never runs to sweep the query-only leak #581 implicates. The
  existing RSS ceiling/slope/ratio checks become the #581 detector.
- soak.yml: workflow_dispatch (duration_minutes, mode) + push to qa/soak-** ;
  builds the prod binary and runs the soak with timeout = duration + 60, on
  ubuntu + macos. Pushing a qa/soak-* branch starts a real multi-hour run.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 12:15:33 +02:00
Martin Vogel c66719a7ce test(repro): large graph-quality INVARIANT test group
A systemic-invariant suite derived from the prior QUALITY_ANALYSIS (only 3.69% of
real-repo CALLS edges are Function/Method-sourced; the rest fall back to Module):

- repro_invariant_calls: source-position-aware CALLS attribution per language —
  a call inside a function body must be sourced at Function/Method, never Module.
  C/C++/Rust/Java/C# RED (Module fallback + LSP-rescue join too strict); Go/Python
  GREEN guards.
- repro_invariant_graph: discovery hygiene (.claude-worktrees must be skipped —
  RED), FQN same-stem distinctness (api.h vs api.c collide via strip_ext — RED),
  no-dangling-edges (GREEN integrity guard), Perl enclosing-func parity
  (func_kinds_for_lang lacks subroutine_declaration_statement — RED).
- repro_invariant_breadth: 26-language table asserting in-body calls are
  callable-sourced (~12 RED incl. r/julia + the known-gap langs, ~14 GREEN guards).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 12:15:33 +02:00
Martin Vogel d2ec388e89 test(repro): memory-budget #363 + bounded RSS-soak #581
- #363: the cgroup CPU axis was fixed in v0.8.0 (detect_system_linux reads
  cpu.max/cfs_quota), but there is no user-controllable memory ceiling —
  cbm_mem_init derives the budget from host/cgroup RAM with no override. Test
  sets CBM_MEM_BUDGET_MB and asserts cbm_mem_budget honors it; RED because that
  env knob is not read (mirrors the open ask from the issue thread; note this is
  the memory-override remainder, adjacent to enhancement #580).
- #581: bounded RSS-growth reproduction for the long-running leak — repeats a
  query op ~150x and asserts current RSS (cbm_mem_rss / /proc/self/statm) stays
  within 3x of the warmup baseline. Documents flakiness + that a slow per-op leak
  may not trip the bounded threshold (then a true multi-hour soak is needed).

#513 (Windows stdio handshake hang) is NOT reproducible in the unit-test runner:
it is Windows-only WaitForSingleObject code in cbm_mcp_server_run. It needs the
prod cbm binary built on windows-latest + a stdio-driver test that sends an
initialize request, keeps stdin open, and asserts a response before EOF. Deferred
as a board extension (documented in private/BUG_REPRO_PLAN.md).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 10:17:41 +02:00
Martin Vogel 895069ae5c test(repro): fix #471 Windows build (unused-function under -Werror)
build_perl_nested_calls is only used in the POSIX fork/alarm branch; on Windows
the test body is SKIP_PLATFORM, so the helper was unused and tripped
-Werror=unused-function (windows-only board failure). Mark it unused.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 09:57:08 +02:00
Martin Vogel 51cc7d8b12 test(repro): #548 lighter harness, strengthen #56, + 3 NEW bugs
- #548: reworked off the live-HTTP-server draft — calls cbm_is_dir (the exact
  function handle_browse gates on) with a backslash path + the drive-root parent
  strrchr logic; no sockets/threads. RED on current code.
- #56: was a false-pass (bare-name resolver routed crate_a::helper to the only
  'helper' candidate). Added a second local helper to force ambiguity and now
  assert a CALLS edge whose target QN is in crate_a's namespace. Genuinely RED.

NEW bugs found by the discovery sweep (each a RED reproduction, root-cause traced):
- repro_new_ts_class_field_arrow: TS class-field arrow methods (handler = () => {})
  are never emitted as Method defs and inner calls mis-attribute to the class QN
  (extract_class_methods + resolve_toplevel_arrow_name ignore public_field_definition).
- repro_new_py_tuple_unpack: 'x, y = f()' yields no Variable defs — extract_vars
  only handles an identifier 'left', not pattern_list.
- repro_new_cypher_limit_zero: 'LIMIT 0' returns ALL rows — limit==0 is used as
  both the unset sentinel and a valid value; three guards check limit>0.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 09:55:14 +02:00
Martin Vogel 8bf892cd8f test(repro): GLR blowup #471 + opencode PATHEXT guard #221
- #471 (RED): deeply-nested ambiguous Perl call chain f(f(f(...))) makes the GLR
  stack-merge O(n^2) (stack_node_add_link recurses over all shared heads; the
  #461 recursion-depth cap bounds stack depth, not total iterations). Reproduced
  in a forked child with alarm(15) at depth 5000; asserts the child is not
  signal-killed (RED when the quadratic blowup blows the time budget).
- #221 (GREEN guard): cbm_find_cli now probes Windows PATHEXT (.exe/.cmd/.bat/.ps1,
  commit 0485d3f), so opencode is resolvable. Guards that fix on a fake
  opencode shim placed on PATH. Candidate to close after reporter retest.

(#548 held: its agent draft spins up a live HTTP server in a thread to exercise
handle_browse; reworking to a lighter harness before adding.)

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 07:01:59 +02:00
Martin Vogel 806da45896 test(repro): more install/UX + persistence reproductions for #607, #403, #434
- #607 (RED, DATA LOSS): cbm_cmd_install prints 'must be rebuilt' then calls
  cbm_remove_indexes() which unlink()s every .db in the cache and never rebuilds
  — re-running install destroys the user's index. Asserts the DB survives.
- #403 (RED): cbm_should_skip_dir excludes neither Antigravity / Programs /
  AppData, and the .gitignore path is git-gated, so an IDE install tree is fully
  indexed. Asserts a sentinel under the install dir is not discovered.
- #434 (RED): the incremental dump_and_persist only re-exports the artifact when
  one already exists and never receives the persistence flag, so persistence=true
  is silently dropped on first index. Asserts the artifact exists after one
  index_repository with persistence=true.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 01:49:57 +02:00
Martin Vogel ed15d0611a test(repro): install/UX reproductions for #570, #409, #431
In-process via cli.h + a temp HOME + the cbm_build_install_plan_json dry-run
oracle (no real filesystem mutation of the user's config):

- #570 (RED): install_cli_agent_configs hardcodes the Codex hook target to
  ~/.codex/config.toml and never checks for ~/.codex/hooks.json, so the hook is
  planned into config.toml even when hooks.json is in use (dual registration).
- #409 (GREEN guard): the legacy blocking PreToolUse gate regression is already
  fixed (cbm_install_hook_gate_script writes the non-blocking hook-augment shim);
  this guards the upgrade/overwrite scenario no existing test covered. Issue is a
  candidate to close after reporter retest.
- #431 (RED): the VSCode install path computes only Code/User/mcp.json and has no
  profile-aware API, so Code/User/profiles/<id>/mcp.json is never written; the
  plan omits the profile path entirely.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 01:43:54 +02:00
Martin Vogel 78d1aff20d test(repro): Rust trait-method extraction depth for #333
push_nested_class_nodes (extract_defs.c) re-queues only class-like/field/decl
children of a trait body — never function_item / function_signature_item — so
abstract + default trait methods are dropped from the graph (a major source of
the shallow-Rust-index degradation). impl-block methods (separate code path) are
extracted, serving as the positive control. Asserts all three trait-body methods
appear as defs; RED on current code.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 01:27:20 +02:00
Martin Vogel 8c35d5e2f4 test(repro): data-loss + watcher reproductions for #557, #520
- #557 (DATA LOSS): resolve_store() in mcp.c unlink()s the user's DB (+wal/+shm)
  with no backup when cbm_store_check_integrity() returns false — e.g. a project
  row whose root_path fails the path-shape SQL check. The test plants root_path
  "826" (from the issue evidence) under a CBM_CACHE_DIR temp dir, calls a tool
  that routes through resolve_store, and asserts the DB still exists OR a backup
  was made (RED: it is silently deleted).
- #520: detect_changes runs 'git diff', which never lists UNTRACKED new files, so
  a newly-created file is invisible until a manual re-index. Indexes a git repo,
  creates an untracked file, calls detect_changes, asserts the new file appears.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 01:19:33 +02:00
Martin Vogel 2534f3bb89 test(repro): crash + trace + gitignore reproductions for #627, #514, #510
- #627: query_graph crash — integer overflow in cypher.c cross_join_with_rels
  (node_count^2 * growth overflows int -> tiny malloc -> OOB write) on an
  OPTIONAL MATCH with an already-bound terminal node. Reproduced in a FORKED
  child (crash must not kill the runner); asserts the child is not signalled.
- #514: trace_path data_flow mode drops argument expressions — cbm_edge_info_t
  carries no properties_json, so the CALLS-edge arg text never reaches the MCP
  JSON. Asserts the arg expression appears in the data_flow response.
- #510: non-root .gitignore ignored — try_load_nested_gitignore() bails when the
  walk frame prefix is empty, so a directory's own .gitignore is never loaded
  when indexing a non-git-root subtree. Drives cbm_discover() directly and
  asserts an explicitly-ignored file is excluded.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 01:09:10 +02:00
Martin Vogel a8e274ce04 test(repro): fix harness include + #408 comment; add #571, #523, #546
Build fixes (wave 2 broke on all platforms):
- repro_harness.h: include <pipeline/pipeline.h> for cbm_project_name_from_path
  (-Werror=implicit-function-declaration).
- repro_issue408.c: the doc comment contained '["packages/*"]' whose '/*' opened
  a nested block comment (-Werror=comment); reworded.

New reproductions:
- #571: cbm_project_name_from_path strips CJK (per-byte [A-Za-z0-9._-] filter
  rewrites every UTF-8 continuation byte to '-'); a purely-CJK trailing path
  segment vanishes. Asserts the name is not the ASCII-only truncation.
- #523: cross-repo HTTP_CALLS — unindexed-lib guard in pass_calls.c drops the
  client call before the HTTP_CALLS edge is emitted, so cbm_cross_repo_match
  returns http_edges==0 for a byte-identical call/route. Asserts >=1.
- #546: trace_path splits a symbol duplicated by an ambient .d.ts into two nodes;
  inbound traversal walks only one, dropping callers by import style. Asserts
  BOTH the relative-import and alias-import callers appear.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 00:58:16 +02:00
Martin Vogel a84c59c27a test(repro): cross-file + trace reproductions for #408, #56, #480
First users of the shared repro_harness.h (validates the multi-file + MCP-tool
harness end to end):

- #408: STRONGER than the existing weak test_lang_contract.c guard (which any
  IMPORTS edge satisfies) — fixture has zero relative imports + no dependencies
  field, so the only possible IMPORTS edge is the workspace cross-package one
  packages/b -> @org/a; asserts >=1.
- #56: Rust multi-crate workspace; crate_b::run calls crate_a::helper; asserts
  CALLS >= 2 so an intra-crate edge can't mask the missing cross-crate edge.
- #480: precondition asserts CALLS>0 (edges exist), then drives the trace_path
  MCP tool and asserts the caller appears + the result is not the empty
  "callers":[] shape — isolating it as a traversal bug, not extraction.

All assert correct behaviour; RED on current code (board verifies).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 00:47:54 +02:00
Martin Vogel 463de270a2 test(repro): make the board robust to RED-test early-return leaks
A reproduction fails its assertion and returns before cleanup, so LeakSanitizer
flagged benign harness leaks on every red store-level test and _exit()'d,
swallowing the unflushed summary — repro.sh then misread it as a build failure
(Linux only; macOS/Windows have no LSan). Fixes:

- repro.sh: export ASAN_OPTIONS=detect_leaks=0 for the board run. Leak-cleanliness
  is not the board's signal (the RED rows are); the #581 leak bug gets a dedicated
  RSS-growth test. ASan's real checks (use-after-free, overflow) stay enabled.
- repro_main.c: setvbuf(stdout, _IONBF) so the summary + RED rows survive any
  abnormal _exit (sanitizer or crash).
- add tests/repro/repro_harness.h: shared multi-file index + store-query + fork
  crash-detector helpers (ported from the proven test_lang_contract.c harness)
  for the cross-file / store-level / crash reproduction waves.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 00:36:27 +02:00
Martin Vogel 8423b0b274 test(repro): -Itests fix + reproductions for #495, #521, #382
- Makefile: add -Itests to the test-repro-runner compile so repro files in the
  tests/repro/ subdir resolve "test_framework.h" (they sit one dir deeper than
  the existing tests/*.c, which find it relative to their own directory).
- #495: cfg-gated twin functions collapse — two mutually-exclusive #[cfg] Rust
  fns get identical qualified_name and the UNIQUE(project,qualified_name) upsert
  overwrites one; asserts the twins get distinct QNs.
- #521: Route nodes minted from URL string literals in infra/config files
  (try_upsert_infra_route has no source-vs-config guard); indexes a YAML-only
  fixture and asserts zero Route nodes.
- #382: Java class-level + marker_annotation decorators dropped; asserts @Entity/
  @RestController on the class and @Override on the method (strengthens the weak
  existing #382 method-only test).

All three assert correct behaviour and are RED on current code.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 00:25:40 +02:00
Martin Vogel 6e70a8b019 test(repro): scaffold cumulative bug-reproduction suite + cross-platform board
Stand up a separate, non-gating reproduce-first suite that holds one RED case
per open bug issue (the redness is the deliverable + the regression guard):

- tests/repro/ + repro_main.c -> `make test-repro` (its own runner with its own
  main + counters; deliberately EXCLUDED from ALL_TEST_SRCS so the gating
  `make test` / ci-ok required check stays green and PRs are not wedged)
- repro_extraction.c: first reproduction, #554 -- a C++ out-of-line method's
  inner CALLS edge must attribute to the class-qualified Method QN, not the
  Module; ties the call's enclosing_func_qn to the method definition's own
  qualified_name so a class-qualifier drop (the live root cause) fails it
- scripts/repro.sh: build+run the board; a build/link failure fails the job,
  while expected test redness is reported as the board state (job stays green)
- .github/workflows/bug-repro.yml: workflow_dispatch (platform filter) + qa/**
  push; runs the board on linux x2 / macos x2 / windows so many bug vectors can
  be reproduced on many platforms at once

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-26 00:09:23 +02:00
Martin Vogel b075f0506c Merge pull request #633 from DeusData/test/cpp-enclosing-attr-438
test(extract): guard C++ out-of-line method/ctor/dtor enclosing attribution
2026-06-25 22:47:19 +02:00
Martin Vogel 4953fcaf21 test(extract): guard C++ out-of-line method/ctor/dtor enclosing attribution
DCO / dco (push) Has been cancelled
After the C declarator-name walker was de-duplicated into one shared helper
(cbm_resolve_c_declarator_name_node), the C/C++ enclosing-function resolver now
resolves qualified names (Foo::bar) via resolve_qualified_name() and no longer
treats type_identifier as a terminal name. Add reproduce-first coverage so the
#438 fix cannot silently regress on the qualified-declarator path:

- cpp_out_of_line_method_caller_attribution: a call inside `void Foo::bar()` must
  attribute to the method, not the module.
- cpp_out_of_line_ctor_dtor_caller_attribution: calls inside `Foo::Foo()` and
  `Foo::~Foo()` must attribute to the special member, not the module.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-25 21:42:31 +02:00
Martin Vogel 66b3e3004b Merge pull request #614 from linze0721/berserk/fd632085-2b69-4b14-930b-47025d80d973
fix: get_architecture should honor path scope
2026-06-25 21:18:49 +02:00
Martin Vogel 677582ccf8 Merge pull request #539 from RithvikReddy0-0/fix/516-adr-persistence
fix(pipeline): preserve ADR across full re-index (#516)fix(pipeline): preserve ADR across full re-index (#516)
2026-06-25 21:18:33 +02:00
Martin Vogel 7d11db8ee4 Merge pull request #527 from Ravandevil25/fix/json-escape
fix(foundation): properly escape JSON control characters as \u00XX
2026-06-25 21:18:10 +02:00
Martin Vogel 1c3c5573c4 Merge pull request #463 from KerseyFabrications/fix/c-calls-function-source
fix(extract): attribute C/C++ CALLS edges to the enclosing function
2026-06-25 21:17:52 +02:00
Martin Vogel a76e97daaa Merge pull request #449 from isc-tdyar/fix/class-lines-zero
fix(extract): Class.lines always 0 for all languages
2026-06-25 21:17:35 +02:00
萧瑟 c80a294585 Merge branch 'main' into berserk/fd632085-2b69-4b14-930b-47025d80d973 2026-06-25 08:34:49 +08:00
Kris Kersey adc8304c57 refactor(extract): dedup C declarator-name walker into one shared helper
Addresses #463 review: the declarator-chain name resolver was copied into
helpers.c, extract_unified.c, and extract_defs.c, and CBM_DECLARATOR_DEPTH_LIMIT
was #defined twice -- the same triplication drift that caused #438.

- Add cbm_resolve_c_declarator_name_node() to helpers.{c,h} as the single
  source of truth, carrying is_c_terminal_name/resolve_qualified_name with it.
- Route the defs, calls, and unified extractors through it.
- Hoist CBM_DECLARATOR_DEPTH_LIMIT into helpers.h; extract_defs.c's
  DECLARATOR_DEPTH_LIMIT now derives from it.

Canonicalizes on the original extract_defs.c logic (operator/destructor aware)
so defs behavior is unchanged and calls/unified now agree with it.

Test: full suite green except an unrelated ASan RSS-budget check; clang-format clean.

Signed-off-by: Kris Kersey <kris@kerseyfabrications.com>
2026-06-24 12:42:38 -04:00
Kris Kersey 13c3429651 fix(extract): attribute C/C++ CALLS edges to the enclosing function
A CALLS edge whose caller is a C/C++/CUDA/GLSL function was sourced to the
file's Module node instead of the calling Function. "Find callers of X"
returned a file path, outbound trace_path returned empty, and
(:Function)-[:CALLS]->(:Function) queries missed for these languages.

Root cause: the enclosing-function resolvers read only tree-sitter's `name`
field, but a `function_definition` node has none — the name lives in the
declarator chain (pointer/function/parenthesized/array declarators). So
func_node_name() (internal/cbm/helpers.c) and resolve_func_name_node()
(internal/cbm/extract_unified.c) returned NULL, the enclosing scope fell
back to the module QN, and the edge was attributed to the Module node. This
is the C counterpart to #220, which fixed the definition-naming path but not
the enclosing-call path.

Fix: descend the declarator chain to the innermost name node (mirroring
resolve_c_declarator_name in extract_defs.c, including qualified and operator
names) when a function_definition lacks a `name` field. Adds the regression
test c_caller_attribution asserting a C call's enclosing_func_qn is the
function, not the module.

Fixes #438

Signed-off-by: Kris Kersey <kris@kerseyfabrications.com>
2026-06-24 12:42:38 -04:00
saurav kumar 078e9e2d85 Merge branch 'main' into fix/json-escape 2026-06-24 20:36:59 +05:30
Saurav Kumar fdcafbb53f fix(foundation): properly escape JSON control characters as \u00XX
Signed-off-by: Saurav Kumar <sauravsk2507@gmail.com>
2026-06-24 20:33:52 +05:30
Berserk Agent e270ceb8a4 style(store,mcp): clang-format-20 for CI lint (#604)
Signed-off-by: Berserk Agent <berserk@agent.local>
2026-06-24 13:54:33 +00:00
Berserk Agent 55058c05f0 fix(arch): normalize path trailing slashes; align MCP path_scoped with store (#604)
Signed-off-by: Berserk Agent <berserk@agent.local>
2026-06-24 12:54:45 +00:00
Berserk Agent adf602ec94 fix(mcp): document path on get_architecture and emit root/scoped totals (#604)
Signed-off-by: Berserk Agent <berserk@agent.local>
2026-06-24 12:50:49 +00:00
Berserk Agent 9332593b26 Store path scoping for get_architecture
Signed-off-by: Berserk Agent <berserk@agent.local>
2026-06-24 12:38:11 +00:00
Martin Vogel 34efbc0bc5 Merge pull request #596 from DeusData/chore/triage-automation 2026-06-24 08:35:12 +02:00
RithvikReddy0-0 98c4fc345a fix(pipeline): harden ADR preservation and add regression test (#516)
Addresses review on #539.

- Free p->saved_adr in cbm_pipeline_free so it is not leaked on error
  paths that exit before the restore in dump_and_persist_hashes (e.g. a
  cbm_gbuf_dump_to_sqlite failure).
- Check cbm_store_adr_store's return value on restore and log an error
  instead of silently dropping the ADR (the original #516 symptom).
- Add reproduce-first test pipeline_adr_survives_full_reindex: index,
  store an ADR, force a full re-index by adding files, assert the ADR
  survives unchanged. Passes against the fix.

Signed-off-by: RithvikReddy0-0 <rithvikreddymukkara@gmail.com>
2026-06-24 01:27:32 +00:00
RithvikReddy0-0 7f622b1cde fix(pipeline): preserve ADR across full re-index (#516)
manage_adr stores ADRs in project_summaries, but a full re-index
(triggered by file changes or new files) deletes the DB in
try_incremental_or_delete_db and rebuilds it from the graph buffer,
which writes an empty project_summaries table. file_hashes were
re-persisted after the rebuild but project_summaries were not, so the
ADR was silently lost.

Fix: capture the ADR before the DB is unlinked, stash it on the
pipeline struct, and restore it after the rebuilt DB is reopened in
dump_and_persist_hashes. The incremental path is unaffected (it never
rewrites the DB). Verified: ADR now survives a full re-index.

Signed-off-by: RithvikReddy0-0 <rithvikreddymukkara@gmail.com>
2026-06-24 01:24:06 +00:00
Martin Vogel 170d5a82ab fix(ci): allow-list MSYS2 toolchain URL in binary string audit
The MSYS2 CLANG64 toolchain bakes its package-tracker URL
(https://github.com/msys2/MINGW-packages) into the static Windows .exe via
libc++/compiler-rt. The Layer 2 binary string audit flagged it as an
unauthorized URL, failing smoke-windows (both the standard and ui variants)
while Linux smoke stayed green. Add it to ALLOWED_URLS alongside the other
compiler/linker toolchain URLs (gcc.gnu.org, sourceware.org, launchpad).

Add tests/test_security_strings_allowlist.sh as a reproduce-first regression
guard: it reproduces the BLOCKED failure with a binary fixture and includes a
negative control proving a genuinely unauthorized URL is still rejected. Wired
into scripts/test.sh as Step 6.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-24 03:15:36 +02:00
Martin Vogel dc5a1aa675 Merge pull request #590 from DeusData/vendor/objectscript-grammar
chore(vendor): vendor the InterSystems ObjectScript tree-sitter grammars
2026-06-24 01:21:51 +02:00
Martin Vogel c37848a73c ci: add issue-triage bots (stale, label-actions, area-labeler)
DCO / dco (push) Has been cancelled
Three native GitHub Actions to automate the mechanical parts of issue
triage:

- stale.yml: actions/stale scoped to the awaiting-reporter label —
  warns at 21 days idle, closes at 35, auto-resets when the reporter
  replies. Never touches PRs or unlabeled issues.
- label-actions.yml + .github/label-actions.yml: posts a templated
  comment when duplicate or awaiting-reporter is applied (duplicates are
  linked, not auto-closed).
- issue-labeler.yml + .github/issue-labeler.yml: adds area labels
  (windows, stability/performance, parsing/quality, editor/integration,
  ux/behavior, cypher, language-request) from title/body keywords.
  Additive only; base bug/enhancement labels still come from the forms.

All third-party actions pinned to full commit SHAs with least-privilege
per-job permissions (issues: write only where required).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-24 01:18:29 +02:00
Martin Vogel 5352d5229d Merge pull request #591 from DeusData/fix/security-alerts
chore(security): resolve flagged Scorecard + Dependabot alerts
2026-06-24 01:15:35 +02:00
Thomas Dyar 36e127c113 fix(extract): Class node lines property always 0
extract_class_def() sets start_line and end_line from the tree-sitter
node span, but left def.lines = 0 (zeroed by memset at function entry).
The equivalent function push_method_def() correctly computes
  def.lines = end_line - start_line + 1
The same one-liner was simply missing from the class extraction path.

This affects all languages — Python, TypeScript, Go, and any other
language where Class nodes are extracted via extract_class_def().

Regression test: after indexing a project, at least one Class node must
have c.lines > 0.

Signed-off-by: Thomas Dyar <tdyar@intersystems.com>
2026-06-23 19:14:09 -04:00
Martin Vogel a3336bf346 chore(security): resolve flagged Scorecard + Dependabot alerts
- graph-ui: bump vite ^6.4.2 -> ^6.4.3 and add overrides pinning the transitive
  form-data >=4.0.6 and @babel/core >=7.29.6 (all dev-scope build/test deps, not
  shipped in the binary). Clears the 4 open Dependabot alerts and Scorecard's
  VulnerabilitiesID. `npm audit` now reports 0 vulnerabilities.
- codeql.yml: move `security-events: write` from the workflow top level to the
  `analyze` job (top level is now `contents: read`), resolving Scorecard's
  TokenPermissionsID least-privilege finding. CodeQL still uploads results from the
  job-scoped token.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-24 00:34:05 +02:00
Martin Vogel 880f899099 Merge pull request #532 from DeusData/dependabot/github_actions/softprops/action-gh-release-3.0.1
build(deps): bump softprops/action-gh-release from 3.0.0 to 3.0.1
2026-06-24 00:30:35 +02:00