0.167.5
Fixed
- Ложный 409 Conflict при сохранении на странице
/agents/{id}/soul. При нажатии «Сохранить душу» появлялся баннер «agent was modified by another request, please retry», аdescriptionиthinking_levelфактически не сохранялись. Это второй экземпляр того же класса бага, что был закрыт в для/permissionsи/mcp. Причина —save()вweb/src/routes/agents/[id]/soul/+page.svelteшлётapi.soul.updateиapi.agents.updateпараллельно черезPromise.all. Оба пишут в таблицуagents:UpdateAgentSoul(internal/store/sqlite.go:538, PG-аналогpostgres.go:708) безусловно бампаетupdated_at, аAgentHandler.Update(internal/server/handler/agent.go:272) идёт черезUpdateAgentIfNotChangedс optimistic lockingWHERE id=? AND updated_at=?. Еслиsoul.updateкоммитится внутри race-окна второго запроса —agents.updateвидит устаревшийupdated_at, получаетRowsAffected=0→ErrConcurrentModification→ HTTP 409.Promise.allреджектится целиком → пользователь видит ошибку, а часть изменений теряется. Фикс: запросы выполняются последовательно (soul.update→agents.update); ответsoul.updateприменяется к локальному стейту сразу после первого запроса, чтобы при падении второго retry не переслал «грязные» локальные данные. Порядок soul → agents критичен: безусловный writerupdated_atдолжен идти первым, чтобы последующийagents.updateсделал свежийGetAgentи прошёл optimistic lock. Зеркало фикса #268 (web/src/lib/features/permissions/usePermissions.svelte.ts:109-148). Добавлен регрессионный vitest-тестweb/src/routes/agents/[id]/soul/save.test.ts, проверяющий строгую последовательность вызовов и отсутствие «частичного save» при паденииsoul.update. Проведён полный аудит всех страниц внутри/agents/{id}/**— других экземпляров бага нет.