incr_full_index bumps the full-index RSS limit from 2048MB to 2816MB to absorb
ARM's documented ~2385MB peak (vs x86's ~1870MB on the same index), but gated
the bump on a 16KB page size. ARM Linux uses 4KB pages, so the bump never fired
there even though glibc's per-CPU malloc arenas + allocation rounding still
inflate RSS to ~2385MB — CI's ubuntu-22.04-arm measured 2386MB against the
un-bumped 2048 limit and failed (the value is the documented ARM peak, i.e. not
a regression: the page-size heuristic just missed 4KB-page ARM).
Also apply the higher ARM budget on any ARM target (__aarch64__/__arm__/
_M_ARM64). The guard still catches a real leak (GBs over 2816) while no longer
false-failing on 4KB-page ARM. x86 stays at the tight 2048 budget.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The incremental full-index RSS-delta assertion used a fixed 2048 MB
ceiling that 16 KB-page ARM hosts exceed -- larger page granularity
inflates resident set. Raise the ceiling to 2816 MB when the page size
is >= 16 KB, keeping the tighter bound on 4 KB-page hosts.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
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>
detect_changes advertised a `since` parameter in its inputSchema but the
handler never read it — it always diffed against base_branch (default
"main"), so detect_changes(since="HEAD~10") silently returned the wrong or
empty result when HEAD was on the default branch.
Fix: read `since` and, when present, route it through base_branch so the
existing shell-arg validation (cbm_validate_shell_arg) and the
`<base>...HEAD` diff apply unchanged; `since` takes precedence over
base_branch. Also narrows the schema description — the prior "date" form
(e.g. 2026-01-01) is not a revision and never worked through this path — and
documents the inherited three-dot semantics. Adds regression tests
tool_detect_changes_since and tool_detect_changes_since_precedence.
Refs #371
Signed-off-by: Kris Kersey <kris@kerseyfabrications.com>
MATCH (c:Class)-[:DEFINES_METHOD]->(m:Method) returned at most 10 results
for any class, regardless of how many methods it actually has.
Root cause: bind_cap was set to scan_count (the number of nodes matched in
the initial pattern — typically 1 when querying a single class by name).
max_new = bind_cap * 10 = 10, so the edge expansion loop exited after
collecting 10 results. No error, no warning, no truncation indicator.
This is language-agnostic: any class with more than 10 methods in any
language was silently truncated. The fix is two characters:
bind_cap = scan_count > max_rows ? scan_count : max_rows
Regression test: a Python class with 15 methods must return all 15 via
MATCH (c:Class)-[:DEFINES_METHOD]->(m:Method) with label filtering.
Signed-off-by: Thomas Dyar <tdyar@intersystems.com>
Add scripts/check-no-test-skips.sh (run from lint) which fails the lint phase on any plain SKIP() or direct tf_skip_count manipulation; only SKIP_PLATFORM() (for genuinely platform-specific tests) is tolerated. Add FAIL() and SKIP_PLATFORM() helpers to the test framework and convert the remaining SKIP()/perf-gated skips across the suite into pass-or-fail assertions, so a suite that cannot meet its preconditions reports a red failure instead of a silent skip.
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>
Inject incr_test_injected/helper in suite setup so tool tests work
with CBM_SKIP_PERF=1. Use different function names in incr_modify_file
to avoid duplicate injection. Update baseline counts after injection.
Lower graph thresholds for sparse checkout on CI.
CBM_SKIP_PERF=1 now skips only phases 2-7 (incremental delta, stress,
perf regression) inside the suite. Phase 1 (initial index) and phases
8-30 (135 tool integration tests) always run. This keeps ~2672 tests
on CI vs the full ~2692 locally.
Also fix Windows build: guard symlink() with #ifndef _WIN32.
- 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
On CI runners, skip docs/ and tests/ directories when cloning
FastAPI (62% of 18K files). The fastapi/ package source remains
intact for all test assertions. Locally, full clone is preserved.
Shared CI runners are too variable for hard timing thresholds.
Performance is still logged and warns above 15s, but no longer
blocks the test suite. Added 30min timeout on test-unix jobs.
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 = "..." }).
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.
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).
- 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
Comprehensive test suite using real repo (FastAPI 0.99.1, ~1100 files):
- Full index baseline with perf metrics (nodes, edges, RSS, timing)
- Incremental: modify/add/delete/rename files, noop, formatter run
- Adversarial: empty file, syntax errors, 5000-line function, binary
- Stress: rapid reindex, batch 20 files, delete-all + re-add
- Accuracy: incremental vs full within ±2 nodes/edges
- MCP tools: all 14 tools, every parameter, content validation
- Error handling: bad project, missing params for each tool
- Performance: 5s timeout on every tool call
Fix use-after-free in detect_changes and manage_adr:
yyjson_mut_arr_add_str stored pointer to stack buffer without copy.
Changed to yyjson_mut_arr_add_strcpy / yyjson_mut_obj_add_strcpy.