Skip to content

Commit 00e97bd

Browse files
committed
docs(handoff): bring NEXT.md and plan.md up to the empty-queue state
Both headers were stale: they still read 17,676 / 38, graph 41/94, fixtures 52/264, and a ticket queue with one open todo. Every figure is re-measured rather than carried forward -- gate 17,732/38 green, graph 41/95, seams 3/20, fixtures 53/269, tickets 2,406 done / 0 todo / 3 blocked / 5 wontfix, task fully classified. The headers now state plainly that THE POST-AUDIT QUEUE IS EMPTY, and that the three blocked tickets are not unfinished work but work this container lacks the means to do -- #2381 measured rather than assumed, since cna builds against the sibling checkout on develop where DateTimeKind does not exist at all, so the repair cannot compile before the merge. What is carried forward is the part a fresh session cannot re-derive: - The three findings made WHILE WORKING ON SOMETHING ELSE (#2415, #2416, and #1945's RoundtripKind limitation), because none of them was on any list and the method that produced them keeps working. - Three recurring process lessons that each cost real time: a mis-passed -k is worse than none because it looks like success; a restore to the wrong baseline, or an anchor that matches twice or not at all, invalidates every verdict after it; and a segfault is not a verdict. - One operational fact about the downstream consumer: cna's graphics tests need a virtual display, and a first attempt to attribute that failure compared a filtered run against a full one, which proved nothing. No production code changed; the gate figure is unmoved.
1 parent b45a153 commit 00e97bd

2 files changed

Lines changed: 105 additions & 271 deletions

File tree

NEXT.md

Lines changed: 58 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -3,141 +3,81 @@
33

44
# NEXT.md
55

6-
> **Test-count floor, 2026-08-20 — 17,676 / 38, AND THE GATE IS GREEN.** The complete
7-
> 38-executable gate reads **17,676 run: 17,676 passed, 0 failed, 0 skipped**, recounted from the
6+
> **Test-count floor, 2026-08-20 — 17,732 / 38, AND THE GATE IS GREEN.** The complete
7+
> 38-executable gate reads **17,732 run: 17,732 passed, 0 failed, 0 skipped**, recounted from the
88
> per-executable logs with every executable run separately and continuing past failures, zero build
9-
> warnings at `--parallel 2`. Every checkpoint below this one ends with *"the gate is not green"*;
10-
> this one does not. Two of the three historical failure sources were environmental and are simply
11-
> absent in this container; the third was a real repair (#2351).
9+
> warnings at `--parallel 2`. Graph **41 / 95**, seams **3 / 20**, negative fixtures **53 / 269**.
1210
>
13-
> **The queues were empty and the work was found by measurement instead (#2397, then #2398).**
14-
> With `ticket` at 0 `todo` and `task` fully classified, the next move was **not** to stop but to
15-
> point the restored reference at the modules with **no test sources of their own**. Two have now
16-
> been measured and both held real defects.
11+
> ---
1712
>
18-
> **#2397 — `System::Text::RegularExpressions`.** Four divergences, **two of them silent data loss
19-
> through a public member**: `Regex::Split` discarded every matched capture group's value *and*
20-
> dropped a trailing empty segment, both because the body was a single
21-
> `std::sregex_token_iterator(-1)`.
13+
> ## THE POST-AUDIT QUEUE IS EMPTY
2214
>
23-
> **#2398 — `System::Security::Cryptography::RandomNumberGenerator`.** It **threw
24-
> `PlatformNotSupportedException` on Emscripten**, on a premise **this repository had already
25-
> measured false**: `Guid.cpp:377-388` records #2228's finding that Emscripten's `getentropy()` is
26-
> `__wasi_random_get()`, so `Guid::NewGuid()` has been getting real entropy there through the very
27-
> call the cryptographic RNG refused to make. .NET does not refuse either. **And its shipped tests
28-
> could not have caught it** — two cases asserting `buffer.size()` after filling a buffer whose size
29-
> was fixed before the call, both of which pass against a generator that writes nothing.
15+
> Measured 2026-08-20: `ticket` is **2,406 done, 0 todo, 3 blocked, 5 wontfix**, and `task` is fully
16+
> classified (1,082 ported, 15,119 ignored). **There is no remaining implementation work that this
17+
> container can do.**
3018
>
31-
> **#2401 — `ClientWebSocket`'s entropy.** Found by asking #2398's question **once more** rather
32-
> than by opening another module: *#2228 put a real CSPRNG behind `Guid::NewGuid` — what else needs
33-
> unpredictable bytes, and where does it get them?* `ClientWebSocket` drew **both** its
34-
> `Sec-WebSocket-Key` nonce and its **per-frame masking key** from `std::random_device`, which the
35-
> standard permits to be deterministic and which **`Random.cpp:69-70` already records as
36-
> deterministic on MinGW-w64**, a supported target. RFC 6455 §5.3 requires the mask to come from a
37-
> strong source of entropy by name.
19+
> **The three blocked tickets are not unfinished work; they are work this container lacks the means
20+
> to do**, and each was measured rather than assumed:
3821
>
39-
> **#2402 closed the entropy sweep by recording what is NOT a defect** — the half a sweep usually
40-
> leaves out. Five sites need random bytes; two were repaired and **two are parity and look exactly
41-
> like the defect**, because `HashCode::GlobalSeed` and unseeded `Random` both call
42-
> `std::random_device`. .NET has **two** entropy entry points and deliberately uses the
43-
> **non**-cryptographic one at both. `docs/EntropySourceSweep.md` records all five with citations,
44-
> so nobody re-opens them.
22+
> * **#1773** and **#2381** wait on the `next` → `develop` merge. #2381 is the sharper of the two:
23+
> `cna` builds against the **sibling checkout on `develop`**, where `DateTimeKind` does not exist
24+
> at all, so the repair cannot compile before the merge — not a decision, an impossibility.
25+
> * **#1962** needs a raw ICMP socket, hence `CAP_NET_RAW`, which this container does not have.
4526
>
46-
> **Three patterns worth carrying forward, in order of yield.** (1) **Ask a repaired subsystem's
47-
> question of its neighbours** — that alone found #2398 and #2401, and #2402 closed it out. (2) **A
48-
> module with no test sources** is where an undetected divergence survives. (3) **A test that cannot
49-
> fail** is how it survives there: **every** defect this sweep found sat under one, **four** of them
50-
> literally — two `EXPECT_EQ(buffer.size(), N)` on a buffer sized before the call, a case whose name
51-
> claimed "DiffersAcrossProcesses" while its body only checked within one, and
52-
> `EXPECT_NO_THROW(System::ComponentModel::Attribute{})`, which asserted that an empty type can be
53-
> default-constructed. §4b has the remaining candidates.
27+
> The five `wontfix` entries are recorded decisions with their reasons, not oversights.
5428
>
55-
> **#2403 — `System::ComponentModel`, and the pattern that found it is pattern (2) below.** Six
56-
> attributes published a **bare mutable public data member** where .NET publishes a get-only
57-
> property, most with **no statics and no equality members at all** — while four siblings **in the
58-
> same header** already had the correct shape. The module's whole prior coverage for those six was
59-
> constructor round-trips through the public field, so .NET's `Default` values — the actual contract
60-
> of a metadata attribute — were unpinned, and `MergablePropertyAttribute::Default` is `Yes` where
61-
> its four siblings are `No`.
29+
> ---
6230
>
63-
> **#2405 finished the `component-model` pass**: the two `PropertyChanged`/`PropertyChanging`
64-
> event-args types each carried a **second, mutable, lossy** copy of `PropertyName` beside the
65-
> private `std::optional` — a field whose own doc-comment described the loss and kept it "for
66-
> existing consumers", a reason that measures to **zero** — and `System::ComponentModel::Attribute`
67-
> turned out to be a **phantom**: no .NET counterpart, no members, no derived classes, no callers.
31+
> ## HOW THE LAST STRETCH WENT, AND WHAT IS WORTH CARRYING FORWARD
6832
>
69-
> **#2406 closed the `component-model` sweep, and its largest half is a DECLARATION.** The eleven
70-
> `ValidationAttribute` subclasses — `Required`, `Range`, `StringLength`, `RegularExpression`,
71-
> `EmailAddress` and the rest — **validate nothing**; .NET has `IsValid`/`Validate`/
72-
> `FormatErrorMessage`/`RequiresValidationContext` and this port has none of them. The **names** are
73-
> what make that dangerous: a caller who writes `RequiredAttribute` and sets an error message has
74-
> every reason to think something checks it, and the mistake surfaces as *validation that silently
75-
> never happened*. It is now a `@warning` on the base class and a pinned absence — **mutation M7
76-
> adds an `IsValid` and is caught**, so the declaration is enforced.
33+
> The queue was emptied by the date/time chain rooted at **#1940**, plus three findings made **while
34+
> working on something else**. That second category is the one worth naming, because none of the
35+
> three was on any list:
7736
>
78-
> **SA-14 WAS GRANTED ON 2026-08-20 AND UNBLOCKS THE DATE/TIME CHAIN.** Three decisions, all as
79-
> recommended, recorded in `docs/StandingApprovals.md`: (1) the provider reaches the parser by
80-
> **moving `DateTimeFormatInfo` into `Core.Base`** — measured at two files and **zero changed include
81-
> lines**, against 34 files across eight modules for the new-component shape #1940's own wording
82-
> implied; (2) the **culture-concurrency** defect is repaired **separately and first** — that is
83-
> **#2409, now done**; (3) an unrecognised culture **name** throws from **both** doors.
37+
> * **#2415 — a gate had been RED for a day behind a green test count.**
38+
> `scripts/check_selective_components.sh` failed on a fixture #1889 had legitimately invalidated,
39+
> **and nothing ran the script**, so CLAUDE.md rule 2's green reading said nothing about it. It
40+
> also **built eight trees into `/tmp`**, the one place the build policy exists to keep builds out
41+
> of — a mechanism (`build-tmp/`) that was designed and never wired up. It now runs last in
42+
> `local_ci_check.sh`, at a measured ~10 minutes, deliberately **not** behind an opt-out: *a check
43+
> that can be skipped is the check that rotted.*
44+
> * **#2416 — the two halves of one type disagreed about what `o` means.** A probe taken to check
45+
> something else measured that `DateTime::ToString` had **no standard-format table at all**:
46+
> `ToString("o")` emitted the literal `"o"`, `"s"` returned `"0"` by reading it as *seconds*. The
47+
> table already existed on `DateTimeFormatInfo` and was simply never called.
48+
> * **A limitation found by a test of mine FAILING** (#1945): `RoundtripKind` could not carry a kind
49+
> across a string, because nothing wrote a marker and nothing read one. It was declared and
50+
> pinned, and SA-16.3 later closed it — with the pin **inverted rather than deleted**.
8451
>
85-
> **#2410 IS `needs_user` AND IT IS THE ONE THING HELD OPEN DELIBERATELY.** Decision 3 is granted,
86-
> but its **boundary** is not: measured, .NET in invariant globalization mode — this port's own mode
87-
> — accepts **only `""` and `"und"`** and throws for **every** other name, *including `"de-DE"`*
88-
> (`CultureData.cs:660-675`, `GlobalizationMode.cs:19`). The two readings (invariant-mode-exact vs a
89-
> syntactic BCP-47 check) differ enormously in blast radius, so the choice was put to the user and
90-
> **not made unilaterally**. **#1940 does not depend on it** and can proceed.
52+
> **Three recurring process lessons, each of which cost real time this stretch:**
9153
>
92-
> **#1940 IS CLOSED AND THE DATE/TIME CHAIN IS OPEN.** It was the root: **#1942, #1943 and #1945
93-
> are now `todo`**, and **#1944** follows through #1943. The blocker turned out to be **two** things
94-
> where the ticket recorded one — the component cycle *and* the fact that **nothing in this runtime
95-
> implemented `IFormatProvider` at all**, so there was nobody for `DateTime` to ask. Shape C's
96-
> measured claim held exactly: two renames, **zero changed include lines**, graph still 41/94.
54+
> 1. **A mis-passed `-k` is worse than none, because it looks like success.** It appeared twice:
55+
> once as CMake printing a usage banner and exiting, once as ninja rejecting `-k` without a
56+
> number. Both reported *zero errors*. Check the **exit code**, never the error count alone.
57+
> 2. **A restore that reverts to the wrong baseline invalidates every verdict after it.** Using
58+
> `git checkout` on a file whose change was still **uncommitted** produced five consecutive
59+
> BUILD FAILED readings that were a harness state, not five findings. So did an anchor that
60+
> matched **twice**, and one that matched **nothing**. *An ambiguous or absent anchor is a
61+
> harness result, not a mutation result.*
62+
> 3. **A segfault is not a verdict.** Undefined behaviour must never be read as a mutation passing;
63+
> reformulate the mutation into a realistic defect and re-run.
9764
>
98-
> `ticket` has **3 `todo`** (#1942, #1943, #1945 — the newly unblocked chain); `task` has **0**
99-
> unclassified (14,979 ignored / 1,082 ported / 140 ignore). Ticket totals: **2,394 done, 3 todo, 6
100-
> blocked, 2 needs_user, 5 wontfix**. Graph **41 / 94**, negative fixtures **52 / 264**. Seventeen
101-
> tickets were filed or closed by this sweep: #2397–#2402 on 2026-08-19, #2403–#2409, #2411 and
102-
> #1940 on 2026-08-20.
65+
> **And one operational fact about the downstream consumer, learned the hard way:** `cna`'s graphics
66+
> tests need a **virtual display**. Without one, `Texture2DCacheReconstructionTest` fails for
67+
> display reasons unrelated to any change under test. Run its suite under `xvfb-run`; it then reads
68+
> **6,332 tests, 0 failed**. A first attempt to attribute that failure compared a *filtered* run
69+
> against a *full* one, which is not a like-for-like measurement and proved nothing.
10370
>
104-
> **#1942 AND #1943 LISTED EACH OTHER, AND #2412 TOOK THE HALF THAT SEPARATES.** #1942 waited for
105-
> an overload taking a `DateTimeStyles` (there was none, measured) and #1943 waited for #1942.
106-
> `DateOnly`/`TimeOnly` **have no `DateTimeKind`**, so .NET rejects every kind-affecting style
107-
> outright — **the styles that would need a timezone contract are exactly the styles that are
108-
> illegal there** — and that half needed no approval. It is landed as **#2412**.
71+
> ---
10972
>
110-
> **Both tickets are back to `blocked`, on their `DateTime` halves alone**, which need **#1941 phase
111-
> 2** and its unapproved timezone provider. That is a *user decision*, not a measurement: #1941's
112-
> record says a phase-2 approval must name a date-sensitive timezone provider.
73+
> ## IF WORK IS WANTED AND THE QUEUES ARE STILL EMPTY
11374
>
114-
> **SA-15 WAS GRANTED ON 2026-08-20 AND IS THE STATE OF THE QUEUE.** Three decisions, all as
115-
> recommended, in `docs/StandingApprovals.md`: (1) `DateTime` reaches a timezone through an
116-
> **abstraction in `Core.Base`** rather than by moving `TimeZoneInfo` — **with the accepted caveat
117-
> that .NET's `ToLocalTime()` takes no argument**, so the source must come from a hidden hook or an
118-
> explicit overload, a deviation either way that must be *recorded* as one; (2) the culture-name
119-
> boundary is a **syntactic BCP 47 check** — landed as **#2410**; (3) **SA-3 now covers vtable and
120-
> base-class changes**, under five conditions whose fourth (enumerate every `catch` clause whose
121-
> meaning changes) exists because a reparenting is invisible to a layout pin.
122-
>
123-
> **#1941 PHASE 2 IS LANDED AND THE DATE/TIME CHAIN IS FULLY OPEN.** `DateTime` converts by its
124-
> `Kind` against an `ILocalTimeZone` the caller passes. **The recorded blocker looked at the wrong
125-
> type**: `TimeZoneInfo` is date-INsensitive by its own documentation, while
126-
> `System::TimeZone::CurrentTimeZone()` is per-date — and that is exactly the zone these
127-
> conversions need, so the model was present all along.
128-
>
129-
> **#1980 IS CLOSED** — G-3 landed as the first change under SA-15.3, and G-1/G-2/G-4/G-5 landed
130-
> 2026-08-19. **Four `todo`**: #1942, #1943, #1944 (unblocked by #1941 phase 2), #1945, plus #1997
131-
> (unblocked by SA-15.3, A-2/A-4 remaining). **Only three tickets remain blocked**, none of them on
132-
> a decision this repository can take: #1773 and #2381 wait on downstream or merge events, #1962 on
133-
> `CAP_NET_RAW`.
134-
>
135-
> **One thing #2406 deliberately did NOT do, so it is not mistaken for parity**: `DisplayAttribute`'s
136-
> eight fields stay public data members (correct — .NET's are `{ get; set; }`), but their
137-
> **nullability** still diverges (`string?`, `int?`, `bool?` with `GetOrder()`/
138-
> `GetAutoGenerateField()`), which is the #2295 shape across eight signatures. What remains *blocked* needs the user or an external event,
139-
> and each is itemised in §2 below. **§4b says where to look next, and the method that found all
140-
> three of today's tickets.**
75+
> The method that produced #2397, #2398, #2415 and #2416 is recorded because it keeps working:
76+
> **point the reference at what has no coverage of its own, and at assertions that cannot fail.**
77+
> Concretely — modules with no dedicated test executable; tests whose assertion is satisfied by the
78+
> defect they claim to pin (five were found this way); and the question *"what else in this runtime
79+
> asks this same question, and does it get the same answer?"*, which is what found #2401 from #2398
80+
> and #2416 from #1945.
14181

14282
## 2026-08-20 — #1944: multi-format `ParseExact` — **the last open post-audit ticket**
14383

0 commit comments

Comments
 (0)