From 20162234d95d94eb7e3b97efe93d031cb3499680 Mon Sep 17 00:00:00 2001 From: magdev Date: Sat, 2 May 2026 15:06:11 +0200 Subject: [PATCH] Detail Phase 3 scope: ReactiveObject + 2 makers + todo app + tests Adds a 5-step sub-commit sequence and the done-criteria for Phase 3. Defaults baked in (subject to user override before sub-commit 1): - Ship `make:bridge:command` and `make:bridge:window` only; defer `make:bridge:event` and `make:bridge:read-model` since the todo app doesn't use them. Phase 3.x can pick them up. - Multi-window + crash-recover validated via a bridge-integration test that boots a real FrankenPHP child + offscreen Qt host. qmltestrunner smoke covers RestClient.qml and AppShell.qml. - Maker-output snapshot test in CI catches silent generator drift by diffing fresh maker runs against the checked-in baseline. Co-Authored-By: Claude Opus 4.7 (1M context) --- PLAN.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/PLAN.md b/PLAN.md index 2246541..bd3f41d 100644 --- a/PLAN.md +++ b/PLAN.md @@ -694,6 +694,53 @@ Phase 2 turns the framework from "transports work" into "you can ship a reactive - Multi-window test passes. - Crash-and-recover test passes (covers `tokenRotated` and `Reconnecting` → `Online` recovery). +#### Phase 3 detailed scope + +Phase 3 turns the framework from "the smallest reactive resource" into "a real application that exercises every architectural primitive". The POC todo app becomes the artefact a sceptical reader can clone, run, and use to evaluate the framework. + +**Maker scope:** + +| Maker | Status | +| --- | --- | +| `make:bridge:resource` | shipped (Phase 2) | +| `make:bridge:command` | **shipped in Phase 3** — todo app uses it for "mark all done" | +| `make:bridge:window` | **shipped in Phase 3** — todo app uses it for the second window | +| `make:bridge:event` | **deferred** — not required by the todo app; Phase 3.x or beyond | +| `make:bridge:read-model` | **deferred** — same | + +**Sub-commits (each ends runnable):** + +1. **`ReactiveObject` C++ type.** Single-entity twin of `ReactiveListModel` with the same envelope handling, a `pending` indicator on the bound properties, and an optimistic `invoke()`. The todo app's edit form binds to it; opening "the same todo" in a second window shows in-flight changes converging. +2. **`make:bridge:window` + `make:bridge:command` makers.** Window maker generates `Window.qml` using `AppShell` boilerplate and registers it with a small window registry on the C++ host so it's openable from menus or single-instance launch-arg dispatch (PLAN.md §3, §6, §7). Command maker generates a Messenger command + handler + controller route on the PHP side and a QML helper on the bridge module. Templates excluded from PHPStan / cs-fixer the same way the resource maker's are. +3. **`examples/todo` app — built via the makers.** Standalone Composer/CMake project under `examples/todo/` derived from the skeleton with: + - `Todo` resource generated via `make:bridge:resource`, + - `MarkAllDone` command generated via `make:bridge:command`, + - Main window with a list, add input, toggle/delete actions, and an "open second window" menu item, + - Second window scaffolded via `make:bridge:window`, sharing the same `ReactiveListModel` so both windows update live. + + No handwritten glue between PHP and QML — every cross-side wire is maker-generated. Verifies the convention test from Phase 2 holds for a non-trivial app. +4. **Multi-window + crash-and-recover tests.** Bridge-integration test that boots a real FrankenPHP child plus an offscreen Qt host (CI-friendly, headless) and: + - Triggers a CRUD round-trip; asserts the QML model reflects it within 100 ms. + - Opens a second window; asserts both models converge. + - Kills the FrankenPHP child mid-test; asserts `connectionState` transitions Online → Reconnecting → Online on restart with no model corruption. + + Plus a `qmltestrunner` smoke test for `RestClient.qml` and `AppShell.qml` so QML-side unit tests have a place to grow. CI's `quality` job invokes both. +5. **Maker-output snapshot test + phase closure.** CI step that re-runs `make:bridge:resource Todo`, `make:bridge:command MarkAllDone`, `make:bridge:window TodoWindow` against a clean copy of the skeleton and `git diff --exit-code`s against the checked-in baseline. Catches silent generator drift. PLAN.md updated; `examples/todo`'s README documents the multi-window and crash-recovery procedures so a human can reproduce them too. + +**Deferred to Phase 3.x or Phase 4:** + +- `ReactiveObject` cursor pagination (the resource has too few rows to need it). +- `make:bridge:event` and `make:bridge:read-model` — no use case in the todo app yet. +- A full Squish / Qt Test end-to-end suite — out of scope; the bridge-integration test is the floor. + +**Done criteria:** + +- `examples/todo` is buildable (`make build`) and runnable (`make dev`) standalone. +- Two windows of the same app stay in sync within 100 ms. +- Killing FrankenPHP visibly flips both windows to `Reconnecting` / `Offline`; restart restores `Online` and re-fetches without dupes. +- `make quality` runs all Phase-2 checks plus the bridge-integration test, the qmltestrunner suite, and the maker-output snapshot test. +- `make:bridge:command` and `make:bridge:window` ship with the same template / quality-tooling exclusions as `make:bridge:resource`. + ### Phase 4 — Bundled mode, packaging, release CI, and auto-update - Add bundled-mode startup to `BackendConnection`: spawn the embedded `frankenphp`, generate per-session secret, run first-launch migrations.