Skip to content

Commit aaa2bc2

Browse files
committed
docs: record SA-8, SA-9 and SA-10, unblocking 25 tickets
SA-8 -- public representation: where this port publishes a mutable or public representation and .NET's is private, readonly or absent, match .NET and migrate the first-party sites. Granted AGAINST the recommendation to split the family by hazard, and knowing the price: t.Item1 becomes t.getItem1Property() permanently under rule 5, in a CNA-facing API. Nine tickets. SA-9 -- a type that exists only because .NET has one, and whose content is permanently out of scope, wears .NET's public shape with bodies that throw. This resolves a third state that is worse than either: a surface that is neither .NET's nor internal, i.e. project-owned API wearing a .NET name. Priced and accepted: LocalDataStoreSlot reaches that shape only behind a new Thread data-slot API, and that new public surface is authorised. Seven tickets. SA-10 -- a public signature change (return type, noexcept, nullability, [[deprecated]]) is a public source break and lands under SA-2's five conditions. A clarification, not a new grant: nine tickets had treated SA-3's narrower object-layout wording as the only relevant approval. Vtable and base-class changes still ask per action; #1888, #1889 and #1896 stay declined.
1 parent 7332b5b commit aaa2bc2

3 files changed

Lines changed: 84 additions & 1 deletion

File tree

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
full-consumer-rebuild requirement, and the full gate runs — a vtable or base-class change
5454
still asks, and #1888, #1889 and #1896 stay declined; **SA-4** Unicode tables are derived
5555
from .NET's own generated data in `/rv` at **UCD 16.0**, cross-checked against Perl 15.0.0
56-
and Python 15.1.0, version pinned until an explicit bump ticket. That document also records
56+
and Python 15.1.0, version pinned until an explicit bump ticket. On 2026-08-18 the user granted three more: **SA-8** where this port publishes a mutable or public representation and .NET's is private, readonly or absent, **match .NET and migrate the first-party sites** — granted *against* the recommendation to split the family by hazard, and knowing that `t.Item1` becomes `t.getItem1Property()` permanently under rule 5; **SA-9** a type that exists only because .NET has one, and whose content is permanently out of scope, wears **.NET's public shape with bodies that throw** — which authorises the new `Thread` data-slot API that `LocalDataStoreSlot` needs; **SA-10** a public **signature** change (return type, `noexcept`, nullability, `[[deprecated]]`) is a public source break and lands under SA-2's five conditions, which nine tickets had wrongly treated as covered only by SA-3. That document also records
5757
the environment facts those approvals rest on: `/rv/tmp/runtime` **is present** in this
5858
container (a .NET **11** preview snapshot, so a behaviour read from it must be reported as
5959
.NET 11's, not as timeless parity), and so are both downstream consumers. A ticket whose only

docs/StandingApprovals.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,89 @@ not green"*.
179179

180180
---
181181

182+
## 4e. SA-8 — public representation: match .NET, and migrate the sites
183+
184+
> Where this port publishes a mutable or public representation and .NET's is private, readonly or
185+
> absent, **match .NET**. Break the source and migrate the first-party sites.
186+
187+
Granted 2026-08-18, answering the nine-ticket family **#2322, #2324, #2325, #2326, #2327, #2328,
188+
#2330, #2332, #2339**.
189+
190+
**The user chose against the recommendation, and did so knowing the price.** The alternative
191+
offered was to split the family by hazard — repair `SequencePosition` and `Attribute`, pin
192+
`Tuple::Item1` as cosmetic — and the objection stated at the time was that `t.Item1` becomes
193+
`t.getItem1Property()` under CLAUDE.md rule 5, permanently, in a CNA-facing API. The answer was
194+
*always match .NET*. That is the decision; it is not to be re-litigated ticket by ticket.
195+
196+
**What it authorises**, over and above SA-2, whose five conditions still all apply to each landing:
197+
198+
* making a public data member private and adding the rule-5 accessor pair;
199+
* migrating first-party read and write sites to the accessor spelling — 75 of them in `Tuple`
200+
alone, all in this repository's own tests;
201+
* making a public default constructor protected, or a concrete class abstract, where .NET's is;
202+
* replacing an identity `Equals`/`GetHashCode` with .NET's field-wise definition.
203+
204+
**What it does not authorise.** A vtable or base-class change still asks (SA-3's exclusion is
205+
unchanged). And SA-8 is not a licence to invent: where .NET's own shape is unclear the answer is
206+
still derived from the reference or deferred, never guessed — SA-5's limit applies here too.
207+
208+
Each landing still carries its own migration note, per-spelling negative consumer fixture,
209+
downstream ticket, full gate and measured consumer impact.
210+
211+
---
212+
213+
## 4f. SA-9 — out-of-scope types wear .NET's shape and throw
214+
215+
> For a type that exists only because .NET has one, and whose content is permanently out of scope
216+
> (reflection, serialization, remoting, interop): **the public shape matches .NET, and the bodies
217+
> throw.**
218+
219+
Granted 2026-08-18, answering **#2276, #2281, #2291, #2295, #2297, #2298, #2334**.
220+
221+
The rule resolves a third state these types are in today, which is the worst of the three: the
222+
surface is neither .NET's nor internal, so it is a project-owned API wearing a .NET name.
223+
`MarshalByRefObject` is directly constructible where .NET is abstract; `LocalDataStoreSlot` has a
224+
public default constructor .NET makes internal, and one `std::any` shared by every thread, which
225+
is a data race.
226+
227+
**The shape:**
228+
229+
* abstract where .NET is abstract, protected constructor where .NET's is protected, internal
230+
constructor rendered unreachable where .NET's is internal;
231+
* members .NET keeps are **present**, so a caller receives a runtime diagnostic
232+
(`PlatformNotSupportedException`, or `NotImplementedException` where CLAUDE.md's parity section
233+
already names one) instead of a compile error;
234+
* members .NET does **not** have are removed.
235+
236+
**One consequence was priced and accepted at grant time:** `LocalDataStoreSlot` reaches its .NET
237+
shape only behind a new `Thread::AllocateDataSlot` / `AllocateNamedDataSlot` / `GetData` /
238+
`SetData` / `FreeNamedDataSlot` surface, which this repository does not have. That is
239+
substantial new public API and it is authorised.
240+
241+
CLAUDE.md's parity section already required a stub to throw "with a comment explaining why —
242+
never silently return a wrong value". SA-9 adds the half that was missing: the *shape* is .NET's
243+
too, not this project's invention.
244+
245+
---
246+
247+
## 4g. SA-10 — SA-2 covers a public signature change
248+
249+
> A change to a public **signature** — return type, `noexcept`, nullability, `[[deprecated]]` — is
250+
> a public source break, and lands under SA-2's five conditions like any other.
251+
252+
Confirmed 2026-08-18. This is a clarification, not a new grant: SA-2 already said "a public source
253+
break may land with a migration note, a per-spelling negative consumer fixture, a #1773-shaped
254+
downstream ticket, the full gate, and a measured impact report against the local `cna` and
255+
`mobile-eggbert` checkouts". Nine tickets were nonetheless recorded as `blocked` on the theory
256+
that SA-3's narrower object-layout wording was the only relevant approval. It is not.
257+
258+
Unblocks **#2170, #2172, #2185, #2215, #2246, #2250, #2269, #2289, #2299**.
259+
260+
**Unchanged:** a vtable or base-class change still asks per action, and #1888, #1889 and #1896
261+
stay declined.
262+
263+
---
264+
182265
## 4d. SA-7 — the `NotifyFilters` → inotify mapping (ticket #2346)
183266

184267
> Answer the five priced questions of `docs/SystemIONamespaceReviewPlan.md` §21.11 as

plan.sqlite3

12 KB
Binary file not shown.

0 commit comments

Comments
 (0)