Repository navigation
Add the Python API over grund-core and prove binding parity - #480
Merged
Merged
Conversation
Retain fetch I/O sources and locations through the additive failure carrier (§FS-distribution.3.3.2), and preserve symlink/.. inputs for engine resolution (§FS-distribution.3.3.3). Correct independent CLI stream and golden comparisons (§FS-distribution.3.0.3), maintain frontend isolation (§AR-bindings.1), and separate the discovery citation note (§FS-inline-citation-style.2.3.1). Add binding regressions for both behavior corrections.
Retain the original snapshot-folder traversal error and its embedded I/O source through the additive fetch diagnostic carrier (§FS-distribution.3.3.2). Preserve scanner records, refusal ordering, and CLI failure text, and retain the fallible walk source alongside its location. Pin denied traversal with direct FilesystemError, location, original cause, OS-code, caution, canonical-parity, and restored-permission byte assertions. Move the unchanged reporting pass into its scanner sibling module to satisfy the staged file-size check. Behavioral verification remains with green.
vjovanov
force-pushed
the
fix/issue-470
branch
from
October 6, 2026 13:03
bba278f to
984baf6
Compare
vjovanov
marked this pull request as ready for review
October 6, 2026 13:03
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #470
Before this change, the checkout had no Python frontend:
import grundfailed withModuleNotFoundError. After a local install with CPython 3.10+ and Rust (python -m pip install .from the checkout), an application can check a tree, iterate its findings and read a declaration:The output above comes from the caller's
print; the API itself is silent. The Python guide and runnable example use this fixture.The complete initial disk-backed inventory includes check/selectors and report iteration, scan, single/batch show, refs, ID lists and sizes, coverage/text, formatting, ID proposal, init, effective configuration and validation, fetch, managed integrations, ID completion, reference style and agent setup instructions. Required operands are positional and other options are keywords with documented defaults. Process transport, watch/exit lifecycle and LSP editor utilities retain their stated frontend scope. §FS-distribution.3.3.5
Results are frozen dataclasses with tuple collections and explicit
Nonefor optional fields; effective configuration is recursively read-only.CheckResultkeeps both the completereportandselected_report, plus separaterun_cautions. Findings preserve locations, all sites, suggestions and rule authority. A completed check with findings returns normally. §FS-distribution.3.3.1Operations that cannot run raise
ConfigError,FilesystemError,QueryErroror fallbackOperationError, each carrying a structured.failurewith causes, details, cautions and partial output. Single query failures raise; batch queries retain individual failures in ordered records. Fetch execution, snapshot writes and snapshot traversal retain filesystem locations and original I/O causes. The final conversion fix extracts OS error codes from the retained source chain, without parsing messages or synthesizing codes. §FS-distribution.3.3.2Each call resolves its own root; omitted roots snapshot cwd and explicit paths preserve engine scope, including filesystem-significant
symlink/... Inputs acceptstrandos.PathLike[str], reject bytes, surrogates and NUL as documented, and retain logical report paths with/. A core preflight rejects the known unsafe unnamed non-Unicode workspace alias. §FS-distribution.3.3.3 Calls are synchronous, release the GIL during Rust work, read no process argv, change no global cwd and never exit Python. Independent reads may overlap; callers serialize writers. Interrupts are checked on return, so work may finish beforeKeyboardInterrupt; there is no async or mid-call cancellation promise. §FS-distribution.3.3.4Mutation requires explicit opt-in:
fmt()andinit()preview by default,init(check=True)suppresses writes, andfetch(..., write=True)authorizes materialization. Fetch without opt-in refuses before config loading or fetcher execution. Integration writes reuse managed ownership, preference validation and agent gates, preserving manual text and instructions. Existing engine data-preservation contracts and CLI defaults remain intact. §FS-distribution.3.3.6crates/grund-pyis an independent PyO3 frontend overgrund-core. Python owns conversion and exception policy; additive core adapters own warning/failure propagation, queries, path preflight and integration orchestration. It uses no CLI subprocess or frontend dependency and duplicates no parser, scanner, resolver or rules. Existing supported Rust entry points and CLI output remain compatible. §FS-distribution.3.1, §AR-bindings.6Root
pyproject.tomluses maturin to build the privategrund._nativeextension withabi3-py310. The publicpython/grundpackage supplies annotated signatures, types andpy.typed; source inclusion supports clean-checkout and unpacked-sdist installs. Ordinary Cargo CLI builds need no Python build dependencies. This handoff targets CPython 3.10+ with the GIL; PyPy and free-threaded Python are unsupported. It adds no competing console entrypoint. §FS-distribution.3.3.7The shared corpus and core-only Rust oracle prove Rust/Python parity through separate complete-data and exact canonical UTF-8 JSON assertions. They cover ordering, nulls, escaping, Unicode/logical paths, warnings, suggestions, sites and authority, alongside mutation preview/write/refusal bytes. Frozen CLI stdout/stderr projections remain checked against authoritative existing goldens, including null-line findings on stderr and the existing empty-stream fixture convention. Node joins through #469. §FS-distribution.3.0.3, §AR-goal-measurement.2
Verification at
bba278fc068ff8594e39dd29ddf3f29a8cac9a8b:cargo build --locked -p grund-core --example grund-binding-oracle --target-dir targetpassed.python tests/bindings/run.pypassed all 33 tests in 103.158s. Coverage includes clean-checkout/unpacked-sdist installs, actual signatures/types/examples, complete-data/canonical-byte parity, CLI JSON goldens, mutation bytes, root independence, silence, GIL/interrupt behavior and resolved frontend isolation. Missing-executable, symlink-parent, denied snapshot-write and denied snapshot-traversal regressions all passed; both permission tests ran as an unprivileged POSIX user.env TMPDIR=/dev/shm pre-commit run --all-filespassed all ten hooks, including the warnings-as-errors build, Rust/Python tests, grounding, formatting, managed init, links and file-size budgets. The final three-command local gate took 8m42s.PyPI publication remains pending. #471 consumes the source/build/type handoff and owns the release matrix, CLI payload, assembly and publication. This change performs no upload, tag, release dispatch or release and assigns no milestone or additional 1.0 gate. Carry Adapt Python marshalling to #466/#453/#454, replacing internal adapters while preserving the approved Python schema and rerunning parity. These coordination items are not landing prerequisites. §FS-distribution.3.1, §FS-distribution.3.3.7
AI workflow: `rhei`, 24 agent invocations across 1 model; 12 tasks completed, 4 in progress.
github-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 1) — cdx, openai/gpt-6.1-sol — 1m27s — 373.4k in / 3.5k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.triageassessing (visit 1) — cdx, openai/gpt-6.1-sol — 1m31s — 331.8k in / 3.4k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.triagefitting (visit 1) — cdx, openai/gpt-6.1-sol — 6m55s — 1.7M in / 18.2k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 2) — cdx, openai/gpt-6.1-sol — 2m13s — 658.6k in / 5.0k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.clarifyclarifying — cdx, openai/gpt-6.1-sol — 2m25s — 749.3k in / 5.8k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 3) — cdx, openai/gpt-6.1-sol — 1m26s — 350.3k in / 3.8k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.planplanning — cdx, openai/gpt-6.1-sol — 11m05s — 3.3M in / 25.8k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 4) — cdx, openai/gpt-6.1-sol — 1m09s — 479.1k in / 2.7k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 5) — cdx, openai/gpt-6.1-sol — 1m33s — 420.5k in / 4.1k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.specifyspecify — cdx, openai/gpt-6.1-sol — 24m35s — 7.8M in / 58.5k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 6) — cdx, openai/gpt-6.1-sol — 2m06s — 708.6k in / 5.4k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.implementimplement — cdx, openai/gpt-6.1-sol — 36m06s — 12.2M in / 84.4k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 7) — cdx, openai/gpt-6.1-sol — 1m40s — 602.0k in / 4.2k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.review-1review — cdx, openai/gpt-6.1-sol — 7m19s — 3.5M in / 17.0k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 8) — cdx, openai/gpt-6.1-sol — 1m53s — 592.9k in / 4.9k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.fix-1fix — cdx, openai/gpt-6.1-sol — 5m20s — 1.7M in / 13.4k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 9) — cdx, openai/gpt-6.1-sol — 1m47s — 625.2k in / 4.6k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.review-2review — cdx, openai/gpt-6.1-sol — 4m18s — 1.6M in / 9.7k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 10) — cdx, openai/gpt-6.1-sol — 1m56s — 848.9k in / 4.8k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.fix-2fix — cdx, openai/gpt-6.1-sol — 7m53s — 1.6M in / 20.5k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 11) — cdx, openai/gpt-6.1-sol — 2m03s — 775.2k in / 4.9k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.greengreen-fix (visit 1) — cdx, openai/gpt-6.1-sol — 3m23s — 1.5M in / 7.8k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticket.greengreen-fix (visit 2) — cdx, openai/gpt-6.1-sol — 56.0s — 335.4k in / 1.5k outgithub-issues-agent-grounds-grund-470-implement-379c3f6c.ticketsupervising (visit 12) — cdx, openai/gpt-6.1-sol — 2m07s — 680.5k in / 4.5k out