mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-03 21:28:59 +00:00
162 lines
16 KiB
Markdown
162 lines
16 KiB
Markdown
# 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 строки в одном файле, три места:
|
||
|
||
1. одна строка таблицы «Факты по #449» (маркер в теле код-вердикта 16:01);
|
||
2. абзац под таблицей, объясняющий эту строку, плюс следствие в «не-скоупе»
|
||
про необратимую потерю `spent` первого спек-раунда #449;
|
||
3. переформулировка **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.yml` main/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 без повторной проверки. Вердикт — зелёный,
|
||
бюджет цикла не тратится.
|
||
|
||
---
|
||
|
||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||
|
||
## Материал раунда
|
||
|
||
- Ветка: `issue/454-review-round-counter`, коммит `f3e60578d443` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||
- Дерево материала: `983c66cca25d56b4a147e535608bce8f2261ad05`
|
||
```
|
||
git log --all --format='%H %T' | grep 983c66cca25d
|
||
```
|
||
- ТЗ `docs/specs/454-review-round-counter.md`, блоб `b5af292101a495e4699d839397e837a3a2467c85`
|
||
```
|
||
git log --all --find-object=b5af292101a495e4699d839397e837a3a2467c85 -- docs/specs/454-review-round-counter.md
|
||
```
|