From b8d9aa4fce78f4523cffaba8b46095d2dfb66310 Mon Sep 17 00:00:00 2001 From: blasty Date: Sat, 25 Jul 2026 23:03:10 +0200 Subject: projects phase 4: cross-binary back, linkage-guided pre-warm, project verbs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three things, all following from phase 3 making cross-binary jumps ordinary. **A cross-binary jump was a one-way door.** Nav history is per-binary, so arriving in another binary — a project search hit, or now following an import into the library that implements it — landed you in an empty history with nothing to take you back. _switch_then_goto records the binary it came FROM, and action_back falls through to that hop once local history is spent: Esc walks back through the function you were in, then the binary you were in. Manual Ctrl+O switching records nothing, because that isn't navigation. **Pre-warm follows the linkage graph, not list order.** _prewarm_provider warms the binary providing the most of this one's imports — where a follow is most likely to go, so its startup is paid before you ask for it. "Next in the list" would have been arbitrary; phase 3 gave us something better to ask. pool.prewarm() refuses rather than making room. Evicting a binary the user visited to speculatively load one they haven't is a straight downgrade, and it throws away that binary's caches as well; at a tight budget pre-warm just does nothing. The cost of a worker that doesn't exist yet can only be estimated, so it uses the largest resident one (same program, different database) — and if that estimate proves wrong, the speculative worker is the one evicted, never a chosen one. **Driving a project.** pane spawn --project FILE [--open BIN]; `binaries` lists the inventory (active / resident / indexed / where Esc returns to) and `switch {binary,addr?}` makes another active — with an address it takes the search-hit path, so it records a hop. state gains `binary` and `hops`, which it should have had the moment project mode existed. Verified on real sessions: drive binaries/switch against an echo+cat project pane; Esc crossing back from a switch; and prewarm on echo+libc picking libc (provider of echo's imports) and warming it after an evict. tests: +5 pool (prewarm warms, no-ops when resident, refuses at budget, evicts nothing when refusing, ignores unknown labels) and +4 project UI (jump records the hop, Esc crosses back, hop consumed). Confirmed the Esc-back checks fail with the branch removed. 195/0 scenarios, 27/0 project UI, 36/0 index, 27/0 pool, 33/0 project. Left open: project-level persistence across sessions. --- tests/test_pool.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'tests/test_pool.py') diff --git a/tests/test_pool.py b/tests/test_pool.py index d4347d9..5c6e2c4 100644 --- a/tests/test_pool.py +++ b/tests/test_pool.py @@ -155,6 +155,35 @@ def main() -> int: check("default budget is derived, not a fixed worker count", pool3.budget_mb >= 256, pool3.budget_mb) + # -- prewarm: speculative, and never at the cost of a real binary ------ # + with tempfile.TemporaryDirectory() as tmp: + proj = _mkproject(tmp, n=3) + made2 = {} + + def spawn2(ref, ttl): + c = FakeClient(ref, mem=100) + made2[ref.label] = c + return c + + pool = WorkerPool(proj, budget_mb=250, spawn=spawn2, + mem_fn=lambda c: c.mem) + labels = [r.label for r in proj.refs] + a, b, c_ = labels[0], labels[1], labels[2] + pool.get(a) + pool.set_active(a) + check("prewarm warms a binary when the budget has room", + pool.prewarm(b) is True and b in pool.resident(), f"{pool.resident()}") + check("prewarm is a no-op for something already resident", + pool.prewarm(b) is False) + # 2 x 100MB resident, estimate 100 more -> 300 > 250: must refuse + check("prewarm refuses rather than making room", + pool.prewarm(c_) is False and c_ not in pool.resident(), + f"resident={pool.resident()} mem={pool.memory_mb()}/{pool.budget_mb}") + check("refusing to prewarm evicts nothing", + set(pool.resident()) == {a, b}, f"{pool.resident()}") + check("prewarm ignores a label outside the project", + pool.prewarm("nope") is False) + print(f"\n{PASS} passed, {FAIL} failed") return 1 if FAIL else 0 -- cgit v1.3.1-sl0p