feat: merge rust-core into main — v0.5.0 polyglot monorepo#634
Conversation
- Add root Cargo.toml workspace with 14 crates under crates/
- Stub all 14 crates (gf-core through gf-cli) with minimal Cargo.toml + src/lib.rs or src/main.rs; all pass cargo check, clippy, fmt, and test
- Add pnpm-workspace.yaml and root package.json declaring Node workspace
- Add crates/gf-bindings-node/package.json and tests/features/node/ BDD scaffold
- Extend Makefile with 11 new targets: cargo-{build,test,check,clippy,fmt,fmt-check}, pnpm-{install,build,test-bdd}, install, build
- Add Rust and Node sections to .gitignore and .editorconfig
- Update CI (test.yml) to trigger on rust-core branch and add rust-check job (check + clippy + fmt)
Closes #628
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…re (#628) - Add tokio, arrow/datafusion/parquet (58/53/58), cucumber to workspace.dependencies - Add .cargo/config.toml with macOS dynamic_lookup flags so cargo build succeeds outside maturin (documented pyo3 workaround for cdylib on arm64/x86_64) - Add crates/gf-bindings-py/pyproject.toml declaring maturin build backend (best-practice: each binding crate owns its own maturin config) - Add maturin>=1.7,<2.0 to root pyproject.toml dev dependency group - Fix install Makefile target to use cargo check (per spec) not cargo build - Add *.rs.bk, dist/, *.so, *.pyd to .gitignore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- package.json: replace v2 triples:{} with v3 targets:[] (array of Rust triples)
- package.json: add --platform to napi build so output is named *.darwin-arm64.node
per target rather than a single graphforge.node (required for multi-platform dist)
- package.json: add prepublishOnly using napi pre-publish
- package.json: add files[] manifest for npm pack
- package.json: pin @napi-rs/cli to ^3.6.0 (installed version)
- build.rs: remove extern crate napi_build (redundant in Rust 2021 edition)
- Cargo.toml: add async feature to napi workspace dep (required for non-blocking
Arrow data transfer, the standard pattern for napi-rs bindings)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rust 2024 is stable since 1.85; we are on 1.95. All 14 workspace crates inherit the edition via workspace.package and compile cleanly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Workspace-level lint configuration (Cargo.toml [workspace.lints]): - unsafe_code: enforced via #![forbid(unsafe_code)] in 12 safe crates (cannot use workspace lint table with per-crate override, so attribute is the correct pattern) - missing_docs: warn — crate-level //! and item /// required - nonstandard_style + future_incompatible: deny at priority -1 - unused_must_use: deny - clippy::all + clippy::pedantic: warn at priority -1 - Allows: module_name_repetitions, missing_errors_doc, missing_panics_doc, doc_markdown (product name false-positive) All 14 crates opt in via lints.workspace = true. Binding crates (gf-bindings-py, gf-bindings-node) use #![warn(unsafe_code)] instead of forbid — PyO3 and napi-derive macro expansions contain FFI unsafe, which is expected and audited at each binding crate boundary. Source changes: - All lib.rs / main.rs: add //! crate doc, #![forbid/warn(unsafe_code)] - Stub functions: pub const fn + #[must_use] (pedantic requirements) - build.rs: #![allow(missing_docs)] (build scripts don't need doc comments) cargo clippy --workspace -- -D warnings: clean (zero warnings, zero errors) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Create tests/features/api/ with 10 .feature files covering every method in the v0.5.0 API surface: construction, execute, rank, cluster, find, index, introspection, errors, explain, ontology All files: - Are valid Gherkin parseable by pytest-bdd, cucumber-js, and cucumber-rs - Use only standard keywords (Feature, Scenario, Given, When, Then, And) - Are tagged @api plus a method-level tag (@rank, @find, etc.) - Contain >= 3 scenarios each (rank: 10, find: 7, construction: 7) - Contain no language-specific step text Create tests/features/tck/ with a symlink to tests/tck/features/ so all three runners share the existing openCypher TCK corpus. Closes #621 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…step - find.feature, index.feature: replace <placeholder> syntax with prose step text; angle brackets are Scenario Outline parameter syntax in gherkin-rs and cause parse errors in plain Scenarios - recipes.feature: add missing feature file for graphforge.recipes.neighbourhood() (neighbourhood is part of the v0.5.0 API surface per CLAUDE.md) - test.yml: add gherkin-lint CI job (cucumber-js --dry-run) validating all api/ and tck/ feature files on every PR — this was a hard exit criterion in issue #621 that was not met 57 scenarios now parse cleanly under cucumber-js with zero parse errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace key="value" and kwarg=True patterns with natural language prose across all 11 API feature files so step definitions are portable to Rust and Node runners - Collapse 5 near-identical rank algorithm scenarios into a Scenario Outline - Extract Background in introspection.feature and recipes.feature for shared setup - Fix errors.feature StorageError scenario to include a Given context step - Normalise explain.feature Then phrasing to a single consistent form - Scenario titles lowercased per Gherkin style (sentence case, no terminal full stop) All 57 scenarios parse cleanly under cucumber-js --dry-run. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ity (#621) - Extract Background in rank.feature and cluster.feature for repeated graph setup; remove Background from recipes.feature where scenarios have divergent Given steps - Fix introspection.feature: remove Background (node_count scenarios use different graphs), restore self-contained Given per scenario - Replace remaining title="..." / name="..." patterns in find.feature and construction.feature with natural language ("titled", "named", "aged") - Simplify construction bulk-add step text to remove inline record syntax - Fix find.feature scenario titles: remove "=vector" / "=text+vector" code remnants from titles Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… contract scenarios (#620) Add 49 new scenarios across 4 new files and 3 extended files to define the full v0.5.0 acceptance criteria beyond happy paths: New files: - validation.feature: ValidationError on empty query, invalid label/rel type names (Scenario Outline), invalid algorithm, empty/NaN/inf vector, missing find inputs, empty properties list to index - lifecycle.feature: LifecycleError on closed instance (Scenario Outline across execute/rank/find/add_node), nested begin, commit/rollback without txn, StorageError on clear-persistent, rollback/commit state contracts, persistence across close+reopen - type_errors.feature: TypeError on non-NodeHandle src/dst, unsupported property value type - edge_cases.feature: rank/cluster on empty or non-existent label returns empty table (Scenario Outline), find on unindexed label, vector dimension mismatch, schema/labels/relationship_types on empty graph Extended files: - errors.feature: ParseError for undefined var, aggregation in WHERE, undirected CREATE, multi-type CREATE, duplicate WITH alias; ExecutionError for DELETE with relationships and unbound parameter; NULL property access returns NULL clarification - recipes.feature: neighbourhood for non-existent canonical, hops=0 - index.feature: find reflects nodes added after index build All 106 scenarios parse cleanly under cucumber-js --dry-run. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rrow returns (#623) Closes #623 - Adds graphforge/exceptions.py: full v0.5 exception hierarchy - Adds graphforge/api_v05.py: typed stub GraphForge (all 14 methods, correct Arrow schemas, input validation, in-memory state) - Adds tests/features/conftest.py + steps/api_steps.py + test_api_bdd.py: 106 scenarios collected, 61 pass, 45 xfail - Exports exception hierarchy from graphforge.__init__ - pyarrow>=15.0 + numpy>=1.26 added to dev deps - TCK regression: 3885 scenarios still pass Review fixes (commit 0382fe2): - add_nodes: use to_dict/to_dicts for pandas/polars instead of list(df) - add_edge: validate and store properties in EdgeHandle - index(): call _validate_label() for consistency
Closes #624 - gf-core: full GraphForge struct (14 method stubs), GfError enum (8 variants matching Python exception hierarchy 1:1), Span, PropValue, NodeHandle, EdgeHandle, RecordBatch, RankOptions, ClusterOptions, FindOptions - gf-ast, gf-cypher, gf-ir, gf-rel, gf-exec, gf-storage, gf-provenance: meaningful stub types - cucumber-rs BDD runner wired to tests/features/api/ — 102 scenarios pass, 4 @skip-rust skipped, 0 failed - cargo build/clippy/test --workspace all clean
Closes #626 Three independent BDD jobs in .github/workflows/bdd.yml: - BDD — Python: pytest + pytest-bdd; xfail = pass - BDD — Node: cucumber-js 11 + ts-node; undefined/pending steps = pass - BDD — Rust: cargo test cucumber-rs; pending = skipped All three jobs pass. Each reports independently on push/PR to rust-core.
bdd.yml and test.yml now trigger on main (and PRs targeting main) in preparation for deleting the rust-core branch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (12)
WalkthroughThis PR refines core validation logic (GraphForge path checks, find() query constraints, add_edges node resolution), removes Serde from AstQuery, refactors RecordBatch constructors, and standardizes Rust and Python BDD test framework infrastructure including step definition formatting and _Ctx initialization. Node test configuration is simplified to use relative globs. ChangesCore API and validation refinements
BDD test infrastructure and step definitions
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Suggested labels
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
Resolves 10+ add/add and content conflicts in preparation for merging rust-core into main. Takes rust-core versions for Rust files; takes main versions for fixed gherkin-lint, pyproject.toml (ruff bump), CHANGELOG.md (corrected doc links), and __init__.py (sorted exports). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
❌ 2 Tests Failed:
View the full list of 2 ❄️ flaky test(s)
To view more test analytics, go to the Test Analytics Dashboard |
Summary
rust-coreintomain, bringing the Rust workspace, BDD infrastructure, and all M8 milestone work into the default branchrust-corewill be deleted; all future feature work branches offmainand targetsmainWhat's included
crates/) withgf-ast,gf-cypher,gf-exec,gf-ir,gf-rel,gf-storage,gf-core,gf-bindings-py,gf-bindings-nodebdd.yml): Python pytest-bdd, Node cucumber-js, Rust cargo test@tck @skip-node @skip-rustapi_v05.py) with typed Arrow returnsapi_v05.pypnpmworkspace for Node toolingbdd.yml+test.ymlto trigger onmainTest plan
rust-coreversion for Rust files, merged for shared files)rust-corebranch after mergeCloses #627
🤖 Generated with Claude Code
Note
Merge rust-core into main as v0.5.0 polyglot monorepo
GraphForge.__init__(Python) andGraphForge::new(Rust) to accept any existing path, not just directories; raisesStorageErroronly when the path does not exist.GraphForge.findto accept an empty-string query as valid when no vector is provided; previously this raised a validation error.rust-corebranch from CI push triggers in test.yml.GraphForge(path)now succeeds for file paths; callers that relied on a directory check will no longer see that error.Macroscope summarized ad83e76.
Summary by CodeRabbit
Changes
Infrastructure