Commit Graph
86 Commits
Author SHA1 Message Date
Andrew Hundt 5d164c7efb test(cli): assert exact query row-cap contract
tests/test_cli.c:6554 still required the word 'upstream' after commit aefbec05 changed query_max_rows from an unsafe scan prefix to an exact post-selection result ceiling. That stale wording failed the CLI sanitizer suite even though the registry described the corrected behavior.

Assert the public invariants instead: query_max_rows is a result-row cap, lowering it does not change which rows match, and Cypher LIMIT cannot bypass it. The focused contract passes 1/1 and the complete CLI plus agent-client ASan/UBSan gate passes 232/232; scripts/check-source-safety.sh and git diff --check also pass.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-19 19:40:56 -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 7dd1e27677 fix(config): document auto_index as enabled by default
docs/CONFIGURATION.md:82 previously listed auto_index=false even though CBM_CONFIG_REGISTRY in src/cli/cli.c defaults the key to true. This could lead users to assume streamlined first-use indexing was disabled.

tests/test_cli.c:3837 now derives the expected Markdown row from CBM_CONFIG_REGISTRY, so future default changes must keep the configuration table synchronized.

Verification: CBM_ONLY_SUITE=cli build/c/test-runner (151 passed); bash scripts/check-source-safety.sh; git clang-format --diff HEAD -- tests/test_cli.c.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-18 18:15:46 -04:00
Andrew Hundt 292299857e fix(mcp): skip unfiltered rows for semantic-only JSON
search_graph previously ran an unfiltered graph search before a JSON semantic-only lookup, so an empty vector result returned unrelated nodes and paid an unnecessary graph-result-page scan. Detect semantic-only requests, skip cbm_store_search and cbm_store_search_overlay_view, and return explicit empty semantic_results with recovery guidance.

Define query_graph as an early compositional tool for effective, computationally efficient custom Cypher. Mark examples, labels, properties, and LIMIT as optional guidance; retain server caps and dependency-ranking instructions; make truncation hints offer narrowing or cap changes without prescribing LIMIT.

Install portable sandbox recovery guidance that distinguishes MCP approval from shell sandbox authorization.

Verification: ASan/UBSan MCP 228 passed; tool_consolidation 103 passed; token_reduction 50 passed; CLI 150 passed; source-safety passed. The repository-wide clang-format target remains red on pre-existing files; changed-line formatting issues were corrected.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-18 17:56:39 -04:00
Martin Vogel bc3594b728 fix(test): pin XDG_CONFIG_HOME in the three env-coupled cli tests
The parallel runner's isolated-process execution exposed three cli tests
that were passing for the wrong reason on Linux: cbm_zed_config_dir (and
the VS Code/vendor path resolvers) prefer $XDG_CONFIG_HOME over
$HOME/.config, CI runners export it, and an isolated `test-runner cli`
process therefore resolved config paths OUTSIDE the test fixture — the
tests only stayed green in the all-suites single process because an
earlier suite's env mutations leaked into them (hidden cross-suite
coupling, deterministic failure in isolation, macOS unaffected since its
resolvers do not consult XDG).

- cli_detect_agents_finds_zed: save/set XDG_CONFIG_HOME to the fixture's
  .config for the detection call, restore after.
- cli_vscode_profile_mcp_uninstall: same pin alongside its existing
  HOME/PATH/APPDATA handling.
- cli_durable_profiles_follow_current_vendor_paths: XDG_CONFIG_HOME joins
  its unset-and-restore env list.

All 222 cli tests pass locally with a hostile XDG_CONFIG_HOME exported.
No production code changed; no assertion weakened.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-18 14:10:06 +02: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 cc3021a9c2 fix(install): publish binary replacements atomically
Change cbm_copy_binary_to_target() in src/cli/cli.c to copy into a sibling .installing.XXXXXX file, apply executable permissions, and publish with cbm_replace_file(). Copy, chmod, or replacement failures unlink only the temporary file, leaving the installed executable intact.

Add qwen, forgecode, and windsurf to cbm_build_install_plan_json() agents_detected so the machine-readable receipt matches the config paths emitted by the shared install dispatcher.

Extend tests/test_cli.c to require a new destination inode after replacement and require all three reference harness names before config_files_planned. Red evidence: stale_st.st_ino == upgraded_st.st_ino and missing qwen in agents_detected. Validation: sanitizer CLI suite 473 passed; live install replaced ~/.local/bin/codebase-memory-mcp and reported Claude Code, Codex, Gemini, Antigravity, Aider, KiloCode, VS Code, Cursor, Windsurf, Qwen Code, and ForgeCode.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-15 16:40:46 -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 78427b4dd2 fix(install): make uninstall previews and cleanup ownership-safe
Prevent cbm_cmd_uninstall --dry-run -y from calling cbm_remove_indexes or prompting while still reporting the planned index action.

Require codebase-memory-mcp command identity when upserting and removing SessionStart JSON hooks so user hooks with the same matcher survive. Remove the owned Codex hooks.json entry, Claude hook scripts, and per-profile VS Code MCP registrations during uninstall without deleting unrelated configuration.

Add lifecycle regressions in tests/test_cli.c. The focused ASan/UBSan CLI suite passes 142 tests.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-15 14:37:23 -04:00
Martin Vogel 5ae6ef7875 fix: migrate Windows Claude hook scripts safely
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-14 19:08:54 +02:00
Martin Vogel c22020d18d test: cover Windows hook migration safety
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-14 18:50:35 +02: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 90fab0844a test: model Windows agent hook contracts
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-13 05:21:55 +02:00
Martin Vogel be1e98fd99 test: write Windows fixtures byte-exactly
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-13 04:17:58 +02:00
Martin Vogel eb203ff6fa test: guard POSIX filesystem checks on Windows
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-13 03:31:31 +02: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 2040488cf4 fix(cli): preserve hook compatibility after rebase
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-13 02:00:44 +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 da4c00671f Merge pull request #1057 from DeusData/fix/929-windows-cmd-hooks
fix(install): Windows hook scripts get .cmd form; legacy files removed
2026-07-12 21:30:21 +02:00
Martin Vogel 5c9c554a2b Merge pull request #1055 from DeusData/fix/858-hook-deadline
fix(hook): raise + env-configure the augment deadline, breadcrumb on fire
2026-07-12 20:52:21 +02:00
Martin Vogel b1502bf3eb fix(install): Windows hook scripts get .cmd form; legacy files removed
Extensionless bash shims under %USERPROFILE%\.claude\hooks triggered
the Windows 'How do you want to open this file?' dialog whenever an
editor (Cursor) scanned the hooks dir, and could not execute without
bash anyway. All three Claude hook scripts (discovery gate, session
reminder, subagent reminder) now install as .cmd files with cmd syntax
on Windows - @echo off bodies, caret-escaped pipes in the reminder
text, 2>/dev/null redirects - and the install removes the pre-existing
extensionless twin so upgrades stop triggering the dialog. The
settings.json command paths follow automatically since they are built
from the same script-name macros. POSIX behavior is byte-identical and
guarded (no .cmd twin).

Closes #929

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-12 19:45:29 +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 39ffb97ceb fix(hook): raise + env-configure the augment deadline, breadcrumb on fire
The 300ms in-process SIGALRM budget in hook-augment self-terminated
with a silent _exit(0) on real cold starts (SQLite/mmap open under
load), so PreToolUse augmentation never appeared in real sessions
(reporter: 0/24 observed) while warm manual invocations worked - and a
fired deadline was indistinguishable from a legitimate no-match run.

Default budget is now 2000ms (the settings.json hook timeout stays the
outer backstop), overridable via CBM_HOOK_DEADLINE_MS (clamped
50..10000). When the deadline fires, the handler write()s a
pre-formatted breadcrumb (deadline, pid, the env knob to raise) to
~/.cache/codebase-memory-mcp/logs/hook-augment-timeouts.log before
exiting - fd and message are prepared at arm time so the handler stays
async-signal-safe; CBM_HOOK_TIMEOUT_LOG overrides the path for tests.
Windows keeps relying on the settings.json timeout (unchanged no-op).

Deterministic reproduction: stdin is a pipe whose writer never sends,
so the read blocks past a 60ms deadline - the timer must fire, exit 0
(fail-open), and leave the breadcrumb. RED before (no breadcrumb),
GREEN after.

Closes #858

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-12 19:06:47 +02:00
Martin Vogel 2950e4ec03 fix(cli): reject unknown tool flags with a nearest-flag suggestion
cbm_cli_build_args_json typed unknown flags as strings and shipped them
as JSON args the server ignores: 'trace_path --max-depth 1' succeeded
but traced at the default depth 3 — silently-wrong output that inflated
an agent evaluation by thousands of tokens of unwanted hop-2/3 rows.

Unknown flags for a known tool now fail loudly with a Levenshtein
nearest-flag suggestion:
  unknown flag --max-depth for this tool (did you mean --depth?) — run
  'cli trace_path --help' for the supported flags

Unknown-tool (no schema), raw-JSON, --args-file, stdin, and supervisor
worker argv paths are unaffected — none of them route through the flag
converter.

Reproduce-first: cli_build_args_json_unknown_flag_rejected is RED on
the permissive code (JSON produced) and GREEN with the rejection.

Closes #997

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-10 21:12:33 +02:00
Martin Vogel 664313e4ac feat(index): missed graph in UI + read-time coverage hook + recovery subtraction
Four refinements to the coverage signal:

- extraction: subtract DEFINITE recovery before flagging. Tree-sitter
  error recovery plus the ERROR-descending def walker often re-extract
  constructs inside a failed region (verified: `def broken(:` comes
  back as a def); a region whose every line is covered by definitions
  that START inside it is not a miss, and a fully recovered file is not
  flagged at all. Container defs (Module/Package) don't count as
  evidence, and partially covered regions stay flagged — the
  #ifdef-split case keeps its flag because the first branch's function
  is genuinely lost
- naming: the query_graph option is graph="missed" (the graph shows
  ONLY misses — "coverage" was misleading); shadow project renamed to
  "<name>::missed"; tool descriptions updated so agents discover both
  the option and its semantics
- hook: the CLI-installed PreToolUse augmenter now also matches Read
  and injects a coverage note when the file being read is listed as not
  fully indexed ("line ranges X-Y could not be parsed — the file
  content you are reading is ground truth"). Safe against the old
  issue-362 hazard: the augmenter is structurally non-blocking (always
  exit 0, additionalContext only), mirroring the Gemini matcher that
  already includes read_file; matcher upgrade bookkeeping updated
- ui: "Missed files" toggle in the graph sidebar renders the miss
  graph as a second graph option — /api/layout gains graph=missed
  (same db file, shadow-project scoping; base project name validated
  as before)

Tests: recovery-subtraction cases (recovered def unflagged, garbage
region flagged, trailing recovered defs keep the flag), CLI matcher
tests updated, e2e resilience fixtures switched to an unrecovered
miss; verified end-to-end: hook emits the note for a flagged file and
stays silent otherwise, /api/layout?graph=missed serves the miss graph
and the code graph is unchanged, frontend build + tests green.

Refs #963

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-08 19:13:25 +02:00
Martin Vogel be410a6be9 cli: compute self-update checksum in-process instead of shelling out
cbm_cli_sha256_file shelled out to sha256sum/shasum, which is unportable:
the tool may be absent, and under cmd.exe the single-quoted path is not
dequoted so the hash of a downloaded release could never be computed on
Windows. Add a small in-process SHA-256 (FIPS 180-4, src/foundation/sha256.c)
and use it directly — no external tool, no per-OS branching, no popen. The
checksum test now covers three NIST vectors (empty, "abc", and a 56-byte
input that forces padding into a second block).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-08 00:05:52 +02:00
Martin Vogel 4bbcfec503 cli: fix self-update checksum computation and fail closed
The macOS digest path invoked `shasum -a CBM_SZ_256` — a literal string
(not a macro; string literals do not expand) naming an invalid algorithm, so
the digest always failed on macOS, and the self-update path then treated a
could-not-verify result as non-fatal and installed the download regardless.
Use the correct algorithm, and install only a positively-verified download:
a mismatch, a missing checksum entry, or an unavailable hash tool now all
abort. Adds a known-vector digest regression test.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-07 21:31:23 +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
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
Martin VogelandSS-42 7b93210ca2 fix(cli): overflow-safe ZIP entry bounds check in self-update extraction
The truncation check `header_end + (int)comp_size > data_len` was
bypassable for comp_size >= 2^31: the int cast turns the size negative,
the sum drops below data_len, and the entry is accepted -- authorizing
inflate to read up to ~4GB past the downloaded archive buffer during
self-update ZIP extraction. Replace it with
`header_end > data_len || comp_size > (uint32_t)(data_len - header_end)`,
which is overflow-safe and strictly tighter.

Regression guard cli_extract_binary_from_zip_rejects_truncated_deflate_size_over_int_max
builds a 52-byte archive whose entry claims comp_size=0xFFFF0000 with a
self-terminating DEFLATE stream: the old check admits it and extraction
returns non-NULL (verified red pre-fix); the new check rejects it.

Secondary cppcheck cleanups from the same review:
- cli.c: extract zip_read_u16le/zip_read_u32le little-endian helpers
  (behavior-identical) and widen zip_extract_entry sizes to size_t with
  an explicit UINT_MAX guard before the zlib uInt narrowing.
- cypher.c: drop unreachable IS NULL / IS NOT NULL null guards in
  eval_condition (resolve_condition_value result is checked earlier).

Distilled from PR #784.

Co-authored-by: SS-42 <noreply@incogni.to>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-03 20:05:10 +02:00
Andrew Hundt 16f683a98f fix(cli): make subcommand help non-mutating
Return install, uninstall, and update subcommand help before auto-answer parsing, home lookup, index scans, prompts, release checks, downloads, or file mutation.

Refresh top-level usage for existing install/update flags and add focused CLI tests that prove help works with HOME and USERPROFILE unset.

Validation: product build /private/tmp/cbm-cli-help-build1.log rc 0; ASan test-runner build /private/tmp/cbm-cli-help-test-runner-build2.log rc 0; CLI suite /private/tmp/cbm-cli-help-cli-suite2.log rc 0 (118/118); source-safety /private/tmp/cbm-cli-help-source-safety1.log rc 0; manual help smoke outputs under /private/tmp/cbm-cli-help-{install,uninstall,update}1.*.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-02 17:59:41 -04:00
Andrew Hundt 428ef427f1 fix(cli): scan all fallback cli paths
Use the fallback path array length for cbm_find_cli instead of the unrelated retry-count constant. This keeps CLI agent detection tied to the path list and prevents future constant drift from skipping later fallback locations.

Add a focused .cargo/bin fallback regression so path index 3 remains covered alongside the existing PATH and .local/bin cases.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-01 21:44:16 -04:00
Andrew Hundt 3ad25bfd79 fix(cli): tighten reindex startup guidance
Avoid describing reindex_on_startup as always-fresh. The setting only refreshes stale indexes during startup/staleness checks, so the generated config help now says that directly.\n\nAdd a focused CLI registry test to keep the old overclaim from returning.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-01 21:13:59 -04:00
Andrew Hundt a64f7eac28 fix(cli): clarify hook reminder guidance
Clarify the Codex/Gemini/Antigravity SessionStart reminder so it recommends graph tools before broad grep for structural code discovery instead of implying they replace file reads. Spell out that auto-indexing uses the MCP server CWD or explicit repo paths when enabled, and add a focused Codex hook regression assertion for the wording.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-01 20:40:19 -04:00
Andrew Hundt 13511cd7f8 test(portability): reuse filesystem wrappers in suites
Replace direct environment and filesystem cleanup calls in MCP, CLI, input validation, and HTTP link tests with existing cbm compatibility wrappers. Also updates the MCP publish metadata fixture to use the current three-file containment fallback instead of the now-exact new-folder path.

Validation: git diff --check; bash scripts/check-source-safety.sh; make -j8 -f Makefile.cbm build/c/test-runner; CBM_ONLY_SUITE=mcp ./build/c/test-runner; CBM_ONLY_SUITE=cli ./build/c/test-runner; CBM_ONLY_SUITE=input_validation ./build/c/test-runner; CBM_ONLY_SUITE=httplink ./build/c/test-runner.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-07-01 19:33:52 -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 3261ce9383 fix(cli): harden install path formatting
Add cbm_getenv_fits so path-like environment values can fail closed when set but too long, instead of being silently truncated by bounded copies or falling back to HOME.

Use checked formatting for Claude hook command/script paths, install/uninstall Claude config paths, install/update binary targets, and PATH directory writes. Overlong paths now return or report an error before mutating a truncated location.

Add focused CLI regressions for overlong hook homes and CLAUDE_CONFIG_DIR, plus platform coverage for the new environment helper.

Validation: make -f Makefile.cbm cbm; make -f Makefile.cbm build/c/test-runner; CBM_ONLY_SUITE=cli ./build/c/test-runner; CBM_ONLY_SUITE=platform ./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:49:19 -04:00
Andrew Hundt 404feb8210 fix(cli): reject overlong config paths
Validate CLI config and instruction parent paths before creating directories so truncated fixed buffers cannot create a different target. Route JSON and markdown writes through the existing cbm_write_file_atomic helper for consistent replace semantics.

Add regression coverage for overlong JSON config and instruction paths to prove failed writes do not create truncated parent directories.

Validation: make -f Makefile.cbm cbm; 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 17:33:06 -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 cbacf99e74 docs(cli): list dependency ranking config
search_graph already reads search_disable_dep_ranking, and the MCP schema names that config key. Add it to CBM_CONFIG_REGISTRY so config list/get guidance exposes the same setting users see in the API description.

Add a CLI registry regression test for the key, default, range, and dependency-ranking guidance. This does not change search behavior, MCP schemas, DB schema, or tool visibility.

Validated with make -f Makefile.cbm build/c/test-runner, CBM_ONLY_SUITE=cli ./build/c/test-runner, CBM_ONLY_SUITE=tool_consolidation ./build/c/test-runner, git diff --check, and bash scripts/check-source-safety.sh.

Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-06-30 07:19:07 -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
Andrew Hundt ec650bb3ce fix(cli): classify planned skill installs
Add a skill_dirs_planned array to the install --plan receipt and route planned Claude Code skill directory writes there instead of instruction_files_planned.

This keeps the no-mutation install receipt accurate for agents reviewing planned changes before install. Real install behavior and hook upsert paths are unchanged.

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; make -f Makefile.cbm cbm; HOME=/private/tmp/cbm-install-plan-smoke-20260630 ./build/c/codebase-memory-mcp install --plan.
Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
2026-06-30 05:28:24 -04:00
Shane McCarron 5255939a95 fix(install): address QA round 1
QA round 1 (PR #632) flagged that the SubagentStart hook uses matcher "*",
the same matcher a user is most likely to pick for their own catch-all
SubagentStart hook. Because is_cmm_hook_entry keyed ownership on the matcher
string alone, install would remove the user's "*" entry and replace it with
ours, and uninstall could remove the wrong one.

Add an optional `match_command_substr` to the upsert/remove args, threaded into
is_cmm_hook_entry: when set, an entry must ALSO carry a hooks[].command
containing that substring to be claimed as ours. The Claude SubagentStart hook
passes "cbm-subagent-reminder"; all existing callers leave it NULL, preserving
their matcher-only behavior unchanged. Install/uninstall now only ever touch
CMM's own entry and never clobber a foreign "*" hook.

Add cli_claude_subagent_hook_preserves_user_entry covering the case: a
pre-existing user "*" SubagentStart hook survives both install and uninstall.

Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
2026-06-29 08:42:36 -05:00
Shane McCarron 3466ba02e8 test(install): cover SubagentStart hook registration
Verify the Claude SubagentStart reminder: install writes a SubagentStart
entry with a match-all matcher pointing at cbm-subagent-reminder, a second
upsert is idempotent (no duplicate entry), and removal leaves no SubagentStart
key behind.

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