Commit Graph

14 Commits

Author SHA1 Message Date
a3d35a7925 Phase 5 sub-commit 5: closure — done-criteria verified, status updated
All four planned sub-commits (4c15ac226a2b37) landed; the unplanned
docs/ rewrite (da04843) followed, lifting long-form material out of
the README into ten topic guides under docs/.

Done-criteria checked:
  - bin/php-qml-init scaffolds a runnable app (sub-commit 2).
  - DevConsole.qml + childLogLine signal surface child stdout/stderr
    with Ctrl+` toggle in skeleton + todo example (sub-commit 1).
  - README is end-to-end (60-second tour + links into docs/).
  - CHANGELOG v0.1.0 entry records every Phase 0–4a + Phase 5 deliverable.
  - `make quality` from framework/skeleton passes (16 tests, 45
    assertions; PHPStan clean; cs-fixer clean; qmllint warnings only;
    maker snapshots match).

Status line at PLAN.md head bumped to "Phases 0–5 complete; v0.1.0
ready to tag pending LICENSE selection + Gitea host URL substitution".

Two release-prep items remain — both user-driven, neither a framework
regression — captured in the new Phase-5-closure paragraph: choose +
add a LICENSE (composer.json still says "proprietary"), and replace
the `gitea.example/<org>/` placeholder URLs in CHANGELOG / README /
docs once the repo's published location is fixed. Tagging itself
remains the user's call per the release-process memory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 09:44:29 +02:00
26a2b3771b Phase 5 sub-commit 4: release readiness — README + CHANGELOG + status line
README.md rewritten to reflect actual onboarding (clone → php-qml-init
→ make dev / make appimage) instead of the planning-stage placeholder.
Phase status checklist now reflects 0–4a green and 5 in progress.

CHANGELOG.md created at repo root following Keep-a-Changelog
conventions, with a v0.1.0 entry that summarises Phases 0–4a plus the
Phase 5 polish work (DevConsole, php-qml-init, editor configs,
hot-reload docs). Date is TBD; tagging is the user's call.

PLAN.md gains a Status banner so it's obvious at a glance which phase
the implementation tracks against the design.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 21:30:08 +02:00
31bdac80e6 Detail Phase 5 scope: dev console + init script + hot-reload + v0.1.0 prep
Phase 5 closes out the remaining DX seams from PLAN.md §8: child-output
capture with an optional DevConsole.qml, a single-file `bin/php-qml-init`
bash script for scaffolding fresh apps (chosen over a Composer template
since the project mixes PHP and CMake/Qt — no clean Composer fit), the
hot-reload story documented and IDE configs shipped with the skeleton,
then a release-readiness pass (README, CHANGELOG.md) culminating in a
plausible v0.1.0 milestone — tagging stays user-driven per the
release-process feedback rule.

4 sub-commits. macOS / Windows packaging stays deferred to 4b / 4c.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 20:05:03 +02:00
3005815fe4 Phase 4a sub-commit 5: performance-smoke harness + 4a closure
examples/todo/tests/perfsmoke.sh asserts the PLAN.md §11 budgets
against the built AppImage:

  - Bundle size ≤ 200 MB (hard cap; ≤ 120 MB target)
  - Cold start ≤ 2000 ms from launch to first /healthz 200
  - Idle RSS (host + descendants in the process group) ≤ 200 MB after
    a 2 s settle.

Each budget is overridable via env (PERF_COLD_START_MS etc.) for slow
shared CI runners; defaults are the strict numbers from the plan. Runs
the AppImage under xvfb-run when DISPLAY is unset; falls back to
QT_QPA_PLATFORM=offscreen otherwise (the build script already bundles
libqoffscreen.so via EXTRA_PLATFORM_PLUGINS).

Wired into:
  - examples/todo/Makefile  → `make perf`
  - .gitea/workflows/release.yml → runs after AppImage build, before
    zsync + upload, with cold-start budget bumped to 4 s for CI.

CI now also installs zsync + xvfb in one step.

examples/todo/README.md gains an "AppImage packaging (Phase 4a)"
section walking through `make appimage`, bundled-mode behaviour, the
auto-update QML hooks (BackendConnection.checkForUpdates() / applyUpdate()),
and `make perf`.

PLAN.md §13 Phase 4 marked **4a closed**. 4b (macOS) and 4c (Windows)
stay stubs until their runners + certs exist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 20:01:52 +02:00
d8726bac94 Fix CI: bump PHP requirement to ^8.4 (Symfony 8 enforces it)
CI was failing on the Install-bundle-dependencies step because
shivammathur/setup-php was installing 8.3 while Symfony 8.x dependencies
declare php >= 8.4. Local composer install worked because the dev box
runs PHP 8.5.5; CI doesn't.

Bumps:
  - framework/php/composer.json
  - framework/skeleton/symfony/composer.json
  - examples/todo/symfony/composer.json
  - .gitea/workflows/ci.yml         php-version: '8.3' → '8.4'
  - .gitea/workflows/release.yml    same
  - PLAN.md §13 Phase 1 *Detailed scope* PHP minimum row

PHPStan / cs-fixer / PHPUnit stay green locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 19:53:00 +02:00
ccd2f1b27c Detail Phase 4 scope; split into 4a (Linux now) / 4b (macOS) / 4c (Windows)
Honest scoping: macOS and Windows packaging carry hard operational
prerequisites (self-hosted runners, Apple Developer + Authenticode certs)
that can't be solved from a Linux dev machine. Phase 4a delivers the full
Linux pipeline now; 4b and 4c wait until those prerequisites land.

4a sub-commits:
  1. Bundled-mode startup (auto-detected: no BRIDGE_URL → spawn child,
     per-session secret, first-launch migrations into XDG data dir)
  2. AppImage recipe (packaging/linux/build-appimage.sh + make appimage)
  3. Linux release.yml on v* tags (Gitea Release + SHA256SUMS + appcast)
  4. AppImageUpdate + BackendConnection.checkForUpdates()
  5. Performance-smoke harness + 4a phase closure

The framework code stays platform-agnostic — only the packaging layer
is per-OS. 4b / 4c entries get filled into PLAN.md when their runners
and certs become available.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 16:32:20 +02:00
20162234d9 Detail Phase 3 scope: ReactiveObject + 2 makers + todo app + tests
Some checks failed
CI / Quality (push) Failing after 1m26s
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) <noreply@anthropic.com>
2026-05-02 15:06:11 +02:00
030502ca38 Phase 2 sub-commit 3: full Update Semantics + ReactiveListModel + AppShell
Some checks failed
CI / Quality (push) Failing after 1m45s
BackendConnection's ConnectionState enum is now Connecting / Online /
Reconnecting / Offline (PLAN.md §5). The probe loop tracks the first
failure since the last Online and transitions to Reconnecting on any
failed probe, then to Offline once the configurable threshold (30 s
default) is exceeded. The Error state is gone; Reconnecting + the
exposed `error` string subsume its UI role.

ReactiveListModel is the headline QML type:

- QAbstractListModel that GETs `baseUrl + source` for an initial JSON
  array and then keeps in sync via an internal MercureClient subscribed
  to `topic`.
- Role names are derived dynamically from the first row's keys plus an
  internal `pending` boolean role used by optimistic mutations.
- Diff application: upsert (insert-or-update), delete, replace; gap
  detection via the envelope `version` field with auto re-fetch.
- `invoke(method, path, body, optimistic)` is the optimistic command
  primitive. Generates an Idempotency-Key, applies the local diff,
  POST/PATCH/DELETEs with that key, and resolves on the matching
  Mercure echo (correlation-key matched in ModelPublisher's envelope).
  Rolls back and emits commandFailed on 4xx/5xx, commandTimedOut after
  10 s without an echo. Phase 4 packaging will surface configuration
  for the timeout.

AppShell.qml is the optional convenience root:

- Reads BackendConnection.connectionState.
- Reconnecting → top banner.
- Offline → modal overlay with the error string and a Retry button
  (calls BackendConnection.restart()).
- Wraps user content via `default property alias content`.

Apps that want full chrome control can skip AppShell entirely; the
skeleton's Main.qml keeps its own status display for demonstration
and is unaffected.

ReactiveObject (single-entity twin of ReactiveListModel) is intentionally
deferred — same envelope handling, smaller surface; will land in Phase 2
follow-up or Phase 3 alongside the todo example. Cursor pagination is
similarly deferred (the Phase 2 done criterion uses small lists).

Smoke tested: /healthz + /api/ping round-trip cleanly, zero Mercure 401s,
clean shutdown. composer quality stays green (16 tests, 45 assertions).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 02:40:12 +02:00
10d10d675d Phase 2: switch default ID type to UUIDv7
Some checks failed
CI / Quality (push) Has been cancelled
Makes the time-ordered, distributed-friendly UUIDv7 (via symfony/uid)
the framework's default. Auto-increment integers remain available via
an explicit --int-id flag on the maker.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 02:21:01 +02:00
e0dc209896 Detail Phase 2 scope: 5 sub-commits, Doctrine ORM 3 + SQLite, headline maker
Some checks failed
CI / Quality (push) Has been cancelled
Adds a stack-additions table (ORM, dev DB, default ID type, pagination
strategy, Doctrine→Mercure trigger), a 5-step sub-commit sequence, and
the done-criteria for Phase 2. Defaults baked in (subject to user
override before sub-commit 1 starts):
- Doctrine ORM 3.x with DoctrineBundle + DoctrineMigrationsBundle
- SQLite at var/data.sqlite for dev
- Auto-incrementing int IDs by default; the maker takes a UUIDv7 flag
- Cursor-based pagination, default page size 50
- Synchronous postPersist/postUpdate/postRemove subscribers

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 02:19:04 +02:00
eafe12b588 Phase 1 sub-commit 2: Symfony bundle internals
All checks were successful
CI / Quality (push) Successful in 4s
Bundle code for php-qml/bridge: BridgeBundle (AbstractBundle, autoloads
config/services.yaml), Publisher (thin wrapper over Mercure HubInterface
that enforces envelope-as-JSON), SessionAuthenticator (bearer-token
custom Symfony authenticator with problem+json failures), and
HealthController (GET /healthz readiness probe).

Composer constraints bumped to Symfony ^8.0 across the board (per user
request); mercure component to ^0.7. PHPUnit 11 suite covers Publisher
publish + private flag and SessionAuthenticator support/auth/failure
paths — 8 tests, 22 assertions, all green.

PLAN.md §13 updated to record the Symfony 8 minimum.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:05:19 +02:00
16dfffd916 Detail Phase 1 spec; switch task runner from Task to Make
Adds naming/identifier table, directory layout, eight sub-commits, and
done criteria for Phase 1. Also swaps the planned Taskfile for a plain
Makefile across §8 and §13 — Make is universal and skips a dependency
that openSUSE Tumbleweed doesn't package.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 00:25:58 +02:00
0b394510bc Expand Phase 0 with a concrete spike spec
Adds the spike's layout, flow, hardcoded values, and done criteria so
implementation has a clear target. No code yet.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 00:03:15 +02:00
8faaf764eb Add initial plan and README
Architectural design (PLAN.md) and project intro committed before any
implementation begins.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 23:58:26 +02:00