Skip to content

Commit bc44b93

Browse files
committed
docs: close the negative-fixture record gap, and correct a claim I asserted rather than measured
The todo queue is empty and every blocked ticket was swept last turn, so this turn verified the repository's own declared invariants instead. Two were clean and two records were wrong. CLEAN: the version-seam ODR guard and the module-boundary validator both pass (41 modules / 93 edges). CORRECTION 1 — a false statement I introduced yesterday. §22.4 of NegativeConsumerFixtureValidation.md claimed the fixtures added since #2054 "were each recorded in their own ticket's migration note rather than here, so the record exists". That was asserted, not measured, and it is false: audited by grepping docs/ for every fixture filename, 17 of 45 had NO record in docs/ at all. The first pass of that audit was also misleading in the alarming direction: it searched for each FILENAME inside ticket text and reported eight fixtures as having no ticket record either. That was an artefact -- tickets describe their fixture without naming its file. Reading each fixture's own header instead shows all 45 name a real ticket, so there are NO orphans. The gap was never traceability; it was this document's coverage. It is now closed rather than merely reported: §22.4 carries a table of the 17 with their tickets and subjects, and the audit re-runs at 0 fixtures without a docs/ record. CORRECTION 2 — CollectionVersionTestSeamDesign.md records 2 seams / 17-18 definitions throughout; the checker reports 3 / 20. A third seam, KeyMaterialAccess, was added after that document's last revision. The historical figures are NOT retro-edited -- each was accurate when made -- so a dated current-state section is appended instead. CLAUDE.md requires both guards for every seam, and the audit confirms the third has both: the ODR checker and security_cryptography_key_material_negative.cpp, which cites the requirement in its own header. Only the document's arithmetic fell behind, not the enforcement. Docs only; no code changed, so the gate is unaffected at 17,585.
1 parent cbad0fb commit bc44b93

2 files changed

Lines changed: 83 additions & 5 deletions

File tree

docs/CollectionVersionTestSeamDesign.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,3 +870,41 @@ production, ABI, layout, or semantic impact, and without a new SR-AUD identifier
870870
(audit numbering stays frozen at 364). It does **not** broaden the checker into a
871871
general repository ODR analyser — its remit remains the two named seams'
872872
definition ownership, now including their primary templates.
873+
874+
---
875+
876+
## Current state, re-measured 2026-08-19
877+
878+
**The figures throughout this document are 2 seams / 17–18 definitions. The checker now reports
879+
3 seams / 20 definitions.** The earlier figures are *not* corrected in place: each describes a run
880+
that was accurate when it was made, and this repository does not retro-edit historical
881+
measurements.
882+
883+
```
884+
OK: test-only access seams have one definition each (3 seam(s), 20 specialisation definition(s))
885+
```
886+
887+
### What the third seam is
888+
889+
`SharpRuntime::Testing::KeyMaterialAccess<T>`, declared by
890+
`modules/security-cryptography/include/System/Security/Cryptography/detail/SecureMemory.hpp` and
891+
befriended by `KeyedHashAlgorithm`, `HMAC` and `Rfc2898DeriveBytes`. It was added after this
892+
document's last revision, which is why the running figures fell behind.
893+
894+
### The invariant it had to satisfy, and does
895+
896+
CLAUDE.md requires **both** guards for every seam — the ODR checker *and* a
897+
`test/consumer/*_negative.cpp` site — because they catch different mutations: the checker cannot
898+
see a collection's private counter being made public, and the consumer fixture cannot see a second
899+
definition added in another test translation unit.
900+
901+
Audited on 2026-08-19: the third seam has both. `test/consumer/security_cryptography_key_material_negative.cpp`
902+
covers it and cites this requirement in its own header. **So it is only the arithmetic in this
903+
document that fell behind, not the enforcement.**
904+
905+
| seam | declared by | consumer fixture |
906+
|---|---|---|
907+
| `CollectionVersionAccess` | `System/Collections/detail/MutationCounter.hpp` | `collections_mutation_version_negative.cpp` |
908+
| `SortedSetVersionAccess` | `System/Collections/Generic/SortedSet.hpp` | `collections_sorted_set_version_negative.cpp` |
909+
| `KeyMaterialAccess` | `System/Security/Cryptography/detail/SecureMemory.hpp` | `security_cryptography_key_material_negative.cpp` |
910+

docs/NegativeConsumerFixtureValidation.md

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,13 +1551,53 @@ sanitizer was given a deliberate defect built with the same flags:
15511551
| shift exponent ≥ width under UBSan | **1 report — instrumentation live** |
15521552
| no defect (control) | **0 reports — correctly silent** |
15531553

1554-
### 22.4 A correction to this document's running total
1554+
### 22.4 A correction to this document's running total — and a correction to that correction
15551555

15561556
§21.5 records **11 fixtures / 94 sites**, and that has been stale since 2026-08-04: the measured
1557-
total today is **45 fixtures / 231 sites**. The ~34 fixtures added between #2054 and now were each
1558-
recorded in their own ticket's migration note rather than here, so the record exists — it is this
1559-
document's *running total* that fell behind, not the evidence. #1894 adds no fixture of its own, so
1560-
the total is unchanged by this section.
1557+
total today is **45 fixtures / 231 sites**. #1894 adds no fixture of its own, so the total is
1558+
unchanged by this section.
1559+
1560+
**The first version of this subsection claimed the intervening fixtures "were each recorded in
1561+
their own ticket's migration note rather than here, so the record exists". That was asserted rather
1562+
than measured, and it is false.** Audited on 2026-08-19 by grepping `docs/` for every fixture
1563+
filename: **17 of the 45 had no record in `docs/` at all** — not in this document, not in any
1564+
migration note.
1565+
1566+
Two things the audit got right only on the second pass, recorded because the first pass was
1567+
misleading in the *alarming* direction:
1568+
1569+
* A first attempt searched for each **filename** inside ticket text and reported eight fixtures as
1570+
having "no ticket record either". That was an artefact of the search: tickets describe their
1571+
fixture without naming its file. Reading each fixture's own header instead shows **every one of
1572+
the 45 names a real ticket** — there are **no orphans**.
1573+
* So the gap was never traceability. It was this document's coverage, and it is closed below rather
1574+
than merely reported.
1575+
1576+
#### The 17 fixtures that had no `docs/` record
1577+
1578+
| fixture | ticket(s) | subject |
1579+
|---|---|---|
1580+
| `core_appdomain_switch_nullable_negative.cpp` | #2250 | ticket #2250 (SR-AUD-103, switch half) |
1581+
| `core_applicationid_dotnet_shape_negative.cpp` | #2291 | ticket #2291 (SR-AUD-117) |
1582+
| `core_argument_out_of_range_guard_domain_negative.cpp` | #2213, #2254 | ticket #2254 (finding SR-AUD-091) |
1583+
| `core_attribute_protected_ctor_negative.cpp` | #2339 | ticket #2339 (SR-AUD-114) |
1584+
| `core_deprecated_members_negative.cpp` | #2289 | ticket #2289 (SR-AUD-117) |
1585+
| `core_func_nonvoid_result_negative.cpp` | #2299 | ticket #2299 (SR-AUD-126) |
1586+
| `core_integer_style_validation_negative.cpp` | #2269 | ticket #2269 (SR-AUD-178) |
1587+
| `core_localdatastoreslot_no_public_ctor_negative.cpp` | #2298 | ticket #2298 (SR-AUD-129), route B |
1588+
| `core_marshalbyrefobject_protected_ctor_negative.cpp` | #2297, #2374 | ticket #2297 (SR-AUD-128) |
1589+
| `core_obsoleteattribute_nullable_negative.cpp` | #2295 | ticket #2295 (SR-AUD-116) |
1590+
| `core_resolveeventhandler_optional_negative.cpp` | #2325 | ticket #2325 (SR-AUD-123) |
1591+
| `core_runtimetype_removed_negative.cpp` | #2333, #2334 | ticket #2334 (SR-AUD-110, approval-gated clause |
1592+
| `core_tuple_getter_only_negative.cpp` | #2330 | ticket #2330 (SR-AUD-063) |
1593+
| `core_unityserializationholder_removed_negative.cpp` | #2281 | ticket #2281 (SR-AUD-137) |
1594+
| `core_valuetype_protected_ctor_negative.cpp` | #2322 | ticket #2322 (SR-AUD-068) |
1595+
| `numerics_complex_abs_return_negative.cpp` | #2172 | ticket #2172 (SR-AUD-277 remainder) |
1596+
| `numerics_generic_math_negative.cpp` | #2168 | ticket #2168 (SR-AUD-278): proves that every static member of the |
1597+
1598+
Each is validated by `scripts/check_negative_consumer_fixtures.py` exactly like the others — the
1599+
checker is the enforcing mechanism and it never fell behind; only the prose did. With this table
1600+
the audit re-runs clean: **0 fixtures without a `docs/` record.**
15611601

15621602
Build directories used: `build-asan` (reused) and `build-ubsan` (created), both `--parallel 2`,
15631603
both with `ccache`.

0 commit comments

Comments
 (0)