Integrate stage A review from main; resolve reviewed.md; fix dressRulesPanel unused import, managementPanel test, PortraitApiTests URL.
26 KiB
Проверенные срезы
Журнал ревью. Фаза с ✅ в 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. Оболочка и карта
- Фазы: 0–4
- Проверен на:
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. SchoolWorker—LongRunning, свой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--screen—height: fit-content;DefaultStartDateUTC;MapSnapshotSizeот сообщения; outboxDropOldest;WaitToReadAsyncпереносится между итерациями; меню патчитcard.update.- Родной язык — HTTP/JSON без бампа протокола. Старый сейв без поля берёт первый язык набора,
не бросает кубик (
ReloadWithoutASavedPick_TakesTheFirstLanguageInsteadOfRolling).
Дописано:
SchoolApiTests.Catalog_WithAnUnknownMod_IsRejectedSchoolApiTests.ModId_ThatEscapesTheModsFolder_IsRejectedOnBothEndpointsSkillGrantTests.ReloadWithoutASavedPick_TakesTheFirstLanguageInsteadOfRolling
Исправлено:
- Два поля
speedIndexв клиентскомSchool(api.ts) — артефакт мержа фазы 26; vitest не ловил,npm run buildпадал с TS2300.
Срез 2. Люди
- Фазы: 5–9
- Проверен на:
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. Штат
- Фазы: 10–13
- Проверен на:
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. Расписание
- Фазы: 14–17
- Проверен на:
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_CarryTheDocumentedCodes—no-teacher,unknown-class,unknown-subject,unknown-room,unknown-lesson,invalid-query.
Исправлено:
- В
design/schedule.md«панель локации из расписания» и «люди находятся по расписанию» помечены как отменённые срезом 5.
Срез 5. Жизнь школы
- Фазы: 18–21
- Проверен на:
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_PutsSomeoneOnCampusAssigningMath_AfterDayPlansWereBuilt_PutsSomeoneOnCampus
Исправлено:
School.SetTimetableобнуляетPlanDay. Иначе после назначения предмета без смены численностиEnsurePlansсчитает планы актуальными,AppearAtостаётсяnull, кампус пуст. Найм это маскировал (численность растёт).OpeningASchoolDuringAMathLesson_...после снятия паузы сразу ждал людей и съедал бюджет на паузные кадры. Теперь ждётclock.Running, потом людей.
Срез 6. Фундамент
- Фазы: 22–28
- Проверен на:
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. Этап A — данные и гардероб
- Фазы: 29–31
- Проверен на:
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/inventory.md); портрет/SwarmUI-строки вstrings.ts— не этап A. ResolveClimatePresetвSchoolWorkerпри reload без сохранённого пресета берёт первый пресет страны (schoolSeed: 0,rollIfOmitted: false) — по дизайну для legacy; create кидает пресет изGameLoopServiceдо spawn.
Срез 7. Этап B–C — климат, жизнь одежды и правила
- Фазы: 32–37
- Проверен на:
<commit>, 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_StagesPeKitForTodaysLessonAppropriatenessSimulationTests.PeBreak_CompletesChangeBeforeLessonAppropriatenessSimulationTests.PeLesson_WearsPeThenReturnsToEverydayAppropriatenessSimulationTests.AfterPeBreak_ModeExpectsEverydayPresenceTests.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-сборка не падала.