feat(v0.6): Lima E2E зелёный с нуля + shell software-render screenshot

План 5 ч.2: поднял Lima-VM и довёл сквозной E2E до зелёного из чистого yaml
(just vm-reset && just e2e — exit 0). Приёмка §9.4 (v0.1 + v0.6 + шагающий скелет).

Shell (lib+bin split):
- режим --screenshot <path>: headless software-render первого кадра в PNG
  (Slint software-renderer, без дисплея/композитора, §6); TDD-тест «кадр не
  пустой + тема отражена», зелёный и на dev-Mac, и в VM (Linux).
- shturman-shell.service → oneshot software-render → /run/shturman/frame.png
  (RemainAfterExit → is-active детерминированно, без хрупкого weston;
  живой weston-shell — v0.5). just shell-frame — инспекция кадра.

E2E (tests/e2e/run.sh, двухфазно pre→reboot→post):
- /data+power-safe опции, volatile-tmpfs, first-boot идемпотентность, per-unit
  active, имена на шине + GetPowerState, fake-ACC SetAcc→AccChanged, первый кадр
  PNG, base-бюджеты (journald volatile / zram / oomd / fake-hwclock→/data /
  eMMC-прокси), персист Settings + machine-id every-boot bind после reboot.

Провижининг (lima/shturman.yaml) — правки по реальным ошибкам Lima:
- build-deps Slint/winit на Linux (libfontconfig1-dev/libxkbcommon-dev/libwayland-dev);
- linux-modules-extra (zram/vcan не в vz-ядре); systemd-oomd; rm стокового
  /etc/fake-hwclock.data (A11); VM-локальный CARGO_TARGET_DIR.

Док-синхронизация (спека §13/§8.1/§7.5 + CLAUDE.md): швы реализации, eMMC-порог
T=4096 сект, fake-hwclock masked-в-Lima, dev-mock policy не нужен.

Перф-вердикт — на RK3588 (в VM — функционально, performance §2). just ci зелёный.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Alexander <akotenev2003@gmail.com>
This commit is contained in:
2026-06-24 17:14:31 +03:00
parent a9aad21636
commit 9b87751ab8
11 changed files with 609 additions and 209 deletions
+36 -7
View File
@@ -390,9 +390,10 @@ Oneshot-бинарь под `shturman-firstboot.service` (`ConditionPathExists=!
по мере событий).
- **eMMC write-min (A11):** дисциплина (volatile-логи, tmpfs-транзиент, zram, без спама в `/data`).
**Измеримая проверка (детерминированный VM-прокси):** дельта записанных секторов на loop-устройстве `/data`
(`/proc/diskstats`) за фиксированное окно простоя (напр. 60 c после boot-settle) **ниже порога T** (🟡
калибруется) + **нет периодических флашей вне allow-list писателей** (`fake-hwclock`, `Settings` on-Set);
всё прочее → fail. Абсолютный байт-бюджет — вердикт на RK3588 (performance §2).
(`/proc/diskstats`, поле 10) за фиксированное окно простоя (E2E: `E2E_IDLE_SECS`=20 c после boot-settle) **ниже
порога T** + **нет периодических флашей вне allow-list писателей** (`fake-hwclock`, `Settings` on-Set); всё прочее
→ fail. **Калибровка (Lima, 2026-06-24): ~80104 сектора/20 c простоя; порог T = 4096 секторов (~2 МБ/окно),
env `E2E_EMMC_MAX_SECTORS`.** Абсолютный байт-бюджет — вердикт на RK3588 (performance §2).
### 7.6 systemd-оркестрация (A15)
@@ -419,11 +420,18 @@ Oneshot-бинарь под `shturman-firstboot.service` (`ConditionPathExists=!
«VM лёгкая»; правится локально); `mounts:` репозиторий **writable** (правим на хосте — собираем в VM).
- **provision (system):** установить пакеты (`systemd`, `dbus`, `pipewire` + WirePlumber [задел v1],
`weston` + `weston-screenshooter`, `can-utils`, `rustup`/toolchain, `python3`+venv, **`systemd-zram-generator`**,
`fake-hwclock`, кириллические шрифты); `modprobe vcan` + `ip link add vcan0`;
`fake-hwclock`, кириллические шрифты + **build-deps Slint/winit на Linux**: `libfontconfig1-dev`/`libxkbcommon-dev`/
`libwayland-dev` — иначе `cargo build` shell падает на `yeslogic-fontconfig-sys`); **`linux-modules-extra-$(uname -r)`**
(модули `zram`/`vcan` НЕ входят в базовый vz-образ Lima); `modprobe vcan` + `ip link add vcan0` (vcan может
отсутствовать в vz-ядре — VM↔HW-граница, как раньше);
создать loopback-`/data` (ext4 + power-safe-опции) и завести **постоянный** `data.mount`/fstab + tmpfs-overlay;
override `fake-hwclock` пути на `/data`; разложить `systemd/`-юниты + journald/zram-generator/oomd drop-ins +
dbus policy (прод `ru.shturman.conf` + dev-only `ru.shturman.dev.conf`); включить `shturman.target`.
*(screenshot кадра в CI — через Slint software-renderer, без пакета grim; см. §6.)*
override `fake-hwclock` пути на `/data` + удалить стоковый `/etc/fake-hwclock.data` (A11; сервис в Lima **masked**
Lima сам синхронит время, на HW юнит размаскирован и читает `FILE` через `EnvironmentFile`); разложить
`systemd/`-юниты + journald/zram-generator/oomd drop-ins + dbus policy (прод `ru.shturman.conf`; dev-mock
`ru.shturman.dev.PowerMock1` — интерфейс на объекте `ru.shturman.Power`, **отдельное dev-имя/policy НЕ нужны**,
покрыт `send_destination`); включить `shturman.target`.
*(screenshot кадра в E2E — через Slint software-renderer → PNG, без weston/grim; `shell.service` в v0.6 =
oneshot-screenshot, живой weston-shell — v0.5; см. §6.)*
- **reference-«BSP» (A16):** в dev это **Lima-профиль** (дев-таргет). Реальный reference-BSP (DT overlay +
HAL + DBC) — на HW (a-base §13), вне VM.
- **Подъём:** `just vm-up``limactl start --name=shturman lima/shturman.yaml` (создание+provision);
@@ -663,6 +671,27 @@ SOFTWARE.
- **`principles #12`**: уточнить LGPL — гранулярно (динамическая/системная линковка допустима), а не blanket;
согласовать с `deny.toml`/§3.
**Реализация (План 5 ч.2 — v0.6 Lima E2E, 2026-06-24, проверено в Lima):**
- **`shell.service` (§6/§7.6):** v0.6 = **oneshot software-render → PNG** (`shturman-shell --screenshot
/run/shturman/frame.png`, tmpfs/volatile; `RemainAfterExit=yes` → `is-active=active` детерминированно, без
хрупкого weston). Живой weston-shell (`ui.run()`) — **v0.5**. `shturman-shell` стал lib+bin (рендер тестируем
headless и на dev-Mac). Доки §6/§7.6 уже называют software-renderer основным — синхронизировано.
- **Провижининг Lima (§8.1):** добавлены build-deps `libfontconfig1-dev`/`libxkbcommon-dev`/`libwayland-dev`
(Slint/winit на Linux тянут fontconfig — на macOS CoreText, поэтому всплыло только в VM) +
`linux-modules-extra-$(uname -r)` (модули `zram`/`vcan` не в базовом vz-ядре). vcan-модуль всё равно может
отсутствовать — `zram` ставится, `vcan` — best-effort (Vehicle Sim v2).
- **fake-hwclock (§7.3):** сервис в Lima **masked** (Lima синхронит время с хоста) → override через
`EnvironmentFile` не срабатывает в VM; скрипт читает `FILE` из env, E2E демонстрирует запись в `/data` напрямую.
Стоковый `/etc/fake-hwclock.data` удаляется в провижининге (A11). На HW юнит размаскирован — механизм тот же.
- **eMMC-порог T (§7.5):** калибровка ~80104 сект/20 c → **T=4096 сект**; окно простоя 20 c (не 60).
- **CARGO_TARGET_DIR (§8.2):** E2E/сборка в VM пишут в **VM-локальный** target (`~/.cache/shturman/target`), не в
смонтированный `target/` — иначе конфликт Darwin↔Linux-артефактов + медленный virtiofs.
- **dev-mock policy (§5.1):** отдельный `ru.shturman.dev.conf` для `PowerMock1` **не нужен** — это интерфейс на
объекте `ru.shturman.Power` (имя то же), покрыт `send_destination=ru.shturman.Power`. Файл зарезервирован на
случай отдельного dev-**имени** на шине.
- **E2E reboot (§9.3.4):** двухфазно `just e2e` (pre → guest-reboot Lima → post); персист Settings + machine-id
every-boot bind проверяются после реального ребута. `just run` = только pre (без ребута).
---
## 14. Дальше по ритму