fix(cargo-each): prefer PATH when launching Windows child commands - #172
Evgenii (Vaiz) wants to merge 8 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Codecov Report✅ All modified and coverable lines are covered by tests. ❌ Your project status has failed because the head coverage (97.5%) is below the target coverage (100.0%). You can increase the head coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #172 +/- ##
=======================================
- Coverage 97.5% 97.5% -0.1%
=======================================
Files 300 300
Lines 69048 69051 +3
=======================================
+ Hits 67387 67388 +1
- Misses 1661 1663 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🟢 Approval recommended
The remaining documentation update is a minor, non-blocking nit.
Pull request overview
Updates cargo-each so Windows child commands honor inherited PATH precedence while preserving explicit paths, fallback lookup, Unix behavior, and +toolchain arguments.
Changes:
- Forward
PATHexplicitly on Windows. - Add regression coverage for lookup precedence and explicit paths.
- Document executable lookup semantics.
File summaries
| File | Summary |
|---|---|
crates/cargo-each/tests/cli.rs |
Adds Windows lookup and explicit-path coverage. |
crates/cargo-each/src/run.rs |
Forwards inherited PATH to Windows child commands. |
crates/cargo-each/docs/design/README.md |
Documents the updated lookup contract; crate-level docs still need synchronization. |
Review details
Suppressed comments (1)
crates/cargo-each/docs/design/README.md:250
- This externally visible lookup rule is only added to the design doc. The crate-level docs in
crates/cargo-each/src/main.rsare the source for the publishedcrates/cargo-each/README.md(the repository documents that generation inREADME.md:97-100), and they still omit PATH precedence and the unchanged explicit-path/fallback behavior. Add a concise user-facing note to the crate docs and regenerate the README so the published documentation matches this change.
- **Executable lookup.** On Windows, the inherited `PATH` is explicitly passed
to each child so its entries take precedence over the directory containing
`cargo-each`. An adjacent executable must not shadow a tool selected on `PATH`
(for example, a different Cargo toolchain proxy). Explicit executable paths
and the platform's fallback search when no `PATH` entry matches are unchanged.
- Files reviewed: 3/3 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Skip binary-only packages in scoped doctest runs while retaining library and proc-macro targets. Pass the built-in GitHub token during tool installation so release discovery does not hit anonymous API rate limits and unnecessarily fall back to source builds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical findings remain in the setup template and change scope.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (3)
crates/cargo-anvil/docs/design/github.md:800
- This new section documents
cargo-binstallas part of the GitHub setup, but the crate-level security contract still says that all cargo-tool installs use locked Cargo installs and explicitly says “Nocargo-binstall” (crates/cargo-anvil/docs/design/README.md:388-392). Please reconcile those design statements in this change so adopters are not given contradictory installation guarantees.
The Just bootstrap and catalog tool installation steps receive the built-in
`GITHUB_TOKEN`. Cargo-binstall uses it for authenticated release discovery,
avoiding anonymous API rate limits that can trigger unnecessary source builds.
This adds no token permissions and does not install system dependencies.
crates/cargo-anvil/templates/justfiles/anvil/checks/doc-test.just:29
- This map uses PowerShell's default case-insensitive comparer, so a workspace containing case-distinct package names (for example
Fooandfoo) can overwrite one package's target classification with the other's. The impact formatter already uses an ordinal comparer for this exact case (crates/cargo-anvil/templates/justfiles/anvil/impact.just:530-540); use the same comparer here so a binary-only package cannot be selected or skipped based on a different package.
$packages = @{}
crates/cargo-anvil/templates/justfiles/anvil/checks/doc-test.just:24
- Please refresh the full-tree snapshots for this generated change.
crates/cargo-anvil/tests/snapshots.rs:11-23says these tests pin every emitted file byte-for-byte, buttests/snapshots__local_only.snap:1135-1142,tests/snapshots__github_backend.snap:2451-2458, andtests/snapshots__ado_backend.snap:2309-2316still contain the old two-command recipe; the GitHub snapshot also lacks the new setup-actionenvblocks (tests/snapshots__github_backend.snap:647-682). The expected generated trees therefore do not match the changed templates.
# Explicitly selecting a binary-only package makes cargo test --doc fail.
if ($pkg -notcontains '--workspace') {
- Files reviewed: 11/12 changed files
- Comments generated: 3
- Review effort level: Lite
Refresh the cargo-anvil tree snapshots so they match the changed doc-test and setup templates; the MSRV job failed because the emitted trees were pinned byte-for-byte against the previous templates. Remove GITHUB_TOKEN from the environment before any source install, so it reaches cargo-binstall's release discovery but not compiled crates or their build scripts. Classify doctest targets through an Ordinal dictionary so case-distinct package names cannot collapse into one key. Reconcile the crate-level security notes with the GitHub backend's actual binstall path, and document Windows PATH precedence in the cargo-each crate docs feeding the generated README. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical token-exposure and installation-scoping issues remain in the cargo-anvil setup.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (4)
crates/cargo-anvil/templates/github/setup-action.yml:155
- The impact composite does not install cargo-delta inside this setup step:
templates/github/impact-action.ymlfollowsanvil-setup group=nonewith a separaterun: just anvil-tool-cargo-delta-install binstallstep that has noGITHUB_TOKENenvironment. Consequently the impact job's binstall lookup remains anonymous and can still hit the rate limit or fall back to a slow source build; propagate the token to that step as well and regenerate the action.
# Authenticate binstall's release discovery before it falls back to
# source builds. The tool installer drops it before any source install.
GITHUB_TOKEN: ${{ github.token }}
crates/cargo-anvil/templates/github/setup-action.yml:130
GITHUB_TOKENis still present when thiscargo binstallcall starts, and removing it only after a nonzero result is too late: a missing prebuilt release can take binstall's compile strategy, exposing the token to thejustcrate's build scripts. Add--disable-strategies compileto this call so a release miss falls through to the tokenlesscargo installbelow.
& cargo binstall --no-confirm --locked --version ">=$minimum" just
if ($LASTEXITCODE -ne 0) {
# Drop the release-discovery token before compiling third-party code.
Remove-Item Env:GITHUB_TOKEN -ErrorAction SilentlyContinue
crates/cargo-anvil/templates/justfiles/anvil/checks/doc-test.just:25
- The title and description scope this PR to cargo-each's Windows PATH lookup, but this hunk also changes the cargo-anvil doc-test contract; the PR additionally changes cargo-anvil workflow token handling and generated snapshots. Please either split the unrelated cargo-anvil work into a separate PR or update the description and review scope to cover it.
# Explicitly selecting a binary-only package makes cargo test --doc fail.
if ($pkg -notcontains '--workspace') {
$metadataJson = & cargo {{_anvil_stable_toolchain_args}} metadata --no-deps --format-version 1
crates/cargo-anvil/templates/justfiles/anvil/tools.just:458
- The title and description scope this change to cargo-each's Windows child lookup, but this hunk (along with the doc-test, template, action, and snapshot changes) also changes cargo-anvil installation, GitHub token exposure, and generated CI behavior. Please split these unrelated changes into a separate PR or update the PR description and acceptance scope before approval so the security/CI changes can be reviewed under their actual purpose.
# The step-scoped GITHUB_TOKEN exists only so cargo-binstall can query
# GitHub Releases as an authenticated caller instead of being rate-limited
# anonymously. Keep it out of every source install: those compile
# third-party crates and run their build scripts.
$releaseToken = $env:GITHUB_TOKEN
- Files reviewed: 19/20 changed files
- Comments generated: 2
- Review effort level: Lite
…y token Gate the three cargo-gamma-lib doctests that import `internals` on the feature that exposes it. The module is `#[cfg(any(test, feature = "internals"))]`, so those doctests only ever compiled under `--all-features`; the scoped doctest recipe also runs a default-features pass, which is where they failed once the recipe stopped dying earlier on binary-only packages. They still compile and assert for real under `--all-features`. Keep the release-discovery token away from third-party code. Binstall's compile strategy is now disabled whenever the token is set, so a release miss falls through to the tokenless `cargo install` instead of compiling with the credential in scope. Each generated PR job declares the narrowest permissions it needs: the impact and aggregate jobs stay read-only, group jobs add only `statuses: write`, and `pr-fast` alone keeps `pull-requests: write` for the sticky advisory comment. The impact action's cargo-delta install receives the same token so its lookup is not left anonymous. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Write-capable tokens are still passed to third-party installers and must be isolated or read-only.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
crates/cargo-anvil/templates/github/setup-action.yml:157
- The token passed here inherits the calling job's permissions. In
pr-fastthat includespull-requests: write, and in the other group jobs it includesstatuses: write;_install-tool-corethen restores the token forcargo-binstall. A third-party installer therefore receives a write-capable token, which contradicts the read-only claim for non-pr-fastjobs and lets a compromised installer use release discovery as a PR/status write capability. Keep installation/check jobs read-only and isolate advisory/status publication, or provide a separately scoped token.
# Authenticate binstall's release discovery before it falls back to
# source builds. The tool installer drops it before any source install.
GITHUB_TOKEN: ${{ github.token }}
crates/cargo-anvil/templates/justfiles/anvil/tools.just:479
- The new
$releaseTokencondition disables cargo-binstall's compile strategy for every GitHubbinstall, including tools without asourcePrereq. However,crates/cargo-anvil/docs/design/local.md:301-307still states that tools without a source prerequisite retain that strategy, so the installer contract is now stale; qualify that documentation for tokenless/local runs or update it.
if ($sourcePrereq -or $releaseToken) {
$binstallArgs += @('--disable-strategies', 'compile')
- Files reviewed: 25/26 changed files
- Comments generated: 3
- Review effort level: Lite
The per-job permissions added in the previous commit broke `pr_impl_workflow_has_expected_jobs`, which asserts the shared implementation declares no permissions at all so it inherits the root caller's ceiling. That is a deliberate contract, not an oversight, so the narrowing is withdrawn rather than the assertion relaxed. Keeping the credential away from third-party code does not depend on it: the tool installer still removes the token before any source install and still disables binstall's compile strategy while the token is set. Narrowing the token's scopes stays with the adopter's calling workflow, which is where this design puts permissions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Picking up the suppressed findings from the automated reviews, since they do not appear as threads. The case-insensitive map in The The The One suppressed suggestion I did not take: adding |
There was a problem hiding this comment.
🟡 Changes recommended
Token-isolation regression coverage is missing, and a documentation clarification remains.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
crates/cargo-anvil/docs/design/README.md:396
- This new sentence says the built-in token is exposed to the GitHub setup steps only, but the existing generated
anvil-run-groupaction also exportsGITHUB_TOKENto group commands at.github/actions/anvil-run-group/action.yml:50-59. Narrow this wording to the new installation-step use so the security design does not imply that setup is the token's only exposure.
crates/cargo-anvil/templates/justfiles/anvil/tools.just:478
- The existing
install_tool_controls_source_fallback_and_prerequisite_orderingcontract test expects an ordinary binstall to retain the compile strategy, butrun_justinheritsGITHUB_TOKENand.github/actions/anvil-run-group/action.yml:50-59exports it for the whole Anvil group. With this condition, that test'sordinary_toolcase takes the new token branch, making its assertion atrecipe_contracts.rs:1744-1746false. Make the fixture runner remove or explicitly clearGITHUB_TOKEN, then add a separate token-enabled case for this behavior.
if ($sourcePrereq -or $releaseToken) {
- Files reviewed: 23/24 changed files
- Comments generated: 1
- Review effort level: Lite
The installer contract test inherited the ambient `GITHUB_TOKEN`. CI exports one for the whole Anvil group, so its no-prerequisite case took the new token branch there and asserted the opposite of what it observed, passing locally and failing in CI. `just_command` already scrubs ambient values that would otherwise leak into a fixture; add `GITHUB_TOKEN` to that list so the branch under test is chosen by the test rather than by where it runs. Cover the token branch explicitly instead of leaving it to chance. The new case uses a tool with no source prerequisite, so disabled compilation can only come from the token, and it records the environment each fake Cargo call and the prerequisite recipe actually saw: binstall's release discovery sees the sentinel token, while the prerequisite and the source install see none. Reverting the condition makes it fail. Also correct the security note: `anvil-run-group` has always exported the token to group commands, so setup is not its only exposure. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Answering the second suppressed finding from the latest review, on You are right and the sentence I wrote was wrong. It said the built-in token is exposed to the GitHub setup steps only, but Rewritten in 2f501ee to name both surfaces, and to keep the guarantee attached to the path it actually covers: on the installation path the token is removed before any source install and binstall's compile strategy is disabled while it is set, so no third-party build runs with the credential in scope. |
There was a problem hiding this comment.
🔵 Needs a closer look
Broad CI, installer, generated-artifact, and Windows behavior changes include an unresolved moderate contract-coverage gap and require human review.
Review details
Suppressed comments (2)
crates/cargo-anvil/templates/github/setup-action.yml:132
- The separate
Install justbootstrap now has its own token-present binstall-to-cargo installfallback, but the new GitHub artifact test only checks that the token is present; the token contract test exercises_install-tool-core, not this shell step. A regression removing this cleanup would leave tests green while the source build receives the credential, so add a focused contract or harness that records the environment for both calls.
Remove-Item Env:GITHUB_TOKEN -ErrorAction SilentlyContinue
crates/cargo-anvil/templates/justfiles/anvil/tools.just:478
- This new condition changes the documented installer contract: when
GITHUB_TOKENis present, even tools without source prerequisites no longer retain binstall's compile strategy. However,crates/cargo-anvil/docs/design/local.md:301-306still says those tools retain it unconditionally, while that document also says local and cloud invocations have the same behavior; please qualify the documented no-token case.
if ($sourcePrereq -or $releaseToken) {
- Files reviewed: 23/24 changed files
- Comments generated: 0 new
- Review effort level: Lite
The token case pushed `install_tool_controls_source_fallback_and_prerequisite_ordering` to 151 lines, past the repository's `clippy::too-many-lines` threshold, which failed the Fast Checks group. Split the token isolation into its own test behind a shared fixture rather than silencing the lint; the two tests now describe two separate contracts. Pin the Just bootstrap's token guards in the generated-artifact test. That step is a shell step rather than a Just recipe, so the installer contract tests never reach it, and a regression removing its cleanup would have left every behavioral test green. The assertions check that binstall cannot compile there and that the token is dropped after release discovery but before the source fallback. Correct the installer contract in the local design doc: tools without a source prerequisite retain binstall's compile strategy only when no token is present, which is the local case but not the GitHub one. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Both suppressed findings from the latest review are addressed in a6f3967, along with a Clippy failure I caused myself. The
Separately, my own regression. Adding the token case pushed the installer contract test to 151 lines, past this repository's |
There was a problem hiding this comment.
🔵 Needs a closer look
Add recipe-specific error handling for malformed Cargo metadata in the doctest recipe.
Review details
Suppressed comments (1)
crates/cargo-anvil/templates/justfiles/anvil/checks/doc-test.just:27
- This parse is not wrapped with the recipe-specific diagnostic used by the sibling metadata consumers (for example,
checks/examples.just:39-43). If Cargo returns malformed JSON while exiting successfully, the globalStoppreference makes PowerShell surface its rawConvertFrom-Jsonerror, so the new hard-error path does not identify thatanvil-doc-testfailed to parse Cargo metadata. Wrap this assignment intry/catch, emitanvil-doc-test: could not parse cargo metadata output: ..., and exit nonzero.
$metadata = $metadataJson | ConvertFrom-Json
- Files reviewed: 24/25 changed files
- Comments generated: 0 new
- Review effort level: Lite
The doctest recipe read Cargo's metadata without the recipe-specific guard its siblings use. With `$ErrorActionPreference = 'Stop'`, malformed JSON from a successful Cargo run surfaced PowerShell's own ConvertFrom-Json error, which never names the recipe that failed to parse it. Wrap the parse the way examples, semver-check, external-types and bolero already do, and identify the metadata command's own failure while there. Assert the diagnostic in the shared metadata-failure contract rather than only asserting that the recipe failed. All three recipes it covers now emit `<recipe>: could not parse cargo metadata output`, so a future recipe added without one is caught. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Taking the suppressed finding on Every sibling metadata consumer wraps the parse and names itself: Rather than just fixing the one recipe, I strengthened the shared contract: For the record on the previous head: |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical, moderate, and nit findings remain.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (3)
crates/cargo-anvil/docs/design/README.md:399
- The global security description says the token reaches only two generated surfaces, but this change also exports it in
.github/actions/anvil-impact/action.yml:36-40so the cargo-delta binstall step can use authenticated release discovery. Please include that impact-installation surface here; otherwise the documented token boundary omits one of the newly changed paths.
- The built-in `GITHUB_TOKEN` reaches two generated surfaces. The run-group action
has long exported it so checks that call GitHub's API get the authenticated
quota, and the setup steps now receive it so `cargo-binstall` can discover
releases as an authenticated caller instead of hitting anonymous rate limits.
crates/cargo-anvil/templates/justfiles/anvil/checks/doc-test.just:25
- This metadata probe is not locked, although both doctest invocations below are explicitly
--locked. On a workspace with a missing or stale lockfile,cargo metadatacan resolve and updateCargo.lockbefore the test, so the recipe can repair the lockfile and bypass the lockfile validation that the check is meant to enforce. Pass--lockedto this metadata command as well so package classification uses the same read-only lock contract.
$metadataJson = & cargo {{_anvil_stable_toolchain_args}} metadata --no-deps --format-version 1
justfiles/anvil/checks/doc-test.just:24
- This new metadata-filtering path makes the cargo-each design contract stale:
crates/cargo-each/docs/design/README.md:306-308explicitly listsdoc-testamong recipes that become a singlecargo each … --onceline, while the new recipe now callscargo metadataand classifies targets. Please update that design documentation (or revise the claim) in the same change so the documented Anvil integration matches the implementation.
# Explicitly selecting a binary-only package makes cargo test --doc fail.
if ($pkg -notcontains '--workspace') {
- Files reviewed: 24/25 changed files
- Comments generated: 1
- Review effort level: Lite
| # release miss. | ||
| $binstallArgs = @('binstall', '--no-confirm', '--locked') | ||
| if ($sourcePrereq) { | ||
| if ($sourcePrereq -or $releaseToken) { |
There was a problem hiding this comment.
🤖 Clawpilot here! Posted automatically by Clawpilot (an AI agent), not by a human. Please verify before acting.
Correct, and worth stating plainly: the old assertion was passing for the wrong reason. tools.just contains a second, unrelated if ($sourcePrereq) block further down — the one that runs the prerequisite recipe before the source install — so the contains check kept matching even though the guard it claimed to describe had become if ($sourcePrereq -or $releaseToken).
Fixed in #174, where this work has been re-landed on current main. The assertion now pins the guard together with the body it controls:
TOOLS_JUST.contains(concat!(
"if ($sourcePrereq -or $releaseToken) {\n",
" $binstallArgs += @('--disable-strategies', 'compile')\n",
" }"
))Verified the way it should have been the first time: I weakened the guard back to if ($sourcePrereq), confirmed the new assertion fails, and restored it.
| // An explicit child PATH makes Windows search it before this executable's | ||
| // directory, even when the value is unchanged. Otherwise an adjacent | ||
| // cargo/rustup proxy can shadow the toolchain proxy selected by the caller. | ||
| #[cfg(windows)] |
There was a problem hiding this comment.
This is a duplicate of changes made in this PR: #153
There was a problem hiding this comment.
🤖 Clawpilot here! Posted automatically by Clawpilot (an AI agent), not by a human. Please verify before acting.
You are right, and thank you — I checked rather than taking it on faith, and #153 merged 16 minutes before you commented. origin/main now carries exactly this in execute():
let mut command = Command::new(program);
if let Some(path) = std::env::var_os("PATH") {
command.env("PATH", path);
}That is the whole of what this PR's title promises, so the headline change here is redundant.
It is worse than redundant, in fact. This branch is based on the pre-#153 main, so as it stands its diff against current main removes 1207 lines under crates/cargo-each — your target-aware selection, filter expressions and per-target execution included. Merging it as-is would revert #153, which is presumably why the PR has just gone to DIRTY. So this needs restructuring, not a routine rebase.
What is still unique here is the Anvil CI work that got pulled in along the way: the scoped doctest recipe no longer passes binary-only packages to cargo test --doc, tool installation authenticates its release discovery while keeping the token out of source builds, and three cargo-gamma-lib doctests that only ever compiled under --all-features are gated. None of that is in #153.
I have deliberately not rebased or force-pushed, since choosing between "drop the cargo-each changes and keep the Anvil repairs" and "close this and re-land the Anvil work separately" is my author's call, not mine. I have flagged it to them. Sorry for the duplicated effort on your side.
There was a problem hiding this comment.
🤖 Clawpilot here! Posted automatically by Clawpilot (an AI agent), not by a human. Please verify before acting.
Resolved by dropping this change entirely rather than rebasing it.
I checked what was actually left that main does not already have. The PATH forwarding is yours, in main, and so is a regression test for it — relative_child_program_uses_path_before_cargo_each_directory, which compiles two real probes and asserts the adjacent one is not the one that runs. Nothing here improved on that, so there was nothing to keep.
What was unique was the Anvil CI work that got pulled in along the way, and that has been re-landed as #174 on top of current main, with everything under crates/cargo-each dropped. This PR is superseded; no rebase of it will happen. Thanks again for catching it early — it would have been a quiet revert of #153 otherwise.
|
Superseded by #174. martin-kolinek was right: #153 landed the #174 is the remaining unique half — the Anvil CI repairs — rebuilt from scratch on top of current Both open threads here are carried over and answered inline. This PR can be closed in favour of #174. |
🤖 Clawpilot here! Posted automatically by Clawpilot (an AI agent), not by a human. Please verify before acting.
What this changes
cargo-eachexplicitly forwards the inheritedPATHto child commands on Windows. This prevents adjacent executables from shadowing commands selected throughPATH.Effects
PATHbefore the directory containingcargo-each.+toolchainarguments. No dependencies are added.Also in this PR: the CI repairs needed to land it
The
cargo-eachfix could not be validated on its own, because the branch hit three separate failures in the shared Anvil CI path. They are fixed here rather than split out, since splitting leaves this PR permanently red.Scoped doctests skipped no packages.
anvil-doc-testpassed its affected--packageselection straight tocargo test --doc, so a binary-only package in that set failed the run — which is exactly what happened tocargo-eachitself, across four platforms. The recipe now filters the selection to packages with a library target, keeping every library kind including proc-macro, keeping version-qualified specs, and keeping both the all-feature and default-feature runs. An all-binary selection now skips visibly; unknown packages and metadata failures stay hard errors.Tool installation was unauthenticated. The Linux ARM fast-checks job hit anonymous GitHub release-API 403s and fell back to a slow source build that then failed on a missing system dependency. The GitHub setup steps and the impact action's
cargo-deltainstall now pass the built-inGITHUB_TOKENso release discovery is authenticated. The credential is kept out of third-party builds: it is removed from the environment before any source install, and binstall's compile strategy is disabled whenever it is set, so a release miss falls through to a tokenlesscargo install. Token scopes remain the caller's decision, which is where this design puts permissions.Three
cargo-gamma-libdoctests only ever compiled with--all-features. They importcargo_gamma_lib::internals, which is gated behind the feature that exposes it, so the recipe's default-features pass could not compile them. This was pre-existing and simply unreachable while the recipe was dying earlier on binary-only packages; fixing the recipe surfaced it. The doctest bodies are now gated on that feature, and still compile and assert for real under--all-features.Generated files,
.anvil.lockand the emitted-tree snapshots are regenerated to match.