Skip to content

Fix three runvil-vfs leftovers: range reads, a refusal path, and the glob root - #16

Merged
vinniefalco merged 3 commits into
cppalliance:masterfrom
vinniefalco:master
Nov 14, 2026
Merged

vinniefalco merged 3 commits into
cppalliance:masterfrom
vinniefalco:master

Conversation

@vinniefalco

@vinniefalco vinniefalco commented Nov 14, 2026 •

Copy link
Copy Markdown
Member

Three small fixes in runvil-vfs that the private run store work (#15) found and left as they were.

Commits

  • Forward a byte-range read through a mounted handle. The comment on HandleAccess said that the capability has no byte-range read. Access has read_range, so a range read through an overlay took the trait default: the base handle read the whole file, and the default sliced it. HandleAccess now forwards read_range, and a base backend that can seek reads only those bytes. The policy check, the read claim, and the event are the same on both routes.
  • Name / when an ended store view refuses a spawn. A spawn names no path, so its refusal names /. On a store view that path was re-spelled to the empty path, while the refusal of a new view of the same ended access named /. Both name / now.
  • Match no glob pattern against the root of a memory backend. MemoryBackend keeps the root among its directories, and /* matches the spelling / with an empty segment, so a glob for directories returned the root. store.glob('*/') gave one empty string in an empty store. The memory backend now leaves the root out, as the walk of RealBackend does.

Behavior that changes

  • A glob on any memory-backed handle, a store view included, never returns the root. The patterns /, /*, /**, and /**/* returned it before. The real backend already behaved this way, and one test now runs the same assertions on both.
  • A range read through an overlay reaches the base backend as a range read.
  • The path in one ScopeEnded refusal changes from the empty path to /.

Tests

  • a_read_range_through_an_overlay_reaches_the_base_backend_as_that_range fails without the forward, because the base backend records no range.
  • a_directory_glob_never_returns_the_root runs on a memory handle and on a real directory. A test holds the rule for a store view, and one in runvil-lua holds it for store.glob.
  • Two tests of a refused store.view and a refused scope.spawn now check the path, where they matched the variant alone.

Checks

Every command in AGENTS.md passes on the final tree, with the run-prompt example, cargo doc -p runvil, the private-items doc build of runvil-runtime, and cargo deny check. Nextest runs 3,791 tests, all passing, and skips 24. xtask api --check passes with no change to either listing.

Left as it is

  • store_error_message keeps its wording for the store codes that the Harness never gives. A caller of the Engine can answer a Vfs effect with any VfsError, so those messages are reachable through the Engine's API.
  • The path parameter of Scope::fork and of Scope::attach is always /, and some test names still say "the access root".

Summary by CodeRabbit

  • Bug Fixes
    • Directory searches no longer return the virtual root; matching directories and files are still returned as expected.
    • Byte-range reads through overlays now preserve the requested offset and length.
    • Calls made after a scope ends now report the scope-ended error with the root path.
  • Documentation
    • Clarified that glob patterns matching only the root return no results.

`HandleAccess` is the session of a handle that is mounted as a backend, and its comment said that the capability has no byte-range read. `Access` has `read_range`, so `HandleAccess` now forwards `read_range` to it, and the comment names only the POSIX extras as left on their trait defaults.

- A range read through an overlay took the trait default before: the base handle read the whole file and the default sliced it. The base backend now gets the range, so a backend that can seek reads only those bytes.
- The policy check, the read claim, and the event are the same on both routes, because `read` and `read_range` of `Access` take the same steps.
- The new test in `read_range.rs` reads through an overlay of a handle on `RangeSpy`. It fails without the forward, because the base backend records no range.
A spawn names no path, so its refusal names `/`. `Access::spawn` re-spelled that path for a store view, and the refusal named the empty path there, while the refusal of a new view of the same ended access named `/`. The spawn now reports the path as the scope gives it.

- The two calls of `relativize` in `spawn` are removed. A spawn from a plain access is unchanged, because `relativize` left its errors as they were.
- Two tests in `tests/store.rs` matched the refusals of `store.view` and of `scope.spawn` on the variant alone. They now check the path of each, which is `/`.
`MemoryBackend` keeps the root in its set of directories, and `/*` matches the spelling `/` with an empty segment, so a glob for directories returned the root: `store.glob('*/')` gave one empty string in an empty store. `MemoryBackend::glob` now leaves the root out, as the walk of `RealBackend` does, because the root holds every stored path and is not one itself.

- The filter is in `glob` of `memory.rs`, so a handle, a store view, and a mount of a memory backend all get it. The patterns `/`, `/*`, `/**`, and `/**/*` matched the root before.
- The docs of `VfsAccess::glob` and `Access::glob` state that no pattern matches the root.
- `a_directory_glob_never_returns_the_root` runs the same assertions on a memory handle in `handle/tests/semantics.rs` and on a real directory in `real/tests/semantics.rs`. The real backend passed them before this change.
- A test in `handle/tests/store.rs` holds the rule for a store view, and one in the `tests/store.rs` of `runvil-lua` holds it for `store.glob`.
@coderabbitai

coderabbitai Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The memory backend excludes the virtual root from glob results. VFS documentation and tests describe this behavior. HandleAccess forwards byte-range reads, and Access::spawn preserves refusal errors without relativizing their paths.

Changes: Glob root handling

Layer / File(s) Summary
Exclude the root from glob results
crates/runvil-internal/vfs/src/memory.rs, crates/runvil-internal/vfs/src/traits/backend.rs, crates/runvil-internal/vfs/src/handle/operations.rs, crates/runvil-internal/vfs/src/memory-tests.rs
MemoryAccess::glob filters out /. The VFS documentation states that glob patterns do not match the root. Memory-backend tests check root exclusion and stored-path results.
Check glob results across VFS views
crates/runvil-internal/vfs/src/handle/tests/semantics.rs, crates/runvil-internal/vfs/src/real/tests/semantics.rs, crates/runvil-internal/vfs/src/handle/tests/store.rs, crates/runvil-internal/lua/src/tests/store.rs
Tests check that directory glob patterns return no root entry and return stored directories after a nested file is written.

Handle access behavior

Layer / File(s) Summary
Forward byte-range reads
crates/runvil-internal/vfs/src/handle/forward.rs, crates/runvil-internal/vfs/src/handle/tests/read_range.rs
HandleAccess::read_range forwards the path, offset, and length to the mounted capability. The overlay test checks that the base backend receives the same range.
Preserve spawn refusal paths
crates/runvil-internal/vfs/src/handle/access.rs, crates/runvil-internal/vfs/src/handle/tests/store.rs
Access::spawn returns refusal and fork errors without relativizing them. Ended-scope tests check for refusal errors with path /.

Estimated code review effort: 2 (Simple) | ~12 minutes

Merge Risk: Minimal · up to b92fd

This change makes range reads, ended-view refusal paths, and memory-backend glob results behave consistently, with tests for each. No merge-blocking risk was found.

Pre-merge checks: Passed 4

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title names three concrete fixes in runvil-vfs: range reads forwarded through overlays, a refusal path naming the root for ended store views, and the glob root exclusion. The changeset matches all…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names three concrete fixes in runvil-vfs: range reads forwarded through overlays, a refusal path naming the root for ended store views, and the glob root exclusion. The changeset matches all three: HandleAccess forwards read_range, Access::spawn returns errors without relativizing, and MemoryAccess::glob excludes '/'. The title covers the main changes, though it lists three topics rather than one primary change, so it is a partial summary of the whole PR.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: d7e8c65e-ca11-4e54-a444-68592e52dfc0
Commits

Reviewing files that changed from the base of the PR and between 1664eaf and b92fdb3.

Files selected for processing: 11

  • crates/runvil-internal/lua/src/tests/store.rs
  • crates/runvil-internal/vfs/src/handle/access.rs
  • crates/runvil-internal/vfs/src/handle/forward.rs
  • crates/runvil-internal/vfs/src/handle/operations.rs
  • crates/runvil-internal/vfs/src/handle/tests/read_range.rs
  • crates/runvil-internal/vfs/src/handle/tests/semantics.rs
  • crates/runvil-internal/vfs/src/handle/tests/store.rs
  • crates/runvil-internal/vfs/src/memory-tests.rs
  • crates/runvil-internal/vfs/src/memory.rs
  • crates/runvil-internal/vfs/src/real/tests/semantics.rs
  • crates/runvil-internal/vfs/src/traits/backend.rs

Included review availability: This review used your included allowance. 2 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.

@greptile-apps

greptile-apps Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] This PR appears safe to merge; no actionable issues were found.

Summary

This PR fixes three small differences in runvil-vfs:

  • Overlay reads pass the requested byte range to the mounted handle.
  • Memory-backed globs return stored paths without the root.
  • Ended-scope spawn refusals name /, like refused new store views.

Added tests cover range forwarding, root exclusion, and refusal paths. No actionable issues were found.

Acknowledged by vinniefalco as intentionally unchanged: reachable store_error_message wording, the / arguments to Scope::fork and Scope::attach, and test names that still say “the access root.”

Reviews (1) · Last reviewed commit: "Match no glob pattern against the root o..." · Reviewed by Greptile

@vinniefalco
vinniefalco merged commit b92fdb3 into cppalliance:master Nov 14, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant