# Progress Where the project stands, and what happened in each session. Newest first. The process is in CLAUDE.md ("Working rules"). ## Current state - **Implementation iteration 1 (DSH-1 and configuration), phase 3 (implementation) done, waiting for the user's approval.** All plan steps are implemented and committed; next is phase 4, testing on the Frame (plan item 10). - Started by SteamVR, the app now logs to `logs/frame-assistant.log` in the install folder: the manifest passes `--log-file` (CFG-2 wants the settings error in a log file). Whether SteamVR on the Frame honours the manifest's `arguments` is checked in phase 4. ## Next steps Requirements and design cover the whole MVP; it is **implemented in four small iterations** (D37), each with implementation, testing and assessment: | Iteration | Content | Platform change | Checked by | |---|---|---|---| | 1 | DSH-1: HA web UI (Qt WebEngine) in a dashboard tab; configuration (D34) with start-up hook and `--config` | start-up hook (D21), WebEngine initialisation before the `QGuiApplication` | HA web UI in the tab on the Frame; result documented | | 2 | MQTT client (own thread), HA device with discovery and availability, libmosquitto in the package, status display UI-1 | modes (D22) | device appears in HA, online/offline right, reconnect works | | 3 | OpenVR wrappers and the 13 sensor entities | `--desktop` with optional SteamVR (D22) | sensor values in HA on the Frame | | 4 | notification manager, `notify` entity, world overlay | world overlay, premultiplied flag (D25) | notification from HA in VR, also in a game | ### Plan for implementation iteration 1: DSH-1 and configuration Goal: a second dashboard tab **"HA Dashboard"** shows HA's web UI at the URL from the configuration; what works out of the box is tested and documented. The main tab stays "Frame Assistant". Platform (`vrdashboard_core`): 1. Start-up hook `prepare()` (D21). 2. App-specific command-line options (D38): the base constructor takes an optional list of extra `QCommandLineOption`s, adds them to parsing and `--help`, and exposes their values. App: 3. `QtWebEngineQuick::initialize()` in `main.cpp` before the app object (D39); no platform change. 4. Configuration (`src/config/`): immutable value plus `load(path, &error)`, complete per D34; path from `--config`, else `$XDG_CONFIG_HOME` or `~/.config/frameassistant/config.json`; loaded in `Dashboard::prepare()` (overlay and desktop modes). 5. HA web UI (`src/ha/HaWebUi`, D18): holds the URL (injected), exposed to QML as a singleton owned by `Dashboard`; a named, persistent WebEngine profile under `~/.local/share/frameassistant/` so the HA login survives restarts (D39). 6. New surface `dashboard` ("HA Dashboard"), QML root `HaDashboard.qml` with a `WebEngineView`; without a URL it shows a hint. 7. Build: `find_package(Qt6 … WebEngineQuick)`; `qt6-webengine-dev` (native and `:arm64`) in the containers; a new static library for app logic (configuration, HaWebUi) that tests link. Tests (D30): 8. `tst_config`: valid file, missing required fields, invalid JSON, wrong types, defaults, derived and explicit `ha_unique_id`, unknown keys, `--config`. 9. Platform: `tst_surfaces` extended for `prepare()` (success/abort) and extra options. 10. Manual, results documented: host `--desktop`; Frame desktop mode over RDP; Frame in VR with Vulkan and OpenGL: page loads, laser click, scrolling, SteamVR keyboard in the page's input fields, login kept after restart; CPU/GPU while the tab is open. 11. `clang-format` clean, `ctest` green; `container-test.sh` only if Vulkan code is touched. Docs: 12. README (configuration file, `--config`, new tab), ARCHITECTURE.md and CLAUDE.md (new hook, app options), THIRD_PARTY_NOTICES (Qt WebEngine from the system), STEAM-FRAME.md (results), PROGRESS.md. Known limitation: the bundled-Qt package does not support WebEngine in this iteration. ## Log ### 2026-10-05: requirements approved - User approved REQUIREMENTS.md including the priorities (D13). Phase 2 started. - Q4 decided: libmosquitto, shipped in the package (D14). Qt MQTT ruled out: private Qt API requires the exact Qt version. Checked on the Frame: no MQTT library installed; libssl/ libcrypto 3 and libcjson 1 present. - HA discovery: own small layer on QJson, device-based discovery (D15); hacpp and the embedded libraries rejected. - Checked on the Frame which Qt modules, plugins and audio/network tools exist; library list per requirement in REQUIREMENTS.md Appendix C. Notable: Qt WebEngine and Qt WebSockets are present (relevant for Q2/Q3). - libmosquitto ABI check: Debian's 2.0.21 needs at most `OPENSSL_3.0.0`/`GLIBC_2.34`; the Frame has OpenSSL 3.2.1 and glibc 2.39. No libcjson dependency. D14 holds. - Phase 3 of implementation iteration 1: - Platform: `prepare()` hook and app-specific command-line options, tested in `tst_surfaces` (incl. `surfaces_prepare_fail`). - Settings file (`src/config/`, new library `frameassistant_lib`), `--config`; `tst_config` (37 cases). `config.example.json` in the package; README.txt explains the set-up. - "HA Dashboard" tab: `WebEngineView`, `HaWebUi` with a persistent profile, WebEngine initialisation in `main()`. Host: desktop mode loads a local test page, profile data lands in `~/.local/share/frameassistant/webengine`; snapshot renders both tabs. - Build containers with Qt WebEngine. Cross build: the aarch64 binary needs no private Qt symbols, at most `Qt_6.8` and `GLIBC_2.34`. Container tests 8/8 (incl. Vulkan with validation layers, no messages). - Snags: moc misses classes in files with raw strings containing `//` (CLAUDE.md); generated QML type registration includes headers by file name; Qt ≥ 6.9 hints at `WebEngineProfilePrototype` (not in the Frame's 6.8). Deviations: `HaWebUi` lives in the app, not the library; the password warning needs a password in the file. - Log file for SteamVR-started instances: the manifest passes `--log-file logs/frame-assistant.log` (user's choice among: default log path in the app, manifest argument, document only). - Not verified yet: WebEngine with a URL in the off-screen pipeline (Frame, phase 4); the bundled package (not supported for WebEngine in this iteration). - Plan for implementation iteration 1 approved; phase 3 started. - Plan for implementation iteration 1 written; new tab "HA Dashboard" (D38, D39). - MVP implemented in four iterations; DSH-1 first, at the user's wish (D37). - NFR-3 measurement method, manual in the MVP (D36). MVP details done. - Shipping libmosquitto (D35). - Configuration file format (D34). - MVP notification: `notify` entity with first line as title; JSON command later (D33). - HA MQTT interface: ids (D31), topics, retain, availability (D32), MVP entity list. - Test strategy in four levels (D30). High-level architecture done. - Threads: MQTT client in its own thread, everything else incl. OpenVR in the main thread (D29). - DSH-1 split: web UI out-of-the-box test in the MVP, full dashboard as DSH-2 (D28). - Overlays: two kinds (D25), one overlay for all notifications (D26), MVP placement "spawn in front, then stay" (D27). Researched notification UI in VR (DESIGN.md, Appendix A). Found: premultiplied-alpha flag missing in the platform. - HA channels: MQTT for everything device-related; dashboard channel decided with Q2/Q3 (D24). - Entities: one class per HA entity type, native types preferred, own service only as fallback (D23). Found: MQTT `notify` drops the title. - Start-up hook `prepare()` in the platform (D21); modes, `--desktop-novr` and `--config` (D22). - New requirement UI-1: status display in the main tab (D20). - The user installed `mosquitto` on the dev host, so native builds can use libmosquitto. - Started docs/DESIGN.md: one process (D16), three layers (D17), HA-centric object classes (D18). HA side: FrameAssistant needs only stock HA; how the user wraps commands (scripts, pyscript) is up to them (NFR-6 unchanged). - Agreed to settle the high-level architecture first (list under "Next steps"), before component details. - Stay with the Debian build container: an Arch container wouldn't match SteamOS's own package versions (private repos, rolling Arch) and has no arm64 multiarch for cross builds. ### 2026-10-04/05: project set-up and requirements - Copied the vrdashboard template. Removed what the app doesn't need: - `examples/` (diagnostics app) and the `VRDASH_BUILD_EXAMPLES` option - the Frame test package (`scripts/package-frame-test.sh`, `docs/FRAME-TESTING.md`, screenshots) - the demo UI (`src/qml/DemoPage.qml`) `Main.qml` shows a placeholder card. - Named the app **FrameAssistant**, "Steam Frame companion for Home Assistant": - CMake project `frameassistant`, executable `frame-assistant` - app key `net.matzman.frameassistant`, tab "Frame Assistant", QML module `FrameAssistant` Names rejected: - "Steam…" and "…Home Assistant": trademarks - "HASS…": the user dislikes it, because "Hass" is German for hate. - Agreed working rules (in CLAUDE.md): - explicit permission for everything; ask instead of assuming - iterative five-phase cycle; an informal "ok" approves a phase - document everything in Markdown in `docs/` - `git init`. Baseline commit `4a5b090`. - Requirements engineering (several question rounds with the user). The results are in REQUIREMENTS.md: - decisions D1–D12 - 51 requirements - research on OpenVR data sources (Appendix A) - Checks: `native-debug` builds, `ctest` passes 6/6 (Vulkan surface test skipped, no Vulkan on this host), `--snapshot` renders.