Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2a04d00
Add ambient filesystem boundary crates for lint compliance
Jul 8, 2026
5d5ca80
Fix Whitaker Dylint findings across production and test code
Jul 8, 2026
9783099
Adopt the Whitaker Dylint suite in the lint gate and CI
Jul 8, 2026
46a6d2e
Deduplicate network policy and config precedence tests
Jul 8, 2026
32daa28
Harden the Whitaker install step
Jul 8, 2026
18a269b
Gate ambient_fs as a workspace member
Jul 8, 2026
b044d98
Deduplicate the command test config helper
Jul 8, 2026
3f6f1ac
Localize from_current_dir errors and simplify config fixtures
Jul 8, 2026
2d5da1b
Tidy file I/O and hash test diagnostics
Jul 8, 2026
6d4b9db
Fix developer guide module reference and comment spelling
Jul 8, 2026
34b29ad
Widen arb_path proptest strategy to reduce collisions
Jul 8, 2026
80d5852
Guard canonicalize_cycle_by against undersized cycles
Jul 8, 2026
cc4b76a
Close a TOCTOU window in the fetch cache size check
Jul 8, 2026
274a7bf
Explain the early cwd_guard drop in config override tests
Jul 8, 2026
790cd93
Add ambient_fs unit tests for the public probes
Jul 8, 2026
4e756cc
Share a tempdir fixture across the ambient_fs probe tests
Jul 8, 2026
e48c98f
Give the ambient_fs canonicalize and sync tests real oracles
Jul 9, 2026
fb19e90
Satisfy Whitaker lints in new review-response code
Jul 9, 2026
c2bb00e
Make define_newtype accessors opt-in to remove dead-code suppressions
Jul 9, 2026
0325590
Add structured tracing across the fetch cache and workspace open paths
Jul 9, 2026
9122604
Cap the cache read, not just the fstat size check
Jul 9, 2026
12a44a2
Separate ambient_fs probe commands from their assertions
Jul 9, 2026
3d9fe15
Distinguish missing manifest file name from non-UTF-8 paths
Jul 9, 2026
2521921
Log network request failures and guard the seconds invariant
Jul 9, 2026
559913f
Tidy test helpers, fixtures, and cleanup ordering
Jul 9, 2026
4d951a0
Name test_support in the no_std_fs_operations exclusion note
Jul 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ updates:
- package-ecosystem: "cargo"
directories:
- "/"
- "/ambient_fs"
- "/test_support"
open-pull-requests-limit: 5
labels:
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
BUILD_PROFILE: debug
# Override rust-toolchain.toml to actually use the matrix toolchain
RUSTUP_TOOLCHAIN: ${{ matrix.rust }}
WHITAKER_INSTALLER_VERSION: '0.2.5'
steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
- name: Setup Rust
Expand All @@ -42,8 +43,34 @@ jobs:
run: ninja --version
- name: Format
run: make check-fmt
- name: Cache Whitaker installer
if: matrix.rust == 'stable'
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.cargo/bin/whitaker-installer
~/.cache/cargo-binstall
key: whitaker-installer-${{ runner.os }}-${{ runner.arch }}-${{ env.WHITAKER_INSTALLER_VERSION }}
- name: Install Whitaker
if: matrix.rust == 'stable'
run: |
if ! command -v whitaker-installer >/dev/null 2>&1; then
if cargo binstall --version >/dev/null 2>&1; then
cargo binstall --no-confirm --locked "whitaker-installer@${WHITAKER_INSTALLER_VERSION}"
else
echo "cargo-binstall unavailable; building whitaker-installer from crates.io"
cargo install --locked whitaker-installer --version "${WHITAKER_INSTALLER_VERSION}"
fi
fi
whitaker-installer
Comment on lines +46 to +65

@coderabbitai coderabbitai Bot Jul 8, 2026

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.

🚀 Performance & Scalability | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect whitaker-installer's install layout to find cacheable paths.
fd -HI 'whitaker' -t f
grep -RIn "local/bin" Makefile

Repository: leynos/netsuke

Length of output: 262


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## ci workflow excerpt\n'
sed -n '1,140p' .github/workflows/ci.yml

printf '\n## Makefile excerpt\n'
sed -n '1,140p' Makefile

printf '\n## Whitaker docs and references\n'
rg -n "whitaker-installer|whitaker|local/bin|cargo-binstall|WHITAKER_INSTALLER_VERSION" -S .

Repository: leynos/netsuke

Length of output: 12366


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## docs/whitaker-users-guide.md (relevant section)\n'
sed -n '40,70p' docs/whitaker-users-guide.md

printf '\n## AGENTS.md Whitaker guidance\n'
sed -n '148,170p' AGENTS.md

printf '\n## any install/output-path mentions\n'
rg -n "DYLINT_LIBRARY_PATH|whitaker-ls|Creates `whitaker`|~/.local/bin|~/.cargo/bin|whitaker-installer --experimental|whitaker-installer" docs AGENTS.md Makefile .github -S

Repository: leynos/netsuke

Length of output: 4919


🌐 Web query:

whitaker-installer install output location DYLINT_LIBRARY_PATH ~/.local/bin cache installer

💡 Result:

The whitaker-installer is a tool used to install, stage, and manage Dylint lint libraries [1][2][3]. Install Location and Staging: The installer manages the build and staging of lint libraries. It generates wrapper scripts (e.g., whitaker, whitaker-ls) to simplify the interaction with Dylint [1][2]. The installer is designed to stage these libraries in a designated directory. After installation, you are instructed to set the DYLINT_LIBRARY_PATH environment variable to this staged directory so that cargo dylint can locate and load the installed libraries [1][2]. DYLINT_LIBRARY_PATH: Dylint uses the DYLINT_LIBRARY_PATH environment variable to discover dynamic libraries containing lints [4][5]. When this variable is set, Dylint treats it as a colon-separated list of paths and searches them for files matching its required naming format [4][5]. The whitaker-installer effectively automates the management of this path by creating wrappers that handle the path configuration for you [1][2]. Regarding ~/.local/bin: While ~/.local/bin is a common location for user-installed binaries (like the wrapper scripts generated by the installer), the DYLINT_LIBRARY_PATH should point to the directory where the actual lint libraries (compiled dynamic library files) are staged, not necessarily where the binary scripts reside [1][4]. In summary, you should use the path provided by the whitaker-installer (or its generated shell configuration snippets) for DYLINT_LIBRARY_PATH, ensuring it points to the location of the staged lint artifacts [1][2].

Citations:


🌐 Web query:

whitaker-installer docs output directory wrapper scripts DYLINT_LIBRARY_PATH install location cacheable artefacts

💡 Result:

The whitaker-installer is a tool designed to simplify the installation and management of Dylint lint libraries by automating the building, linking, and staging of these libraries [1][2]. Wrapper Scripts The installer generates two primary wrapper scripts to simplify usage [3][4]: - whitaker: This script automatically invokes cargo dylint and sets the necessary DYLINT_LIBRARY_PATH to the directory where the Whitaker lint libraries have been staged [3][1][5]. - whitaker-ls: This script lists the installed Whitaker suite libraries available at the staged path [3][5]. DYLINT_LIBRARY_PATH and Install Location The DYLINT_LIBRARY_PATH environment variable is used by Dylint to locate lint libraries [6][7]. When using the whitaker-installer, it clones the Whitaker repository to a platform-specific data directory, builds the libraries, and stages them [1]. The installer configures this staged directory as the DYLINT_LIBRARY_PATH [3][4]. Users can bypass the automatic generation of these wrappers by using the --skip-wrapper flag, which instead prints the required DYLINT_LIBRARY_PATH configuration instructions [1]. Cacheable Artefacts The whitaker-installer manages the build and staging pipeline, which includes the handling of prebuilt artefacts [2]. While the installer orchestrates the download, verification, and staging of these artefacts, it relies on Dylint's underlying mechanics—such as workspace metadata or path-based resolution—to manage how those libraries are eventually consumed by the Dylint tool [6][8][9]. The installer's internal architecture includes modules for prebuilt artefact orchestration and canonical destination path resolution to ensure consistency across environments [2].

Citations:


🌐 Web query:

docs.rs whitaker-installer default install paths staged libraries wrapper scripts ~/.local/bin platform-specific data directory

💡 Result:

The whitaker-installer crate is a tool designed to build, link, and stage Dylint lint libraries for local use in Rust projects [1][2]. According to the documentation on docs.rs, the installer handles various system-level tasks, including directory resolution and wrapper script generation [3][4]. While the exact absolute file paths are managed dynamically by the installer's internal logic, the following details are confirmed by the crate's technical design: - Staged Libraries: The installer manages the build and staging of lint libraries to a centralized directory to avoid redundant rebuilds during cargo dylint invocations [1][2]. The crate includes specific modules for file staging (stager) and platform-specific naming conventions [3][4]. - Wrapper Scripts: The installer automatically generates wrapper scripts to simplify the invocation of Dylint with the staged libraries [3][4]. Notably, it provides the whitaker command, which runs cargo dylint with the correct library path, and whitaker-ls to list installed libraries [1]. - Platform-Specific Paths: The installer utilizes an internal dirs module specifically for directory resolution and abstraction of platform-specific paths [3][4]. This ensures that data directories and binary locations conform to standard platform conventions, rather than being hardcoded to a single location like ~/.local/bin across all systems [3][4]. Users are generally instructed to set the DYLINT_LIBRARY_PATH environment variable to the directory containing the staged libraries after the installation process completes [1][2]. For further details on specific path configuration or architecture, the project's User's Guide and Design Document are available in the main GitHub repository [5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## Whitaker user guide path mentions\n'
rg -n "data directory|wrapper scripts|DYLINT_LIBRARY_PATH|~/.local/bin|~/.cargo/bin|whitaker-ls|whitaker-installer" docs/whitaker-users-guide.md -n -A3 -B3

printf '\n## Full install section around the numbered steps\n'
sed -n '1,90p' docs/whitaker-users-guide.md

Repository: leynos/netsuke

Length of output: 173


Cache Whitaker’s staged artefacts too. Cache the generated whitaker/whitaker-ls wrappers and staged libraries, not just whitaker-installer and cargo-binstall, so the stable job does not redo the Whitaker setup on every run.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 46 - 65, The Whitaker cache currently
only preserves the installer and cargo-binstall state, so the stable job still
recreates the staged wrappers and libraries each run. Update the workflow job
around Cache Whitaker installer and Install Whitaker to also cache the generated
whitaker and whitaker-ls wrappers plus the staged library artefacts produced by
whitaker-installer, using a cache key that still tracks
WHITAKER_INSTALLER_VERSION so stable runs can reuse the full setup.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@coderabbitai Has this now been resolved in the latest commit?

Use codegraph analysis to determine your answer.

If this comment is now resolved, please mark it as such using the API. Otherwise, please provide an AI agent prompt for the remaining work to be done to address this 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.

@leynos, checked the current state of .github/workflows/ci.yml against this comment. The "Cache Whitaker installer" step (Lines 46–53) still only caches ~/.cargo/bin/whitaker-installer and ~/.cache/cargo-binstall. There is no path for the staged Whitaker libraries or the generated whitaker/whitaker-ls wrapper scripts. This finding remains unresolved — the stable leg still rebuilds and stages the Whitaker artefacts on every run, even when the installer binary itself is cached.

I won't mark this as resolved. Here's the agent prompt for the remaining work:

In .github/workflows/ci.yml around lines 46-65, the "Cache Whitaker installer"
step only caches ~/.cargo/bin/whitaker-installer and ~/.cache/cargo-binstall.
Extend the cache `path:` list to also include the directory where
whitaker-installer stages its built libraries and generates the `whitaker`
and `whitaker-ls` wrapper scripts (consult the whitaker-installer/Whitaker
documentation or run `whitaker-installer --skip-wrapper` output locally to
determine the exact staged-artefact and wrapper-script directories for the
runner's platform, since these are resolved via the crate's internal `dirs`
module rather than being fixed paths). Keep the cache key tied to
WHITAKER_INSTALLER_VERSION (and runner.os/runner.arch) so a version bump still
invalidates stale caches. Verify after the change that a warm cache hit skips
the rebuild/staging step entirely on the stable matrix leg.

🧠 Learnings used
Learnt from: leynos
Repo: leynos/netsuke PR: 253
File: .github/workflows/build-and-package.yml:82-82
Timestamp: 2026-01-03T20:51:29.799Z
Learning: In GitHub Actions workflows, the uses: value must be a static string (no runtime interpolation). Do not use expressions like ${{ env.VARIABLE }} or ${{ vars.VARIABLE }} inside uses:. This ensures deterministic action references and supports policy enforcement. If you need to parameterize actions, use inputs or job-level variables, not dynamic action references.

- name: Lint
if: matrix.rust == 'stable'
run: make lint
# Whitaker lints under its own pinned toolchain, so re-running it per
# matrix leg repeats identical work; non-stable legs run Clippy only.
- name: Lint (Clippy only)
if: matrix.rust != 'stable'
run: make lint-clippy
- name: Setup uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39
with:
Expand Down
11 changes: 8 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,16 @@ project:
- `make lint` executes:

```sh
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo doc --no-deps
cargo clippy --all-targets --all-features -- -D warnings
whitaker --all -- --all-targets --all-features
```

linting every target with all features enabled and denying all Clippy
warnings.
linting every target with all features enabled, denying all Clippy
warnings, and running the Whitaker Dylint suite (see
`docs/whitaker-users-guide.md`; install via `cargo install
whitaker-installer && whitaker-installer`). `make lint-clippy` runs the
Clippy-only subset when Whitaker is unavailable.
- `make test` executes:

```sh
Expand Down
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ tracing-subscriber = { version = "0.3", features = ["fmt"] }
serde_json = { version = "1", features = ["preserve_order"] }
serde_json_canonicalizer = "0.3"
tempfile = "3.8.0"
ambient_fs = { path = "ambient_fs" }
Comment thread
coderabbitai[bot] marked this conversation as resolved.
shell-quote = { version = "0.7.2", default-features = false, features = ["sh"] }
shlex = "1.3.0"
time = { version = "0.3.44", features = ["formatting", "macros", "parsing", "serde"] }
Expand Down Expand Up @@ -145,7 +146,7 @@ result_large_err = "deny"
unknown_lints = "deny"
renamed_and_removed_lints = "deny"
missing_docs = "deny"
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(kani)"] }
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(kani)", "cfg(dylint_lib, values(any()))"] }

[lints.rustdoc]
missing_crate_level_docs = "deny"
Expand Down Expand Up @@ -179,3 +180,19 @@ trybuild = "1.0.116"
[target.'cfg(unix)'.dev-dependencies]
# Used only to construct FIFOs and device nodes in tests.
rustix = { version = "1.0.8", features = ["fs"] }

[workspace]
# `ambient_fs` is the sanctioned ambient-filesystem escape hatch, so it must be a
# workspace member for the root-level `cargo fmt`, `cargo doc`, `cargo clippy`, and
# `cargo test` gates to format, document, lint, and run its doctests and unit tests.
members = ["ambient_fs"]
# Operate on both packages by default so the bare-cargo gates (`cargo test`,
# `cargo check`, `cargo clippy`, `cargo doc`) cover `ambient_fs` without needing
# `--workspace`; the root package (netsuke, ".") is listed explicitly because a
# default set that omitted it would stop gating netsuke itself.
default-members = [".", "ambient_fs"]
# `test_support` is a path dependency that Cargo would otherwise auto-include as a
# member. It is excluded here to keep its gate coverage unchanged in this focused
# change; folding it into the workspace is tracked separately as it requires
# clearing its own lint backlog.
exclude = ["test_support"]
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help all clean test test-workflow-contracts test-typos-config build release lint fmt check-fmt typecheck markdownlint nixie install-kani kani-check kani-full kani-ir install-verus verus formal-pr
.PHONY: help all clean test test-workflow-contracts test-typos-config build release lint lint-clippy lint-whitaker fmt check-fmt typecheck markdownlint nixie install-kani kani-check kani-full kani-ir install-verus verus formal-pr

APP ?= netsuke
CARGO ?= $(shell command -v cargo 2>/dev/null || printf '%s' "$$HOME/.cargo/bin/cargo")
Expand Down Expand Up @@ -26,8 +26,9 @@ PROVER_TOOLS ?= uv tool run --from $(PROVER_TOOLS_SOURCE) prover-tools
RUSTDOC_FLAGS ?= --cfg docsrs -D warnings
VERUS_FLAGS ?=
VERUS_INSTALL_FLAGS ?=
WHITAKER ?= whitaker

export PATH := $(HOME)/.cargo/bin:$(HOME)/.bun/bin:$(PATH)
export PATH := $(HOME)/.cargo/bin:$(HOME)/.local/bin:$(HOME)/.bun/bin:$(PATH)

build: target/debug/$(APP) ## Build debug binary
release: target/release/$(APP) ## Build release binary
Expand All @@ -49,10 +50,15 @@ test-typos-config: ## Verify typos.toml matches its generator
target/%/$(APP): ## Build binary in debug or release mode
$(CARGO) build $(BUILD_JOBS) $(if $(findstring release,$(@)),--release) --bin $(APP)

lint: ## Run Clippy with warnings denied
lint: lint-clippy lint-whitaker ## Run Clippy and the Whitaker Dylint suite with warnings denied

lint-clippy: ## Run rustdoc and Clippy with warnings denied
RUSTDOCFLAGS="$(RUSTDOC_FLAGS)" $(CARGO) doc --no-deps
$(CARGO) clippy $(CLIPPY_FLAGS)

lint-whitaker: ## Run the Whitaker Dylint suite with warnings denied
RUSTFLAGS="-D warnings" $(WHITAKER) --all -- --all-targets --all-features

fmt: ## Format Rust and Markdown sources
$(CARGO) fmt --all
mdformat-all
Expand Down
54 changes: 54 additions & 0 deletions ambient_fs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[package]
name = "ambient_fs"
version = "0.1.0"
edition = "2024"
rust-version = "1.89.0"
publish = false

[dependencies]
camino = "1.2.0"
walkdir = "2.5"

[dev-dependencies]
rstest = "0.26.1"
tempfile = "3.8.0"

[lints.clippy]
pedantic = { level = "warn", priority = -1 }

# 1. hygiene
# Unfortunately, due to an 'unused-braces' false positive with
# single line rstest fixtures, and the fact that fixtures do
# not permit 'expect' attributes, we must disable this deny.
# allow_attributes = "deny"
allow_attributes_without_reason = "deny"
blanket_clippy_restriction_lints = "deny"

# 2. debugging leftovers
# Disabled pending further investigation into applicability.
# dbg_macro = "deny"
# print_stdout = "deny"
# print_stderr = "deny"

# 3. panic-prone operations
unwrap_used = "deny"
# Expect used in tests. Discouraged in implementation code.
# expect_used = "deny"
indexing_slicing = "deny"
string_slice = "deny"
integer_division = "deny"
integer_division_remainder_used = "deny"

# 4. portability
host_endian_bytes = "deny"
little_endian_bytes = "deny"
big_endian_bytes = "deny"

# 5. nursery idiom polish
or_fun_call = "deny"
option_if_let_else = "deny"
use_self = "deny"
string_lit_as_bytes = "deny"

# 6. numerical foot-guns
float_arithmetic = "deny"
Loading
Loading