Register slice 12 and mark phase 68 in progress.

EOF

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-21 09:26:06 +03:00
co-authored by Cursor
parent c3d17cafc6
commit 99eca80d6d
10 changed files with 426 additions and 0 deletions
+1
View File
@@ -27,6 +27,7 @@ way; this file is *how to work in them*.
| lesson consequences (teacher present, skill, warmth, textbook, weather commute) | [`docs/design/off-queue/lesson-consequences.md`](docs/design/off-queue/lesson-consequences.md) — phases 48, 5053 | | lesson consequences (teacher present, skill, warmth, textbook, weather commute) | [`docs/design/off-queue/lesson-consequences.md`](docs/design/off-queue/lesson-consequences.md) — phases 48, 5053 |
| layer tests, client tsc-in-test, worker/card splits, dump nodes | [`docs/design/10-craft/`](docs/design/10-craft/craft.md) — slice 10, phases 5659 | | layer tests, client tsc-in-test, worker/card splits, dump nodes | [`docs/design/10-craft/`](docs/design/10-craft/craft.md) — slice 10, phases 5659 |
| notices, toasts, scene prompt contributions, Krea-only catalog | [`docs/design/11-events/`](docs/design/11-events/events.md) — slice 11, phases 6367 | | notices, toasts, scene prompt contributions, Krea-only catalog | [`docs/design/11-events/`](docs/design/11-events/events.md) — slice 11, phases 6367 |
| class teachers, director summons queue, parent meetings | [`docs/design/12-office/`](docs/design/12-office/office.md) — slice 12, phases 6872 |
| a bug in already-shipped behaviour | `.claude/skills/bug-work` — document in `docs/bugs/`, discuss only if the fix has a fork, then patch | | a bug in already-shipped behaviour | `.claude/skills/bug-work` — document in `docs/bugs/`, discuss only if the fix has a fork, then patch |
| a task that is not in any slice | `.claude/skills/side-work` — discuss, document in [`docs/phases/off-queue/`](docs/phases/off-queue/README.md), then implement | | a task that is not in any slice | `.claude/skills/side-work` — discuss, document in [`docs/phases/off-queue/`](docs/phases/off-queue/README.md), then implement |
| a new named slice of the game | `.claude/skills/slice-work` — discuss, write design and phases, then `/phase-orch` | | a new named slice of the game | `.claude/skills/slice-work` — discuss, write design and phases, then `/phase-orch` |
+185
View File
@@ -0,0 +1,185 @@
# Кабинет директора и классный
Договорённость на срез после событий и общения, не текущий код.
Люди: [`people.md`](../02-people/people.md). Штат: [`staffing.md`](../03-staffing/staffing.md).
ИИ: [`ai.md`](../05-ai/ai.md). Общение: [`social.md`](../09-social/social.md).
События: [`events.md`](../11-events/events.md). Урок: [`lesson-consequences.md`](../off-queue/lesson-consequences.md).
У школы появляется **власть на карте**: проступок помнится коротко, ученика **сами** гонят к
директору — с очередью у кабинета и ожиданием в коридоре. У класса появляется **классный**
(учитель из Управления); он редко оставляет класс после уроков на родительское собрание, и
родители **реально входят** на карту.
Игрок **назначает классных** и **смотрит**. Кнопки «вызвать к директору» и «назначить собрание»
нет: авто и ИИ классного.
## Что увидит игрок
- В **Управлении** — у каждого класса слот «классный»: только из нанятых учителей; снять /
переназначить.
- На карточке ученика — **небольшой список** недавних проступков (несколько последних), не
шкала дисциплины и не журнал оценок.
- После драки / выговора система может отправить ученика к директору: он идёт, если кабинет
занят — **ждёт в коридоре** у входа, внутри — **очередь по одному**.
- Редко после последнего урока класса: классный и часть родителей в кабинете класса; тост, что
собрание идёт.
## На какие вопросы отвечает
- Как приказ «к директору» живёт в том же ИИ, что урок (сильная обязанность), без телепорта.
- Как очередь у `PrincipalsOffice` не ломает присутствие и детерминизм.
- Кто такой классный без нового `PositionDef`.
- Как родитель впервые получает узел на карте и уходит после собрания.
- Что видит игрок без кнопки вмешательства.
## Чего нет
- Кнопки игрока «вызвать» / «на собрание».
- Шкалы дисциплины 0…100 и дневника оценок.
- Травм, медкабинета как больницы, выговора в отдельной вкладке «Правила».
- Еженедельного календаря собраний и явки 100%.
- Завуча как отдельной роли в этом срезе.
- Оценок и приказов «отправить домой».
## Что меняется в уже принятом
| Было | Стало | Почему |
| --- | --- | --- |
| Игрок только наблюдает; приказов нет ([`ai.md`](../05-ai/ai.md)) | Наблюдает вызовы; **назначает** классного | Классный — единственное решение игрока в срезе |
| Драка → выговор на месте; кабинет директора не заводим ([`social.md`](../09-social/social.md)) | Часть проступков → авто-вызов, очередь | Иначе выговор пустой |
| Родители без места на карте ([`people.md`](../02-people/people.md)) | На собрании получают узел и цель | Задел с ростера наконец используется |
| `SchoolClass` — id, год, литера, кабинет, ученики | Плюс `classTeacherId` (учитель или пусто) | Не должность, слот на классе |
| `EventDef`: утро, звонок, сбой генерации | Плюс вызов / собрание (info) | Игрок видит факт, не только строку в локации |
| «Родителя вызвать — отдельный сюжет» | Собрание классного; **не** вызов одного родителя к директору | Узкий scope |
## Этап A — классный
У `SchoolClass` опциональный id учителя. Назначить / снять — HTTP через мейлбокс школы (как
предметы), только хозяин. Кандидаты: нанятые с должностью `Teacher`. Один учитель — классный у
нескольких классов (ваниль не запрещает). Пустой слот: собраний нет, класс живёт как сейчас.
Карточка класса / строка в Управлении показывает имя. Сейв — в `people.json` / ростере рядом с
классами.
После этапа школа целая: классных можно расставить, вызовов ещё нет.
## Этап B — проступки и кабинет
### Память
На человеке **короткий список** недавних проступков (ваниль: несколько последних, потолок в
`BehaviorDef`, старые вытесняются). Запись: вид (ссора / драка / выговор / …), когда (игровые
часы или день+слот), опционально id второго участника. Не шкала. Писать при содержательном
событии (тот же шов, что мнения), не каждый тик.
Карточка ученика (вкладка «Сейчас» или рядом) показывает список. HTTP через мейлбокс.
### Вызов — только авто
Игрок не жмёт. Триггер из уже живых фактов: обрыв драки сотрудником, выговор учителя, при
необходимости грубый срыв с политикой речи — веса и пороги в `BehaviorDef`, не `if` по фамилии.
Состояние «вызван» — **временное** (флаг / обязанность), пока не дошёл, не отбыл приём и не
Sorвался день. Без долгой шкалы «дисциплина».
### Путь и очередь
Кабинет — `PrincipalsOffice` (уже в `core`). Вызванный идёт обычной ходьбой.
- Директор занят приёмом или отсутствует → очередь: ждут в **коридоре** у связанного узла (ребро
карты к кабинету), не толпятся внутри.
- В кабинете — **один** на приём. Очередь FIFO по id вызова (детерминизм: стабильный порядок).
- Приём — короткое действие (выговор / разговор), мнение о директоре падает, проступок может
дописаться; затем ученик свободен (обязанность урока снова тянет).
- Skip пустого времени не оставляет вечный «вызван» без разрешения: утро сбрасывает зависшее
или доигрывает по правилу в фазе.
Директор без найма: вызов не стартует (или гаснет) — порог в данных, не паника.
Тост info: кого вызвали (через `EventDef`). Протокол присутствия: действие / узел достаточно;
отдельное поле «очередь» в кадре — только если без него UI врёт. Версию сокета бампит **коммит
фазы**, не этот документ.
После этапа школа целая без собраний: драки гонят к директору, очередь видна в коридоре.
## Этап C — родительские собрания
Только **ИИ классного**, редко. Условия (числа в `BehaviorDef`):
- у класса есть классный;
- рабочий день, после **последнего** урока этого класса;
- классный сегодня в школе;
- бросок редкости от сида класса и дня.
Классный остаётся в кабинете класса (homeroom). Часть родителей учеников класса приходит:
получают место (двор → путь → кабинет), как обычная ходьба. Не 100% семей — доля и «кто» из
сида. Учитель-родитель этого класса, если уже в школе, может войти в собрание без второго
человека.
Собрание — действие/кружок ограниченной длины; мнения семья↔классный слегка двигаются; тост
info. После — родители уходят с карты (снова «вне школы»), классный свободен.
Игрок собрание не назначает и не отменяет.
После этапа школа целая целиком по срезу.
## Поток данных
| Что | Где |
| --- | --- |
| `classTeacherId` | ростер / сейв; HTTP Управление |
| Список проступков | на человеке; сейв; карточка HTTP |
| Очередь вызовов | состояние школы на потоке воркера; не клиент |
| Выбор «вызвать» / «собрание» | `HSchool.Ai` + адаптер симуляции |
| Ходьба родителей | те же узлы и `travelMinutes`, что у всех |
| Тосты | `EventDef` + доска уведомлений среза 11 |
| Назначение классного | намерение HTTP → мейлбокс (инвариант 3, 7) |
Инвариант 1: клиент не решает, кого вызвать. Инвариант 4: симуляция не знает тосты и ASP.NET.
## Где живёт код
Нового проекта нет.
| Что | Куда |
| --- | --- |
| Поля `BehaviorDef`, триггеры, потолки списка | `HSchool.Content` + JSONC `core` |
| `SchoolClass` + классный | `HSchool.People` + сейв |
| Обязанность вызова, очередь, собрание | `HSchool.Ai` + адаптер в `HSchool.Simulation` |
| HTTP назначение, карточка проступков | `HSchool.Server` + клиент Управление / карточка |
| `EventDef` вызова и собрания | `core` + шов среза 11 |
| Присутствие | уже есть; бамп протокола только если нужен новый статус |
## Советы, которые стоит принять сразу
- Не заводить `PositionDef` «классный» — слот на классе, как предметы у учителя.
- Не телепортировать к директору и не пихать очередь внутрь кабинета.
- Не давать игроку кнопку вызова: согласие на «только авто».
- Не шкалу дисциплины рядом со списком — два представления одной идеи путают.
- Родитель на карте только на время собрания (этот срез), не «живёт в школе».
- Очередь и вызовы считает поток школы; HTTP их не трогает.
- Редкость собраний — данные, не магическая константа в UI.
## Заведомо не сейчас
- Кнопка «вызвать к директору» / «назначить собрание».
- Вызов одного родителя к директору по проступку.
- Оценки, журнал посещаемости, «отправить домой».
- Травмы, медпункт как лечение после драки.
- Завуч, рассадка, настроение-нужда.
- Календарь собраний на четверть.
## Зафиксировано этим разговором
| Тема | Решение |
| --- | --- |
| Форма | Именованный срез 12, не off-queue |
| Вызов | Только авто; игрок не жмёт |
| Поведение | Временный «вызван» + короткий список недавних проступков |
| Классный | Только из учителей; Управление |
| Собрание | Только ИИ классного, редко, после последнего урока класса |
| Родители / вызов | Реально ходят по карте; у директора очередь, ждут в коридоре |
| Ваниль | `core`, не отдельный пак |
| Стоп | После A — классные; после B — кабинет без собраний |
| Протокол | Бамп только если фазе нужен новый статус присутствия |
| Оценки / шкала дисциплины | Не в срезе |
+1
View File
@@ -15,4 +15,5 @@
| 9. Общение и романтический пак | [09-social](09-social/social.md) | | 9. Общение и романтический пак | [09-social](09-social/social.md) |
| 10. Ремесло | [10-craft](10-craft/craft.md) | | 10. Ремесло | [10-craft](10-craft/craft.md) |
| 11. События и сцена | [11-events](11-events/events.md) | | 11. События и сцена | [11-events](11-events/events.md) |
| 12. Кабинет и классный | [12-office](12-office/office.md) |
| Вне очереди | [off-queue](off-queue/) | | Вне очереди | [off-queue](off-queue/) |
+40
View File
@@ -0,0 +1,40 @@
# Фаза 68. Классный руководитель
## Зависимости
- [Фаза 13](../03-staffing/13-management-tab.md)
- [Фаза 7](../02-people/07-people-in-school.md)
## Зачем
У класса появляется учитель-классный. Без него собраниям некого инициировать; игрок впервые
в этом срезе что-то решает.
## Задачи
- [ ] У `SchoolClass` опциональный `classTeacherId` (или эквивалент); сейв в ростере
- [ ] Назначить / снять — HTTP через мейлбокс школы; только хозяин; гость `403`
- [ ] Кандидат — нанятый с должностью `Teacher`; иначе отказ с текстом, не молчание
- [ ] Один учитель может быть классным у нескольких классов
- [ ] UI в «Управлении»: список классов со слотом классного (выбор / снять)
- [ ] Имя классного видно там, где уже показывают класс (карточка ученика / управление)
- [ ] Строки через `t(...)`, обе локали
- [ ] Пустой слот — школа живёт как сейчас; собраний ещё нет
## Тесты, без которых фаза не закрыта
- [ ] Назначение учителя класса пишет id в ростер и переживает сейв / reload
- [ ] Не-учитель и чужой id отклоняются
- [ ] Гость не назначает (API)
- [ ] Снятие очищает слот; класс без классного валиден
- [ ] Два класса могут указать одного и того же учителя
## Критерий готовности
- В Управлении назначить классного 5А, открыть карточку ученика / список — имя видно; F5 / reload
сохраняет
- Отфильтрованные тесты проекта по Testing policy проходят
## Стоп
Не вызов к директору. Не проступки. Не собрания. Не новый `PositionDef`.
@@ -0,0 +1,36 @@
# Фаза 69. Память проступков
## Зависимости
- [Фаза 44](../09-social/44-quarrel-fight.md)
## Зачем
Вызов и карточка опираются на короткий список недавних событий, не на шкалу дисциплины.
## Задачи
- [ ] На человеке разреженный список проступков: вид, игровое время (или день+слот), опционально
второй участник
- [ ] Потолок длины и какие факты пишут — поля `BehaviorDef` / данные `core`, не константы в UI
- [ ] Писать при ссоре, драке, выговоре (обрыв драки сотрудником); старые вытесняются
- [ ] Сейв вместе с человеком; ноль записей не хранить раздуто
- [ ] Карточка ученика показывает несколько последних (HTTP через мейлбокс)
- [ ] Строки видов через локаль мода / `t(...)` по договорённости фазы; обе локали клиента для UI
## Тесты, без которых фаза не закрыта
- [ ] Драка с выговором добавляет запись жертве и/или задире по правилам фазы
- [ ] Сверх потолка старая запись исчезает
- [ ] Список переживает сейв
- [ ] Карточка отдает тот же порядок, что в мире (не клиентская фантазия)
## Критерий готовности
- После драки с сотрудником в узле на карточке ученика виден проступок; перезагрузка школы не
стирает
- Отфильтрованные тесты по Testing policy проходят
## Стоп
Не шкала 0…100. Не авто-вызов (фаза 70). Не журнал оценок. Не кнопка игрока.
@@ -0,0 +1,46 @@
# Фаза 70. Вызов к директору и очередь
## Зависимости
- [Фаза 69](69-offense-memory.md)
- [Фаза 21](../05-ai/21-decisions.md)
- [Фаза 18](../05-ai/18-presence-walking.md)
## Зачем
Проступок гонит ученика к директору сам: ходьба, ожидание в коридоре, один в кабинете.
## Задачи
- [ ] Авто-триггер вызова из фактов (обрыв драки / выговор и пороги в `BehaviorDef`); кнопки
игрока нет
- [ ] Временное состояние «вызван» — сильная обязанность дойти до `PrincipalsOffice`, пройти
приём, сняться
- [ ] Нет директора в штате или нет узла кабинета — вызов не стартует / гаснет по правилу в данных
- [ ] Кабинет занят приёмом → ждут в коридорном узле у ребра к кабинету, не внутри
- [ ] В кабинете один на приём; очередь FIFO с детерминированным порядком
- [ ] Приём — короткое действие; мнение о директоре падает; при необходимости допись в список
проступков (69)
- [ ] Обычная ходьба и `travelMinutes`; телепорта нет
- [ ] Skip / утро не оставляют вечный «вызван» без разрешения (явное правило в коде фазы)
- [ ] Очередь и вызовы только на потоке школы (инвариант 3)
## Тесты, без которых фаза не закрыта
- [ ] После qualifying-проступка ученик получает обязанность к кабинету (при живом директоре)
- [ ] Двое вызванных: один в кабинете, второй в коридоре у входа, не оба внутри
- [ ] Освобождение кабинета впускает следующего из очереди
- [ ] Тот же сид и те же события → тот же порядок очереди
- [ ] Без директора вызов не зависает навечно
- [ ] Игрок не может послать вызов по HTTP/сокету (нет такого намерения)
## Критерий готовности
- Драка с обрывом → ученик идёт к директору; второй вызванный ждёт в коридоре; после приёма
оба снова живут обычным днём
- Отфильтрованные тесты по Testing policy проходят
## Стоп
Не собрания. Не тосты (если нужны — фаза 71). Не присутствие-протокол без нужды — только если
без нового статуса UI врёт; бамп версии тогда в этом коммите.
@@ -0,0 +1,38 @@
# Фаза 71. Тосты вызова и очередь на экране
## Зависимости
- [Фаза 70](70-director-summons.md)
- [Фаза 64](../11-events/64-event-defs.md)
## Зачем
Игрок видит, что кого-то вызвали, не вычисляя очередь глазами по всему дереву.
## Задачи
- [ ] `EventDef` info на авто-вызов (ваниль в `core`); факт из симуляции → доска уведомлений
среза 11
- [ ] Тост не паузит часы; не в сейве sticky
- [ ] В панели локации / присутствии понятно «идёт к директору» / «ждёт у кабинета» / «на приёме»
— через действие и узел; новый байт в кадре присутствия — только если иначе нельзя; тогда
протокол +1 в этом коммите (`ProtocolCodec`, `protocol.ts`, `docs/protocol.md`)
- [ ] Гость видит те же info; ничего не назначает
- [ ] Локали RU/EN
## Тесты, без которых фаза не закрыта
- [ ] Qualifying-вызов эмитит notice с ожидаемым `EventDef`
- [ ] Info не пишет sticky в сейв
- [ ] Если бамп протокола — round-trip и byte-layout на C# и TS
- [ ] Без открытого клиента очередь в мире всё равно двигается (подписка не обязательна для сима)
## Критерий готовности
- Вызов → тост; в коридоре у кабинета видно ожидающих; старый клиент при бампе отваливается на
Hello
- Отфильтрованные тесты по Testing policy проходят
## Стоп
Не собрания. Не warning-пауза на каждый вызов.
@@ -0,0 +1,44 @@
# Фаза 72. Родительские собрания
## Зависимости
- [Фаза 68](68-class-teacher.md)
- [Фаза 71](71-summons-notices.md)
- [Фаза 18](../05-ai/18-presence-walking.md)
## Зачем
Классный редко оставляет класс после уроков; родители впервые ходят по карте.
## Задачи
- [ ] Только ИИ: редкий бросок от сида класса и дня; кнопки игрока нет
- [ ] Условия: есть классный, рабочий день, после последнего урока **этого** класса, классный в
школе; пороги в `BehaviorDef`
- [ ] Классный остаётся в homeroom класса
- [ ] Доля родителей класса приходит: получают узел (двор → путь → кабинет), обычная ходьба
- [ ] Учитель-родитель ученика класса, уже в школе, может участвовать без второго инстанса
- [ ] Собрание — ограниченное по времени действие/занятость узла; лёгкий сдвиг мнений
семья↔классный
- [ ] После — родители снова «вне школы»; классный свободен
- [ ] `EventDef` info «собрание»; локали
- [ ] Нет классного — собрание не планируется
## Тесты, без которых фаза не закрыта
- [ ] Без `classTeacherId` собрание не стартует при том же сиде дня
- [ ] С классным и прохождением редкости родители появляются на карте и уходят после
- [ ] Собрание не раньше последнего урока класса
- [ ] Тот же сид класса/дня → те же «кто пришёл» (детерминизм доли)
- [ ] Игрок не назначает собрание по API
- [ ] Skip ночи не оставляет родителей вечно в кабинете
## Критерий готовности
- Назначить классного, дождаться редкого собрания: родители в кабинете класса, тост, потом
снова вне школы
- Отфильтрованные тесты по Testing policy проходят
## Стоп
Не вызов одного родителя к директору. Не календарь на четверть. Не явка 100%. Не оценки.
+34
View File
@@ -0,0 +1,34 @@
Индекс срезов: [`../README.md`](../README.md).
## Срез 12. Кабинет директора и классный
Дизайн: [`office.md`](../../design/12-office/office.md).
Проступок помнится коротко, ученика самих гонят к директору (очередь, коридор). Классный —
учитель из Управления; редко собирает родителей после уроков, и они ходят по карте. Игрок
назначает классных и смотрит. Срез можно остановить после этапа A — классные стоят, даже если
кабинета ещё нет.
**Этап A — классный.** Слот на классе.
| Фаза | Статус | Зачем |
| --- | --- | --- |
| [68. Классный руководитель](68-class-teacher.md) | 🔄 | Назначение в Управлении, только учителя |
**Этап B — проступки и кабинет.** Память, авто-вызов, экран.
| Фаза | Статус | Зачем |
| --- | --- | --- |
| [69. Память проступков](69-offense-memory.md) | ⬜ | Короткий список на человеке и карточке |
| [70. Вызов и очередь](70-director-summons.md) | ⬜ | Авто, ходьба, коридор, один в кабинете |
| [71. Тосты вызова](71-summons-notices.md) | ⬜ | `EventDef` info; очередь видна |
69 стоит на 44; 70 — на 69 и ходьбу/решения; 71 — на 70 и 64.
**Этап C — собрания.**
| Фаза | Статус | Зачем |
| --- | --- | --- |
| [72. Родительские собрания](72-parent-meetings.md) | ⬜ | ИИ классного, родители на карте |
72 стоит на 68 и 71.
+1
View File
@@ -22,4 +22,5 @@
| 9. Общение и романтический пак | 41–47 | [09-social](09-social/README.md) | [social](../design/09-social/social.md) | | 9. Общение и романтический пак | 41–47 | [09-social](09-social/README.md) | [social](../design/09-social/social.md) |
| 10. Ремесло | 5659 | [10-craft](10-craft/README.md) | [craft](../design/10-craft/craft.md) | | 10. Ремесло | 5659 | [10-craft](10-craft/README.md) | [craft](../design/10-craft/craft.md) |
| 11. События и сцена | 63–67 | [11-events](11-events/README.md) | [events](../design/11-events/events.md) | | 11. События и сцена | 63–67 | [11-events](11-events/README.md) | [events](../design/11-events/events.md) |
| 12. Кабинет и классный | 68–72 | [12-office](12-office/README.md) | [office](../design/12-office/office.md) |
| Вне очереди | 48–55 | [off-queue](off-queue/README.md) | [off-queue](../design/off-queue/) | | Вне очереди | 48–55 | [off-queue](off-queue/README.md) | [off-queue](../design/off-queue/) |