0.167.11
Fixed
memory_contextмолча выбрасывался всеми провайдерами, но расходовал токен-бюджет (P0). Рольmemory_context— единственный механизм, компенсирующий отсутствие tool-контекста между ходами (ADR 2026-07-02): трасса tool-работы хода (persistToolTrace) и результатыmemory_search. Оба провайдерных конвертера имелиswitch m.Roleбезdefaultи безcase "memory_context"— сообщение не матчило ни одну ветку и тихо исчезало перед отправкой к LLM, при этом грузилось из БД, считалось вhistoryTokensи запускалоenforceMemoryContextBudget, который при «переполнении» выбрасывал другие сообщения. Фикс (1) — доставка:internal/providers/openai_compat.go—case "memory_context"переписывает сообщение вsystemна своей позиции в массиве (семантическая смена: инструкция, а не реплика; статично — не хойстится в dynamic-system prefix, зарезервированный за промпт-инжинирингом, #278);internal/providers/anthropic.go— вuser-сообщение (system у Anthropic вынесен в отдельное поле API). Оба конвертера получилиdefault-ветку: неизвестная роль деградирует (system/user) сslog.Warn(msg_index,content_len,dropped_fields) — тихая потеря сообщений исключена в принципе. ПомощникиdegradedSystemMessage/degradedUserMessageприменяют fallback" "для пустого/whitespace-only контента (пустой text block — 400 от Anthropic; часть openai-совместимых бэкендов отвергает пустой content) с WARN-логом;degradedRoleFieldNamesперечисляет структурные поля (tool_calls, tool_call_id, tool_name, is_error, media, reasoning_blocks), не переживающие текстовую деградацию — потеря наблюдаема в логах; WARN о потере зеркален и вcase "memory_context"(продюсеры ставятToolName="tool_trace"). Merge-hazard задокументирован и запинен тестом: реальная топология БД[..., assistant, mc, user(след.ход)]после user-переписывания даёт смежные user-ходы, которыеmergeConsecutiveAnthropicсливает в одно multi-block сообщение — текст retrieved-контекста доезжает до модели (блоки: контекст → реплика пользователя), теряется только per-message identity. Фикс (2) — бюджет:enforceMemoryContextBudget(internal/agent/actor.go) сравнивал сcontextMaxTokens/4токены ВСЕЙ истории — на модели 128K выброс memory_context начинался, как только диалог сам превышал 32K токенов, независимо от объёма retrieved-контекста. Теперь бюджет меряется по самим memory_context-сообщениям (estimateMessageTokens, без slice-оверхедаEstimateTokens): старейшие вне tool-пар удаляются, пока остаток не уложится. Unit-тесты:internal/providers/memory_context_delivery_test.go— memory_context доставляется (system для OpenAI-compat, user для Anthropic) с сохранением позиции; merge с следующим user-ходом; неизвестная роль не теряется (оба провайдера);internal/agent/audit_medium_agent_test.go— огромный диалог не трогает маленький mc (регрессия старой семантики); переполнение выбрасывает старейшие mc до укладки в бюджет. Пункт 3 issue (прекратить запись tool-трассы) осознанно отложен до реализации ADR live-tool-messages (#280): сейчас трасса — единственный механизм осведомлённости о tool-работе. Проверки:go test ./...— ok;golangci-lint ./internal/...— 0 issues;ocr review— цикл до стабилизации (9 прогонов, актуальные замечания устранены, остальные — обоснованно неактуальные/LOW);make build-cross— 6/6.