v0.1.33 - cache-friendly llama.cpp agent-loop release
v0.1.33, cache-friendly llama.cpp agent-loop release (2026-04-10)
This release turns Successor's local-model loop into something that is
KV-cache-friendly by design instead of by luck.
The core change is architectural: the request builder now keeps the
cache-critical system prefix stable across ordinary turns, moves
volatile ledger/reminder state to a tail context message, and makes the
llama.cpp cache/slot path explicit instead of relying on server
defaults. The budget UI, fill bar, and autocompact gate also now read
from the same canonical outbound request envelope, so context reporting
tracks what the harness actually sends.
What landed
src/successor/chat_agent_loop.py- splits prompt assembly into a stable system bundle and volatile
tail-only runtime sections - caches the stable rendered prompt on the chat instance
- records stable/volatile hashes and cache metadata in trace events
- keeps one-turn reminders, ledger/runtime nudges, and other
per-turn state out of the cache-critical front of the prompt
- splits prompt assembly into a stable system bundle and volatile
src/successor/context_usage.py- new canonical request-envelope layer used for both prompt assembly
accounting and runtime budget reporting - tracks stable-system hash, volatile-tail hash, cache-break reasons,
slot id, and prompt-cache preference per turn
- new canonical request-envelope layer used for both prompt assembly
src/successor/providers/llama.py- explicitly sends
cache_prompt=true - supports preferred
id_slotwhen llama.cpp exposes slot support - adds exact
/tokenizesupport for llama-backed token accounting
- explicitly sends
src/successor/chat.py- applies provider cache preferences on live client/profile changes
- reserves a foreground slot for the parent chat when slot-aware
background scheduling is available - aligns post-compact cache-warmer behavior with the deferred-turn
resume path
src/successor/subagents/manager.py- routes child chats onto non-foreground slots when available
- claims and releases child slot affinity explicitly
src/successor/tasks.py- splits stable task primer guidance from volatile execution state
src/successor/verification_contract.py- splits stable verification primer guidance from volatile runtime
verification state
- splits stable verification primer guidance from volatile runtime
src/successor/runbook.py- splits stable experiment/runbook primer guidance from volatile
attempt/runtime state
- splits stable experiment/runbook primer guidance from volatile
src/successor/providers/openai_compat.py- preserves tool-call fields and
tools=handling so the generic
OpenAI-compatible path stays coherent with the new request envelope
- preserves tool-call fields and
- docs
- adds:
docs/chat-agent-loop-refactor-plan.mddocs/chat-display-runtime-refactor-plan.md
- updates:
docs/chat-runtime-refactor-plan.mdREADME.mdCHANGELOG.md
- adds:
Release verification
- lint:
ruff check src tests
- full suite:
PYTHONPATH=src pytest -q1256 passed in 25.00s
- live supervised E2E:
- workspace:
/home/lycaon/Desktop/successor-kv-cache-e2e-20260410
- trace:
/home/lycaon/.config/successor/logs/20260410-142431-p898945.jsonl
- app:
/home/lycaon/Desktop/successor-kv-cache-e2e-20260410/command-cascade.html
- screenshots:
/tmp/command-cascade-initial.png/tmp/command-cascade-autoplay.png
- observed cache behavior:
- stable system hash remained
e13605d528a0 - volatile tail hash changed independently across turns
- llama requests carried
cache_prompt=true - foreground chat stayed on slot
0
- stable system hash remained
- observed runtime behavior:
- the model adopted
taskandverify - the model authored the app with native file tools
- the model found and fixed a real runtime logger bug on its own
- independent Playwright verification passed for:
- start screen load
- start-game transition
- correct-command scoring
- autoplay/debug flow
- the model adopted
- remaining limitation surfaced by the run:
- browser
typestill failed on a custom input control and the
supervised loop spent too long retrying selector variants instead
of pivoting immediately to a deterministic fallback
- browser
- workspace: