fix: one session sends byte-identical tools[] across TUI, oneshot and gateway hops

The session tools pin (sessions.tool_names) stored names only, so every fresh
process re-materialized the bytes from its own surface and every surface hop
of one durable session was a full prompt-cache miss:

* tool_search's deferred catalog is built per process ("Search 6 additional
  tools" in the TUI gateway vs 5 in -q);
* a pinned tool missing from the fresh build (skill_manage under the -q
  footprint) came back from the static registry schema, without its
  dynamic_schema_overrides;
* a -q --resume that rebuilt the stored prompt (model switch, cwd drift)
  persisted its own pruned array over the pin.

The pin now stores the full definitions and restore replays a pinned tool that
is still available byte-for-byte (deregistered tools drop, new ones append at
the tail, legacy name-only pins still work). A continuing session whose prompt
is rebuilt applies the pin before building it, matching the freeze policy
(tools[] only changes on /new, /reload-mcp, compaction). The array is
content-addressed in the existing system_prompts store like the prompt itself,
so identical arrays across sessions are stored once; get_session resolves it.
This commit is contained in:
teknium1
2026-09-23 06:58:16 -07:00
committed by Teknium
parent 01217c5fc2
commit 7a31c365c3
7 changed files with 149 additions and 46 deletions

View File

@@ -669,6 +669,8 @@ CREATE INDEX IF NOT EXISTS idx_sessions_handoff_state
ON sessions(handoff_state, started_at);
CREATE INDEX IF NOT EXISTS idx_sessions_system_prompt_hash
ON sessions(system_prompt_hash);
CREATE INDEX IF NOT EXISTS idx_sessions_tool_names
ON sessions(tool_names);
-- Recent-session browsing must never derive recency by scanning messages.
-- This expression is the durable, indexable approximation used to preselect
-- a small candidate set before compression-chain and preview hydration.