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 locking WHERE id=? AND updated_at=?. Если soul.update коммитится внутри race-окна второго запроса — agents.update видит устаревший updated_at, получает RowsAffected=0ErrConcurrentModification → HTTP 409. Promise.all реджектится целиком → пользователь видит ошибку, а часть изменений теряется. Фикс: запросы выполняются последовательно (soul.updateagents.update); ответ soul.update применяется к локальному стейту сразу после первого запроса, чтобы при падении второго retry не переслал «грязные» локальные данные. Порядок soul → agents критичен: безусловный writer updated_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}/** — других экземпляров бага нет.