Match hyphen in multi-revision comment matchers#124137
Conversation
|
rustbot has assigned @compiler-errors. Use |
|
Some changes occurred in src/tools/compiletest cc @jieyouxu |
|
Reasoning: https://github.com/rust-lang/rust/pull/123816/files#diff-0238262528c07a864b8aa49d6d3aa989c49b045a012b1a8e2c491c84e3ccac3b wasn't matching anything labeled |
|
r? @jieyouxu |
|
The new regex looks good, @tgross35. Would you mind adding a unit test for the |
|
Making revision names accept - makes sense to me, but I don't remember if the dash messes with crate names generated by revisions, could you double check if something like isn't borked? |
|
IIRC revision names are used in crate names for artifact names and output, I don't immediately recall if we normalized it to become underscore. |
| // //[rev1,rev2]~^^ | ||
| static RE: Lazy<Regex> = | ||
| Lazy::new(|| Regex::new(r"//(?:\[(?P<revs>[\w,]+)])?~(?P<adjust>\||\^*)").unwrap()); | ||
| Lazy::new(|| Regex::new(r"//(?:\[(?P<revs>.+)])?~(?P<adjust>\||\^*)").unwrap()); |
There was a problem hiding this comment.
Does this regex mean test.name is accepted, along other non-alphanumeric characters? If so, that will break anything using revision name as crate names unless you also perform "name mangling" to normalize the non-alphanumeric characters
There was a problem hiding this comment.
This is another case of "silently failing" in compiletest where it really really needs to loudly report that your directives don't work and won't work as expected...
|
#123816 is modifying a test case that already uses However, generally restricting revision names to valid ASCII-only identifiers seems reasonable to me (as long as we give a good error message when compiletest encounters an invalid revision name 🙂) |
I think that only recently works because I added some explicit crate name mangling for revisioned run-rustfix: #123601, which modifying the accepted revision name regex luckily hits. But that only handles . and - I want to say? So if the revision name contains a $ it probably breaks? |
I think we could just only accept revision names that are crate-name-like (that is, restrict revision names to only consist of alphanumeric + underscore characters), and report an error otherwise. I don't think we want to perform any weird crate name mangling, because e.g. if you naively mangle |
|
I agree, the simpler the better. |
|
Having What would you prefer for this PR? I can leave it as-is and add a test, or change back to the original pattern and just add |
Huh, I suppose then it does work with |
|
But otherwise it seems like an oversight that |
4b4673c to
23fea67
Compare
|
I changed this PR to just do the simplest thing and match Since there is no new rejecting behavior, is this okay as-is or do you want a test still? (if so, what would that look like - just a dummy UI test?) |
Could you still add a unit test for |
|
Alrightie I added a simple test, let me know if that looks fine. |
23fea67 to
feec066
Compare
|
Tidy failed so it didn't push before, should be up to date now |
This comment has been minimized.
This comment has been minimized.
Currently, the matcher `//[rev-foo,rev-bar]~` does not get selected by the regex. Change the matcher to also match strings that contain a `-`.h
feec066 to
282488c
Compare
|
Looks good to me, thanks for the patch! @bors r+ rollup |
|
Thanks! |
…iaskrgr Rollup of 3 pull requests Successful merges: - rust-lang#123409 (Implement Modified Condition/Decision Coverage) - rust-lang#124104 (Fix capturing duplicated lifetimes via parent in `precise_captures` (`impl use<'...>`)) - rust-lang#124137 (Match hyphen in multi-revision comment matchers) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#124137 - tgross35:testsuite-multi-rev-regex, r=jieyouxu Match hyphen in multi-revision comment matchers Currently, the matcher `//[rev-foo,rev-bar]~` does not get selected by the regex. Change the matcher to include `-`.
|
Thanks for getting this fixed, everyone! |
Adds the CI job that runs the per-handler branch-coverage producer introduced in earlier waves and feeds its artifact into scorecard-aggregate. Side-car design (data layer + workflow stay in lockstep): - Pinned nightly channel from rust-nightly-coverage-toolchain.toml via scripts/nightly-coverage-channel.sh — the rest of the repo stays on stable. Removal path is one PR (toml + script + this job + the moon task) when rust-lang/rust#124137 stabilizes. - continue-on-error: true mirrors quality.toml's coverage_handler.report_only = true: nightly outage surfaces in the CI UI and the scorecard pending-note, never blocks the merge queue. Promotion to a hard gate is two paired edits. - scorecard-aggregate consumes the artifact via download-artifact with continue-on-error so a missing file falls through to the renderer's "producer pending" pathway. Reuses existing tools.toml pins (cargo-nextest@0.9.133, cargo-llvm-cov@0.8.5) — no new pins needed. coverage-handlers is intentionally NOT in verdict's needs[]: matches the existing convention for continue-on-error jobs (desktop-e2e, crap-delta). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tly side-car (#805) * chore(coverage): #583 — pin nightly-only side car for branch-coverage producer Branch-level coverage instrumentation (-Zcoverage-options=branch surfaced via cargo llvm-cov --branch) is nightly-only as of rustc 1.97 (rust-lang/rust #124137). The repo's stable 1.95.0 pin makes per-handler branch coverage — the signal Row::CoverageDelta.breakouts.handlers[].branch_coverage_pct names in the V4 schema — unobtainable without a nightly side channel. Rather than override rust-toolchain.toml (which would bleed nightly into every other task), this commit lands the date-pinned channel in a separate file consumed only by: - the new shop:coverage-branches moon task (--branch on nightly, output coverage-branches.json — separate artifact from coverage.json so the CRAP gate path stays on stable), - the coverage-handlers CI job that will follow. Single source of truth: rust-nightly-coverage-toolchain.toml. Both consumers read it through scripts/nightly-coverage-channel.sh, so a pin bump is a single-file edit. The rationale and the four-step removal path (delete file + task + script + CI job; add --branch to the existing coverage task) are documented in the toolchain file's prologue. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(coverage): #583 — coverage-breakouts producer (route walker + LLVM JSON join) Lifts per-handler branch coverage out of "(producer pending — see #583)" sentinel territory into a real artifact the scorecard aggregator can consume. New `coverage-breakouts` bin under `tools/docs-gen/`: - syn-based route walker (tools/docs-gen/src/coverage/route_walker.rs) resolves `(method, url_path, handler_rust_path)` from `.route()` and `.nest()` calls. Handles fully-qualified handler refs (`crate::x::y`), bare idents resolved via in-file `use` items (with alias support), and inline-anonymous nested routers. Records unresolvable findings rather than silently dropping them. - LLVM coverage JSON parser (tools/docs-gen/src/coverage/llvm_cov.rs) decodes the `cargo llvm-cov --branch --json` payload (3.x schema as emitted on nightly), demangles function names via `rustc-demangle`, and computes branch coverage per LLVM convention: count = 2 × branches.len(), covered = sum of (true>0) + (false>0). Partially- covered branches (one side hit) register as 1-of-2 — exactly the negative-path signal Quinn's blind-spot 3 wants surfaced. - Producer (tools/docs-gen/src/coverage/producer.rs) discovers crates from crates/*/Cargo.toml + apps/*/Cargo.toml, applies the same exclusion ledger as crap4rs.toml, joins routes with coverage on Rust path equality, and emits CoverageBreakoutArtifact JSON. Diagnostics surface every unresolved-handler and unresolvable-route with file + line so the operator can fix root cause; the bin exits with code 2 when any are present (artifact still written for inspection). - Bin shim (tools/docs-gen/src/bin/coverage-breakouts.rs) is CC=1 by the same logic as lcov-dedup and adr-validate: coverage credit lands on the library, the bin is a thin arg parser. Wire schema unchanged. The producer-internal HandlerArtifactEntry carries rust_path, branch counts, and function_count for diagnostics; the aggregator (next commit) translates these into the already-defined HandlerBreakout wire shape (handler + branch_coverage_pct). Smoke-tested end-to-end against a partial coverage payload (scorecard crate only): walker discovers 55 routes across kikan + mokumo-shop, all resolve to coherent Rust paths, and the producer correctly reports all 55 as unresolved (no kikan/mokumo-shop coverage in the partial payload) — the exact failure mode CI will hit if a handler is renamed without the coverage rerun. Tests: 34 unit tests across artifact, llvm_cov, route_walker, crap_exclusions, producer (epoch math + crate discovery). Real-fixture test in llvm_cov is opt-in (skipped when fixture absent so a fresh checkout still passes). Also tightens .gitignore — re-includes tools/docs-gen/src/coverage/ since the global `coverage/` rule (for runtime artifacts) was hiding the producer source. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(scorecard): #583 — wire per-handler breakouts producer artifact into aggregator + threshold gate Closes the second leg of #583: the aggregator now reads the `coverage-breakouts.json` producer artifact, populates `Row::CoverageDelta.breakouts.by_crate[].handlers[]` with `(route, branch_coverage_pct)` pairs, and runs them through a configurable threshold gate. Producer artifact reader: new `crates/scorecard/src/coverage_breakouts.rs` mirrors the wire types from the producer (under `tools/docs-gen/src/ coverage/artifact.rs`) so the aggregator doesn't take a build-time dep on docs-gen. Versioned (`ARTIFACT_VERSION_MAX = 1`); a higher-version artifact is a hard parse error so a producer/consumer skew surfaces loudly. The wire translation drops producer-internal fields (`rust_path`, branch counts, `function_count`) — the renderer only needs route + percentage. Uses `Result<T, String>` rather than `anyhow` so the scorecard lib's deps-zero-by-default invariant holds. CLI: `scorecard aggregate` gains `--coverage-breakouts-json <PATH>`. Optional — when omitted (or the file is missing), the drill-down stays empty and the existing `(per-handler producer pending — see #583)` note path still applies. Threshold gate: new `[rows.coverage_handler]` table in `quality.toml`. - `warn_pct_below` (default 60.0): handler at-or-below resolves Yellow. - `fail_pct_below` (default 40.0): handler at-or-below resolves Red. - `report_only` (default true): when true, gate verdict is informational only — does not escalate row status. Defaults to true so a nightly- toolchain outage on the producer side cannot block the merge queue. Operators flip to false in `quality.toml` once the side-channel's reliability is established. Verdict logic: handler-floor verdict = worst-of across all handlers (one Red handler drives the row Red). Final row status = max(delta- driven status, handler verdict) when `report_only = false`. When Red fires from the handler path, `failure_detail_md` names up to 5 offending handlers + their pcts so the operator sees the actionable signal without expanding the drill-down. Wire schema: unchanged (the existing `Breakouts.by_crate[].handlers[]` shape is what we populate). Operator-config schema bumps the `additionalProperties:false` count from 7 to 8 (new `CoverageHandlerThresholds`). Regenerated `.config/scorecard/quality.config.schema.json` via `scorecard emit-schema`. Tests: 5 new aggregate-level tests pin breakouts population, the report_only-true default no-escalation path, the enforce-mode Red, the warn-floor Yellow, and the missing-input empty-drill-down path. 6 new coverage_breakouts unit tests pin parse/round-trip, version rejection, wire translation, iter_handler_pcts, and diagnostics classification. 256 lib tests pass total. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(scorecard): #583 — render per-handler branch coverage drill-down Closes the third leg of #583. The sticky-comment renderer now surfaces the breakouts the aggregator populates (Wave C) inside a collapsible `<details>` block beneath the `Row::CoverageDelta` row. Layout: - Handlers grouped by crate (matches the wire shape's `by_crate[]`). - Within each crate, sorted ascending by `branch_coverage_pct` so the most-uncovered handlers float to the top — operator's eye is drawn to the actionable end first. - Each handler row carries a small icon (🔴 ≤40%, 🟡 ≤60%, 🟢 above) matching the `[rows.coverage_handler]` quality.toml defaults. The numbers live in named constants (`HANDLER_FAIL_PCT`, `HANDLER_WARN_PCT`) so a future "render thresholds from artifact" upgrade has one grep target. Operators tuning the gate threshold will see slight cosmetic drift between icons and verdict — that's acceptable; the row's status is the authoritative signal. Producer-pending fallback: when the artifact carries no handlers (no `--coverage-breakouts-json` supplied to the aggregator, or producer artifact is empty), the renderer emits an inline italic note linking to issue #583 — wires the existing `(per-handler producer pending — see #583)` documented behavior that types.d.ts already promised but the renderer hadn't implemented yet. Tests: 13 new vitest cases pin (a) the threshold constants matching quality.toml defaults, (b) the empty/undefined breakouts → pending note path, (c) the populated → details block path, (d) ascending sort by pct, (e) icon mapping at the inclusive boundaries (40.0 → 🔴, 60.0 → 🟡), (f) per-crate grouping with multiple crates, (g) singular nouns at count=1, (h) integration through renderScorecardMarkdown. 78 vitest cases pass total across the scorecard renderer suite. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(scorecard): #583 — coverage-handlers nightly side-car job Adds the CI job that runs the per-handler branch-coverage producer introduced in earlier waves and feeds its artifact into scorecard-aggregate. Side-car design (data layer + workflow stay in lockstep): - Pinned nightly channel from rust-nightly-coverage-toolchain.toml via scripts/nightly-coverage-channel.sh — the rest of the repo stays on stable. Removal path is one PR (toml + script + this job + the moon task) when rust-lang/rust#124137 stabilizes. - continue-on-error: true mirrors quality.toml's coverage_handler.report_only = true: nightly outage surfaces in the CI UI and the scorecard pending-note, never blocks the merge queue. Promotion to a hard gate is two paired edits. - scorecard-aggregate consumes the artifact via download-artifact with continue-on-error so a missing file falls through to the renderer's "producer pending" pathway. Reuses existing tools.toml pins (cargo-nextest@0.9.133, cargo-llvm-cov@0.8.5) — no new pins needed. coverage-handlers is intentionally NOT in verdict's needs[]: matches the existing convention for continue-on-error jobs (desktop-e2e, crap-delta). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(scorecard): #583 — handler-coverage BDD specs + nightly side-car notes Wave 6 (BDD): four @future scenarios under a new "Per-handler drill-down" rule in scorecard_display.feature documenting the V4.1 contract — populated breakouts render a per-crate <details> block sorted ascending, empty breakouts render a producer-pending note, worst-of-handler thresholds escalate the row only when report_only is disabled, and the report-only default keeps the gate purely informational. @future-tagged so bdd-lint --exclude-tags treats them as documented placeholders ahead of step-def implementation. Wave 7 (docs): - COVERAGE.md gains a "Per-handler branch coverage (mokumo#583)" section walking the three pipeline stages (capture → producer → aggregator + threshold gate), the non-blocking design, the two paired edits to promote to a hard gate, and the one-PR removal path when branch coverage stabilizes on rustc. - CHANGELOG.md "Unreleased / Added" entry for V4.1 — schema additive (no schema_version bump), new operator surface ([rows.coverage_handler] in quality.toml), new CI job (coverage-handlers consuming pinned nightly). - AGENTS.md §Dep-graph and verdict assertions gains a "Nightly toolchain side-cars" callout codifying the side-car convention used by mokumo#583 so future nightly-only features follow the same registry pattern. - quality.toml gains a documented [rows.coverage_handler] section with the M00 60% / 40% defaults so operators can see and tune the handler thresholds without diving into Rust source. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(coverage-breakouts): #583 — resolve sibling-module handler refs The route walker mis-resolved multi-segment handler refs whose head named a sibling module declared in the same file. Smoke-running the producer against the real workspace surfaced six kikan auth handlers collapsing to literal `login::login` / `me::me` / `logout::logout` / `recover::recover_*` instead of the fully-qualified `kikan::platform::v1::auth::<sub>::<fn>` paths the LLVM coverage artifact carries — the join in producer::run() then logged them as `unresolved_handlers` and dropped them from the wire breakouts. Root cause: `FileVisitor::resolve_path()` had three branches — `use_map` hit, single-ident module-local, and multi-segment "external crate". The third branch fired for `pub mod login; ... .post(login::login)` patterns because `login` matched neither a `use` import nor was a single-ident. Fix: track sibling module declarations via a new `module_decls: HashSet<String>` field populated from `visit_item_mod` (handles both `mod foo;` and inline `mod foo { ... }`). In `resolve_path()`, a multi-segment head whose value is in `module_decls` now resolves under `<file_module_path>::<head>::<tail>` — the same shape as the single-ident module-local branch, just with a tail. Pinning test: `resolves_sibling_module_handler_via_mod_decl` writes a two-file fixture mimicking the real auth/mod.rs + auth/login.rs layout and asserts the resolved path is `demo::auth::login::login`. Re-running the producer against the workspace post-fix shows the auth handlers correctly resolved (still on the unresolved list because the synthetic LLVM JSON only has one function — the path is now correct, the join key just has nothing to join against until real coverage data lands). The "external-crate qualified" fallback branch is preserved for genuinely external multi-segment references (e.g. `axum::Router`); no existing walker test relied on the previous behavior for sibling-mod patterns. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * quality(coverage): #583 — bring crap-rust gate green for coverage-breakouts surface CI surfaced 7 functions over CRAP threshold 15 (worst 272.0) — all in the new producer surface added by this PR. Two compounding causes: 1. `bin/coverage-breakouts::main` and `coverage::producer::run` reported 0% coverage because cargo-llvm-cov nextest doesn't credit `src/bin/` code, and `run()` had no end-to-end test exercising it through the library — the CRAP formula `CC + CC²·(1-cov)³` exploded. 2. Five route-walker / producer functions had high CC (22..31) from tightly-packed match arms and let-else early returns. Fixes: - New `docs_gen::coverage_breakouts` lib module mirroring `validate.rs`: `parse_args` / `Args` / `execute` with 13 unit tests covering CLI parse + happy/error execute paths. Bin shrinks to a 4-line shim. - Three end-to-end `run()` tests in `producer.rs` building tempdir workspaces with synthetic LLVM JSON: happy join, unresolved-handler diagnostic, and crap4rs.toml exclusion path. Coverage on `run` jumps 0% to 93%, dropping CRAP 272 to 16. - `route_walker::collect_method_router` (CC 31) split into `head_call_method_handler` + `chain_call_method_handler` per chain position. - `FileVisitor::resolve_path` (CC 22) dispatches keyword heads (`crate` / `self` / `super`) to a `join_path(prefix, tail)` helper and routes the non-keyword case to `resolve_other_head`. - `route_walker::walk` (CC 29) decomposes into `parse_crate_sources` / `scan_src_tree` / `visit_one_file` / `emit_routes` over a `ParsedSources` accumulator. - `route_walker::file_module_path` (CC 15) delegates per-component classification to `file_path_segment`. - `producer::discover_crates` (CC 23) splits into `scan_subdir_for_packages` + `read_package_name`. - `producer::run` (CC 16) decomposes into `gather_walker_inputs` / `join_routes_with_coverage` / `join_one_crate` / `lift_unresolvable`. Local crap4rs against tools/docs-gen drops 7 to 0 above threshold; worst 14.4 (PASS). All 143 docs-gen lib tests pass. The coverage-handlers job's separate failure (LLVM SIGSEGV in `getInstantiationGroups` on nightly-2026-04-15) is upstream nightly LLVM and already correctly soft-gated (`continue-on-error: true` + not in verdict's `needs:`), so it doesn't block the rollup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(coverage): #583 — narrow coverage-branches scope + bump nightly to dodge llvm-cov SIGSEGV The `coverage-handlers` job's previous run crashed during the post-test merge step: `llvm-cov export` SIGSEGV in `llvm::coverage::CoverageMapping::getInstantiationGroups` (LLVM 22.1 shipped with `nightly-2026-04-15`). All 968 tests passed; the bug is upstream in the instrumentation pipeline, not in our code. Two cheap mitigations: 1. Bump the pinned nightly to `nightly-2026-05-01`. Rust's bundled LLVM rolls weekly and the bug may be already fixed in a newer rev. 2. Replace `--workspace --exclude {mokumo-desktop,kikan-tauri,kikan-admin-ui}` with `-p kikan -p kikan-cli -p kikan-spa-sveltekit -p mokumo-shop` — only crates that register `Router::route(...)` / `.nest(...)` need instrumentation for the producer's per-handler join. Drops the count of `-object` files llvm-cov merges from 11 to 4, narrowing the surface for the buggy code path. The route walker still walks every crate (it's a source-level scan, independent of coverage); coverage-less crates simply contribute zero handler lookups, which the producer already handles cleanly. If both fail to clear the bug, `coverage-handlers` stays soft-gated (`continue-on-error: true`, not in verdict's `needs:`) and the rollup remains green — same containment we already have. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * review(coverage): #583 — address CodeRabbit feedback on PR #805 Addresses 10 of the 12 review comments. Skips: - moon.yml --exclude annotation request: stale, the prior commit (33d71a3) replaced --exclude flags with positive -p selection. - route_walker multi-mount prefix fan-out: real bug but heavy lift (HashMap value to Vec, DFS over parent_of, multi-prefix emit). Mokumo's current Axum topology mounts each builder fn at most once so the bug is latent; deferred to a follow-up issue rather than expanding this PR's scope further. Fixes: - Branchless handlers report 100.0% (coverage::llvm_cov, coverage::artifact). A handler with no conditionals is vacuously fully covered; encoding the empty case as 0.0 would trip the worst-of [rows.coverage_handler] gate against handlers with nothing to cover. - Producer exit_code follows the documented 0/2 contract (coverage::producer::run). Previously returned 0/1 internally and coverage_breakouts::execute re-coerced 1->2; library callers now get the right value directly without the translation layer. - Cargo package names preserved in artifact (coverage::producer, coverage::route_walker). The walker now carries both the package name (e.g. mokumo-shop, used in RouteEntry.crate_name and the artifact's by_crate[].crate_name) and the Rust ident form (mokumo_shop, used for path resolution against demangled symbols). - Inline .nest() targets walked once (coverage::route_walker::FileVisitor::visit_expr_method_call). handle_nest_call already recurses into target_expr with the prefix on the inline-prefix stack; falling through to the default visitor walked it a second time without the prefix and emitted duplicate routes. Now we descend into the receiver chain explicitly and skip the default args walk for the nest case. - Yellow handler downgrade carries actionable detail (Row::coverage_delta_yellow, aggregate::handler_yellow_failure_detail). Yellow constructor now takes Option<String>; when the per-handler gate causes the downgrade (!report_only and handler_status == Yellow), the row carries a detail naming the offending handlers in the (warn, fail] band. Plain delta-driven Yellow stays detail-less. - Offender count corrected after take(5) (aggregate::coverage_red_failure_detail). Previously counted post-take so any breakout >5 reported "5 handler(s)"; now totals before truncation and appends "and N more" when applicable. - coverage_handler thresholds validated at config-load (aggregate::validate_threshold_config). NaN/Inf, out-of-range ([0, 100]), and inverted (fail > warn, making Yellow unreachable) configs now fail loud with structured error messages — same treatment the other threshold rows already get. - JSON schema constrains pct_below thresholds to [0, 100] (threshold::CoverageHandlerThresholds schemars annotation + regenerated quality.config.schema.json). The config validator above enforces it at load; the JSON schema enforces it for ajv at the schema-drift gate. - Nightly side-car continue-on-error: true carries the required tracked: annotation (.github/workflows/quality.yml). Per the exclusion-tracking contract added in #740, deliberate exclusion sites need an inline tracked: <repo>#<n> — <reason> marker. - awk field separator includes single quotes (scripts/nightly-coverage-channel.sh). Inline doc claimed quote-tolerance for both ' and " but the awk -F only included "; a single-quoted channel would have leaked the surrounding quotes. Local crap4rs against tools/docs-gen stays at 0 above threshold; all 404 docs-gen + scorecard tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * quality(scorecard): #583 — decompose validate_threshold_config Extracted four per-section helpers — validate_coverage_section, validate_count_sections, validate_ci_wall_clock_section, validate_coverage_handler_section — so the entry function is a linear orchestrator (CC=5, CRAP=5.0) instead of carrying every section's branch fan-out (CC=15, CRAP=17.15 on the previous revision after the coverage_handler validation block was added). Largest helper post-split is CC=6 / CRAP=13.15, comfortably under the threshold of 15. Behaviour is identical; the same error strings are returned for the same inputs, validated by 256 lib tests still passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * review(coverage): #583 — address CodeRabbit second-pass feedback Six fixes on revision e387ad9 — five correctness-leaning rustdoc / behaviour gaps and one boundary test set that pins the new resolver: 1. route_walker.rs: visit_one_file no longer silently skips files whose `syn::parse_file` errors. Every `.rs` under a crate's `src/` is expected to be valid Rust; a silent skip would let the producer emit a partial artifact under exit-0 cover — exactly the drift the producer's loud-by-design diagnostics exist to surface. 2. llvm_cov.rs: module docs updated to (a) note `parse_str` accepts schema 2.x and 3.x, not just 2.x, and (b) document the 100% branchless rule on `branch_coverage_pct` so callers reading the rustdoc don't trip on the old "0.0% when total == 0" claim. 3. artifact.rs: doc on `CrateHandlerSet::crate_name` now states the field carries the Cargo package name (`mokumo-shop`) — matching the producer's pass-through behaviour after the previous round — instead of the stale Rust-ident form (`mokumo_shop`). 4. nightly-coverage-channel.sh: `awk` regex now tolerates indented ` channel = "..."` keys and matches the value by `nightly-` prefix rather than fixed field index, so a TOML formatter that indents under `[toolchain]` doesn't silently fail the side-car. 5. aggregate.rs: `read_coverage_breakouts` no longer returns `Ok(None)` for an explicit `--coverage-breakouts-json <missing>`. Operator-supplied paths now fail loud, matching the contract of `read_pr_meta`, `read_ci_wall_clock_json`, and the rest of the reader family. A path typo on a CI invocation will surface instead of silently degrading the verdict to a pending stub. Pinned by two new regression tests. 6. threshold.rs: 12 boundary tests for `resolve_coverage_handler`, the only resolver here that lacked them. Covers empty input, each side of warn / fail (using `f64::next_up()` for the smallest representable step at the boundary magnitude), the worst-of fold's promotion of one-Red over Greens, and the short-circuit-on-Red contract via a NaN-after-Red probe. Test deltas: scorecard lib 256 → 270 passing; clippy clean across both crates. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Christopher Bays <cmbays@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Currently, the matcher
//[rev-foo,rev-bar]~does not get selected by the regex. Change the matcher to include-.