fix: a refused geometry preflight names its reason and hands over diagnostics (#295)

Диалог «Оптимизировать» при отказе перечисляет причину по каждому
пространству (7 значений OptimizeGeometryFailureReason получили RU/EN
строки), даёт «Скопировать диагностику» — JSON-блок с origin: runtime,
версией карточки, отпечатками и классами исключений (граница приватности
checkOptimizeGeometry; privacy-тесты дополнены позитивной проверкой) — и
пишет одну структурированную запись в dev-лог (дедупликация по fingerprint).
При недоступном clipboard блок раскрывается прямо в диалоге.

Совет «обновите House Plan» больше не безусловный: websocket
houseplan/config/get теперь возвращает integration_version (бэкенд-тест),
и подсказка показывается только при реальном расхождении с версией карточки;
старый бэкенд без поля — подсказки нет.

Три новых мутанта (потеря причины в диалоге, блок без reason, отключённый
dev-лог) — краснота каждого проверена исполнением; смок
smoke_preflight_diagnostics на dev падает.

Issue: #295
User-Visible: yes
This commit is contained in:
Codex
2026-08-26 10:28:29 +03:00
parent a5abfe8bd6
commit 1cdd4ed6de
16 changed files with 615 additions and 270 deletions
+36
View File
@@ -2246,6 +2246,42 @@ export const MUTANTS = [
replace: ' const reach = self.length;',
}],
},
{
id: 'preflight-reason-lost-in-dialog',
// #295: диалог обязан называть причину отказа по каждому пространству.
guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
+ '&& node demo/smoke_preflight_diagnostics.mjs',
because: 'отказ preflight без причины недиагностируем — ровно исходный дефект #295',
patches: [{
file: 'src/houseplan-card.ts',
find: " ${failure.displayName}: ${this._t(`gs.preflight_reason_${failure.reason}` as any)}",
replace: " ${failure.displayName}",
}],
},
{
id: 'preflight-diagnostics-without-reason',
// #295: копируемый блок без reason бесполезен для отчёта об ошибке.
guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
+ '&& node demo/smoke_preflight_diagnostics.mjs',
because: 'диагностический блок обязан нести reason каждого отказа',
patches: [{
file: 'src/houseplan-card.ts',
find: " reason: failure.reason,",
replace: " reason: undefined,",
}],
},
{
id: 'preflight-dev-log-disabled',
// #295: dev-лог — второй канал диагностики, его потерю обязан ловить смок.
guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
+ '&& node demo/smoke_preflight_diagnostics.mjs',
because: 'структурированная запись отказа в консоли — часть контракта диагностики #295',
patches: [{
file: 'src/houseplan-card.ts',
find: " console.warn('[houseplan] optimize preflight failed', this._preflightDiagnostics(preflight));",
replace: " void preflight;",
}],
},
{
id: 'visual-mitre-limit-back-to-4',
// #309: порог визуального среза возвращается к классическим 4·h — шип на