Qt-removal R0: foundations - Python backend, single SPA, native pywebview shell, burn-down gate#99
Merged
Merged
Conversation
…down gate Per doc/QT_REMOVAL_PLAN.md phase R0 (terminal goal: ZERO PySide6/Qt): - backend/: FastAPI app + session-scoped WebSocket event bus carrying the same versioned full-state-snapshot + named-intent wire semantics as the IslandBridge layer it succeeds; static serving of the SPA build; /api/health; 14 pytest cases (bus + WS endpoint). - web_ui/src/app: the single-SPA target consolidating the islands (GRAPHLINK_ISLAND=app builds to dist/app). WS transport module with auto-reconnect/re-subscribe (9 tests), token-driven shell layout, live system panel. - graphlink_island_codegen.py: emits web_ui/src/lib/api-contract/topics.ts, the SPA's topic->type/validator registry derived from the same schema registry (--check enforced). - graphlink_desktop.py: NATIVE pywebview/WebView2 window (not a browser, zero Qt) that boots the backend and opens the SPA. - tests/test_no_qt_anywhere.py + qt_burndown.json: THE permanent gate. Pin = 168 files importing Qt (90 source + 78 tests); any increase fails, any decrease must lower the pin in-commit; flips to zero-mode assertions (package uninstalled, undeclared) when the pin reaches 0. backend/, web_ui/, and graphlink_desktop.py are held to zero Qt from day one. Acceptance drive PASSED: native window, SPA served by the Python backend, live WS ping round-trip 4.1 ms. 17 pytest + 544 vitest green. Burn-down: 168 of 168 remaining (R0 adds only Qt-free code by design). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… SPA target - App.tsx: drop the vestigial transportRef (ref write during render - react-hooks/refs error); the memoized transport was already the only consumer. - transport.test.ts: comma-expression assertion rewritten as a real assertion (no-unused-expressions error). - test_gl_vars_dev_css.py: src/app is a documented carve-out from the dev-only token rule - the SPA has no Qt host injecting :root tokens, so the shipped file IS its token source until R2's backend-served theme. Islands remain fully guarded. Local CI parity: npm run check exit 0; full offscreen pytest 1783 passed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dovvnloading
added a commit
that referenced
this pull request
Jul 22, 2026
…e R1 superset Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dovvnloading
added a commit
that referenced
this pull request
Jul 22, 2026
…ng the R2 superset # Conflicts: # backend/app.py # backend/canvas.py # backend/tests/test_app_ws.py # backend/tests/test_canvas.py # graphlink_app/graphlink_island_codegen.py # graphlink_app/graphlink_scene_payload.py # web_ui/src/app/App.tsx # web_ui/src/app/canvas/SceneCanvas.tsx # web_ui/src/app/canvas/sceneStore.test.ts # web_ui/src/app/canvas/sceneStore.ts # web_ui/src/app/styles.css # web_ui/src/lib/bridge-core/generated/scene-state.schema.json # web_ui/src/lib/bridge-core/generated/scene-state.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase R0 of the Qt/PySide6 full-removal plan
Terminal goal (the only definition of done): zero PySide6 anywhere, package uninstalled, full parity — enforced by a permanent gate test. This PR lands the foundations; it adds only Qt-free code and touches no existing behavior.
What's in it
backend/— FastAPI + session-scoped WebSocket event bus (versioned full-state snapshots + named intents, the direct successor of the QWebChannel IslandBridge wire contract), static SPA serving,/api/health. 14 tests.web_ui/src/app— the single-SPA target that will consolidate the ~19 islands (GRAPHLINK_ISLAND=appbuilds todist/app). New WS transport with auto-reconnect + re-subscribe (9 tests), token-driven shell.topics.tsgenerated from the existing island schema registry: topic → TS type + runtime validator,--checkenforced.graphlink_desktop.py— native desktop window via pywebview/WebView2. Not a browser, not Qt: boots the backend on a free localhost port and opens the app window.tests/test_no_qt_anywhere.py+qt_burndown.json, pinned at 168 Qt-importing files (90 source + 78 tests). Any increase fails CI; every removal must lower the pin in the same commit; at pin 0 the test additionally asserts PySide6 is uninstalled and undeclared.backend/,web_ui/, and the desktop entry are held to zero Qt from day one.Acceptance (per plan R0)
python graphlink_desktop.pyopened a native window with the SPA shell served by the Python backend ✅--checkclean ✅Burn-down: 168 of 168 remaining. (R0 builds the replacement rails; deletion begins as surfaces move over in R1+.)