diff --git a/AGENTS.md b/AGENTS.md index 536a75e5..97487bac 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -71,8 +71,11 @@ covers how to route by job. What is specific to Underlay: does not ship `check:agent-instructions`. - Fall back to raw `oxide`, `bun`, or `vitest` only when the needed operation is not represented in `effigy.toml`. Rust goes through `oxide` (Cargo with - managed build storage), not `cargo`; `rust:check:cargo`, `rust:clippy:cargo` - and `rust:test:cargo` are the plain-Cargo fallback if `oxide` misbehaves. + managed build storage), never plain `cargo`; a tool that runs Cargo itself or + needs its own target directory runs `oxide exec -- `. No selector keeps + a plain-Cargo `:cargo` sibling. The only escape is an operator decision — + `EFFIGY_OXIDE_ESCAPE=cargo` on a routed surface that honours it, or Cargo by + hand outside Effigy — never a silent fallback. - First-time local bring-up from outside this repo: `effigy bootstrap git@github.com:inflatable-cookie/underlay.git` @@ -90,6 +93,7 @@ effigy fmt:rust:check # oxide fmt --all --check; read-only effigy fmt:rust # oxide fmt --all; mutates the workspace effigy fmt:ts -- ts/src/client/format.ts # format the named TypeScript files effigy fmt:ts:check -- ts/src/client/format.ts # read-only formatting check +effigy check:coverage-route # fake-tool proof of the coverage wrapper's Oxide route effigy test:unit # vitest, filter {args} to the touched code effigy test:components # vitest component config effigy test --plan # when the test shape is what you need to know @@ -108,6 +112,19 @@ These selectors do not include Svelte formatting or run automatically in QA. `underlay-db` Postgres integration tests need a running Docker runtime and are `#[ignore]`d by default; see `README.md` for the bring-up. +## Scratch Placement + +- Agent and proof scratch goes in a unique directory below + `/Volumes/Builds/scratch/underlay/`. If the volume is not mounted, refuse and + report it; never fall back to `$TMPDIR`, `$HOME`, a drive root, or the + checkout, and never create a mount point that pretends to be the volume. +- Delete only scratch your own run created; leave unknown state where it is. +- Proof output records key presence, never secret values, and no generic `HOME` + override substitutes for the scratch rule. +- Product-managed temp files are not agent scratch; leave runtime behaviour and + guest `/tmp` files alone. +- Owner: `docs/knowledge/contracts/123-local-rust-routing-and-scratch-placement.md`. + ## Documentation Rules - Consumer-facing product docs live in `docs/guides/`, `docs/usage/`, diff --git a/README.md b/README.md index 5387d342..e3f0078e 100644 --- a/README.md +++ b/README.md @@ -104,4 +104,7 @@ Some `underlay-db` tests spin up Postgres via `testcontainers`. ### Coverage - Install tarpaulin: `oxide install cargo-tarpaulin` -- Run coverage check: `rust/scripts/check-coverage.sh` +- Run coverage check: `rust/scripts/check-coverage.sh`, which launches the tool + through `oxide exec -- cargo tarpaulin --workspace --out Xml` +- Prove the wrapper's dispatch, output and exit behaviour without running + Tarpaulin: `effigy check:coverage-route` diff --git a/docs/guides/041-rust-module-splitting.md b/docs/guides/041-rust-module-splitting.md index b9167cbe..9134f72c 100644 --- a/docs/guides/041-rust-module-splitting.md +++ b/docs/guides/041-rust-module-splitting.md @@ -92,8 +92,8 @@ pub use crate::postgres_scheduled::Notifier; 2. Create the new file with the extracted code. 3. Replace the inline code with a module reference or import. 4. Update `lib.rs` with `mod` declarations and re-exports. -5. `cargo check -p --all-features` — fix compile errors. -6. `cargo test -p --all-features` — verify all tests pass. +5. `oxide check -p --all-features` — fix compile errors. +6. `oxide test -p --all-features` — verify all tests pass. 7. Commit as a single change for easy revert. ## Reference diff --git a/docs/knowledge/README.md b/docs/knowledge/README.md index 15eaa7f6..fc00ad6f 100644 --- a/docs/knowledge/README.md +++ b/docs/knowledge/README.md @@ -10,6 +10,7 @@ Every topic has exactly one owning file. Link to it; don't restate it. | Public Rust API stability | [contracts/122-rust-public-api-inventory.md](contracts/122-rust-public-api-inventory.md) | | Compatibility and consumer rollout | [contracts/023-release-and-compatibility-rollout.md](contracts/023-release-and-compatibility-rollout.md) | | How we release | [contracts/release.md](contracts/release.md) | +| Local Rust routing and agent/proof scratch | [contracts/123-local-rust-routing-and-scratch-placement.md](contracts/123-local-rust-routing-and-scratch-placement.md) | | Writing style | [contracts/writing-style.md](contracts/writing-style.md) | | Retired concepts | [retired.toml](retired.toml) | | Open questions | [questions.md](questions.md) | diff --git a/docs/knowledge/contracts/022-testing-posture-and-shared-harnesses.md b/docs/knowledge/contracts/022-testing-posture-and-shared-harnesses.md index ebb29b1c..41a00d47 100644 --- a/docs/knowledge/contracts/022-testing-posture-and-shared-harnesses.md +++ b/docs/knowledge/contracts/022-testing-posture-and-shared-harnesses.md @@ -101,10 +101,13 @@ Rules: ### Coverage tooling Install Tarpaulin with `oxide install cargo-tarpaulin`. The coverage script -still checks for `cargo-tarpaulin` and runs -`cargo tarpaulin --workspace --out Xml`; Tarpaulin's instrumentation, profile, -and platform behavior is not qualified through Oxide, so its execution remains -a Cargo exception. +still requires `cargo-tarpaulin` and runs the tool as +`oxide exec -- cargo tarpaulin --workspace --out Xml`: Tarpaulin invokes Cargo +itself, so its inner `cargo` word belongs to the tool, and the `oxide exec` +lease is routing only. Arguments, thresholds and exit behaviour stay in +`rust/scripts/check-coverage.sh`. Routing does not qualify Tarpaulin's +instrumentation, profile or platform behaviour. See +[`123-local-rust-routing-and-scratch-placement.md`](123-local-rust-routing-and-scratch-placement.md). ### Underlay repository TypeScript formatting diff --git a/docs/knowledge/contracts/123-local-rust-routing-and-scratch-placement.md b/docs/knowledge/contracts/123-local-rust-routing-and-scratch-placement.md new file mode 100644 index 00000000..c779d15c --- /dev/null +++ b/docs/knowledge/contracts/123-local-rust-routing-and-scratch-placement.md @@ -0,0 +1,129 @@ +# Contract: Local Rust Routing and Scratch Placement + +Status: active +Owner: repo maintainers +Depends on: `022-testing-posture-and-shared-harnesses.md`, `120-tooling-testing-and-contract-artifacts.md` + +## Purpose + +Durable rules for two local-host facts about this checkout: + +- which command runs Rust for ordinary local work +- where agent and proof scratch lives + +Operator ruling: Tom, 2026-10-25, relayed by Oxide Supervisor. It supersedes the +earlier postponed exceptions and the pre-formal-v0.15 retention of `:cargo` +escape tasks. It does not retroactively qualify earlier recorded results and it +does not authorise replays of them. + +This contract covers this repository. Consumer apps keep their own manifests and +their own commands; nothing here asks a consumer to install, adopt or rewrite +anything. + +## Sources of Truth + +- [`effigy.toml`](../../../effigy.toml) — the effective local route catalogue +- [`rust/scripts/check-coverage.sh`](../../../rust/scripts/check-coverage.sh) — + external tool routed through `oxide exec` +- [`rust/scripts/test-check-coverage.sh`](../../../rust/scripts/test-check-coverage.sh) + — fake-tool proof of that route +- [`scripts/test-consumer-conformance-fixtures.sh`](../../../scripts/test-consumer-conformance-fixtures.sh) + and [`scripts/auth-webauthn-manual-dossier.sh`](../../../scripts/auth-webauthn-manual-dossier.sh) + — proof scratch placement +- [`AGENTS.md`](../../../AGENTS.md), [`rust/AGENTS.md`](../../../rust/AGENTS.md) + +## Rust routing + +Ordinary local Rust work runs through Oxide. + +- Modeled commands: `oxide check|test|clippy|build|run|fmt`. Effigy selectors + `rust:build`, `rust:check`, `rust:clippy`, `rust:test`, `fmt:rust` and + `fmt:rust:check` spell Oxide directly. +- A tool that runs Cargo itself, or needs its own target directory or + `CARGO_TARGET_DIR`, runs `oxide exec -- …`. The inner `cargo` word + belongs to that tool. Tarpaulin is the current case. +- Oxide owns build storage, so it refuses `--target-dir` and the build-dir + config keys. +- The `oxide init` block in `AGENTS.md` is managed; do not restate it. + +No selector keeps a plain-Cargo `:cargo` sibling. Their removal is the point: +they read as supported local routes and quietly wrote build output into the +checkout's `target/`. + +Escape posture: + +- The only escapes are operator decisions, recorded on the task that uses them. +- `EFFIGY_OXIDE_ESCAPE=cargo` applies to a routed surface that honours it, such + as Effigy's own oxide-selector routes. Underlay's catalog routes spell `oxide` + directly, so they do not read that variable. +- Running Cargo by hand outside Effigy is the manual escape. +- No custom escape wrapper, no silent fallback, no automatic retry on Cargo. A + missing or refusing Oxide fails the run loudly. + +## Remaining Cargo words by class + +The current ordinary local Rust route inventory contains no unexplained Cargo +invocation. Cargo still appears where it is the subject or the host: + +- hosted CI: `.github/workflows/` and CI examples in guides run Cargo, because + hosted runners have no Oxide. +- generic consumer recipes: guide snippets that `cd apps/api` and run a consumer + app's own workspace. These are consumer examples, not this checkout's routes. +- Cargo as subject or metadata: `cargo-tarpaulin` and other `cargo-*` binary + names, dependency and crate names, `[package]`/`[workspace]` manifest schema, + `cargo:` build-script directives, release notes and changelog entries about + Cargo, and workspace-shape checks that read `Cargo.toml`. +- product and fixture behavior: scripts, samples and fixtures whose behavior is + the thing being proved, plus container/VM guests that build inside their own + target directory. +- historical records: release, upgrade and sweep records that quote what a past + run executed, and guides that declare themselves a historical reference for + retired posture (for example `205-legacy-migration-framework.md`). They are + evidence, not live instructions. Recheck trigger: reviving such a guide as a + current route means re-routing its commands through Oxide before it can be + followed again. + +These are classified, not pending migrations. Do not mechanically rewrite them. + +## Scratch placement + +Agent and proof scratch belongs on the Builds volume, never in a home +directory, a drive root, or the checkout. + +- Place scratch in a unique directory below + `/Volumes/Builds/scratch/underlay/`, for example + `mktemp -d /Volumes/Builds/scratch/underlay/