Repository navigation
🤖 fix: keep the cached tool block when the skill list changes mid-session - #7308
Conversation
…sion Inside a context segment, the "Available skills" index of the agent_skill_read tool description now stays at the list the segment first sent, read from the ledger (MuxMetadata.skillIndex). A changed list goes in one system row after the newest user message, and every rebuild puts the row back in place, so the cached tool block stays byte-identical. A new skill still reaches the model: the row names it, and agent_skill_read loads any skill by name. The next compaction folds the current list into the description. Same mechanism and gating as the custom-instructions and volatile-tail records. --- _Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high -->
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
🟢 e2e stories (Haiku): 14 passed27 agent steps · 7 replayed from cache · 32 model calls · 236.9k tokens (76% cached) All 14 tests in 9 files
e2e 0.20.0 · 3m 9s · web · run artifacts 🟢 e2e Electron stories (Haiku): 3 passed3 agent steps · 3 model calls · 8.1k tokens (32% cached) All 3 tests in 3 files
e2e 0.20.0 · 19.6s · electron · run artifacts 🟢 e2e agent repros (Haiku): no tests selectedSpend: $0.00 of the $1.00 cap (proxy ledger) e2e 0.20.0 · 5.3s · 2 targets (web, phone) · run artifacts |
# Conflicts: # src/node/services/turnContextAssembler.test.ts # src/node/utils/messages/volatileSystemTail.ts
…ewrite The merge of d9b2461 moved the empty-baseline fix into planRemovableSection, so the skill index gets it too: a segment that starts with no skill listed records "" and a first skill becomes a replacement row. This test covers that path and fails with the baseline record removed. --- _Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high -->
|
Post-merge perf note (perf owner), covering #7304 ( What changed on the turn path: each turn now plans three system sections (volatile tail, custom instructions, skill index) instead of one. Each plan slices the segment after the latest context boundary and, once a segment has a frozen record, rebuilds the message array with one Measured on main
This is far below the send-path trigger I track on #6912 (>= 50 ms per turn). If a fourth section joins this pattern, or segments of 100k+ rows become common, the three plans can share one segment read and one Generated with |
Summary
A skill added to or removed from a workspace mid-session no longer rewrites the cached Anthropic tool block. Inside a context segment (between compactions), the "Available skills" list in the
agent_skill_readtool description stays at the list the segment first sent, and Xum reads it from the ledger (chat.jsonl). When the live list differs, Xum sends the new list as one system row after the newest user message, so the model knows about the new skill on that turn. Every later rebuild puts the row back in place. The next compaction folds the current list into the description. Stacked on #7304, which does the same for AGENTS.md.Background
Measured on one host (10-22 08:12 to 10-23 01:28 UTC, 1,548 Anthropic turns): 10
cache.prefix_breakevents onagent_skill_readin the tools section, 0.64 rewritten histories per 100 turns. The description grew from 11,129 to 11,392 chars after skill commits merged on main, when agents merged main into their worktree. The tools section is the first part of the cached prefix, so each change rewrote the whole history.Implementation
MuxMetadata.skillIndex = { text, placement: "system" | "row" }, the same shape, schema and rule ascustomInstructionsandvolatileSystemTail. A corrupt value loads as no record. Xum writes it only at a segment start and on a change.skillIndexSectionFor(agent_skill_read.ts) reports the description prefix and the skill list, and the assembler freezes the list only while the description still starts with that prefix. It does not search the description for markers.agent_skill_readloads any skill by name.Validation
Risks
Medium-low. It changes only how the
agent_skill_readdescription is built for Anthropic turns.Tool: <name>sections from AGENTS.md also go into tool descriptions and are still not frozen (follow-up).Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high• Cost:$585.33