Files
h-school/docs/phases/reviewed.md
T

23 KiB
Raw Blame History

Проверенные срезы

Журнал ревью. Фаза с в README.md — заявка автора; строка здесь — проверенный факт: каждое обещание фазы сверено с кодом и тестом, найденное дописано или исправлено.

Коммит в «Проверен на» делает журнал самопроверяющимся. Срез перестаёт считаться проверенным, как только git log <коммит>..HEAD -- <пути> перестаёт быть пустым — поэтому «Пути» обязательны.

Закрытые замечания из прошлых проходов сюда не возвращаются. История перепроверок свёрнута в строку «Проверен на». Последняя проверка срезов 1–6 была до фаз 29–30 (страна, одежда): дрейф по путям есть, это очередь следующего прохода, а не задняя датировка.

Оговорки, которые относятся сразу к нескольким срезам (не дублировать ниже):

  • Хостовый OpeningASchoolDuringAMathLesson_... после правки явки не гонялся: Aspire держал DLL (MSB3021). Симуляционные тесты явки зелёные.
  • npm test в клиенте не гоняет tsc. Дубликат поля и любой TS2300 зелёный в vitest и красный на npm run build.
  • GET /api/catalog отдаёт каркас дня без lunchBreaks (только longBreakAfter). Сетке смены не нужны; молча расширять HTTP ревью не стало.

Срез 1. Оболочка и карта

  • Фазы: 04
  • Проверен на: 418a4ea, 2026-08-20
  • Пути: src/HSchool.Client, src/HSchool.Protocol, src/HSchool.Content, src/HSchool.Server/Game, src/HSchool.Server/Api/ModEndpoints.cs, src/HSchool.Server/Api/SchoolEndpoints.cs, src/HSchool.Server/Net, tests/HSchool.Content.Tests, tests/HSchool.Protocol.Tests, tests/HSchool.AppHost.Tests/SchoolApiTests.cs, tests/HSchool.AppHost.Tests/GameSocketTests.cs
  • Итог: обещания фаз 0–4 целы; дописаны 3 теста; протокол v7 в трёх местах

Что подтверждено:

  • PixiJS нет; дерево карты, пять секций локации, клиентский фильтр, localize(). Оболочка — вкладки Карта/Люди, не три панели; отказ от ленты событий записан в фазе 1 и в design/near-term.md.
  • SchoolWorkerLongRunning, свой World, аккумулятор с потолком 5. Супервизор таблицу держит и World не трогает. Сейв на create/shutdown/SaveIntervalSeconds; ReloadFromDisk_RestoresAPausedClock, PausingOneSchool_DoesNotStopAnother.
  • Восемь тестов каталога/карты в HSchool.Content.Tests. Ванильная раскладка валидна. Пропавшая папка мода не стартует школу и файл не трогает.
  • GET /api/mods, каталог, create с картой и модами, снимок при OpenSchool. core в диалоге создания нельзя снять. Кодек, protocol.ts и docs/protocol.md описывают один MapSnapshot.
  • modal.ts резолвит промис явно; .dialog--screenheight: fit-content; DefaultStartDate UTC; MapSnapshotSize от сообщения; outbox DropOldest; WaitToReadAsync переносится между итерациями; меню патчит card.update.
  • Родной язык — HTTP/JSON без бампа протокола. Старый сейв без поля берёт первый язык набора, не бросает кубик (ReloadWithoutASavedPick_TakesTheFirstLanguageInsteadOfRolling).

Дописано:

  • SchoolApiTests.Catalog_WithAnUnknownMod_IsRejected
  • SchoolApiTests.ModId_ThatEscapesTheModsFolder_IsRejectedOnBothEndpoints
  • SkillGrantTests.ReloadWithoutASavedPick_TakesTheFirstLanguageInsteadOfRolling

Исправлено:

  • Два поля speedIndex в клиентском School (api.ts) — артефакт мержа фазы 26; vitest не ловил, npm run build падал с TS2300.

Срез 2. Люди

  • Фазы: 59
  • Проверен на: bdb1253, 2026-08-20
  • Пути: src/HSchool.People, src/HSchool.Content/PeopleDefs.cs, src/HSchool.Simulation/RosterSpawner.cs, src/HSchool.Simulation/School.cs, src/HSchool.Server/Api/SchoolEndpoints.cs, src/HSchool.Server/Game/PersonCardReader.cs, src/HSchool.Server/Game/SchoolWorker.cs, src/HSchool.Client/src/ui/peoplePanel.ts, src/HSchool.Client/src/ui/personCard.ts, tests/HSchool.People.Tests, tests/HSchool.Content.Tests/PeopleDefTests.cs, tests/HSchool.Simulation.Tests/PeopleInSchoolTests.cs, tests/HSchool.AppHost.Tests/PeopleApiTests.cs, tests/HSchool.AppHost.Tests/SchoolSeedTests.cs
  • Итог: обещания фаз 5–9 целы; починены два API-теста, дописан один на reload после набора

Что подтверждено:

  • Дефы человека: разбор, наследование, патч, неизвестная ссылка, склонение, мод со своим набором.
  • Генератор: шесть тестов списка фазы, без Arch/ASP.NET/DateTime.Now. Неполные семьи 5–10%. Сид — поле школы, не school.Id; хостовые тесты, которым нужен состав, передают сид явно.
  • Одиннадцать кабинетов, сущности в World, PersistPeople только при смене состава. Штат при создании пуст — это фаза 11.
  • Список с опубликованного снимка, карточка через TaskCompletionSource. Фильтры, пейджер, семейные ссылки, всё через t(...). Вкладка рядом с картой, не нижний ряд — так записано в фазе 8 и в design/people.md.
  • Выпуск старшей имеющейся, вместимость, семьи через поколения, reload после набора.

Дописано:

  • PeopleApiTests.ReloadAfterTheYearlyIntake_RestoresTheNewComposition — ждёт 1 сентября и требует состав после набора, отличный от исходного (детерминизм от сида иначе скрыл бы потерянный файл).

Исправлено:

  • Card_IncludesFamilyAndLiveNeeds брал People[0] и требовал двух родителей. Состав зависит от сида; на чистом клоне первый ученик иногда из неполной семьи. Теперь ищет ученика с матерью и проверяет диапазон.
  • List_SortsBySurname требовал ordinal-порядок, сервер ставит Ё на место Е. Совпадали, пока в core не было фамилий на Ё.

Срез 3. Штат

  • Фазы: 1013
  • Проверен на: bdb1253, 2026-08-20
  • Пути: src/HSchool.People/Staffing.cs, src/HSchool.People/ApplicantPool.cs, src/HSchool.Content/SubjectDef и defs/staffing, src/HSchool.Server/Api/SchoolEndpoints.cs (staffing/hire/subjects), src/HSchool.Server/mods/core/defs/{subjects,positions,rooms,staffing,traits}, src/HSchool.Client/src/ui/managementPanel.ts, src/HSchool.Client/src/net/api.ts, tests/HSchool.People.Tests/{StaffingTests,ApplicantPoolTests}.cs, tests/HSchool.AppHost.Tests/StaffingApiTests.cs, src/HSchool.Client/src/ui/managementPanel.test.ts
  • Итог: обещания фаз 10–13 целы; дописаны 3 теста; docs/protocol.md дополнен ?lang=

Что подтверждено:

  • PETeacher нет; кабинеты без учительской должности; места через defaultSeats. Неизвестный навык в предмете роняет каталог. Стартовая дата 31 марта 2012.
  • Пул: детерминизм по сиду и неделе, частичное обновление, устойчивый размер, «сильный просит больше», пустой штат, соискатель вне ростера до найма. Пул 32.
  • Фонд оплаты, деление часов, пол ставки, покрытие. GET /staffing читает снимок, наём и назначение — GameCommand с TaskCompletionSource. MaxWeeklyHours не запрещает назначение, а оставляет предмет непокрытым. PrimarySchool на ванили требует трёх учителей (teachersShort).
  • Экран: деньги, непокрытые, пул, штат, назначение с карточки, отказ по пределу текстом, всё через t(...).
  • Полностью укомплектованная школа влезает в 100 000 впритык (запас 5–13%). Нанять пул целиком без назначений предела достигает. Раскладка «каждому все предметы» — самая дешёвая, не «укомплектованная школа».

Дописано:

  • StaffingApiTests.AssigningPastTheCap_IsRejectedWithTheNumbers — фаза 12 требовала API-тест на отказ по пределу; единственное место было написано через if (over.StatusCode == Conflict) и проходило при любом исходе.
  • ApplicantPoolTests.ConfidentTraits_AskForMoreAndQuietOnesForLess
  • В AssignAndUnassign_HonourTheCap_AndReloadKeepsAssignments — тот же пул с теми же ставками после перезапуска.

Исправлено:

  • docs/protocol.md не упоминал ?lang= у hire/subjects, хотя клиент его шлёт.

Срез 4. Расписание

  • Фазы: 1417
  • Проверен на: bdb1253, 2026-08-20
  • Пути: src/HSchool.Schedule, src/HSchool.Content (каркас дня, каникулы, SubjectDef.room), src/HSchool.Simulation/SchoolTimetables.cs, src/HSchool.Server/Api/TimetableEndpoints.cs, src/HSchool.Server/Game/SchoolWorker.cs (пин, перестроение), src/HSchool.Client/src/ui/timetableGrid.ts, src/HSchool.Client/src/ui/gameScreen.ts, tests/HSchool.Schedule.Tests, tests/HSchool.Content.Tests/CalendarTests.cs, tests/HSchool.Content.Tests/LunchBreakTests.cs, tests/HSchool.AppHost.Tests/TimetableApiTests.cs, src/HSchool.Client/src/ui/timetableGrid.test.ts
  • Итог: обещания фаз 14–17 целы; дописан тест на коды отказа пина; две строки дизайна помечены как отменённые срезом 5

Что подтверждено:

  • Календарь: суббота, каникулы и ночь — «вне учебного дня»; 10:20 вторника — третий урок; шестидневка; зима через 1 января. Физкультура в спортзале. Обеденные смены в каркасе дня (младшие после 3-го, старшие после 4-го).
  • Планировщик: четыре запрета, класс не влезает в меньший кабинет, без Arch/ASP.NET/DateTime.Now.
  • Перестроение только при PeopleChanged + TimetableDirty, не по тику. GET /timetable читает снимок, пин — TaskCompletionSource. Reload_RestoresLockedLessons.
  • Сетка, закрепление, тексты отказа (pin-rejected / no-teacher / unknown-lesson), скобки в дереве из присутствия, личное расписание в карточке. Всё через t(...).
  • Занятость узла в протоколе v7 живёт в кадре Presence, не в снимке карты — фаза 19.

Дописано:

  • TimetableApiTests.PinAndUnpinRefusals_CarryTheDocumentedCodesno-teacher, unknown-class, unknown-subject, unknown-room, unknown-lesson, invalid-query.

Исправлено:

  • В design/schedule.md «панель локации из расписания» и «люди находятся по расписанию» помечены как отменённые срезом 5.

Срез 5. Жизнь школы

  • Фазы: 1821
  • Проверен на: cbe739a, 2026-08-20
  • Пути: 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, src/HSchool.Server/mods/core/defs/{actions,behavior,needs}, tests/HSchool.Ai.Tests, tests/HSchool.Simulation.Tests/{PresenceTests,DecisionTests,ActivityTests,NeedDecayTests,LunchTests}.cs, tests/HSchool.AppHost.Tests/GameSocketTests.cs
  • Итог: все 32 теста из списков фаз на месте; дописаны 2 теста явки; SetTimetable сбрасывает планы дня. Голод закрыт данными. AppHost после правки не гонялся — Aspire держал DLL.

Что подтверждено:

  • Ходьба: 13 тестов списка фазы 18 (маршрут, travelMinutes, воскресенье/каникулы, звонок, детерминизм, пропуск пустого времени, лето, промотанная неделя).
  • Присутствие: раскладка с обеих сторон, круговой прогон, люди не в снимке карты, пропуск в учебное время отбрасывается. На паузе кадры идут (occupancy + подписи урока); людей в них может не быть.
  • Нужды: декей, обед, стулья, ночь вне школы, неизвестная нужда, детерминизм. Hunger восстанавливается вне школы, в столовой 112 стульев, обед — смена по параллелям. SleepAndHunger_ReturnToMaxOffCampus, AfterASchoolDay_NobodyIsLeftStarving.
  • Решения: восемь тестов фазы 21, в том числе туалет с урока и возврат, потолок отложенных, детерминизм за неделю. HSchool.Ai без Arch/ASP.NET/DateTime.Now.

Дописано:

  • HireAndAssignMath_DuringLessonThree_PutsSomeoneOnCampus
  • AssigningMath_AfterDayPlansWereBuilt_PutsSomeoneOnCampus

Исправлено:

  • School.SetTimetable обнуляет PlanDay. Иначе после назначения предмета без смены численности EnsurePlans считает планы актуальными, AppearAt остаётся null, кампус пуст. Найм это маскировал (численность растёт).
  • OpeningASchoolDuringAMathLesson_... после снятия паузы сразу ждал людей и съедал бюджет на паузные кадры. Теперь ждёт clock.Running, потом людей.

Срез 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
  • Итог: все тесты из списков семи фаз на месте; дописан один клиентский; foundation.md приведён к закрытому срезу. Хостовые тесты сверены по коду, не прогоном.

Что подтверждено:

  • Пак: манифест, missing-mod, порядок — выбор игрока плюс топология (не алфавит), цикл — mod-cycle, def без подписи предупреждает и грузится.
  • mods/example на диске; каталог/create/reload; патч только с паком; ваниль без выбора не меняется.
  • Веса в BehaviorDef; пак с обедом выше урока уводит класс; отрицательный вес роняет загрузку.
  • Золотой ростер и сейв; PrimarySchool требует трёх; teachersShort в API и в t(...).
  • Сид — поле школы. Format новее — школа не стартует, файл нетронут. Дамп через снимок + мейлбокс, не в World с HTTP. HSchool.Simulation.Tests без параллельности.
  • Клиентские экраны в happy-dom: фильтры/пейджер, create, сетка, предел фонда текстом.

Дописано:

  • managementPanel.test.ts — непокрытый предмет показывает teachersShort.

Исправлено:

  • AGENTS.md утверждал, что на паузе кадры присутствия не приходят. Работник их шлёт (occupancy + подписи). Тест, который ждёт людей на паузе, зависнет; тест на подпись урока — нет.
  • design/foundation.md: порядок загрузки — не алфавит; «почему сейчас» про веса в Decision.cs устарел.

Замечено рядом:

  • Dump_ReturnsPeopleNodesAndTimetable принимает NodeId is not null || Needs.Count > 0. Нужды есть у всех, так что узлы на кампусе не проверяются. Усиливать до явки — срез 5.
  • Срез 7, фаза 37 — в работе на момент проверки B–C; этап A проверяет соседний ревьюер.

Срез 7. Этап B–C — климат и жизнь одежды (без 37)

  • Фазы: 3236
  • Проверен на: e461a9f, 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,PeopleModels}.cs, src/HSchool.Server/Game/PersonCardReader.cs, src/HSchool.Client/src/{ui/personCard.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.test.ts
  • Итог: фазы 32–36 подтверждены; дописано 5 тестов; исправлены 2 бага переодевания; фаза 37 в работе

Что подтверждено:

  • Погода детерминирована от пресета, сида и времени; skip выставляет утро; кадр часов v8 (27 байт) в ProtocolCodec, protocol.ts, docs/protocol.md; клиент рисует температуру с wire, не из месяца.
  • Warmth декейит на морозе, дома восстанавливается; черты HeatLoving/ColdLoving несовместимы.
  • Техник держит комфорт; двор = улица, кабинет теплее двора без техника; две раздевалки на ванили; шкафчики по полу/старшинству, пересчёт на 1 сентября.
  • Износ только на кампусе, skip/утро заменяют ветхое; утренняя выдача пишет apparel-replaced.
  • Уместность: утро, PE, погода, правила «с завтра» через API; карточка — вкладки и HTTP-лог с 6:00.
  • HSchool.Simulation без ASP.NET; dotnet test и Vitest (personCard, weather, protocol) зелёные.

Дописано:

  • AppropriatenessSimulationTests.MorningDress_StagesPeKitForTodaysLesson
  • AppropriatenessSimulationTests.PeBreak_CompletesChangeBeforeLesson
  • AppropriatenessSimulationTests.PeLesson_WearsPeThenReturnsToEveryday
  • AppropriatenessSimulationTests.AfterPeBreak_ModeExpectsEveryday
  • PresenceTests.PhysicalEducationBeforeLesson_GoesToChangingRoomOnTheBreak (переименован с ожидания зала на перемене)

Исправлено:

  • PresenceSystem: ходьба по duty больше не обрывает активный ChangeClothes — форма успевает надеться до звонка.
  • ApparelPresence.ModeAt: после перемены following PE режим «everyday», иначе PeForbidden не поднимался и форму не снимали.

Замечено рядом:

  • Фаза 37 (вкладка «Правила», UI смены дресс-кода) — в работе, не проверялась.
  • PhysicalEducationBeforeLesson_… в PresenceTests не гоняет полный цикл «зал с формой» — это в AppropriatenessSimulationTests.PeLesson_….