Files
houseplan-card/docs/reviews/SPEC-REVIEW-399-r2.md
T
2026-08-31 01:31:41 +00:00

15 KiB
Raw Blame History

SPEC-REVIEW-399-r3

  • Issue: https://github.com/Matysh/houseplan-card/issues/399
  • ТЗ: docs/specs/399-backend-gate-honesty.md
  • Материал: SHA bb635298c153ba8d5104e19a70e695d1fcf1a5c5 (ветка issue/399-backend-gate-honesty, ревизия 3 поверх dev; merge-base с origin/dev = f7fb3369 = текущий tip dev — рёбейза не было)
  • Заход: r3, не r2 — см. «Расхождение с заданием раунда» ниже
  • Блокирующих циклов израсходовано: 2/4 (r1 жёлтый, r2 жёлтый; зелёный цикла не тратит, #227)
  • Трек: полный (не изменился, наследуется из r1/r2)
  • Вердикт: зелёный

Расхождение с заданием раунда (нужно проговорить явно)

Задание на этот прогон присвоило заходу номер r2 и указало «блокирующих циклов израсходовано 1 из 4». Это не соответствует фактическому состоянию issue:

  • на #399 уже стоят два реальных комментария-вердикта: Вердикт: жёлтый · заход r1 · блокирующих циклов 0/4 · High: 0 · Medium: 1 → в задаче (2026-08-31T01:14:00Z) и Вердикт: жёлтый · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 1 → в задаче (2026-08-31T01:23:10Z);
  • на каждый из них автор ответил правкой: 6d229c66 docs: #399 spec revision 2 per SPEC-REVIEW-399-r1, затем bb635298 docs: #399 spec revision 3 per SPEC-REVIEW-399-r2 (комментарий автора «Ревизия 3 — Medium закрыт», 2026-08-31T01:26:20Z);
  • файл docs/reviews/SPEC-REVIEW-399-r1.md в репозитории существует, но содержит текст, который сам себя называет «SPEC-REVIEW-399-r2» (шаг публикации предыдущего прогона присвоил ему имя r1 по (тоже ошибочному) заданию того прогона, затерев исходный документ r1 — тот же класс сбоя, который этот прогон обязан не повторить).

То есть реально состоялись два цикла (r1 и r2), оба жёлтые, оба стоили бюджета: 2/4. Присвоение этому прогону имени r2 создало бы риск нового столкновения — второй комментарий-вердикт с заголовком «заход r2» на одной issue — и заняло бы неверную позицию в бюджете (1/4 вместо фактических 2/4). Поэтому документ и вердикт этого прогона используют номер r3, полученный из вердиктов и коммитов issue, а не из присланного заголовка задания. Далее — процедура §2.9/§2.10 для «не первого» цикла.

Дельта, которая является предметом этого раунда

git diff 6d229c66..bb635298 -- docs/specs/399-backend-gate-honesty.md — ровно три места:

  1. строка «Ревизия» в шапке (3, со ссылкой на SPEC-REVIEW-399-r2 и причиной: «план тестов повторял снятую формулировку AC5»);
  2. раздел «План автотестов», пункты 4–5 переписаны: пункт 4 теперь описывает перебор каталога .github/workflows/*.yml целиком и явно фиксирует «списка обходимых файлов в тесте нет и быть не должно»; пункт 5 добавлен и называет вывод проверки на реальном дереве («девять workflow, установка python-зависимостей — в двух»);
  3. в раздел «Мутанты» добавлена новая запись workflow-scan-hardcodes-the-list (замена перебора каталога на фиксированный список имён обязана красить пункт 4 плана).

Ничего за пределами этих трёх мест не менялось: контракт п.(3), AC5 сам текст, разделы (1) M3, (2) Low «а», скоуп/не-скоуп, AC1–AC4/AC6, риски, откат, release-артефакты — байт в байт те же, что видел r2.

Закрытие раунда r2

Находка r2 Чем закрыта Где видно
Medium: «План автотестов» п.4 дословно повторял снятую (ревизия 2) формулировку AC5 — «явный список обходимых файлов зафиксирован; добавление нового файла без обновления списка краснеет» — то есть описывал именно ту хардкод-конструкцию, от которой переписанный AC5 уходит П.4 переписан: «Каталог .github/workflows/*.yml перебирается целиком… краснеет без правки каких-либо списков в тесте… Списка обходимых файлов в тесте нет и быть не должно — файл, не ставящий python-зависимостей, распознаётся по собственному содержимому.» Формулировка теперь дословно исключает хардкод-список, а не допускает его как законное прочтение docs/specs/399-backend-gate-honesty.md:155-159 (план, п.4), :170-172 (новый мутант workflow-scan-hardcodes-the-list, закрепляющий это как проверяемый контракт для код-ревью), SHA bb635298

Находка закрыта по существу, а не переформулирована уклончиво: старая фраза «список… без обновления списка краснеет» заменена на прямой запрет («списка… нет и быть не должно»), и добавлен мутант, ловящий именно откат к списку, если реализация всё же попытается его завести — то есть контракт теперь не только описан текстом плана, но и зафиксирован как проверяемая точка для код-ревью.

Унаследовано из r2 (без повторной проверки)

Со ссылкой на docs/reviews/SPEC-REVIEW-399-r1.md (файл содержит текст раунда r2), SHA 6d229c66:

  • §7.1: все обязательные разделы на месте (сценарий, что увидит человек, проблема по пунктам, скоуп/не-скоуп, UX/данные/i18n — н/п обоснованно, AC с доказательствами, риски, откат, release-артефакты) — делта их не трогает.
  • Контракт п.(3) и текст AC5 (перебор каталога, а не списка; два исхода на файл) — не менялись этой ревизией, r2 их принял.
  • AC1–AC4, AC6 — текст не менялся, доказательства признаны однозначными в r1/r2.
  • Факт «в репозитории девять workflow, python-зависимости ставят два (validate.yml, mutation-gate.yml)» — перепроверялся в r2 на дереве той ревизии; в этом раунде перепроверен заново (см. ниже), так как та же цифра теперь дополнительно фигурирует в новом п.5 плана — расхождений нет.
  • Классификация трека (полный, класс B, три несвязанные поверхности) — не меняется.
  • Продуктовое обрамление и персоны SCOPE.md (задача инфраструктурная, User-Visible: no, ни одна J-строка Core user jobs не затронута) — не изменилось.
  • «Чего не проверял» из r1/r2 (сетевое содержимое package_constraints.txt тега 2026.8.3, объём ruff-долга при исходе (2), аудит-документ вне репозитория) — остаётся в силе, эта делта их не касается.
  • Расхождение задания/факта в самом r2 (там заход был неверно назван r1 в задании, скорректирован до r2) — исторический факт, не влияет на эту ревизию, кроме того, что от него унаследована необходимость сверять номер захода по вердиктам issue, а не по заголовку задания (сделано выше).

Как проверялось

  • перечитаны docs/SCOPE.md, AGENTS.md, PROCESS.md целиком, включая §2.9, §2.10 (объём по дельте), §4 (лимит циклов, разница «заход»/«цикл»), §7.1 (обязательные разделы), §12 (запрещено);
  • прочитано тело issue #399 и все 4 комментария (gh api repos/Matysh/houseplan-card/issues/399/comments) — восстановлена реальная последовательность r1 → ревизия 2 → r2 → ревизия 3;
  • сверены SHA каждого раунда с git log по docs/specs/399-backend-gate- honesty.md и по docs/reviews/SPEC-REVIEW-399-r1.md;
  • дельта git diff 6d229c66..bb635298 построчно сверена с находкой r2 — проверено, что новая формулировка п.4 не оставляет читателю законного прочтения «список с ручным обновлением»;
  • независимо перепроверен факт AC5/п.5 на текущем дереве: ls .github/workflows/*.yml | wc -l → 9; git grep -l "pip install" .github/workflows/*.yml → ровно mutation-gate.yml и validate.yml. Совпадает с текстом ТЗ дословно;
  • формат нового мутанта (workflow-scan-hardcodes-the-list, kebab-case, структура записи) сверен с существующими id: в scripts/mutation-gate.mjs — согласуется с уже принятым в репозитории стилем;
  • проверено отсутствие рёбейза: git merge-base origin/dev HEAD совпадает с tip origin/dev (f7fb3369) — делта локальна, полный разбор с нуля не требуется по критериям §2.10.

Находки

Нет. Делта закрывает находку r2 по существу, не вводит новых противоречий между разделами, факты в новом тексте перепроверены и точны.

Что проверено и корректно (в дополнение к унаследованному)

  • П.4 и п.5 плана автотестов теперь непротиворечивы контракту п.(3) и AC5: оба говорят про каталог, оба явно запрещают список для ручного обновления, оба ссылаются на один и тот же синтетический третий workflow.
  • Новый мутант workflow-scan-hardcodes-the-list даёт код-ревью проверяемую точку для отлова именно того отката к списку, который стал возможен между ревизией 2 и 3 (риск, который сама находка r2 и описывала) — то есть закрытие сделано не только словами ТЗ, но и обязательством для реализации.
  • Изменение не трогает трек, скоуп/не-скоуп, риски, критерии приёмки как формулировки (AC5 не редактировался), не переносит вопрос владельцу.
  • Заголовок «Ревизия 3» корректно ссылается на SPEC-REVIEW-399-r2 (тот факт, что физически это docs/reviews/SPEC-REVIEW-399-r1.md, — не ошибка автора, а последствие сбоя предыдущего шага публикации, разобранного выше).

Чего не проверял

  • Сетевое содержимое package_constraints.txt тега 2026.8.3 home-assistant/core (претензия M3) — не относится к этой делте (раздел (1) не менялся), недоступно и в этой среде; будет видно на код-ревью.
  • Объём ruff-долга при исходе (2) для Low «а» — делта его не касается.
  • npm test/npx tsc --noEmit/npm run build — это ревью документа (ТЗ), а не кода; делта правит только docs/specs/399-backend-gate-honesty.md, кода нет вовсе. Дешёвые гейты §2.10 в этом раунде неприменимы буквально (нет предмета для typecheck/test/build), они будут прогнаны на этапе код-ревью, когда появится реализация.
  • Аудит-документ AUDIT-2026-08-31-v1700beta1.md вне репозитория — как и в r1/r2, не найден локально, тело issue самодостаточно.

Вердикт

Зелёный: делта раунда — три места в «Плане автотестов»/«Мутантах», все закрывают находку r2 по существу (проверено построчно, не на слово автора), новых расхождений между разделами ТЗ не введено, факты (9 workflow, 2 ставят python-зависимости) перепроверены и точны. Блокирующих находок нет — High: 0, Medium: 0. Зелёный вердикт цикла не образует и бюджет не тратит (#227): израсходовано 2/4 (r1, r2), после этого раунда — по-прежнему 2/4. Задача может двигаться дальше по конвейеру (S5-ready/реализация) без ещё одного цикла ревью ТЗ.