Files
houseplan-card/docs/reviews/SPEC-REVIEW-482-r2.md
T
2026-09-07 06:23:59 +00:00

202 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPEC-REVIEW-482-r2 — Доводка экспорта пространства в PDF
- **Issue:** https://github.com/Matysh/houseplan-card/issues/482
- **Этап:** ревью ТЗ (PROCESS.md §2.4)
- **ТЗ:** `docs/specs/482-pdf-export-polish.md`
- **Трек:** полный (не пересматривается в r2 — решение аналитики #482 не
задето дельтой)
- **Заход:** r2 · блокирующих циклов израсходовано 1 из 4 (до этого вердикта)
## Скоуп ревью
Второй заход, разбор по дельте (PROCESS.md §2.10, issue #214) — дельта
локальна, полный повторный разбор не требуется, обоснование ниже.
1. **Вердикт предыдущего раунда:** комментарий `claude`, 2026-09-07T06:15:24Z —
жёлтый · r1 · High: 0 · Medium: 1 → в задаче (M1, provenance/лицензия
векторного компаса). Документ: `docs/reviews/SPEC-REVIEW-482-r1.md`.
2. **Материал r1** взят из блока «Материал раунда» в конце того документа:
ветка `issue/482-pdf-export-polish`, коммит
`bc93babdf8e7dc346e3465a72b8f2927875095d7`. SHA живой, не осиротел:
`git cat-file -t bc93babdf8e7` → `commit`; дерево `38bf116ad9ad52b85ed8e0aaee3799819a5a1e58`
резолвится тем же коммитом (`git log --all --format='%H %T' | grep 38bf116ad9ad`
→ одна строка, тот же SHA). Дельта объявляется напрямую по SHA, без
content-addressing якорей — ребейза между r1 и r2 не было.
3. **Дельта:** `git diff bc93babd..HEAD` (HEAD = `5c1175cebc8d393f0b08488f76c11411ed686cd0`,
коммит «docs: pin PDF compass provenance»). Единственный содержательный файл —
`docs/specs/482-pdf-export-polish.md`, 16 insertions / 5 deletions, целиком
внутри раздела «13. Векторный компас». Второй изменившийся файл —
`docs/reviews/SPEC-REVIEW-482-r1.md`, который дельту не образует: это
публикация предыдущего вердикта, ожидаемый артефакт конвейера, а не правка
автора. Тела issue #482 и комментариев дельта не касается: сверил текущее
тело issue и полный список комментариев (5 шт.) — новых продуктовых
вопросов или уточнений владельца после r1 нет, последний комментарий
владельца — анонс фикса M1.
4. **`src/**` не тронут:** `git log --oneline 08aad891..HEAD -- src/` пуст —
ветка по-прежнему содержит только ТЗ и review-документы поверх
`v1.73.0-beta.3`; это по-прежнему этап spec, гейтов кода нет и не может
быть.
5. **Почему разбор сокращённый, а не полный:** дельта не задевает ни ребейз на
ушедший вперёд `dev` (SHA r1 жив в текущей истории), ни новую подсистему,
ни контракт поведения — правка меняет только текст обоснования provenance
одного SVG-ассета. Объём дельты (11 чистых строк) несопоставим с исходной
задачей (485 строк ТЗ, 12 AC, 6 подсистем). Единственный AC, чьё
доказательство эта дельта задевает, — AC8 (§17, «license сохранена»,
`docs/specs/482-pdf-export-polish.md:393`).
## Как проверялось
- Перечитал §13 ТЗ целиком (`docs/specs/482-pdf-export-polish.md:308-338`) —
и старую версию на `bc93babd`, и новую на `HEAD`, построчно через
`git diff bc93babd..5c1175ce -- docs/specs/482-pdf-export-polish.md`.
- Сверил формулировку M1 (r1) с текстом финта: старая ссылка на `master`
(`.../blob/master/icons/travel/compass-line.svg`) заменена на три ссылки на
**неизменяемый** upstream commit `bf6bdd0dd3f247f1a320d44d13fecdeda18c071c`
(сам commit, файл в нём, `LICENSE` в нём) — это устраняет именно тот
дефект, который называл r1: ссылка на движущуюся `master` не может уехать
и стать неверной незаметно, потому что коммит зафиксирован по SHA.
- Проверил, что новая формулировка **не скрывает** несовпадение SHA-256:
старый текст утверждал «совпадает по path с каноническим ассетом» без
уточнений; новый прямо признаёт, что файл владельца **не совпадает
побайтово** с upstream (SVG Repo добавил обёртку и `800×800` вместо
`36×36`), и указывает, что совпадают именно `viewBox` и оба `d` — то есть
сузил claim ровно до того, что можно проверить сравнением текста, а не
расширил его. Это соответствует одному из трёх путей закрытия, которые
предлагал r1 («заменить ссылку на master точным commit/blob»), хотя автор
не добавил формальную пометку «принято предположительно» — см. ниже,
почему это не считаю новым замечанием.
- Попытался независимо дойти до upstream `LICENSE` и `compass-line.svg` на
зафиксированном commit через `WebFetch` — инструмент запросил разрешение и
не получил его в этой сессии (тот же результат, что в r1 при попытке через
`mcp__github__get_issue`/`WebFetch`; ограничение окружения, не находка).
Поэтому байт-в-байт я по-прежнему не подтверждаю и не опровергаю — см.
«Чего не проверял».
- Проверил AC8 (`docs/specs/482-pdf-export-polish.md:393`) — текст критерия и
способ доказательства («license check» отдельным пунктом в списке методов)
не менялись дельтой и не нуждались в изменении: AC8 уже предполагал
отдельную проверку лицензии на этапе код-ревью (когда ассет реально
вендорится и появляется файл, который можно сравнить построчно), а не на
этапе ТЗ. Пиннинг на неизменяемый commit — это именно то, что делает такую
будущую проверку осмысленной (проверять фиксированный SHA, а не «текущее
состояние master»).
- Проверил остальные части ТЗ (§1–§12, §14–§20) на предмет того, не появилось
ли противоречий или ссылок, которые эта правка могла разбалансировать —
дельта географически изолирована в §13, соседние разделы (§12 — layout,
§14 — footer/i18n) не ссылаются на provenance компаса и не пострадали.
- Дешёвые гейты кода (`tsc`/`test`/`build`) не гонял: `src/**` не менялся ни
в r1, ни в дельте r2 — гонять их не по чему, как и в r1.
## Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
| **M1** — provenance/лицензия компаса заявлены как факт со ссылкой на движущуюся `master`, без воспроизводимого способа перепроверить | Ссылка на `master` заменена тремя ссылками на неизменяемый upstream commit `bf6bdd0dd3f247f1a320d44d13fecdeda18c071c` (сам коммит, файл, LICENSE); дополнительно текст перестал скрывать несовпадение SHA-256 владельца с upstream и объяснил его источником обёртки SVG Repo, сузив claim до проверяемого (`viewBox` + оба `d`) | `docs/specs/482-pdf-export-polish.md:312-329` (diff `bc93babd..5c1175ce`); коммит `5c1175cebc8d393f0b08488f76c11411ed686cd0` «docs: pin PDF compass provenance» |
Считаю M1 закрытой без выхода за скоуп: правка того же раздела того же ТЗ, не
новая подсистема.
**Остаточное наблюдение (не новое Medium/Low, входит в «чего не проверял»):**
фраза «Provenance проверен перед реализацией» звучит как уже свершившийся факт,
хотя ни в r1, ни в r2 никто с доступом к вебу это не подтвердил — у меня
`WebFetch` не авторизован в обеих сессиях. Это не возвращаю как отдельную
находку, потому что: (а) сама правка отвечает на процессуальное требование
r1 — reproducibility ссылки, а не немедленное личное подтверждение
ревьюером; (б) AC8 уже называет «license check» отдельным методом
доказательства, который по своей природе относится к моменту, когда ассет
реально появляется в репозитории на этапе кода — это точка, где сравнение
станет механическим (файл в коммите против зафиксированного upstream SHA), а
не вопросом доверия к прозе ТЗ. Рекомендую код-ревью этой задачи явно
подтвердить совпадение путём чтения обоих файлов (или через веб-доступ, если
он будет у код-ревьюера), а не принимать формулировку ТЗ как готовое
доказательство.
## Унаследовано из r1
Всё содержимое ТЗ вне §13 принято без повторной проверки в этом раунде — оно
не входит в дельту (`git diff bc93babd..5c1175ce` не касается ничего, кроме
§13.) Основание: `docs/reviews/SPEC-REVIEW-482-r1.md`, вердикт жёлтый на
коммите `bc93babdf8e7dc346e3465a72b8f2927875095d7` (дерево
`38bf116ad9ad52b85ed8e0aaee3799819a5a1e58`), раздел «Что проверено и
корректно»:
- продуктовая рамка и предложение «до/после» (§1–§2 ТЗ);
- скоуп/не-скоуп и изменяемый контракт (§4–§6);
- нормализация контуров, включая корневую причину ложной диагонали (§8);
- локальная дедупликация противоположных сторон (§9);
- полосы размещения размеров (§10);
- материал стен/штриховка и компоновка листа (§11–§12);
- footer/i18n (§14);
- модель/миграция/rollback, touch/a11y/perf/security (§15–§16);
- AC1–AC7, AC9–AC12 (§17) — не переоткрывались, дельта их доказательств не
задевает;
- тест-план и Windows/Linux границы golden (§18);
- документация и release-артефакты (§19), карта изменений (§20).
Наследование не распространяется на AC8 и §13 — они разобраны заново выше.
## Находки
Нет. High: 0. Medium: 0 (M1 закрыта, новых не появилось).
## Что проверено и корректно
- M1 закрыта воспроизводимым способом: ссылка на неизменяемый commit вместо
движущейся ветки — именно то процессуальное требование, которое не
выполнялось в r1 (аналогия с #159, где ссылка тоже не была проверяемой).
- Текст стал честнее, а не более уверенным: явно признано несовпадение
SHA-256 файла владельца с upstream и указана причина — это снижает, а не
создаёт риск «выдать догадку за факт», потому что граница знания названа
прямо (совпадают path/viewBox, не совпадает контейнер).
- AC8 и способ его доказательства не нуждались в изменении: «license check»
как отдельный метод уже покрывает верификацию на этапе кода.
- Дельта не задела ни одну другую подсистему ТЗ; соседние разделы (§12 layout,
§14 footer) остались согласованными сами с собой и с §13.
- `src/**` не менялся — код по задаче ещё не написан, дешёвые гейты неприменимы
на этом этапе, как и в r1.
## Чего не проверял
- Не подтверждал независимо через веб, что зафиксированный upstream commit
`bf6bdd0dd3f247f1a320d44d13fecdeda18c071c` в репозитории
`vmware-archive/clarity-assets` действительно содержит указанный
`compass-line.svg` с `viewBox 0 0 36 36` и обоими `d`-путями, и что `LICENSE`
в том же коммите — действительно MIT с copyright VMware 2018:
`WebFetch` запросил разрешение и не получил его в этой сессии, как и
`mcp__github__get_issue`/`get_issue_comments` (те два я обошёл через `gh`
CLI, у `WebFetch` такого обхода нет). Это не молчаливый пропуск — то же
ограничение зафиксировано в r1, и я явно оставляю его на код-ревью
(см. «Закрытие раунда r1» выше).
- Не перепроверял AC1–AC7, AC9–AC12 — дельта их не касается, основание
наследования указано в разделе выше.
- Не гонял `tsc`/`test`/`build`/`golden`/смоки/инварианты модели — `src/**` не
менялся ни разу за всю историю ветки, гонять нечего; это верно и для r1, и
для r2.
- Не проверял `docs/specs/README.md`/`docs/STATUS.md` на актуальность записи —
дельта их не касается (эти файлы не менялись между `bc93babd` и `HEAD`,
кроме самого добавления записи в r1, уже принятой).
## Вердикт
Единственная находка предыдущего раунда (M1, Medium в скоупе) закрыта
воспроизводимым способом; новых High/Medium/Low находок дельта не породила.
Зелёный вердикт цикла не образует и бюджет не тратит (PROCESS.md §4, #227):
израсходованный бюджет остаётся 1 из 4, заход — r2.
---
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/482-pdf-export-polish`, коммит `5c1175cebc8d` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `4237e7ddaa1fab740d71ebb69648c824f2dd45c8`
```
git log --all --format='%H %T' | grep 4237e7ddaa1f
```
- ТЗ `docs/specs/482-pdf-export-polish.md`, блоб `c6f4fbd7cf5b3e84473ec68513054c3e5ff1e0f9`
```
git log --all --find-object=c6f4fbd7cf5b3e84473ec68513054c3e5ff1e0f9 -- docs/specs/482-pdf-export-polish.md
```