P0 checklist
| Item | Status | Where |
|---|---|---|
cargo compatibility shim; qrust management executable |
done | src/cli.rs, src/session.rs · tests/compat.rs |
| Recursion-safe engine (COMP-021, COMP-022) | done: the toolchain’s own Cargo; a linked toolchain whose cargo is QuickRust is refused |
src/engine.rs · test0268_recursion_is_refused…, test0269_an_unreachable_dist_server… |
Toolchains: +toolchain, RUSTUP_TOOLCHAIN, toolchain files, default (COMP-012, COMP-020) |
done: QuickRust installs and selects toolchains itself (deviation 6) | src/toolchain/ · qa003_*, test0238_toolchain_programs_run_through_quickrusts_proxies, test0237_builds_and_their_build_scripts_get_quickrusts_toolchain…, test0271_environment_reaches_build_scripts_unchanged |
| argv / stdin / stdout / stderr / signal forwarding, exact exit status | done | src/proc.rs · qa022, qa023, test0253_stdin_and_exit_codes… |
| External subcommands, aliases, unknown flags | done | qa019, qa020, qa030 |
| Cargo config / environment non-interference | done | test0271_environment_reaches_build_scripts_unchanged, test0233_no_rebuild_when_alternating… |
| Nested invocations + opt-out | done, through PATH and $CARGO; see deviation 1 |
qa019, test0237_builds_and_their_build_scripts_get_quickrusts_toolchain… |
| Workspace, toolchain, environment fingerprints (FR-010) | done | src/discover.rs · qa002, test0188_report_follows… |
| Cargo JSON-event collector | done, when the user requests JSON on a pipe | qa018 |
| rustc wrapper collector; existing wrapper composition | done | src/wrapper.rs · qa010_qa011_qa012, test0250_wrapper_configured_in_cargo_config… |
| Observed build-unit DAG; critical path (FR-030) | done | src/analyze.rs unit tests |
| Rebuild / invalidation classifier (FR-040) | done | src/waste.rs unit tests · test0189_rebuild_causes…, test0190_toolchain_change… |
| Version duplication; feature/profile/target variants (FR-050) | done | src/waste.rs unit tests |
| Build-script analysis (FR-060); proc-macro identification (FR-070) | done | qa007_qa008_qa009, test0191_build_script_without_rerun… |
| Linker / codegen visibility (FR-080) | done | qrust analyze codegen |
| Incremental policy evaluator (FR-090) | done | test0204_sccache_policy… |
| sccache integration and reporting (FR-100) | done | src/cache.rs · test0204_sccache_policy…, qa026 |
Artifact inventory, reclaimability, GC (FR-110): qrust gc keeps the cache within its bounds, --dry-run previews |
done | src/inventory.rs, src/space.rs · test0194_inventory_and_its_stale_plan_are_read_only…, test0199_the_stale_plan_is_blocked_while_a_build_is_running, test0196_quickrusts_cache_removes_what_is_gone_then_the_least_recently_used… |
Exact upstream cargo clean |
done | qa016 |
| Worktree identification (FR-120) | done | test0203_worktrees_report… |
| Scenario runner (FR-020); comparison (FR-160); experiments | done | src/bench.rs, src/compare.rs · benchmark_*, experiment_* |
| Recommendation engine (FR-150) | done | src/recommend.rs unit tests |
| Safe remediation preview (FR-170) | done; safe class can also be applied and rolled back |
src/remedy.rs |
| JSON sidecar schema | done | report-schema.md |
| CI regression budgets (FR-130) | done | test0193_budgets_gate_ci… |
| Secret / path redaction | done | test0192_secrets_never_reach…, qa021 |
| Cross-platform process abstraction | done; on Windows a smoke run (setup, build, run, test) | src/proc.rs |
| Compatibility corpus QA-001…030 | done except QA-024 (Windows) | tests/compat.rs |
| Performance-overhead test | done | test0273_dispatch_overhead_stays_within_budget |
Migration / uninstall documentation; doctor; escape hatch |
done | How to adopt QuickRust gradually, How to install QuickRust · test0208_doctor_setup_and_uninstall |
Not in this release (P1 and later in the specification)
Controlled GC execution, remote-cache administration and read-only cache mode,
central service and organization policy, PR annotations, container analysis
(FR-140), the plugin protocol (FR-180), nightly --unit-graph /
-Zbuild-analysis / section-timing adapters, the metadata-embedding
experiment, and network / disk-I/O telemetry. Nightly capabilities are detected
and listed in toolchain.capabilities; nothing depends on them.
Deviations and decisions
-
CARGOis QuickRust’scargo(COMP-030), by running Cargo under another name. Cargo hands everything it starts (external subcommands, build scripts,env!("CARGO"), test binaries) its own path, and takes an inheritedCARGOinstead only when its own executable is not namedcargo(Cargo 1.86 and later), or, after that, the path in itsargv[0]when that is namedcargo. QuickRust therefore runs a hard link of the toolchain’scargo,bin/.qrust-engine, withargv[0]andCARGOset to~/.qrust/bin/cargo(Windows has no separateargv[0]: there Cargo’s help names the link,.qrust-engine.exe): a nested build through$CARGO(Clippy’s, nextest’s,cargo llvm-cov’s) is a QuickRust session linked to its parent (COMP-031), with QuickRust’s settings, like one throughPATH. Either can be opted out withQRUST_NESTED=upstream(COMP-032).qrust upstreamruns the toolchain’scargoas itself, and a linked toolchain is never changed, so there nested builds through$CARGOreach that Cargo directly; their rustc invocations are still observed, becauseRUSTC_WRAPPERis inherited. -
Run state lives in
~/.qrust, not in the repository. The specification’s configuration example writes reports to.qrust/runs/. Creating files in a repository on everycargo buildis not something a drop-in replacement should do, so recording goes toQRUST_HOMEand a repository report path is opt-in (measurement.report,QRUST_REPORT). -
Analysis is lazy by default. To keep dispatch overhead inside NFR-PERF-001/003, the build path only records; reports are produced on demand or synchronously when a report or budget enforcement was requested. A run analysed after later runs keeps everything recorded at build time (units, timings, revision) and reports workspace metadata, dirtiness and the artifact footprint as unavailable rather than describing today’s tree.
-
Fresh units need Cargo’s JSON stream. On a stable toolchain, nothing else says which units Cargo considered fresh. QuickRust observes the stream only when the user already asked for it and stdout is not a terminal, so terminal behaviour is never altered; otherwise
units_freshisnullwith a reason. -
Build-script run time is taken from files Cargo writes around the run (
invoked.timestamp, thenstderr/root-output). Cargo back-datesoutputto the invocation time, so it cannot be used. -
QuickRust manages the toolchains (decision of 2026-10-12), not rustup (COMP-020). The specification resolves an upstream Cargo through
PATHand rustup. QuickRust instead installs toolchains from the Rust dist server into~/.qrust/toolchainsand selects them in rustup’s documented order (+toolchain,RUSTUP_TOOLCHAIN, toolchain file, default; rustup’s per-directory overrides have no equivalent). Every command runs that toolchain’s own Cargo with QuickRust’s Cargo home (~/.qrust/cargo).QRUST_REAL_CARGOandcompatibility.real-cargono longer exist: a toolchain built elsewhere is used withqrust toolchain link. -
Configuration errors apply to every command. An invalid
.qrust/config.tomlstopscargo --versionas well ascargo build, with the field and file named;qrust upstreamis unaffected. -
No
cache.modeorartifacts.gcsettings. The specification’s example configuration lists them, but with remote-cache administration and GC execution out of this release each would have exactly one legal value. A read-only cache mode that a running sccache server may not honour would also be a false assurance. The keys are rejected as unknown rather than accepted and ignored. -
Portable unit identity includes source content. Cargo hashes workspace members by their workspace-relative path, so two worktrees share unit hashes even on different branches. Cross-worktree duplicates are counted only when the inputs are identical too.
-
JSON message order is not part of the oracle. Upstream Cargo emits independent units in a different order from run to run, so the compatibility test compares the set of messages byte for byte, not their sequence.
-
Fast by default (spec revision of 2026-10-11). In the default
mode = "fast", QuickRust changes what upstream Cargo would build in ways that keep program behaviour identical: debug-information settings, rustc’s parallel frontend for units compiled from scratch, a global artifact cache, and its own terminal output.mode = "compat"builds exactly upstream’s builds; the compatibility corpus’s byte-for-byte oracle tests run in compat mode, and fast mode has tests of its own (settings yield to the user, the parallel frontend never reaches an incremental rebuild,#![feature]stays rejected on a stable compiler, the cache restores correctly and never serves an edited source, fast mode and upstream keep separate artifacts instead of rebuilding each other). Every lever is measured by the speed index and checked against the benchmark workloads’ own test suites before it becomes a default. -
RUSTC_BOOTSTRAPfor-Zlevers. The stable compiler contains the parallel frontend and the linker selection QuickRust uses behind-Z. QuickRust’s wrapper setsRUSTC_BOOTSTRAP=1for the compiler processes of the units Cargo schedules, with-Zallow-features=so that#![feature]is rejected as on stable (with rustc’s “not in the list of allowed features” error instead of the stable-channel one). Never for build scripts or the compiler probes they run, so crates do not switch to nightly code paths. A nightly compiler accepts-Zflags and#![feature]anyway, so there no-Zallow-features=is added. No such lever applies when the user setsRUSTC_BOOTSTRAPthemselves. -
QuickRust’s compiler driver compiles the units Cargo schedules (fast mode,
fast.early-cutoff). The driver is the toolchain’s own rustc (librustc_driver, its LLVM, its release) run through QuickRust’s callbacks, built once per toolchain against itsrustc-devcomponent. With no callbacks active its outputs are rustc’s byte for byte (testtest0276_quickrusts_compiler_driver_builds_byte_for_byte_what_rustc_builds). In fast mode three things differ from upstream’s builds, none of them in program behaviour: a library’s crate hash (SVH) is computed from what its dependents can observe, so libraries’ metadata and rlibs differ from rustc’s (the hash is an identifier; nothing compares it across compilers); outputs are linked before rustc saves its incremental state, which it finishes after Cargo has moved on; and binaries’ object files are kept (hard links next to the output) so that a binary whose own code is unchanged is linked again instead of compiled. Restored and relinked units are checked against building the same source from nothing byqrust-bench cutoff(random edits on the benchmark workloads, byte for byte; recorded inbenchmarks/cutoff-gate.jsonl). Programs Cargo runs in rustc’s place (clippy-driver as a workspace wrapper, a user’s wrapper) run as they are; a crate the driver fails on is compiled by rustc. -
No
target/in the project (decision of 2026-10-12). Upstream Cargo builds into<workspace>/targetunless told otherwise; QuickRust tells it otherwise for every command: each workspace (ascargo locate-project --workspacenames it) builds into~/.qrust/cache/builds/<name>-<id>/, given to Cargo and every tool under it throughCARGO_TARGET_DIRandCARGO_BUILD_BUILD_DIR, socargo metadatareports it too. A target directory the user chose (--target-dir,--config build.target-dir,CARGO_TARGET_DIR/CARGO_BUILD_TARGET_DIR) is used as it is;build.target-dirin a Cargo configuration file is overridden. Scripts that hard-code./target/…must askqrust pathinstead. Tests:test0239_builds_go_to_quickrusts_cache_and_never_into_the_project,test0241_a_target_directory_the_user_chose_is_used…,test0242_a_build_script_building_another_workspace….
Open decisions of the specification, as resolved here
| Decision | |
|---|---|
| OQ-001 minimum Rust/Cargo | QuickRust declares rust-version = 1.80, built and tested with exactly 1.80 in CI from the lockfile (cargo install --locked); it delegates to whatever Cargo is selected and needs only cargo metadata format 1 and RUSTC_WRAPPER |
| OQ-002 platforms | macOS and Linux release-blocking; the suites pass on macOS and Linux x86_64 in CI; Windows has a CI smoke run, the suites are Unix-only |
| OQ-003 central service | none; all contracts are local files |
| OQ-004 cache provider | whatever sccache is configured with |
| OQ-005 fail-open vs fail-closed | cache.fail, default open |
| OQ-006 remediation trust | only QuickRust’s own configuration is safe |
| OQ-007, OQ-008 | measured and reported; no emulation of upstream features |