mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
@@ -0,0 +1,133 @@
|
||||
# SPEC-REVIEW-385-r2
|
||||
|
||||
- Issue: https://github.com/Matysh/houseplan-card/issues/385
|
||||
- Этап: ТЗ на ревью (PROCESS.md §2.4)
|
||||
- Артефакт под ревью: `docs/specs/385-audit-lows.md`, ревизия 2 (2026-08-30),
|
||||
коммит `687b2966` ("docs: #385 spec revision 2 per SPEC-REVIEW-385-r1")
|
||||
- Заход: r2 · блокирующих циклов израсходовано 1 из 4 (до этого вердикта)
|
||||
- Предыдущий раунд: `docs/reviews/SPEC-REVIEW-385-r1.md`, вердикт жёлтый на
|
||||
ревизии 1, коммит `c28b2f2d` ("docs: specify #385 audit-lows batch")
|
||||
|
||||
## Скоуп раунда
|
||||
|
||||
Дельта — `git diff c28b2f2d..687b2966 -- docs/specs/385-audit-lows.md`: правка
|
||||
текстовая, ровно по требованиям вердикта r1 (M1 + Low L2/L3). Код продукта не
|
||||
менялся ни в r1, ни в r2 — стадия ТЗ. Единственный изменённый файл:
|
||||
`docs/specs/385-audit-lows.md` (+23/-9 строк), затронуты четыре места:
|
||||
строка «Ревизия», раздел «Проблема / Контракты» пункт (в), «DoR-примечания»,
|
||||
«Release-артефакты». Разбор по дельте, не заново (PROCESS.md §2.9): полный
|
||||
повторный разбор ТЗ, продуктовой рамки и AC1–AC6 не требуется — дельта
|
||||
локальна, новую подсистему не задевает, ребейза не было.
|
||||
|
||||
## Как проверялось
|
||||
|
||||
По каждой находке r1 — построчное сравнение старого и нового текста (`git
|
||||
diff`) плюс сверка новых утверждений с источником истины (кодом), а не с
|
||||
заявлением автора о том, что правка внесена.
|
||||
|
||||
### Закрытие раунда r1
|
||||
|
||||
| Находка (r1) | Чем закрыта | Где это видно |
|
||||
|---|---|---|
|
||||
| **M1** — контракт (в) называет только первый дизъюнкт `isRelease`, риск ложного отказа CI на бета-коммитах приёмки эталонов | Абзац «Контракт» переписан: назван **весь** предикат (`(/^Release v\d/...) \|\| Boolean(one('Release'))`), явно оговорено «НЕ пересказ по памяти и НЕ только первый дизъюнкт», приведён конкретный контрпример-коммит и путь отказа через `evaluateCommit`; реализация явно требует одну функцию, используемую и `makeCommit`, и гейтом в `parseRecords`, AC4 привязан к переиспользованию | `docs/specs/385-audit-lows.md:45-59`. Выражение сверено дословно с `scripts/process-gate.mjs:133-135` — совпадает посимвольно (проверено `sed -n '125,136p' scripts/process-gate.mjs`). Контрпример `5f6ee657` перепроверён заново командой `git show -s --format='%s%n---%n%B' 5f6ee657`: subject `test: accept explicit value source golden` не матчит `/^Release v\d/`, трейлер `Release: v1.69.0-beta.5` присутствует — вторым дизъюнктом `isRelease` действительно становится `true`. Утверждение точное |
|
||||
| **L2** — DoR-примечания не называют влияние на производительность | Добавлена третья фраза: «производительность — (в) сокращает работу pre-push/CI-гейта на длинных диапазонах (только выигрыш, бенч не требуется)» | `docs/specs/385-audit-lows.md:134-136` |
|
||||
| **L3** — «(б)–(г) — мелкие уточнения» в Release-артефактах двусмысленно относительно changelog | Переписано прямо: changelog получает запись только про (а); (б)–(г) явно исключены из changelog («видимого поведения не меняют… НЕ входят»), с явной привязкой к `User-Visible: no` | `docs/specs/385-audit-lows.md:140-143` |
|
||||
| **L1** — «план автотестов» ссылается на несуществующий тестовый паттерн `_valueBadgeForBinding` | Не требовала правки — в r1 снята решением ревьюера без возврата («технический вопрос — домен автора, не блокирует») | Текст не менялся, `docs/specs/385-audit-lows.md:115-117` — по-прежнему присутствует нетронутым; закрытие r1 было «оставляю как есть», а не «поправить», так что отсутствие правки — ожидаемо, не регресс |
|
||||
|
||||
M1 и L2/L3 закрыты по существу и корректно. Однако при сверке дельты нашёл
|
||||
остаточную несогласованность текста — новая находка ниже.
|
||||
|
||||
## Находки
|
||||
|
||||
### Low (правится или снимается решением ревьюера — не блокирует)
|
||||
|
||||
**L4. Абзац-обоснование перед «Контрактом» (в) сохраняет старую неточную
|
||||
формулировку предиката, которую r1 требовал заменить.**
|
||||
|
||||
`docs/specs/385-audit-lows.md:41-44`:
|
||||
> `parseRecords` зовёт дорогую проверку (2×`git show` на каждый src-файл) для
|
||||
> КАЖДОГО коммита, хотя потребляется она только для стабильных релизных
|
||||
> (`/^Release v\d/` без beta/candidate, :134).
|
||||
|
||||
Это почти дословно та же фраза, которую вердикт r1 (M1, «Требуется на этом
|
||||
раунде») просил заменить на точную — и она действительно заменена, но только
|
||||
в следующем абзаце («Контракт: …»). Абзац-обоснование перед ним остался
|
||||
нетронутым и по-прежнему называет лишь первый дизъюнкт, без трейлера
|
||||
`Release:`. Формально в документе сейчас два соседних утверждения о том, при
|
||||
каких коммитах включается проверка: неточное (проблема) и точное (контракт).
|
||||
|
||||
Почему это не Medium: нормативная часть — именно «Контракт», не «Проблема»;
|
||||
контракт сформулирован недвусмысленно, с конкретным контрпримером и
|
||||
файл:строка, и явно предупреждает «это не то же, что первый дизъюнкт». Риск,
|
||||
из-за которого M1 был возвращён (реализатор напишет упрощённую версию,
|
||||
прочитав только описание проблемы) кода не создаёт критического пути, потому
|
||||
что реализатор будет реализовывать по «Контракту» и AC4, а не по абзацу
|
||||
«Проблема». Но самопротиворечие в тексте ухудшает читаемость и не помешало бы
|
||||
поправить заодно, раз уж абзац переписывался.
|
||||
|
||||
Не блокирует переход в `S5-ready`; снимаю записью, правка на усмотрение
|
||||
автора при следующей правке этого файла (не стоит отдельного раунда).
|
||||
|
||||
## Унаследовано из r1
|
||||
|
||||
Без повторной проверки в r2 приняты факты, установленные в
|
||||
`docs/reviews/SPEC-REVIEW-385-r1.md` на коммите `c28b2f2d` — дельта их не
|
||||
затрагивает:
|
||||
|
||||
- Обоснование полного трека (критерий «одна поверхность» §5 не выполняется,
|
||||
прецедент #369 / SPEC-REVIEW-376-r1 H1).
|
||||
- Точность описаний дефектов (а), (б), (г) — построчная сверка с
|
||||
`houseplan-editor-runtime.ts:12252-12312`, `devices.ts:868-892`,
|
||||
`import_export.py:504-519` соответственно; текст этих пунктов в дельте r2
|
||||
не менялся.
|
||||
- Наличие всех обязательных разделов §7.1, однозначность и доказуемость
|
||||
AC1, AC2, AC3, AC5, AC6 (AC4 перепроверен в r2 отдельно — см. ниже),
|
||||
реалистичность плана автотестов и мутантов (кроме отмеченного L1),
|
||||
корректность отката, отсутствие незаявленных догадок, обоснованный отказ
|
||||
от эскалации продуктовых вопросов владельцу.
|
||||
- Ссылка контракта (а) на букву `docs/specs/378-value-face-source.md:85`.
|
||||
- Единственность пути записи `value_source`/`value_badge` через
|
||||
`_valueBadgeForBinding` (два вызова, :12260/:12308, третьего нет) —
|
||||
проверено в r1 через `grep`, риск в разделе «Риски» не менялся дельтой.
|
||||
- Отсутствие задвоенности AC5 относительно существующих pytest-тестов.
|
||||
- Неприменимость гейтов `typecheck`/`test`/`build`/`check-docs`/`invariants`/
|
||||
смоков/`golden:verify` на этой стадии — код продукта не существует; в r2
|
||||
подтверждено, что диапазон `c28b2f2d..687b2966` тоже не касается кода
|
||||
(`git show --stat` — единственный файл, `docs/specs/385-audit-lows.md`).
|
||||
|
||||
## Что проверено заново в r2 (сверх таблицы закрытия)
|
||||
|
||||
- **AC4 остаётся согласован с новым текстом контракта.** AC4 говорит
|
||||
«классификация релизности — та же функция, что в гейте (юнит сверяет
|
||||
идентичность/переиспользование предиката)» — это не изменилось и корректно
|
||||
описывает исправленный контракт (полное выражение, а не первый дизъюнкт).
|
||||
Расхождения между новым текстом (в) и AC4 нет.
|
||||
- **Точность нового текста контракта (в) против кода.** Выражение
|
||||
`(/^Release v\d/.test(subject) && !/-(beta|rc|alpha)\.|candidate/i.test(subject)) || Boolean(one('Release'))`
|
||||
сверено с `scripts/process-gate.mjs:133-135` — совпадает дословно.
|
||||
- **Точность контрпримера `5f6ee657`.** Перепроверено заново (не полагался на
|
||||
заявление r1): `git show -s --format='%s%n---%n%B' 5f6ee657` — subject не
|
||||
матчит regex, трейлер `Release: v1.69.0-beta.5` присутствует, значит
|
||||
`isRelease` истинно вторым дизъюнктом. Пример в спеке верен.
|
||||
- **Файловый скоуп дельты.** `git show --stat 687b2966` — единственный
|
||||
файл `docs/specs/385-audit-lows.md`; других изменений в этом коммите нет.
|
||||
|
||||
## Чего не проверял
|
||||
|
||||
- Полный повторный разбор AC1, AC2, AC3, AC5, AC6, разделов «Сценарий», «Что
|
||||
человек увидит», «Скоуп/не-скоуп», «UX», «Модель данных», «i18n», «Риски»
|
||||
кроме их незатронутых дельтой частей — они не менялись между r1 и r2,
|
||||
наследую вывод r1 (раздел «Унаследовано из r1» выше).
|
||||
- Гейты `typecheck`/`test`/`build`/`check-docs`/`invariants`/смоки/
|
||||
`golden:verify` — неприменимы, код продукта не существует (стадия ТЗ),
|
||||
дельта r2 тоже не код (подтверждено `git show --stat`).
|
||||
- Реальные числовые издержки `2×git show` на типичный диапазон коммитов — не
|
||||
требуется AC4, только факт отсутствия лишних вызовов.
|
||||
|
||||
## Вердикт
|
||||
|
||||
Зелёный: находка M1 предыдущего раунда закрыта по существу и корректно
|
||||
(текст контракта точен, сверен с кодом заново), L2 и L3 закрыты полностью.
|
||||
Новая находка L4 — Low, самопротиворечие соседних абзацев — не блокирует и
|
||||
снимается записью на усмотрение автора. High нет, Medium нет. ТЗ готово к
|
||||
переходу в `S5-ready`.
|
||||
Reference in New Issue
Block a user