# Фаза 87. Субъект кадра ## Зависимости - [Фаза 66](../11-events/66-scene-prompt.md) - [Фаза 60](../off-queue/60-portrait-models.md) (пресеты и shot kind) - [Фаза 39](../08-session/39-school-owners.md) (гость уже генерирует портрет человека) ## Зачем Кабинет и футболка — не человек в URL портрета. Появляется HTTP субъекта «узел» и «вещь», PNG на диске, kind `scene`/`thing` без лифта живых пресетов. ## Задачи - [ ] `GET`/`POST` `.../schools/{id}/nodes/{nodeId}/image` и `.../image/prompt`. Ключ узла — id карты. PNG: `saves/{id}.images/node.{safeId}.png` - [ ] `GET`/`POST` `.../schools/{id}/things/{defName}/image` (query `color`) и `.../image/prompt`. PNG: `saves/{id}.images/thing.{def}.{color\|none}.png`. Нет instance id - [ ] Сборка узла: Room/Territory prompt + fill с текстом + погода, если улица. Без внешности и одежды человека. При ненулевой занятости узла — не больше одного общего фрагмента из `SimulationOptions`, не имена - [ ] Сборка вещи: `prompt` def + цвет + износ, если смотрим надетое (износ в промпте; ключ файла без износа). Молчаливый def — не Swarm - [ ] Пустой вклад — `400` `cannot-generate`. Нет узла/def — `404`. Swarm как портрет (`503`/`502`/`504`) - [ ] Гость: тот же успех, что `POST .../people/.../portrait`, не `403` - [ ] В шаблоне `swarmui.json` у пресетов shot kind `scene` и `thing`. Живая школа без них не переписывается; fallback строки в `SimulationOptions` - [ ] [`protocol.md`](../../protocol.md) — маршруты и коды, тем же коммитом. Сокет не бампить. `PortraitKind` человека не расширять значением `scene` ## Тесты, без которых фаза не закрыта - [ ] GET картинки узла до POST — `404` `image-missing` (или согласованный код в protocol.md) - [ ] POST класса: prompt содержит место/fill, не «teenage girl» / возраст карточки - [ ] POST узла без вклада (этаж/лестница без prompt) — `400`, Swarm не звали - [ ] POST `Chair` — `400` `cannot-generate` - [ ] POST `TShirt?color=White` — prompt английский про футболку, без субъекта-человека - [ ] Гость POST узла — не `403` (тот же класс исхода, что портрет; хост с фикстурой Swarm или тот же skip-контракт, что у портрета) - [ ] Живой `portraitSettings` без kind `scene` генерирует узел через fallback и не перезаписывает сейв пресета - [ ] Occupancy > 0 добавляет не больше одного общего фрагмента; имён людей в prompt нет - [ ] Сокет Version не меняется ## Критерий готовности - curl/хостовый тест: POST кабинета → PNG на диске; GET отдаёт image/png - «Показать промпт» узла доступен HTTP, даже если кнопки в UI ещё нет - Отфильтрованные тесты: AppHost (маршруты), сборщик на сервере; не весь раствор ## Стоп Не кнопки в DOM. Не автоген всем узлам. Не ControlNet. Не бамп сокета. Не групповые лица.