Contributing to GraphForge
Thank you for your interest in contributing to GraphForge!
GraphForge is a Rust core with thin Python and Node bindings. The current
public release is v0.5.1. Develop and verify from source on main for
engine and binding work.
| Branch | Role |
|---|---|
main |
Current product line (Rust core, Arrow results, Parquet projects, analyst verbs) |
Next steps for contributors: set up the environment below → run the validation
suite → open a focused PR against main. For release operators, start at
Publishing and
release process.
Development Setup
Section titled “Development Setup”Prerequisites: Python 3.10+, Rust stable (pinned by rust-toolchain.toml),
uv, maturin, pnpm for the Node binding, and
Bazelisk (bazelisk on PATH).
CI Rust compile/test authority is Bazel — start with bazel.md.
# Install Rustcurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shrustup update stable
# Install Bazelisk (example: macOS Homebrew)brew install bazelisk
git clone https://github.com/CurateLabs/graphforge.gitcd graphforge
# Install Python dev dependenciesuv sync --dev
# Build and install the native Python extensionmaturin develop --release -m crates/graphforge-bindings-py/Cargo.toml
# Verifycargo test --workspacepython -c "import graphforge; print(graphforge.__version__)"make pre-push-fast # requires bazelisk; runs Cargo/Bazel drift# Optional heavy local Bazel suite (mirrors CI authority):# make bazel-testSee Installation for the published-package path.
Development Workflow
Section titled “Development Workflow”Before Pushing Code
Section titled “Before Pushing Code”Always run the full validation suite before pushing:
cargo fmt --all -- --checkcargo clippy --workspace -- -D warningscargo test --workspacemake pre-push-fast # bazelisk + drift, then format/lint/security/…make pre-pushmake bazel-test # optional: bazelisk test //:ci_rust_testsmake pre-push mirrors the CI gate for the changed surface. Fast path requires
bazelisk and fails closed on Cargo/Bazel feature drift
(scripts/ci/cargo-bazel-drift-check.py). Full local Bazel suite:
make bazel-test (see bazel.md).
Running Tests
Section titled “Running Tests”# Rustcargo test --workspace # all cratescargo test -p graphforge-cypher # one cratecargo test --workspace -- --nocapture # with output
# Python binding / workspace checksmake testmake test-unitCode Quality
Section titled “Code Quality”# Rustcargo fmt --allcargo clippy --workspace -- -D warnings
# Python tooling (ruff / mypy via make targets)make formatmake lintmake type-checkProject Structure
Section titled “Project Structure”graphforge/├── crates/ # Rust workspace│ ├── graphforge-api/ # public Rust facade│ ├── graphforge-cypher/ # openCypher parser│ ├── graphforge-ir/ # graph IR│ ├── graphforge-rel/ # relational lowering│ ├── graphforge-exec/ # execution + analyst verbs│ ├── graphforge-storage/ # project generations, Arrow schemas, Parquet storage│ ├── graphforge-knowledge/ # knowledge + epistemic record domains│ ├── graphforge-bindings-py/ # PyO3 Python binding│ ├── graphforge-bindings-node/ # napi-rs Node binding│ └── … # (Swift/Kotlin UniFFI not a Bazel-migration deliverable)├── packages/ # Node packaging and agent skills├── docs/ # Markdown sources (Starlight syncs an allowlist)├── docs-site/ # Astro Starlight site├── tests/├── Cargo.toml└── pyproject.toml # workspace tooling (not the published wheel)The published graphforge wheel is built from crates/graphforge-bindings-py. Python and
Node are thin bindings — never fallback engines.
Testing Guidelines
Section titled “Testing Guidelines”Writing Tests
Section titled “Writing Tests”Prefer Rust tests colocated with the module under test for core behavior. Binding tests exercise the thin adapter surface only.
#[cfg(test)]mod tests { use super::*;
#[test] fn test_node_scan_op() { let op = GraphOp::NodeScan { var: VarId(0), ty: TypeId(1) }; assert!(matches!(op, GraphOp::NodeScan { .. })); }}Test Quality Standards
Section titled “Test Quality Standards”- Fast where isolation allows
- Isolated: no shared mutable state between tests
- Deterministic: same input = same output
- Named descriptively
See ../engineering/TESTING.md for the release-prep
testing strategy (layered gates, TCK posture, binding release-candidate evidence),
and testing.md for command recipes and suite layout.
Code Style
Section titled “Code Style”cargo fmtenforced in CIcargo clippy -- -D warningsenforced in CI- No
#[allow(dead_code)]without explanation - Public items need doc comments
Python / TypeScript bindings
Section titled “Python / TypeScript bindings”- Thin adapters only — no semantic ownership in the binding layer
- Type hints / typed APIs on public surfaces
- No
# type: ignorewithout explanation - First-party TypeScript compiler/loader policy: typescript-toolchain.md
Pull Request Process
Section titled “Pull Request Process”PR Size Guidelines
Section titled “PR Size Guidelines”Keep each PR focused on one issue and one concern, with the tests needed to prove its acceptance criteria. Size is advisory: split XL work or independently reviewable concerns when the review benefit justifies another CI cycle.
Good:
- Single feature or bug fix
- Clear, focused purpose
- Acceptance criteria covered by tests or deterministic evidence
Too large:
- Multiple unrelated changes
- Refactoring + new feature + bug fixes combined
For example, a bounded Cypher feature may need parser, IR, lowering, execution, and regression-test changes in one PR to demonstrate working behavior. Do not split solely at crate boundaries or defer a change’s acceptance tests to a later PR. When a split is justified, each PR must have independently verifiable acceptance criteria, and dependencies must be explicit.
Merge cadence
Section titled “Merge cadence”Finish and merge reviewed work before starting more implementation. Coordinated agent teams have a limit of three unmerged changes across all agents, including draft PRs and implemented local branches. The coordinating agent owns the merge queue; prioritize existing PRs and shared CI blockers, and integrate dependent changes in order. See the work-in-progress rules in AGENTS.md for counting, the bounded blocker exception, and handling an inherited backlog.
No Bandaid Fixes
Section titled “No Bandaid Fixes”Fix problems properly, not with temporary workarounds. Investigate root causes, add regression tests, and keep CI checks enabled.
PR Requirements
Section titled “PR Requirements”All PRs must:
- Pass required CI checks for the changed surface
- Include tests or deterministic evidence for new behavior
- Update relevant documentation
- Have a clear description
- Reference the issue number in the commit and PR body (
Closes #XXorRefs #XX)
See AGENTS.md for agent workflow and CONTRIBUTING.md for contribution, conduct, and licensing onboarding contract.
Design Principles
Section titled “Design Principles”- Spec-driven correctness — openCypher semantics over performance
- Arrow as the data-plane wire contract — Cypher and analyst/data-bearing results cross language boundaries as Arrow RecordBatch streams; control/metadata/lifecycle/explanation/construction may return scalars, collections, unit, or handles
- GraphForge owns the semantics — no binding or storage provider becomes the semantic owner
- Surfaces stay independent — analyst verbs bypass the Cypher parser; they do not rewrite it
- Inspectable —
explainat every compiler stage; structured errors with spans
openCypher TCK Compliance
Section titled “openCypher TCK Compliance”When implementing openCypher features:
- Check the TCK coverage matrix and related conformance docs under
docs/reference/ - Mark features as supported, planned, or unsupported as appropriate
- Add corresponding TCK / regression coverage
- Ensure semantic correctness per the openCypher specification
Supported features must pass their TCK scenarios — this is a hard merge gate.
Documentation
Section titled “Documentation”Code documentation
Section titled “Code documentation”- Rust: doc comments (
///) on all public items;cargo docmust build cleanly - Bindings: document only the thin public adapter surface
Project documentation
Section titled “Project documentation”When adding features, update:
docs/book/architecture/— if the change affects the compiler pipeline, storage, or execution modeldocs/reference/— if the public API changes
Bazel migration work follows the sub-agent contracts in bazel-migration-orchestration.md (canonical issue #1). Start with the developer guide bazel.md. The frozen inventory, baseline, and #1 close-readiness evidence map live in bazel-migration-ledger.md, bazel-migration-baseline.md, and bazel-migration-ac-evidence.md. Mobile (Swift/Kotlin/UniFFI) bindings are not a Bazel-migration deliverable.
Releases and Versioning
Section titled “Releases and Versioning”GraphForge follows Semantic Versioning. The current coordinated public release is v0.5.1 (see installation).
See release-process.md for the full release procedure and roadmap.md for delivery sequencing.
Getting Help
Section titled “Getting Help”- Questions: GitHub Discussions
- Bugs: GitHub Issues
License
Section titled “License”GraphForge is open source under the Apache License 2.0 (Apache-2.0). Under
Section 5 of that license, intentionally submitted contributions are provided
under Apache-2.0 unless explicitly stated otherwise. Contributors retain
ownership and must have the right to submit their work; contributions made
within the scope of employment require employer authorization.