Contributing to GraphForge
Thank you for your interest in contributing to GraphForge!
GraphForge is a Rust core with thin Python and Node bindings. These docs target v0.6.0; see installation for
artifact availability. 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 RELEASING.md at the
repository root.
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
cargo-nextest. Cargo with nextest is the CI Rust
compile/test authority
(ADR 0048); the exact CI
commands are in agent-environment.md.
# Install Rustcurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shrustup update stable
# Install cargo-nextestcargo install --locked cargo-nextest
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 checkSee Installation for the published-package path.
Development Workflow
Section titled “Development Workflow”Before Pushing Code
Section titled “Before Pushing Code”Run the targeted tests for the changed surface, then make check before pushing:
cargo fmt --all -- --checkcargo clippy --workspace -- -D warningsmake check # Python format/lint/type-check/security, workflow lint, repo-checksmake check mirrors the CI Lint job. For Rust: run make test-rust (or narrow
with make test-rust ARGS="-p <crate>"). For Python/Node bindings: make test-python
/ make test-node. The CI Gate Rust lane’s exact nextest commands are in
agent-environment.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 / ty via make targets)make formatmake lintmake type-checkPython type checking uses the pinned ty development dependency. make type-check,
make check, and the local pre-commit ty hook use the same pyproject.toml
configuration: Python 3.10 and the public binding package, including
_graphforge_rs.pyi. Run uv sync --locked --all-extras to install the development
environment first. The existing CI lint job runs this check; pre-commit.ci leaves
it to that job because the hook needs the project environment.
The migration retains unsafe-return, redundant-cast, unused-ignore, and redundant
condition diagnostics. Ty checks unannotated function bodies by default. Its
comparison and unreachable-code coverage currently differs from mypy: the
redundant-condition rules cover boolean conditions, but do not replace all of
mypy’s strict_equality and warn_unreachable diagnostics. See
Astral’s migration guide
for the rule mapping. Ty’s strict-equality-semantics option controls inference
and narrowing; it is not an equivalent of mypy’s strict_equality check.
Project 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│ └── …├── 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 six 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, agent-environment.md for sandbox and native-binding caveats, 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
Method and hashes live in the repo; results live on the issue. A development
page records how to reproduce a measurement and the content digests that
identify its inputs. Raw output (JSON, logs, receipts, per-run tables) is
attached to the issue or pull request that produced it, or to a release
artifact when a release claim depends on it, and is never committed under
docs/. scripts/ci/docs-tree-policy.py fails CI on evidence-shaped or
oversize files under docs/ and on any docs/development/*.md that no other
tracked file references; a page named after an issue is folded into its topic
page or deleted when the issue closes. docs/ is the only hand-maintained
source: the published site renders an allowlisted subset and keeps no copies.
Releases and Versioning
Section titled “Releases and Versioning”GraphForge follows Semantic Versioning. The documentation targets v0.6.0 (see installation for artifact availability). Before v1.0.0, backward compatibility and migration support are not guaranteed.
See RELEASING.md at the repository root for the 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.