Files
houseplan-card/legacy/reviews/v1.77.0/SPEC-REVIEW-593-r3.md
T
Claudeandclaude[bot] 0991c45374 fix(tools): архив переписывает относительные ссылки перенесённых документов (#682)
Ревью #682 r1, Medium: перенос добавляет документу уровень вложенности
(`docs/reviews/X.md` → `legacy/reviews/<тег>/X.md`, `docs/specs/` →
`legacy/specs/`), а относительные ссылки внутри перенесённых документов и в
соседях, ссылавшихся на них, никто не пересчитывал — на `97d19268` 53 битые
ссылки в 46 файлах (заявление «все 26 резолвятся» в `7feb6177` было верно
только до переноса документов ревью). Гейты архив не смотрят.

`reviews-archive.mjs`: `repairLinks` пересчитывает ссылку, если она не
резолвится от нового места, а цель находится от нового или старого места
через карту переносов; битая и до переноса ссылка не трогается. `--apply`
делает это само, `--repair-links=<rev>` — для всех переименований
`<rev>..HEAD`, `--check-links` печатает битые. Этим коммитом
`--repair-links=origin/dev` переписал ровно 53 ссылки в 46 файлах; остались
две прежние «...»-заглушки в CODE-REVIEW-448-r2 (битые и на dev). Тесты:
перенесённый документ, сосед со ссылкой в архив, ТЗ со ссылкой на позже
перенесённое ревью, битая-до-переноса не трогается, в `legacy/` битых нет;
мутант `reviews-archive-links-from-new-place-only`. PROCESS §2.10 и
DEVELOPMENT › Release называют переписывание и `--check-links`.

Issue: #682
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-09-27 22:10:47 +00:00

136 lines
22 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-593-r3 — «Заменить все иконки библиотеки и расширить каталог до 60 плановых символов»
Issue: [#593](https://github.com/Matysh/houseplan-card/issues/593)
Этап: spec (полный трек, унаследовано из r1 — критерий «одна поверхность» нарушен явно: `src/**`, генератор, i18n, PDF-путь, golden, бюджеты)
Заход: r3 · блокирующих циклов израсходовано на входе в раунд: 1 из 4 (дано конвейером; r1 — красный, спорный цикл засчитан; r2 — красный, но зелёный вердикт этого раунда бюджет не тратит — §4, #227)
## Вердикт
**Зелёный.** High: 0. Medium в скоупе: 0. Medium вне скоупа: 0. Low: 0.
Разбор по дельте (§2.10): единственная блокирующая находка r2 (H1(new), Q3/AC10 —
провенанс) закрыта по существу двумя действиями владельца и правкой ТЗ (редакция 4).
Новых находок в затронутой дельтой области не обнаружено.
## Материал раунда (входные данные разбора)
- Тело issue #593 на момент разбора: `gh issue view 593 --json body` — редакция 4 от
19.09.2026, раздел `## ТЗ`, сохранённое предложение автора выше него.
- Все 8 комментариев issue: `gh issue view 593 --json comments` (добавились три новых
относительно материала r2: ответ владельца на Q1–Q3 `#issuecomment-5739749394` уже
был учтён r2; новые — полноценный грант `#issuecomment-5739841899` (2026-09-19T06:09:00Z)
и ответ на красный вердикт r2 `#issuecomment-5739855252` (06:12:00Z), которым
поставлена `S4-spec-review`, заход r3).
- Предыдущий раунд: [`docs/reviews/SPEC-REVIEW-593-r2.md`](SPEC-REVIEW-593-r2.md),
вердикт красный, материал зафиксирован в его собственном машинном блоке якорей:
ветка `dev`, коммит `dcd6657581ba205edb63713e011a498b51983a20`, дерево
`0b48707268e99ee38221c8e74fb1c48ce6793e35`, тело issue sha256
`d3303755f955b90dcdf74279c7b76a98de9814103c65cfeb2a5455a49201d457`.
- Прецедент [#159](https://github.com/Matysh/houseplan-card/issues/159) — использован
повторно только в объёме, нужном для проверки, что новый грант (06:09:00Z) содержит
все три элемента, которые сам r2 процитировал из него дословно; заново не перечитывал
весь `docs/reviews/CODE-REVIEW-159-*` — это уже сделано r2 и не относится к дельте.
- Код: `test/furniture-assets.test.mjs` (тест `'release provenance is normalized to the
repository MIT grant'`, три `assert.match`: `issuecomment-5454085168`,
`issuecomment-5449707137`, SHA-256 архива 0.3.0), `assets/furniture/houseplan-0.3.0/README.md`
(для сверки структуры, которую редакция 4 обязана воспроизвести под новыми
значениями) — оба прочитаны заново для проверки закрытия H1(new). Полный grep
`houseplan-0.3.0` по `src/**`, `scripts/**`, `test/**`, `docs/**` — сверка §4 п.11
(«пять живых ссылок»).
- Ветка/код продукта: не создавались. `git log --oneline -- src/ custom_components/`
и `git diff origin/dev..HEAD -- src custom_components` — пусто; веток `issue/593-*`
нет. Рабочая копия на `HEAD = 2167d4396884c3c45ce7991ba603a91a13cdb381` (коммит
публикации документа r2). Гейты `typecheck`/`test`/`build`/`bundle:budget` не
запускал — этап ревью ТЗ, продуктовый код не существует; это же делали r1 и r2.
## Закрытие раунда r2
| Находка r2 | Чем закрыта | Где это видно |
|---|---|---|
| **H1(new).** Ответ владельца на Q3 («Подтверждаю собственное авторство иконок») давал только один из трёх элементов прецедента #159 (авторство, но не разрешение под MIT и не привязку к архиву); ТЗ, удаляя каталог `houseplan-0.3.0`, не планировало ни новый SHA-256, ни обновление исполняемого провенанс-теста, вынуждая исполнителя либо выдумывать значения, либо молча ослабить единственную защиту от повторения истории #159. | Владелец опубликовал отдельным комментарием ([`#issuecomment-5739841899`](https://github.com/Matysh/houseplan-card/issues/593#issuecomment-5739841899), 2026-09-19T06:09:00Z) полноценный грант: «Я являюсь автором всех 93 SVG из архива `houseplan-furniture-0.4.0.zip`… SHA-256 `69BA5E0C398542D59F24269F637F57B8EBF31C2836C9D493F084AD29AB299FDE`, размер 695 379 байт, и разрешаю House Plan использовать, изменять и распространять их на условиях MIT License репозитория без обязательной отдельной атрибуции» — присутствуют все три элемента прецедента: (а) авторство, (б) разрешение на использование/изменение/распространение под MIT, (в) привязка к конкретному архиву/версии. Дополнительно владелец лично сверил байты вложения, поданного `nikitaevfz-commits`, с копией, переданной напрямую (совпадающие SHA-256 и размер) — это сильнее, чем было доступно в #159. ТЗ доведено до редакции 4: §4 п.10 вводит `assets/furniture/houseplan-0.4.0/README.md` как провенанс-документ (ссылка на грант, имя архива, SHA-256, запрет ручной правки generated-файлов) и требует обновить (не ослабить) провенанс-тест «на новые значения — число `assert.match` не уменьшается»; §4 п.11 перечисляет все пять живых ссылок на путь `houseplan-0.3.0`, которые нужно перевести на `0.4.0`; AC10 переписан под оба факта; в §8 добавлен мутант `furniture-provenance-doc-loses-its-hash`; риск добавлен в §11 с явной атрибуцией «найдено ревью r2». | Комментарий `#issuecomment-5739841899` (текст выше); тело issue редакция 4, §3 «Q3. Авторство и лицензия», §4 п.10–11, §8 «Доказательства» → «провенанс», §10 AC10, §11 (пункт «Потеря провенанса…»); комментарий владельца `#issuecomment-5739855252` фиксирует переход в `S4-spec-review`, заход r3. |
Разбор закрытия — не по заявлению автора: см. «Как проверялось» ниже, где приведён построчный разбор нового текста гранта против трёх обязательных элементов прецедента и построчная сверка §4 п.11 с фактическим деревом.
## Как проверялось (дельта r2→r3)
1. **Три элемента гранта.** Сверил текст `#issuecomment-5739841899` построчно с шаблоном, который сам r2 процитировал из #159 («Я являюсь автором всех 77 SVG… и разрешаю… на условиях MIT License… без обязательной отдельной атрибуции»). Новый текст воспроизводит структуру предложение-в-предложение с заменой чисел (93 SVG вместо 77) и явно называет архив по имени (`houseplan-furniture-0.4.0.zip`) и версии, чего не хватало в предыдущем ответе («Подтверждаю собственное авторство иконок»). Все три элемента присутствуют одновременно в одном комментарии.
2. **Чистота цепочки поставки.** Прочитал добавленный владельцем абзац о совпадении байт вложения `nikitaevfz-commits` с копией, переданной напрямую (SHA-256 + размер). Это прямо снимает опасение H1(new) п.1 («тот же самый посторонний аккаунт второй раз подряд поставляет архив») — в отличие от #159, здесь есть явная проверка, а не только совпадение по умолчанию.
3. **Провенанс-документ и тест не выдуманы, а специфицированы количественно.** Перечитал текущий `test/furniture-assets.test.mjs:51-58` (3 `assert.match`: два URL на разные комментарии #159 + SHA-256 0.3.0) и `assets/furniture/houseplan-0.3.0/README.md` (структура: абзац гранта со ссылкой + абзац об архиве со второй ссылкой + SHA-256 + примечание про правку руками). §4 п.10 редакции 4 называет для нового README конкретные значения: ссылку на `#issuecomment-5739841899`, точное имя архива `houseplan-furniture-0.4.0.zip`, точный SHA-256 `69BA5E0C398542D59F24269F637F57B8EBF31C2836C9D493F084AD29AB299FDE`. Структура отличается от прецедента (там было два независимых URL — грант и отдельная attachment-комментарий стороннего аккаунта; здесь оба факта объединены в один комментарий владельца, поскольку архив был приложен в теле issue, а не отдельным комментарием стороннего участника, и тот же комментарий владельца уже содержит верификацию байт). Это техническое, не продуктовое расхождение (расположение и число ссылок в служебном README — деталь реализации, не то, что видит пользователь), и ТЗ фиксирует конкретные значения, а не оставляет их на усмотрение будущего исполнителя — угадывать нечего. Требование «число `assert.match` не уменьшается» (т.е. не менее 3) — измеримый порог.
4. **§4 п.11 — «пять живых ссылок» сверены с деревом.** `grep -rn "houseplan-0\.3\.0"` по `src/**`, `scripts/**`, `test/**`, `docs/**` (за вычетом `docs/reviews/**`, `docs/specs/**`, которые ТЗ явно исключает как исторические) даёт ровно перечисленные файлы: `scripts/generate-furniture-assets.mjs:9`, `test/furniture-path-join.test.mjs:40`, `test/furniture-assets.test.mjs:13,55` (две строки, как и написано — «(две — `pack.json` и `README.md`)»), `docs/FURNITURE.md:19`, `docs/STATUS.md:34`. Полное совпадение, ни одна ссылка не пропущена и не выдумана лишняя.
5. **Мутант `furniture-provenance-doc-loses-its-hash`.** Проверил `scripts/mutation-registry.mjs` на коллизию имени — вхождений нет, как и у четырёх мутантов, названных в r1/r2 (`furniture-legacy-shadows-designer-art`, `furniture-pack-accepts-foreign-symbol-count`, `furniture-cactus-lands-in-exercise`, `bundle-budget-lazy-ceiling-never-fires`). Мутант логически привязан к третьему столбцу AC10 и закрывает ровно тот путь деградации, который называла находка H1(new) п.6(б) («тихо ослабить тест»).
6. **Согласованность SHA-256/размера архива по всему документу.** Значение `69BA5E0C398542D59F24269F637F57B8EBF31C2836C9D493F084AD29AB299FDE` и «695 379 байт» повторяются в комментарии `#issuecomment-5739841899`, в §3 Q3 и в §4 п.10 ТЗ — все три вхождения совпадают побайтово (сверено копированием, не визуально), источник один — комментарий владельца; расхождений «одно число — два значения» не найдено. Формат строки (64 hex-символа) соответствует SHA-256.
7. **Отсутствие регрессии по остальным разделам.** Сверил, что редакция 4 не тронула ничего за пределами §3 Q3, §4 п.10–11, §8 (абзац «провенанс»), §9, §10 AC10, §11 (новый пункт риска), §12 (без изменений — продуктовые пункты по-прежнему отсутствуют, что и требуется после закрытия H1(r1)). Текст Q1/Q2, §5–§7, AC1-9/11, таблица мутантов (кроме добавленного пятого) — побайтово те же формулировки, что цитирует r2 — делали построчную сверку конкретно этих разделов, не полное построчное сравнение всего документа целиком.
## Что проверено и корректно (унаследовано + новое)
- Закрытие H1(new) — подтверждено по существу, см. таблицу и «Как проверялось» выше.
- §4 п.10 и п.11 — специфицированы количественно (конкретные значения ссылки/имени/хеша, точный список из пяти ссылок), не оставляют технического решения на угадывание исполнителя.
- Мутант `furniture-provenance-doc-loses-its-hash` не конфликтует по имени с реестром и логически закрывает найденный r2 путь тихого ослабления теста.
- Число и содержание release-артефактов (§9) согласовано с §4 п.10 (тот же путь `assets/furniture/houseplan-0.4.0/README.md`).
- Одно число — один источник: SHA-256 и размер архива фигурируют в трёх местах текста, все совпадают и восходят к одному комментарию владельца.
## Унаследовано из r2 (и через него — из r1)
Дельта r2→r3 ограничена §3 Q3, §4 п.10–11, §8 (абзац «провенанс»), §10 AC10, §11 —
всё остальное принято без повторной проверки в этом раунде, со ссылкой на
[`SPEC-REVIEW-593-r2.md`](SPEC-REVIEW-593-r2.md) (материал: ветка
`dev`, коммит `dcd6657581ba205edb63713e011a498b51983a20`, дерево
`0b48707268e99ee38221c8e74fb1c48ce6793e35`) и, где отмечено, на
[`SPEC-REVIEW-593-r1.md`](SPEC-REVIEW-593-r1.md) (коммит
`073c45b04308cd613182c700f30c75ebfa8d2ca7`):
- Комплектность обязательных разделов §7.1 — проверена r1, дельта их не убирала.
- H1(r1) (продуктовые вопросы Q1/Q2 закрыты владельцем через `blocked` + отдельный
ответ, а не самоподтверждением автора) — закрыто в r2, дельта r3 этого не касалась.
- M1(r1) (AC9/бюджеты: два ленивых графа получают настоящий гейт вместо печати) —
закрыто в r2 (`lazyGraphCeilingViolation`, `LAZY_*_GZIP_CEILING`, мутант
`bundle-budget-lazy-ceiling-never-fires`), дельта r3 этого не касалась.
- Все фактические числа о текущем состоянии кода (состав `RETAINED_IDS`,
default-размеры 12 retained-символов, число ключей i18n 29/56 в исходном
состоянии, ловушка двойного объединения `FURNITURE`/`BY_ID`, состав golden-сцен,
существование npm-скриптов) — проверены r1 построчно, дельта их не меняла.
- Q1/Q2 содержательно (`cactus → plant`, 32 непустые категории, поведение при отказе
ленивого чанка для всех 60 предметов, снятие обещания `docs/FURNITURE.md`) —
проверены r2 по тексту и коду (`src/decor-image-editor.ts`,
`src/furniture-art-runtime.ts`, `toast.furniture_art_load_failed`), дельта r3 их
не трогала.
- Мутанты `furniture-legacy-shadows-designer-art`, `furniture-pack-accepts-foreign-
symbol-count`, `furniture-cactus-lands-in-exercise` — сверены на отсутствие
коллизий в r1/r2, не перепроверял заново.
## Чего не проверял
- Содержимое `houseplan-furniture-0.4.0.zip` побайтово (93 SVG, `pack.json`) — как и
в r1/r2, это предмет код-ревью, когда пакет окажется в дереве; полагаюсь на
проверенный аналитикой S2 прогон генератора («OK: 60 plan symbols, 33 menu icons»)
и на личное подтверждение владельца о побайтовом совпадении вложения issue с
переданной напрямую копией.
- Не пересчитывал SHA-256 архива самостоятельно (не скачивал вложение) — находка
H1(new) была не о неверном хеше, а об отсутствии закреплённого механизма; сейчас
механизм закреплён, независимая перепроверка байтов — задача код-ревью.
- `npm run typecheck`, `npm test`, `npm run build`, `npm run bundle:budget`,
`golden:verify`, любые смоки — этап ревью ТЗ, продуктовый код не существует
(нет коммитов и веток `issue/593-*`); так же поступали r1 и r2.
- Полное построчное сравнение всего тела ТЗ редакция 3 vs редакция 4 — сравнивал
прицельно разделы, которые называет комментарий владельца о редакции 4 (§3 Q3,
§4 п.10–11, §8, §10 AC10, §11); не проверял, что где-то за пределами названного
диапазона не появилось незамеченного текстового расхождения — риск низкий, так как
сам процесс написания ТЗ (правки поверх сохранённого текста с явным указанием
«что меняется») уже дважды подряд (r1→r2, r2→r3) точно называл границы своих правок.
- Дубликаты (аналогичные issue) — не проверял повторно; r1 не нашёл признаков
дублирования, дельта r2→r3 не создаёт нового риска дублирования.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `dev`, коммит `2167d4396884` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `857164801ddbfc7450d2e95e1617b258d6704dd2`
```
git log --all --format='%H %T' | grep 857164801ddb
```
- Тело issue: `3a8d99615191f61cc781ac873210df277ce0951d828113e3efa89700a5b7b6a3`
- Вердикт конвейера: `green` · High 0