diff --git a/FABRIC.md b/FABRIC.md index 96b95e9..09039cf 100644 --- a/FABRIC.md +++ b/FABRIC.md @@ -1405,3 +1405,106 @@ rule looks correct. within a fixed total. Whether that total is itself fixed for the machine's lifetime is §20.5 #1, still open — and it should stay fixed, or §2's inescapable wall is not inescapable. + +--- + +## 23. §12 Q1 dissolved, §12 Q2 sized + +### 23.1 Q1 — the inline/by-reference threshold should not exist + +> *Q1: Payload threshold — what size goes inline versus by reference.* + +§3's motivation is sound: a cell sized for a 1024-byte block would be grotesque for a +patron that carries twelve bytes. But §19 supplies a better answer than a threshold. + +If cells are small and uniform, a large patron **occupies more of them, chained by index**. +That is exactly what mass already means. A block is not "by reference" — a block is +**heavy**. + +This closes the loophole recorded in §19.6 #1 without introducing a rule: + +> **If the payload is in the Stadium, it counts toward mass. If it is not in the Stadium, +> the patron is not resident — it is a handle to the warehouse.** + +A 1 MB block cannot occupy one cell and read as dense, because its bytes are on the floor +and the floor is what mass measures. + +This is also what gives §19's hysteresis its teeth. Blocks *should* be expensive to keep +resident — that is the entire reason migration back to Artemis is their reap event (§17.2). +A threshold that let big patrons masquerade as light ones would have quietly disabled the +mechanism. + +Nothing in §3 is violated: cells stay fixed-size, links stay indices, the Stadium stays an +array. Multi-cell patrons are consistent with all of it. **By-reference is reserved for +things genuinely outside the Stadium**, and those are not patrons. + +**DECIDED — Q1 is dissolved rather than answered.** + +### 23.2 Q2's premise moved, and an unsettled question sits under it + +> *Q2: Arena entry header size… The header must be sized for the worst case, and that case +> is the screen.* + +§17.5 removed the screen grid from the Stadium, so that premise no longer holds. What +replaces it depends on something §17.5 established only halfway: it decided the **dirty +event** is the patron, but not what one event *covers*. + +| Granularity | 80×25 full redraw | Consequence | +|---|---|---| +| per cell | 2,000 simultaneous patrons | floods the Stadium; starves every other patron | +| **per line span / region** | **~25 patrons** | negligible | + +A two-order-of-magnitude swing, currently undefined. + +**Recommend region-based.** Framebuffer updates are naturally regional — a scroll dirties +everything, a print dirties one span — overlapping regions coalesce for free, and per-cell +events would make the console the numerically dominant patron kind in the entire system. +That is absurd for something §17.5 correctly classified as a *utility* rather than an +occupant. + +**LEANING region-based.** It is a console-design decision as much as a Stadium one, so it +should be confirmed when the console work happens rather than fixed here. + +With that settled, the worst case for cardinality becomes **messages** — numerous, +individually small. Which yields the sizing rule: + +> **Size the cell so that a typical message is exactly one cell.** + +### 23.3 Concrete sizing — proposal, to be validated + +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 | +| Per-VM Stadium | ~4096 cells = 256 KB | hundreds of hot words and blocks, ACLs, messages in flight | + +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. + +Firmness of each figure: + +- **Heat at 8 bytes is fixed**, not chosen — Q48.16 in a `uint64_t`, matching + `execution_heat_q48` in the existing implementation. +- **Link at 4 bytes** caps the Stadium at ~4 billion cells, far past anything plausible. It + could shrink to 3 or even 2 bytes if the header gets tight. +- **TTL at 4 bytes** gives ~4 billion ticks — over a year at 100 Hz. Almost certainly + oversized; 2 bytes may do. +- **Cell size 64** is the one to validate first, because everything else is expressed + relative to it. + +**LEANING.** The structure is decided; the constants are not. + +### 23.4 Open + +1. **Dirty-event granularity** (§23.2) — confirm region-based when console work begins. +2. **Cell size validation.** Build the header for real, count the bytes, and check that a + typical message still fits in one cell with the behaviour tag and flags included. +3. **Is `identity` needed at all for every patron kind?** For a word it is a name; for a + block a content hash; for a message possibly nothing — its identity could be its index. + If identity can be elided for some kinds, 8 bytes of a 32-byte header is a large saving. + This must not become a per-kind branch (§18.3), so it is only worth doing if it can be + expressed uniformly.