Skip to content

fix(stella-cli): let the witness author name the candidate root in glob - #1843

Merged
macanderson merged 1 commit into
mainfrom
fix/witness-glob-root-path
Aug 6, 2026
Merged

fix(stella-cli): let the witness author name the candidate root in glob#1843
macanderson merged 1 commit into
mainfrom
fix/witness-glob-root-path

Conversation

@macanderson

@macanderson macanderson commented Aug 6, 2026

Copy link
Copy Markdown
Owner

What & why

Refs #1792, #1813.

The review bot flagged this on #1813 (witness_tools.rs:200) and it merged before the thread was answered, so the defect is on main now.

The witness author's glob guard refuses the tool's own default argument. crates/stella-tools/src/glob.rs documents and implements the root two ways:

"path": { "type": "string", "description": "Subdirectory to search (default: workspace root)" }
...
let search_path = input.get("path").and_then(|v| v.as_str()).unwrap_or(".");
// `.`/empty resolve to the root itself, so existing default-scoped calls keep working.

But WitnessToolExecutor gated path on normalized_candidate_path, which answers None for both:

  • "" → the is_empty() guard
  • "." → the CurDir component is dropped, parts ends up empty, and (!parts.is_empty()).then(...) yields None

So a model that spells the default out loud — which they routinely do — is told "the path must stay within the candidate root" about the root itself. That is the blind author's opening move, and the whole reason glob was offered to it in #1792.

The root cause

normalized_candidate_path's None conflates two different answers: "escapes the root" and "is the root". That is correct for read_file, which was what it was written for — a path naming no file is simply not readable. It is wrong for a listing tool, where the root is the most ordinary argument there is.

names_candidate_root answers the second question separately. It rules out absolute and drive-qualified spellings first, so / — which would otherwise trim to the empty string and look like the root — stays an escape.

The witness

  • This PR includes a witness test (fails on main, passes here).

candidate_ws::witness_tools::tests::glob_accepts_the_root_spelled_out_as_well_as_omitted, checked the artisanal way:

panicked at crates/stella-cli/src/candidate_ws/witness_tools.rs:655:17:
`path: "."` names the root and must be allowed: Error { message:
"`glob` is not available to the witness author: the path must stay within the candidate root" }
test result: FAILED. 0 passed; 1 failed

It asserts both directions: ., "", ./ are allowed and actually search the root; /, .., ../.., /etc are still refused.

Why the existing test did not catch it: glob_lets_the_author_discover_tests_without_leaking_credentials only ever passes no path (exercising the tool's own default, which never reaches the guard) or an escaping one. The explicit-root case sat exactly in the gap between them.

The gate

  • cargo fmt --check -p stella-cli
  • cargo test -p stella-cli — 1421 pass, 0 fail

Nothing left behind

  • There is nothing: everything I noticed is fixed in this PR.

Summary by Sourcery

Allow the witness glob tool to treat explicit root paths as valid while still denying paths that escape the candidate workspace.

Bug Fixes:

  • Fix glob witness tool incorrectly rejecting explicit root paths such as "." or "" that should resolve to the workspace root.

Enhancements:

  • Introduce a helper to detect when a path names the candidate root, distinguishing it from paths that escape the root.

Tests:

  • Add a witness test verifying that glob accepts explicit root spellings and continues to refuse paths that leave the candidate root.

…lob`

The `glob` tool documents `path` as "Subdirectory to search (default:
workspace root)" and resolves both `.` and `""` to the root. The witness
executor's guard reused `normalized_candidate_path`, whose `None` means
"no relative path" — which covers *both* "escapes the root" and "is the
root". Only the second is legal, and collapsing them made `glob` refuse
its own default argument, denying the blind-discovery move #1792 exists
to enable.

`names_candidate_root` answers the second question separately. It rules
out absolute and drive-qualified spellings first, so `/` — which would
otherwise trim to the empty string — stays an escape.

Witness: `glob_accepts_the_root_spelled_out_as_well_as_omitted`, which
also pins `/`, `..`, `../..` and `/etc` as still refused.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @macanderson, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
stella-cli-docs Ignored Ignored Aug 6, 2026 10:54am

@sourcery-ai

sourcery-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adjusts the glob witness tool path guard so that explicit root spellings are accepted while still rejecting escaping paths, by introducing a dedicated root-detection helper and adding regression tests.

File-Level Changes

Change Details Files
Relax glob path guard to allow explicit root spellings while still rejecting paths that escape the candidate root.
  • Update the glob arm in WitnessToolExecutor to short‑circuit the denial check when the provided path names the candidate root, instead of relying solely on normalized_candidate_path returning Some.
  • Preserve the existing behavior that denies glob calls whose path escapes the candidate root or is otherwise invalid.
crates/stella-cli/src/candidate_ws/witness_tools.rs
Introduce a helper to detect whether a user-provided path denotes the candidate root itself.
  • Add names_candidate_root function that normalizes separators, rejects absolute and drive-qualified paths, and treats empty, ., and ./-style spellings as naming the root.
  • Document the separation of concerns between names_candidate_root and normalized_candidate_path, clarifying the different semantics of None for listing vs. reading tools.
crates/stella-cli/src/candidate_ws/witness_tools.rs
Add regression test to verify glob accepts explicit root spellings and still refuses escaping paths.
  • Create async test glob_accepts_the_root_spelled_out_as_well_as_omitted that sets up a temporary candidate workspace with a test file.
  • Assert that glob with path values of ., "", and "./" returns results containing the root test file.
  • Assert that glob with path values that escape or are absolute (e.g., /, .., ../.., /etc) are rejected with an error.
crates/stella-cli/src/candidate_ws/witness_tools.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@macanderson
macanderson merged commit 97adc64 into main Aug 6, 2026
10 of 12 checks passed
@macanderson
macanderson deleted the fix/witness-glob-root-path branch August 6, 2026 18:27
macanderson added a commit that referenced this pull request Aug 6, 2026
…1813 (#1859)

## What this is

An unbreak: 608a0aa (#1813) landed two `clippy -D warnings` failures in
`crates/stella-pipeline/src/pipeline/witness_stage.rs`, so the
fmt+clippy+test gate is red on main and on every PR branched from it.
The first masks the second because cargo stops at the first error.

- **clone_on_copy** (line 55): `apply_role_shaping` did `params.clone()`
where `GenerationParams` became `Copy` in a parallel change — copy it
out of the borrow instead.
- **field_reassign_with_default** (line 648, tests): the #1785 witness
test built its worker config by mutating a `default()` — struct-update
syntax now.

## Verification

Pure lint fixes, no behavior change, so no witness test — the witness is
clippy itself: `cargo clippy -p stella-pipeline --all-targets -- -D
warnings` fails on main at both sites and passes on this branch. `cargo
test -p stella-pipeline shaping` (including #1785's
`verifier_shaping_overlays_the_worker_engine_config`) passes.

After this merges, open PRs (#1843, #1836, #1844) need `gh pr
update-branch` to go green.

## Summary by Sourcery

Fix clippy lint violations in stella-pipeline’s witness_stage to restore
a clean build.

Bug Fixes:
- Avoid cloning a Copy GenerationParams value when applying role shaping
overrides.
- Construct test EngineConfig instances with struct update syntax
instead of mutating a default value to satisfy clippy lints.

Co-authored-by: Stella Test <test@stella.local>
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