Beagle SCM
BE-050: work/status views re-mmap .be per row, never close — close after drain + reuse memos
Context
Read-only investigation 2026-07-19 of ///be/, parent incident JSQUE-021; the native half is ABC-020 (abc.close is a resource no-op today — release is GC-only, so every mmap below pins an fd until GC).
- Every map funnels through shared/ulog.js:42-48 each(): abc.mmap("ULOG",…), drain, drop to GC — NO caller closes; ditto withRO (ulog.js:262-267, its comment promises a close the code never does) and book's snapshot (:239).
- resolve_hash.treeAt (core/resolve_hash.js:161-178) = anchors climb (:61-70, 1 mmap) + discover row0Row (core/discover.js:85-91, 1 mmap) — 2 uncached mmaps of a wt's
.be per call, no memo anywhere in the chain.
- DOMINANT (~890 maps in one
status //WT drive): status mints a navLink per FILE ROW (views/status/status.js:326-327, hunk :298) → shared/nav.js:15-22 authority() → be.navTree → core/discover.js:328-334 runs THREE separate treeAt climbs = 6 mmaps of the same .be per file row.
- work view (views/work/work.js): classify + wtlog.open = 3-5 mmaps × N rows per drive (:216,:218; pin/URI-track rows add :227,:232,:237); registry() rebuilt every drive (:570 — packs, idx runs, refs redone); root wtlog opened twice (:468 after nodeTip); nodeAt per tree node (:157,:161).
- pager status line probes the context per keypress (views/bro/pager.js:460-461, 858-864 → discover.wtdir → treeAt) = 2-4 mmaps even on j/k — which otherwise correctly repaint from the row cache (:391-401, :527-528) and re-drive nothing.
- store.open (shared/store.js:160) builds a fresh reader per call (git.pack.mmap per keeper pack :183, idx :226, refs drain :419); ~200 packs held open = the 212-fd launch baseline. gitmodules.parse (shared/gitmodules.js:20): io.mmap, unclosed, no memo.
Goals
A resident session's fd count plateaus; one status //WT drive costs O(1) mmaps of the target .be instead of 6×fileRows; j/k costs zero file opens (the JSQUE-021 ruling).
- Red-first pty repro (recreate the shape of the lost fdcount/clickback tests): keypress loop and a
status //WT drive under a lowered RLIMIT_NOFILE — exhausts/grows today, plateaus after.
Constraints
- Rulings in force: j/k rerenders from the buffer, no opens; pager context changes ONLY by navigation (BRO-024) so context-keyed memos invalidate on nav, and per-drive memos reset at drive start (mutating verbs!); one-line status bar — message inline + trimmed, never a second inverse row.
- ALL URI/hash resolution stays on be/core/resolve_hash.js — memoize AROUND the canonical calls; never reimplement, fork, or bypass them.
- FORBIDDEN: any parallel ULOG read path (whole-file byte copies etc.) — the 2026-07-19 attempt of that got its whole worktree rm -rf-ed; mmap remains the one read mechanism and closing rides ABC-020 abc.close.
- abc.close is inert until ABC-020 lands — order the work so the reuse memos deliver the ~10× map-count cut on their own; the close calls are correct-by-construction now and activate with ABC-020.
- No unrelated edits, no edits to other tests; bro/color + bro/view goldens have pre-existing readdir-order flakiness — cross-check an untouched clone before blaming your diff.
WIP
Design decisions
TODOs
Blockers and bummers
Outcome