Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
4d7544e
docs(platform-probes): record that the encoded row is the contract, a…
Sep 12, 2026
7689680
docs(platform-probes): correct two M2 items wrongly called unaffected…
Sep 12, 2026
0116197
docs(platform-probes): close M2 and re-sequence its leftovers into M4…
Sep 12, 2026
658a631
feat(platform-probes)!: publish each diagnostic as itself, not as a c…
Sep 12, 2026
5765fff
fix(platform-probes): assert the payload a substring used to discrimi…
Sep 13, 2026
ec6af09
feat(platform-probes)!: publish which counter disagreed
Sep 13, 2026
45cf0b0
docs(platform-probes): order M3.4 before M3.3, and record the review …
Sep 13, 2026
5b1d6fa
feat(platform-probes): assert the observation-to-verdict invariants o…
Sep 13, 2026
3a45150
feat(platform-probes)!: retire the prose oracle and re-aim the accoun…
Sep 13, 2026
77a83fc
feat(platform-probes)!: emit the row from a typed value through one w…
Sep 13, 2026
ba786ce
refactor(platform-probes): remove the last prose parsing from the tes…
Sep 13, 2026
1741fbf
docs(platform-probes): split DESIGN-NOTES into Tier 1 and Tier 2
Sep 13, 2026
bd45d63
docs(platform-probes): add the blank lines two moved headings inherited
Sep 13, 2026
5fc68d4
fix(platform-probes): make the row's key reader escape-aware
Sep 13, 2026
09da7e9
fix(probes): make four instruments as strong as their names claim
Sep 13, 2026
d6d3b41
fix(probes): make BlockingState::ALL exhaustive by construction
Sep 13, 2026
a60f99d
docs(platform-probes): re-plan M2.14 from writing rules to making the…
Sep 13, 2026
b5adbcd
test(platform-probes): add the sabotage manifest this crate lacked
Sep 13, 2026
89ff49b
docs: sabotage the claim, not the symptom, and record the sabotage
Sep 13, 2026
60e6675
fix(platform-probes)!: decide row well-formedness by a real parse
Sep 13, 2026
065042f
refactor(platform-probes): delete the last hand-written string scanners
Sep 13, 2026
a067783
docs(platform-probes): close M3 and archive it
Sep 13, 2026
d20556a
docs: give repository timestamps their offset
Sep 13, 2026
b54c3a0
docs(platform-probes): correct claims this branch's own later commits…
Sep 13, 2026
4afc212
fix(platform-probes): hold the NUMA counter to the invariant that nam…
Sep 13, 2026
6f57dd5
test(platform-probes): close the mutation survivors, and encode what …
Sep 14, 2026
2e63a3d
test(platform-probes): pin what the diagnostics publish into the row
Sep 14, 2026
7c9fb7d
fix(platform-probes): call out a diagnostic that describes itself as …
Sep 14, 2026
7e0c3d5
test(platform-probes): make two instruments enforce the names they carry
Sep 14, 2026
3135c09
test(ioring): escalate the in-flight handover width instead of only r…
Sep 14, 2026
3ed2723
fix(platform-probes): stop conflating uncollected coherence with disa…
Sep 14, 2026
e0a85ac
test: close the coverage and measurement gaps the latest review found
Sep 14, 2026
c266129
fix(platform-probes): define row() by check(), so the two cannot disa…
Sep 14, 2026
6ef80f7
fix(platform-probes): oblige every diagnostic variant to be exercised…
Sep 14, 2026
afa4a31
chore(ioring): name the completion-event requirement, so it fits wher…
Sep 14, 2026
28b2340
fix(platform-probes): rename assert_corresponds to what M3 left it doing
Sep 14, 2026
d523f2b
fix(platform-probes): close the remaining review findings, and narrow…
Sep 14, 2026
40ea4f3
feat(platform-probes): pin the row's value SHAPES, not just its key n…
Sep 14, 2026
80fe75d
docs(platform-probes): retire the "the key set is derivable" claim, w…
Sep 14, 2026
b68a124
fix(platform-probes): gate BOTH schema assertions, not just the first
Sep 14, 2026
399cc39
fix(platform-probes): check the whole diagnostic entry through the re…
Sep 14, 2026
af82a22
docs(platform-probes): note that `enumeration_anomalies` names a code…
Sep 14, 2026
0c4aced
fix(platform-probes): make the row's guarantees hold at every level, …
Sep 14, 2026
c1927a2
docs(platform-probes): put the supersedence marker where a reader mee…
Sep 14, 2026
c8f7e63
chore(ioring): record why the in-flight precondition holds, since a r…
Sep 14, 2026
a4a2f74
fix(platform-probes): make `keys` refuse a row the oracle rejects
Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -1195,6 +1195,28 @@ When you add such a predicate, **verify the binding by sabotage**: change the de
confirm the consumer's *behavior* changes. If only a test's expectation moves, or nothing moves,
the binding is cosmetic and the copy is still there.

**Sabotage the CLAIM, not the symptom.** When a change asserts that it *removed* a weakness — a
census eliminated, a check made exhaustive, a duplicate collapsed — the sabotage that matters is
the one that would falsify *that* assertion, which is rarely the same as the one that reproduces
the original symptom. This is the failure mode the rule above does not cover on its own: an author
who believes they derived a fact when they only **moved** the restatement will happily sabotage the
old site, watch it go red, and record the class as closed. Measured on one guard in
`windows-platform-probes`, three times in succession — strings, then a hand-written `ALL`, then
generation — each fix relocating the census somewhere harder to see while its commit message
claimed the class was closed, and each caught by a review rather than by its author. Ask what the
commit message asserts, then break *that*.

**A sabotage is worth nothing once it is discarded**, so record it where something re-runs it
rather than in a terminal you will close. Put it in the component's `sabotage.json` and sweep it
with [tools/run-sabotage.ps1](../tools/run-sabotage.ps1) — see
[tools/README-sabotage.md](../tools/README-sabotage.md) for the manifest format and for why a
manifest with no `expect: "survives"` control can only tell you the tests are sensitive, never that
they are sensitive to the right things. The harness is the authority on whether a patch site is
unique; do not re-implement that check beside it. This is not a preference: the `sabotage-harness`
CI job exists because eleven review rounds on that harness produced thirteen later defects
*introduced by earlier fixes*, "because every verification was a one-off command that was then
discarded and nothing re-checked an earlier guarantee."

Know the limit — but know that it is narrower than it first appears. **Sequencing rules
(ordering, bracket entry states, what may follow what) are not value-level, and are still
derivable**: define them once as a shared executable oracle — a state machine over the
Expand Down Expand Up @@ -1434,13 +1456,44 @@ step breakdowns described during planning.

When a group of related items is fully complete:
1. Move the completed group to `COMPLETED-CHECKLIST.md` in the same directory.
2. Prefix the moved block with a heading: `## Moved YYYY-MM-DD — <brief description of what was done>`.
2. Prefix the moved block with a heading:
`## Moved YYYY-MM-DD HH:MM:SS ±hh:mm — <brief description of what was done>`, taken from
`Get-Date -Format "yyyy-MM-dd HH:mm:ss zzz"`. Carry the offset, per "Timestamps carry their
offset" below; existing headings without one are fine and are not worth going back to change.
3. `COMPLETED-CHECKLIST.md` is **append-only**; always add new groups at the bottom.
4. Leave only the remaining pending or in-progress items in the source `CHECKLIST.md`.

Named feature files (`CHECKLIST-<feature>.md`) should be **deleted entirely** once all items are
complete. Move their content to `COMPLETED-CHECKLIST.md` in the same directory before deleting.

### Timestamps carry their offset

**When you write a date into a repository file, make it UTC or give it its offset.** This governs
`## Moved`, `## Resolved`, and the completed-item stamp. It costs a few characters and it is worth
them.

**This is a presentation concern, not a correctness one.** A timestamp with an offset is
self-describing: two readers in different zones, or one reader on a machine whose zone is set
wrongly, still agree on the instant it denotes. A bare local date leaves that to be inferred. Nothing
is *wrong* with a bare date — the event happened when it happened — it is just ambiguous in a way
that a few extra characters remove.

Note what the offset does and does not buy. It does **not** prevent a misconfigured machine from
writing a misleading date; it makes that date convertible afterwards. Worked example from this
repository: a laptop reporting `-04:00` while its owner sat in `-07:00` ran three hours fast, so
timestamps taken late in the evening carried the next day's date. Every affected commit was still
unambiguous, because git stores the instant with its offset — `2026-09-13T01:14:28-04:00` is exactly
`2026-09-12 22:14 -07:00`. A bare `2026-09-13` in a checklist was the only thing that had to be
re-derived from elsewhere.

- **Do not go back and repair bare dates already written**, and do not rewrite history to relabel an
offset. The instants are correct either way, the ambiguity is small, and rewriting changes every
hash — on the branch that prompted this, two tracked files cited commit hashes, one of them a
split's mandatory `Split from ... at <hash>` provenance line, and both would have dangled. Fix such
a date only when something visible actually depends on it.
- **`Get-Date` reports what the machine believes.** If its offset looks implausible for where the
engineer actually is, say so rather than quietly writing the date down.

## Design note files

Any directory in the repository may have a DESIGN-NOTES.md file.
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion PLANS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ plans tracker: [crates/windows-file-enumeration-sys/PLANS.md](crates/windows-fil
| [CHECKLIST-thread-ambient.md](CHECKLIST-thread-ambient.md) | in progress | M22-M23: extract the captured-context composite into `windows-thread-ambient-sys`, a standalone platform layer that captures a thread's ambient state and applies it on another thread. M24-M26: `windows-namespace-request-sys`, marshalable Win32 namespace call parameter sets, over a round-one entry list audited from three real consumers (this repository's watcher and enumeration crates, and `MikeGrier/Globazog-rs`) rather than guessed. M27: `windows-platform-probes`, a durable home for the measurements this workspace's designs rest on, under a three-tier scheme (asserted / ignored / binary-only) where every tier is compiled by an ordinary build. Feature-scoped and deleted when complete; it is the whole of the `mikegrier/thread-ambient` branch's work, and is deliberately separate from the deferred namespace-facility items in [CHECKLIST.md](CHECKLIST.md). | [crates/windows-thread-ambient-sys/DESIGN-NOTES.md](crates/windows-thread-ambient-sys/DESIGN-NOTES.md) |
| [crates/windows-overlapped-io-sys/CHECKLIST.md](crates/windows-overlapped-io-sys/CHECKLIST.md) | not started | M14: finish the contract audit -- categories 1, 2, 6, 8, 9 were not examined -- and sweep `outstanding()` for the advisory-predicate hazard. | [crates/windows-overlapped-io-sys/DESIGN-NOTES.md](crates/windows-overlapped-io-sys/DESIGN-NOTES.md) |
| [crates/windows-ioring-sys/CHECKLIST.md](crates/windows-ioring-sys/CHECKLIST.md) | in progress | Memory-safe Rust over the Windows `IoRing` submission/completion ring, as a new crate. M1-M7 (ring lifecycle through the `ring-copy` topology-aligned sample) are complete and archived. The parked, pinned-thread `M6+` work and the new M10 contract audit remain. | [crates/windows-ioring-sys/DESIGN-NOTES.md](crates/windows-ioring-sys/DESIGN-NOTES.md) |
| [crates/windows-platform-probes/CHECKLIST.md](crates/windows-platform-probes/CHECKLIST.md) | in progress | M1 (streaming reports) is done and archived: every probe now writes into the sink as it measures, through a `fmt::Write` adapter that left all 332 `writeln!` call sites untouched, and the `catch_unwind`/`resume_unwind` pair is gone because there is no longer a buffer to rescue. Measured with a control -- a probe killed 300 ms into a 0.8 s run keeps its banner and heading on six runs of six, where the previous build kept nothing on six of six. M2 remains: check correspondence *between* a report's parts, which is the defect class no per-part instrument in this crate can see. | [crates/windows-platform-probes/DESIGN-NOTES.md](crates/windows-platform-probes/DESIGN-NOTES.md#d-streaming-report) |
| [crates/windows-platform-probes/CHECKLIST.md](crates/windows-platform-probes/CHECKLIST.md) | in progress | M1 (streaming reports) is done and archived: every probe now writes into the sink as it measures, through a `fmt::Write` adapter that left all 332 `writeln!` call sites untouched, and the `catch_unwind`/`resume_unwind` pair is gone because there is no longer a buffer to rescue. Measured with a control -- a probe killed 300 ms into a 0.8 s run keeps its banner and heading on six runs of six, where the previous build kept nothing on six of six. M2 built the report oracle -- one executable definition of the correspondences between a report's prose and NDJSON halves, bound inside the renderers so every test that renders inherits it -- along with a derived fact set and a corpus of report shapes. It is complete; its ten unrelated leftovers -- CI hygiene, a doc repair, probe-prose corrections -- were re-sequenced into M4 (gated on M3) and M5 (gated on nothing). M3 then supersedes its central rule. Re-reading M2's own evidence showed that both defects which motivated the oracle were defects in the ENCODED ROW, not in the relation between two renderings, and that the row published its three diagnostic lists as bare counts -- so a survey reading `"parse_incomplete":1` could not tell a probe self-bug from host flakiness. The row is the machine contract and gets the facts and the invariants; the prose is for a reader and gets review. M3 is complete and archived (ten items): those three fields publish arrays of OBJECTS, each carrying a stable `code` plus the values its variant holds -- `{"code":"partitioning_summary_missing","level":9}` rather than the bare `"partitioning_summary_missing"` of the superseded M3.1 form; the surviving correspondences became invariants over the observation rather than over two renderings, so a rule that reads the diagnostic lists -- which would be a restatement of `verdict()` and blind to a deleted push site -- was rewritten to read the observation; the row is emitted from a typed value through one writer with total escaping, which is the crate's only defence against caller text reaching the mined artifact; the prose oracle and every parser serving it were deleted, and no test extracts structured data from prose anywhere in the crate. Four later items came from reviews and are the more instructive half: three instruments were found asserting less than their names claimed, `BlockingState::ALL` was found to be a census the compiler did not check despite a doc comment claiming it did, and the row's hand-written JSON well-formedness check was measured against a real parser over 1807 generated corruptions -- 159 disagreements, every one a FALSE accept -- and replaced by `serde_json`, after which the remaining hand-written string scanners were deleted too. What remains is M4 (four M2 leftovers M3 gated, now unblocked and re-scoped) and M5 (six ungated hygiene items). | [crates/windows-platform-probes/DESIGN-NOTES.md](crates/windows-platform-probes/DESIGN-NOTES.md#d-streaming-report), [#d-encoded-row-is-the-contract](crates/windows-platform-probes/DESIGN-NOTES.md#d-encoded-row-is-the-contract) |
| [CHECKLIST-mutation-survivors.md](CHECKLIST-mutation-survivors.md) | not started | Work queued from the workspace-wide cargo-mutants sweep of 2026-09-02, whose findings are kept in [mutation-sweeps/2026-09-02/](mutation-sweeps/2026-09-02/README.md) rather than re-derived -- the run took roughly fourteen hours. 2,792 caught, 1,112 survived, 198 timed out. **The headline numbers mislead in three ways and the README says how**: a timeout in a blocking-API crate is usually a detection that lost its name rather than a gap (measured: one of `windows-waitable-queues`' 120 timeouts fails four tests in 0.00s when re-injected alone), a low score on an executable probe crate is measuring the wrong thing, and three kinds of survivor -- equivalent mutants, unreachable code, and constants that want a `const` assertion -- are not missing tests at all. M1 covers the shipping crates; M2 holds the two crates that are not libraries and whose scope is an engineer's decision; M3 re-runs and prunes rather than hand-editing the tool's output into a second source of truth. | [mutation-sweeps/2026-09-02/README.md](mutation-sweeps/2026-09-02/README.md) |

Add a row here when new work is planned, against [CHECKLIST.md](CHECKLIST.md) or any crate's.
Loading