Files
houseplan-card/docs/reviews/SPEC-REVIEW-421-r2.md
T
2026-09-02 17:08:26 +00:00

12 KiB
Raw Blame History

SPEC-REVIEW-421-r2

  • Issue: https://github.com/Matysh/houseplan-card/issues/421
  • Этап: S4-spec-review (ревью ТЗ, PROCESS.md §2.4)
  • Материал: docs/specs/421-negative-test-proofs.md на коммите fac1f884 (ветка origin/issue/421-negative-test-proofs).
  • Заход: r2. Разбор — по дельте (PROCESS.md §2.9, issue #214): предыдущая находка была текстовой (отсутствие разделов §7.1), правка — тоже текстовая, AC и Контракт не менялись.

Скоуп раунда

r1 (SHA c409ec6a, документ docs/reviews/SPEC-REVIEW-421-r1.md) дал жёлтый вердикт с единственной находкой Medium в скоупе: в ТЗ отсутствовали обязательные по §7.1 разделы «Сценарий», «Что человек увидит до и после», «UX»; «Модель данных и миграция» была не выделена отдельным заголовком. Автор («ТЗ обновлено после ревью r1», 2026-09-02T17:04:15Z) заявил правку без изменения AC и технического контракта, коммит fac1f884.

Дельта этого раунда — git diff c409ec6a..fac1f884 -- docs/specs/421-negative-test-proofs.md: четыре добавленных раздела («Сценарий», «Что человек увидит до и после», «UX», «Модель данных и миграция»), вставленных в существующие места документа. Ни одна строка «Контракт», «Критерии приёмки», «Скоуп/Не-скоуп» или «План отрицательной проверки» не тронута — подтверждено самим diff (hunks затрагивают только окрестности вставок, существующие разделы видны в контексте без изменений).

Дельта локальна: новая подсистема не затронута, поведенческий контракт не менялся, объём правки (4 коротких раздела) несопоставим с объёмом исходной задачи. Полный разбор ТЗ заново не требуется — переразбирается только закрытие находки r1 и факт-чек нового текста.

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

  1. Получен вердикт r1 и его SHA — из комментария в issue (короткий вердикт SHA не называет — сверено с полным документом docs/reviews/SPEC-REVIEW-421-r1.md, где раздел «Материал раунда» прямо называет c409ec6a; расхождения между коротким комментарием и документом нет, просто короткий комментарий не обязан дублировать SHA).
  2. git diff c409ec6a..fac1f884 -- docs/specs/421-negative-test-proofs.md — построчный разбор дельты (см. «Закрытие раунда r1» ниже).
  3. Прочитан ТЗ целиком на текущем SHA fac1f884, чтобы убедиться, что новые разделы синтаксически и по смыслу встали на место, названное r1 (не просто заголовки-заглушки).
  4. Факт-чек нового текста против кода, а не только против issue: раздел «Модель данных и миграция» утверждает, что поле lastWriteWasFingerprintOnly уже действует в проде — проверено чтением scripts/docs-accept.mjs:157 ({ ...(previous || {}), lastWriteWasFingerprintOnly: true }), утверждение точное, это не новая догадка, выданная за факт.
  5. Проверено, что новый текст не вводит утверждений о поведении, не зафиксированных ни в одном документе и не помеченных как предположение — не найдено; все новые фразы — перефразировка уже существующих разделов («Проблема», «Контракт», «Не-скоуп») под нужным заголовком.

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

Находка r1 Чем закрыта Где это видно
Medium: нет раздела «Сценарий» Добавлен раздел «Сценарий» — явно называет наблюдателя (разработчик, меняющий одну из трёх подсистем) и момент наблюдения (запуск объявленной проверки) docs/specs/421-negative-test-proofs.md:9-18
Medium: нет раздела «Что человек увидит до и после» Добавлен раздел с явными «До:» / «После:», отвечающий, что видимого продуктового различия нет, эффект косвенный (регрессии ловятся до релиза) docs/specs/421-negative-test-proofs.md:20-29
Medium: нет раздела «UX» Добавлен раздел «UX», явно перечисляющий отсутствие новых экранов/сообщений/настроек и то, что desktop/touch/kiosk/ARIA не затронуты docs/specs/421-negative-test-proofs.md:87-92
Medium: «Модель данных и миграция» не выделена отдельно Добавлен отдельный раздел с этим заголовком, называющий единственный затронутый артефакт (docs/images/screenshots.json.acceptance) и что миграция не нужна docs/specs/421-negative-test-proofs.md:186-196

Все четыре пункта одной находки закрыты именно так, как их описал r1 в «Что чинит находку» (сценарий = разработчик, UX = «нет UI-поверхности», данные = поле lastWriteWasFingerprintOnly) — правка не подменяет замечание формальными заголовками без содержания.

Унаследовано из r1

Без повторной проверки в этом раунде, так как дельта их не касается: документ docs/reviews/SPEC-REVIEW-421-r1.md, SHA c409ec6a.

  • Фактическая точность описания трёх разрывов доказательности (idempotent discard в websocket_api.py:2242-2247; раздельные roundTripLivePages() в reportPageErrors()/finish(), demo/serve.mjs:98-99 vs 108-113; инлайновая сборка acceptance в docs-accept.mjs:150-159 на момент r1) — подтверждена чтением production-кода в r1, дельта эти файлы не трогает.
  • Однозначность и доказуемость AC1–AC9 — контракт и AC не менялись.
  • Реализуемость плана на существующей инфраструктуре (backend-test-guard.mjs, demo/guard/, параметризуемый _prune_support_previews(rt, now)) — код инфраструктуры дельтой не затронут.
  • Корректность «Скоуп»/«Не-скоуп», «Риски», «План отрицательной проверки», «Откат», «Release-артефакты» — не менялись.
  • Снятый в r1 Low (формулировка каденции browser-пробы в «Производительность») — раздел «Производительность» не менялся, решение остаётся в силе.
  • Выбор полного трека вместо small (обоснование «нарушен критерий одной поверхности») — не пересматривался, не затронут дельтой.

Находки

Нет. Дельта закрывает единственную находку r1 без побочных эффектов; новых разрывов доказательности, недоказанных допущений или продуктовых вопросов не внесено.

Что проверено и корректно

  • Все четыре добавленных раздела стоят под требуемыми §7.1 заголовками и содержат конкретный ответ, а не общую фразу без содержания.
  • Новый текст не расширяет и не сужает ни один AC, не меняет «Контракт», «Скоуп»/«Не-скоуп» — сверено построчно по diff.
  • Утверждение о поле lastWriteWasFingerprintOnly как об уже действующем — фактически верно (подтверждено чтением кода, не только текста ТЗ).
  • ТЗ на этом SHA закрывает все обязательные разделы DoR §2.5, применимые к этапу spec-review: AC пронумерованы и у каждого назван способ доказательства, файлы перечислены, i18n/миграция/touch/производительность/откат/ release-артефакты названы явно (в т.ч. явным «нет» там, где нет эффекта), открытых продуктовых вопросов не осталось.

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

  • Гейты typecheck/npm test/npm run build — неприменимо, как и в r1: на этом SHA есть только текст ТЗ, реализации ещё нет; это предмет код-ревью следующего этапа.
  • Повторное чтение custom_components/houseplan/websocket_api.py, demo/serve.mjs, scripts/docs-accept.mjs, scripts/mutation-gate.mjs — не требовалось: дельта r1→r2 не касается технического контракта, эти файлы и их сверка с ТЗ унаследованы из r1 (см. выше).
  • docs/SCOPE.md-обоснование задачи как техдолга без прямой строки Core user jobs — не пересматривалось повторно; framing принят в r1 неявно (не вызвал находки) и не является предметом правки этого раунда.

Материал раунда

  • Ветка: origin/issue/421-negative-test-proofs
  • SHA: fac1f884
  • Дельта: git diff c409ec6a..fac1f884 -- docs/specs/421-negative-test-proofs.md
  • Предыдущий раунд: docs/reviews/SPEC-REVIEW-421-r1.md, SHA c409ec6a

Вердикт

Зелёный. Единственная находка r1 закрыта точно так, как была описана «что чинит находку»; новых находок дельта не создала. ТЗ готово к разработке.


Материал раунда

  • Ветка: issue/421-negative-test-proofs, коммит fac1f8840ed1 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: b8775ea49c4263aeafdea84e92dfcc523a3d059c
    git log --all --format='%H %T' | grep b8775ea49c42
    
  • ТЗ docs/specs/421-negative-test-proofs.md, блоб 41cd21d1f105502a9c9a7464af0d4b199ae322c9
    git log --all --find-object=41cd21d1f105502a9c9a7464af0d4b199ae322c9 -- docs/specs/421-negative-test-proofs.md