mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
docs: #397 spec revision 2 per SPEC-REVIEW-397-r1
User-Visible: no Issue: #397
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
- Issue: https://github.com/Matysh/houseplan-card/issues/397
|
||||
- Приоритет: P1, bug; полный трек — класс A (продуктовый код) плюс правка
|
||||
подстроенного доказательства AC10 ТЗ #74
|
||||
- Ревизия: 1 (2026-08-31)
|
||||
- Ревизия: 2 (2026-08-31) — по SPEC-REVIEW-397-r1 (Medium: доказательства AC5/AC7)
|
||||
|
||||
## Сценарий
|
||||
|
||||
@@ -25,7 +25,7 @@ Undo/Redo молча гаснут — история очищена, хотя м
|
||||
|
||||
### (1) B3 — канонический ответ не возвращается в локальный layout
|
||||
|
||||
`_persistDevicePlacement` (`src/houseplan-card.ts:5226-5258`) отправляет на
|
||||
`_persistDevicePlacement` (`src/houseplan-card.ts:5226-5261`) отправляет на
|
||||
сервер `canonicalizePosition(this._layout[deviceId])`, но сам `_layout`
|
||||
оставляет как есть, а следом (`:5253`) фиксирует
|
||||
`_layoutContentFingerprint = contentFingerprint(this._layout)` — по
|
||||
@@ -112,18 +112,30 @@ out.sameContentReloadKeepsHistory = c._devicePositionHistory.canUndo;
|
||||
получил) `canUndo` остаётся `true`. Доказательство: смок с честной
|
||||
фикстурой.
|
||||
- **AC3**. Тот же инвариант для `_adoptStructuralResponses` (полная
|
||||
перезагрузка конфига и layout, reconnect-путь).
|
||||
перезагрузка конфига и layout, reconnect-путь). Доказательство: смок,
|
||||
пункт 5 плана — перемещение, затем полная перезагрузка с честным серверным
|
||||
слепком, `canUndo` остаётся `true`.
|
||||
- **AC4**. Чужое изменение по-прежнему чистит историю: сервер отвечает
|
||||
позицией, отличной от отправленной, → `canUndo === false`, `_layout`
|
||||
заменён. Доказательство: тот же смок, обратная ветка.
|
||||
- **AC5**. Удаление позиции (`placement === null`) подчиняется AC1–AC4:
|
||||
локальный ключ удалён до фиксации отпечатка, эхо удаления историю не чистит.
|
||||
- **AC5**. Удаление позиции (`placement === null`) подчиняется AC1–AC4 в обеих
|
||||
половинах. (а) Локальный ключ удалён до фиксации отпечатка — доказательство:
|
||||
юнит, пункт 2 плана. (б) Эхо удаления не чистит историю — доказательство:
|
||||
смок, пункт 7 плана: удаление позиции, затем честный reload, `canUndo`
|
||||
остаётся `true`. Вторая половина отдельная не для симметрии: удаление идёт
|
||||
другой веткой (`houseplan/layout/delete`, `pending = null`), и запись в
|
||||
`_layout` там снимает ключ, а не заменяет значение — доказательство первой
|
||||
половины про вторую ничего не говорит.
|
||||
- **AC6**. Смок AC10 краснеет на коде до фикса (1). Доказательство: прогон
|
||||
переписанного смока против `git stash` реализации, зафиксирован в документе
|
||||
ревью.
|
||||
- **AC7**. Позиции, отправленные и ещё не подтверждённые (`_sentPos`),
|
||||
продолжают побеждать ответ сервера при слиянии — поведение `_reloadLayoutOnly`
|
||||
в этой части не меняется.
|
||||
продолжают побеждать ответ сервера при слиянии — поведение
|
||||
`_reloadLayoutOnly` в этой части не меняется. Доказательство: смок, пункт 8
|
||||
плана — пока запись «в полёте», сервер отвечает СТАРОЙ позицией, и после
|
||||
слияния в `_layout` остаётся отправленная, а не серверная. Инвариант назван
|
||||
явно, потому что фикс правит соседний код (порядок записи в `_layout` и
|
||||
регистрации в `_sentPos`): без своего теста он ломается молча.
|
||||
|
||||
## План автотестов
|
||||
|
||||
@@ -142,6 +154,10 @@ out.sameContentReloadKeepsHistory = c._devicePositionHistory.canUndo;
|
||||
5. Перемещение → полный `_adoptStructuralResponses` (reconnect) →
|
||||
`canUndo === true` (AC3).
|
||||
6. Сервер отвечает другой позицией → история очищена, `_layout` заменён (AC4).
|
||||
7. Удаление позиции → честный reload → `canUndo` остаётся `true`, ключ не
|
||||
возвращается (AC5б).
|
||||
8. Запись «в полёте» (`_sentPos` не пуст), сервер отвечает старой позицией →
|
||||
после слияния в `_layout` отправленная позиция, история цела (AC7).
|
||||
|
||||
**Мутант** (`scripts/mutation-gate.mjs`):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user