Commit Graph
51 Commits
Author SHA1 Message Date
Andrew Hundt 393d3a297f fix(mcp): report blocked automatic indexing by active tool mode
Previously, build_project_list_error_srv discarded whether automatic indexing was disabled or stopped by auto_index_limit and always recommended index_repository, even when streamlined tools/list hid that tool. Double-quoted path examples could also invalidate the nested structured JSON response.

Record request-thread-owned block state in maybe_auto_index and cbm_mcp_auto_index_within_limit. mcp_index_recovery_action at src/mcp/mcp.c:3937 now uses the existing profile/reveal authorities: classic or revealed streamlined mode calls index_repository directly, unrevealed streamlined mode calls _hidden_tools and refreshes tools/list first, and profiles without that tool use the CLI. Existing synchronous first-use recovery still runs before any user action is emitted. Centralize streamlined/classic config values in src/cli/cli.h:383.

tests/test_mcp.c:9617 covers auto_index=false, bounded file-limit rejection, classic, and revealed streamlined behavior; each response must parse as JSON with structuredContent and must not claim auto_indexing. Verified: focused ASan/UBSan test 1/1; scripts/check-source-safety.sh; git diff --check; git clang-format --diff; staged private-path scan.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-20 00:32:11 -04:00
Andrew Hundt 45c11176c9 merge(upstream): retain streamlined APIs with indexed impact analysis
Merge upstream/main 7d6cdb23 into api-consolidation 0fcb7e10 as a tested capability superset.

Retain the branch's streamlined, classic, and hidden-reveal MCP surfaces; JSON/TOON output; read-only Cypher execution; semantic search; dependency indexing; PageRank; incremental indexing; and modular harness installer. Integrate upstream ObjectScript routine/UDL extraction, macro and return-type call resolution, Python alias and C++ header resolution, atomic SQLite publication, SCC/cycle reporting, Cypher deadlines, and bounded multi-source impact traversal.

Fix merge-specific defects in handle_detect_changes project validation, cbm_pipeline_release_objectscript_tables ownership, no-sanitizer test defines, focused-suite registration, portable config publication, and installed streamlined guidance. The guidance keeps auto-index/get_code/query_graph discovery while adding coverage tiers and removes the stale fixed row ceiling.

Verification: ASan/UBSan full runner 7,155 passed with 27 sandbox-loopback cases separately passing in the escalated HTTP suite (44 passed, 1 Windows-only skip); TSan 449 passed; incremental leak gate 514 passed with 0 leaks; MCP 261; CLI 232; extraction 313; tool consolidation 113; Cypher 179; SQLite writer 16; configuration editors 127; integration 28; language contracts 38; PageRank 60. scripts/check-source-safety.sh and git diff --cached --check pass.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-19 14:09:36 -04:00
Andrew Hundt ad9d637402 feat(config): add default_response_format (toon/json) canonical enum and key
query_graph and related tools previously had no config-controlled
default output encoding, and the TOON/JSON format enum lived nowhere
canonical, risking drift between the wire strings different call sites
might use. Add cbm_mcp_output_format_t {CBM_MCP_OUTPUT_TOON,
CBM_MCP_OUTPUT_JSON, CBM_MCP_OUTPUT_INVALID} plus the "toon"/"json" wire
string constants to mcp.h with a drift-prevention comment, as the single
source of truth for every response-format call site.

Add the default_response_format config key to CBM_CONFIG_REGISTRY in
cli.c (default "toon", validated to "toon" or "json" only via
cbm_config_set), so `codebase-memory-mcp config set default_response_format
json` persists a default and CBM_MCP_OUTPUT_INVALID.

Verification: make -f Makefile.cbm test — 6850 passed, 1 skipped, 0
failed, ASan/UBSan clean.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-19 01:10:36 -04:00
Martin Vogel cc5f71bdff fix(hook,smoke): teach the last two consumers the tree output shape
The PR CI caught two consumers the format migration missed — both parsed
tool output by its old shape and failed silently or with a wrong count:

- hook-augment built its PreToolUse additionalContext by reading the
  legacy 'results' object-array from search_graph format:json; after the
  json-tree reshape that key no longer exists, so the hook emitted nothing
  (caught end-to-end by tests/windows/test_hook_augment.py). The parser
  now walks groups -> qn_prefix/file + column-ordered rows. A new local
  test feeds the parser the LIVE server envelope, so any future drift
  between response shape and hook parser fails in the normal suite on
  every platform — not only in the Windows CI guard. Reproduced RED
  (ctx NULL, the exact CI failure) before the fix, GREEN after.

- smoke-test.sh carried six old-shape parsers (callers[N], rows[N]{,
  clusters[N], semantic[N]{, and the assert_toon_table helper); the tree
  headers never matched, so trace verification read 0 callers. All six
  updated to the tree contract; the full smoke script passes end-to-end
  locally.

cli suite 222 passed; lint clean; scripted smoke ALL PASSED.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-18 10:36:08 +02:00
Andrew Hundt 78245da17e fix(install): support Kilo CLI and remove PATH blocks
Standalone Kilo stores global local MCP servers in ~/.config/kilo/kilo.jsonc, while the installer only handled the legacy VS Code extension adapter. Detect standalone Kilo separately and reuse cbm_upsert_opencode_mcp()/cbm_remove_opencode_mcp() for its documented top-level mcp, type=local, command-array JSONC schema.

Uninstall also left the exact '# Added by codebase-memory-mcp install' PATH block in shell startup files after deleting the binary. Add cbm_remove_owned_path() and scan .zshrc, .bashrc, .bash_profile, .profile, and Fish config, removing only marker-owned exact blocks through atomic writes while preserving user content and dry-run behavior.

Document both Kilo targets in README.md with the official Kilo MCP configuration reference. Add detection/plan/JSONC/foreign-entry/uninstall coverage plus POSIX/Fish PATH ownership tests in tests/test_cli.c.

Verification on native Apple Silicon macOS: intentional compile-red tests captured missing kilo_cli and cbm_remove_owned_path; ASan/UBSan CLI suite passed 150/150; make -j2 -f Makefile.cbm cbm passed with -O2 -DCBM_BIND_TS_ALLOCATOR=1 and ad-hoc signing. An isolated 17-target install produced 32 byte-identical files across repeated installs; uninstall removed every owned reference and binary while preserving a foreign Kilo server. No native Windows execution is claimed.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-16 09:25:45 -04:00
Andrew Hundt 53c38455e8 feat(config): apply exact capability presets atomically
Add cbm_config_apply_preset() in src/cli/cli.c with six named capability sets committed through one SQLite BEGIN IMMEDIATE transaction. Reuse the existing CBM_CONFIG_* keys from cli.h, depindex.h, pagerank.h, and pipeline.h instead of defining parallel settings.

Expose 'config preset list' and 'config preset apply <name>'. Return a nonzero status and identify any environment override whose effective value differs from the stored preset, so comparisons cannot silently run with a mixed configuration.

Document the quality and ablation presets in docs/CONFIGURATION.md. Cover the exact streamlined-quality and minimal-indexing values plus unknown-name rejection in tests/test_cli.c.

Verification: macOS Apple Silicon ASan/UBSan CLI suite 147/147 passed; optimized -O2 binary listed and applied classic-quality in an isolated cache; CBM_TOOL_MODE=streamlined correctly caused classic-quality to exit 1 with the effective-value warning; git diff --cached --check passed.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-16 09:01:18 -04:00
Andrew Hundt 0434df337c feat(install): configure Claude Desktop MCP server
Previous behavior: install detection and receipts omitted Claude Desktop even when its platform config directory existed, so claude_desktop_config.json required manual registration.

Add cbm_claude_desktop_config_path() at src/cli/cli.c:1267 and route the detected client through the existing mcpServers editor writer at lines 4504-4509. Route uninstall through cbm_remove_editor_mcp() at lines 5232-5237 so only the codebase-memory-mcp entry is removed.

Add plan/install/uninstall ownership coverage at tests/test_cli.c:2157 and platform-directory detection coverage at line 2479. Document the target in README.md, docs/CONFIGURATION.md, and the CLI help output.

Verification: CBM_ONLY_SUITE=cli build/c/test-runner (ASAN+UBSAN, native Apple Silicon macOS): 146 passed. CBM_ONLY_SUITE=cli build/c/test-runner-nosan: 146 passed. Native Windows execution was not performed.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-16 07:01:10 -04:00
Andrew Hundt cfc168bd5d feat(install): configure Qwen ForgeCode and Windsurf
Detect the documented Qwen Code, ForgeCode, and Windsurf config roots and register codebase-memory-mcp using each client's native mcpServers JSON path. Add owned QWEN.md and AGENTS.md instruction blocks where the clients load global guidance.

Use the same code paths for install plans and uninstall. Lifecycle tests preserve foreign MCP servers and user-authored instructions while removing only codebase-memory-mcp entries; plan tests verify no files are written.

Document the complete supported-client matrix and correct the Claude hook description. The focused ASan/UBSan CLI suite passes 144 tests.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-15 14:44:49 -04:00
Andrew Hundt 59def6aaeb merge(upstream): integrate main through Laravel route fixes
Merge upstream/main at 2469ecc3 into integrate-upstream-split-search-tools while retaining branch-specific incremental indexing, MCP API consolidation, and graph extraction behavior.

The staged tree adds upstream's Mojo and Perl grammar support, issue reproduction suites, Graph UI changes, Windows smoke coverage, TOON graph output, subprocess supervision, and Laravel facade route handling. Conflict resolutions in src/pipeline/httplink.c and pass_httplinks.c retain dynamic growth and IMPORTS edge identity; scripts/smoke-test.sh and scripts/soak-test.sh retain hermetic cache isolation.

Validation against the merge plus the follow-up working-tree reconciliation: ASan/UBSan MCP suite 216/216 passed. Follow-up semantic and concurrency fixes remain intentionally unstaged for the next focused commit.
2026-07-14 01:47:43 -04:00
Martin Vogel a537d3bd84 fix(cli): make Windows Claude hooks shell portable
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-13 02:18:10 +02:00
Martin Vogel d6c9d28bf5 style: apply current C formatting
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-13 02:00:32 +02:00
Martin Vogel f0db224140 feat: add coverage-aware agent integrations
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-13 01:50:03 +02:00
Martin Vogel a3903caa0b feat(cli): expand agent integration coverage
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-13 01:50:02 +02:00
Martin Vogel 783892aa63 fix(install): give Aider CLI-form instructions instead of MCP tool calls
Aider has no MCP support - it reads CONVENTIONS.md but can only run
shell commands. The installer wrote the shared MCP-tool-centric
instructions there, telling the model to call search_graph(...) etc.,
tools Aider cannot invoke; a reporter reasonably asked how that was
ever supposed to work (#1032).

Aider now gets a dedicated variant: the same discovery priority
expressed as runnable codebase-memory-mcp cli commands (usable via
/run), including first-index and list_projects bootstrapping, with the
no-MCP constraint stated explicitly.

Closes #1032

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-12 19:18:20 +02:00
Martin Vogel 9a03ed3fd1 Merge pull request #664 from mvanhorn/feat/651-feat-auto-install-support-for-the-junie-
feat: auto-install support for the Junie agent
2026-07-05 01:23:46 +02:00
Martin VogelandAndy11-cpu aa153166d7 feat(watcher): auto_watch config gate for background watch registration (default on)
Add the auto_watch config key (default: true) and route both session
watcher-registration sites in mcp.c (autoindex completion and the
already-indexed connect path) through a register_watcher_if_enabled()
helper. When disabled, the skip is logged as a short structured line
(watcher.register.skipped reason=auto_watch_off).

Default is TRUE (opt-out): existing users keep background auto-sync
unchanged; the knob exists for multi-project users who want each
session contained to explicit indexing.

Distilled from the auto_watch half of PR #625. The PR's bundled
project-index dedup commit is excluded here — it belongs to #754's
own review. Unlike the original PR, no watch registration is added
to the index_repository handler (none exists on main; adding one
would be new behavior beyond the gate), and the default is flipped
from off to on to preserve current behavior.

Tests: default-unset registers the watcher on connect (guards the
no-behavior-change promise); auto_watch=false registers nothing —
verified RED against the ungated production code, GREEN with the gate.

Co-authored-by: Andy11-cpu <canada11@duck.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-04 14:09:00 +02:00
Andrew Hundt 3b2b552a15 fix(cypher): align query row defaults with upstream
Restore the Cypher executor safety ceiling to upstream's 100000 rows and expose the MCP query_graph default as query_max_rows. Explicit max_rows arguments remain caller-authoritative; omitted max_rows uses the config default. Add CLI registry and MCP coverage for the new discoverable default.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-03 22:20:15 -04:00
catsmonster 4bb9effe4c fix(hook): make hook-augment work on Windows drive-letter paths
hook-augment's PreToolUse Grep/Glob augmenter required POSIX-style
'/'-prefixed absolute paths in two guards, so a Windows cwd (C:\repo or
C:/repo) always failed: the _WIN32 cwd check returned early, and the
walk-up loop guard (dir[0] == '/') never iterated. The result was a
structural no-op on Windows — zero additionalContext for every Grep/Glob,
even for an exactly-indexed symbol.

Add cbm_hook_path_is_abs(), accepting POSIX "/..." and Windows "X:/..." roots;
normalize backslashes to forward slashes on the Windows cwd; and stop the
parent-climb at the drive root as well as the POSIX root. POSIX behavior
is unchanged.

Adds a cli_hook_augment_path_is_abs regression test (the predicate is
exposed as cbm_hook_path_is_abs via cli.h) covering POSIX and Windows
drive roots — it fails on the pre-fix POSIX-only guard and passes after.

Verified with that test plus a standalone walk self-test (full path
resolves first, then climbs to one level below the drive root, symmetric
to POSIX); clang-format clean on all three files; clang -fsyntax-only on
the translation unit. Not built through the full toolchain locally (no
make/zlib) — relying on Windows CI to confirm the build.

Fixes #618

Signed-off-by: catsmonster <shaked.brand@gmail.com>
2026-07-01 06:19:30 -06:00
Andrew Hundt 8335b78719 docs(cli): clarify hook stdout semantics
Make SessionStart hook comments explicit that stdout is harness-injected session context, not MCP protocol output. This removes vague same-methodology wording without changing install or hook behavior.

Validation: CBM_ONLY_SUITE=cli ./build/c/test-runner; bash scripts/check-source-safety.sh; git diff --check.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-06-30 17:19:05 -04:00
Martin Vogel 3c2c12006f feat(cli): accept flags, stdin, and --args-file for tools + per-tool --help (#680)
The CLI only accepted a single inline JSON argument (cbm cli <tool> '<json>'),
which PowerShell mangles on Windows and which made `cli <tool> --help` return
"repo_path is required" -- the "--help" token was parsed as the JSON args, and
there was no per-tool help at all.

run_cli now resolves tool arguments by precedence: --args-file <path>, a raw
JSON object (back-compat), --flag / --flag=value / bare-boolean flags, piped
stdin, then empty {}. Flags are converted to a JSON object via the tool's
input_schema: kebab-case keys map to snake_case, values are typed
(string/integer/boolean), and repeated flags accumulate into array-typed
properties (--semantic-query a --semantic-query b -> ["a","b"]). stdin and
--args-file are UTF-8-clean and bypass shell quoting entirely (the robust path
on Windows). `cli <tool> --help` prints usage + the tool's flags, generated
from the same input_schema the MCP tools/list advertises -- no hand-maintained
table.

cbm_mcp_tool_input_schema() exposes a tool's schema; cbm_cli_build_args_json()
and cbm_cli_print_tool_help() do the conversion and help.

Reproduce-first: 8 cli tests (string / integer-not-string / bare-boolean /
repeated-array / kebab->snake / --key=value with spaces / bad-positional-errors
/ help) -- RED on a stub, GREEN after. Full suite 5730/0.

Note: true CJK-path support on Windows still needs a UTF-8/wmain entry point
(argv is ANSI-codepage-mangled upstream of parsing); stdin/--args-file mitigate
it and are tracked separately.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-30 15:44:36 +02:00
Andrew Hundt 26f574c215 fix(mcp): honor bm25 search_limit
search_graph documented limit as configurable through search_limit, but the BM25 query path used its internal fallback when callers omitted limit. That made default pagination depend on search mode.

Read the config-backed default once in handle_search_graph, apply it to both BM25 and regex/vector paths, and share the search_limit config-key definition with CLI/tests.

Add an MCP regression that sets search_limit=1, omits the request limit, and verifies BM25 returns one result with has_more=true.

Validation: make -f Makefile.cbm build/c/test-runner; CBM_ONLY_SUITE=mcp ./build/c/test-runner; CBM_ONLY_SUITE=tool_consolidation ./build/c/test-runner; CBM_ONLY_SUITE=cli ./build/c/test-runner; bash scripts/check-source-safety.sh; git diff --check.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-06-30 07:31:10 -04:00
Andrew Hundt 5f4ca14968 fix(cli): decouple session hook matchers
Use the Claude SessionStart matcher array length instead of the unrelated NUM_DIRS constant, and expose the helper with a Claude-specific name that matches the Gemini session hook API.

Add a focused CLI regression test that verifies startup, resume, clear, and compact SessionStart hooks are all installed and removed.

Validation: make -f Makefile.cbm build/c/test-runner; CBM_ONLY_SUITE=cli ./build/c/test-runner; bash scripts/check-source-safety.sh; git diff --check.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-06-30 05:35:11 -04:00
Shane McCarron 64af0b8c7e feat(install): inject CMM code-discovery reminder into Claude subagents
Subagents spawned via the Agent tool do not fire SessionStart, so the
existing SessionStart reminder never reaches them — they start without the
codebase-memory-mcp code-discovery guidance and fall back to grep/file-read.

Register a Claude Code SubagentStart hook (matcher "*") that injects a leaner
variant of the protocol via JSON additionalContext, omitting the
index_repository step since the parent session has already indexed the
project. SubagentStart injects context only via a JSON object on stdout, not
plain text, so the generated script emits a static JSON literal — no runtime
escaping and no python3/jq dependency. Advisory only; installed and removed
alongside the SessionStart hook in install_claude_code_config.

Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
2026-06-29 08:42:36 -05:00
Andrew Hundt a0581987f5 fix: align OpenClaw and worktree discovery
Port upstream OpenClaw MCP config behavior to the fork branch: OpenClaw now writes nested mcp.servers entries with enabled, command, and args instead of the generic mcpServers shape, while preserving existing config.

Also skip .claude-worktrees during discovery to avoid indexing stale duplicate worktree content alongside the existing .claude and .worktrees exclusions.

Verified: build/c/test-runner; build/c/codebase-memory-mcp; CBM_ONLY_SUITE=cli (107); CBM_ONLY_SUITE=discover (84).
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-06-28 17:21:55 -04:00
Andrew Hundt ba3d97c66a fix: bound autoindex with discover filters
Use the discover walker for MCP autoindex file-limit checks instead of shelling out to git ls-files, so non-git roots and ignored files follow the same filters as indexing.

Add typed effective config helpers so env-backed registry settings such as CBM_AUTO_INDEX_LIMIT and CBM_REINDEX_ON_STARTUP are honored consistently by MCP startup logic.

Repair the CBM_ONLY_SUITE discover allowlist and add regressions for bounded non-git discovery counts and env-over-db config priority.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-06-28 16:41:31 -04:00
Andrew Hundt b0858ee1b6 fix: preserve config store during index cleanup
Install, update, and uninstall cleanup paths are scoped to project indexes, but the old .db predicate also selected _config.db. Add a shared project-index predicate, exclude the persistent config store, and keep list/count/remove behavior consistent.

Verification: make -f Makefile.cbm build/c/test-runner; CBM_ONLY_SUITE=cli build/c/test-runner; make -B -f Makefile.cbm build/c/codebase-memory-mcp.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-06-28 16:14:36 -04: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
Matt Van Horn 3d4979ed64 feat: add auto-install support for the Junie agent
Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-06-27 23:29:52 -07:00
Caio Ribeiro 2358b3c452 Fix OpenClaw MCP config install path
Signed-off-by: Caio Ribeiro <caio.ribeiro.clw@gmail.com>
2026-06-27 23:17:49 +00:00
Andrew Hundt 92f3b86f7a merge(upstream/main): integrate DeusData main into api-consolidation
Deep --no-ff merge of upstream DeusData/main (597 commits, merge-base 988d975)
into fork api-consolidation (HEAD 3018b22), producing a superset that combines
upstream breadth with the fork's surviving depth.

Upstream additions integrated: semantic/embedding search (vendored/nomic),
minhash/SimHash, cross-repo + cross-file LSP + route + pkgmap passes, artifact
import/export, path_alias, git_context, hook_augment, Windows support
(compat_fs/compat_thread), the UI layer, and ~140 expanded tree-sitter grammars.

Fork depth retained: PageRank/LinkRank ranking (src/pagerank/; sort_by=
relevance/linkrank/degree/calls), dependency indexing (src/depindex/;
CBM_INDEX_MODE=DEP), token reduction, and HTTP-endpoint discovery
(src/pipeline/httplink.c, pass_httplinks.c).

Conflict resolution (27 regions across the 39-file intersection):
- src/mcp/mcp.c: kept the fork superset handler pattern (resolve_project_store +
  expand_project_param + inject_context_once) as the single path; UNIONed the
  tool dispatch table; emit status:"indexed", excluded[], cross_service trace.
- src/store/store.c: upstream base + fork pagerank/linkrank/node_degree tables
  and sort_by plumbing; cbm_store_node_degree now excludes INHERITS
  (WHERE type != 'INHERITS'); removed the duplicate cbm_store_get_db.
- src/pipeline/pipeline.c: took upstream run_extraction_phase; grafted the fork
  passes (httplinks, normalize, flush_store dump branch); call
  cbm_pipeline_set_committed_counts before cbm_gbuf_dump_to_sqlite.
- internal/cbm/lang_specs.c: 158 entries combining the fork section_node_types
  with upstream ts_factory/embedded_imports; wired 13 orphaned type-arrays.
- src/depindex/depindex.h: renamed CBM_PATH_MAX -> CBM_DEP_PATH_MAX (it collided
  with constants.h enum CBM_PATH_MAX=1024) + 11 call sites in depindex.c.
- Makefile.cbm: upstream grammar/nomic units + fork CGO targets; added
  httplink.c + pass_httplinks.c to PIPELINE_SRCS; removed mongoose NOSAN
  machinery (mongoose was deleted upstream).
- httplinks restored (the merge silently deleted them because the fork had left
  them unchanged since the base): httplink.c/.h, pass_httplinks.c,
  tests/test_httplink.c; registered RUN_SUITE(httplink) in tests/test_main.c.
- CBM_INDEX_MODE enum unified to FULL=0, MODERATE=1, FAST=2, DEP=3.

Completeness (dual-parent check): 0 upstream files dropped from the merge tree;
6 fork files dropped, all intentional (upstream-superseded): CHANGELOG.md,
vendored/mimalloc/src/{arena-abandon,segment-map,segment}.c,
vendored/mongoose/{mongoose.c,mongoose.h}. Fork features (pagerank, depindex,
token_reduction, httplink) verified present and registered in tests/test_main.c.
src/pipeline/pass_parallel.c has an identical function set to upstream (49=49,
none dropped); the large line-deltas vs upstream are within-function divergence
of the fork extractor, not dropped functions.

Gate (run manually; hooks skip on merge commits): build green
(make -f Makefile.cbm cbm, exit 0); full C test suite 5980 passed / 2 failed /
0 crashes. The fork's pre-existing ASan crash in build_project_list_error_srv is
fixed by upstream's mcp.c rewrite, so the merge is strictly better than the fork
baseline on the crash axis.

Known issue, tracked separately (NOT a merge defect): 2 nondeterministic
failures in tests/test_incremental.c — incr_db_deleted_recovery:772 (diff_pct)
and incr_accuracy_vs_full:803 (full_nodes vs incr_nodes). Cause: the fork's
extractor (internal/cbm/extract_*.c) and parallel-resolve Route-node creation
are not thread-safe under the concurrent use of upstream's parallel pipeline
(run_parallel_pipeline), producing nondeterministic route/infra HANDLES edges
(~234k edge swing between runs). Sequential extraction (CBM_WORKERS=1) is
deterministic and correct. Root cause, bisect, and repro are documented in
notes/2026-06-24-fork-vs-upstream-divergence-assessment.md (section 8f); the fix
is deferred to a dedicated thread-safety audit (the make test-tsan target is
currently a stub and needs wiring).
2026-06-24 16:12:00 -04:00
b63aa9dc39 fix(cli): copy and sign the built binary on install instead of re-signing the stale target (#473)
* fix(cli): copy and sign the built binary on install instead of re-signing the stale target

`install` (especially with --force) only ad-hoc-signed whatever already sat at
~/.local/bin/codebase-memory-mcp and never copied the binary the operator ran
install from. An operator who built from source and ran `install -y --force`
was silently left with the OLD binary at the target — running stale code while
believing they had upgraded (#472).

Install now mirrors `update`: detect the running binary, copy it to the
canonical target (skipping the copy when we already ARE the target, which would
otherwise truncate the running file), make it executable, ad-hoc sign the
TARGET, and point all agent configs at the target. A different pre-existing
binary is only replaced with --force or interactive confirmation; --dry-run
reports the intended swap without touching anything.

The copy+sign also resolves the secondary report: a hand-copied clang build is
linker-signed (flags=0x20002) and gets Killed:9 when spawned by an MCP host —
re-signing ad-hoc (flags=0x2) makes it launchable, which install now does for
the placed binary.

Adds cbm_copy_binary_to_target() (with a same-file guard) plus regression tests
covering the binary swap and the self-copy guard.

Closes #472

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>

* fix(cli): address QA round 1

Extend cli_install_same_file_guard_issue472 with a symlink case: two distinct
path strings resolving to the same inode (which a non-canonical
cbm_detect_self_path vs the hardcoded target can produce) must also be detected
as same-file and skipped, not truncated. POSIX-only (#ifndef _WIN32).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>

* test(cli): guard install copy exec-bit assertion to POSIX

cli_install_copies_binary_to_target_issue472 asserted the executable bit on the
copied target, but cbm_copy_binary_to_target only chmods on POSIX (the exec bit
is not meaningful on Windows, and MinGW stat() derives it from the file
extension). Wrap the stat/S_IXUSR assertion in #ifndef _WIN32 so test-windows
passes; the content and creation assertions still run on all platforms.

Refs #472

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>

---------

Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
Co-authored-by: Shane McCarron <shane.mccarron@corvexconnect.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:03:37 +02:00
Martin Vogel 6c71244e63 feat(hooks): SessionStart reminders for Codex, Gemini CLI, Antigravity (#330)
Codex, Gemini CLI, and Antigravity all gained lifecycle-hook support, so give
them the same non-blocking SessionStart reminder Claude Code has — stdout is
injected as session context, nudging the agent to use codebase-memory-mcp
graph tools before grep.

- Codex: append a sentinel-delimited [[hooks.SessionStart]] block to
  ~/.codex/config.toml (idempotent upsert, preserves other content, removable).
- Gemini CLI: SessionStart hook in ~/.gemini/settings.json, reusing the shared
  JSON hook upsert (alongside the existing BeforeTool reminder).
- Antigravity: same JSON hook in ~/.gemini/antigravity/settings.json (it shares
  Gemini hook semantics).

The reminder command is written to be valid both as a TOML single-quoted
literal and a JSON string (no single quotes, no newlines). Wired into install,
uninstall, and the install --plan receipt. remove_hooks_json now prunes an
emptied event key so removal leaves no stale "<Event>": [] cruft. README
Multi-Agent table updated. Tests cover Codex upsert/idempotency/removal and
Gemini parity.
2026-05-31 19:39:31 +02:00
Martin Vogel 4c38c5a275 feat(install): add install --plan machine-readable receipt (#388)
An installer that configures MCP entries, instruction files, Skills, and hooks
across many agents should let callers see what it will mutate before it does.
`--dry-run` already lists planned writes in human-readable form; this adds the
machine-readable `agent.install.plan.v1` JSON receipt the issue asked for.

`install --plan` runs the real install dispatch in record-only mode — a global
g_install_plan recorder that each write-site function appends to (at the same
point it would write) while all mutations are disabled — then emits JSON with
agents_detected, config_files_planned, instruction_files_planned,
hooks_planned, writes_started:false, network_after_install:false, and
next_safe_command. Because the plan is recorded on the actual install code
path, it cannot drift from real behavior. No config is written, no index
deleted, no network used.

cbm_build_install_plan_json is exposed for testing; the test asserts the
receipt content AND that building it creates no config files.
2026-05-31 18:15:40 +02:00
Martin Vogel 61453e928f test(hooks): guard PreToolUse gate shim against predictable temp file (#384)
The symlink-attack vector (predictable /tmp/cbm-code-discovery-gate-$PPID)
was removed in c29e6d5 when the blocking bash gate became a stateless
compiled augmenter writing to stdout only. Add a regression guard so a
predictable temp/state file can never be reintroduced: assert the emitted
gate shim contains no /tmp path and no $PPID, and delegates to hook-augment.

Export cbm_install_hook_gate_script (was static) so the security property
is directly testable.
2026-05-31 13:32:08 +02:00
Martin Vogel f88d0315ac fix(install): detect Cursor IDE and register MCP config (#222)
Cursor was never in the editor-detection table, so install/update only
ever wrote the VS Code config and silently skipped ~/.cursor/mcp.json,
even when Cursor was present. Uninstall removed the Cursor entry but a
subsequent install never re-created it.

Detect ~/.cursor/ as the Cursor agent, register the MCP server in
~/.cursor/mcp.json (mcpServers format, same as Windsurf/Gemini) on
install, remove it on uninstall, and list Cursor in detected agents.
2026-05-31 13:21:31 +02:00
Martin Vogel c29e6d51f4 fix(hooks): replace blocking Claude PreToolUse gate with non-blocking augmenter
The previous PreToolUse hook gated Grep/Glob/Read/Search with 'exit 2'
on the first call per session, which broke Claude Code's
read-before-edit invariant (issue #362) and could deny tool calls under
upgrade/missing-binary failure modes.

Replace it with a structurally non-blocking augmenter:

- New 'codebase-memory-mcp hook-augment' subcommand reads the hook JSON
  from stdin and, for Grep/Glob, queries search_graph (in-process, no
  shell) and emits hookSpecificOutput.additionalContext. Every failure
  path (no project, short token, missing binary, slow query, timeout)
  exits 0 with no stdout — the hook physically cannot block a tool call.
- 300 ms SIGALRM/_exit(0) in-process deadline; 5 s settings.json timeout
  backstop. Output is written exactly once at the very end, so a
  mid-work timeout yields a clean no-op (never partial JSON).
- Matcher narrowed to 'Grep|Glob' (Read explicitly excluded) for Claude;
  Gemini matcher narrowed to 'google_search|grep_search' (excludes
  read_file) for the same reason.
- The installed shim is a thin wrapper that delegates to the binary;
  legacy filename 'cbm-code-discovery-gate' is kept so existing
  settings.json entries upgrade with zero migration. Installer refuses
  to embed binary paths containing a double quote (shim injection
  defense).
- Per-agent 'old matchers' lists let upsert/remove clean up historical
  matcher strings during upgrade.
- Smoke tests (8d/8e/8l) updated to assert the new behavior and
  regress-test against re-introducing Read in the matcher or 'exit 2'
  in the shim.
- Session reminder text updated: 'always Read a file before editing it'
  replaces the prior 'fall back to Read only for text content'.

(cherry picked from commit f72c8e68c4d91e52911a569a967ad782ce5472b2)
2026-05-19 23:46:46 +02:00
testandDustin Obrecht 404b5f822c feat: add Kiro CLI support (#96)
Detect ~/.kiro/ directory, auto-configure MCP at ~/.kiro/settings/mcp.json
using standard mcpServers format. Adds install, uninstall, detection, and test.

Based on #174 by dLo999, rebased onto refactored install infrastructure.

Co-Authored-By: Dustin Obrecht <dustin@kurtnoble.com>
2026-04-15 23:56:03 +02:00
Andrew Hundt 2ecedbeb80 Merge remote-tracking branch 'origin/main' into api-consolidation
# Conflicts:
#	.gitignore
#	.mcp.json
#	Makefile.cbm
#	cmd/codebase-memory-mcp/assets/skills/codebase-memory-exploring/SKILL.md
#	cmd/codebase-memory-mcp/assets/skills/codebase-memory-quality/SKILL.md
#	cmd/codebase-memory-mcp/assets/skills/codebase-memory-reference/SKILL.md
#	cmd/codebase-memory-mcp/assets/skills/codebase-memory-tracing/SKILL.md
#	internal/cbm/extract_imports.c
#	internal/cbm/lang_specs.c
#	src/discover/language.c
#	src/foundation/compat_fs.c
#	src/foundation/compat_fs.h
#	src/foundation/str_util.h
#	src/graph_buffer/graph_buffer.c
#	src/graph_buffer/graph_buffer.h
#	src/main.c
#	src/mcp/mcp.c
#	src/pipeline/pipeline.c
#	src/pipeline/pipeline.h
#	src/pipeline/pipeline_incremental.c
#	src/pipeline/pipeline_internal.h
#	src/store/store.c
#	src/store/store.h
#	src/watcher/watcher.c
#	tests/test_main.c
#	tests/test_pipeline.c
#	tests/test_store_bulk.c
#	tests/test_store_search.c
2026-04-10 22:13:18 -04: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
Andrew Hundt 1646f96988 feat(config,ranking): parameterize limits, enrich config docs, add autotune
Fixes codebase://architecture returning only 10 results all from graph-ui
by wiring hardcoded limits through the config system and raising defaults to 25.

Key changes:
- mcp.c: add key_functions_count config (default 25); wire into
  build_key_functions_sql (was hardcoded LIMIT 10 at line 4317) and
  build_resource_architecture call site
- mcp.c: add arch_hotspot_limit config (default 25); wire into classic
  get_architecture tool handler
- store.c/store.h: raise CBM_ARCH_HOTSPOT_DEFAULT_LIMIT 10->25; add
  hotspot_limit param to cbm_store_get_architecture
- store.c/store.h: add sort_by=calls (ORDER BY calls_in+calls_out DESC)
  and sort_by=linkrank (ORDER BY linkrank_in DESC) dispatch cases;
  add degree_mode config (weighted|unweighted|calls_only) for
  min_degree/max_degree filter column selection
- watcher.c/watcher.h: add poll_base_ms/poll_max_ms to struct cbm_watcher;
  change cbm_watcher_run and cbm_watcher_poll_interval_ms signatures to
  accept base_ms/max_ms params (0=defaults); wire watcher_poll_base_ms and
  watcher_poll_max_ms config keys through main.c
- cli.h: extend cbm_config_entry_t with range and guidance fields (5->7)
- cli.c: replace entire CBM_CONFIG_REGISTRY with 7-field entries for all 32
  config keys with broadest feasible ranges and actionable guidance strings;
  update config list/get/help display to print [range] + guidance per entry
- scripts/autotune.py: new standalone Python 3.9+ script that sends JSON-RPC
  directly to the binary via stdin/stdout, tries 7 experiments, scores
  against expected top-10 ground truth for 3 repos, resets config on exit
- tests: update all callers of cbm_store_get_architecture (pass 0 for
  hotspot_limit) and cbm_watcher_poll_interval_ms (pass 0,0 for defaults)

All 2238 tests pass.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-03-26 04:40:13 -04:00
Martin Vogel 8951647d3e Fix remaining install/update gaps + in-memory zip extraction
Install command:
- Add cbm_kill_other_instances() to kill stale MCP servers
- Add cbm_macos_adhoc_sign() to sign binary if placed unsigned

Update command:
- Replace skills-only reinstall with full cbm_install_agent_configs()
- Replace external unzip with cbm_extract_binary_from_zip() via zlib

Refactor: extract 10-agent config loop into cbm_install_agent_configs()
called by both install and update.

New: cbm_extract_binary_from_zip() — in-memory zip extraction with
stored + deflate support, path traversal rejection, bounds checks.
4 unit tests. Smoke: add install.ps1 E2E for Windows.
2026-03-24 23:14:33 +01:00
Martin Vogel 8fc19497e7 Add cbm_replace_binary: unlink-before-write for update command
TDD: two tests (overwrite read-only file, create new file) written
first, then cbm_replace_binary() implemented and wired into update.

The update command failed when the existing binary had no write
permission (e.g., 0500). unlink() only requires write permission on
the parent directory, not the file itself, so removing first then
creating with O_CREAT | 0755 handles all permission combinations.

Fixes #114.
2026-03-23 15:47:05 +01:00
Andrew Hundt 1418b36d8c cli: add config registry with 25 keys, env var overrides, grouped help
Config registry (CBM_CONFIG_REGISTRY in cli.c):
- 25 config keys across 5 categories: Indexing, Search, Tools, PageRank,
  Dependencies. Each entry has key, default, env var name, category,
  description.
- All defaults verified against code-level #define values.

cbm_config_get_effective(): priority chain env > DB > default.
- Checks registry for env var name, reads env first, falls back to DB.
- Used by config get CLI and auto_index in maybe_auto_index.

Env var overrides for key settings:
- CBM_AUTO_INDEX (bool), CBM_AUTO_INDEX_LIMIT (int)
- CBM_REINDEX_ON_STARTUP (bool)
- CBM_KEY_FUNCTIONS_EXCLUDE (comma-separated globs)
- CBM_TOOL_MODE (streamlined/classic)

config list output:
- Grouped by category with [Category] headers
- Shows (env) when env var is active, (set) when DB value differs from default
- All 25 keys visible (was: only 2)

config help:
- Shows storage location (~/.cache/codebase-memory-mcp/_config.db)
- Priority explanation (env > config set > default)
- Examples for config set and env var usage
- Keys grouped by category with [env: VAR_NAME] annotation

Fixed: auto_dep_limit default 5→20, dep_max_files default 5000→1000
to match code-level CBM_DEFAULT_AUTO_DEP_LIMIT and CBM_DEFAULT_DEP_MAX_FILES.
Fixed: hint message provides complete commands, not fragments.
Improved: dependency config descriptions explain what packages/files mean.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-03-23 07:19:13 -04:00
Andrew Hundt cecf6278cb mcp: apply Phase 8.5 refinements to merged branch
mcp.c: key_functions (top 10 by PageRank) in get_architecture response
mcp.c: pagerank stats (ranked_nodes, computed_at) in index_status response
mcp.c: conditional in_degree/out_degree (only when PageRank not computed)
pagerank.c: cbm_pagerank_compute_with_config() for config-backed edge weights
pagerank.h: 9 CBM_CONFIG_EDGE_WEIGHT_* config key constants + forward decl
cli.c: cbm_config_get_double() for double config values
test_pagerank.c: 7 Phase 8.5 tests (key_functions, config, stats, streamlining)

Total: 2126 tests passing (7 new over merged baseline of 2119)
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-03-22 03:09:11 -04:00
Martin Vogel 63e6141ac6 Add OpenClaw + VS Code agent detection (10 agents total)
- OpenClaw: detect ~/.openclaw/, write MCP config to openclaw.json
- VS Code was already wired in PR #79 but not counted in README
- Agent struct initializer uses memset instead of counting booleans
- README updated: 8 → 10 agents
2026-03-21 01:43:41 +01:00
Bing Ho 02575fb307 Add VS Code detection and MCP registration to install/uninstall
The install command detected many editors (Cursor, Zed, Gemini, etc.)
but not VS Code, even though cbm_install_vscode_mcp() already existed.
Add VS Code User config dir detection and wire it into both install
and uninstall flows, writing to ~/.config/Code/User/mcp.json (Linux)
or ~/Library/Application Support/Code/User/mcp.json (macOS).
2026-03-20 08:37:44 -05:00
Martin Vogel 7629940dca Restore session auto-detect + auto-index + config CLI from Go
- Config store: persistent SQLite key-value in _config.db (get/set/delete/bool/int)
- Config CLI: codebase-memory-mcp config list|get|set|reset
  Keys: auto_index (default false), auto_index_limit (default 50000)
- Session detection: detect project root from CWD on MCP initialize
- Auto-index: if auto_index=true and project not yet indexed, background pipeline
- Watcher hookup: after index completes, register project for ongoing git polling
- 6 new config store tests (open/close, get/set, bool, int, delete, persistence)

Enable auto-indexing:
  codebase-memory-mcp config set auto_index true
2026-03-19 20:13:17 +01:00
442cb958f0 Add KiloCode support, fix Zed JSONC parsing (#24, #53)
- KiloCode: detect globalStorage dir, upsert mcp_settings.json, install
  global rules at ~/.kilocode/rules/codebase-memory-mcp.md
- Zed: parse JSONC (comments + trailing commas) in existing settings.json
  — fixes "Invalid JSON" error on install with existing Zed config
- 2 new tests: KiloCode detection, Zed JSONC settings parsing
- Now supports 8 agents: Claude Code, Codex, Gemini, Zed, OpenCode,
  Antigravity, Aider, KiloCode

Co-Authored-By: David34920 <179368816+David34920@users.noreply.github.com>
Co-Authored-By: Paul Cohen <200370+sonicviz@users.noreply.github.com>
Co-Authored-By: Chitral Verma <11135032+chitralverma@users.noreply.github.com>
Co-Authored-By: Noel Kurian <1851449+noelkurian@users.noreply.github.com>
Co-Authored-By: José Almeida <57680069+zeval@users.noreply.github.com>
Co-Authored-By: Vasani Harshil <147682127+harshil480@users.noreply.github.com>
2026-03-19 18:56:16 +01:00
Martin Vogel 159378ad8e Multi-agent install: auto-detect 7 coding agents, upsert configs + hooks + instructions
- Detect Claude Code, Codex CLI, Gemini CLI, Zed, OpenCode, Antigravity, Aider
- Per-agent MCP config upsert: Codex TOML, OpenCode JSON, Antigravity JSON
- Instruction file upsert with marker-based sections (no duplicates on re-install)
- Claude Code PreToolUse hook (Grep|Glob|Read -> MCP reminder)
- Gemini CLI BeforeTool hook (grep_search|read_file -> MCP reminder)
- Fix Zed MCP config: args:[""] instead of broken source:"custom" (#24)
- Rewrite skill descriptions to directive pattern (100% auto-activation)
- Keyword-rich MCP tool descriptions for Tool Search discovery
- 35 new tests (agent detection, config upsert, instructions, hooks)
- All platforms green: macOS 2022, Linux 2004+18skip, Windows cross-compile OK
2026-03-19 16:08:43 +01:00