Skip to content

Prompt-cache health: stable prefix, watcher-default polls, read folding - #130

Merged
davidrhodus merged 1 commit into
mainfrom
feat/prompt-cache-health-and-bg-watcher
Jul 26, 2026
Merged

Prompt-cache health: stable prefix, watcher-default polls, read folding#130
davidrhodus merged 1 commit into
mainfrom
feat/prompt-cache-health-and-bg-watcher

Conversation

@davidrhodus

Copy link
Copy Markdown
Contributor

Summary

  • Stable request prefix: the system message is split — message[0] carries only stable content (identity, rules, cwd, project guides) and is hash-gated; volatile state (memory, task index, goal state, decisions) rides a [hi:context] block on each turn's user message, exactly one copy in the transcript. Mid-turn rounds are append-only, so provider prompt caches (implicit and explicit) actually hit.
  • Cache visibility: per-round prefix-divergence telemetry (prefix_stable_rounds / prefix_break_rounds / earliest_prefix_break) in TurnTelemetry and --report.
  • Watcher-default background polls: bash_output without wait_secs parks on the registry's change notification with escalating patience (15s→240s) instead of returning instantly — instant-poll API loops become structurally impossible. wait_secs: 0 = explicit peek; HI_BG_POLL_WAIT_BASE_SECS=0 opt-out.
  • Superseded-read folding: older read results of the same (path, offset, limit) shape collapse to one-line digests, like the poll folding.

Evidence: a nanogpt session burned 8.09M input tokens on a ~75K-token conversation at 3.6% cache reads purely from per-round system-message churn; sol-view sessions burned an API round-trip per instant poll.

Testing

  • 1,589 tests pass across hi-agent, hi-tools, hi, hi-tui, hi-eval; no new clippy warnings.
  • New invariant test: system message byte-identical across all session requests, singular context block, ≤1 prefix break per turn, never at message 0.
  • Live runs: nanogpt (fresh + resumed turns — stable prefix, prefix_stable_rounds=3/0 breaks) and sol-view (four polls parked ~6s each on the watcher, turn ends with an honest status; 58% cache reads on a provider that previously reported zero).

🤖 Generated with Claude Code

…lls, superseded-read folding

Driven by real transcripts: a nanogpt session spent 8.09M input tokens on
a ~75K-token conversation at 3.6% cache reads, because the system message
was rebuilt every model round (memory ranking + task index churn), which
invalidated the entire prefix for implicit and explicit prompt caches
alike. A sol-view session showed background polls still costing one API
round-trip per instant peek whenever the model didn't pass wait_secs.

Stable request prefix:
- Split the system prompt: message[0] now carries only identity, rules,
  working directory, and durable project guides, and is replaced only
  when that content actually changes (hash-gated replace_system).
- Task-ranked memory, the task context index, session goal, long-horizon
  goal state, and the decision log move into a marked [hi:context] block
  attached to each turn's user message; the previous turn's block is
  stripped when the new one attaches, so exactly one copy exists and the
  per-turn prefix cost is one late re-anchor instead of a per-round
  message[0] invalidation. Mid-turn rounds are append-only.
- Durable state still survives compaction — it lives in agent state and
  is re-injected each turn, no longer parked in the system message.

Cache visibility:
- PrefixStability tracker hashes each outgoing request's message list and
  classifies every round append-only vs prefix-breaking. New telemetry:
  prefix_stable_rounds, prefix_break_rounds, earliest_prefix_break —
  wired through --report so metrics can watch cache health directly.
  (OpenAI-compat stream_options/include_usage was already requested.)

Watcher-default background polls:
- bash_output with no wait_secs now parks on the registry's change
  notification whenever the process is running with no new output,
  with escalating patience (15s→240s, reset by fresh output). wait_secs:0
  stays an instant peek; explicit N parks up to N (600 cap);
  HI_BG_POLL_WAIT_BASE_SECS=0 restores instant polls. Instant-poll API
  loops are structurally impossible regardless of model behavior.
- Live verification (sol-view, pipenetwork): four polls parked ~6s each
  and returned with fresh output; 58% cache reads on the same provider
  that previously reported zero.

Transcript hygiene:
- Superseded read results fold to a one-line digest per (path, offset,
  limit) shape, mirroring the bash_output poll folding (one session had
  re-read src/model.rs 21×; only the newest copy reflects the file).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@davidrhodus
davidrhodus merged commit 30b6fa2 into main Jul 26, 2026
1 check failed
@davidrhodus
davidrhodus deleted the feat/prompt-cache-health-and-bg-watcher branch July 26, 2026 00:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant