FABRIC-3.md: scope FIRSTTOUCH, correct stale g.total_user_lbn wording

Traced g.total_user_lbn and blk_meta_t's chain fields before scoping: the M3 punch-list wording ("claim at g.total_user_lbn") predates BMAPFMT's distributed-ownership decision and doesn't describe a workable mechanism -- total_user_lbn only grows when a whole new device attaches, not when claiming space within one already attached. Real job is scanning Artemis's already-attached device's own blk_meta_t records for unowned devblocks. Also found blk_meta_t already has real, unused prev_block/next_block/chain_length linkage fields, untouched by BMAPFMT's redesign. Decisions: claims are a scattered chain via those fields (fragmentation-immune, free), discovered via full linear scan every time (no cached index, matches BMAPFMT's own no-centralized-table philosophy), fail outright with no partial-claim fallback if the device can't satisfy a request.
This commit is contained in:
Robert Allan James
2026-08-27 14:41:50 -04:00
parent 7f60df3d5c
commit 9c0e583554
+58 -2
View File
@@ -140,7 +140,12 @@ decisions get added here, not to `FABRIC-2.md`. Follow the same discipline `FABR
2026-08-27 (`FABRIC-3.md` §F.6, decision 3): a user's pool is their entire thumbdrive by
default (never contested) plus any system-resident device blocks they additionally claim,
first-come-first-served — this function only governs that second, system-side extension,
not the drive itself.**
not the drive itself.** **SCOPED 2026-08-27 (`FABRIC-3.md` §F.11)**: the "claim at
`g.total_user_lbn`" phrasing above is stale, predating `BMAPFMT`'s distributed-ownership
decision — claims are found by scanning Artemis's already-attached device's own `blk_meta_t`
records for unowned devblocks, not by extending a counter. Claims may be a scattered chain
(reusing `blk_meta_t`'s existing `prev_block`/`next_block`/`chain_length` fields), found via
a full linear scan each time, no cached index.
- [x] **SCOPED 2026-08-27 (FABRIC-3.md §F.4).** Design the on-drive block-map format (Section
U item 4). Resolved as: no separate table — repurpose the existing, fully-wired-but-
@@ -1426,7 +1431,7 @@ graph TD
PH8["✅ Phase 8 — Zuse identity<br/>+ block-fence, DONE 2026-08-26"]
CERTVERIFY["❌ Zuse-signed user-cert verification (M3)<br/>SCOPED 2026-08-27 (§F.7) — X.509/DER, own trust root"]
FIRSTTOUCH["❌ First-touch identity→block-range<br/>allocation (M3)"]
FIRSTTOUCH["❌ First-touch identity→block-range<br/>allocation (M3) — SCOPED 2026-08-27 (§F.11)"]
BMAPFMT["❌ On-drive block-map format (M3)<br/>SCOPED 2026-08-27 (§F.4) — repurpose blk_meta_t"]
BMAPWRITE["❌ Write block-map to drive (M3)"]
BMAPREAD["❌ Read/validate block-map on insert (M3)"]
@@ -1541,6 +1546,11 @@ finished). Dashed arrows = softer "gates/informs" relationships.
today never resets `g_repl_active_vm`, so killing the VM a console is currently `USE`'d onto
leaves a dangling pointer. Reported, not fixed — the new `EJECT`/hot-unplug call sites handle
this correctly, but the existing `KILL` word's own call sites do not.
- **`FIRSTTOUCH`'s own punch-list wording was stale** (§F.11) — "claim at `g.total_user_lbn`"
predates `BMAPFMT`'s distributed-ownership decision and doesn't describe a workable
mechanism against the current design. A second, unrelated discovery in the same pass —
`blk_meta_t`'s existing chain fields — turned what looked like a fragmentation problem into
a non-issue for free.
**Not yet done:** an ordered plan (which node to attack first, given the graph). Per Captain
Bob's own framing, that's the next pass — "start asking and answering questions iteratively
@@ -2003,6 +2013,52 @@ the latter, given the single-USB-device constraint confirmed in `F.8` means ther
than one candidate — not committed here); the console message text distinguishing a graceful
eject from an unclean one in the transcript.
### F.11 — `FIRSTTOUCH` (identity → system-device block-range allocation)
Traced `g.total_user_lbn` (`block_subsystem.c:634,650,655,677,688,753`) and `blk_meta_t`'s
existing chain fields before assuming the M3 wording was still accurate. **Finding: it isn't,
fully.** "Claim a new range at `g.total_user_lbn`" predates `BMAPFMT`'s decision (§F.4) to drop
the centralized block-map in favor of distributed per-block ownership. `total_user_lbn` is a
global high-water mark that only grows when an entirely new *device* attaches (RAM, Artemis's
disk, a USB drive) — it says nothing about claiming space *within* an already-attached,
fixed-size device. `FIRSTTOUCH`'s real job is scanning Artemis's own system-resident device's
existing `blk_meta_t` records for unowned devblocks, not extending any counter.
Also confirmed live and unrelated to `BMAPFMT`'s repurposing: `blk_meta_t`'s "Link/chain
support" fields (`prev_block`/`next_block`/`parent_block`/`chain_length`,
`block_subsystem.h:232-236`) are real, general-purpose, block-number-granularity linkage — not
device-chain-specific — and completely untouched by `F.4`'s field redesign.
**Decisions made 2026-08-27:**
1. **A claim is a scattered chain, not a required contiguous run.** Reuses the existing
`prev_block`/`next_block`/`chain_length` fields directly — immune to fragmentation, and
this mechanism already exists, unused, waiting for exactly this. The claim's identity to
the caller is its chain-head devblock number; `owner_fp` is written to *every* devblock in
the chain (not just the head), so ownership is directly readable from any member block
without first walking the chain — consistent with `BMAPFMT`'s whole point of making
ownership locally readable per-block.
2. **Discovery: full linear scan, every time, no cached index.** Matches `BMAPFMT`'s own
explicit "no centralized table, nothing extra to keep in sync" philosophy exactly. One scan
pass serves both questions this node needs answered — "does this identity already own a
claim" (`owner_fp` match) and "which devblocks are free" (`owner_fp` all-zero) — collected
together in the same walk, not two separate scans.
3. **Failure mode: fail outright, no partial claim.** If the device doesn't have enough free
devblocks (scattered or not) to satisfy the request, return an error and let the caller
decide — matches this codebase's existing return-code convention throughout (`capsule_birth_baby()`
and friends), no new partial-allocation semantics invented.
4. **Allocation unit: whole devblocks**, already decided in `BMAPFMT` (§F.4, decision 4) —
`FIRSTTOUCH` doesn't revisit this, just inherits it.
**Not yet scoped (deferred within this node):** the actual function signature/call site (this
pass decided the algorithm, not its C interface); who calls `FIRSTTOUCH` and when — most
likely `MIGSM` (the migration state machine, M3, still 🟡 partial) deciding "this identity
needs N more devblocks," but that call site doesn't exist yet either; whether a first-touch
scan should skip/short-circuit once the caller's own already-attached thumbdrive still has
room (matching the pool-scope clarification in §F.6: the thumb is the default pool, this
node is specifically the *overflow* case) — implied yes by that clarification, not explicitly
re-confirmed here.
### D.5 — Scope expansion (2026-08-27): identity is common to every VM, not just users
Surfaced while scoping `ACLKEY`, stated directly: *"the whole object is to deliver a