16 KiB
SPEC-REVIEW — issue #454 · заход r2
- Issue: https://github.com/Matysh/houseplan-card/issues/454
- Этап: ТЗ на ревью (PROCESS.md §2.4), заход r2, блокирующих циклов израсходовано 1 из 4
- Материал:
docs/specs/454-review-round-counter.mdна коммитеf3e60578(комментарий автора «Замечание r1 (M1) исправлено, ТЗ обновлено:f3e60578», веткаissue/454-review-round-counter) - Предыдущий раунд: r1, жёлтый, документ
docs/reviews/SPEC-REVIEW-454-r1.md, материалebcf1223 - Ревьюер: свежая сессия, без контекста написания ТЗ и r1
Скоуп разбора
Разбор по дельте (PROCESS.md §2.9/§2.10). Дельта — один коммит f3e60578,
git diff ebcf1223..f3e60578 -- docs/specs/454-review-round-counter.md:
32 строки в одном файле, три места:
- одна строка таблицы «Факты по #449» (маркер в теле код-вердикта 16:01);
- абзац под таблицей, объясняющий эту строку, плюс следствие в «не-скоупе»
про необратимую потерю
spentпервого спек-раунда #449; - переформулировка AC2 + новый AC2b + синхронный абзац в «Плане тестирования».
Ребейза не было (родитель дельты — тот же ebcf1223, на котором получен r1).
Контракт поведения (§1–§5 ТЗ), скоуп/не-скоуп по составу, карта реализации,
риски, release-артефакты — не тронуты дельтой, разбираю их по r1, без
повторной проверки. Задета только доказательная база одного AC и одна
фактическая иллюстрация в разделе «Подтверждённая проблема» — сокращённый
разбор оправдан, дельта локальна.
Как проверялось
Правки не вношу — только читаю и перепроверяю исполнением/рассуждением на реальных данных.
- Прочитан диф
git diff ebcf1223..f3e60578целиком (не только резюме автора). - Independently (не со слов автора) снят фактический снимок #449 на сегодня:
gh issue view 449 --repo Matysh/houseplan-card --json comments— все комментарии-вердикты с их точным текстом;git show origin/dev:docs/reviews/SPEC-REVIEW-449-r1.md/…-r2.md/CODE-REVIEW-449-r1.md/…-r2.md— содержимое и собственная итоговая строка вердикта каждого файла;git show <blob>:docs/reviews/SPEC-REVIEW-449-r1.mdна трёх исторических блобах (1ce62613,070c276e,b39f99b3), названных автором, чтобы подтвердить, что-r1.mdфизически содержит тело второго раунда, а-r2.md— третьего.
- По этим данным вручную пересчитаны обе формулы контракта §1–§3 ТЗ для фикстур AC2 и AC2b (см. «Закрытие раунда r1» ниже) — не поверил заявлению автора на слово, получил числа заново из первичных данных.
- Прочитан весь остаток документа (шапка, скоуп/не-скоуп, контракт, крайние случаи, AC1–AC9, карта реализации, риски, release-артефакты, принятые предположения) на предмет того, не сломала ли дельта что-то, что дельта не должна была трогать — не сломала.
Гейты (tsc/test/build/check-docs/invariants/смоки/golden) не
гонял: класс изменения — документация ТЗ, реализации на ветке нет
(scripts/review-doc-guard.mjs, test/review-doc-guard.test.mjs на ветке
задачи отсутствуют), это унаследовано из r1 и дельтой не задето.
Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
M1 (Medium, в скоупе): AC2 требовала attempt=3, spent=2 на фикстуре «реальные данные #449», но буквальный пересчёт по реальным файлам/комментариям даёт spent=1 — план тестирования не указывал, какое из двух прочтений (буквальное или реконструкция) имеется в виду |
AC2 переписан на буквальный слепок (attempt=3, spent=1), добавлен отдельный AC2b на реконструкцию («история, прожитая с исправлением», attempt=4, spent=2); «План тестирования» называет обе фикстуры по имени и раздельно; в «не-скоупе» явно зафиксировано, что spent=1 на сегодняшних данных — правильный ответ, а не недосчёт |
docs/specs/454-review-round-counter.md:96‑111,174‑194 (коммит f3e60578). Перепроверено мной независимо: SPEC-REVIEW-449-r1.md на origin/dev содержит тело раунда 2 (собственная финальная строка — «жёлтый вердикт... возвращается автору»), …-r2.md — тело раунда 3 (финал — «зелёный вердикт... бюджет циклов не тратит»); attemptFromFiles=max(1,2)+1=3, spentFromFiles=1 (только -r1.md блокирующий); spentFromComments: из трёх комментариев маркер несут два (14:56, 15:17), из них блокирующий один (14:56) → 1. max(1,1)=1. Совпадает с новой формулировкой AC2 |
| L1 (Low, была снята с записью в r1, без обязательства правки) — нет разделов «UX»/«i18n»; r1 предлагал добавить строки-заглушки «заодно», если раунд правит документ | Не добавлено — но это была необязательная опция («было бы уместно… не отдельным циклом»), не требование; L1 уже была закрыта самим r1 без возврата автору | Текущий текст ТЗ: шапка по-прежнему содержит только Touch editor: not exposed, строк «UX:»/«i18n:» нет — не регрессия, а неиспользованная опция |
L2 (Low, к сведению, не в счёт вердикта) — cohesion review-doc-guard.mjs |
Не поднималась к правке в r1 и не поднимается сейчас — technical, оставлена автору кода | Карта реализации не изменилась дельтой |
Унаследовано из r1
Без повторной проверки принимаю из docs/reviews/SPEC-REVIEW-454-r1.md
(материал ebcf1223) — дельта этих мест не касается:
- Контракт §1 (источник истины — файлы,
max+1, а не количество) и его проверка на крайних случаях (дыра в нумерации, пустое множество файлов). - Контракт §2 (строка вердикта,
жёлт/краснбез учёта регистра) — совпадает с существующимprocess.yml:100. - Контракт §3 (страховка максимумом) —
max(a,b)не может дать перерасчёт при данном построении источников. - AC1, AC3–AC7 — формулировки однозначны, способ доказательства достижим; AC4/AC5/AC7 согласованы с уже действующими инвариантами #227/#89.
- AC8, AC9 — синхронизация
process.ymlmain/dev через существующий шаг Validate; логика в тестируемом модуле, а не в inline-shell. - Не-скоуп (ручная правка задним числом комментария #449, восстановление
SPEC-REVIEW-449-r1.md, обязательный гейт «назови файл») — исключения корректны и не додуманы. - Ограничение «
process.ymlидентичен в main и dev», план отката, release-артефакты (User-Visible: no, класс B, трейлеры). - Технические наблюдения L1/L2 (не блокируют, см. таблицу выше).
Что проверено и корректно (дельта)
- AC2 (новая формулировка). Число
attempt=3, spent=1подтверждено независимым пересчётом по первичным данным (см. «Как проверялось» и таблицу закрытия) — не осталось расхождения, из-за которого r1 вернул ТЗ. Фикстура названа однозначно («буквальный слепок сегодняшнего состояния ветки»), способ доказательства не изменился (unit). - AC2b (новый). Формула контракта §1/§3, применённая к трём
независимым файлам (
r1жёлтый,r2жёлтый,r3зелёный), даётattemptFromFiles=max(1,2,3)+1=4,spentFromFiles=2(r1, r2 блокирующие, r3 нет) — совпадает с заявленнымattempt=4, spent=2. Формулировка не оставляет второго прочтения: явно названа «реконструкция», а не факт. - Правка в «Подтверждённая проблема» про код-вердикт 16:01. Автор
дополнительно (сверх M1) исправил собственную фактическую ошибку: красный
код-вердикт 16:01 содержит подстроку
CODE-REVIEWв свободном тексте («путь соберёт шаг публикации,CODE-REVIEW-449-r1»), а не отсутствует, как было написано раньше. Проверено дословно по тексту комментария (gh issue view 449 --json comments, комментарий2026-09-04T16:01:28Z, последний абзац) — подстрока действительно там. Утверждение «guard видит… один код-вердикт из одного (attempt=2, верно)» было точным на момент написания дельты (единственный код-вердикт на #449 в тот момент — этот красный). Это иллюстрация в разделе с фактажом, не часть контракта или AC — её точность на дальнейшее развитие живого issue #449 не влияет на доказательность AC2/AC2b, которые используют замороженную (unit-)фикстуру, а не пересчёт по живому issue при каждом прогоне теста. - Внутренняя согласованность документа после правки. Прочитан документ целиком: старое утверждение «дефект повторится на первом же возврате #449 в S7-code-review» удалено (заменено на факт про 16:01), нигде в остальном тексте (скоуп, контракт, карта реализации, риски) на него больше нет ссылок — висячих противоречий не осталось.
Чего не проверял
- Не гонял гейты (
tsc/test/build/check-docs/invariants/смоки/golden/pytest) — класс изменения документация, кода на ветке нет; унаследовано из r1, дельта тоже только в.md. - Не проверял
gh api/git ls-remoteна предмет реальной способности перечислить файлыdocs/reviews/на произвольной ветке без checkout — унаследовано из r1 как «техническая деталь реализации, не продуктовое ограничение», дельта эту часть контракта (§4 ТЗ) не трогает. - Не проверял дальнейшую судьбу код-этапа #449 после комментария 16:01: на
момент этого ревью на issue #449 уже существует второй код-вердикт
(зелёный,
2026-09-04T16:22:58Z, опубликован какdocs/reviews/CODE-REVIEW-449-r2.mdбез коллизии имени — комментарий сам явно называет свой документ). Это не расходится с текстом ТЗ (иллюстрация фиксирует факт на момент авторской правки, а не обещание, что живой issue #449 остановится) и не требует правки ТЗ — привожу для полноты, не как находку. - Не проверял отдельно раздел «Карта реализации»/«Риски» повторно — дельта их не касается, инвариант «унаследовано из r1» покрывает их.
Итог
Находка предыдущего раунда (M1) закрыта и перепроверена исполнением по
первичным данным, а не со слов автора: spent=1 для буквальной фикстуры и
spent=2 для реконструкции — оба числа независимо пересчитаны и совпадают с
новыми AC2/AC2b. Новых High или Medium дельта не создала. Остаток контракта
не тронут и наследуется из r1 без повторной проверки. Вердикт — зелёный,
бюджет цикла не тратится.
Материал раунда
- Ветка:
issue/454-review-round-counter, коммитf3e60578d443— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
983c66cca25d56b4a147e535608bce8f2261ad05git log --all --format='%H %T' | grep 983c66cca25d - ТЗ
docs/specs/454-review-round-counter.md, блобb5af292101a495e4699d839397e837a3a2467c85git log --all --find-object=b5af292101a495e4699d839397e837a3a2467c85 -- docs/specs/454-review-round-counter.md