diff --git a/CLAUDE.md b/CLAUDE.md index 7638750..d8f9cf6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,7 +67,19 @@ save-time timer (B07). `just vm-reset && just e2e` зелёный с нуля: * регресс v0.1/v0.2 + machine-id-стабильность цел. prod-build-gate: `--no-default-features` без `PowerMock1`. Приёмка спека v0.3 §9.4 выполнена. **VM-модель** (abort/PONR = stop+umount+remount); аппаратное (MCU/hold-up/fail-safe-таймер, **B08/B09**) → v0.4. -**Следующее:** `v0.5` полный shell (живой weston-shell) и `v0.4` MCU/thermal (замыкает B08/B09) — параллельно поверх v0.2/v0.3. +**v0.4 MCU/thermal fail-safe — ГОТОВО (ветка `feat/v0.4-mcu-thermal`):** спека `docs/specs/v0.4-mcu-thermal.md` + план +`docs/specs/plans/08-v0.4-mcu-thermal.md`. Поверх FSM v0.3, в стиле «чистое ядро → абстракция → dev-mock»: **A12/B10** +тепло — чистая `ThermalPolicy` (банды + гистерезис) → `Event::ThermalTrip` (реюз FSM) + abort `ThermalCleared`; +`TempSource`/`Throttler` абстракции (VM mock/noop; sysfs/cpufreq + пороги → RK3588). **B08** MCU-протокол +(`SocToMcu`/`McuToSoc`) + кодек (CRC16/replay/desync-guard) + `CoprocessorClient` (heartbeat/wait-for-completion/ +`safe-to-cut`). **B09** fail-safe-таймер — **модель** (`MockCoprocessor`: hang/budget → `Event::FailsafeCut` → off). +`ru.shturman.Power` += `ThermalState`/`ThermalChanged` (рендер «перегрев» → v0.5). `just vm-reset && just e2e` зелёный +с нуля: thermal-trip→`ShutdownImminent(thermal)`, throttle-банд, **MCU fail-safe (HangSoc → cut)**; регресс v0.1–v0.3 +цел. prod-build-gate без `PowerMock1`/`SetTemp`/`HangSoc`. Приёмка спека v0.4 §9.4 выполнена. **Физический выбор B08/B09 +(MCU vs supercap-only) + реальное железо (UART/MCU-чип/таймер/cpufreq) → HW-bring-up-подфаза** (нужна плата RK3588). + +**Следующее:** `v0.5` полный shell (живой weston-shell; замкнёт thermal-UX-рендер) — поверх v0.2. **HW-bring-up** +(MCU/supercap, реальный UART/cpufreq/B09-чип, тепловой/перф-вердикт) — отдельной подфазой при появлении платы. > CI: GitHub-Actions-конфиг **удалён** (его ловит Gitea). Гейт — локальный `just ci`. CI на Gitea — решение позже. diff --git a/docs/capability-catalog.md b/docs/capability-catalog.md index b68d53c..aa672bf 100644 --- a/docs/capability-catalog.md +++ b/docs/capability-catalog.md @@ -36,7 +36,7 @@ | A09 | Память (zram + OOM + cgroup-лимиты) | A | MVP (день 1) | v0 | — | ✅ | | A10 | Логирование (journald volatile + критичное в `/data` + pstore) | A | MVP (день 1) | v0 | — | ✅ | | A11 | eMMC write-minimization | A | MVP (день 1) | v0 | — | ✅ | -| A12 | Тепловой мониторинг + базовый throttling (SoC) | A | MVP | v0 | hardware | ✅ | +| A12 | Тепловой мониторинг + базовый throttling (SoC) | A | MVP | v0 | hardware | ✅ v0.4 (политика+абстракция; cpufreq/пороги → RK3588) | | A13 | Тепловой тюнинг (политики под горячий салон) | A | later | v1 | — | ✅ | | A14 | Hardware watchdog (вооружён в boot-окне) + recovery | A | MVP | v0 | hardware, B | ✅ | | A15 | systemd-таргеты / оркестрация | A | MVP | v0 | — | ✅ | @@ -56,9 +56,9 @@ | B05 | Watchdog (runtime + shutdown-фаза + boot-окно) | B | MVP | v0 | hardware, a-base | ✅ | | B06 | Load-shedding при power-loss | B | MVP | v0 | селективные рейлы (hardware §6) | ✅ | | B07 | Save last-known-time + периодика | B | MVP | v0 | a-base §7 | ✅ | -| B08 | MCU-копилот shutdown-протокол (если MCU) | B | MVP | v0 | hardware §3 | 🟡 MCU vs supercap-only | -| B09 | MCU аппаратный fail-safe-таймер | B | MVP | v0 | hardware §3 | 🟡 MCU vs supercap-only | -| B10 | Thermal shutdown (триггер + hysteresis + UX) | B | MVP | v0/v1 | a-base §10, hardware §1a | ✅ | +| B08 | MCU-копилот shutdown-протокол (если MCU) | B | MVP | v0 | hardware §3 | v0.4 софт (протокол+кодек+клиент); 🟡 физический MCU vs supercap → HW | +| B09 | MCU аппаратный fail-safe-таймер | B | MVP | v0 | hardware §3 | v0.4 модель (hang/budget→cut); 🟡 реальный таймер-чип → HW | +| B10 | Thermal shutdown (триггер + hysteresis + UX) | B | MVP | v0/v1 | a-base §10, hardware §1a | ✅ v0.4 (триггер+гистерезис; UX-рендер → v0.5) | | B11 | MCU прошивка: update path | B | later | v1 | hardware | 🟡 MCU vs supercap-only | | B12 | Sleep/wake + battery-cutoff | B | later | v1/v2 | — | ✅ | | B13 | Гейт wake-word по состояниям (с D) | B | MVP | v1 | D | ✅ | diff --git a/docs/contracts/hardware.md b/docs/contracts/hardware.md index bacb131..c0ed0af 100644 --- a/docs/contracts/hardware.md +++ b/docs/contracts/hardware.md @@ -54,6 +54,11 @@ Panfrost GPU, мощности хватает на плавный UI и **лок Рекомендую MCU-копилот: он же закрывает watchdog и пробуждение. (Прошивка МК — домен B.) +> **Статус (v0.4):** SoC-сторона MCU-протокола (B08), кодек линка и **модель** fail-safe-таймера (B09) реализованы +> в софте (`shturman-power`, симметрия с FSM v0.3) — спека `docs/specs/v0.4-mcu-thermal.md`. **Физический выбор +> B08/B09** (MCU-копилот vs supercap-only), реальный МК-чип/прошивка/независимый таймер и hold-up sizing — остаются +> 🟡 и закрываются в **HW-bring-up-подфазе** (нужна плата RK3588; перф/тепловой вердикт — там же). + **Бюджет hold-up (числовой контракт; sizing — здесь, sequencing — домен B):** энергия = worst-case ток (SoC + контроллер хранилища при флаше/unmount) × hold-time (верхняя оценка flush+durable-write+unmount с запасом) × **дератинг** (низкая T −40 °C: ёмкость/ESR supercap diff --git a/docs/contracts/ipc.md b/docs/contracts/ipc.md index d9c3887..6cab48b 100644 --- a/docs/contracts/ipc.md +++ b/docs/contracts/ipc.md @@ -58,9 +58,10 @@ ### `ru.shturman.Power` — питание и жизненный цикл (домен B) - **Методы:** `GetPowerState() → state` (enum `off`/`accessory`/`running`/`shutting_down`/`sleep`/`battery_cutoff`), `RequestSleep()` (внутр.). -- **Сигналы:** `AccChanged(on)`, `ShutdownImminent(seconds, reason)` (`reason ∈ acc_off|under_voltage|thermal|battery_cutoff`), **`ShutdownAborted()`** (re-power до PONR), `Sleep()`, `Wake()`. -- **Properties:** `IgnitionState` (off/accessory/running — **канон**; E зеркалит, не дублирует), `Uptime` (монотонные часы), `PowerSource` (`vehicle_12v`/`holdup_cap`/`sleep_rail`/`low_battery`). -- **Реализация (v0.3):** состояние/сигналы **оживлены из FSM** (`PowerFsm` в `shturman-power`, не mock); `ShutdownImminent`/`ShutdownAborted` — из реальных переходов (abort до PONR + grace-таймер). `Sleep`/`Wake`/`RequestSleep` объявлены, но **зарезервированы** (v1/v2, B §7). Источник событий (ACC/voltage/thermal через MCU) → v0.4; в v0.3 кормит dev-mock. +- **Сигналы:** `AccChanged(on)`, `ShutdownImminent(seconds, reason)` (`reason ∈ acc_off|under_voltage|thermal|battery_cutoff`), **`ShutdownAborted()`** (re-power/остывание до PONR), `ThermalChanged(state, celsius)`, `Sleep()`, `Wake()`. +- **Properties:** `IgnitionState` (off/accessory/running — **канон**; E зеркалит, не дублирует), `Uptime` (монотонные часы), `PowerSource` (`vehicle_12v`/`holdup_cap`/`sleep_rail`/`low_battery`), `ThermalState` (`normal`/`warn`/`throttle`/`critical`). +- **Реализация (v0.3):** состояние/сигналы **оживлены из FSM** (`PowerFsm` в `shturman-power`, не mock); `ShutdownImminent`/`ShutdownAborted` — из реальных переходов (abort до PONR + grace-таймер). `Sleep`/`Wake`/`RequestSleep` объявлены, но **зарезервированы** (v1/v2, B §7). +- **Реализация (v0.4):** `ThermalState`/`ThermalChanged` — из `ThermalPolicy` (банды + гистерезис), `ShutdownImminent(thermal)` реально эмитится; SoC↔MCU протокол + кодек + клиент (B08) + fail-safe-**модель** (B09). Источник событий — dev-mock (`SetTemp`/`HangSoc`); реальный MCU/sysfs/cpufreq + рендер «перегрев» в Shell → HW/v0.5. ### `ru.shturman.Settings` — конфигурация и состояние - **Методы:** `Get(key) → value`, `Set(key, value)`, `List(prefix) → [key]`, `Reset(key)`. diff --git a/docs/domains/b-power-lifecycle.md b/docs/domains/b-power-lifecycle.md index 3aa4471..6cd87c6 100644 --- a/docs/domains/b-power-lifecycle.md +++ b/docs/domains/b-power-lifecycle.md @@ -10,8 +10,15 @@ **Реализация (v0.3):** срезы **B01–B07** реализованы — чистый `PowerFsm` (§2: `off↔accessory↔running→shutting-down {abortable→committed}→off`, abort до PONR) + сервис `ru.shturman.Power` оживлён из FSM (grace-таймер + durable-barrier `sync` на commit), watchdog/save-time-конфиг. **VM-модель:** abort/PONR в Lima = stop+umount+remount, power-cut = -SIGKILL+`fsck`. Аппаратное (MCU/hold-up/heartbeat/`safe-to-cut`/fail-safe-таймер) и выбор **B08/B09** → **v0.4**; -sleep/wake/battery-cutoff — каркас (no-op), тело → v1/v2 (§7). Спека: `docs/specs/v0.3-power-safe.md`. +SIGKILL+`fsck`. sleep/wake/battery-cutoff — каркас (no-op), тело → v1/v2 (§7). Спека: `docs/specs/v0.3-power-safe.md`. + +**Реализация (v0.4):** срезы **A12/B08/B09/B10** — софт/модель. Тепло (§4/§1a): чистая `ThermalPolicy` (банды + +гистерезис) → `Event::ThermalTrip` (реюз FSM) + abort `ThermalCleared`; `TempSource`/`Throttler` абстракции (VM mock/noop, +реальный sysfs/cpufreq + числовые пороги → RK3588). MCU (§5/§6): протокол `SocToMcu`/`McuToSoc` + кодек (CRC16/replay/ +desync-guard) + `CoprocessorClient` (heartbeat/wait-for-completion/`safe-to-cut`); **B09 fail-safe-таймер — модель** +(`MockCoprocessor`: hang/budget → `Event::FailsafeCut` → off). `ru.shturman.Power` += `ThermalState`/`ThermalChanged` +(рендер «перегрев» → v0.5). **Физический выбор B08/B09** (MCU vs supercap-only), реальный UART/MCU-чип/fail-safe-таймер, +supercap-only-путь → **HW-bring-up-подфаза**. Спека: `docs/specs/v0.4-mcu-thermal.md`. --- @@ -200,7 +207,8 @@ power-эффектом; ни одно SoC-сообщение не должно ( ## 12. Открытые вопросы - 🟡 **MCU-копилот vs supercap-only** (hardware §3, **B08/B09**) — определяет владельца ACC/watchdog, **наличие - независимого бэкстопа и fail-safe-снятия при зависшем SoC**, и доступность scheduled-wake. **→ v0.4** (вероятно нужна аппаратная проверка). + независимого бэкстопа и fail-safe-снятия при зависшем SoC**, и доступность scheduled-wake. Протокол/кодек/клиент + + fail-safe-**модель** реализованы в **v0.4** (софт); **физический выбор + железо → HW-bring-up-подфаза** (нужна плата). - ◻️ **Протокол SoC↔MCU** (UART/I2C/GPIO, формат, keepalive, политика тишины-линка, replay-защита) — shutdown-подмножество уже специфицировано в §4/§5, остальное здесь. - ◻️ **Бюджет разряда АКБ** (sleep, ACC-off listening, battery-cutoff порог) — числа с hardware.