0.167.27
Fixed
- Кластер фиксов аудита 2026-06 (#204, #205 — P2). (1) #203 [A-015]: байтовая обрезка
newText[:4000]soul_evolved в Dream резала многобайтовые UTF-8 руны (кириллица, эмодзи) — в БД и system prompt попадал инвалидный UTF-8. Теперь лимитsoulEvolvedMaxRunesсчитается в рунах, обрезка — rune-safe через общийtruncateRunesс маркером «…[обрезано]» (виден в UI и в следующем dream-цикле), hard limit синхронизирован с промптом («target max 1000 chars; hard limit 4000 chars»), no-op-детектnewText == currentSoulперенесён после обрезки (сравнивает фактическое сохраняемое значение). (2) #204 [A-016]: лимит summary/reflection в skill_tool намеренно остаётся в БАЙТАХ — он согласован с PG CHECKchk_skill_runs_summary_size/reflection_size(миграция 089,octet_length), а rune-based Go-чек разошёлся бы с БД для кириллицы/эмодзи. Расхождение с JSON Schema устранено явно: description параметров и сообщение об ошибке называют единицу («4000/8000 UTF-8 bytes, multibyte characters count as 2-4 bytes each») — прежде schemamaxLength(code points) и текст ошибки молча подразумевали разные единицы, и LLM с 4000 кириллическими символами получал непонятный reject на 8000 байтах. (3) #205 [A-017]: data race на полеloggerв SkillReflectionJob —SetLoggerписал голое поле без синхронизации,reflectSkillчитал из другой горутины (на практике main.go зовёт SetLogger до Start, но контракт этого не гарантирует). Поле переведено наatomic.Pointer[llmlog.Logger](Store/Load), nil-семантика сохранена. Тесты: rune-safe обрезка на 4500 рунах кириллицы+эмодзи (валидный UTF-8, лимит+маркер) и позитивная граница (500 рун сохраняются дословно); байтовый лимит на кириллице (2000 рун=4000 байт проходят, 2001 руна=4002 байта и 4001 руна reflection — reject с указанием единицы); конкурентные Store/Load логгера под-race. Попутно устранён пре-существующий data race вTestMaybeCompactAsync_EnabledGate/TestMaybeCompactAsync_TryLock(наблюдатели читалиfakeProvider.callsAllбез мьютекса; добавлен потокобезопасныйcallsSnapshot()) —go test -race ./internal/memory/...теперь чистый.