mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-01 04:09:17 +00:00
@@ -0,0 +1,209 @@
|
||||
# SPEC-REVIEW — issue #478, заход r1
|
||||
|
||||
- **Issue:** https://github.com/Matysh/houseplan-card/issues/478
|
||||
- **Этап:** spec (PROCESS.md §2.4)
|
||||
- **ТЗ:** `docs/specs/478-remove-room-drafts.md`
|
||||
- **Ветка/SHA:** `issue/478-remove-room-drafts` @ `30a16ed36461246e06d395f2bab7f4b6d9e12eaa`
|
||||
- **Заход:** r1 · блокирующих циклов израсходовано 0 из 4 (первый заход, бюджет §4 не тратится)
|
||||
- **Вердикт: зелёный**
|
||||
|
||||
## Скоуп ревью
|
||||
|
||||
Задача не помечена `small` (метки: `P2`, `S4-spec-review`, `tech-debt`; автор сам
|
||||
классифицировал её как полный трек — миграция схемы v9→v10, несколько
|
||||
поверхностей, изменение контракта сохранения незамкнутой цепочки). Поэтому ТЗ
|
||||
обязано жить в `docs/specs/`, что и сделано; файла лишнего в теле issue нет.
|
||||
Диапазон изменений этого раунда — только `docs/specs/478-remove-room-drafts.md`
|
||||
и одна строка в `docs/specs/README.md` (класс C, документация, ожидаемо для
|
||||
этапа spec):
|
||||
|
||||
```
|
||||
docs/specs/478-remove-room-drafts.md | 531 +++++++++++++++++++++++
|
||||
docs/specs/README.md | 1 +
|
||||
```
|
||||
|
||||
Продуктового кода в ветке нет — это правильно для стадии `S4-spec-review`.
|
||||
|
||||
## Как проверялось
|
||||
|
||||
1. Прочитан `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` §2.4/§7.1/§4/§7.2/§12.
|
||||
2. Прочитано тело issue #478 целиком и все 3 комментария (аналитика, занятие,
|
||||
передача на ревью, решения владельца от 06.09.2026).
|
||||
3. Прочитан ТЗ целиком (531 строка, разделы 1–20).
|
||||
4. Прочитаны канонические документы, которые ТЗ обязуется обновить при
|
||||
реализации: `docs/CANVAS.md`, `docs/WALL-THICKNESS.md`,
|
||||
`docs/CONFIG-COMPATIBILITY.md`, `docs/ARCHITECTURE.md`,
|
||||
`docs/USER-GUIDE.ru.md` — сверена терминология («черновик», «независимая
|
||||
стена», resume-жест) с тем, что уже описано там сегодня.
|
||||
5. Технические утверждения ТЗ и исходного текста issue сверены с текущим
|
||||
кодом на `origin/dev` (`fc5973c2`), а не приняты на слово:
|
||||
- `MAX_ROOM_DRAFTS=200`, `MAX_DRAFT_SEGMENTS=2000`, `MAX_PARTITIONS=2000` —
|
||||
существуют в `src/houseplan-card.ts`, `src/houseplan-editor-runtime.ts`,
|
||||
`custom_components/houseplan/validation.py` ровно как описано;
|
||||
- `_offerWallFaces`, `_offerExistingWallFace`, `_wallGraphSources`,
|
||||
`_planStructuralGeometrySnapshot` — существуют в
|
||||
`src/houseplan-editor-runtime.ts` с сигнатурами, соответствующими
|
||||
описанию в issue;
|
||||
- `fixedTopologyWallLineageHints` — существует в `src/wall-segment-model.ts`
|
||||
и используется в `houseplan-editor-runtime.ts`;
|
||||
- `partitionsReconciled` / `redundantDraftsRemoved` — существуют в
|
||||
`src/plan-optimizer.ts` и `src/coincident-partitions.ts` ровно с той
|
||||
семантикой, которую ТЗ предлагает свести к нулю;
|
||||
- `draft-live-preflight.ts` / `draft-live-commit.ts` (Fast path #461) —
|
||||
существуют, есть тест `test/draft-live-preflight.test.mjs`;
|
||||
- `WALL_SEGMENT_MODEL_VERSION` и `PLAN_MODEL_VERSION` действительно равны
|
||||
`9` сегодня и исторически бампались синхронно (`git log -p` по обеим
|
||||
константам) — заявленный переход v9→v10 не расходится с прецедентом;
|
||||
- `wall_model_client_outdated` — существующий код ошибки
|
||||
(`src/houseplan-card.ts`, `src/space-copy-runtime.ts`, все локали), а не
|
||||
изобретённый в ТЗ;
|
||||
- `mutation-gate` как механизм (AC13 требует «мутант... краснит gate») —
|
||||
реально существующая инфраструктура (`scripts/mutation-gate.mjs`,
|
||||
`test/mutation-gate.test.mjs`, `docs/TESTING.md`), не выдуманный
|
||||
инструмент.
|
||||
6. Сверена таблица `docs/specs/README.md`: новая строка вставлена без колонки
|
||||
«Статус ТЗ» — соответствует зачистке из PROCESS.md §7.3 п.1, уже принятой в
|
||||
остальной таблице.
|
||||
7. Проверено соответствие §7.1 (обязательные разделы) и формату AC (каждый
|
||||
пункт называет способ доказательства).
|
||||
|
||||
Гейты (typecheck/test/build) не гонялись: на этом этапе (spec) продуктового
|
||||
кода в ветке нет, гонять их не над чем. Это не пропуск гейта, а его
|
||||
неприменимость к диапазону изменений раунда.
|
||||
|
||||
## Разбор по требованиям процесса
|
||||
|
||||
### §7.1 — обязательные разделы
|
||||
|
||||
Все присутствуют, хотя «контракт поведения» не оформлен единым заголовком, а
|
||||
распределён по §8–12 (активная цепочка / face detection / Undo-Redo / limits /
|
||||
import-export) — это не нарушение, содержание есть и логично сгруппировано:
|
||||
|
||||
сценарий (§1) · что человек увидит (§2) · проблема (§3) · скоуп/не-скоуп (§5) ·
|
||||
контракт поведения (§8–12) · UX/i18n (§13) · модель данных и миграция (§6–7) ·
|
||||
критерии приёмки AC1–AC15, каждый со способом доказательства (§14) · план
|
||||
автотестов (§15) · риски (§17) · откат (§18) · release-артефакты (§19).
|
||||
|
||||
Два продуктовых раздела («сценарий», «что человек увидит») идут первыми, как
|
||||
требует PROCESS.md, и оба не используют термины реализации.
|
||||
|
||||
### Продуктовые вопросы vs технические
|
||||
|
||||
Открытых продуктовых вопросов нет: владелец 06.09.2026 ответил ровно на два
|
||||
продуктовых вопроса (жест возобновления контура; подсветка незамкнутых стен),
|
||||
и оба ответа перенесены в §4 ТЗ дословно. Раздел 20 «Принятые технические
|
||||
предположения» содержит только техническое: имя/расположение
|
||||
session-состояния, переименование файлов fast-path, источник fallback ID,
|
||||
место экстракции reconciliation-логики, судьба deprecated-счётчика, механизм
|
||||
CSS-подсветки. Ни один из этих семи пунктов не задевает то, что видит
|
||||
пользователь — деление между продуктовым и техническим сделано верно, ничего
|
||||
техническое не выдано владельцу, и ничего продуктовое не спрятано в
|
||||
«технические предположения».
|
||||
|
||||
### Догадка, выданная за факт
|
||||
|
||||
Не найдена. Каждое нетривиальное техническое утверждение («уже сегодня
|
||||
предложение комнаты работает и на чужих партициях», «дубли схлопывает только
|
||||
оптимизатор», названные функции и константы) проверено против кода и
|
||||
подтвердилось — см. предыдущий раздел. Формулировки вида «предполагаю»
|
||||
отсутствуют там, где нужно было бы решение, потому что владелец их уже принял.
|
||||
|
||||
### Однозначность AC
|
||||
|
||||
15 AC, каждый называет способ доказательства (`unit`, `unit + Python parity`,
|
||||
`smoke`, `performance + mutation`, `golden verify`, `typecheck+unit+build+docs
|
||||
review`). Формулировки конкретны и допускают проверку «упало/не упало»:
|
||||
например AC7 требует «итог содержит одну masonry, нет coincident partitions»
|
||||
— проверяемо инвариантом, а не оценочно. AC13 явно требует существования
|
||||
красного мутанта на «coincident partition либо draft» — это ровно дисциплина
|
||||
«тест должен уметь падать», перенесённая в план ещё до кода.
|
||||
|
||||
### Миграция и откат
|
||||
|
||||
Миграция v9→v10 нормативно описана (§7.1–7.3): один partition на одно legacy
|
||||
edge, без слияния/дедупликации, детерминированные ID с указанным источником
|
||||
энтропии, требование TS/Python parity. Откат (§18) корректно разделяет
|
||||
кодовый revert (безопасен) и уже сохранённый v10-конфиг (несовместим со старой
|
||||
карточкой по замыслу, downgrade запрещён явно) — это соответствует
|
||||
`docs/CONFIG-COMPATIBILITY.md`, где подобные необратимые migrate-on-write
|
||||
переходы уже прецедент.
|
||||
|
||||
### Соответствие docs/SCOPE.md
|
||||
|
||||
Задача — tech debt/миграция модели, устраняющая дублирующую сущность и
|
||||
невидимо накапливающийся артефакт (`room_drafts`, не отличимый от обычной
|
||||
стены после reload, блокирующий resize соседней стены). Это поддерживает J6
|
||||
(«Keep the plan true as the home evolves») — упрощает и делает надёжнее
|
||||
механизм разметки контура/комнаты, не расширяя видимый функционал за пределы
|
||||
уже существующего поведения. Новых кнопок, настроек или диалогов ТЗ явно не
|
||||
вводит (§5.2, §13) — соответствует принципу «View mode остаётся продуктом»,
|
||||
редакторская сложность не растёт для пользователя.
|
||||
|
||||
### Release-артефакты и User-Visible
|
||||
|
||||
`User-Visible: yes` обоснован верно (§19): исчезает resume персистентного
|
||||
черновика, меняется видимое поведение незамкнутых стен после reload. Список
|
||||
документов для обновления полный и включает оба changelog, что при реализации
|
||||
обязано попасть в тот же коммит по AGENTS.md.
|
||||
|
||||
## Что проверено и корректно
|
||||
|
||||
- Обязательные разделы §7.1 — все на месте.
|
||||
- Каждый AC — с методом доказательства, формулировки допускают падение теста.
|
||||
- Технические утверждения ТЗ и предпосылки issue — верны по факту чтения кода
|
||||
`origin/dev`, догадок, выданных за решённый факт, не найдено.
|
||||
- Продуктовые решения владельца зафиксированы дословно и исчерпывающе;
|
||||
раздел «технические предположения» не содержит скрытых продуктовых развилок.
|
||||
- Скоуп/не-скоуп конкретны и проверяемы, границы задачи не размыты.
|
||||
- Миграция и откат внутренне согласованы и соответствуют прецеденту
|
||||
`docs/CONFIG-COMPATIBILITY.md`.
|
||||
- `docs/specs/README.md` обновлён в формате, уже принятом для остальной
|
||||
таблицы (без колонки статуса).
|
||||
|
||||
## Чего не проверял
|
||||
|
||||
- Не гонял `npx tsc --noEmit`/`npm test`/`npm run build` — в ветке нет
|
||||
продуктового кода, гонять их не над чем на этапе spec.
|
||||
- Не проверял `npm run invariants` — геометрия ещё не реализована, инварианты
|
||||
модели проверять не на чем.
|
||||
- Не читал полностью весь текст `docs/CANVAS.md`/`docs/WALL-THICKNESS.md`/
|
||||
`docs/ARCHITECTURE.md` построчно — выборочно сверил только фрагменты,
|
||||
относящиеся к `room_drafts`/lineage/reconciliation, поскольку остальное не
|
||||
затрагивается этим ТЗ.
|
||||
- Не оценивал реализуемость помодульно (файлы/хелперы) — ТЗ прямо и верно
|
||||
относит это к техническим решениям вне продуктового ревью (§20, PROCESS.md
|
||||
§7.1 «всё, чего пользователь не наблюдает, агенты решают сами»).
|
||||
- Не связывался с #477/#461/#173/#282/#314 по существу — они упомянуты как
|
||||
контекст связи, не как обязательства этого ТЗ; не-скоуп (§5.2) явно
|
||||
исключает пересечение с #461.
|
||||
|
||||
## Находки
|
||||
|
||||
Нет ни одной находки уровня High или Medium. Low-находок, требующих правки или
|
||||
пометки waived, тоже нет.
|
||||
|
||||
## Итог
|
||||
|
||||
ТЗ полное, однозначное, все обязательные разделы на месте, каждый AC проверяем
|
||||
и называет способ доказательства, продуктовых вопросов не осталось, а
|
||||
технические утверждения подтверждены чтением актуального кода, а не приняты на
|
||||
веру. Задача полностью укладывается в `docs/SCOPE.md` (J6) и не расширяет
|
||||
скоуп за счёт незаявленной пользователю функциональности.
|
||||
|
||||
**Вердикт: зелёный · заход r1 · блокирующих циклов 0/4 · High: 0 · Medium: 0**
|
||||
|
||||
---
|
||||
|
||||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||||
|
||||
## Материал раунда
|
||||
|
||||
- Ветка: `issue/478-remove-room-drafts`, коммит `30a16ed36461` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||||
- Дерево материала: `66116fde28ee91b0ee64d7dc0d3125b82c972505`
|
||||
```
|
||||
git log --all --format='%H %T' | grep 66116fde28ee
|
||||
```
|
||||
- ТЗ `docs/specs/478-remove-room-drafts.md`, блоб `8817d2c4307eed78b4eba9f731b3b6fd7c5270c3`
|
||||
```
|
||||
git log --all --find-object=8817d2c4307eed78b4eba9f731b3b6fd7c5270c3 -- docs/specs/478-remove-room-drafts.md
|
||||
```
|
||||
Reference in New Issue
Block a user