Update AGENTS.md to correct the behavior of presence frames during school pauses, clarify the design documentation regarding mod load order, and add a new test for uncovered teaching positions in the management panel. Enhance reviewed phase details for accuracy and completeness.
ci / server (push) Failing after 3m48s
ci / client (push) Successful in 42s

This commit is contained in:
Leonid Pershin
2026-08-20 02:57:13 +03:00
parent cf086600c3
commit ed80aa5d08
4 changed files with 119 additions and 22 deletions
+10 -18
View File
@@ -1,11 +1,7 @@
# Фундамент: паки, числа, сид, версия и золотые файлы
Договорённость на срез после жизни школы. Не текущий код — то, что решено сделать.
Срез не добавляет игроку ни одной новой кнопки. Он берёт то, что ревью нашло дешёвым и заметным,
и доводит до конца: мод становится настоящим объектом, числа поведения уезжают из кода в данные,
сид перестаёт быть идентификатором школы, у сейва появляется читаемая версия, а регрессии, которые
сейчас ловятся только глазами, начинают ловиться тестом.
Договорённость на срез после жизни школы. Срез закрыт фазами 22–28; таблица внизу — решения.
Абзацы «почему сейчас» ниже описывают дыры, которые срез закрыл, а не текущий код.
## Почему сейчас
@@ -16,17 +12,13 @@
маленький скучный пак на диске, чтобы last-wins, патчи и дорога «игрок выбрал мод» проверялись
настоящей папкой, а не документами в памяти.
**Числа поведения живут в коде вопреки [`ai.md`](ai.md).** Там записано: «Числа поведения —
отдельный деф правил, как `StaffingDef` у штата». В `BehaviorDef` уехали порог нужды, скорость
обучения и разброс на дорогу, а веса целей остались константами в `Decision.cs`. Пока они там, мод
не может перебалансировать поведение, не написав кода, — а это ровно то обещание, ради которого
заводились дефы.
**Числа поведения уехали в `BehaviorDef`.** Порог нужды, обучение, разброс на дорогу и веса целей
(урок, переход, нужда на нуле, обед) — данные. Каталог без дефа падает на константы кода, а не
ломается. Пак может поднять `lunchWeight` выше урока без форка.
**Две регрессии ловятся руками.** Генератор людей переписывали дважды за одну сессию ревью, а
тест на детерминизм сравнивает два прогона *в одном процессе*: он не заметит, если поменяется сам
порядок бросков. [`people.md`](people.md) называет отпечаток «единственным способом поймать
регрессию в генераторе». Так же с сейвом: поле `nativeLanguage` добавили без бампа формата, и то,
что старые сейвы грузятся, держится на комментарии в коде.
**Золотые файлы ловят то, что раньше ловили глазами.** Отпечаток ростера — файл в фикстурах.
Сейв текущего формата и сейв без `nativeLanguage` грузятся тестом хоста. Формат новее своего
школу не стартует и файл не трогает.
## Удостоверение пака
@@ -152,8 +144,8 @@
- Не даёт менять набор модов у живой школы. Каталог по-прежнему замерзает на работнике.
- Не кладёт `defName` комнаты в снимок карты. Клиент смог бы стилизовать типы помещений от модов,
но это версия протокола и правка в трёх местах — не «дёшево», значит не сюда.
- Не заводит UI для порядка модов. Порядок — алфавит плюс зависимости; ручная перестановка ждёт
того дня, когда паков станет больше трёх.
- Не заводит UI для порядка модов. Порядок — выбор игрока плюс устойчивая топологическая
сортировка по `requires`; ручная перестановка ждёт того дня, когда паков станет больше трёх.
## Зафиксировано этим разговором
+66 -1
View File
@@ -519,7 +519,7 @@ Calendar+обеды 20, планировщик 9, TimetableApi 6.
## Срез 5. Жизнь школы
- **Фазы:** 1821
- **Проверен на:** `450495f`, 2026-08-20 (первичная проверка — `21d79cb`; предыдущая перепроверка — `5a00ad7`)
- **Проверен на:** `cbe739a`, 2026-08-20 (первичная проверка — `21d79cb`; предыдущая перепроверка — `5a00ad7`; дерево до коммита правок — `450495f`)
- **Пути:** `src/HSchool.Ai`, `src/HSchool.Simulation/{PresenceSystem,ActivitySystem,LessonLearningSystem,School}.cs`,
`src/HSchool.Protocol` (кадр `Presence`, пропуск в кадре часов),
`src/HSchool.Server/Game/PresenceFrame.cs`, `src/HSchool.Client/src/ui/gameScreen.ts`,
@@ -653,6 +653,71 @@ Calendar+обеды 20, планировщик 9, TimetableApi 6.
Ai 29, Presence+Decision+Activity+NeedDecay+Lunch 31, Presence_RoundTrips 1.
## Срез 6. Фундамент
- **Фазы:** 2228
- **Проверен на:** `cbe739a`, 2026-08-20
- **Пути:** `src/HSchool.Content` (`PackManifest`, `PackLoadOrder`, `BehaviorDef`),
`src/HSchool.Server/mods/{core/pack.jsonc,example}`, `src/HSchool.Server/Game/SchoolStore.cs`,
`src/HSchool.Server/Api/DevEndpoints.cs`, `src/HSchool.Server/Game/SchoolDumpReader.cs`,
`src/HSchool.People/RosterJson.cs`, `src/HSchool.Client/src/ui/*.test.ts`,
`tests/HSchool.Content.Tests/{PackIdentityTests,ExamplePackTests,BehaviorDefTests}.cs`,
`tests/HSchool.People.Tests/GoldenRosterTests.cs`,
`tests/HSchool.AppHost.Tests/{ExamplePackTests,GoldenSaveTests,SchoolSeedTests,ServiceabilityTests}.cs`
- **Итог:** все тесты из списков семи фаз на месте; дописан один клиентский; исправлен ложный
gotcha про паузу; `foundation.md` приведён к закрытому срезу. Хостовые тесты сверены по коду,
не прогоном — Aspire держит DLL.
Что подтверждено:
- **Фаза 22.** Пак без `pack.jsonc` (id вместо названия), подписи `?lang=`, `core` с манифестом,
`400 missing-mod` с id недостающего, зависимость грузится раньше зависимого, цикл — `mod-cycle`,
def без подписи предупреждает и грузится. Порядок — устойчивая топология поверх выбора игрока,
не алфавит; разрешённый список в ответе создания и в сейве.
- **Фаза 23.** `mods/example` на диске (`pack.jsonc`, локали, черты, набор имён, патч, комната,
README). Копируется в вывод тестов как `core`. `GET /api/catalog?mods=example`, create+reload,
патч только с паком, last-wins, карта пака валидна. Ваниль без выбора не меняется.
- **Фаза 24.** Веса в `BehaviorDef` с комментариями, что перевешивают. Таблица ванильных решений,
пак с обедом выше урока уводит класс, каталог без дефа на константах, отрицательный вес роняет
загрузку.
- **Фаза 25.** `golden/roster.txt` и первая несовпавшая строка; правило в README рядом. Сейв
текущего формата и сейв без `nativeLanguage`. Кривая голода `Hunger_FollowsTheSchoolDayCurve`.
`PrimarySchool` требует трёх, второй учитель не закрывает. `teachersShort` в API и в `t(...)`.
- **Фаза 26.** Сид — поле школы, не id. Тот же сид — те же люди; без сида после reload тот же
состав; золотой сейв `seed == id` грузится; переданный сид в списке. На экране школы и в create.
- **Фаза 27.** Format новее — школа не стартует, файл нетронут. Текущий грузится. Дамп через
снимок + мейлбокс (`DumpSchool` → работник), не в `World` с HTTP. `404 unknown-school`.
`HSchool.Simulation.Tests` без параллельности. Дамп в `docs/protocol.md` за тем же
переключателем, что reload.
- **Фаза 28.** `happy-dom` на экранах; фильтры/пейджер, create (`core` нельзя снять, сброс карты,
busy submit), сетка (pin-rejected / no-teacher / unknown-lesson), предел фонда текстом.
Политика в `AGENTS.md`. `npm test` — 46 тестов, ~5 с.
- **Инварианты.** `Simulation` без `DateTime.Now`. Протокол не бампили. Сид в хостовых тестах,
которым нужен состав, передаётся явно.
Дописано:
- `managementPanel.test.ts` — непокрытый предмет показывает, скольких учителей не хватает
(`staffUncoveredShort` с `n: 3`). Задача фазы 25 была в коде без теста экрана.
Исправлено:
- `AGENTS.md` утверждал, что на паузе кадры присутствия не приходят вовсе. Это ложь: работник
крутит цикл и шлёт occupancy + подписи урока из таблицы. Фаза 27 записала заблуждение ревью.
Строка приведена к факту (тест, который ждёт *людей* на паузе, зависнет; тест на подпись урока —
нет).
- В `design/foundation.md` «порядок — алфавит плюс зависимости» расходился с кодом (порядок
игрока + топология). «Почему сейчас» про веса в `Decision.cs` устарел — срез это закрыл.
Замечено рядом:
- `Dump_ReturnsPeopleNodesAndTimetable` принимает `NodeId is not null || Needs.Count > 0`.
Нужды есть у всех, так что узлы на кампусе не проверяются. Дамп поле `nodeId` отдаёт; критерий
«кто где стоит» руками. Усиливать до явки — соседний срез 5, не здесь.
- Срез 7 (одежда) в работе: фазы 29–30 🔄, 31–37 ⬜. В журнал как закрытый не писать.
Content 17, People 2, Ai 3, Hunger curve 1, клиент 46/46. AppHost не гонялся.
## Что из журнала закрыто, 2026-08-19
Ревью нашло семь пунктов; шесть закрыты в этот же день, седьмой снят как несуществующий.