mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
fix(tools): архив переписывает относительные ссылки перенесённых документов (#682)
Ревью #682 r1, Medium: перенос добавляет документу уровень вложенности (`docs/reviews/X.md` → `legacy/reviews/<тег>/X.md`, `docs/specs/` → `legacy/specs/`), а относительные ссылки внутри перенесённых документов и в соседях, ссылавшихся на них, никто не пересчитывал — на `97d19268` 53 битые ссылки в 46 файлах (заявление «все 26 резолвятся» в `7feb6177` было верно только до переноса документов ревью). Гейты архив не смотрят. `reviews-archive.mjs`: `repairLinks` пересчитывает ссылку, если она не резолвится от нового места, а цель находится от нового или старого места через карту переносов; битая и до переноса ссылка не трогается. `--apply` делает это само, `--repair-links=<rev>` — для всех переименований `<rev>..HEAD`, `--check-links` печатает битые. Этим коммитом `--repair-links=origin/dev` переписал ровно 53 ссылки в 46 файлах; остались две прежние «...»-заглушки в CODE-REVIEW-448-r2 (битые и на dev). Тесты: перенесённый документ, сосед со ссылкой в архив, ТЗ со ссылкой на позже перенесённое ревью, битая-до-переноса не трогается, в `legacy/` битых нет; мутант `reviews-archive-links-from-new-place-only`. PROCESS §2.10 и DEVELOPMENT › Release называют переписывание и `--check-links`. Issue: #682 User-Visible: no Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
This commit is contained in:
@@ -408,6 +408,9 @@ dev, ни при публикации документа код-ревью: ин
|
||||
в последнюю; закрытая без выпуска (как #522) уезжает с линией, где лёг её
|
||||
документ — коммит документа несёт трейлер; `RELEASE-REVIEW-vX.Y.Z.md` уходит в
|
||||
каталог своего тега, поэтому перенос делается после публикации ревью линии.
|
||||
Относительные ссылки в перенесённых документах и в соседях, которые на них
|
||||
ссылаются, инструмент переписывает сам; `--check-links` печатает оставшиеся
|
||||
битые.
|
||||
Перенос идёт при пустой очереди `S7-code-review`: ребейз чужой ветки иначе
|
||||
упрётся в перемещённый каталог.
|
||||
|
||||
|
||||
+3
-2
@@ -648,8 +648,9 @@ and what HACS downloads.
|
||||
(`RELEASE-REVIEW-vX.Y.Z.md`) is in `dev` and the `S7-code-review` queue is
|
||||
empty, archive the line's review documents (`PROCESS.md` §2.10):
|
||||
`node scripts/reviews-archive.mjs --through=vX.Y.Z` prints the plan,
|
||||
`--apply` moves the files into `legacy/reviews/vX.Y.Z/` with `git mv` and
|
||||
rebuilds `docs/reviews/INDEX.md`; commit the result as one class C commit
|
||||
`--apply` moves the files into `legacy/reviews/vX.Y.Z/` with `git mv`, rewrites
|
||||
the relative Markdown links in and to the moved documents and rebuilds
|
||||
`docs/reviews/INDEX.md` (`--check-links` lists what is still broken); commit the result as one class C commit
|
||||
whose `Issue:` trailer names the issue doing the move or the repository-hygiene
|
||||
umbrella (`PROCESS.md` §11.3).
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ H=0, M=0, «Находки: —» — как будто находок не бы
|
||||
строку 14, а не 106. Индекс:
|
||||
|
||||
```
|
||||
| #594 | [CODE-REVIEW-594-r1.md](CODE-REVIEW-594-r1.md) | code · r1 | 🟡 жёлтый | 0 | 0 | — |
|
||||
| #594 | [CODE-REVIEW-594-r1.md](../../legacy/reviews/v1.77.0/CODE-REVIEW-594-r1.md) | code · r1 | 🟡 жёлтый | 0 | 0 | — |
|
||||
```
|
||||
|
||||
Реально в этом документе 3 Medium (M1 приёмка эталонов, M2 отпечаток
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- Этап: `code` (PROCESS.md §2.7)
|
||||
- Диапазон: `origin/dev...HEAD`, `origin/dev` = `22e98c5`, `HEAD` = `6ea3ebf`
|
||||
(ветка `issue/89-isometric-stage1`, детач `HEAD`)
|
||||
- ТЗ: [`docs/specs/089-isometric-view-stage1.md`](../specs/089-isometric-view-stage1.md),
|
||||
- ТЗ: [`docs/specs/089-isometric-view-stage1.md`](../../../docs/specs/089-isometric-view-stage1.md),
|
||||
ревизия 3, ревью ТЗ зелёное — [`SPEC-REVIEW-89-r1.md`](SPEC-REVIEW-89-r1.md)
|
||||
- Цикл: **r2/4**
|
||||
- Вердикт: **красный**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
- Диапазон: `origin/dev...HEAD`, `origin/dev` = `869fe16`, `HEAD` = `7a2577d`
|
||||
(ветка `issue/89-isometric-stage1`, детач `HEAD`); мёрж-база с `origin/dev` —
|
||||
`9f02d88`
|
||||
- ТЗ: [`docs/specs/089-isometric-view-stage1.md`](../specs/089-isometric-view-stage1.md),
|
||||
- ТЗ: [`docs/specs/089-isometric-view-stage1.md`](../../../docs/specs/089-isometric-view-stage1.md),
|
||||
ревизия 3, ревью ТЗ зелёное — [`SPEC-REVIEW-89-r1.md`](SPEC-REVIEW-89-r1.md)
|
||||
- Предыдущий цикл код-ревью: [`CODE-REVIEW-89-r2.md`](CODE-REVIEW-89-r2.md)
|
||||
(красный, High H1 — обязательный смок красный на исполнении)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
- Issue: [#89](https://github.com/Matysh/houseplan-card/issues/89)
|
||||
- Этап: `spec` (PROCESS.md §2.4)
|
||||
- ТЗ под ревью: [`docs/specs/089-isometric-view-stage1.md`](../specs/089-isometric-view-stage1.md), ревизия 3
|
||||
- ТЗ под ревью: [`docs/specs/089-isometric-view-stage1.md`](../../../docs/specs/089-isometric-view-stage1.md), ревизия 3
|
||||
- Диапазон: `origin/dev...74b08df` (ветка `issue/89-isometric-stage1`, детач `HEAD`)
|
||||
- Цикл: **r1/4** (первый независимый ревью-артефакт этой задачи в `docs/reviews/`;
|
||||
«историческое ревью ревизии 1», упомянутое в теле issue и в самом ТЗ, честно
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Код-ревью issue #107 — переключение виртуального источника света «Всегда» (r1)
|
||||
|
||||
- **Issue:** https://github.com/Matysh/houseplan-card/issues/107
|
||||
- **ТЗ:** [`docs/specs/107-virtual-light-toggle.md`](../specs/107-virtual-light-toggle.md), ревью
|
||||
- **ТЗ:** [`docs/specs/107-virtual-light-toggle.md`](../../specs/107-virtual-light-toggle.md), ревью
|
||||
[`SPEC-REVIEW-107-r1.md`](SPEC-REVIEW-107-r1.md) — зелёное, High 0 / Medium 0.
|
||||
- **Диапазон:** `origin/dev...HEAD`, коммит `1079cdfab25617df924b8c3592631aa40e078d87`
|
||||
("feat: add persistent virtual light toggles"), ветка `issue/107-virtual-light-toggle`.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Ветка: `issue/141-wall-joints` · implementation-коммит
|
||||
[`3e33f4a`](https://github.com/Matysh/houseplan-card/commit/3e33f4a5845a29694473697bea916bb3e2490ac2)
|
||||
· ТЗ: [`docs/specs/141-wall-junctions.md`](../specs/141-wall-junctions.md)
|
||||
· ТЗ: [`docs/specs/141-wall-junctions.md`](../../../docs/specs/141-wall-junctions.md)
|
||||
(reviewed `2858175`, зелёный SPEC-REVIEW-141-r1).
|
||||
|
||||
## Скоуп проверки
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Ветка: `issue/146-four-phase-sun-background` · implementation-коммит
|
||||
[`debb13b`](https://github.com/Matysh/houseplan-card/commit/debb13baa280042c79a004c97152e3b1be5ab11b)
|
||||
· ТЗ: [`docs/specs/146-four-phase-sun-background.md`](../specs/146-four-phase-sun-background.md)
|
||||
· ТЗ: [`docs/specs/146-four-phase-sun-background.md`](../../../docs/specs/146-four-phase-sun-background.md)
|
||||
(зелёный [`SPEC-REVIEW-146-r1`](SPEC-REVIEW-146-r1.md), High:0, Medium:1 → #147,
|
||||
не блокирует).
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Ветка: `issue/150-wall-thickness-transition-fix` · implementation-коммит
|
||||
[`1975d1a`](https://github.com/Matysh/houseplan-card/commit/1975d1ae3784a0b98cf2f489910370f37417a1c6)
|
||||
на базе `origin/dev` (`a05aa5d`) · ТЗ:
|
||||
[`docs/specs/150-wall-thickness-transition.md`](../specs/150-wall-thickness-transition.md)
|
||||
[`docs/specs/150-wall-thickness-transition.md`](../../specs/150-wall-thickness-transition.md)
|
||||
(r2, зелёный `SPEC-REVIEW-150-r2`, High: 0 · Medium: 1 → #171, комментарий issue
|
||||
от 2026-08-18T08:40:34Z).
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
- Диапазон: `git log --oneline origin/dev..HEAD` = `0df8051` (реализация),
|
||||
`8c9241b` (ревью ТЗ r1), `9d6cd8b` (ТЗ)
|
||||
- Диапазон диффа: `git diff origin/dev...HEAD`
|
||||
- ТЗ: [`docs/specs/198-optimize-micro-interval.md`](../specs/198-optimize-micro-interval.md)
|
||||
- ТЗ: [`docs/specs/198-optimize-micro-interval.md`](../../specs/198-optimize-micro-interval.md)
|
||||
(ревью ТЗ зелёное, r1)
|
||||
|
||||
## Скоуп
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
`1c9575a` (follow-up тесты на замечания r1), `0625b6f` (обновление
|
||||
provenance скриншотов после изменения `src/`)
|
||||
- Диапазон диффа: `git diff origin/dev...HEAD`
|
||||
- ТЗ: [`docs/specs/198-optimize-micro-interval.md`](../specs/198-optimize-micro-interval.md)
|
||||
- ТЗ: [`docs/specs/198-optimize-micro-interval.md`](../../specs/198-optimize-micro-interval.md)
|
||||
(ревью ТЗ зелёное, r1)
|
||||
- Предыдущий цикл: [`docs/reviews/CODE-REVIEW-198-r1.md`](CODE-REVIEW-198-r1.md)
|
||||
(жёлтый · Medium-1 AC5, Medium-2 AC8 — обе «доказательство обещанным
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
r2), `5ce3cee` (исправление находки r2 — изоляция AC5-фикстуры), `2d5fec0`
|
||||
(обновление screenshot provenance после технического ребейза)
|
||||
- Диапазон диффа: `git diff origin/dev...HEAD`
|
||||
- ТЗ: [`docs/specs/198-optimize-micro-interval.md`](../specs/198-optimize-micro-interval.md)
|
||||
- ТЗ: [`docs/specs/198-optimize-micro-interval.md`](../../specs/198-optimize-micro-interval.md)
|
||||
(ревью ТЗ зелёное, r1)
|
||||
- Предыдущий цикл: [`docs/reviews/CODE-REVIEW-198-r2.md`](CODE-REVIEW-198-r2.md)
|
||||
(жёлтый · Medium-1 — новый AC5-тест не хермитичен к сценарию входной
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Код-ревью issue #200 — r1
|
||||
|
||||
- Issue: [#200](https://github.com/Matysh/houseplan-card/issues/200)
|
||||
- ТЗ: [docs/specs/200-room-label-parity.md](../specs/200-room-label-parity.md)
|
||||
- ТЗ: [docs/specs/200-room-label-parity.md](../../specs/200-room-label-parity.md)
|
||||
- ТЗ-ревью: [SPEC-REVIEW-200-r1.md](SPEC-REVIEW-200-r1.md) — зелёный
|
||||
- Диапазон: `origin/dev..HEAD` (детач на `origin/issue/200-room-label-parity`),
|
||||
коммиты `4089c91`, `bf83246`, `cd029a0`, `88a2877`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Код-ревью #201 — r1
|
||||
|
||||
- Issue: [#201](https://github.com/Matysh/houseplan-card/issues/201)
|
||||
- ТЗ: [docs/specs/201-atomic-thickness-lookup.md](../specs/201-atomic-thickness-lookup.md)
|
||||
- ТЗ: [docs/specs/201-atomic-thickness-lookup.md](../../specs/201-atomic-thickness-lookup.md)
|
||||
(ревью ТЗ зелёное: [SPEC-REVIEW-201-r1.md](SPEC-REVIEW-201-r1.md))
|
||||
- Диапазон: `git log --oneline origin/dev..HEAD`
|
||||
- `f7abf14` fix: inherit parent thickness for atomic walls (`Issue: #201`, `User-Visible: yes`)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
`1290927 fix: hide disabled room names` (`Issue: #203`, `User-Visible: yes`),
|
||||
плюс два уже смёрженных документа ревью ТЗ (`84e62dc`, `950403d`,
|
||||
`f7b811a`, `009fed9`) — без продуктового кода.
|
||||
- ТЗ: [`docs/specs/203-hide-room-names.md`](../specs/203-hide-room-names.md),
|
||||
- ТЗ: [`docs/specs/203-hide-room-names.md`](../../specs/203-hide-room-names.md),
|
||||
ревью ТЗ зелёное на r2: [`SPEC-REVIEW-203-r2.md`](SPEC-REVIEW-203-r2.md).
|
||||
- Issue: [#203](https://github.com/Matysh/houseplan-card/issues/203)
|
||||
- Ревьюер: Claude (роль «ревьюер кода»), свежая сессия без контекста реализации.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# CODE-REVIEW-204-r1
|
||||
|
||||
- Issue: [#204](https://github.com/Matysh/houseplan-card/issues/204)
|
||||
- ТЗ: [docs/specs/204-space-create-display-defaults.md](../specs/204-space-create-display-defaults.md)
|
||||
- ТЗ: [docs/specs/204-space-create-display-defaults.md](../../specs/204-space-create-display-defaults.md)
|
||||
- Ветка: `issue/204-space-create-display-defaults`, коммит `12c4f77`
|
||||
- Диапазон: `origin/dev..HEAD` = `f703242` (spec) → `ec0ccaf` (spec review doc) → `12c4f77` (реализация)
|
||||
- Вердикт: **зелёный**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- Этап: `code` (PROCESS.md §2.7)
|
||||
- Диапазон: `origin/dev...HEAD`, `origin/dev` = `ad8e7a5`, `HEAD` = `11b0283`
|
||||
(ветка `issue/205-vacuum-trail-grace`, detached `HEAD`); merge-base — `f287bdd`
|
||||
- ТЗ: [`docs/specs/205-vacuum-trail-resume-grace.md`](../specs/205-vacuum-trail-resume-grace.md),
|
||||
- ТЗ: [`docs/specs/205-vacuum-trail-resume-grace.md`](../../specs/205-vacuum-trail-resume-grace.md),
|
||||
ревью ТЗ зелёное — [`SPEC-REVIEW-205-r1.md`](SPEC-REVIEW-205-r1.md)
|
||||
- Цикл: **r1/4**
|
||||
- Ревьюер: Claude, свежая сессия, без переписки с автором реализации
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
- Диапазон: `origin/dev...HEAD`, `origin/dev` = `5dc9016` («docs: review document
|
||||
for #204»), `HEAD` = `e158f8f` (ветка `issue/205-vacuum-trail-grace`, detached
|
||||
`HEAD`); merge-base — `5dc9016`
|
||||
- ТЗ: [`docs/specs/205-vacuum-trail-resume-grace.md`](../specs/205-vacuum-trail-resume-grace.md),
|
||||
- ТЗ: [`docs/specs/205-vacuum-trail-resume-grace.md`](../../specs/205-vacuum-trail-resume-grace.md),
|
||||
ревью ТЗ зелёное — [`SPEC-REVIEW-205-r1.md`](SPEC-REVIEW-205-r1.md)
|
||||
- Предыдущий цикл: [`CODE-REVIEW-205-r1.md`](CODE-REVIEW-205-r1.md) —
|
||||
**зелёный**, High: 0, Medium: 0; вернулся не по замечаниям, а из-за конфликта
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPEC-REVIEW-174-r1
|
||||
|
||||
- **Issue:** https://github.com/Matysh/houseplan-card/issues/174
|
||||
- **ТЗ:** [`docs/specs/174-linked-virtual-light-controller.md`](../specs/174-linked-virtual-light-controller.md)
|
||||
- **ТЗ:** [`docs/specs/174-linked-virtual-light-controller.md`](../../specs/174-linked-virtual-light-controller.md)
|
||||
(commit `4a8958291d28fbd86d0233e6ac9208b068b24f76`, ветка `issue/174-linked-virtual-light`)
|
||||
- **Ревьюер:** Claude (ревью ТЗ ≠ автор), этап `S4-spec-review`
|
||||
- **Цикл:** r1/4 (обычный трек — issue не `small`/`trivial`, что подтверждено
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPEC-REVIEW-178-r1
|
||||
|
||||
- **Issue:** https://github.com/Matysh/houseplan-card/issues/178
|
||||
- **ТЗ:** [`docs/specs/178-toggle-entity.md`](../specs/178-toggle-entity.md)
|
||||
- **ТЗ:** [`docs/specs/178-toggle-entity.md`](../../specs/178-toggle-entity.md)
|
||||
(commit `e46ef6f55c44ec1f05268cdff4ceeb4dcc5af116`, ветка `issue/178-toggle-entity`)
|
||||
- **Ревьюер:** Claude (ревью ТЗ ≠ автор), этап `S4-spec-review`
|
||||
- **Цикл:** r1/4 (обычный трек — issue не `small`/`trivial`, подтверждено
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPEC-REVIEW-178-r2
|
||||
|
||||
- **Issue:** https://github.com/Matysh/houseplan-card/issues/178
|
||||
- **ТЗ:** [`docs/specs/178-toggle-entity.md`](../specs/178-toggle-entity.md)
|
||||
- **ТЗ:** [`docs/specs/178-toggle-entity.md`](../../specs/178-toggle-entity.md)
|
||||
(commit `76f75f85aafabcf9f698c85de0185e2ee64a98b5`, ветка `issue/178-toggle-entity`)
|
||||
- **Ревьюер:** Claude (ревью ТЗ ≠ автор), этап `S4-spec-review`, сессия без
|
||||
контекста написания ТЗ и без контекста r1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Ревью ТЗ — issue #198, цикл r1
|
||||
|
||||
- Этап: `S4-spec-review` (PROCESS.md §2.4)
|
||||
- Артефакт ТЗ: [`docs/specs/198-optimize-micro-interval.md`](../specs/198-optimize-micro-interval.md),
|
||||
- Артефакт ТЗ: [`docs/specs/198-optimize-micro-interval.md`](../../specs/198-optimize-micro-interval.md),
|
||||
коммит `9d6cd8b` на ветке `issue/198-optimize-micro-interval`
|
||||
- Issue: [#198](https://github.com/Matysh/houseplan-card/issues/198)
|
||||
- Ревьюер: Claude (роль «ревьюер ТЗ», отдельная сессия от аналитика/автора)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Ревью ТЗ — issue #200, цикл r1
|
||||
|
||||
- Этап: `S4-spec-review` (PROCESS.md §2.4)
|
||||
- Артефакт ТЗ: [`docs/specs/200-room-label-parity.md`](../specs/200-room-label-parity.md),
|
||||
- Артефакт ТЗ: [`docs/specs/200-room-label-parity.md`](../../specs/200-room-label-parity.md),
|
||||
коммит `4089c91` на ветке `issue/200-room-label-parity`
|
||||
- Issue: [#200](https://github.com/Matysh/houseplan-card/issues/200)
|
||||
- Ревьюер: Claude (роль «ревьюер ТЗ», отдельная сессия от аналитика/автора)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Ревью ТЗ — issue #201, цикл r1
|
||||
|
||||
- Этап: `S4-spec-review` (PROCESS.md §2.4)
|
||||
- Артефакт ТЗ: [`docs/specs/201-atomic-thickness-lookup.md`](../specs/201-atomic-thickness-lookup.md),
|
||||
- Артефакт ТЗ: [`docs/specs/201-atomic-thickness-lookup.md`](../../specs/201-atomic-thickness-lookup.md),
|
||||
коммит `7b759f3` на ветке `issue/201-atomic-thickness-lookup`
|
||||
- Issue: [#201](https://github.com/Matysh/houseplan-card/issues/201)
|
||||
- Ревьюер: Claude (роль «ревьюер ТЗ», отдельная сессия от аналитика/автора)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Ревью ТЗ — issue #203, цикл r1
|
||||
|
||||
- Этап: `S4-spec-review` (PROCESS.md §2.4)
|
||||
- Артефакт ТЗ: [`docs/specs/203-hide-room-names.md`](../specs/203-hide-room-names.md),
|
||||
- Артефакт ТЗ: [`docs/specs/203-hide-room-names.md`](../../specs/203-hide-room-names.md),
|
||||
коммит `009fed9` на ветке `issue/203-hide-room-names`
|
||||
- Issue: [#203](https://github.com/Matysh/houseplan-card/issues/203)
|
||||
- Ревьюер: Claude (роль «ревьюер ТЗ», отдельная сессия от аналитика/автора)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Ревью ТЗ — issue #203, цикл r2
|
||||
|
||||
- Этап: `S4-spec-review` (PROCESS.md §2.4)
|
||||
- Артефакт ТЗ: [`docs/specs/203-hide-room-names.md`](../specs/203-hide-room-names.md),
|
||||
- Артефакт ТЗ: [`docs/specs/203-hide-room-names.md`](../../specs/203-hide-room-names.md),
|
||||
правка коммитом `f7b811a` поверх `009fed9` на ветке `issue/203-hide-room-names`
|
||||
- Issue: [#203](https://github.com/Matysh/houseplan-card/issues/203)
|
||||
- Ревьюер: Claude (роль «ревьюер ТЗ»)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPEC-REVIEW-204-r1
|
||||
|
||||
- Issue: [#204](https://github.com/Matysh/houseplan-card/issues/204)
|
||||
- ТЗ: [docs/specs/204-space-create-display-defaults.md](../specs/204-space-create-display-defaults.md)
|
||||
- ТЗ: [docs/specs/204-space-create-display-defaults.md](../../specs/204-space-create-display-defaults.md)
|
||||
- Ветка: `issue/204-space-create-display-defaults`, коммит `f703242`
|
||||
- Трек: обычный (метка `small` не выставлена — файл ТЗ обязателен и присутствует)
|
||||
- Вердикт: **зелёный**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPEC-REVIEW-205-r1
|
||||
|
||||
- Issue: [#205](https://github.com/Matysh/houseplan-card/issues/205) — след пылесоса обнуляется после мойки швабр
|
||||
- ТЗ: [docs/specs/205-vacuum-trail-resume-grace.md](../specs/205-vacuum-trail-resume-grace.md)
|
||||
- ТЗ: [docs/specs/205-vacuum-trail-resume-grace.md](../../specs/205-vacuum-trail-resume-grace.md)
|
||||
- Ветка: `issue/205-vacuum-trail-grace`, коммит спеки: `f3472de` ("docs: specify vacuum trail resume grace")
|
||||
- Этап: ТЗ на ревью (PROCESS.md §2.4)
|
||||
- Цикл: r1/4 (лёгкий трек не применяется — `small` не выставлен, сложность 4, риск 7)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# CODE-REVIEW-218-r1
|
||||
|
||||
- **Issue:** [#218](https://github.com/Matysh/houseplan-card/issues/218) — floating-point шум одной комнаты гасит Glow всего пространства
|
||||
- **ТЗ:** [docs/specs/218-glow-floor-geometry.md](../specs/218-glow-floor-geometry.md), принято на [SPEC-REVIEW-218-r2](SPEC-REVIEW-218-r2.md) (зелёный, r2/2)
|
||||
- **ТЗ:** [docs/specs/218-glow-floor-geometry.md](../../specs/218-glow-floor-geometry.md), принято на [SPEC-REVIEW-218-r2](SPEC-REVIEW-218-r2.md) (зелёный, r2/2)
|
||||
- **Диапазон:** `origin/dev...HEAD`, продуктовый коммит `3d11758` (единственный коммит с изменением кода; `c6ff34c`…`4c512fa` — ТЗ и его ревью)
|
||||
- **Ветка:** `issue/218-glow-floor-geometry`
|
||||
- **Цикл:** r1/4
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Код-ревью #226 — r1
|
||||
|
||||
- Issue: [#226](https://github.com/Matysh/houseplan-card/issues/226)
|
||||
- ТЗ: [`docs/specs/226-entity-parent-dedup.md`](../specs/226-entity-parent-dedup.md)
|
||||
- ТЗ: [`docs/specs/226-entity-parent-dedup.md`](../../specs/226-entity-parent-dedup.md)
|
||||
(зелёное ревью r2: [`SPEC-REVIEW-226-r2.md`](SPEC-REVIEW-226-r2.md))
|
||||
- Ветка: `issue/226-entity-parent-dedup`, коммит реализации `f151e70`
|
||||
- Материал: `git diff origin/dev...HEAD`, `git log --oneline origin/dev..HEAD`
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
`HEAD` = `ee672dcd` (ветка `issue/316-migration-auto-resolve`, ребейз на `dev` выполнен
|
||||
автором до этого ревью — коммент issue от 2026-08-26T19:12:24Z, конфликт был только
|
||||
в `CHANGELOG`)
|
||||
- ТЗ: [`docs/specs/316-opening-host-auto-resolution.md`](../specs/316-opening-host-auto-resolution.md),
|
||||
- ТЗ: [`docs/specs/316-opening-host-auto-resolution.md`](../../specs/316-opening-host-auto-resolution.md),
|
||||
ревизия 4, ревью ТЗ зелёное — [`SPEC-REVIEW-316-r4.md`](SPEC-REVIEW-316-r4.md)
|
||||
- Заход ревью: **r1**, блокирующих циклов код-ревью израсходовано **0/4**
|
||||
- Вердикт: **красный**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
- Issue: [#223](https://github.com/Matysh/houseplan-card/issues/223) «Оптимизировать планы» должна
|
||||
канонизировать координаты, а не консервировать floating-point шум
|
||||
- ТЗ: [`docs/specs/223-optimize-coordinate-canonicalization.md`](../specs/223-optimize-coordinate-canonicalization.md)
|
||||
- ТЗ: [`docs/specs/223-optimize-coordinate-canonicalization.md`](../../specs/223-optimize-coordinate-canonicalization.md)
|
||||
на коммите `3a81dd6223095465f5563cf9cd76cd3ca5355bdb`
|
||||
- Трек: обычный (не `small`) — оценка владельца в аналитике: сложность/риск 4/10, одна общая
|
||||
функция координат + изменения в `AlignReport`/`OptimizeReport` + пользовательский текст + несколько
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
- Issue: [#223](https://github.com/Matysh/houseplan-card/issues/223) «Оптимизировать планы» должна
|
||||
канонизировать координаты, а не консервировать floating-point шум
|
||||
- ТЗ: [`docs/specs/223-optimize-coordinate-canonicalization.md`](../specs/223-optimize-coordinate-canonicalization.md)
|
||||
- ТЗ: [`docs/specs/223-optimize-coordinate-canonicalization.md`](../../specs/223-optimize-coordinate-canonicalization.md)
|
||||
на коммите `965711ee2005b8ec2587b9c70fb9b14735c7756e` (HEAD)
|
||||
- Раунд: r2/4
|
||||
- Вердикт: **жёлтый**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
- Issue: [#223](https://github.com/Matysh/houseplan-card/issues/223) «Оптимизировать планы» должна
|
||||
канонизировать координаты, а не консервировать floating-point шум
|
||||
- ТЗ: [`docs/specs/223-optimize-coordinate-canonicalization.md`](../specs/223-optimize-coordinate-canonicalization.md)
|
||||
- ТЗ: [`docs/specs/223-optimize-coordinate-canonicalization.md`](../../specs/223-optimize-coordinate-canonicalization.md)
|
||||
на коммите `8c9e5feae3503c086cc9f987d57f676e5435e537` (HEAD)
|
||||
- Раунд: r3/4
|
||||
- Вердикт: **зелёный**
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
- **Issue:** [#282 — Геометрия стен: сменить представление, а не чинить последствия](https://github.com/Matysh/houseplan-card/issues/282)
|
||||
- **Этап:** spec (PROCESS.md §2.4)
|
||||
- **Заход:** r1 (первый; дельта-режим §2.10 не применяется)
|
||||
- **Артефакт ТЗ:** [`docs/specs/282-stable-wall-segment-identity.md`](../specs/282-stable-wall-segment-identity.md)
|
||||
- **Артефакт ТЗ:** [`docs/specs/282-stable-wall-segment-identity.md`](../../specs/282-stable-wall-segment-identity.md)
|
||||
- **SHA ТЗ на момент ревью:** `8856fbda` (`docs: specify stable wall segment identity`, единственный коммит в ветке поверх `dev`)
|
||||
- **Нормативный документ:** [`docs/adr/282-wall-geometry-representation.md`](../adr/282-wall-geometry-representation.md), статус: Stage 0 принят и реализован (#283), Stage 1 — предмет этого ТЗ
|
||||
- **Нормативный документ:** [`docs/adr/282-wall-geometry-representation.md`](../../../docs/adr/282-wall-geometry-representation.md), статус: Stage 0 принят и реализован (#283), Stage 1 — предмет этого ТЗ
|
||||
- **Поставляемый этап:** ADR Stage 1 — stored identity сегментов contour walls
|
||||
|
||||
## Скоуп ревью
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
- **Issue:** [#282 — Геометрия стен: сменить представление, а не чинить последствия](https://github.com/Matysh/houseplan-card/issues/282)
|
||||
- **Этап:** spec (PROCESS.md §2.4)
|
||||
- **Заход:** r2 · блокирующих циклов израсходовано 1 из 4 (§2.10, §4: зелёный вердикт r1 не был — r1 был жёлтым и потратил цикл 1; если этот заход зелёный, он сам цикла не образует)
|
||||
- **Артефакт ТЗ:** [`docs/specs/282-stable-wall-segment-identity.md`](../specs/282-stable-wall-segment-identity.md)
|
||||
- **Артефакт ТЗ:** [`docs/specs/282-stable-wall-segment-identity.md`](../../specs/282-stable-wall-segment-identity.md)
|
||||
- **SHA ТЗ на момент этого ревью:** `2f30c481` (`docs: address wall identity spec review`)
|
||||
- **SHA предыдущего ревью (r1):** `8856fbda` (`docs: specify stable wall segment identity`)
|
||||
- **Документ r1:** [`docs/reviews/SPEC-REVIEW-282-r1.md`](./SPEC-REVIEW-282-r1.md), вердикт жёлтый, High: 0, Medium: 2 (обе в скоупе)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Issue: [#359](https://github.com/Matysh/houseplan-card/issues/359) — Предпросмотр мебели на плане перед размещением
|
||||
SHA: `fd762fa7` (`issue/359-furniture-placement-preview`)
|
||||
Предыдущий раунд: [CODE-REVIEW-359-r1](../reviews/CODE-REVIEW-359-r1.md) (в дереве: `docs/reviews/CODE-REVIEW-359-r1.md`) — вердикт красный, SHA `8b66d67d`
|
||||
Предыдущий раунд: [CODE-REVIEW-359-r1](CODE-REVIEW-359-r1.md) (в дереве: `docs/reviews/CODE-REVIEW-359-r1.md`) — вердикт красный, SHA `8b66d67d`
|
||||
Заход: r2 · блокирующих циклов израсходовано 1 из 4 (r1 — красный, потратил цикл)
|
||||
|
||||
## Скоуп проверки
|
||||
@@ -50,7 +50,7 @@ r1 (красный) содержал ровно одну находку — High
|
||||
|
||||
Без повторной проверки — код не менялся с `8b66d67d`, на котором это было
|
||||
проверено чтением и тестами в
|
||||
[CODE-REVIEW-359-r1.md](../reviews/CODE-REVIEW-359-r1.md):
|
||||
[CODE-REVIEW-359-r1.md](CODE-REVIEW-359-r1.md):
|
||||
|
||||
- **AC1–AC9** (появление preview, геометрический паритет preview/commit через
|
||||
единый `resolveFurniturePlacement`, живое обновление по полям размера,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- Этап: `code` (PROCESS.md §2.7)
|
||||
- Диапазон: `origin/dev...HEAD`, `origin/dev` = `ec9824f2`, `HEAD` = `a2867df9`
|
||||
(ветка `issue/54-zigbee-topology-hover`, детач `HEAD`)
|
||||
- ТЗ: [`docs/specs/054-zigbee-topology-overlay.md`](../specs/054-zigbee-topology-overlay.md),
|
||||
- ТЗ: [`docs/specs/054-zigbee-topology-overlay.md`](../../specs/054-zigbee-topology-overlay.md),
|
||||
ревью ТЗ зелёное на заходе r2 — [`SPEC-REVIEW-54-r2.md`](SPEC-REVIEW-54-r2.md)
|
||||
(r1 → M1/L1-L3 закрыты правкой `aed0b5b6`, подтверждено r2 зелёным)
|
||||
- Заход: **r1** код-ревью (первый заход этого этапа для #54; ревью ТЗ и код-ревью
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
- Диапазон общий: `origin/dev...HEAD`, `origin/dev` = `ec9824f2`, `HEAD` = `f0ed526a`
|
||||
(ветка `issue/54-zigbee-topology-hover`, детач `HEAD`, merge-base с `origin/dev`
|
||||
не сдвинулся — `ec9824f2` тот же, что в r1, ребейза не было)
|
||||
- ТЗ: [`docs/specs/054-zigbee-topology-overlay.md`](../specs/054-zigbee-topology-overlay.md),
|
||||
- ТЗ: [`docs/specs/054-zigbee-topology-overlay.md`](../../specs/054-zigbee-topology-overlay.md),
|
||||
ревью ТЗ зелёное на заходе r2 — [`SPEC-REVIEW-54-r2.md`](SPEC-REVIEW-54-r2.md)
|
||||
- Заход: **r2** код-ревью
|
||||
- Блокирующих циклов израсходовано: **1/4** (зелёных вердиктов ревью ТЗ бюджет
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Issue: [#437](https://github.com/Matysh/houseplan-card/issues/437) — конфигурируемая read-only сводная панель поверх плана.
|
||||
Материал: `git log --oneline origin/dev..HEAD` / `git diff origin/dev...HEAD` на SHA `96e07b9a0255eef3a55cd6c3be08198a0adcc7ba`.
|
||||
ТЗ: [docs/specs/437-summary-panel.md](../specs/437-summary-panel.md), принято ревью ТЗ r2 (зелёное, High 0/Medium 0).
|
||||
ТЗ: [docs/specs/437-summary-panel.md](../../specs/437-summary-panel.md), принято ревью ТЗ r2 (зелёное, High 0/Medium 0).
|
||||
Этап: код-ревью, заход r1, лимит циклов 4/4 (полный трек).
|
||||
|
||||
## Скоуп диффа
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
- Issue: [#495](https://github.com/Matysh/houseplan-card/issues/495)
|
||||
- Этап: `spec` (PROCESS.md §2.4)
|
||||
- ТЗ под ревью: [`docs/specs/495-import-commit-and-route-runs-durability.md`](../specs/495-import-commit-and-route-runs-durability.md)
|
||||
- ТЗ под ревью: [`docs/specs/495-import-commit-and-route-runs-durability.md`](../../specs/495-import-commit-and-route-runs-durability.md)
|
||||
- Материал: HEAD `70a394d2` (detached), содержит коммит ТЗ
|
||||
`70a394d2 docs: spec for #495 — import result follows the commit, dropped route runs reach the store`
|
||||
- Заход: **r1**, блокирующих циклов израсходовано 0/4 (первый раунд — раздел
|
||||
|
||||
@@ -10,7 +10,7 @@ Issue: [#588](https://github.com/Matysh/houseplan-card/issues/588)
|
||||
|
||||
## Скоуп разбора (по дельте, §2.10)
|
||||
|
||||
Предыдущий вердикт: жёлтый, заход r1, [docs/reviews/SPEC-REVIEW-588-r1.md](../../docs/reviews/SPEC-REVIEW-588-r1.md), материал — тело issue на момент разбора (SHA-256 тела `ee15ac6db7376cfb878034a0fb3bdce2907fc84f45a69cf7c0e9cd0804b7e6ce`, дерево материала `14bf5e35f9bccc2d74e54a390ebf9c9d176f2e8f`, ветка `dev`@`a6185e295d2e`).
|
||||
Предыдущий вердикт: жёлтый, заход r1, [docs/reviews/SPEC-REVIEW-588-r1.md](SPEC-REVIEW-588-r1.md), материал — тело issue на момент разбора (SHA-256 тела `ee15ac6db7376cfb878034a0fb3bdce2907fc84f45a69cf7c0e9cd0804b7e6ce`, дерево материала `14bf5e35f9bccc2d74e54a390ebf9c9d176f2e8f`, ветка `dev`@`a6185e295d2e`).
|
||||
|
||||
Дельта между r1 и r2 объявлена самим автором в комментарии перехода (`Matysh`, 2026-09-18T08:33:23Z) и подтверждена сверкой с текстом r1-документа (цитаты кода и AC в нём) построчно против текущего тела issue:
|
||||
|
||||
@@ -34,7 +34,7 @@ Issue: [#588](https://github.com/Matysh/houseplan-card/issues/588)
|
||||
|
||||
## Унаследовано из r1
|
||||
|
||||
Без повторной проверки в этом раунде, по [SPEC-REVIEW-588-r1.md](../../docs/reviews/SPEC-REVIEW-588-r1.md) (материал: тело issue SHA-256 `ee15ac6d...b7e6ce`, дерево `14bf5e35f9bc...`, `dev`@`a6185e295d2e`):
|
||||
Без повторной проверки в этом раунде, по [SPEC-REVIEW-588-r1.md](SPEC-REVIEW-588-r1.md) (материал: тело issue SHA-256 `ee15ac6d...b7e6ce`, дерево `14bf5e35f9bc...`, `dev`@`a6185e295d2e`):
|
||||
|
||||
- Сценарий и «что человек увидит до/после» — форма и содержание по §7.1, персона и поверхность названы (r1 §«Что проверено и корректно», п.1). Текст не менялся в дельте.
|
||||
- Скоуп/не-скоуп (за вычетом убранной фразы M2) — соответствует файлам, реально содержащим логику `static_icon`/`value`; не-скоуп корректно исключает `import_export.py`.
|
||||
|
||||
@@ -10,7 +10,7 @@ Issue: [#588](https://github.com/Matysh/houseplan-card/issues/588)
|
||||
|
||||
## Скоуп разбора (по дельте, §2.10)
|
||||
|
||||
Предыдущий вердикт: жёлтый, заход r2, [docs/reviews/SPEC-REVIEW-588-r2.md](../../docs/reviews/SPEC-REVIEW-588-r2.md), материал — тело issue на момент разбора (SHA-256 тела `40a3c8b12af7fe3803ad3fece1a00b54c8fa12bd8fdc36b6bccd6516bf41756f`, дерево материала `002d320431837447efa84ee6119a95334bac4080`, рабочая копия кода на `git rev-parse HEAD` = `5b7add94d15a3961adc7f288f00750820cbbba07`).
|
||||
Предыдущий вердикт: жёлтый, заход r2, [docs/reviews/SPEC-REVIEW-588-r2.md](SPEC-REVIEW-588-r2.md), материал — тело issue на момент разбора (SHA-256 тела `40a3c8b12af7fe3803ad3fece1a00b54c8fa12bd8fdc36b6bccd6516bf41756f`, дерево материала `002d320431837447efa84ee6119a95334bac4080`, рабочая копия кода на `git rev-parse HEAD` = `5b7add94d15a3961adc7f288f00750820cbbba07`).
|
||||
|
||||
Дельта между r2 и r3 объявлена автором в комментарии перехода (`Matysh`, 2026-09-18T08:48:00Z) и подтверждена построчной сверкой текущего тела issue с цитатами в документе r2:
|
||||
|
||||
@@ -28,7 +28,7 @@ Issue: [#588](https://github.com/Matysh/houseplan-card/issues/588)
|
||||
|
||||
## Унаследовано из r2
|
||||
|
||||
Без повторной проверки в этом раунде — код и текст этих разделов не менялись дельтой r2→r3; см. [SPEC-REVIEW-588-r2.md](../../docs/reviews/SPEC-REVIEW-588-r2.md) (материал: тело issue SHA-256 `40a3c8b1...b7e6ce`, дерево `002d3204...`, рабочая копия `5b7add94d15a`) и через него [SPEC-REVIEW-588-r1.md](../../docs/reviews/SPEC-REVIEW-588-r1.md) (материал: тело issue SHA-256 `ee15ac6d...b7e6ce`, дерево `14bf5e35f9bc...`, `dev`@`a6185e295d2e`):
|
||||
Без повторной проверки в этом раунде — код и текст этих разделов не менялись дельтой r2→r3; см. [SPEC-REVIEW-588-r2.md](SPEC-REVIEW-588-r2.md) (материал: тело issue SHA-256 `40a3c8b1...b7e6ce`, дерево `002d3204...`, рабочая копия `5b7add94d15a`) и через него [SPEC-REVIEW-588-r1.md](SPEC-REVIEW-588-r1.md) (материал: тело issue SHA-256 `ee15ac6d...b7e6ce`, дерево `14bf5e35f9bc...`, `dev`@`a6185e295d2e`):
|
||||
|
||||
- Сценарий и «что человек увидит до/после» — форма и содержание по §7.1 (r1 §«Что проверено и корректно», п.1).
|
||||
- Скоуп/не-скоуп — соответствует файлам, реально содержащим логику `static_icon`/`value`; не-скоуп корректно исключает `import_export.py`; фраза про «подсветку убираемой комнаты» убрана (M2, закрыт в r2), #589 существует, открыт, метки `bug, docs, vacuum, P3, S1-new` — проверено повторно в r2, не проверялось заново здесь.
|
||||
|
||||
@@ -48,7 +48,7 @@ Issue: [#593](https://github.com/Matysh/houseplan-card/issues/593)
|
||||
|
||||
Воспроизведение: `gh api repos/Matysh/houseplan-card/issues/593/timeline` показывает единственный комментарий issue (00:05:53) с текстом «Два продуктовых вопроса владельцу» и тут же — «Молчание считаю согласием с обоими вариантами по умолчанию: ТЗ пишу на них». Метка `S3-spec` появляется через 4 секунды после этого комментария (00:05:57), `S4-spec-review` — ещё через 7 минут (00:12:35). Метка `blocked` не применялась вовсе. Второго комментария, письма или иного независимого источника, где владелец лично подтверждает выбор, в issue нет.
|
||||
|
||||
`PROCESS.md` §7.1 резервирует «молчание — согласие» **только** за аналитическими оценками этапа S2 (§2.2: «Комментарий аналитики — уведомление, а не запрос»); для продуктовых вопросов этапа ТЗ предписан другой протокол — вопрос пачкой с дефолтом, `blocked` поверх `S3-spec`, и ожидание фактического ответа. Прецедент того, как это должно выглядеть, в этом же проекте: [SPEC-REVIEW-588-r1](../../docs/reviews/SPEC-REVIEW-588-r1.md) констатирует «владелец принял варианты по умолчанию по всем трём вопросам 18.09.2026 непосредственно в теле issue» — отдельным действием, с датой, отдельно от вопроса.
|
||||
`PROCESS.md` §7.1 резервирует «молчание — согласие» **только** за аналитическими оценками этапа S2 (§2.2: «Комментарий аналитики — уведомление, а не запрос»); для продуктовых вопросов этапа ТЗ предписан другой протокол — вопрос пачкой с дефолтом, `blocked` поверх `S3-spec`, и ожидание фактического ответа. Прецедент того, как это должно выглядеть, в этом же проекте: [SPEC-REVIEW-588-r1](SPEC-REVIEW-588-r1.md) констатирует «владелец принял варианты по умолчанию по всем трём вопросам 18.09.2026 непосредственно в теле issue» — отдельным действием, с датой, отдельно от вопроса.
|
||||
|
||||
Более того, прецедент по этой же самой подсистеме прямо предупреждает именно об этой ошибке: в [#159](https://github.com/Matysh/houseplan-card/issues/159) (внедрение библиотеки мебели 0.3.0) reviewer поставил **High-1** за то, что подтверждение авторства/MIT было дано «только в рабочей сессии» и не публично, хотя аналитика формулировала это как решённый факт — задача была заблокирована до тех пор, пока `Matysh` не опубликовал отдельный явный комментарий от первого лица. Автор текущего ТЗ этот урок применил к AC10 (лицензия) буквально, сославшись на #159 по номеру, но не применил его к собственным Р1/Р2 — те получили формулировку «Принято» без аналогичного независимого голоса.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Issue: [#593](https://github.com/Matysh/houseplan-card/issues/593)
|
||||
- Тело issue #593 на момент разбора: `gh issue view 593 --json body` (редакция 3 от 19.09.2026, раздел `## ТЗ`), сохранённое предложение автора выше него.
|
||||
- Все 5 комментариев issue: `gh issue view 593 --json comments`.
|
||||
- Полная временная шкала: `gh api repos/Matysh/houseplan-card/issues/593/timeline`.
|
||||
- Предыдущий раунд: [`docs/reviews/SPEC-REVIEW-593-r1.md`](../../docs/reviews/SPEC-REVIEW-593-r1.md), вердикт красный, материал зафиксирован в его собственном машинном блоке якорей: ветка `dev`, коммит `073c45b04308cd613182c700f30c75ebfa8d2ca7`, дерево `393fc8925392ed600ae675587da91f34ba6b3372`, тело issue sha256 `8be001d5a0b2efa4aeb3f2bcd347a9253252dd47c38b091473e6686ca24f91d6`. Текущее тело issue (редакция 3) очевидно отличается от этого текста — задача прошла через редакции 2 и 3 в ответ на вердикт r1; байтового совпадения с r1 не проверял, поскольку различие заведомо есть (сам факт правки — предмет этого раунда).
|
||||
- Предыдущий раунд: [`docs/reviews/SPEC-REVIEW-593-r1.md`](SPEC-REVIEW-593-r1.md), вердикт красный, материал зафиксирован в его собственном машинном блоке якорей: ветка `dev`, коммит `073c45b04308cd613182c700f30c75ebfa8d2ca7`, дерево `393fc8925392ed600ae675587da91f34ba6b3372`, тело issue sha256 `8be001d5a0b2efa4aeb3f2bcd347a9253252dd47c38b091473e6686ca24f91d6`. Текущее тело issue (редакция 3) очевидно отличается от этого текста — задача прошла через редакции 2 и 3 в ответ на вердикт r1; байтового совпадения с r1 не проверял, поскольку различие заведомо есть (сам факт правки — предмет этого раунда).
|
||||
- Прецедент [#159](https://github.com/Matysh/houseplan-card/issues/159) — та же подсистема, предыдущее внедрение библиотеки мебели (0.3.0): его r1-ревью, его находка High-1, его remediation-комментарии, финальный код (`test/furniture-assets.test.mjs`, `assets/furniture/houseplan-0.3.0/README.md`). Читал заново специально для этого раунда, поскольку именно на него ссылается текущий ТЗ (AC10) как на образец, и именно его конкретный текст стал мерилом находки H1(new) ниже.
|
||||
- Код: `test/furniture-assets.test.mjs` (тест `'release provenance is normalized to the repository MIT grant'`), `assets/furniture/houseplan-0.3.0/README.md`, `src/furniture-art-runtime.ts`, `src/houseplan-card.ts:2693`, `src/i18n/{ru,en,fr,de}.json` (ключ `toast.furniture_art_load_failed`) — прочитаны, чтобы проверить два конкретных утверждения редакции 3 (см. «Как проверялось»).
|
||||
- Ветка/код продукта: не создавались. `git log` подтверждает отсутствие любых коммитов или веток `issue/593-*`; рабочая копия на `HEAD = dcd6657581ba205edb63713e011a498b51983a20` (последний коммит — публикация документа r1), продуктовый код не менялся с r1. Гейты `typecheck`/`test`/`build`/`bundle:budget` не запускал — на этапе ревью ТЗ они не относятся к предмету раунда (см. «Чего не проверял», и это же практика самого r1).
|
||||
|
||||
@@ -21,7 +21,7 @@ Issue: [#593](https://github.com/Matysh/houseplan-card/issues/593)
|
||||
был учтён r2; новые — полноценный грант `#issuecomment-5739841899` (2026-09-19T06:09:00Z)
|
||||
и ответ на красный вердикт r2 `#issuecomment-5739855252` (06:12:00Z), которым
|
||||
поставлена `S4-spec-review`, заход r3).
|
||||
- Предыдущий раунд: [`docs/reviews/SPEC-REVIEW-593-r2.md`](../../docs/reviews/SPEC-REVIEW-593-r2.md),
|
||||
- Предыдущий раунд: [`docs/reviews/SPEC-REVIEW-593-r2.md`](SPEC-REVIEW-593-r2.md),
|
||||
вердикт красный, материал зафиксирован в его собственном машинном блоке якорей:
|
||||
ветка `dev`, коммит `dcd6657581ba205edb63713e011a498b51983a20`, дерево
|
||||
`0b48707268e99ee38221c8e74fb1c48ce6793e35`, тело issue sha256
|
||||
@@ -73,10 +73,10 @@ Issue: [#593](https://github.com/Matysh/houseplan-card/issues/593)
|
||||
|
||||
Дельта r2→r3 ограничена §3 Q3, §4 п.10–11, §8 (абзац «провенанс»), §10 AC10, §11 —
|
||||
всё остальное принято без повторной проверки в этом раунде, со ссылкой на
|
||||
[`SPEC-REVIEW-593-r2.md`](../../docs/reviews/SPEC-REVIEW-593-r2.md) (материал: ветка
|
||||
[`SPEC-REVIEW-593-r2.md`](SPEC-REVIEW-593-r2.md) (материал: ветка
|
||||
`dev`, коммит `dcd6657581ba205edb63713e011a498b51983a20`, дерево
|
||||
`0b48707268e99ee38221c8e74fb1c48ce6793e35`) и, где отмечено, на
|
||||
[`SPEC-REVIEW-593-r1.md`](../../docs/reviews/SPEC-REVIEW-593-r1.md) (коммит
|
||||
[`SPEC-REVIEW-593-r1.md`](SPEC-REVIEW-593-r1.md) (коммит
|
||||
`073c45b04308cd613182c700f30c75ebfa8d2ca7`):
|
||||
|
||||
- Комплектность обязательных разделов §7.1 — проверена r1, дельта их не убирала.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
- Issue: [#262](https://github.com/Matysh/houseplan-card/issues/262)
|
||||
- Ветка: `issue/262-readd-child-entity`
|
||||
- Статус: реализовано, ожидает код-ревью
|
||||
- Ревью ТЗ: [`docs/reviews/SPEC-REVIEW-262-r1.md`](../../docs/reviews/SPEC-REVIEW-262-r1.md),
|
||||
- Ревью ТЗ: [`docs/reviews/SPEC-REVIEW-262-r1.md`](../reviews/v1.68.0/SPEC-REVIEW-262-r1.md),
|
||||
зелёный вердикт
|
||||
- Приоритет: `P2`
|
||||
- Тип: `bug`
|
||||
|
||||
@@ -9969,6 +9969,17 @@ const MUTANT_DEFINITIONS = [
|
||||
replace: ' for (const issue of line.issues) if (!lineOf.has(Number(issue))) lineOf.set(Number(issue), line.tag); // mutant: first line wins',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'reviews-archive-links-from-new-place-only',
|
||||
guard: 'node --test --test-name-pattern="#682 r1 ссылки: перенесённый документ" test/reviews-archive.test.mjs',
|
||||
because: 'review #682 r1: a moved document keeps links written for its old folder; resolving '
|
||||
+ 'them only from the new place leaves every ../specs/ and sibling link broken in the archive',
|
||||
patches: [{
|
||||
file: 'scripts/reviews-archive.mjs',
|
||||
find: ' for (const base of [path, oldPath]) {',
|
||||
replace: ' for (const base of [path]) { // mutant: old location ignored',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'reviews-index-release-counts-ignored',
|
||||
guard: 'node --test --test-name-pattern="#635 счётчики|#635 индекс покрывает" test/reviews-index.test.mjs',
|
||||
|
||||
+120
-5
@@ -28,9 +28,16 @@
|
||||
* сам документ — первым стабильным тегом, содержащим его добавление;
|
||||
* - имя вне схемы и документ, не попавший ни в одну линию, остаются на месте
|
||||
* и печатаются — решает человек.
|
||||
*
|
||||
* Перенос добавляет документу уровень вложенности (`docs/reviews/X.md` →
|
||||
* `legacy/reviews/<тег>/X.md`), поэтому `--apply` переписывает относительные
|
||||
* Markdown-ссылки — и внутри перенесённых файлов, и в соседях, которые на них
|
||||
* ссылаются (`repairLinks`, ревью #682 r1). `--repair-links=<rev>` делает то же
|
||||
* для всех переименований `<rev>..HEAD`, `--check-links` печатает битые
|
||||
* относительные ссылки архива и живых каталогов.
|
||||
*/
|
||||
import { existsSync, mkdirSync } from 'node:fs';
|
||||
import { dirname, join, resolve } from 'node:path';
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { dirname, join, posix, resolve } from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { isMainModule } from './spawn-portable.mjs';
|
||||
@@ -150,6 +157,100 @@ export function addedLines({ names, through, head = 'HEAD', cwd = ROOT }) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const LINK_RE = /(\]\()([^)\s]+)(\))/g;
|
||||
const EXTERNAL = /^(?:[a-z][a-z0-9+.-]*:|#|\/)/i;
|
||||
|
||||
/**
|
||||
* Переписать относительные ссылки одного Markdown-файла после переносов.
|
||||
*
|
||||
* `path` — где файл лежит сейчас, `oldPath` — где лежал до переноса (для
|
||||
* неперенесённого совпадает). Ссылка, которая и так резолвится от `path`,
|
||||
* не трогается. Иначе цель ищется от `path` и от `oldPath`, проводится через
|
||||
* `moved` (старый путь → новый), и если так найден существующий файл — ссылка
|
||||
* пересчитывается от нового места. Ссылка, битая и до переноса, остаётся как
|
||||
* была: чинить чужую историю — не дело архива.
|
||||
*
|
||||
* @returns {{ text: string, fixed: number }}
|
||||
*/
|
||||
export function repairLinks({ text, path, oldPath = path, moved, exists }) {
|
||||
let fixed = 0;
|
||||
const out = String(text).replace(LINK_RE, (whole, open, target, close) => {
|
||||
if (EXTERNAL.test(target)) return whole;
|
||||
const hash = target.indexOf('#');
|
||||
const file = hash >= 0 ? target.slice(0, hash) : target;
|
||||
const anchor = hash >= 0 ? target.slice(hash) : '';
|
||||
if (!file) return whole;
|
||||
let decoded;
|
||||
try { decoded = decodeURI(file); } catch { decoded = file; }
|
||||
const here = posix.normalize(posix.join(posix.dirname(path), decoded));
|
||||
if (exists(here)) return whole;
|
||||
for (const base of [path, oldPath]) {
|
||||
const candidate = posix.normalize(posix.join(posix.dirname(base), decoded));
|
||||
const now = moved.get(candidate) ?? candidate;
|
||||
if (now !== here && exists(now)) {
|
||||
fixed += 1;
|
||||
let rel = posix.relative(posix.dirname(path), now);
|
||||
if (!rel.startsWith('.')) rel = rel || posix.basename(now);
|
||||
return `${open}${rel}${anchor}${close}`;
|
||||
}
|
||||
}
|
||||
return whole;
|
||||
});
|
||||
return { text: out, fixed };
|
||||
}
|
||||
|
||||
/** Все отслеживаемые Markdown-файлы: ссылаться на перенесённый документ может любой. */
|
||||
function trackedMarkdown(cwd) {
|
||||
return git(['ls-files', '-z', '--', '*.md'], cwd).split('\0').filter(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Прогнать `repairLinks` по всем Markdown-файлам дерева.
|
||||
* @param moved Map<старый путь, новый путь>
|
||||
*/
|
||||
export function repairTreeLinks({ moved, cwd = ROOT }) {
|
||||
const inverse = new Map([...moved].map(([from, to]) => [to, from]));
|
||||
const exists = (rel) => existsSync(join(cwd, rel));
|
||||
let files = 0; let links = 0;
|
||||
for (const path of trackedMarkdown(cwd)) {
|
||||
const full = join(cwd, path);
|
||||
if (!existsSync(full)) continue;
|
||||
const text = readFileSync(full, 'utf8');
|
||||
const result = repairLinks({ text, path, oldPath: inverse.get(path) ?? path, moved, exists });
|
||||
if (result.fixed) {
|
||||
writeFileSync(full, result.text);
|
||||
files += 1; links += result.fixed;
|
||||
}
|
||||
}
|
||||
return { files, links };
|
||||
}
|
||||
|
||||
/** Переименования `rev..HEAD` (`git diff -M`): карта старый путь → новый. */
|
||||
export function renamesSince(rev, cwd = ROOT) {
|
||||
const out = git(['diff', '-M', '--name-status', '--diff-filter=R', '-z', rev, 'HEAD'], cwd).split('\0').filter(Boolean);
|
||||
const moved = new Map();
|
||||
for (let i = 0; i < out.length; i += 3) moved.set(out[i + 1], out[i + 2]);
|
||||
return moved;
|
||||
}
|
||||
|
||||
/** Битые относительные ссылки в архиве и живых каталогах документов ревью и ТЗ. */
|
||||
export function brokenLinks({ cwd = ROOT, roots = [LIVE_DIR, ARCHIVE_DIR, 'docs/specs', 'legacy/specs'] } = {}) {
|
||||
const broken = [];
|
||||
for (const path of trackedMarkdown(cwd).filter((p) => roots.some((root) => p.startsWith(`${root}/`)))) {
|
||||
const text = readFileSync(join(cwd, path), 'utf8');
|
||||
for (const [, , target] of text.matchAll(LINK_RE)) {
|
||||
if (EXTERNAL.test(target)) continue;
|
||||
const file = target.split('#')[0];
|
||||
if (!file) continue;
|
||||
let decoded;
|
||||
try { decoded = decodeURI(file); } catch { decoded = file; }
|
||||
const resolved = posix.normalize(posix.join(posix.dirname(path), decoded));
|
||||
if (!existsSync(join(cwd, resolved))) broken.push({ path, target });
|
||||
}
|
||||
}
|
||||
return broken;
|
||||
}
|
||||
|
||||
export function applyPlan({ moves, cwd = ROOT }) {
|
||||
const dirty = git(['status', '--porcelain', '--', LIVE_DIR, ARCHIVE_DIR], cwd).trim();
|
||||
if (dirty) throw new Error(`рабочее дерево ${LIVE_DIR}/${ARCHIVE_DIR} не чистое:\n${dirty}`);
|
||||
@@ -158,16 +259,30 @@ export function applyPlan({ moves, cwd = ROOT }) {
|
||||
mkdirSync(join(cwd, dirname(move.to)), { recursive: true });
|
||||
git(['mv', move.from, move.to], cwd);
|
||||
}
|
||||
const repaired = repairTreeLinks({ moved: new Map(moves.map((move) => [move.from, move.to])), cwd });
|
||||
if (repaired.files) git(['add', '-u', '--', '.'], cwd);
|
||||
const index = spawnSync(process.execPath, [join(ROOT, 'scripts/reviews-index.mjs'), `--dir=${LIVE_DIR}`], { cwd, encoding: 'utf8' });
|
||||
if (index.status !== 0) throw new Error(`reviews-index: ${index.stderr || index.stdout}`);
|
||||
git(['add', '--', join(LIVE_DIR, INDEX_FILE)], cwd);
|
||||
return repaired;
|
||||
}
|
||||
|
||||
if (isMainModule(import.meta.url)) {
|
||||
const arg = (name) => process.argv.find((a) => a.startsWith(`--${name}=`))?.slice(name.length + 3);
|
||||
if (arg('repair-links')) {
|
||||
const result = repairTreeLinks({ moved: renamesSince(arg('repair-links')) });
|
||||
console.log(`ссылок переписано ${result.links} в ${result.files} файл(ах)`);
|
||||
process.exit(0);
|
||||
}
|
||||
if (process.argv.includes('--check-links')) {
|
||||
const broken = brokenLinks();
|
||||
for (const item of broken) console.log(`${item.path}: ${item.target}`);
|
||||
console.log(`битых относительных ссылок: ${broken.length}`);
|
||||
process.exit(broken.length ? 1 : 0);
|
||||
}
|
||||
const through = arg('through');
|
||||
if (!through || !STABLE_TAG_RE.test(through)) {
|
||||
console.error('usage: node scripts/reviews-archive.mjs --through=vX.Y.Z [--head=HEAD] [--apply]');
|
||||
console.error('usage: node scripts/reviews-archive.mjs --through=vX.Y.Z [--head=HEAD] [--apply] | --repair-links=<rev> | --check-links');
|
||||
process.exit(2);
|
||||
}
|
||||
const head = arg('head') || 'HEAD';
|
||||
@@ -179,8 +294,8 @@ if (isMainModule(import.meta.url)) {
|
||||
: first;
|
||||
console.log(renderPlan({ ...plan, through }));
|
||||
if (process.argv.includes('--apply')) {
|
||||
applyPlan({ moves: plan.moves });
|
||||
console.log(`перенесено ${plan.moves.length}; ${LIVE_DIR}/${INDEX_FILE} пересобран. Коммит — класс C, с трейлером задачи.`);
|
||||
const repaired = applyPlan({ moves: plan.moves });
|
||||
console.log(`перенесено ${plan.moves.length}; ссылок переписано ${repaired.links} в ${repaired.files} файл(ах); ${LIVE_DIR}/${INDEX_FILE} пересобран. Коммит — класс C, с трейлером задачи.`);
|
||||
} else {
|
||||
console.log('план (--apply выполнит git mv и пересоберёт индекс)');
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// #682: архив документов ревью выпущенных линий — кому куда, решают трейлеры.
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { ARCHIVE_DIR, LIVE_DIR, archivePlan, renderPlan, stableTagsThrough } from '../scripts/reviews-archive.mjs';
|
||||
import { ARCHIVE_DIR, LIVE_DIR, archivePlan, brokenLinks, renderPlan, repairLinks, stableTagsThrough } from '../scripts/reviews-archive.mjs';
|
||||
|
||||
const lines = [
|
||||
{ tag: 'v1.76.0', issues: [500, 510, 520] },
|
||||
@@ -66,3 +66,55 @@ test('#682 архив: линии — только стабильные теги
|
||||
assert.throws(() => stableTagsThrough([], 'v1.78.0-beta.1'), /not a stable release tag/);
|
||||
assert.throws(() => archivePlan({ names: [], lines: [{ tag: 'v1.78.0', issues: [] }], open: [], through: 'v1.77.0' }), /newer than/);
|
||||
});
|
||||
|
||||
// Ревью #682 r1 (Medium): перенос добавляет уровень вложенности, и относительные
|
||||
// ссылки внутри перенесённых документов и в соседях, которые на них ссылаются,
|
||||
// ломались молча — ни один гейт не смотрит в архив.
|
||||
const tree = new Set([
|
||||
'docs/specs/089-stage1.md',
|
||||
'docs/reviews/CODE-REVIEW-635-r1.md',
|
||||
'legacy/reviews/v1.77.0/CODE-REVIEW-594-r1.md',
|
||||
'legacy/reviews/v1.77.0/CODE-REVIEW-594-r2.md',
|
||||
'legacy/reviews/v1.68.0/SPEC-REVIEW-262-r1.md',
|
||||
'legacy/specs/262-readd.md',
|
||||
]);
|
||||
const exists = (path) => tree.has(path);
|
||||
const moved = new Map([
|
||||
['docs/reviews/CODE-REVIEW-594-r1.md', 'legacy/reviews/v1.77.0/CODE-REVIEW-594-r1.md'],
|
||||
['docs/reviews/CODE-REVIEW-594-r2.md', 'legacy/reviews/v1.77.0/CODE-REVIEW-594-r2.md'],
|
||||
['docs/reviews/SPEC-REVIEW-262-r1.md', 'legacy/reviews/v1.68.0/SPEC-REVIEW-262-r1.md'],
|
||||
['docs/specs/262-readd.md', 'legacy/specs/262-readd.md'],
|
||||
]);
|
||||
|
||||
test('#682 r1 ссылки: перенесённый документ пересчитывает свои ссылки от нового места', () => {
|
||||
const result = repairLinks({
|
||||
text: 'ТЗ: [s](../specs/089-stage1.md#ac2); прошлый раунд: [r1](CODE-REVIEW-594-r1.md); сайт: [x](https://example.org/a.md)',
|
||||
path: 'legacy/reviews/v1.77.0/CODE-REVIEW-594-r2.md',
|
||||
oldPath: 'docs/reviews/CODE-REVIEW-594-r2.md',
|
||||
moved, exists,
|
||||
});
|
||||
assert.equal(result.text, 'ТЗ: [s](../../../docs/specs/089-stage1.md#ac2); прошлый раунд: [r1](CODE-REVIEW-594-r1.md); сайт: [x](https://example.org/a.md)');
|
||||
assert.equal(result.fixed, 1);
|
||||
});
|
||||
|
||||
test('#682 r1 ссылки: сосед, ссылавшийся на перенесённый документ, ведёт в архив', () => {
|
||||
const live = repairLinks({ text: '[r1](CODE-REVIEW-594-r1.md)', path: 'docs/reviews/CODE-REVIEW-635-r1.md', moved, exists });
|
||||
assert.equal(live.text, '[r1](../../legacy/reviews/v1.77.0/CODE-REVIEW-594-r1.md)');
|
||||
// Ссылка, уже переписанная прошлым переносом (ТЗ ушло в legacy/specs раньше документа ревью).
|
||||
const spec = repairLinks({
|
||||
text: '[r](../../docs/reviews/SPEC-REVIEW-262-r1.md)', path: 'legacy/specs/262-readd.md', oldPath: 'docs/specs/262-readd.md', moved, exists,
|
||||
});
|
||||
assert.equal(spec.text, '[r](../reviews/v1.68.0/SPEC-REVIEW-262-r1.md)');
|
||||
});
|
||||
|
||||
test('#682 r1 ссылки: битая и до переноса ссылка не «чинится» наугад', () => {
|
||||
const result = repairLinks({ text: '[x](...), [y](nowhere.md)', path: 'legacy/reviews/v1.72.0/CODE-REVIEW-448-r2.md', oldPath: 'docs/reviews/CODE-REVIEW-448-r2.md', moved, exists });
|
||||
assert.equal(result.fixed, 0);
|
||||
assert.equal(result.text, '[x](...), [y](nowhere.md)');
|
||||
});
|
||||
|
||||
test('#682 r1 архив legacy/: относительные ссылки резолвятся (кроме известных «...»-заглушек)', () => {
|
||||
const broken = brokenLinks({ roots: ['legacy/reviews', 'legacy/specs'] }).filter((item) => item.target !== '...');
|
||||
assert.deepEqual(broken, []);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user