FABRIC.md §23.3: fix header arithmetic, and stop asserting an unsized cell

Review item REVIEW-C3.

The stated fields sum to 28, not the ~32 claimed, and 28 + 32 inline payload is
60, not the 64-byte cell. Now stated as 28 used plus 4 reserved. The reserve is
deliberate: it keeps the header a clean half-cell, leaves room for the
header/continuation discriminator §3 now requires, and gives §8's exclusivity
primitive somewhere to live if item 1.1 resolves to a holder index.

The larger problem was the "17 cells: 1 header + 16 payload" figure for a
1024-byte block. That silently assumed continuation cells are contiguous and
carry nothing but bytes. §22.3 allocates from a per-VM free list with no
adjacency guarantee, so continuation cells would need a next-index -- 4 bytes
off each one's payload, making the same block 18 continuation cells rather than
16. The alternative, guaranteeing contiguous runs, reintroduces the
fragmentation §3 avoids.

Those are different designs with different costs, and the choice sets the mass
of every large patron. Rather than pick one, the row is marked undetermined and
recorded as §23.4 #4, which gates punch item 3.1: the cell structure cannot be
built until it is settled.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-03 11:00:37 -04:00
co-authored by Claude Opus 5
parent a654e907e5
commit 1f44f47e69
+36 -3
View File
@@ -1717,14 +1717,39 @@ These are numbers to check against a real build, not derived truths.
| | Value | Reasoning |
|---|---|---|
| Cell size | **64 bytes** | one cache line; keeps density-ranking scans cache-friendly |
| Header | ~32 bytes | identity 8, heat 8, TTL 4, link 4, mass 2, flags + behaviour tag 2 |
| Inline payload | ~32 bytes | a small message fits in one cell — mass 1 |
| 1024-byte block | 17 cells | 1 header + 16 payload; genuinely heavy, correctly so |
| Header — used | **28 bytes** | identity 8, heat 8, TTL 4, link 4, mass 2, flags + behaviour tag 2 |
| Header — reserved | **4 bytes** | deliberate slack; see below |
| Header — total | **32 bytes** | |
| Inline payload | **32 bytes** | a small message fits in one cell — mass 1 |
| Per-VM Stadium | ~4096 cells = 256 KB | hundreds of hot words and blocks, ACLs, messages in flight |
| Continuation cell | **undetermined** | see below — depends on an unsettled encoding |
The four reserved bytes are deliberate rather than a rounding artefact. The fields above sum
to 28; padding to 32 keeps the header a clean half-cell, leaves room for the
header/continuation discriminator §3 now requires, and gives the exclusivity primitive of
§8 somewhere to live if item 1.1 resolves to a holder index. Reserved space in a header that
is expected to grow is cheaper than repacking one later.
256 KB per VM is comfortable against QEMU's `-m 1024`, and the outer Stadium's capacity
(§20.5 #1) then follows from how many VMs the machine is willing to host.
#### Why the continuation cell cannot be sized yet
An earlier draft stated a 1024-byte block is "17 cells: 1 header + 16 payload." **That figure
assumes continuation cells are contiguous and carry nothing but bytes.** Neither is
established:
- §22.3 allocates cells from a per-VM free list, so a patron's cells are **not necessarily
adjacent**. If they are not, each continuation cell needs a link to the next — which is
4 bytes off its payload, making it 60 usable, and a 1024-byte block 18 continuation cells
rather than 16.
- Alternatively, allocation could guarantee contiguous runs for multi-cell patrons, keeping
continuation cells pure payload at the cost of reintroducing the fragmentation §3 avoids.
These are different designs with different costs, and the choice determines both the mass of
every large patron and whether §22.3's free list stays a simple list. **OPEN — settle before
item 3.1.** The "17 cells" figure should not be relied on until it is.
Firmness of each figure:
- **Heat at 8 bytes is fixed**, not chosen — Q48.16 in a `uint64_t`, matching
@@ -1755,6 +1780,14 @@ Firmness of each figure:
the discriminator, for instance, would couple the two decisions. Settle the
header/continuation encoding first; identity elision is downstream of it.
4. **The continuation-cell encoding.** Whether a multi-cell patron's cells are contiguous
(continuation cells are pure payload; allocation must find runs, reintroducing
fragmentation) or linked (continuation cells carry a next-index, costing 4 bytes of
payload each and changing every large patron's mass). §22.3's per-VM free list does not
currently guarantee adjacency, so the linked form is the default unless allocation
changes. **This gates item 3.1** — the cell structure cannot be built without it, and
§23.3's sizing table cannot be completed without it either.
---
## 24. Mutation, identity, and mass stability