0.155.0

Added

  • PWA: корректное кэширование + Service Worker — исправление белого экрана при обновлении. После обновления бинарника TaigaClaw (новая версия WebUI зашита через go:embed) между запусками PWA на Android пользователь получал белый экран, лечившийся только ручным pull-to-refresh. Корневая причина: internal/webui/embed.go отдавал index.html и ассеты без Cache-Control → браузер применял heuristic caching (RFC 7234), держал устаревший index.html со ссылками на удалённые хешированные бандлы → 404 → белый экран; в standalone-PWA жест обновления недоступен. См. ADR docs/adr/2026-07-01-pwa-caching.md.
  • HTTP-заголовки (базовый слой, internal/webui/embed.go). index.html и SPA-маршруты — Cache-Control: no-cache + ETag (SHA-256, sync.Once) + Vary: Accept-Encoding + 304 на If-None-Match (браузер всегда revalidate’ит HTML → актуальные ссылки на бандлы). /_app/immutable/*public, max-age=31536000, immutable (имя уникально по содержимому). Прочая статика — public, max-age=3600 + Vary. SPA-fallback для удалённого бандла отдаёт HTML с no-cache. Отсутствие dist/index.html500 с диагностикой (не 404).
  • Service Worker (web/static/sw.js). Навигации — network-first (кэш index.html под canonical /, offline-выдача из кэша → офлайн-режим); /_app/immutable/* — cache-first. Кэшировать только fresh.ok (иначе временная 404 прилипнет). Версия кэша подставляется при сборке (Makefile: __TC_SW_VERSION__git describe), с sentinel-предохранителем (не чистить кэши, если подстановка не прошла). Кэши открываются один раз (memoization, без TOCTOU). SW не регистрируется в dev.
  • UI-промпт обновления. Регистратор web/src/lib/sw.ts ловит updatefound/уже-ждущий reg.waiting → стор swUpdate.svelte.ts → баннер SWUpdateBanner.svelte («Доступна новая версия / Обновить / Позже»). «Обновить» шлёт {type:'SKIP_WAITING'}controllerchange → один reload (флаг __tcReloading против зацикливания; controller !== null гейтит reload при первом заходе). Предохранитель 5с разблокирует кнопку при отсутствии reload.
  • Сборка (Makefile). build-webui/build-webui-dev: sed-подстановка версии в sw.js (delimiter #, test -f guard). Layout +layout.svelte переведён на flex-col (баннер больше не обрезает контент).
  • Проверки: 7 новых тестов в internal/webui/embed_test.go. go test ./internal/... — зелёно; golangci-lint — 0 замечаний; npm run check — 0 ошибок; npm test — 571/571; make build-cross — 6 бинарников; цикл ocr review — валидные замечания устранены (fd leak, load-event-баг, 504→503, кэш не-OK, layout, sentinel, memoization), невалидные/over-engineering обоснованно отклонены.