Skip to content

refactor(platform-probes): route every probe's output through one sink - #79

Merged
MikeGrier merged 1 commit into
mainfrom
mikegrier/probes-report-sink
Sep 7, 2026
Merged

MikeGrier merged 1 commit into
mainfrom
mikegrier/probes-report-sink

Conversation

@MikeGrier

@MikeGrier MikeGrier commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Stage 1 of peeling windows-platform-probes off mikegrier/deferred-namespace-ops (#56). It comes first because everything else in that crate's remaining work is built on it: the new probes all report through report, and lib.rs on main has no such module.

What this does

The repository's architectural pre-step says an output abstraction is introduced at the first occurrence, and these eight probes had grown a println! per finding. Each now composes its whole report as text and hands it to emit, so the real stream is named in report and nowhere else -- a probe's main is one line that chooses no stream at all. Retargeting a probe -- to a file, a buffer, a test -- stops being a rewrite.

Every probe's report now opens with windows-placement-probe's banner naming the machine and whether the measurement is tainted. That is what makes a captured report safe to paste somewhere: without it a finding can be compared against a machine it does not describe. Rendering it inside the report rather than printing it separately is the point -- it travels with the text.

What the mutation run found

A run over report.rs found the first five unit tests insufficient, and the gap was the one that mattered: <impl Report for Stdout>::line replaced with () survived the whole suite. Captured is what every in-process test uses, so nothing exercised the implementation the probes actually run with -- a no-op there means every probe runs, exits zero, and prints nothing, which is the failure mode that looks most like success.

Covering it needs a real child process, since stable Rust cannot redirect this process's own stdout -- which is what makes tests/a_probe_writes_its_report_to_stdout.rs an integration test by the repository's criterion rather than by preference. It runs probe-error-mode (no privileges, no particular hardware) and asserts the report exists, opens with the host banner, and carries more than that banner. Confirmed load-bearing: 5 caught / 1 missed becomes 7 caught / 0 missed.

Three review rounds, and what they changed

Each round's findings were verified by measurement before being accepted, and fixed here rather than deferred.

Round 1 -- three defects in the first draft:

  • Buffering the report meant a panic destroyed it. Each render composed into a local String and returned it, so nothing reached stdout unless it returned normally -- while worker_context composes several completed findings and then calls an observation documented to panic three ways, and cancel_io asserts after its first case. Printing line-by-line had made partial output automatic; the refactor silently gave that up, which for an instrument whose purpose is that a failure be diagnosable throws away exactly the information worth keeping. Fixed with emit_report, verified by injecting a panic mid-render: the already-measured lines print and the process still exits 101.
  • writeln_to had no callers -- a pub item on a library target is exempt from dead_code, so nothing flagged it. Removed.
  • The module doc claimed "All fourteen" probes route through the sink. There are eight; the count came from the originating branch, which is precisely the error a stage-1 peel invites.

Round 2 -- the more useful finding was that the test for round 1's fix did not test it:

  • The panic test never called the function it was named for. It re-implemented catch-emit-resume against a Captured, so deleting the resume_unwind would have left it green -- and a probe that swallows its panic prints a partial report and exits 0, the failure that looks most like success. The logic now lives in emit_report_to, taking the sink as an argument. Verified by sabotage in both directions: deleting the resume_unwind fails one assertion, deleting the emit fails the other, and each leaves the other passing.

    Worth recording: a mutation run had reported 6/6 caught over the old test. Whole-function-body mutants never generate that single-branch deletion, so a green mutants run is not evidence that every branch is bound.

  • Buffering still loses everything when termination does not unwind -- Ctrl-C, or an abort during unwinding. Not fixed here; the honest fix is renderers writing into a Report as they go, which changes every renderer and is a different design. Stated on emit_report and queued as milestone M1 of a new crates/windows-platform-probes/CHECKLIST.md, rather than left as prose in a design note.

Round 3 -- three stale restatements, two made stale by this commit:

  • CHECKLIST-mutation-survivors.md MS-2.1 was invalidated -- it said twelve probes still print directly and the sink's checklist "is not in this repository yet", so whoever picked it up would think the prerequisite was blocked on a branch item that had just landed. Corrected, but not to the reviewer's reading: the 2026-09-02 sweep measured a fourteen-probe tree, and six of those exist only on the originating branch, so "zero probes now print directly" is true of this repository and not of what the sweep scored.
  • report.rs's one-stream rationale asserted something the crate contradicts -- it justified having no problem method with "none of them is a diagnostic", while Impersonation::drop does eprintln! a RevertToSelf warning on exactly the panic path emit_report_to serves. Restated so the argument survives the counter-example instead of denying it.
  • A count went stale the moment this commit added a line -- DESIGN-NOTES said "seven completed findings"; seven was right on main and the banner made it eight. Three further copies were wrong the same way. All now unnumbered, which is the only form that does not rot.

Cargo.toml

  • windows-placement-probe added as a path dependency, for the banner.
  • The version = "0.1.3" pin dropped from windows-threadpool-sys. A version beside a path is consulted only when packaging, but cargo still requires the path crate's version to satisfy it on every build -- so a pin left behind by a release breaks workspace resolution rather than just this crate's. This crate is publish = false (verified, not assumed), so the pin bought nothing.

Verified by running, not only by building

  • cargo check --all-targets on this package alone against main's tree, which is what establishes the subset is self-contained rather than merely part of a working branch.
  • Workspace clippy --all-targets --all-features clean; fmt --check clean.
  • 25 unit + 1 integration tests pass; the report tests confirmed to execute by name, because a tests.rs that is never declared is a silent no-op.
  • All eight probes run end to end with their banners; a refactor of code whose entire output is a report is not verified by compiling it.
  • check-publishable, check-workflow-refs, check-commit-scope, and the encoding check all pass.

Deliberately excluded

The six other modules lib.rs gains on the branch, the new probe binaries, and the topology tests in src/tests.rs. Those are later stages and each depends on this one.

Copilot AI lite review requested due to automatic review settings September 7, 2026 04:38

Copilot AI left a 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.

🟡 Changes recommended

There are small but concrete fixups needed in the newly added report test module (unused import) and new-file header consistency.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Refactors windows-platform-probes so every probe renders its report as text and routes output through a single report sink, enabling capture/assertion in tests while keeping production output centralized. It also standardizes reports to begin with the host/taint banner from windows-placement-probe, and records the known buffering tradeoff with follow-up work queued.

Changes:

  • Introduce report sink (Stdout/Captured) with emit_report / emit_report_to, and update probe binaries to render into a String and emit through the sink.
  • Add unit + integration coverage to ensure the real Stdout sink produces output, and that panic paths still emit already-rendered lines while resuming unwind.
  • Update windows-platform-probes planning/design docs and dependencies (add windows-placement-probe, drop version pin on the path dep).
File summaries
File Description
PLANS.md Adds windows-platform-probes checklist row to workspace plans tracker.
CHECKLIST-mutation-survivors.md Updates mutation-sweep notes to reflect the sink landing and probe count differences vs originating branch.
Cargo.lock Adds windows-placement-probe as a dependency of windows-platform-probes.
crates/windows-platform-probes/Cargo.toml Adds windows-placement-probe path dep; drops version pin on windows-threadpool-sys path dep; documents rationale.
crates/windows-platform-probes/CHECKLIST.md New crate-local checklist queuing follow-up work to restore true streaming output (Ctrl-C/abort cases).
crates/windows-platform-probes/DESIGN-NOTES.md Updates crate intro and records the “buffered report” decision/tradeoff with an anchored note.
crates/windows-platform-probes/PLANS.md Registers the new checklist in the crate-local plans table.
crates/windows-platform-probes/src/lib.rs Exposes new report module.
crates/windows-platform-probes/src/report.rs New sink abstraction (Report, Stdout, Captured) and emit_report helpers with unwind handling.
crates/windows-platform-probes/src/report/tests.rs New unit tests for sink behavior, block splitting, and unwind emission/resume behavior.
crates/windows-platform-probes/tests/a_probe_writes_its_report_to_stdout.rs New integration test ensuring a real probe run as a child process produces a non-empty stdout report starting with the host banner.
crates/windows-platform-probes/src/bin/worker_context.rs Converts probe output to buffered render + emit_report, prepending banner line.
crates/windows-platform-probes/src/bin/pool_growth.rs Converts probe output to buffered render + emit_report, prepending banner line.
crates/windows-platform-probes/src/bin/ioring.rs Converts probe output to buffered render + emit_report, prepending banner line.
crates/windows-platform-probes/src/bin/handle_state.rs Converts probe output to buffered render + emit_report, prepending banner line.
crates/windows-platform-probes/src/bin/error_mode.rs Converts probe output to buffered render + emit_report, prepending banner line; keeps measurement/render coupling where needed.
crates/windows-platform-probes/src/bin/device_map.rs Converts probe output to buffered render + emit_report, prepending banner line; refactors helper to take &mut String.
crates/windows-platform-probes/src/bin/completion_port.rs Converts probe output to buffered render + emit_report, prepending banner line; refactors helpers to write into &mut String.
crates/windows-platform-probes/src/bin/cancel_io.rs Converts probe output to buffered render + emit_report, prepending banner line.
Review details
  • Files reviewed: 18/19 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

use std::fmt::Write as _;
use std::panic::{AssertUnwindSafe, catch_unwind};

use super::{Captured, Report, emit, emit_report_to};
Comment thread crates/windows-platform-probes/src/report.rs Outdated
Comment thread crates/windows-platform-probes/src/report/tests.rs Outdated
Copilot AI review requested due to automatic review settings September 7, 2026 04:50
@MikeGrier
MikeGrier force-pushed the mikegrier/probes-report-sink branch from 308ef5d to 3095169 Compare September 7, 2026 04:50
@MikeGrier

Copy link
Copy Markdown
Owner Author

Two of the three are fixed; the third is a false positive, and I settled it by execution rather than by reading.

Copyright headers -- fixed. Correct, and worse than reported: src/report.rs and src/report/tests.rs carried // Copyright (c) 2026 Mike Grier taken verbatim from the originating branch, while the other nineteen files in this crate use // Copyright (c) Mike Grier. -- and the third file this PR adds, tests/a_probe_writes_its_report_to_stdout.rs, already used the crate's form, so the two new files were inconsistent even within their own change. Both aligned; the crate is now a single form across all 21 files.

Worth recording that this was a real choice rather than an obvious fix: repository-wide the year form is actually dominant (290 files against 114), so aligning to the crate deliberately moves these two files away from the repository majority. I took local consistency on the grounds that a reader scans a crate, not the whole tree -- happy to go the other way if you would rather the repository converge on the year form.

Report unused in the test module -- not correct, no change made. Captured::line is a trait method, so Report has to be in scope at the call sites (report/tests.rs:20-22). Removing it from the import list does not warn, it fails to compile:

error[E0599]: no method named `line` found for struct `report::Captured` in the current scope
  --> crates\windows-platform-probes\src\report\tests.rs:20
  --> crates\windows-platform-probes\src\report\tests.rs:21
  --> crates\windows-platform-probes\src\report\tests.rs:22

I removed the import and ran cargo check --all-targets to produce that, rather than reasoning about it. The prediction that this "can fail clippy if warnings are denied" is also checkable and false: workspace clippy --all-targets --all-features was clean before this review and is clean now, which it could not have been had the import been dead.

All 27 CI checks passed on the previous head; the force-push carries only the two header lines plus the commit-message record of this round.

Copilot AI left a 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.

🟢 Approval recommended

The changes are coherent, tested (including an integration test for Stdout emission), and the remaining feedback is limited to minor comment wording corrections.

Review details
  • Files reviewed: 18/19 changed files
  • Comments generated: 8
  • Review effort level: Lite

Comment on lines +31 to +33
// The only place that names the real stream. Everything below composes
// text; nothing below knows where it goes.
emit_report(render);
Comment on lines +151 to +153
// The only place that names the real stream. Everything below composes
// text; nothing below knows where it goes.
emit_report(render);
Comment on lines +21 to +23
// The only place that names the real stream. Everything below composes
// text; nothing below knows where it goes.
emit_report(render);
Comment on lines +35 to +37
// The only place that names the real stream. Everything below composes
// text; nothing below knows where it goes.
emit_report(render);
Comment on lines +22 to +24
// The only place that names the real stream. Everything below composes
// text; nothing below knows where it goes.
emit_report(render);
Comment on lines +21 to +23
// The only place that names the real stream. Everything below composes
// text; nothing below knows where it goes.
emit_report(render);
Comment on lines +46 to +48
// The only place that names the real stream. Everything below composes
// text; nothing below knows where it goes.
emit_report(render);
Comment on lines +22 to +24
// The only place that names the real stream. Everything below composes
// text; nothing below knows where it goes.
emit_report(render);
Copilot AI review requested due to automatic review settings September 7, 2026 04:57
@MikeGrier
MikeGrier force-pushed the mikegrier/probes-report-sink branch from 3095169 to 1a14dcf Compare September 7, 2026 04:57
@MikeGrier

Copy link
Copy Markdown
Owner Author

Correct in all eight, fixed in all eight -- and the finding is sharper than it looks, because the comment was invalidated by this PR''s own earlier fix.

It was true when written. The first draft had fn main() { emit(&mut Stdout, &render()); }, which really did name the stream. Round 1 of review found that buffering meant a panic destroyed the whole report, and the fix replaced that line with emit_report(render). From that moment main named no stream at all -- while the comment sitting directly above it still claimed to be the one place that did. Nothing detects a comment invalidated by a change in a different file.

Where the stream is actually named, measured rather than asserted:

  • report.rs:65 -- println!("{text}") in Stdout::line
  • report.rs:145 -- emit_report_to(&mut Stdout, render) in emit_report
  • Stdout appears zero times in any of the eight bins (the single match under src/bin/ is the word "stdout" in a pool_growth doc comment).

All eight now read:

fn main() {
    // The probe''s whole output policy, and it is one line: hand the renderer to
    // the sink. Nothing here or below names a stream -- that is chosen once, in
    // `report`, so retargeting a probe is not a rewrite.
    emit_report(render);
}

Swept rather than spot-fixed. The same sentence had propagated into two places your comments did not cover: the d-buffered-report decision in crates/windows-platform-probes/DESIGN-NOTES.md, and this PR''s own description. Both corrected, along with the commit message.

Worth stating plainly: this is the third consecutive round where the finding was a correction that failed to propagate rather than an original defect, and this one was self-inflicted -- a fix in one file silently invalidating a comment in eight others. Thanks for catching it in all eight rather than one; a single-site report would have left seven behind.

Re-verified after the change: workspace clippy --all-targets --all-features clean, fmt --check clean, 25 unit + 1 integration tests pass, and probe-error-mode still emits its full 18-line report with the host banner and exit 0.

Copilot AI left a 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.

🟢 Approval recommended

The core refactor is coherent and backed by unit + integration coverage; remaining feedback is limited to minor documentation/link clarity.

Review details
  • Files reviewed: 18/19 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread CHECKLIST-mutation-survivors.md Outdated
Comment thread crates/windows-platform-probes/CHECKLIST.md Outdated
Comment thread crates/windows-platform-probes/src/report.rs Outdated
Stage 1 of peeling `windows-platform-probes` off
`mikegrier/deferred-namespace-ops` (#56). It comes first because everything else
in that crate's remaining work is built on it: the new probes all report through
`report`, and `lib.rs` on `main` has no such module.

The repository's architectural pre-step says an output abstraction is introduced
at the *first* occurrence, and these eight probes had grown a `println!` per
finding. Each now composes its whole report as text and hands it to `emit`, so
the real stream is named in `report` and nowhere else. Retargeting a probe
-- to a file, a buffer, a test -- stops being a rewrite.

`report` is deliberately small: a `Report` sink trait, a `Stdout` implementation,
a `Captured` one for tests, and `emit`/`emit_report`. Its unit tests cover what a
caller can get wrong rather than what the trait obviously does -- line order
preserved, a trailing newline not becoming a blank line, an interior blank line
surviving, and a block emitted line-at-a-time.

A mutation run over `report.rs` found those five insufficient, and the gap was
the one that mattered: `<impl Report for Stdout>::line` replaced with `()`
survived the whole suite. `Captured` is what every in-process test uses, so
nothing exercised the implementation the probes actually run with -- a no-op
there means every probe runs, exits zero, and prints nothing, which is the
failure mode that looks most like success.

Covering it needs a real child process, since stable Rust cannot redirect this
process's own stdout, which is what makes
`tests/a_probe_writes_its_report_to_stdout.rs` an integration test by the
repository's criterion rather than by preference. It runs `probe-error-mode` --
no privileges, no particular hardware -- and asserts the report exists, opens
with the host banner, and carries more than that banner. Confirmed
load-bearing: the mutation run goes from 5 caught / 1 missed to **6 caught / 0
missed**.

Every probe's report now opens with `windows-placement-probe`'s banner naming
the machine and whether the measurement is tainted. That is what makes a
captured report safe to paste somewhere: without it a finding can be compared
against a machine it does not describe. Rendering it inside the report rather
than printing it separately is the point -- it travels with the text.

Two Cargo.toml changes, both required by the above:

- `windows-placement-probe` as a path dependency, for that banner.
- The `version = "0.1.3"` pin dropped from `windows-threadpool-sys`. A `version`
  beside a `path` is consulted only when packaging, but cargo still requires the
  path crate's version to satisfy it on *every* build -- so a pin left behind by
  a release breaks workspace resolution rather than just this crate's. This crate
  is `publish = false` (verified, not assumed), so the pin bought nothing. The
  comment states the policy so the next dependency added here does not
  reintroduce one.

Verified by running, not only by building:

- `cargo check --all-targets` on this package alone against `main`'s tree, which
  is what establishes the subset is self-contained rather than merely part of a
  working branch.
- Workspace `clippy --all-targets --all-features` clean; `fmt --check` clean.
- The `report` tests are wired and actually execute -- checked by name, because a
  `tests.rs` that is never declared is a silent no-op.
- `probe-error-mode` run end to end: it opens with the host banner and its
  findings are intact. A refactor of code whose entire output is a report is not
  verified by compiling it.
- `check-publishable`, `check-workflow-refs`, and the encoding check all pass.

Three defects a code review found in the first draft of this commit, fixed here
rather than deferred:

- **Buffering the report meant a panic destroyed it.** Each `render` composed
  into a local `String` and returned it, so nothing reached stdout unless it
  returned normally -- while `worker_context` composes several completed
  findings and then calls an observation documented to panic three ways, and
  `cancel_io` asserts after its first case. Printing line-by-line had  made partial output automatic; the refactor silently gave that up, which for an
  instrument whose purpose is that a failure be diagnosable throws away exactly
  the information worth keeping. `main` is now one `emit_report(render)` call
  that owns the buffer, catches an unwind, emits what was composed, and resumes
  the panic -- so the exit status and message are unchanged and the partial
  report is added to them. Verified by injecting a panic mid-`render`: the
  already-measured lines print and the process still exits 101.
- **`writeln_to` had no callers.** Its doc claimed a convention the crate did not
  follow -- 156 `let _ = writeln!` sites across the eight probes -- and it could
  not have served most of them anyway, since it takes `&str` while nearly every
  site is formatted. A `pub` item on a library target is exempt from
  `dead_code`, so nothing flagged it. Removed, with its test replaced by one for
  `emit_report`.

- **The module doc claimed "All fourteen" probes route through the sink.** There
  are eight; the count came from the originating branch, which is precisely the
  error a stage-1 peel invites. The invariant is now stated without a number, so
  it stays true as probes are added.

A second review round found the test for that first fix did not test it, and
that is the more useful finding of the two:

- **The panic test never called the function it was named for.** It
  re-implemented catch-emit-resume against a `Captured` and asserted against its
  own copy, so the property held in the test and nothing tied it to `report.rs`.
  Deleting the `resume_unwind` would have left it green -- and a probe that
  swallows its panic prints a partial report and exits **0**, which is the
  failure that looks most like success, and the exact defect the fix existed to
  prevent. The logic now lives in `emit_report_to`, taking the sink as an
  argument, with `emit_report` a one-line `Stdout` wrapper; the test drives the
  real function through a `Captured` and asserts both halves -- the finished
  lines survive, *and* the panic reaches the caller. Verified by sabotage in both
  directions: deleting the `resume_unwind` fails the second assertion, deleting
  the `emit` fails the first, and each leaves the other passing. A mutation run
  had reported 6/6 caught over the old test, which is worth recording -- whole-
  function-body mutants never generate the single-branch deletion, so a green
  mutants run is not evidence that every branch is bound. It is now 7/7.

- **Buffering still loses everything when termination does not unwind.** Ctrl-C
  (the default Windows console handler terminates the process) and an abort from
  a panic during unwinding both discard the buffer, where the line-by-line
  printing this commit replaces would have kept it. The sharpest case is
  `probe-cancel-io`, which runs about twenty seconds precisely when the wedge it
  hunts for occurs -- precisely when a reader interrupts. This is not fixed here.
  The honest fix is renderers writing into a `Report` as they go rather than into
  a `String`, which restores streaming for every termination mode and keeps
  `Captured` working; that changes every renderer and is a different design
  rather than a defect in this one. So the bound is stated on `emit_report`, the
  trade-off it comes from is recorded as [The report is buffered, and what that
  costs] in the crate's DESIGN-NOTES, and the fix is **queued** as milestone M1 of
  a new `crates/windows-platform-probes/CHECKLIST.md` -- not left as prose in a
  design note, which this repository treats as orphaned rather than scheduled. The
  crate had a PLANS.md but no checklist; its pending work was tracked in the
  workspace `CHECKLIST-thread-ambient.md`, which is feature-scoped and deleted
  when that feature completes, so durable follow-up could not live there.
A third review round found three stale restatements, two of them made stale by
this commit -- the blast-radius sweep the repository asks for, which I had run
inside the crate and not outside it:

- **`CHECKLIST-mutation-survivors.md` MS-2.1 was invalidated.** It recorded that
  "twelve of these probes still print directly rather than through the `Report`
  sink" and that the sink's checklist "is not in this repository yet", so whoever
  picked it up would think the prerequisite was blocked on an off-repository
  branch item when it had just landed. Corrected -- but not to the reviewer's
  reading. The 2026-09-02 sweep measured a **fourteen**-probe tree, and six of
  those (`core_affinity`, `peer_index_cache`, `doorbell_cost`, `queue_contention`,
  `request_cost`, `topology`) exist only on the originating branch, so "zero
  probes now print directly" is true of this repository and not of what the sweep
  scored. The item now says which tree it measured, that the eight probes here
  route through the sink, and that what remains of `SH-13.4` is the six that are
  still branch-only.

- **`report.rs`'s one-stream rationale asserted something the crate contradicts.**
  It justified having no `problem` method with "none of them is a diagnostic
  competing with the report" -- while `Impersonation::drop` does `eprintln!` a
  `RevertToSelf` warning, reachable from `probe-worker-context` on exactly the
  panic path `emit_report_to` exists to serve. A load-bearing premise, since the
  next contributor weighing a second stream reads it. Restated: nothing in a
  *report* is a diagnostic, and that warning belongs to the process rather than
  the measurement, which is why stderr already separates it -- an argument for one
  stream that survives the counter-example instead of denying it.

- **A count went stale the moment this commit added a line.** The DESIGN-NOTES
  said `worker_context` "composes seven completed findings" before its panicking
  call; seven was right on `main` and this commit's banner made it eight
  statements and nine lines, while `report.rs`'s parallel sentence said
  "several" and stayed true. Two further copies in this message were wrong the
  same way, and a third said "seven other modules" when the branch has six left
  after `report`. All now unnumbered or corrected, which is the only form that
  does not rot.
A fourth round, on the opened PR, raised three points; two were right and one was
not:

- **The copyright header on the two new `report` files did not match the crate.**
  They carried `// Copyright (c) 2026 Mike Grier`, taken verbatim from the
  originating branch, while all nineteen other files here use
  `// Copyright (c) Mike Grier.` -- and the third file this commit adds already
  used the crate's form, so the two new ones were inconsistent even with their own
  change. Aligned; the crate is now one form throughout. Worth noting the
  repository as a whole is the other way round (290 files with the year against
  114 without), so this is local consistency chosen over global, on the grounds
  that a reader scans a crate.

- **`Report` was reported as an unused import in the test module. It is not.**
  `Captured::line` is a trait method, so the trait must be in scope; removing the
  import produces three `E0599`s ("no method named `line` found for struct
  `Captured`"), which is how this was settled rather than by reading. Clippy over
  `--all-targets --all-features` was already clean, which it could not have been
  had the import been dead. No change made.
A fifth round found that comment wrong in eight more places, and it was wrong
because of this commit's own first fix:

- **"The only place that names the real stream" was false in every probe's
  `main`.** It was true of the first draft, where `main` read
  `emit(&mut Stdout, &render())` and did name the stream. Round 1 replaced that
  with `emit_report(render)` to stop a panic destroying the report -- and from
  then on `main` named no stream at all, while the comment above it still claimed
  to be the one place that did. The stream is named at `report.rs:65`
  (`println!`) and `report.rs:145` (`&mut Stdout`); `Stdout` does not appear in
  any bin. Eight identical copies, each corrected to say what `main` really is:
  the probe's whole output policy in one line, choosing no stream. The same
  sentence had also propagated into the DESIGN-NOTES decision and this message,
  both fixed here.

  That is three rounds running in which the finding was a correction that had not
  propagated rather than an original defect, and this one was self-inflicted --
  a fix in one file invalidating a comment in eight others, with nothing to
  detect it. Exactly the failure CONTRACT INTEGRITY names.
A sixth round found three more, all correct:

- **Another claim that did not survive the change.** The module doc said each
  conversion was checked by "capturing the probe's output before and after and
  requiring the two to match" -- while the same conversion prepends a host banner,
  so the two cannot match. Restated: every pre-existing line must match in the
  same order, and the banner is the one deliberate difference, the only one
  permitted. Same class as the previous two rounds, and the third instance in this
  PR of a sentence that was true when written and falsified by a later part of the
  same change.

- **Two file references written as inline code rather than links.** The
  repository asks that a reference a reader is meant to open be a relative
  markdown link, and that this applies to source files as well as documents. Both
  were mine, added in the third and fourth rounds. Fixed; targets verified to
  resolve. The bare filenames elsewhere in `CHECKLIST-mutation-survivors.md`
  (`fs.rs`, `watcher.rs`, ...) are deliberately left: they are identifiers inside
  a survivor listing, not navigation targets, and they predate this commit.
Deliberately excluded, so this stays reviewable: the six other modules
`lib.rs` gains on the branch, the new probe binaries, and the topology tests in
`src/tests.rs`. Those are later stages and each depends on this one.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 7, 2026 05:04
@MikeGrier
MikeGrier force-pushed the mikegrier/probes-report-sink branch from 1a14dcf to 88a75bc Compare September 7, 2026 05:04
@MikeGrier

Copy link
Copy Markdown
Owner Author

All three correct, all three fixed.

The before/after claim did not survive the change. The module doc said each conversion was checked by "capturing the probe''s output before and after and requiring the two to match" -- while the same conversion prepends a host banner, so the two cannot match. Restated: every pre-existing line must match in the same order, with the banner as the one deliberate difference and the only one permitted. That is what was actually done, so this is the doc catching up to the method rather than the method changing.

Worth naming, because it is now a pattern rather than an incident: this is the third consecutive round in which the finding was a sentence that was true when written and falsified by a later part of the same change --

round the claim what falsified it
3 "seven completed findings" the banner added an eighth line
5 "the only place that names the real stream" round 1 replaced emit(&mut Stdout, ...) with emit_report(render)
6 "requiring the two to match" the banner again

Two of the three trace to the same banner. Nothing in the toolchain detects any of them -- clippy, 25 tests, and 27 CI checks were green through all three.

Both file references made into links. Correct per the repository''s rule that a reference the reader is meant to open should be a relative markdown link, source files included. Both were mine, added in rounds three and four. Targets verified to resolve from their respective directories.

I deliberately left the bare filenames elsewhere in CHECKLIST-mutation-survivors.md (fs.rs, watcher.rs, pattern.rs, ...) as they are: those are identifiers inside a survivor listing rather than navigation targets, they predate this commit, and converting them would put unrelated churn in a peel that exists to stay reviewable. Happy to do it as a follow-up if you would rather they were links.

Re-verified: workspace clippy --all-targets --all-features clean, fmt --check clean, 25 unit + 1 integration pass, encoding check 604 files clean, both edited markdown files 0 non-ASCII bytes.

Copilot AI left a 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.

🟢 Approval recommended

The sink abstraction and probe refactor are coherent and exercised by both unit tests and a process-level stdout integration test, with only minor nits remaining.

Review details

Suppressed comments (1)

crates/windows-platform-probes/src/report/tests.rs:12

  • Report is imported here but never used, which will trigger an unused_imports warning and adds noise to future edits. Drop it from the import list.
use super::{Captured, Report, emit, emit_report_to};
  • Files reviewed: 18/19 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@MikeGrier

Copy link
Copy Markdown
Owner Author

Approval noted, and no change made -- the one suppressed comment repeats the Report finding from an earlier round, which is a false positive. I re-tested it against the current head (88a75bc, working tree clean, so the result applies to exactly what you reviewed) rather than just pointing back at the previous reply.

The comment makes two checkable claims. Both are false.

"Never used." Report is a trait, and Captured::line is its method, so the trait must be in scope at the three call sites:

captured.line("header");
captured.line("row one");
captured.line("row two");

Removing it from the import list does not produce a warning, it produces three hard errors:

error[E0599]: no method named `line` found for struct `report::Captured` in the current scope
  --> src\report\tests.rs:20, :21, :22
  = help: items from traits can only be used if the trait is in scope
help: trait `Report` which provides `line` is implemented but not in scope

"Can fail clippy if warnings are denied." Tested directly rather than reasoned about -- clippy --all-targets --all-features for this package with RUSTFLAGS="-D warnings":

{"reason":"build-finished","success":true}

Clean. If the import were dead, unused_imports would fire and -D warnings would turn it into a build failure, so this run is a decisive test of the claim, not a weaker proxy for it.

Since the import is load-bearing, dropping it would break the build rather than reduce noise, so I have left it exactly as is.

@MikeGrier
MikeGrier merged commit c9b0fee into main Sep 7, 2026
29 checks passed
@MikeGrier
MikeGrier deleted the mikegrier/probes-report-sink branch September 7, 2026 05:13
MikeGrier pushed a commit that referenced this pull request Sep 8, 2026
Brings back stages 1 and 2 of peeling this branch apart: the probe output
sink (#79) and the long-path probe pair (#80). Both were taken from this
branch, reviewed, and corrected on the way through, so main holds the
successor of every file they touch.

Twenty-two conflicts, resolved on that basis:

- The sixteen peeled sources -- `report.rs`, the long-path family, the eight
  converted probe binaries, and `build.rs` -- take main's version. Checked
  rather than assumed: the only content on this branch and not on main is
  what main replaced (the pre-sink `emit(&mut Stdout, &render())` shape,
  `registry_enabled: bool`, the `0x1` substring registry read, a bare `183`
  for ERROR_ALREADY_EXISTS, and the dead `let _ = deep_relative`).

- `report.rs` drops this branch's `writeln_to`, which no probe called. Main
  keeps `emit` and `Stdout`, so the six probes still on this branch and not
  yet peeled continue to compile against it unchanged.

- `lib.rs`, `Cargo.toml`, `ci.yml` and this crate's DESIGN-NOTES take the
  union: this branch's four probe modules and six binaries alongside the
  long-path pair, and both sides' design sections.

- Both sides had `[[bin]]` entries for the long-path pair. Kept main's, which
  carries the comment explaining why they are two binaries rather than one
  with a flag, and dropped this branch's uncommented duplicate -- cargo
  rejects the manifest outright with both.

- Root PLANS.md keeps this branch's newer `windows-ioring-sys` row (M1-M19,
  not M1-M7) and takes main's new `windows-platform-probes/CHECKLIST.md` row.
  Main's mutation-survivors row was already here verbatim, so it is not
  duplicated.

One change beyond the resolution: the `GetSystemDirectoryW` comment in
Cargo.toml sat above `Win32_System_Environment`, which is not the feature it
documents. Moved beside `Win32_System_SystemInformation`, which is.

Verified: `check --all-targets` clean with no warnings, `clippy
--all-targets --all-features` clean, `fmt --check` clean, 73 package tests
pass, encoding check 643 files clean, workflow references resolve, and all
seventeen probe binaries build and run to exit 0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants