Commit Graph

7 Commits

Author SHA1 Message Date
Martin Vogel 751752bd21 fix(fqn): preserve full filename in File-node QNs so sibling files don't collide
DCO / dco (push) Has been cancelled
cbm_pipeline_fqn_compute stripped the file extension for EVERY qualified
name, including File-node QNs (name=="__file__"). Two different files
whose names share a stem therefore collided on the File QN and the
graph kept only one node per stem:

- .env / .env.local / .env.production all strip to ".env" — only one
  survives per directory (#1077).
- a C/C++ header and its same-stem source (NodeController.h vs .cpp)
  strip to the same stem, so the header got no File node of its own,
  leaving it disconnected (#964's remaining half after #983 fixed the
  include→Class resolution).

File-node QNs now keep the full filename (tokenize_path splits on '/'
only, so the extension rides in the last segment and stays unique).
Extension stripping is retained for MODULE/symbol QNs (name==NULL or a
symbol name) — that stem unification is load-bearing for C/C++
declaration↔definition cross-file resolution, and is left untouched.
All 26 __file__ QN sites route through this one function, so node
creation and every lookup stay consistent.

Reproduce-first:
- fqn_file_qn_preserves_dotfile_variants_issue1077 and
  fqn_file_qn_distinguishes_same_stem_header_source_issue964 assert the
  distinct File QNs (RED before: both collide to the stripped stem).
- fqn_module_qn_still_strips_extension guards that module QNs are
  unaffected.
- repro_issue964 now asserts the header keeps its own File node AND is
  connected (CONTAINS_FILE + DEFINES the class it declares), matching
  the reporter's zero-inbound disconnection metric — GREEN.

Closes #1077
Closes #964

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-16 01:21:45 +02:00
Martin Vogel db20e53459 fix(fqn): cap derived project-name length to avoid ENAMETOOLONG
DCO / dco (push) Has been cancelled
cbm_project_name_from_path hex-encodes non-ASCII path bytes (#571), but had no
length cap -- a deep CJK / non-ASCII path triples in length past the
filesystem's 255-byte filename-component limit, so <cache>/<name>.db becomes
un-openable (ENAMETOOLONG).

Cap the derived name at FQN_MAX_NAME_LEN (200): names within the cap are
returned UNCHANGED (no drift for already-indexed projects), while a longer name
keeps its first (CAP-9) bytes plus an FNV-1a hash of the full name as a "-%08x"
suffix, so distinct long paths stay distinct. The hex encoding scheme is
unchanged.

Distilled from #624 by Matt Van Horn (the ENAMETOOLONG catch); the rest of that
PR was redundant with the #571 fix already on main and would have swapped the
encoding scheme, causing project-name drift.

Reproduce-first: project_name_length_capped_issue624 builds a deep CJK path
(~376-byte raw name) and asserts the result is <= 200, validator-safe, and that
two long paths differing only in the trailing segment map to different names; a
short CJK path stays byte-identical (no drift). RED (376 > 200) -> GREEN. Full
suite 5738/0.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Co-Authored-By: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-07-01 21:23:12 +02:00
Martin Vogel b7f1a71a6b style: apply clang-format to new mcp/ui/logging lines
DCO / dco (push) Has been cancelled
The CI lint gate (scripts/lint.sh --ci, clang-format-20) flagged 7 files whose
new lines were not run through the project formatter. Reformat only those lines
(line wrapping / continuation alignment) — no behavior change.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-28 21:49:17 +02:00
Martin Vogel 345425a1bb merge main into mcp protocol branch
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-28 21:34:18 +02:00
Martin Vogel d5414111b3 feat(ui): add i18n and index picker UX
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-28 21:21:32 +02:00
Martin Vogel 5595ce47f9 fix(naming): derive only validator-safe project names (#349)
cbm_project_name_from_path replaced only "/" and ":" with "-", leaving
spaces, "@", "+", unicode, etc. intact. resolve_store (via project_db_path)
gates on cbm_validate_project_name, which allows only [A-Za-z0-9._-]. So a
repo like "/home/u/my project" was indexed and shown by list_projects (which
opens the .db file directly), yet index_status/search_graph reported
project-not-found because resolve_store rejected the space.

Normalize every rejected character to "-", collapse consecutive dots (the
validator forbids ".."), and strip leading dots, so a derived name always
satisfies cbm_validate_project_name and round-trips through resolve_store.
2026-05-31 17:22:02 +02:00
Martin Vogel 7f579f91ad Add 480+ tests, fix 3 bugs discovered by new test coverage
New tests (6481 lines across 23 files):
- Arena: reset invariants, growth, sized init, destroy safety
- Dynamic array: capacity, remove, clear, grow patterns
- FQN: module/package/class name computation (592 lines)
- Graph buffer: node/edge CRUD, dedup, merge, concurrent access
- Hash table: collision, resize, iteration, edge cases
- MCP: tool dispatch, argument parsing, error handling
- Memory: allocation tracking, collection, limits
- Pipeline: test detection (path + func name patterns)
- Store: node/edge CRUD, search, batch ops, persistence
- String: intern dedup, util edge cases, YAML parsing (1105 lines)
- Traces: ingestion, dedup, query
- Watcher: baseline, polling, change detection
- Worker pool: task distribution, completion

Bugs found and fixed:
1. Arena reset overflow: block_size not reset to block_sizes[0]
   after growth — subsequent allocations could overflow blocks[0]
2. Test path detection: missing __tests__/, tests/, spec/ directory
   patterns and _spec.rb suffix
3. Test func detection: "Testable" falsely matched as Go test —
   now requires uppercase or end-of-string after "Test" prefix
2026-03-24 23:48:23 +01:00