feat(cargo-coverage-gate): orchestrate coverage collection - #179
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
Codecov Report✅ All modified and coverable lines are covered by tests. ❌ Your project status has failed because the head coverage (97.6%) 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 #179 +/- ##
======================================
Coverage 97.6% 97.6%
======================================
Files 304 305 +1
Lines 69683 70384 +701
======================================
+ Hits 68016 68718 +702
+ Misses 1667 1666 -1
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.
🟡 Changes recommended
Two critical and four moderate findings remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds a portable cargo coverage-gate run mode for collecting, merging, publishing, and evaluating coverage while preserving the existing evaluation CLI.
Changes:
- Adds package selection, feature configurations, and collection orchestration.
- Integrates Cargo JSON, LLVM profile merging, LCOV publication, and response files.
- Adds CLI integration tests, fixtures, and updated documentation.
File summaries
| File | Reviewed changes and final findings |
|---|---|
crates/cargo-coverage-gate/tests/fixtures/fake-coverage-tool.rs |
Adds fake Cargo/LLVM tooling fixtures. |
crates/cargo-coverage-gate/tests/cli.rs |
Adds collection and failure-path integration tests. |
crates/cargo-coverage-gate/src/lib.rs |
Updates public documentation. |
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/run.rs |
Shares evaluation logic between modes. |
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/main.rs |
Dispatches evaluation and collection modes. |
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs |
Implements collection. Critical (3): Windows artifact replacement uses non-replacing rename. Critical (1): nightly toolchain validation is absent. Moderate (2): newline-delimited profile paths are not validated. Moderate (1): zero-threshold uninstrumented packages are not handled. Moderate (2): aarch64-pc-windows-msvc fallback is missing. Moderate (1): --quiet does not suppress collection output. |
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/cli.rs |
Adds run-mode arguments and configuration. |
crates/cargo-coverage-gate/README.md |
Updates usage documentation. |
crates/cargo-coverage-gate/docs/implementation.md |
Documents collection implementation details. |
crates/cargo-coverage-gate/docs/design/README.md |
Defines the collection contract. |
Review details
Suppressed comments (2)
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:338
- A selected package with
min-lines-percent = 0can be acoverage(off)/no-coverage-map crate. The existing coverage recipe explicitly removes such packages from the llvm-cov run and executes them with plain nextest (justfiles/anvil/checks/llvm-cov.just:27-36,85-94), because exporting the sole uninstrumented object fails. This path passes every explicit member tocargo llvm-cov nextest, sorun --package <zero-threshold-only>fails during export instead of honoring the documented always-pass opt-out; mirror that split or otherwise handle an empty measured set.
if selection.explicit {
for member in &selection.members {
command.arg("--package").arg(member.spec());
}
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:365
--quietis documented as suppressing stdout, but this branch unconditionally forwards non-JSON nextest output withprintln!. Thereforecargo coverage-gate run --quietstill emits nextest output (and the other collection subprocesses inherit stdout), unlike the legacy quiet mode. Thread the quiet setting through collection and suppress both forwarded and inherited child stdout when requested.
match compiler_artifact_objects(&line) {
Ok(artifact_objects) => objects.extend(artifact_objects),
Err(_error) => println!("{line}"),
}
- Files reviewed: 10/10 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved moderate collection issues affect reproducibility and cross-platform correctness.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (7)
Previously missed (1) — in code that hasn't changed since the last review.
crates/cargo-coverage-gate/src/lib.rs:145
--coverage-dirand--jobsare single-value options incli.rs:96-101; only--configurationand the global--packageselector are repeatable. Please correct this usage text so users are not told they can repeat options that clap will not collect as lists.
crates/cargo-coverage-gate/docs/design/README.md:107
- This contract update leaves
crates/cargo-coverage-gate/docs/implementation-plans/0000.md:14-16saying the crate has a single command, no subcommands, and is read-only, while this change addsrunand writes collection artifacts. That stale implementation plan conflicts with the new CLI and its own instruction to update the document as work lands; update or supersede the plan in this change.
cargo coverage-gate [EVALUATION OPTIONS]
cargo coverage-gate run [SELECTION] [COLLECTION OPTIONS] [EVALUATION OPTIONS]
The bare command remains the backward-compatible evaluation mode. It reads one
**crates/cargo-coverage-gate/docs/implementation.md:17**
* This implementation note says no target-directory scan is needed, but the collector explicitly scans `coverage_target_dir` for `.profraw` files (`collect.rs:259,431-444`). Narrow the claim to executable-object discovery (or mention the raw-profile scan) so the implementation guide does not contradict the pipeline it describes.
cargo llvm-cov nextest --no-report run. Cargo's JSON messages provide the
executable object paths; no target-directory scan or diagnostic parsing is
needed.
**crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:334**
* `--target` is documented and used by the evaluator as the target whose package policy should be selected (`cli.rs:49-52`, `lib.rs:337-341`), but forwarding it here also changes the test build/run target. For example, `run --target x86_64-pc-windows-msvc` on a non-Windows host now requires cross-target test execution, unlike the legacy evaluation mode. Keep collection on the host or introduce/document a separate collection-target option so the existing policy-target semantics remain unambiguous.
if let Some(target) = target {
command.arg("--target").arg(target);
**crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:524**
* This publishes with `std::fs::rename` directly to `final_lcov`, even though that destination may already exist (the new integration test creates it before a successful recollection at `tests/cli.rs:676`). Rename replacement is not portable to Windows, so an otherwise successful recollection will fail instead of atomically replacing the previous artifact on that platform. Use a platform-compatible atomic replacement strategy for an existing destination.
fs::rename(temporary_lcov.path(), final_lcov).into_app_err(format!("failed to publish LCOV file `{}`", final_lcov.display()))?;
**crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:489**
* This merge path is not portable to `aarch64-pc-windows-msvc`: the existing generated coverage recipe explicitly avoids cargo-llvm-cov there because the toolchain's `llvm-profdata` cannot merge the `.profraw` set (`crates/cargo-anvil/templates/justfiles/anvil/checks/llvm-cov.just:71-83`). The new `run` mode unconditionally performs the same merge for every target, so it fails on that platform despite documenting portable collection. Add target-specific handling or a clear unsupported-target diagnostic before this step.
fn run_profdata_merge(tools: &LlvmTools, profile_list: &Path, output: &Path) -> Result<(), AppError> {
let mut command = Command::new(&tools.profdata);
command.args(["merge", "-sparse", "-f"]).arg(profile_list).arg("-o").arg(output);
append_space_separated_env(&mut command, "LLVM_PROFDATA_FLAGS");
run_status(&mut command, "llvm-profdata merge")
**crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:305**
* This collector inherits the ambient `CARGO`/`rustc` toolchain and does not select or validate nightly Rust with `cargo-llvm-cov >= 0.7`. The crate's design explicitly requires that combination for faithful numbers because `coverage_nightly` exclusions are inactive on stable and older cargo-llvm-cov versions omit them (`crates/cargo-coverage-gate/docs/design/README.md:780-792`). As a result, the new default `run` invocation can silently gate on inflated coverage; enforce/check the requirement or make the required toolchain explicit in the `run` contract.
fn coverage_command(workspace: &WorkspaceInfo, coverage_target_dir: &Path) -> Command {
let mut command = Command::new(cargo_program());
command
.current_dir(&workspace.root)
.env("CARGO_LLVM_COV_TARGET_DIR", coverage_target_dir)
.env("CARGO_LLVM_COV_BUILD_DIR", coverage_target_dir);
- **Files reviewed:** 10/10 changed files
- **Comments generated:** 2
- **Review effort level:** Lite
</details>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
There was a problem hiding this comment.
🟡 Changes recommended
Five unresolved moderate findings must be addressed before approval.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (4)
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:49
- This ARM64 fallback returns before the policy probe below, while
WorkspaceInfo::loadonly records package names and versions. As a result, invalid[package|workspace].metadata.coverage-gatevalues (for example an out-of-range threshold or malformed target policy) are never validated and the command reports success when nextest passes, despite the documented exit-2 behavior for invalid configuration (crates/cargo-coverage-gate/docs/design/README.md:111-114). Resolve the selected policies before taking this no-gate path, then skip only coverage collection/evaluation.
if is_unsupported_arm64_windows_target(args.target.as_deref()) {
let result =
format!("`{ARM64_WINDOWS_TARGET}` does not support cargo-llvm-cov; tests passed without coverage collection or gating");
run_plain_configurations(
&workspace,
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:707
- Valid Cargo JSON messages other than
compiler-artifactare silently discarded:compiler_artifact_objectsreturnsOk(empty)and only JSON parse errors are printed. With--cargo-message-format=json-render-diagnostics,compiler-messagerecords contain the compiler's rendered diagnostics; on a failed build the user is left with only the generic nonzero-status error instead of the actionable compiler message. Forward or render non-artifact diagnostic records when--quietis not set.
match compiler_artifact_objects(&line) {
Ok(artifact_objects) => objects.extend(artifact_objects),
Err(_error) if !execution.quiet => println!("{line}"),
Err(_error) => {}
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:728
- The new collector invokes both
cargo llvm-cov nextestand plaincargo nextestthrough this helper, but never passes--locked. The checked-in coverage recipe uses--lockedfor every nextest invocation (justfiles/anvil/checks/llvm-cov.just:80,:88, and:196); without it, a stale lock can be resolved and rewritten during a coverage run, making this mode nondeterministic and unlike the existing coverage check. Add the lockfile guard here.
command.arg(configuration.cargo_flag()).arg("--locked");
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:35
- The documented empty
--package-fileno-op is checked only after resolving the toolchain and loading Cargo metadata. Consequently, an empty impact file still fails when the selected Rustup/toolchain is unusable or when the command is run outside a workspace, instead of returning success without collection; detect the empty file before toolchain/workspace initialization while still reporting file-read errors.
let toolchain = ToolchainSelection::resolve(collection.toolchain.as_deref())?;
let workspace = WorkspaceInfo::load(&toolchain)?;
let selection = Selection::resolve(&workspace, &args.packages, collection.package_file.as_deref())?;
- Files reviewed: 14/15 changed files
- Comments generated: 1
- Review effort level: Lite
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved collection correctness, diagnostics, concurrency, path-handling, and documentation findings remain.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (4)
Previously missed (1) — in code that hasn't changed since the last review.
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:708
- Valid Cargo JSON diagnostic records are silently dropped here:
compiler_artifact_objectsreturnsOk(Vec::new())for every non-compiler-artifactreason, so only malformed/non-JSON lines reachprintln!. Because this command requests--cargo-message-format=json-render-diagnostics, a compilation failure can be reduced to the generic non-zero status while hiding rustc's rendered diagnostics. Forwardcompiler-message.message.renderedbefore continuing, as the analogous Cargo JSON consumer does injustfiles/anvil/checks/miri.just:207-209, while preserving--quiet.
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:755
- This admits every
executablefield from acompiler-artifactrecord; it does not require the Cargo test profile. The repository's analogous Cargo JSON consumers admit only records withprofile.test == trueand explicitly exclude ordinary executables (justfiles/anvil/checks/miri.just:211-216,crates/cargo-anvil/docs/implementation.md:150-156). A normal binary/example artifact in this stream can therefore be passed tollvm-covas an uninstrumented object instead of limiting export to test objects. Filter executable/filename admission by the test profile, retaining only any companion objects the export contract actually requires.
let mut objects = BTreeSet::new();
if let Some(executable) = message.get("executable").and_then(Value::as_str) {
objects.insert(PathBuf::from(executable));
}
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:455
- The new selector matcher recursively explores both branches for every
*, including repeated stars, so a user-supplied pattern such as a long run of*can cause avoidable deep/exponential work before collection starts. The existing evaluator matcher atsrc/verdict.rs:243-260collapses consecutive stars; share that implementation or otherwise memoize/linearize this path.
'*' => {
glob_matches_from(remaining_pattern, name)
|| name
.split_first()
.is_some_and(|(_, remaining_name)| glob_matches_from(pattern, remaining_name))
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:899
- These two arguments are constructed through
Path::display(), which is lossy for non-UTF-8 paths. Because--coverage-diris accepted as aPathBuf, a Unix path containing non-UTF-8 bytes can create the temporary files successfully but pass different paths tollvm-cov, causing export to fail; construct these arguments asOsStrings or reject such coverage directories explicitly.
.arg(format!("-instr-profile={}", profdata.display()))
.arg(format!("@{}", response.display()))
- Files reviewed: 14/15 changed files
- Comments generated: 2
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
There was a problem hiding this comment.
🟡 Changes recommended
Outstanding collection, cleanup, publication, and diagnostic-handling issues remain.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (3)
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:110
- When
collect_configurationfails, this?unwinds directly and relies onTemporaryDirectory::Drop; its drop handler discardsremove_dir_allerrors. A failed collection can therefore leavetarget/coverage-gate/run-*scratch state with no warning, while cleanup errors are only combined after a completed evaluation at line 121. Route collection failures through the same cleanup/error-precedence logic (or report cleanup failure) so repeated failures do not silently accumulate.
let mut lcov_paths = Vec::with_capacity(configurations.len());
for configuration in configurations {
let lcov_path = collect_configuration(&execution, configuration)?;
lcov_paths.push(lcov_path);
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:1209
- The
?returns beforearmedis cleared when temporary-file removal fails, soDropcallsremove_filea second time. This contradicts the collection contract documented indocs/implementation.md:35-36(explicit cleanup disarms after one attempt) and differs fromTemporaryDirectory::cleanup; capture the result, disarm unconditionally, then return it.
fn cleanup(mut self) -> Result<(), AppError> {
remove_if_present(&self.path).into_app_err(format!("failed to remove temporary file `{}`", self.path.display()))?;
self.armed = false;
crates/cargo-coverage-gate/src/lib.rs:144
--coverage-dirand--jobsare scalar options (PathBufandOption<NonZeroUsize>incli.rs), so this says they are repeatable even though only--configurationaccepts multiple values. Please document the actual option cardinalities; the README is generated from this rustdoc.
//! UTF-8 line. Use repeatable `--configuration`, `--coverage-dir`, and
- Files reviewed: 14/15 changed files
- Comments generated: 2
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99e3-4546-847a-e30dd5cb18a4 Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical and moderate issues affect artifact isolation, toolchain consistency, package-file support, and zero-threshold behavior.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
crates/cargo-coverage-gate/tests/cli.rs:1017
- The advertised zero-threshold-only plain-nextest/no-gate path is not implemented here: this test expects
cargo llvm-cov nextestandreportfor a selection whose only package hasmin-lines-percent = 0. The existing coverage recipe separates such packages to plain nextest, while this PR description saysrunhandles them that way. Either restore that routing or update the contract to explain the intentional difference.
fake_collection_command(tmp.path(), &tools, &object)
.env("FAKE_NO_COVERAGE_DATA", "1")
.assert()
.success()
.stdout(predicate::str::contains("all packages meet their threshold"))
- Files reviewed: 11/12 changed files
- Comments generated: 5
- Review effort level: Lite
Declare response-file scratch state only on Windows and exclude an equivalent cleanup mutant whose replacement still executes the same Drop cleanup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
There was a problem hiding this comment.
🟡 Changes recommended
Resolve target consistency and concurrent report publication issues, and correct the CLI documentation.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (2)
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:440
lcov_pathis the shared publication path, andrun_reportwrites to it before this function returns it for evaluation. A concurrentruncan overwrite or truncate that file between the two configurations andevaluate_paths, so this invocation can gate another selection (or read a partial report). Keep each report in invocation-private scratch for evaluation, then publish a completed copy atomically to the stable path.
let lcov_path = execution
.args
.coverage_dir
.join(format!("lcov-{}.info", configuration.artifact_name()));
crates/cargo-coverage-gate/src/lib.rs:145
- Only
--configurationis repeatable here:coverage_dirandjobsare singularPathBuf/Option<NonZeroUsize>fields incli.rs:89-102. This rustdoc (and the generated README) currently tells callers they may repeat all three, which misstates the CLI contract; update the wording and regenerate the README.
//! workspace. Use repeatable `--configuration`, `--coverage-dir`, and `--jobs`
//! options to customize collection.
- Files reviewed: 11/12 changed files
- Comments generated: 1
- Review effort level: Lite
Merge repeated LCOV inputs using the gate's boolean covered-line contract so anomalous execution counts cannot panic in debug builds or wrap to a false uncovered result in release builds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
Resolve one explicit-or-host target for collection and evaluation, and isolate concurrent collection tests with distinct consumer directories. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
There was a problem hiding this comment.
🟡 Changes recommended
The collection path re-reads stable LCOV artifact paths for evaluation, which can yield incorrect/mixed verdicts if concurrent runs share the same --coverage-dir.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:460
collect_configurationreturns the stable--coverage-dir/lcov-*.infopath that is later re-read for evaluation. If twocargo coverage-gate runprocesses share the same--coverage-dir, one run can overwrite these stable artifacts between the other run’s collection and itsevaluate_pathsread, producing a mixed/incorrect verdict (or a transient parse error while a file is being rewritten). Consider keeping an invocation-private LCOV for evaluation (e.g., write report output to a scratch path under the isolatedcoverage_scratch, then copy/rename to the stable consumer path) so publication remains last-writer-wins but the in-flight verdict is stable.
fn collect_configuration(execution: &CollectionExecution<'_>, configuration: FeatureConfiguration) -> Result<PathBuf, AppError> {
let lcov_path = execution
.args
.coverage_dir
.join(format!("lcov-{}.info", configuration.artifact_name()));
- Files reviewed: 12/13 changed files
- Comments generated: 1
- Review effort level: Lite
|
Preserve argv boundaries in rendered command diagnostics by quoting empty and whitespace-containing arguments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
There was a problem hiding this comment.
🔵 Needs a closer look
The new collector evaluates from stable --coverage-dir LCOV paths, which can yield incorrect verdicts if concurrent runs share the same coverage directory.
Review details
Suppressed comments (1)
crates/cargo-coverage-gate/src/bin/cargo-coverage-gate/collect.rs:465
collect_configurationreturns the published LCOV path under--coverage-dirandrunlater re-reads those paths for in-process evaluation. If twocargo coverage-gate runinvocations share the same--coverage-dirconcurrently (defaulttarget/coverage), one run can overwritelcov-*.infobetween collection andevaluate_paths, leading to a verdict computed from a mixed or foreign LCOV pair.
To make the verdict deterministic under concurrency while still publishing stable artifacts, write each configuration’s LCOV into the invocation-private scratch directory (under the already-isolated CARGO_LLVM_COV_TARGET_DIR) and then copy it to the stable --coverage-dir path for consumers; evaluate using the private paths.
fn collect_configuration(execution: &CollectionExecution<'_>, configuration: FeatureConfiguration) -> Result<PathBuf, AppError> {
let lcov_path = execution
.args
.coverage_dir
.join(format!("lcov-{}.info", configuration.artifact_name()));
run_clean(execution.workspace, execution.coverage_target_dir, execution.tools, execution.quiet)?;
run_nextest(execution, configuration)?;
run_report(execution, configuration, &lcov_path)?;
Ok(lcov_path)
- Files reviewed: 12/13 changed files
- Comments generated: 0 new
- Review effort level: Lite
martinhavelka (wukchung)
left a comment
There was a problem hiding this comment.
🤖 Reviewed the collection pipeline against cargo-llvm-cov v0.9.0 (the enforced floor) and shell-escape. Three verified findings below, all in the new run collector. Existing open threads are not repeated.
Use fresh configuration targets without workspace cleanup, normalize Windows error-206 diagnostics, and stage response-file exports before publishing completed or valid empty LCOV. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
There was a problem hiding this comment.
🔵 Needs a closer look
The PR introduces a large, cross-platform process-orchestration and Windows-fallback implementation path whose correctness and operational characteristics are difficult to fully validate from diff inspection alone.
Review details
- Files reviewed: 12/13 changed files
- Comments generated: 0 new
- Review effort level: Lite
Give concurrent fake collectors independent logs and directly test Windows error-206 detection so CI and mutation results do not depend on interleaved writes or platform gating. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9fc919b-99f7-4134-aad1-2116321b4e0c
There was a problem hiding this comment.
🟢 Approval recommended
The changes are internally consistent, include thorough integration/unit coverage for the new behaviors, and update the public-facing documentation/design docs to match the new contract.
Review details
- Files reviewed: 12/13 changed files
- Comments generated: 0 new
- Review effort level: Lite
🤖 Adds a portable
cargo coverage-gate runmode while preserving the existing evaluation CLI.--targetor rustc host—and passes it consistently through collection, reporting, and policy evaluation--no-coverage-targetfallbacks that run plain nextest without claiming coverage or gatingcargo llvm-cov reportlcov-all-features.infoandlcov-no-default.infoartifacts directlyThe debug collector completed end-to-end on ox-tools and oxidizer with every workspace package instrumented. Upload and CI-backend behavior remain outside the tool.