Previously the un-draft step ran inside the verify job, before
publish-registries. If npm or PyPI publish failed, the GitHub release
was already live but the wrappers were not — half-shipped state.
Move the un-draft into a new publish-final job that needs both
[verify, publish-registries]. If any registry fails, the GH release
stays in draft and the run can be re-tried with replace=true.
Add publish-registries job to release.yml that runs after verify
(release published, VirusTotal table appended). Publishes:
- pkg/npm via 'npm publish --access public --provenance'
- pkg/pypi via 'twine upload' (sdist + wheel from hatchling)
Both wrappers fetch the binary at install time, so a version bump is
the only per-release change needed. Bumped to 0.6.1.
Requires NPM_TOKEN and PYPI_TOKEN repo secrets.
The rst tree-sitter grammar (added in the 89-grammar bump) contains a
valid_schemas[] array listing URI schemes (http, https, ftp, mailto,
telnet, ssh) in vendored/grammars/rst/tree_sitter_rst/chars.c. The
'telnet' string ends up in the binary's string table and tripped the
dangerous-command detector, blocking smoke on every platform.
Add an allowlist mechanism for known-benign matches with a comment
pointing at the source file, so future false positives can be
documented the same way.
The CLI's default print mode (cli_print_mcp_result in src/main.c)
unwraps the MCP envelope and prints the inner JSON directly. The
smoke test was double-parsing as if it received {content:[{text:...}]},
which silently fell through to empty values and failed every assertion
across all platforms (8 occurrences fixed).
strndup is a POSIX/GNU extension not available in mingw clang on
Windows. Replace 6 bare strndup() calls with cbm_strndup() and
include foundation/compat.h, matching the pattern already used in
pass_calls.c.
Previous tests ran `cd <tmpdir> && git config user.email test@test && ...`
to set up author info for test commits. If the tmpdir path was ever
interpreted differently (or if the test process inherited a cwd inside
a real git repo), the `git config` call could write to a real repo's
.git/config instead of the temp repo's.
Replace with `export GIT_AUTHOR_NAME=t GIT_AUTHOR_EMAIL=t@t ...` which
are ephemeral env vars that can never leak into persistent config.
- branch_types: case_clause → switch_case + switch_default (correct
grammar node names)
- branch_types: add do_statement (do-while loops)
- import_types: remove 'require' (not a grammar node type)
Verified: TypeScript, Python, C, C++ specs are all correct — every
node type in the spec exists in the grammar's ts_symbol_names.
- C#: add record_declaration, type_declaration to class types;
add namespace_declaration to import types
- JavaScript: add new_expression to call types; add import, extends,
require to import types (also used by TS/TSX)
- Python: add import to import_types
- TypeScript: add function_signature to func types
- Makefile: add recipe to func, call to calls, include to imports
All 153 grammars now have maximally complete extraction specs.
2797 tests pass with zero regressions.
- pass_parallel.c: detect gRPC calls when resolved QN contains
ServiceClient/ServiceGrpc/Servicer — emits GRPC_CALLS edges for
calls resolved to generated protobuf client interfaces
- pass_parallel.c: emit_grpc_edge falls back to resolved QN when
callee_name alone doesn't contain service.method pattern
- extract_calls.c: add resolve_chained_selector() for iterative
extraction of chained method calls (NewClient(conn).GetBar →
"NewClient.GetBar") without recursion
Known limitation: Go receiver-method chained calls like
pb.NewCartServiceClient(conn).GetCart() in rpc.go are not yet
extracted as CALLS edges — the Go grammar's AST structure for
these patterns needs dedicated investigation.
Systematic audit of every grammar's parser.c against the current
lang_specs.c entries. For each language, identified all primary
extraction-relevant node types (function/class/call/import) present
in the grammar but missing from the spec.
Changes:
- 44 new node type arrays created for languages that had empty_types
where the grammar provides extractable constructs
- 121 existing arrays extended with additional node types
- Covers all 153 vendored grammars
Examples of additions:
- Go: import, import_declaration added to import_types
- Python: import, import_from_statement, import_statement added
- JavaScript: new_expression, call_expression added to call_types
- PHP: namespace_use_declaration added (was completely missing)
- Rust: macro_invocation added to call_types
- C/C++: struct_specifier, enum_specifier, union_specifier added
All 2797 tests pass with zero regressions.
Bare import specifiers (@myorg/pkg, github.com/foo/bar, use my_crate::foo)
previously produced zero IMPORTS edges. This adds manifest-aware resolution
during parallel extraction for JS/TS (package.json), Go (go.mod),
Rust (Cargo.toml), Python (pyproject.toml), PHP (composer.json),
Java (pom.xml), Gradle (build.gradle), Dart (pubspec.yaml),
Elixir (mix.exs), and Ruby (*.gemspec).
Workers parse manifest files during extraction with zero extra I/O,
entries are merged into a hash table before registry build, and
cbm_pipeline_resolve_module() provides unified resolution with
prefix matching for Go/Java/PHP path-based specifiers.
Closes#180.
Based on #184 by dLo999 (JS/TS package map approach).
Co-Authored-By: Dustin Obrecht <dustin@kurtnoble.com>
Adds per-label/type property key discovery via json_each() so users can
see which properties are available for Cypher queries without trial and
error. Base columns listed first, JSON keys appended (capped at 50).
Closes#179.
Based on #181 by dLo999.
Co-Authored-By: Dustin Obrecht <dustin@kurtnoble.com>
When a single record payload exceeds 65KB (max_local=65501), the writer
now splits it across overflow pages per SQLite's B-tree spec instead of
underflowing the content_offset and corrupting memory.
Closes#139, closes#187.
Based on #175 by dLo999.
Co-Authored-By: Dustin Obrecht <dustin@kurtnoble.com>
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>
Add .codebase-memory/graph.db.zst — a zstd-compressed knowledge graph
artifact that can be committed to the repo. Teammates bootstrap from
the artifact instead of running a full reindex from scratch.
- Vendor zstd 1.5.7 (amalgamated build) for 8-13:1 compression
- Two-tier export: zstd -9 + index stripping for explicit index,
zstd -3 for watcher/incremental auto-updates
- Import: decompress → integrity check → auto-recreate indexes
- Bootstrap in handle_index_repository: when no local DB exists but
artifact is present, import first then run incremental
- Auto-create .gitattributes with merge=ours to prevent conflicts
- Fix: add missing idx_edges_url_path to create_user_indexes and
url_path_gen generated column to init_schema
- 13 new tests (5 zstd wrapper + 8 artifact round-trip/edge cases)
Pipeline: gRPC/GraphQL/tRPC client libs in service_patterns, edge emitters
in pass_parallel, __grpc__ Route nodes from .proto service defs in
pass_route_nodes, cross-repo matchers in pass_cross_repo. Also adds MQTT,
NATS, Dapr async patterns.
Protobuf extraction: service as Class, rpc as Function with rpc_name
fallback in func_name_node. Route nodes created by line-range matching
rpc Functions to enclosing service Classes.
Tested: Online Boutique protos produce 16 gRPC Route nodes.
New index_repository mode="cross-repo-intelligence" that matches Routes,
Channels, and async topics across indexed projects:
- CROSS_HTTP_CALLS: matches HTTP_CALLS edges against Route nodes in
other projects via deterministic QN (__route__METHOD__/path)
- CROSS_ASYNC_CALLS: matches ASYNC_CALLS edges by broker + topic
- CROSS_CHANNEL: matches Channel nodes (EMITS/LISTENS_ON) by name +
transport across projects
Edges are written bidirectionally: both source and target project DBs
get a CROSS_* edge so the link is visible from either side.
Usage: index_repository(repo_path="/path", mode="cross-repo-intelligence",
target_projects=["*"])
New files: src/pipeline/pass_cross_repo.c/.h
Modified: src/mcp/mcp.c (handler + tool schema), Makefile.cbm
- Tool handlers: set isError:true on actual failures (delete_project, manage_adr,
detect_changes), include errno context in system errors, add structured hints
for empty results (search_graph, query_graph, trace_path, list_projects, index_status)
- verify_project_indexed: include available projects list in error response
- CLI: extract text from MCP envelope for human-readable output, errors to stderr,
exit code 1 on tool errors, --json flag for raw output
- Cancellation: handle notifications/cancelled, track active pipeline in server
struct, signal handler cancels in-progress pipeline and releases lock, watcher
checks g_shutdown before starting new indexing
- Enum member extraction: C#/Java/TS/C++ enum values as Variable nodes
- JS/TS destructured variable splitting: const { A, B, C } = require()
emits individual Variable nodes instead of one blob
- Cypher -- SQL-style single-line comments
- Cypher in_degree/out_degree virtual node properties (thread-safe
via binding store pointer, enables dead code detection via Cypher)
- Cypher regex matching in inline property filters
- Resolution tiebreaking: test/mock QN deprioritization and C# field
type hint resolution for obj.Method() disambiguation
Co-Authored-By: Tommy <Koolerx@users.noreply.github.com>
Fill in function, class, field, call, import, branch, variable,
assignment, throw, and decorator node types for all new languages
based on per-grammar AST analysis. Previously all 89 new languages
had empty_types (module detection only, no extraction).
Programming languages with full specs (31):
Solidity, Typst, GDScript, Gleam, PowerShell, Pascal, D, Nim,
Crystal, Odin, Ada, Sway, Cairo, Move, Hare, Pony, AWK, Fish,
Zsh, Tcl, Fennel, ReScript, PureScript, Nickel, Teal, Luau,
Squirrel, ISPC, Starlark, Puppet, LLVM IR
IDL/config with type/field specs (12):
Prisma, Thrift, Cap'n Proto, Smithy, WIT, Bicep, WGSL, HLSL,
VHDL, SystemVerilog, Apex, Kconfig
Remaining languages have module_types only (config/data formats
where function/class extraction is not applicable).
Add automated extension-to-language mapping tests for all new grammars
that have file extensions. Removes conflicting extensions:
- .blade.php: compound extension, handled by userconfig system
- .env*: filenames, not extensions (no auto-discovery for dotfiles)
- .sv/.svh: already mapped to Verilog, SystemVerilog uses same grammar
Migrate the lang_specs[] array from implicit positional indexing to
C99 designated initializers ([CBM_LANG_X] = {...}), eliminating a
class of silent ordering bugs when adding new languages.
Changes:
- Add ts_factory function pointer to CBMLangSpec struct
- Convert all 66 entries to designated initializer syntax
- Add _Static_assert guard: array size must match CBM_LANG_COUNT
- Replace 140-line cbm_ts_language() switch with 3-line factory dispatch
- Net reduction: 127 lines removed
This is prerequisite infrastructure for the ~90 new language expansion.
- Add SHA256 checksum verification against checksums.txt (was missing,
all other installers had it)
- Validate URL scheme on every redirect hop (HTTPS-only, max 5 redirects)
- Replace execSync string interpolation with execFileSync array args
(eliminates shell injection vector)
- Add path traversal check on extracted binary (tar-slip defense)
install.ps1:
- Remove both Unblock-File calls (Defender ClickFix.R!ml signal)
- Remove ExecutionPolicy ByPass from usage comment (scanned by Defender)
- Add HTTPS-only URL scheme check on CBM_DOWNLOAD_URL
install.sh:
- Add HTTPS-only URL scheme check on CBM_DOWNLOAD_URL
pkg/go wrapper:
- Add validateURLScheme() to httpGet and fetchChecksums (defense-in-depth,
matching Python wrapper's _validate_url_scheme from PR #248)
All installers now allow localhost/127.0.0.1 for testing but reject
http://, ftp://, file:// and other schemes.
Closes#246.
Three security improvements to pkg/pypi/src/codebase_memory_mcp/_cli.py:
1. tar-slip mitigation (S202) — the previous `tf.extractall(tmp)` /
`zf.extractall(tmp)` calls trusted the archive not to contain absolute
paths or `..` components. Replaced with _safe_extract_tar and
_safe_extract_zip:
- On Python 3.12+, tarfile uses the new `filter='data'` (PEP 706).
- On Python 3.8–3.11 and for zipfile (no built-in filter), each member
path is validated against the destination via os.path.abspath checks;
symlinks and hardlinks in tarballs are rejected outright.
2. URL scheme allowlist (S310) — _validate_url_scheme rejects anything
that isn't https before urlretrieve runs. The URL is constructed from
hardcoded constants today, but this is a cheap defense-in-depth check
against future config sources, redirects, or typos.
3. Justified noqa suppressions on the exec path — os.execv and
subprocess.run receive args as a list (not a shell string) and neither
uses shell=True, so there is no injection vector. Comments document
the invariant so future changes don't reintroduce a shell form.
Verification:
- `ruff check _cli.py --select S` — passes (was 5 findings, now 0)
- Syntax check passes under Python 3.14
- Behavior preserved: download/extract/exec flow is unchanged on happy path
- New failure modes: clear `sys.exit` with actionable message when a
malicious member path or non-https URL is detected
No new dependencies; all changes stdlib-only and compatible with the
project's declared `requires-python = ">=3.8"`.
- SECURITY.md: new Transparency & Disclaimer section at the top with
honest description of filesystem access patterns and liability scope;
new Help Us Stay Secure section actively inviting security research
with a defined scope and promise of fast response + public credit
- README.md: Security & Trust callout after the intro paragraph — brief,
direct, links to SECURITY.md for full context
checksums.txt contains hashes of .tar.gz/.zip archives; VirusTotal
indexes the extracted binaries. Updated README table and badge to use
correct binary SHA-256 hashes for v0.6.0. Updated release.yml to hash
extracted binaries from the binaries/ directory for future releases.
- Adds VirusTotal (0/72) and SLSA Level 3 badges to the header
- Adds Security section with per-binary VirusTotal scan links for v0.6.0
- Adds step in release.yml to auto-append a Security Verification table
with per-binary VirusTotal links to every release's notes going forward
Adds a README.md to pkg/npm so the npmjs.com package page shows
documentation. Updates the files list in package.json to include it.
Will be published with the next version bump.
Adds a thin Go wrapper at pkg/go/cmd/codebase-memory-mcp that detects
the current platform and architecture, downloads the matching pre-built
binary from GitHub Releases, verifies its SHA-256 checksum, caches it,
and replaces the current process via exec.
Install via:
go install github.com/DeusData/codebase-memory-mcp/pkg/go/cmd/codebase-memory-mcp@latest
The Go module proxy indexes this automatically once live on main.
Introduces pkg/ as a self-contained home for all package registry wrappers.
Each subdirectory is a ready-to-publish package that downloads the appropriate
pre-built binary from GitHub Releases — no source compilation at install time.
- pkg/npm/ — postinstall downloads binary; bin.js shim for CLI
- pkg/pypi/ — lazy download on first run via _cli.py; pipx-friendly
- pkg/homebrew/ — multi-arch formula (darwin/linux × arm64/amd64)
- pkg/scoop/ — Windows bucket manifest with autoupdate + checksum
- pkg/winget/ — v1.6.0 manifests (version + installer + locale)
- pkg/chocolatey/ — nuspec + install/uninstall scripts
- pkg/aur/ — PKGBUILD + .SRCINFO for x86_64 and aarch64
All hashes are real SHA-256 checksums from the v0.6.0 release.