Record a tool failure to episodic memory (best-effort, opt-in). Only fires when * failure-driven learning is enabled; the pattern miner later decides what's worth * learning. Fire-and-forget — never blocks or throws into the loop.
(tool: string, content: string)
| 134 | private currentTurn = 0; |
| 135 | /** |
| 136 | * Mid-task steering queue. The UI pushes `/btw …` notes here while a run is in |
| 137 | * flight; the run loop drains them at the top of each iteration and injects them |
| 138 | * into the conversation so the model can adjust course without being stopped. |
| 139 | * Single-threaded JS event loop ⇒ no lock needed. |
| 140 | */ |
| 141 | private steerQueue: string[] = []; |
| 142 | /** Session ledger of files the model has demonstrably read (read-before-write gate). */ |
| 143 | private readLedger = new ReadLedger(); |
| 144 | /** Skills already auto-injected this session — never inject the same one twice. */ |
| 145 | private autoInjectedSkills = new Set<string>(); |
| 146 | /** Monotonic union of tool names shipped this session. The relevance gate only ever |
| 147 | * ADDS to this — never drops — so the tools block stays a byte-stable cache prefix |
| 148 | * across turns (a sliding per-turn set would flip and invalidate the prompt cache). */ |
| 149 | private sessionToolNames = new Set<string>(); |
| 150 | /** Where the active model is actually served from ('ollama'/'lmstudio'/'anthropic'/…) and |
| 151 | * its LIVE context window — set each iteration, forwarded on budget_update for the UI. */ |
| 152 | private lastModelSource = ''; |
| 153 | private lastEffectiveCtxWindow = 0; |
no test coverage detected