Skip to content

Commit 4fa34ff

Browse files
author
Roy Lin
committed
feat: add zero-widget platform host contract
1 parent 147645c commit 4fa34ff

17 files changed

Lines changed: 3119 additions & 53 deletions

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ headless = []
9393
graphics = ["dep:a3s-graphics"]
9494
software-reference = ["graphics", "a3s-graphics/software"]
9595
gpu = ["graphics", "a3s-graphics/gpu"]
96+
platform-host = []
97+
host-macos = ["platform-host"]
98+
host-windows = ["platform-host"]
99+
host-linux-wayland = ["platform-host"]
100+
host-linux-x11 = ["platform-host"]
101+
host-linux = ["host-linux-wayland", "host-linux-x11"]
96102
authoring = [
97103
"dep:swc_atoms",
98104
"dep:swc_common",

README.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,20 @@ independently.
245245
- deterministic retained software rendering and an owned `wgpu` renderer
246246
boundary with asynchronous readback
247247

248+
### Zero-widget platform boundary
249+
250+
- opt-in `platform-host` contracts for top-level windows, presentation,
251+
un-targeted input, text/IME state, accessibility snapshots and actions,
252+
explicit system services, and ordered host events
253+
- stable `PlatformElementId` accessibility identity independent from the
254+
legacy control renderer and its `HostNodeId`
255+
- one bounded, validated revision transaction with prepare, atomic commit,
256+
rollback, monotonic ordering, and explicit teardown semantics
257+
- a deterministic `RecordingPlatformHost` with bounded event/history storage,
258+
commit-failure recovery, and sensitive diagnostic redaction
259+
- executable source and Cargo-feature firewalls proving the common contract has
260+
no Graphics, OS toolkit, or legacy renderer dependency
261+
248262
## Roadmap at a glance
249263

250264
| Milestone | State | Evidence or next gate |
@@ -255,7 +269,7 @@ independently.
255269
| M3 · Layout and Scene | Current | Generic calculator rectangle slice landed; full flex, stacking, redraw scheduling, cross-platform fingerprints, and thin-host presentation remain |
256270
| M4 · Text and interaction cutover | Planned | Shaping, glyphs, GUI-owned input, IME, accessibility bridges, overlays, and complete calculator scenarios |
257271
| M5 · Default cutover | Planned | Make self-drawn content the default, then delete the three legacy widget renderers |
258-
| H0-H5 · Thin platform hosts | Planned | Zero-widget host contract, shared window runtime, Win32/macOS/Wayland-X11 slices, and dependency-audited cutover |
272+
| H0-H5 · Thin platform hosts | H0 complete; H1 next | Zero-widget records, transactions, recording host, target feature markers, and dependency/source firewalls landed; shared window runtime is next |
259273
| T0-T5 · TSX native authoring | Proposed | Automatic JSX runtime, versioned Node-to-host session, state/event runtime, self-drawn native window, packages, and stable SDK |
260274

261275
The dependency-ordered plan and acceptance gates are in the
@@ -271,6 +285,9 @@ The default set is `headless + authoring + design-system + software-reference`.
271285
| `graphics` | Pinned A3S Graphics scene vocabulary without a renderer backend |
272286
| `software-reference` | Deterministic retained reference renderer; implies `graphics` |
273287
| `gpu` | Owned offscreen GPU renderer and readback path; implies `graphics` |
288+
| `platform-host` | H0 zero-widget records, transaction trait, recording host, and conformance tests; no Graphics or OS dependency |
289+
| `host-macos`, `host-windows` | H0 target markers over `platform-host`; OS shell implementations land in H2/H3 |
290+
| `host-linux-wayland`, `host-linux-x11`, `host-linux` | H0 target markers over `platform-host`; Linux implementations land in H4 |
274291
| `authoring` | SWC-backed RSX parsing, `ComponentCx`, and explicit component registries |
275292
| `design-system` | Built-in `rsx_ui` registry; implies `authoring` |
276293
| `appkit`, `gtk4`, `winui` | Legacy planning adapters retained for migration evidence |
@@ -286,6 +303,8 @@ cargo check --locked --no-default-features --features authoring --lib
286303
cargo check --locked --no-default-features --features graphics --lib
287304
cargo check --locked --no-default-features --features software-reference --lib
288305
cargo check --locked --no-default-features --features gpu --lib
306+
cargo check --locked --no-default-features --features platform-host --lib
307+
cargo test --locked --no-default-features --features platform-host --lib platform_host::
289308
```
290309

291310
## Platform hosts: migration baseline and target
@@ -395,7 +414,7 @@ src/
395414
|- drawing/layout_scene.rs
396415
| LayoutSnapshot to Graphics Scene lowering
397416
|- render_contract.rs executable field/role/event milestone inventory
398-
|- platform_host/ planned zero-widget OS shell and presentation boundary
417+
|- platform_host/ H0 zero-widget records, transactions, recorder, and validation
399418
|- backend/ + platform/ legacy execution/planning migration baseline
400419
`- *_native/ AppKit, GTK4, and WinUI control hosts during migration
401420

docs/platform-hosts.md

Lines changed: 82 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Self-Drawn Platform Host Architecture
22

3-
Status: planned. The all-content self-drawn direction is decided; the thin
4-
desktop hosts described here are not implemented yet.
3+
Status: H0 contract and dependency firewall complete; H1 shared window runtime
4+
is next. The desktop OS shells described here are not implemented yet.
55

66
Updated: 2026-08-01
77

@@ -30,20 +30,25 @@ or layout container with a toolkit widget.
3030

3131
## Current State and Gap
3232

33-
The repository currently contains two different generations of code:
33+
The repository currently contains three distinct layers:
3434

3535
1. `appkit_native/`, `gtk4_native/`, and `winui_native/` create toolkit
3636
controls. They provide migration evidence for behavior, input,
3737
accessibility, packaging, and real OS execution.
3838
2. `layout/` and `drawing/layout_scene.rs` form the new generic self-drawn
3939
path. The calculator already lowers into stable layout and scene records,
4040
and the software and offscreen GPU renderers have executable evidence.
41-
42-
The missing layer is a production window host that attaches the Graphics GPU
43-
renderer to a real top-level surface and returns OS services to the portable
44-
runtime without constructing content controls. The old control backends are
45-
frozen until this replacement passes its gates. They are migration inputs,
46-
not the target architecture and not a base for new TSX work.
41+
3. `platform_host/` is the H0 zero-widget boundary. It provides bounded window,
42+
presentation, raw-input, text-input, stable-id accessibility, and explicit
43+
system-service records; atomic revision transactions; a recording host; and
44+
executable dependency/source firewalls.
45+
46+
The next missing layer is the H1 shared runtime that connects committed layout,
47+
scene, hit-region, accessibility, and service state to the new host contract.
48+
Production H2-H4 hosts must then attach Graphics to real top-level surfaces and
49+
return OS services without constructing content controls. The old control
50+
backends are frozen until this replacement passes its gates. They are migration
51+
inputs, not the target architecture and not a base for new TSX work.
4752

4853
## Target Pipeline
4954

@@ -178,32 +183,63 @@ a fake host and by all three desktop shells.
178183
- avoid exposing native handles or arbitrary platform calls to components or
179184
the TSX process
180185

181-
## Planned Repository Shape
186+
## Repository Shape
182187

183188
```text
184189
src/platform_host/
185-
|- mod.rs
186-
|- contract.rs window, frame, event, and service records
187-
|- runtime.rs render/service transaction orchestration
188-
|- conformance.rs shared fake-host and zero-widget assertions
189-
|- macos/ NSWindow + custom NSView shell
190-
|- windows/ Win32 HWND shell
191-
`- linux/ Wayland primary + X11 fallback shell
190+
|- mod.rs public H0 boundary
191+
|- contract.rs revision transaction, presentation, events, host trait
192+
|- window.rs top-level window records only
193+
|- input.rs un-targeted pointer, key, and wheel records
194+
|- text_input.rs bounded IME/edit-session state and events
195+
|- accessibility.rs stable PlatformElementId tree, bounds, and actions
196+
|- system.rs typed clipboard, picker, URL, permission, menu services
197+
|- recording.rs bounded deterministic fake host
198+
|- validation.rs shared record validation
199+
`- tests.rs contract, recovery, redaction, and wire-shape tests
200+
201+
tests/platform_host_firewall.rs
202+
203+
Planned next:
204+
src/platform_host/runtime.rs
205+
src/platform_host/macos/
206+
src/platform_host/windows/
207+
src/platform_host/linux/
192208
193209
examples/self_drawn_calculator.rs
194210
src/bin/a3s_gui_host.rs
195211
```
196212

197-
The target Cargo feature names are planned as `host-macos`, `host-windows`,
198-
`host-linux-wayland`, and `host-linux-x11`, with an optional `host-linux`
199-
aggregate. They are not public features until H0 lands. None may enable or
200-
import `appkit-native`, `gtk4-native`, `winui-native`, or the legacy
201-
widget-planning modules.
213+
The `platform-host`, `host-macos`, `host-windows`, `host-linux-wayland`,
214+
`host-linux-x11`, and `host-linux` features landed in H0. The target features
215+
currently select the common contract only; OS dependencies arrive with their
216+
H2-H4 implementation. None enables or imports `appkit-native`, `gtk4-native`,
217+
`winui-native`, or the legacy widget-planning modules.
202218

203219
The new modules are created beside the legacy directories rather than by
204220
renaming a control backend. This makes accidental content-widget reuse visible
205221
and lets each old backend be deleted after its replacement evidence exists.
206222

223+
## H0 Transaction and Thread Contract
224+
225+
`PlatformHost` is intentionally thread-affine. The trait does not require
226+
`Send` or `Sync`, so an H2-H4 implementation can stay on its owning OS event
227+
loop. Every public record crossing the boundary is `Send + Sync` and contains
228+
no native or GPU handle.
229+
230+
The runtime prepares one complete `PlatformHostTransaction` at a monotonically
231+
increasing `PlatformHostRevision`. Validation runs before host mutation and
232+
enforces bounded command counts, finite geometry, stable accessibility ids,
233+
UTF-8 text ranges, sensitive-value rules, and unique per-revision presentation,
234+
accessibility, and system-request identities.
235+
236+
Commit atomically applies the pending revision. A failed commit leaves that
237+
revision pending so the owner must explicitly retry or roll it back; rollback
238+
does not advance the last committed revision. Shutdown rejects a pending
239+
transaction, releases queued events, and makes later operations fail. The
240+
recording host keeps bounded diagnostic history with text-input and sensitive
241+
clipboard payloads redacted while preserving byte lengths and command shape.
242+
207243
## Delivery Plan
208244

209245
The host track is named H0-H5. It is dependency-coupled to renderer milestones
@@ -237,7 +273,7 @@ accessibility gates require M4.
237273

238274
### H0 - Contract and dependency firewall
239275

240-
Status: next.
276+
Status: complete.
241277

242278
Deliverables:
243279

@@ -251,15 +287,27 @@ Deliverables:
251287
Gates:
252288

253289
- the contract contains no widget create/update/remove operation
254-
- platform-host records contain no `NativeElement`, portable style, Node,
255-
toolkit object, or `wgpu` handle
290+
- platform-host records contain no `NativeElement`, portable style, Node.js
291+
runtime value, toolkit object, or `wgpu` handle
256292
- semantic-only builds remain free of Graphics and platform dependencies
257293
- every host-facing record is bounded, deterministic, and `Send + Sync` where
258294
thread affinity does not require an owning executor
259295

296+
Evidence:
297+
298+
- all six H0/target marker features compile without a legacy renderer
299+
- the common `platform-host` dependency graph contains no Graphics or OS
300+
toolkit package
301+
- 13 unit tests cover validation, stable ids, wire shape, atomic revisions,
302+
commit failure, rollback, teardown, bounded storage, and redaction
303+
- three integration tests recursively audit source imports, Cargo feature
304+
edges, the public feature gate, and absence of widget CRUD
305+
- `just verify` runs the H0 compile, dependency-graph, contract, and firewall
306+
gates on every normal CI change
307+
260308
### H1 - Shared self-drawn window runtime
261309

262-
Status: planned after H0; depends on the M3 presentation boundary.
310+
Status: next; depends on the M3 presentation boundary.
263311

264312
Deliverables:
265313

@@ -415,17 +463,16 @@ or dependency-boundary evidence.
415463

416464
## First Reviewable Commit Sequence
417465

418-
1. Add H0 contract records, fake-host conformance, feature firewall, and tests.
419-
2. Add H1 shared frame orchestration and raw-surface presentation lifecycle.
420-
3. Present the rectangle-only shared calculator through the Windows host.
421-
4. Present the same rectangle-only calculator through the macOS host.
422-
5. Present it through Wayland, then add the separately gated X11 fallback.
423-
6. Land text shaping, editing, input/IME, and accessibility slices against the
466+
1. Add H1 shared frame orchestration and raw-surface presentation lifecycle.
467+
2. Present the rectangle-only shared calculator through the Windows host.
468+
3. Present the same rectangle-only calculator through the macOS host.
469+
4. Present it through Wayland, then add the separately gated X11 fallback.
470+
5. Land text shaping, editing, input/IME, and accessibility slices against the
424471
shared host contract, one subsystem at a time.
425-
7. Pass the full calculator cutover matrix on all three platforms.
426-
8. Delete WinUI/XAML, GTK4, and AppKit content-control code in independent
472+
6. Pass the full calculator cutover matrix on all three platforms.
473+
7. Delete WinUI/XAML, GTK4, and AppKit content-control code in independent
427474
platform commits while preserving the new shells.
428-
9. Switch defaults, examples, packaging, and documentation, then run the final
475+
8. Switch defaults, examples, packaging, and documentation, then run the final
429476
repository-wide dead-code and dependency audit.
430477

431478
Each commit must leave the tree buildable for its declared feature set. No

docs/roadmap.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ The repository already provides:
188188
- a shared calculator state model, reducer, RSX component tree, and three
189189
platform entrypoints
190190
- AppKit, GTK4, and WinUI control backends used as migration baselines
191+
- an H0 zero-widget platform-host contract with stable accessibility identity,
192+
bounded revision transactions, a recording host, target feature markers, and
193+
executable dependency/source firewalls
191194

192195
The independent Graphics repository has a versioned scene, stable draw IDs,
193196
canonical fingerprints, retained damage, affine transforms, clipping, opacity,
@@ -407,7 +410,7 @@ Acceptance gates:
407410

408411
## P0-H Self-Drawn Platform Host Track
409412

410-
Status: architecture planned; implementation has not started.
413+
Status: H0 complete; H1 is next.
411414

412415
This track turns the existing offscreen layout/scene/GPU boundary into real
413416
windows without moving component rendering back into an OS toolkit. All
@@ -421,7 +424,7 @@ migration rules, and verification matrix are recorded in
421424

422425
### H0 - Host contract and dependency firewall
423426

424-
Status: next; may begin during M3.
427+
Status: complete.
425428

426429
- add typed window, presentation, input, text-input, accessibility, and system
427430
service records under a new `platform_host/` boundary
@@ -433,14 +436,26 @@ Status: next; may begin during M3.
433436
Gates:
434437

435438
- the contract exposes no widget create/update/remove operation
436-
- host records contain no component style, Node, toolkit object, or `wgpu`
437-
handle
439+
- host records contain no component style, Node.js value, toolkit object, or
440+
`wgpu` handle
438441
- semantic-only builds stay free of Graphics and platform dependencies
439442
- target features do not import or enable legacy renderer modules
440443

444+
Evidence:
445+
446+
- `platform_host/` owns bounded records for windows, presentation, raw input,
447+
text input, stable-id accessibility, system services, and ordered events
448+
- `PlatformHostTransaction` validates one monotonic revision before mutation;
449+
`RecordingPlatformHost` proves prepare/commit/rollback, failed-commit
450+
recovery, bounded queues/history, redaction, and explicit shutdown
451+
- `platform-host`, `host-macos`, `host-windows`, `host-linux-wayland`,
452+
`host-linux-x11`, and `host-linux` compile without enabling a legacy backend
453+
- 13 focused contract tests and three recursive source/feature firewall tests
454+
cover the H0 gates; `just verify` includes their build, graph, and test lanes
455+
441456
### H1 - Shared self-drawn window runtime
442457

443-
Status: planned after H0; depends on M3 presentation work.
458+
Status: next; depends on M3 presentation work.
444459

445460
- transact scene, hit-region, accessibility, and window state as one committed
446461
host frame
@@ -730,15 +745,13 @@ A component or subsystem is complete only when:
730745

731746
## Immediate Commit Sequence
732747

733-
1. Land H0 host contracts, fake-host conformance, target feature boundaries,
734-
and dependency firewalls.
735-
2. Land H1 shared frame orchestration and raw-surface presentation lifecycle.
736-
3. Present the generic rectangle slice through the H2 Windows Win32 host.
737-
4. Present the same slice through the H3 macOS system-shell host.
738-
5. Present it through H4 Wayland, then the separately gated X11 fallback.
739-
6. Add text shaping/rasterization, hit testing, input, IME, and accessibility
748+
1. Land H1 shared frame orchestration and raw-surface presentation lifecycle.
749+
2. Present the generic rectangle slice through the H2 Windows Win32 host.
750+
3. Present the same slice through the H3 macOS system-shell host.
751+
4. Present it through H4 Wayland, then the separately gated X11 fallback.
752+
5. Add text shaping/rasterization, hit testing, input, IME, and accessibility
740753
against the shared host contract.
741-
7. Pass the shared calculator cutover matrix on all three platforms.
742-
8. Delete WinUI/XAML, GTK4, and AppKit content-control code and all final
754+
6. Pass the shared calculator cutover matrix on all three platforms.
755+
7. Delete WinUI/XAML, GTK4, and AppKit content-control code and all final
743756
consumers in reviewable, platform-scoped commits while preserving the thin
744757
OS shells.

justfile

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,11 @@ check-core:
311311
cargo check --locked --no-default-features --features graphics --lib
312312
cargo check --locked --no-default-features --features software-reference --lib
313313
cargo check --locked --no-default-features --features gpu --lib
314+
cargo check --locked --no-default-features --features platform-host --lib
315+
316+
# Compile every zero-widget host marker without a legacy renderer
317+
check-platform-host:
318+
cargo check --locked --no-default-features --features platform-host,host-macos,host-windows,host-linux --lib
314319

315320
# Prove semantic-only builds do not acquire Graphics or wgpu
316321
check-core-graph:
@@ -323,6 +328,22 @@ check-core-graph:
323328
exit 1
324329
fi
325330
331+
# Prove the H0 contract graph contains no renderer or OS toolkit dependency
332+
check-platform-host-graph:
333+
#!/usr/bin/env bash
334+
set -euo pipefail
335+
336+
host_graph="$(cargo tree --locked --no-default-features --features platform-host --prefix none)"
337+
if grep -Eq '^(a3s-graphics|wgpu|gtk4|gdk4|gsk4|winio-winui3|windows-collections|objc2-app-kit) ' <<<"$host_graph"; then
338+
echo "renderer or toolkit dependencies entered the H0 platform-host graph" >&2
339+
exit 1
340+
fi
341+
342+
# Run the zero-widget platform-host contract and firewall suites
343+
test-platform-host:
344+
cargo test --locked --no-default-features --features platform-host --lib platform_host::
345+
cargo test --locked --no-default-features --features platform-host --test platform_host_firewall
346+
326347
# Run native-feature library tests for this operating system
327348
test-native:
328349
#!/usr/bin/env bash
@@ -361,14 +382,15 @@ winui-input-smoke EVIDENCE:
361382

362383
# Lint every target and deny high-confidence Clippy and Rust warnings
363384
clippy:
364-
cargo clippy --locked --all-targets --features appkit,winui,gtk4,gpu -- -A clippy::all -D clippy::correctness -D clippy::suspicious -A clippy::unnecessary_get_then_check -D unused
385+
cargo clippy --locked --all-targets --features appkit,winui,gtk4,gpu,platform-host -- -A clippy::all -D clippy::correctness -D clippy::suspicious -A clippy::unnecessary_get_then_check -D unused
365386

366387
# Build crate documentation and fail on rustdoc warnings
367388
doc-check:
368389
RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-deps --document-private-items
390+
RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-default-features --features platform-host --no-deps --document-private-items
369391

370392
# Run the full local verification suite
371-
verify: fmt-check check-core check-core-graph clippy doc-check test test-examples test-platforms test-graphics diff-check
393+
verify: fmt-check check-core check-core-graph check-platform-host check-platform-host-graph clippy doc-check test test-examples test-platforms test-platform-host test-graphics diff-check
372394

373395
# Run dogfood reducer and protocol-boundary regression tests
374396
dogfood-regression:

0 commit comments

Comments
 (0)