union-parity README: what every runtime walks for a read-only payload
Per vector: the object carrying the extra slot, its depth and the mark (type, slots carried, slots declared); the counting rule (highest key + 1, short arrays and retired gaps do not mark, a union adds no depth); the store-record assertions, the consent rule and the extra-slot-store.cc carry check that cut-slot-readonly-ts/-py/-rs assert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e09700d439
commit
4e9820de6f
1 changed files with 48 additions and 23 deletions
|
|
@ -48,29 +48,54 @@ with one part replaced.
|
|||
|
||||
## Extra trailing slot (outcome `read-only`)
|
||||
|
||||
Each payload is `union-surface.msgpack` with one slot appended past the reader's last declared slot of one
|
||||
record (ruling `cultlib-gaps:ruling:extra-trailing-slots`: the record is read, read-only at any depth, every write
|
||||
of it refused). A reader decodes the value of `union-surface.msgpack` from each; `detail` says where the slot is.
|
||||
Rulings `cultlib-gaps:ruling:extra-trailing-slots` and `cultlib-gaps:ruling:slot-mark-consent`: a payload carrying a
|
||||
slot past its reader's declared slots, in any object at any depth, is read, held read-only, and every write or
|
||||
removal of it is refused before anything is staged. The first four payloads are `union-surface.msgpack` with the
|
||||
string `"extra-slot"` appended as one more slot of one object; a reader decodes the value of `union-surface.msgpack`
|
||||
from each. The fifth is a bare arm of union `UnitOutcome` (0 Waiting `[Message]`; 2 Denied2, -2147483648 Floor2 and
|
||||
2147483647 Ceiling2, each `[]`), the union of the `unit-arm-*` files; a reader decodes Denied2 from it.
|
||||
|
||||
| File | detail | Record with the extra slot |
|
||||
|---|---|---|
|
||||
| `extra-slot-record.msgpack` | record | the document (slot 7) |
|
||||
| `extra-slot-nested-record.msgpack` | nested-record | Composition `comp` |
|
||||
| `extra-slot-arm.msgpack` | arm | the Root Box arm |
|
||||
| `extra-slot-list-element.msgpack` | list-element | Text `s1`, an element of Use.Slots |
|
||||
| `extra-slot-unit-arm.msgpack` | unit-arm | not a UnionSurface: a bare UnitOutcome arm `[2, [extra]]` where Denied2 declares no slot (union `UnitOutcome`, key 2) |
|
||||
An object's declared slots are its highest key plus one. Only an array longer than that marks: a short array
|
||||
(missing trailing slots) keeps the defaults and is writable, and a non-nil value in a retired slot below the highest
|
||||
key (Image's slot 2) does not mark. A union adds no depth: an arm's array is counted against the arm's own slots.
|
||||
|
||||
`depth-skipped-at-limit.msgpack` (bounds file) is also `read-only`: its extra slot is a deeply nested value at depth 0.
|
||||
Five rows of `outcomes.msgpack` are `read-only` (record, nested-record, arm, list-element, unit-arm).
|
||||
| File | detail | Object with the extra slot | Depth | Mark: type, slots carried, slots declared |
|
||||
|---|---|---|---|---|
|
||||
| `extra-slot-record.msgpack` | record | the document (slot 7) | 0 | UnionSurface, 8, 7 |
|
||||
| `extra-slot-nested-record.msgpack` | nested-record | Composition `comp` | nested | Composition, 3, 2 |
|
||||
| `extra-slot-arm.msgpack` | arm | the Root Box arm | nested | Box, 3, 2 |
|
||||
| `extra-slot-list-element.msgpack` | list-element | Text `s1`, an element of Use.Slots | nested | Text, 3, 2 |
|
||||
| `extra-slot-unit-arm.msgpack` | unit-arm | Denied2 in `[2, ["extra-slot"]]` (union `UnitOutcome`, key 2) | as placed | Denied2, 1, 0 |
|
||||
| `depth-skipped-at-limit.msgpack` (bounds file) | depth | the document (slot 7, a value of nested arrays) | 0 | UnionSurface, 8, 7 |
|
||||
|
||||
`extra-slot-store.cc` is a single-file store holding two records of `tests.union_surface`: `marked` (the
|
||||
`extra-slot-nested-record.msgpack` payload) and `clean` (the ordinary value); the store's clock is pinned to
|
||||
2026-01-01T00:00:00Z as `union-surface.cc`'s.
|
||||
Each payload marks exactly one object. Five rows of `outcomes.msgpack` are `read-only` (record, nested-record, arm,
|
||||
list-element, unit-arm); the sixth `read-only` payload is in `bounds-outcomes.msgpack`. The payload nesting check
|
||||
runs before the mark: `depth-skipped-past-limit.msgpack` is refused, never marked.
|
||||
|
||||
Every runtime asserts the same for a `read-only` payload loaded as a store record: the value is read past the extra
|
||||
slot, the record reports the unread slots (the first type read with them, the slots it carried and the slots the
|
||||
reader declares) and is not writable, and a write or removal of it is refused before anything is staged. Opening
|
||||
`extra-slot-store.cc` and writing `clean` leaves `marked` byte for byte, with its schema id and its catalog entry.
|
||||
### What a runtime asserts for a `read-only` payload
|
||||
|
||||
Load it as a store record under the reader's own schema id (the C# reference puts each UnionSurface payload in a
|
||||
`tests.union_surface` store; the unit arm goes in slot 1 of a document `[Name, Outcome: UnitOutcome]`). Then:
|
||||
|
||||
1. the value is read past the extra slot;
|
||||
2. the record reports the mark as in the table: the first type read with extra slots, the slots it carried and the
|
||||
slots the reader declares, and the count of objects that carried extra slots (1 here);
|
||||
3. the record is not writable (C#: `CultCache.IsWritable(key)` false), and a key no store holds is writable;
|
||||
4. a replacing write, a variant write and a removal of the key (and a flatten, when the marked record is a variant)
|
||||
are refused before anything is staged,
|
||||
with the runtime's schema conflict refusal carrying the mark; its message names the type and both counts and
|
||||
never contains `extra-slot`, the slot's value;
|
||||
5. a write to another key of the same store succeeds.
|
||||
|
||||
Consent: a mark is explained only when it is at depth 0 and the schema comparison of the record's stored id against
|
||||
the reader reported ignored extra slots, i.e. the record is stored under an id the reader lists compatible and the
|
||||
catalog entry for that id has more members. Declaring that id consents to an explained mark only. Every mark in the
|
||||
table is unexplained (stored under the reader's own id), so each record stays read-only whatever is declared.
|
||||
|
||||
`extra-slot-store.cc` is a single-file store of two `tests.union_surface` records, the store's clock pinned to
|
||||
2026-01-01T00:00:00Z as `union-surface.cc`'s: `marked`, whose payload is `extra-slot-nested-record.msgpack`, and
|
||||
`clean`, the value of `union-surface.msgpack`. Open it, assert `marked` read-only and `clean` writable, write `clean`
|
||||
and flush: `marked`'s payload bytes, schema id and stored-at, and every catalog entry's bytes, equal the originals.
|
||||
|
||||
## Bounds (`bounds-outcomes.msgpack`)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue