Files
houseplan-card/docs/reviews/SPEC-REVIEW-331-r3.md
T
2026-08-28 01:33:02 +00:00

128 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPEC-REVIEW-331-r3
Issue: #331 — «Ограничения стыков (#329): пограничная точность даёт ложные
отказы и невидимые дубли»
ТЗ: `docs/specs/331-junction-limit-precision.md`
Материал раунда: ревизия 3, SHA `4423d285` (issue-комментарий автора
называет этот SHA явно: «Ревизия 3 (`4423d285`)»).
Предыдущий раунд: r2, вердикт «жёлтый», документ
`docs/reviews/SPEC-REVIEW-331-r2.md`, материал на SHA `2d703543`.
Трек: полный (не `small`) — issue не помечен `small` (метки: `bug`, `P1`,
`S4-spec-review`), ТЗ по-прежнему живёт в `docs/specs/331-*.md`; дифф
r2→r3 трек не меняет.
Заход: r3 · блокирующих циклов израсходовано 2 из 4 (r2 жёлтый цикл
израсходовал 2-й; зелёный вердикт бюджет не тратит и цикла не образует —
см. системную инструкцию по #227).
## Скоуп разбора (дельта, не заново)
Дельта раунда — `git diff 2d703543..4423d285 -- docs/specs/331-junction-limit-precision.md`.
Затронуто три места: статус-строка (сводка ревизии), AC6 (`§4`), формулировка
риска (2) в `§6`. Обе находки r2 (M-r2-1, L2) — предмет этой правки, других
разделов дифф не касается. Это ровно тот случай, когда объём разбора
сокращается до дельты: изменение локально (два абзаца), не меняет трек,
не задевает новую подсистему, не является ребейзом. Полный повторный разбор
не требуется; но каждая из двух правок проверена по существу — совпадает ли
новый текст с тем, что r2 явно потребовал, и не рвёт ли он согласованность
с остальным документом (§2.5, §2.6, AC5).
## Как проверялось
1. `git diff 2d703543..4423d285 -- docs/specs/331-junction-limit-precision.md`
— построчно.
2. Текст находки M-r2-1 (`docs/reviews/SPEC-REVIEW-331-r2.md:78-108`) —
сверен пункт за пунктом с новым текстом AC6 (`docs/specs/331-junction-limit-precision.md:144-150`):
ожидались два явных случая по образцу AC5, требование выполнено дословно.
3. Текст находки L2 (`SPEC-REVIEW-331-r2.md:112-125`) — сверен с новой
формулировкой риска (2) (`:170-171`): «максимальная ветвь» → «сумма
коллинеарной компоненты», совпадает буквально с текстом §2.3 (`:76-78`,
не тронут этим диффом).
4. Перечитан §2.5 (`:88-94`) и §2.6 (`:96-105`) — не тронуты диффом r2→r3 —
чтобы убедиться, что новый текст AC6 не противоречит нормативному
тексту, который он тестирует: candidate → «честная ошибка WS,
fail-closed, как §2.5»; previous → «прежний широкий фолбэк "нет базы
для наследования"». Формулировка AC6 (а)/(б) слово в слово повторяет
эту асимметрию.
5. Перечитан AC5 (`:141-143`, не тронут) — «по образцу AC5» из статус-строки
и текста AC6 действительно означает структурное подобие: два явных
случая по сторонам с разным исходом, как у AC5 (кандидат/baseline).
6. Прочитан полный файл `docs/specs/331-junction-limit-precision.md`
целиком (не только дельту) — на предмет новых внутренних противоречий,
которые правка могла случайно внести в соседние разделы (§3, §5, §6
целиком). Противоречий не найдено.
7. Issue #331 — комментарии перечитаны (`gh issue view 331 --json comments`):
вердикт r2 (жёлтый, M-r2-1 + L2) и хендофф автора о ревизии 3 — оба
совпадают с тем, что видно в диффе; SHA назван автором явно.
Гейты `typecheck`/`test`/`build`/`check-docs`/инварианты модели/смоки/
golden/backend-pytest/perf — не гонялись и не нужны: дифф раунда —
исключительно `docs/specs/331-*.md` (класс C, стадия `spec`), исполняемого
кода нет ни в этом диффе, ни накопительно с r1 (весь путь #331 пока —
только спецификация).
## Закрытие раунда r2
| Находка r2 | Чем закрыта в r3 | Где это видно |
|---|---|---|
| **M-r2-1** — AC6 не различал сторону (`previous`/`candidate`); реализация с перепутанной или отсутствующей асимметрией §2.6 формально проходила байт-в-байт тот же текст, что был до правки §2.6 | AC6 переписан на два явных случая по образцу AC5: (а) TypeError кандидата → честная ошибка WS; (б) TypeError previous → запись проходит фолбэком «нет базы для наследования»; отдельно оговорено, что перепутанные стороны или отсутствие асимметрии красят хотя бы один из двух юнитов | `docs/specs/331-junction-limit-precision.md:144-150`. Текст (а)/(б) сверен слово в слово с нормативным §2.6 (`:100-105`, не тронут этим диффом) — не расходится и не изобретает нового поведения. Критерий теперь однозначно различает две реализации, которые старый AC6 не различал. **Закрыто.** |
| **L2** — §6 «Риски» (2) описывал механизм «максимальная ветвь», которого §2.3 в редакции r2 уже не содержит (там — «сумма компоненты связности») | Формулировка риска (2) заменена на «сумма коллинеарной компоненты» | `:170-171`. Совпадает буквально с текстом §2.3 (`:76-78`). Рассинхрон между разделами устранён. **Закрыто.** |
Обе находки r2 закрыты содержательными правками текста, а не декларацией
в статус-строке (хотя статус-строка тоже обновлена корректно — `:3`
перечисляет обе находки r2 и подтверждается фактическим диффом).
## Унаследовано из r2 (без повторной проверки)
Ниже — то, что r2 (`docs/reviews/SPEC-REVIEW-331-r2.md`, материал @
`2d703543`) проверил и признал корректным, и что дельта r2→r3 не
затрагивает (ни один символ в этих разделах не изменился между
`2d703543` и `4423d285`):
- H1 (квантование ключа, формула канонизации) — сверено побайтово с
`coordinate-canonicalization.ts/.py` в r2; §2.1/AC1 не тронуты этим
диффом.
- M1 (порог инцидентности 2e-7, арифметика примера) — §2.1/AC1 не тронуты.
- M3 (обход по рёбрам вместо DFS, O(E), развилка и П1) — §2.3/AC3 не
тронуты; вывод r2, что любая «развилка» и так нарушает П1 по углу
независимо от версии §2.3, наследуется без повторной проверки кода.
- M4 (USER-GUIDE в Release) — §6/Release не тронут этим диффом (правка
риска (2) — другая строка того же раздела, не пересекается с абзацем
Release).
- Нормативный текст §2.6 (сама асимметрия candidate/previous) — введён и
проверен в r2, этим диффом не тронут; проверялся сейчас только для
сверки с новым AC6 (см. «Как проверялось», п.4), не как повторный аудит
§2.6 с нуля.
- Скоуп/не-скоуп, структура «один AC на пункт», i18n, touch, обязательство
по `docs/specs/329-*.md` — унаследовано ещё из r1 через r2, дельтой r3
не задето.
## Что проверено и признано корректным (эта ревизия)
- AC6 в новой редакции действительно способен различить две реализации,
которые старая редакция не различала: пропущена или перепутана
асимметрия candidate/previous — хотя бы один из двух явно описанных
юнитов красный.
- Новый текст AC6 не вводит поведения, которого нет в нормативном §2.6 —
сверено дословно.
- Формулировка риска (2) в §6 синхронизирована с текущим текстом §2.3.
- Полный документ (не только дельта) перечитан на предмет новых
противоречий — не найдено.
## Чего не проверял
- Всё, что унаследовано из r2/r1 (список выше) — не перепроверялось
повторно.
- Исполняемого кода по-прежнему нет — гейты typecheck/test/build/
check-docs/инварианты/смоки/golden/backend-pytest/perf не применимы
к этой стадии (`spec`) и не гонялись.
- Фактическая реализация AC6 — она ещё не написана; проверялась только
формулировка критерия, а не код, который по нему будет писаться.
## Вердикт
Обе находки r2 (M-r2-1, L2) закрыты содержательными правками, сверенными
построчно с текстом находок и с остальным документом. Новых находок в
дельте r2→r3 нет. High нет, Medium нет.
`Вердикт: зелёный · заход r3 · блокирующих циклов 2/4 · High: 0 · Medium: 0`