Remove off-queue.md and add new design documentation files including README.md, defs.md, near-term.md, projects.md, runtime.md, people.md, staffing.md, and schedule.md to outline the structure and agreements for the game's design phases.

This commit is contained in:
Leonid Pershin
2026-08-20 12:26:13 +03:00
parent 12cc36b4dd
commit a37a5eb82d
101 changed files with 1015 additions and 921 deletions
+49
View File
@@ -0,0 +1,49 @@
# Фаза 29. Страна
## Зависимости
- [Фаза 5](../02-people/05-people-defs.md)
- [Фаза 26](../06-foundation/26-school-seed.md)
## Зачем
Create выбирает страну, а не набор имён. Имена и климатические пресеты перестают быть двумя
несвязанными пикерами.
## Задачи
- [x] `CountryDef` и `ClimatePresetDef` в `HSchool.Content`: страна вкладывает нынешние поля
набора имён в `names`, ссылается на пресеты списками id
- [x] Набор имён больше не выбираемый вид; папка `namesets/` в `core` уезжает в страну
- [x] Ваниль: одна страна `Russia` с нынешним славянским набором и хотя бы одним пресетом
(числа погоды можно заглушить — живая улица в фазе 32)
- [x] `GET /api/catalog` отдаёт `countries` (`defName`, подпись, `nativeLanguages`,
`climatePresets`) вместо `nameSets`
- [x] `POST /api/schools` принимает `countryId`; неизвестный — `400` `unknown-country`.
`nameSetId` не принимается
- [x] Пресет климата записывается на школу: случайный из списка страны, от сида. Живой школе
его не сменить
- [x] Форма создания: подпись «Страна»; язык — если у страны их несколько
- [x] Старый сейв с `nameSetId: Slavic` поднимается как `Russia` + первый пресет; формат
новее без `countryId` — как с прочими полями сейва, школа не стартует
- [x] `docs/protocol.md` и `AGENTS.md` (ориентир create / каталог) в том же коммите
- [x] Золотой отпечаток ростера обновляется, если вход генератора сменил имя поля
## Тесты, без которых фаза не закрыта
- [x] Каталог `core` грузится; страна без имён или с неизвестным пресетом — ошибка загрузки
- [x] Create с `countryId: Russia` и без языка даёт тот же родной язык, что прежний сид без
`nativeLanguage`
- [x] Create с неизвестной страной — `400` `unknown-country`
- [x] Два create с одним сидом получают один и тот же пресет
- [x] Старый сейв без страны поднимается
- [x] Диалог создания показывает страны, не наборы имён; смена страны обновляет список языков
## Критерий готовности
- Создать школу, выбрав страну; люди и язык как раньше на том же сиде
- `dotnet test` и `npm test` / `build` проходят
## Стоп
Не считать живую погоду. Не одевать людей. Не менять кадр часов.
@@ -0,0 +1,43 @@
# Фаза 30. Слои и палитра
## Зависимости
- [Фаза 3](../01-shell/03-defs-map.md)
## Зачем
Каталог умеет описать одежду и ношу, не путая их с партой. Никто ещё ничего не носит.
## Задачи
- [x] Поля `ThingDef`: `layers`, `portable`, `mass`, `insulation`, `formality`, `age`, `sex`,
`colors`, `skirtLength`, `pe`. Пустые `layers` — прежняя мебель, карта не ломается
- [x] Слои — известный набор в коде (`Underwear``Accessory`), как роли. Неизвестный слой —
ошибка загрузки
- [x] `ColorDef`: id и теги (`neutral`, `bright`, `school`). Ссылка вещи на неизвестный цвет —
ошибка
- [x] Вещь с несколькими `layers` допустима (платье). Пересечение слоёв у двух надетых сразу
валидатор не проверяет — это состояние человека, не каталога
- [x] Ваниль по [`docs/design/07-inventory/inventory.md`](../../design/07-inventory/inventory.md): бельё, носки, низы, верх,
свитер, куртка/пальто/шуба, обувь, шапка, аксессуары, платье, форма физкультуры,
портфель, учебник, телефон, бутылка
- [x] Палитра цветов и локали ru/en на все новые def
- [x] Учебник — один `ThingDef` без зашитого предмета; предмет живёт на экземпляре в фазе 31
- [x] Мебель на карте по-прежнему без `layers`; редактор не предлагает надеть стул
## Тесты, без которых фаза не закрыта
- [x] `Chair` без новых полей грузится как раньше
- [x] Платье с `layers: ["Bottom", "Top"]` проходит; неизвестный слой — ошибка
- [x] Футболка ссылается на `Red`; отсутствие `Red` в палитре — ошибка
- [x] Тест полноты локалей зелёный на новый набор
- [x] Ванильная карта и каталог предметов (мебель) не изменились по вместимости
## Критерий готовности
- Каталог `core` грузится, школы создаются, люди голые
- `dotnet test` проходит
## Стоп
Не генерировать экземпляры. Не трогать карточку и create сверх того, что уже есть.
@@ -0,0 +1,49 @@
# Фаза 31. Генератор одевает
## Зависимости
- [Фаза 29](29-country.md)
- [Фаза 30](30-apparel-defs.md)
- [Фаза 6](../02-people/06-people-generator.md)
## Зачем
Люди рождаются одетыми. Гардероб детерминирован и лежит на человеке в `people.json`.
## Задачи
- [x] Экземпляр вещи на человеке: `def`, `color`, `condition` (1), место (`worn` / `bag` /
`locker` / `home`), для учебника — `subject`
- [x] Генератор одевает учеников, сотрудников, родителей и соискателей от семейного сида:
слои без пересечения, пол, возраст, дефолтные правила (обычная форма, без яркого на теле)
- [x] Учебники — по одному на предмет параллели ученика; в сумке пока могут лежать все, разнос
«сегодняшние vs шкафчик» — в фазе 33/35
- [x] Портфель, телефон, бутылка — с возрастом и шансом из данных, не из константы в генераторе
- [x] Навык `Hauling` (`always`); предел массы в дефе правил; на карточке несёшь/можешь.
Перегруз ходьбу не трогает; в сумку сверх предела генератор не кладёт
- [x] `GET .../people/{id}` отдаёт надетое и ношу; список людей — нет
- [x] Карточка пока без вкладок: секции «Одежда» и «Ноша» в том же свитке
- [x] `people.json` пишется при создании и наборе; золотой отпечаток обновляется в этом коммите
с объяснением, что изменилось
- [x] Строки через `t(...)` / локали каталога
## Тесты, без которых фаза не закрыта
- [x] Тот же сид, страна, карта и язык → те же id вещей, цвета и места
- [x] На одном слое не две вещи; платье занимает низ и верх сразу
- [x] Юбка не выдаётся мужчинам на тело; яркий верх не выдаётся на тело при дефолтных правилах
- [x] Ученик параллели с математикой имеет учебник этого предмета
- [x] Родитель и соискатель одеты
- [x] Масса в сумке ≤ предела
- [x] Старый `people.json` без инвентаря поднимается: генератор одевает при загрузке и пишет
файл (как пул соискателей в фазе 11)
## Критерий готовности
- Открыть карточку ученицы: слои заполнены, цвет виден, ноша с числом
- Повтор create с сидом даёт ту же рубашку
- `dotnet test` и `npm test` / `build` проходят
## Стоп
Не считать погоду. Не изнашивать. Не переодевать по ситуации. Не заводить вкладки карточки.
@@ -0,0 +1,45 @@
# Фаза 32. Погода и тепло
## Зависимости
- [Фаза 29](29-country.md)
- [Фаза 20](../05-ai/20-needs-actions.md)
## Зачем
На улице есть температура и осадки. Человек может мёрзнуть. Часы это показывают.
## Задачи
- [x] `ClimatePresetDef` получает рабочие числа: нормы по месяцам, разброс дня, осадки
- [x] Школа считает улицу из пресета + сида + даты/часа; не каждый тик, а когда меняется
надпись или это сдвинет тепло
- [x] В здании теплее улицы за счёт стен, без техника ещё не комфорт (комфорт — фаза 33)
- [x] Двор и крыльцо — улица
- [x] Нужда `Warmth`: декей от разницы «утепление одежды vs температура места»; вне школы
восстанавливается, как сон
- [x] Черты теплолюбивый / холодолюбивый: поле смещения комфорта на `TraitDef`, взаимно
несовместимы
- [x] Кадр часов: температура (десятые доли °C, `i16`) и осадки (`u8`). Версия протокола +1.
`ProtocolCodec.cs`, `protocol.ts`, `docs/protocol.md` в одном коммите
- [x] Клиент рисует погоду у даты; не считает её из месяца
- [x] Пропуск пустого времени выставляет погоду утра, не вчерашнюю
## Тесты, без которых фаза не закрыта
- [x] Тот же пресет, сид и timestamp → та же температура и осадки
- [x] Январь холоднее июля на ванильном пресете
- [x] Ниже нуля осадки — снег, не дождь (если пресет вообще дал осадки)
- [x] На морозе без верхней одежды тепло падает; дома за ночь возвращается
- [x] Кадр часов круглый трип и байтовая раскладка на обеих сторонах
- [x] Клиент с старой версией протокола отваливается Hello, как обычно
## Критерий готовности
- У часов видно «−5 °C, снег» зимним утром
- Полоска тепла на карточке шевелится
- `dotnet test` и `npm test` / `build` проходят
## Стоп
Не нанимать техника. Не переодевать по погоде — замёрзший ещё терпит. Не штрафовать урок.
@@ -0,0 +1,47 @@
# Фаза 33. Техник и шкафчики
## Зависимости
- [Фаза 31](31-dress-generator.md)
- [Фаза 32](32-weather-warmth.md)
- [Фаза 11](../03-staffing/11-applicants.md)
## Зачем
В школе можно нанять человека, который держит тепло зимой и прохладу летом. У учеников появляются
личные шкафчики — кому хватило.
## Задачи
- [x] `RoomDef` теплоузла и `PositionDef Technician`; комната открывает должность, как медкабинет
- [x] Ванильная карта: комната в основном корпусе, связана с коридором
- [x] Нанятый техник сдвигает внутреннюю температуру в комфортную полосу; без него здание
только демпфирует улицу. Числа — в дефе правил климата
- [x] Две раздевалки у спортзала: мужская и женская, разные def, свои шкафчики. Старый один
узел `changing-room` заменяется
- [x] Раздача: ученики этого пола, старшая параллель раньше, при равенстве id. Сотрудникам
шкафчик не дают. Не хватило — место `locker` пустое, вещи в сумке и дома
- [x] Пересчёт раздачи на годовом наборе (параллели сдвинулись)
- [x] Редактор: число шкафчиков в слоте по-прежнему меняется; после создания школы раскладка
заморожена, как вся карта
- [x] Карточка показывает, есть ли шкафчик (ещё без вкладки ноши)
## Тесты, без которых фаза не закрыта
- [x] Новая школа без техника: январский кабинет холоднее, чем с нанятым техником, и теплее
улицы
- [x] Нанятый техник в июле держит кабинет ниже раскалённой улицы
- [x] Две раздевалки на ванильной карте, граф связен
- [x] Шкафчиков 10 на 40 учениц — получают десять старших; одиннадцатая без шкафчика
- [x] Мальчик не получает слот девичьей раздевалки
- [x] После 1 сентября раздача пересчитывается, выпускник слот не держит
## Критерий готовности
- Нанять техника из пула — в январе в кабинете становится тепло
- Открыть карточку старшеклассника — шкафчик есть; у части младших нет
- `dotnet test` проходит
## Стоп
Не переодевать на физкультуру. Не изнашивать. Не делать вкладку «Правила».
+42
View File
@@ -0,0 +1,42 @@
# Фаза 34. Износ и дом
## Зависимости
- [Фаза 31](31-dress-generator.md)
- [Фаза 18](../05-ai/18-presence-walking.md)
## Зачем
Одежда портится на теле в школе. Из дома в лохмотьях не выходят — утром выдают свежую.
## Задачи
- [x] Прочность экземпляра 0–1; падает только у надетого, только пока человек в школе, от
игрового времени. Формула скорости — данные
- [x] Пороги подписей в дефе (`целая` / `поношенная` / `порванная` / `висит лохмотьями`);
карточка — полоска + подпись, клиент не считает пороги сам
- [x] Порог «не выходить»: утром вне школы ветхая надетая вещь заменяется свежей того же def
и цвета (или ближайшего уместного). Событие для истории фазы 36: тип и подпись готовы
даже если лог ещё не рисуется
- [x] Пропуск пустого времени применяет утреннюю замену, иначе после «пропустить» школа в
лохмотьях
- [x] Сумка и шкафчик не изнашиваются
- [x] `people.json` пишется после замены, не каждый тик износа: либо порог пересечён, либо
утренняя выдача
## Тесты, без которых фаза не закрыта
- [x] День в школе снижает прочность надетой рубашки на заявленную величину, ±эпсилон
- [x] Рубашка в сумке за тот же день не меняется
- [x] Человек с одеждой ниже порога к утру рабочего дня одет в свежую; def совпадает
- [x] Skip через ночь даёт ту же замену, что прожитая ночь
- [x] Подпись на карточке меняется вместе с порогом
## Критерий готовности
- Промотать несколько игровых недель — полоска одежды опустилась, потом утром обновилась
- `dotnet test` и `npm test` проходят
## Стоп
Не показывать историю вкладкой — только состояние вещи. Не переодевать по погоде.
@@ -0,0 +1,51 @@
# Фаза 35. Уместность
## Зависимости
- [Фаза 32](32-weather-warmth.md)
- [Фаза 33](33-lockers-technician.md)
- [Фаза 34](34-wear-home.md)
- [Фаза 21](../05-ai/21-decisions.md)
## Зачем
Система сама одевает по правилам, погоде и уроку. В школе переодевание — действие в своей
раздевалке; дома — мгновенно.
## Задачи
- [x] Оценка уместности из данных: пол, возраст, погода/утепление, `pe`, формальность,
цветовые теги, длина низа. Код знает оси, пороги — defs и правила школы
- [x] На школе хранятся правила учеников и сотрудников (форма + цвет). Дефолт: обычная,
без яркого. Смена с экрана — фаза 37; API уже пишет «с завтра»
- [x] «Короткая» форма: длина юбки / короткий рукав; младше порога возраста ходят в обычной
- [x] Дома утром: мгновенно подобрать надетое под правила, погоду и сегодняшний план
(учебники только сегодняшних уроков в сумке, остальное — шкафчик или дом)
- [x] В школе: действие `ChangeClothes` в своей (м/ж) раздевалке. Снятое — в шкафчик, если
есть, иначе в сумку
- [x] Цель «одеться к физкультуре» и «вернуться с формы» рядом с обязанностью урока; не
каждый тик, а по звонку / приходу
- [x] Цель «верх не по погоде» — дойти и сменить куртку, если уже в школе
- [x] Вместимость действия — сколько одновременно переодеваются в комнате; не путать с
числом шкафчиков
- [x] Игрок по-прежнему не одевает с карточки
## Тесты, без которых фаза не закрыта
- [x] Школа с «без яркого»: утром на теле нет цвета с тегом `bright`
- [x] «Короткая» + первоклассница → обычная длина; старше порога — можно короткое
- [x] Перед уроком физкультуры ученик идёт в свою раздевалку и надевает `pe`; после — снимает
- [x] Мальчик не идёт в женскую раздевалку
- [x] Без шкафчика снятое оказывается в сумке, не исчезает
- [x] Морозным утром на теле есть `Outer`; в июле шубы на теле нет
- [x] Смена правила через API сегодня не меняет одежду до следующего рабочего утра
## Критерий готовности
- На физкультуре в зале видно форму, не школьную рубашку
- Смена погоды за день гонит кого-то в раздевалку, не телепортирует куртку
- `dotnet test` проходит
## Стоп
Не рисовать вкладку «Правила». Не штрафовать урок за холод и «не по форме».
@@ -0,0 +1,49 @@
# Фаза 36. Вкладки карточки
## Зависимости
- [Фаза 31](31-dress-generator.md)
- [Фаза 8](../02-people/08-people-browser.md)
- [Фаза 28](../06-foundation/28-screen-tests.md)
## Зачем
Гардероб, ноша и сегодняшний след перестают быть секциями в одном свитке. Подробности о человеке
читаются.
## Задачи
- [x] Окно карточки: вкладки **Обзор / Одежда / Ноша / Сейчас**
- [x] Обзор — прежнее: тело, навыки, черты, нужды, семья, расписание; текущее дело с обзора
уходит на «Сейчас»
- [x] Одежда: слои, цвет, полоска износа и подпись (если сервер прислал `condition` /
`conditionLabel`), короткая уместность — прочерк до фазы 35
- [x] Ноша: сумка, несёшь/можешь, шкафчик или его отсутствие, кратко «ещё N дома» без полного
домашнего списка
- [x] Сейчас: на территории школы — подпись действия (`ест`, `идёт`, `учится (математика)`,
`переодевается`). Вне школы — «дома»
- [x] История за сегодня под текущим делом: поиск, сортировка, пейджинг
- [x] `GET /api/schools/{id}/people/{personId}/log` — страница и фильтр; не сокет, не лента
школы. Граница суток — шесть утра; skip ночи обнуляет вчерашнее
- [x] Запись в лог: начало/конец действия есть; утренняя выдача одежды — тип
`apparel-replaced` подхватывается, пишет фаза 34; переодевание — `apparel-changed` из фазы 35
- [x] Vitest: переключение вкладок, пейджер лога, «дома» когда activity пустая и человек away
- [x] `docs/protocol.md` — HTTP лога в том же коммите
## Тесты, без которых фаза не закрыта
- [x] Лог не едет в `GET .../people/{id}` — только отдельным запросом
- [x] Страница лога не пересекается; неизвестный человек — `404`
- [x] После 6:00 записей вчера нет
- [x] Вне школы вкладка «Сейчас» показывает «дома», не пусто
- [x] Клиентский тест: вкладка «Одежда» не монтирует таблицу лога
## Критерий готовности
- Открыть ученика, переключить четыре вкладки, найти в истории сегодняшний обед
- Тысяча строк лога не приезжает разом
- `dotnet test` и `npm test` / `build` проходят
## Стоп
Не возвращать панель общих событий школы. Не давать надевать с вкладки «Одежда».
@@ -0,0 +1,41 @@
# Фаза 37. Правила школы
## Зависимости
- [Фаза 35](35-appropriateness.md)
- [Фаза 36](36-person-card-tabs.md)
- [Фаза 13](../03-staffing/13-management-tab.md)
## Зачем
Игрок задаёт, как одевается школа. Это единственное его действие в срезе про одежду.
## Задачи
- [x] В «Управлении» вкладка **«Правила»** рядом со штатом, не новый верхний режим
- [x] Четыре комбобокса: форма учеников, цвет учеников, форма сотрудников, цвет сотрудников.
Значения — как в [`docs/design/07-inventory/inventory.md`](../../design/07-inventory/inventory.md)
- [x] Сохранение пишет завтрашнее правило; на экране видно, что действует сегодня и что
вступит завтра
- [x] HTTP: чтение текущих+отложенных, запись отложенных. Отказ по неизвестному коду правила —
`400`, не тишина
- [x] На следующее рабочее утро отложенное становится текущим; фаза 35 уже одевает от него
- [x] Строки через `t(...)`, обе локали
- [x] Vitest: смена комбобокса не зовёт API до подтверждения; ошибка API видна текстом
## Тесты, без которых фаза не закрыта
- [x] GET правил на новой школе — дефолт обычная / без яркого на обе роли
- [x] POST «строгая» сегодня не меняет одежду до следующего рабочего утра
- [x] После утра на теле учеников нет яркого, если отложили «без яркого»
- [x] Неизвестный код политики — `400`
- [x] Вкладка не ломает наём и сетку расписания
## Критерий готовности
- Выставить ученикам «белая верх чёрный низ», промотать на утро — рубашки белые
- `dotnet test` и `npm test` / `build` проходят
## Стоп
Не давать игроку одевать одного человека. Не вводить магазины и оплату формы.
+41
View File
@@ -0,0 +1,41 @@
Индекс срезов: [`../README.md`](../README.md).
## Срез 7. Одежда, вещи и климат
Дизайн: [`../design/inventory.md`](../../design/07-inventory/inventory.md).
Человек одевается, несёт вещи, мёрзнет и переодевается. Игрок смотрит гардероб и выбирает
правила школы; надевает не он. Погода видна у часов. Срез можно остановить после этапа A —
школа останется одетой, даже если климат ещё не живой.
**Этап A — данные и гардероб.** Страна вместо набора имён, вещи умеют быть одеждой, генератор
одевает.
| Фаза | Статус | Зачем |
| --- | --- | --- |
| [29. Страна](29-country.md) | ✅ | `CountryDef`, create выбирает страну, климат-пресет от сида |
| [30. Слои и палитра](30-apparel-defs.md) | ✅ | Поля `ThingDef`, `ColorDef`, ванильная одежда и ноша |
| [31. Генератор одевает](31-dress-generator.md) | ✅ | Гардероб на человеке, ноша-число, `people.json` |
29 и 30 независимы; 31 стоит на обеих.
**Этап B — климат.** Улица, нужда тепла, техник, раздевалки.
| Фаза | Статус | Зачем |
| --- | --- | --- |
| [32. Погода и тепло](32-weather-warmth.md) | ✅ | Пресет крутит улицу, кадр часов, нужда, две черты |
| [33. Техник и шкафчики](33-lockers-technician.md) | ✅ | Комната техника, две раздевалки, раздача шкафчиков |
32 стоит на 29; 33 — на 31 и 32.
**Этап C — жизнь одежды.** Износ, переодевание, экран.
| Фаза | Статус | Зачем |
| --- | --- | --- |
| [34. Износ и дом](34-wear-home.md) | ✅ | Прочность, утренняя замена, из ветхого не выходят |
| [35. Уместность](35-appropriateness.md) | ✅ | Правила, переодевание действием, физкультура |
| [36. Вкладки карточки](36-person-card-tabs.md) | ✅ | Одежда, ноша, сейчас + история за сегодня |
| [37. Правила школы](37-school-rules.md) | ✅ | Вкладка в «Управлении», четыре комбобокса, с завтра |
34 стоит на 31; 35 — на 32–34; 36 — на 31 и может идти параллельно с 35 в части вкладок одежды,
история — после 35; 37 стоит на 35 и 36.
+100
View File
@@ -0,0 +1,100 @@
# Журнал ревью
Сводка: [`../reviewed.md`](../reviewed.md). Индекс среза: [`README.md`](README.md).
## Срез 7. Этап A — данные и гардероб
- **Фазы:** 2931
- **Проверен на:** `d5547b7`, 2026-08-20
- **Пути:** `src/HSchool.Content/{CountryDef,ApparelDefs,CatalogLoader}.cs`,
`src/HSchool.People/{DressGenerator,CountryClimate,RosterJson}.cs`,
`src/HSchool.Server/{Game/SchoolStore.cs,Api/{ModEndpoints,SchoolEndpoints}.cs,Api/PeopleModels.cs}`,
`src/HSchool.Client/src/ui/{createSchoolDialog.ts,personCard.ts}`,
`tests/HSchool.Content.Tests/{CountryDefTests,ApparelDefTests,VanillaCoreTests}.cs`,
`tests/HSchool.People.Tests/{DressGeneratorTests,GoldenRosterTests}.cs`,
`tests/HSchool.AppHost.Tests/{SchoolApiTests,InventoryApiTests,GoldenSaveTests,ServiceabilityTests}.cs`,
`src/HSchool.Client/src/ui/createSchoolDialog.test.ts`
- **Итог:** все 17 тестов из списков фаз на месте; исправлен дубликат `peopleTabOverview` в
`strings.ts` (ломал `npm run build`); одно замечание рядом про вкладки карточки
Что подтверждено:
- **29:** `CountryDef`/`ClimatePresetDef`; `namesets/` убран; ваниль `Russia` с двумя пресетами;
каталог отдаёт `countries`; create принимает `countryId`, `unknown-country` на чужую страну;
пресет от сида (`CreateSchool_WithTheSameSeed_GetsTheSameClimatePreset`); `nameSetId: Slavic`
поднимается через `UpgradeOlderSave` (`GoldenSaveTests`, `legacy-no-native/`); формат без
страны не стартует (`ServiceabilityTests`); диалог — страны и языки (`createSchoolDialog.test.ts`);
золотой ростер обновлён (`GoldenRosterTests`).
- **30:** поля `ThingDef`/`ColorDef`, слои как роли, мебель без `layers`; ванильная палитра и
одежда в `VanillaCoreTests`; локали ru/en (`EveryVanillaLabel_ExistsInBothLocales`); учебник
один def без `subject` на def.
- **31:** `InventoryItem` с `def`/`color`/`condition`/`location`/`subject`; `DressGenerator`
детерминирован (`DressGeneratorTests`, `InventoryApiTests.SameSeed_YieldsTheSameShirt`); слои
без пересечения, платье на два слоя; пол/яркость/учебник/родители/соискатели/масса/Hauling;
карточка отдаёт worn+carried, список — нет (`InventoryApiTests`); старый `people.json` без
items одевается на reload (`PeopleJsonWithoutInventory_IsDressedOnReloadAndRewritten`);
`HSchool.People`/`HSchool.Content` без ASP.NET; протокол не тронут.
Дописано:
- (нет новых тестов — списки фаз закрыты существующими)
Исправлено:
- Дубликат ключа `peopleTabOverview` в `strings.ts` (ru/en): vitest не ловит TS2300/TS1117,
`npm run build` падал; ключ перенесён, `peopleTabPortrait` рядом с остальными вкладками.
- Повтор `using HSchool.Content` в `SchoolStore.cs` (CS0105).
Замечено рядом:
- Карточка уже с вкладками (`personCard.ts`, фаза 31 обещала один свиток — позже по
`../../design/07-inventory/inventory.md`); портрет/SwarmUI-строки в `strings.ts` — не этап A.
- `ResolveClimatePreset` в `SchoolWorker` при reload без сохранённого пресета берёт первый
пресет страны (`schoolSeed: 0`, `rollIfOmitted: false`) — по дизайну для legacy; create
кидает пресет из `GameLoopService` до spawn.
## Срез 7. Этап B–C — климат, жизнь одежды и правила
- **Фазы:** 3237
- **Проверен на:** `5dcdee6`, 2026-08-20
- **Пути:** `src/HSchool.Simulation/{WeatherSampler,WarmthDecay,PlaceClimate,ApparelDresser,ApparelWear,MorningDress,PersonLogBrowser}.cs`,
`src/HSchool.People/LockerAssigner.cs`, `src/HSchool.Content/{Appropriateness,ClimatePreset,DressRules}.cs`,
`src/HSchool.Ai/ApparelGoals.cs`, `src/HSchool.Protocol`, `src/HSchool.Server/Api/{SchoolEndpoints,DressRulesModels}.cs`,
`src/HSchool.Server/Game/{PersonCardReader,SchoolWorker}.cs`, `src/HSchool.Client/src/{ui/dressRulesPanel.ts,ui/managementPanel.ts,format/weather.ts,net/api.ts}`,
`docs/protocol.md`, `tests/HSchool.Simulation.Tests`, `tests/HSchool.People.Tests/LockerAssignerTests.cs`,
`tests/HSchool.Content.Tests/{ClimatePresetTests,AppropriatenessTests,ChangingRoomMapTests}.cs`,
`tests/HSchool.AppHost.Tests/{PersonLogApiTests,DressRulesApiTests}.cs`, `tests/HSchool.Protocol.Tests`,
`src/HSchool.Client/src/ui/{personCard,dressRulesPanel,managementPanel}.test.ts`
- **Итог:** фазы 32–37 подтверждены; дописано 5 тестов симуляции; исправлены 2 бага переодевания и 2
регрессии тестов (не протокол)
Что подтверждено:
- **32–36:** погода детерминирована; skip выставляет утро; кадр часов v8 (27 байт) в трёх местах;
`Warmth` и техник; шкафчики; износ и утренняя замена; уместность и PE; вкладки карточки и HTTP-лог.
- **37:** вкладка «Правила» в «Управлении»; четыре комбобокса; GET/POST `dress-rules` с pending;
`unknown-form`/`unknown-color``400`; правило с завтра; `ColorAllowed` для `whiteTopBlackBottom`;
`dressRulesPanel.test.ts` — combobox без API до Apply, ошибка текстом; `ManagementPanel` не ломает штат
и сетку.
Дописано (32–36, прошлый проход):
- `AppropriatenessSimulationTests.MorningDress_StagesPeKitForTodaysLesson`
- `AppropriatenessSimulationTests.PeBreak_CompletesChangeBeforeLesson`
- `AppropriatenessSimulationTests.PeLesson_WearsPeThenReturnsToEveryday`
- `AppropriatenessSimulationTests.AfterPeBreak_ModeExpectsEveryday`
- `PresenceTests.PhysicalEducationBeforeLesson_GoesToChangingRoomOnTheBreak`
Исправлено:
- `PresenceSystem`: ходьба по duty не обрывает активный `ChangeClothes`.
- `ApparelPresence.ModeAt`: после перемены following PE — режим everyday.
- `managementPanel.test.ts`: панель штата скрывается через `hidden`, не удаляется из DOM.
- `PortraitApiTests.GetSwarmUiSettings_ReturnsPresets`: URL `/api/settings/swarmui` (CS1503).
- `dressRulesPanel.ts`: неиспользуемый импорт `clear` — TS6133 на `npm run build`.
Замечено рядом:
- `PhysicalEducationBeforeLesson_…` не гоняет полный цикл «зал с формой» — это в
`AppropriatenessSimulationTests.PeLesson_…`.
- Портреты/SwarmUI — вне среза 7, но `PortraitApiTests` чинился, чтобы AppHost-сборка не падала.