Files
deusdata--codebase-memory-mcp/CONTRIBUTING.md
T
wehub-resource-sync 41cb1c0170
OpenSSF Scorecard / scorecard (push) Failing after 0s
DCO / dco (push) Failing after 0s
CodeQL SAST / analyze (push) Failing after 1s
Deploy Pages / deploy (push) Failing after 1s
chore: import upstream snapshot with attribution
2026-07-13 12:28:05 +08:00

202 lines
9.1 KiB
Markdown

# Contributing to codebase-memory-mcp
Contributions are welcome. This guide covers setup, testing, and PR guidelines.
> **Important**: This project is a **pure C binary** (rewritten from Go in v0.5.0). Please submit C code, not Go. Go PRs may be ported but cannot be merged directly.
## Build from Source
**Prerequisites**: C compiler (gcc or clang), make, zlib, Git. Optional: Node.js 22+ (for graph UI).
```bash
git clone https://github.com/DeusData/codebase-memory-mcp.git
cd codebase-memory-mcp
git config core.hooksPath scripts/hooks # activates pre-commit security checks
scripts/build.sh
```
macOS: `xcode-select --install` provides clang.
Linux: `sudo apt install build-essential zlib1g-dev` (Debian/Ubuntu) or `sudo dnf install gcc zlib-devel` (Fedora).
The binary is output to `build/c/codebase-memory-mcp`.
## Run Tests
```bash
scripts/test.sh
```
This builds with ASan + UBSan and runs all tests (~2040 cases). Key test files:
- `tests/test_pipeline.c` — pipeline integration tests
- `tests/test_httplink.c` — HTTP route extraction and linking
- `tests/test_mcp.c` — MCP protocol and tool handler tests
- `tests/test_store_*.c` — SQLite graph store tests
## Run Linter
```bash
scripts/lint.sh
```
Runs clang-tidy, cppcheck, and clang-format. All must pass before committing (also enforced by pre-commit hook).
## Run Security Audit
```bash
make -f Makefile.cbm security
```
Runs 8 security layers: static allow-list audit, binary string scan, UI audit, install audit, network egress test, MCP robustness (fuzz), vendored dependency integrity, and frontend integrity.
## Project Structure
```
src/
foundation/ Arena allocator, hash table, string utils, platform compat
store/ SQLite graph storage (WAL mode, FTS5)
cypher/ Cypher query → SQL translation
mcp/ MCP server (JSON-RPC 2.0 over stdio, 14 tools)
pipeline/ Multi-pass indexing pipeline
pass_*.c Individual pipeline passes (definitions, calls, usages, etc.)
httplink.c HTTP route extraction (Go/Express/Laravel/Ktor/Python)
discover/ File discovery with gitignore support
watcher/ Git-based background auto-sync
cli/ CLI subcommands (install, update, uninstall, config)
ui/ Graph visualization HTTP server (first-party httpd)
internal/cbm/ Tree-sitter AST extraction (64 languages, vendored C grammars)
vendored/ sqlite3, yyjson, mimalloc, xxhash, tre, nomic
graph-ui/ React/Three.js frontend for graph visualization
scripts/ Build, test, lint, security audit scripts
tests/ All C test files
```
## Adding or Fixing Language Support
Language support is split between two layers:
1. **Tree-sitter extraction** (`internal/cbm/`): Grammar loading, AST node type configuration in `lang_specs.c`, function/call/import extraction in `extract_*.c`
2. **Pipeline passes** (`src/pipeline/`): Call resolution, usage tracking, HTTP route linking
**Workflow for language fixes:**
1. Check the language spec in `internal/cbm/lang_specs.c`
2. Use regression tests to verify extraction: `tests/test_extraction.c`
3. Check parity tests: `internal/cbm/regression_test.go` (legacy, being migrated)
4. Add a test case in `tests/test_pipeline.c` for integration-level fixes
5. Verify with a real open-source repo
### Infrastructure Languages (Infra-Pass Pattern)
Languages like **Dockerfile**, **docker-compose**, **Kubernetes manifests**, and **Kustomize** do not require a new tree-sitter grammar. Instead they follow an *infra-pass* pattern, reusing the existing tree-sitter YAML grammar where applicable:
1. **Detection helpers** in `src/pipeline/pass_infrascan.c` — functions like `cbm_is_dockerfile()`, `cbm_is_k8s_manifest()`, `cbm_is_kustomize_file()` identify files by name and/or content heuristics (e.g., presence of `apiVersion:`).
2. **Custom extractors** in `internal/cbm/extract_k8s.c` — tree-sitter-based parsers that walk the YAML AST (using the tree-sitter YAML grammar) and populate `CBMFileResult` with imports and definitions.
3. **Pipeline pass** (`pass_k8s.c`, `pass_infrascan.c`) — calls the extractor and emits graph nodes/edges. K8s manifests emit `Resource` nodes; Kustomize files emit `Module` nodes with `IMPORTS` edges to referenced resource files.
**When adding a new infrastructure language:**
- Add a detection helper (`cbm_is_<lang>_file()`) in `pass_infrascan.c` or a new `pass_<lang>.c`.
- Add the `CBM_LANG_<LANG>` enum value in `internal/cbm/cbm.h` and a row in the language table in `lang_specs.c`.
- Write a custom extractor that returns `CBMFileResult*` — do not add a tree-sitter grammar.
- Register the pass in `pipeline.c`.
- Add tests in `tests/test_pipeline.c` following the `TEST(infra_is_dockerfile)` and `TEST(k8s_extract_manifest)` patterns.
## Commit Format
Use conventional commits: `type(scope): description`
| Type | When to use |
|------|-------------|
| `feat` | New feature or capability |
| `fix` | Bug fix |
| `test` | Adding or updating tests |
| `refactor` | Code change that neither fixes a bug nor adds a feature |
| `perf` | Performance improvement |
| `docs` | Documentation only |
| `chore` | Build scripts, CI, dependency updates |
Examples: `fix(store): set busy_timeout before WAL`, `feat(cli): add --progress flag`
## Pull Request Guidelines
### Before You Write Code
- **Open an issue first — always.** Every PR must reference a tracking issue (`Fixes #N` or `Closes #N`). Describe what you want to change and why. Wait for maintainer feedback before implementing. PRs without a prior issue discussion will be closed.
- **Bug fixes and test additions** are the exception — these are welcome without prior discussion, as long as they're focused.
### What Requires Explicit Maintainer Approval
The following changes will not be merged without prior design discussion in an issue:
- **API surface changes** — adding, removing, renaming, or changing defaults of MCP tools
- **New pipeline passes or indexing algorithms** — anything that changes what gets extracted or how
- **Build system / Makefile changes** — beyond trivial fixes
- **Project configuration** — CLAUDE.md, skill files, .mcp.json, CI workflows
- **New dependencies** — vendored or otherwise
- **Breaking changes** of any kind
If in doubt, open an issue and ask.
### PR Scope and Size
- **One issue per PR.** Each PR must address exactly one bug, one feature, or one refactor. Do not bundle multiple fixes or feature additions into a single PR. Kitchen-sink PRs will be closed with a request to split.
- **Keep PRs small.** A good PR is under 500 lines. If your change is larger, split it into reviewable increments that each stand on their own.
- **Don't mix features with fixes.** If you find a bug while implementing a feature, submit the bug fix as a separate PR.
### Code Requirements
- **C code only** — this project was rewritten from Go to pure C in v0.5.0. Go PRs will be acknowledged and potentially ported, but cannot be merged directly.
- Include tests for new functionality
- Run `scripts/test.sh` and `scripts/lint.sh` before submitting
- Keep PRs focused — avoid unrelated reformatting or refactoring
## Security
We take security seriously. All PRs go through:
- Manual security review (dangerous calls, network access, file writes, prompt injection)
- Automated 8-layer security audit in CI
- Vendored dependency integrity checks
If you add a new `system()`, `popen()`, `fork()`, or network call, it must be justified and added to `scripts/security-allowlist.txt`.
## Good First Issues
Check [issues labeled `good first issue`](https://github.com/DeusData/codebase-memory-mcp/labels/good%20first%20issue) for beginner-friendly tasks with clear scope and guidance.
## License and sign-off (DCO) — required on every commit
All contributions are licensed under the project's MIT License
(inbound = outbound). To make that explicit and permanent, this project
uses the [Developer Certificate of Origin 1.1](DCO) — the same mechanism
as the Linux kernel: **every commit must carry a `Signed-off-by` trailer
matching the commit author.**
```bash
git commit -s # adds: Signed-off-by: Your Name <you@example.com>
```
**Adding a `Signed-off-by` line to a commit constitutes your certification
of the [Developer Certificate of Origin 1.1](DCO) — in full, all four
clauses — for that contribution.** The sign-off must match the commit's
author name and email (enforced by CI). In short: you certify that you
wrote the change or otherwise have the right to submit it under the MIT
license, and that you understand the contribution and your sign-off are
public and permanent.
(Independently of the DCO, submitting a contribution to this repository is
also subject to GitHub's Terms of Service §D.6, under which contributions
are licensed inbound = outbound — i.e., under this repository's MIT
license.)
Enforcement is strict and automated:
- CI rejects every push and pull request containing an unsigned commit
(`scripts/check-dco.sh`).
- Install the local hook so unsigned commits are rejected at commit time:
```bash
scripts/install-git-hooks.sh
```
Forgot to sign? `git commit --amend -s` fixes the last commit;
`git rebase --signoff <base>` fixes a whole branch.