test: close device presentation review findings

Issue: #267
User-Visible: no
This commit is contained in:
Matysh
2026-08-27 22:41:46 +03:00
parent 8b0ad08db2
commit 118062bb8c
10 changed files with 145 additions and 92 deletions
+4 -3
View File
@@ -27,9 +27,9 @@ mutation evidence в одном pull request.
| L01 | `marker.removed:true` | `pre.lifecycle.removed` | marker отсутствует в roster/DOM | отсутствует | `devices` tombstone test; `presentation-row-contract` |
| L02 | HA-disabled, View/киоск/static | `lifecycle.ha_disabled_hidden` | face скрыт, live state не участвует | отсутствует на View | `device-presentation-policy-lifecycle`; `presentation-row-contract` |
| L03 | HA-disabled, Device editor | `lifecycle.ha_disabled_hidden` | служебный ghost/preview с причиной `ha_disabled`, без live face | editor-owned, без service action | `device-presentation-policy-lifecycle`; `presentation-row-contract` |
| L04 | user-hidden, View/киоск/static | `lifecycle.user_hidden` | marker и hit-area скрыты | отсутствует | `device-presentation-policy-lifecycle`; `presentation-row-contract` |
| L05 | user-hidden, design preview | `lifecycle.user_hidden_preview` | сохранённый дизайн видим; notice `hidden_design_preview` | preview inert | `device-presentation-policy-lifecycle`; `presentation-row-contract` |
| L06 | orphaned/unverified | `lifecycle.orphaned_diagnostic` / `lifecycle.unverified_diagnostic` | нейтральная диагностическая проекция с причиной, pulse/service не оживают | surface-owned safe path | `device-presentation-policy-lifecycle`; `presentation-row-contract` |
| L04 | user-hidden, View/киоск/static | `lifecycle.user_hidden` | marker и hit-area скрыты | отсутствует | `device-presentation-policy-user-hidden`; `presentation-row-contract` |
| L05 | user-hidden, design preview | `lifecycle.user_hidden_preview` | сохранённый дизайн видим; notice `hidden_design_preview` | preview inert | `device-presentation-policy-user-hidden-preview`; `presentation-row-contract` |
| L06 | orphaned binding | `lifecycle.orphaned_diagnostic` | нейтральная диагностическая проекция с причиной, pulse/service не оживают | surface-owned safe path | `device-presentation-policy-orphaned`; `presentation-row-contract` |
## Источник лица и доступность
@@ -48,6 +48,7 @@ mutation evidence в одном pull request.
| S11 | registry role временно отсутствует, есть primary | `source.primary_fallback` | deterministic primary fallback | normal | `presentation-source-decision-trace`; `presentation-row-contract` |
| S12 | пригодного source нет | `source.none` | neutral base-icon fallback | normal | `presentation-source-decision-trace`; `presentation-row-contract` |
| S13 | critical alarm sibling вне обычного source | `source.critical_sibling` + `status.alarm` | alarm добавлен в aggregate и побеждает normal status | normal | `device-presentation-policy-alarm`; `presentation-row-contract` |
| S14 | static plan fast path без source details | `source.skipped_static_fast_path` | source graph намеренно не вычисляется; static face остаётся neutral | normal; без source-derived данных | `presentation-static-source-fast-path`; `presentation-row-contract` |
## Финальное лицо, контент и диагностика
+11 -11
View File
@@ -2,7 +2,7 @@
"version": 1,
"fixture": "synthetic-only",
"chromium": "151.0.7922.34",
"sourceFingerprint": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceFingerprint": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"captureScriptSha256": "ce2e9542fed9dade3085be87d16f69adb2ac8262893ad78ad966b1b9673f2983",
"command": "npm run build && node demo/docs/capture.mjs",
"scenarios": {
@@ -14,7 +14,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "36223106c073f07d8cc3ecf8eaab37192ebb2687daba65c5c21047d0b7890de0"
},
"view-touch": {
@@ -25,7 +25,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "41e3ba67f8db0e98f26f484293af83ef937c369ca5ca6a59a3350d8954c906f4"
},
"space-create": {
@@ -36,7 +36,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "0dc024726327f60f4a9ceaf3044381691f81f1090af81d1812e870f22d9343ba"
},
"room-contour-close": {
@@ -47,7 +47,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "44cfaa95bd51e2cd628400e28db0ad8b2f0cd904385845bd402494f3f5c0d93c"
},
"plan-context-tray": {
@@ -58,7 +58,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "e0662429b423fb74151b583dcc2c8635b001b637d03bbf7a6b16aec46399c3f8"
},
"device-editor": {
@@ -69,7 +69,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "d0ffd31ce80bfde21ab75da356a5fc1af38246f2b301030880320620c228d89d"
},
"device-display-preview": {
@@ -80,7 +80,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "2cdabae1f89c3286e4fac0ce30f757ee1690b707ab8a5488748b7cd420626160"
},
"background-editor": {
@@ -91,7 +91,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "30147bb00a90eea7136b4cee30995f6e6a9217b5132f3e8d3ad7471413b1af8a"
},
"room-card": {
@@ -102,7 +102,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "029a3e69ec647a8a370d99e6bb7f9225833c526739076022f6b52ba54bff30ea"
},
"device-info": {
@@ -113,7 +113,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "fb7f3cbc180b24cb91421c5cd0b8808cd4e2d0c38dd0c6f00f46d59f94e4a6d7",
"sourceSha256": "bbdc8981e3d11029702a3e5b78a9026e6814bb2bdf8e3cb56d0c2e8f7c519b2c",
"imageSha256": "dd492f53150b7149085daada5cce9eeae9bde9e7ea1d86679a54b3041f72f517"
}
}
@@ -135,7 +135,7 @@
| L03 | HA-disabled в служебном Device editor | диагностический marker/preview с причиной, без live state/action |
| L04 | user-hidden в View/киоске/static card | marker и hit-area отсутствуют |
| L05 | user-hidden в design preview | реальный сохранённый дизайн видим, notice `hidden_design_preview`, preview inert |
| L06 | orphaned/unverified binding | сохраняется действующая диагностическая проекция и причина; pulse/service не оживают |
| L06 | orphaned binding | сохраняется действующая диагностическая проекция и причина; pulse/service не оживают |
### 6.2 Source / availability
@@ -154,6 +154,7 @@
| S11 | registry role временно отсутствует, есть live primary | deterministic `primary` fallback без смены сохранённого binding |
| S12 | нет пригодного source | neutral icon fallback; не выбирается случайная sibling entity |
| S13 | critical alarm sibling вне обычного face source | alarm добавляется к semantic aggregate и имеет публичный приоритет |
| S14 | static plan fast path с `sourceDetails:false` | source graph не вычисляется; trace явно фиксирует пропуск, static face остаётся neutral |
### 6.3 Face / content / diagnostics
@@ -209,7 +210,7 @@ semantic facts, не читает HA registry/state и не строит light g
```ts
interface DevicePresentationPolicyInput {
bindingLifecycle: 'active' | 'ha_disabled' | 'orphaned' | 'unverified';
bindingLifecycle: 'active' | 'ha_disabled' | 'orphaned';
userHidden: boolean;
designPreview: boolean;
display: DeviceDisplayMode;
@@ -250,7 +251,7 @@ Production decision IDs описывают **правила**, а не test fixt
- `device-toggle.ts` и surface handlers владеют action/security/interactivity;
- `resolvePresentationSources()` продолжает владеть HA/light graph, но
возвращает дополнительно явный source-decision ID либо эквивалентный trace,
чтобы S01…S13 не зависели от чтения порядка `if`;
чтобы S01…S14 не зависели от чтения порядка `if`;
- `houseplan-card.ts`, `space-card.ts`, `space-render.ts` не получают права
переопределять policy result.
@@ -409,7 +410,7 @@ renderer и surfaces не принимают альтернативных реш
### AC3 — source decisions названы
Каждая ветка `cover|controls|light|device_role|primary|none` и critical sibling
возвращает стабильный decision ID/trace; S01…S13 проверяют наблюдаемый output.
возвращает стабильный decision ID/trace; S01…S14 проверяют наблюдаемый output.
**Доказательство:** parameterized unit.
@@ -545,4 +546,3 @@ node scripts/mutation-gate.mjs --id=<каждый новый/изменённы
является самоцелью.
5. Existing browser smoke расширяется только если это остаётся узким сценарием;
иначе создаётся новый `smoke_device_presentation_matrix.mjs`.