# Фаза 58. SchoolWorker и карточка ## Зависимости Нет. Поведение уже покрыто хостом и клиентскими тестами карточки. Этап A (56, 57) не обязан быть зелёным, но резать удобнее после tsc в `npm test`. ## Зачем Три файла держат слишком много швов: почта работника, тик, запись; сборка карточки; вкладки DOM. Разрезать по существующим границам, не меняя поток и JSON. ## Задачи - [x] `SchoolWorker` — `partial` (почта / тик / запись или эквивалент по швам). Один тип, тот же `LongRunning`-поток, тот же mailbox. Без `lock` вокруг `School`/`World` - [x] `PersonCardReader`: публичный вход по-прежнему `Read(School, personId, locale)`; сборка вкладок — соседние `internal` helper или `partial`, не второй публичный API - [x] `personCard.ts`: вкладки в отдельных модулях; `personCardHost.ts` по-прежнему fetch - [x] Инверсия Game → типы из `HSchool.Server.Api` **не** входит: `using` можно оставить ## Тесты, без которых фаза не закрыта - [x] Карточка: нужды, одежда/ноша, связи — как сейчас (`PeopleApiTests`, `InventoryApiTests`, `Card_ConnectionsCarryOnlyThisPersonsOpinions`) - [x] `personCard.test.ts` (вкладки, портрет-кнопки, связи) проходит - [x] Пауза одной школы не останавливает другую (существующий хостовый факт) - [x] Дамп школы по-прежнему 200 на известный id (`Dump_ReturnsPeopleNodesAndTimetable` — текущий оракул, ужесточение — фаза 59) - [x] `SchoolWorker` остаётся одним `internal sealed` типом (рефлексия или исходник: нет второго worker-класса с mailbox) ## Критерий готовности - Открыть школу, карточку, паузу — как вчера - Нет нового публичного фасада карточки и нет второго потока на школу ## Стоп Не менять инвариант 3. Не инвертировать DTO. Не трогать протокол, сейв, SwarmUI. Не резать `GameLoopService` «заодно».