Compass-generated macOS (and future iOS) products keep domain logic in crates/core, UI policy in crates/ui, and platform shells as dumb binders over UniFFI.
This is not a custom pixel renderer. SwiftUI (macOS today; iOS later) only maps ViewState → views and user events → Action.
crates/core/ # domain
crates/ui/ # ViewState, Action, Effect, update, semantic tree, simulation, guardrails
crates/ffi/ # UniFFI exports (snapshot + dispatch) over ui (+ core as needed)
apps/macos/ # SwiftUI binder only
CLI and server products do not require crates/ui.
Serializable, versioned presentation state (schema_version). The scaffold greeting screen carries label and caption strings derived from crates/core via update / initial_state — not computed in Swift.
Closed vocabulary of user intents (scaffold: Refresh). Binders never invent domain rules; they dispatch actions.
I/O requests returned from update (save, open URL, call async core, …). The greeting scaffold is pure (empty effects). Simulation stubs effects so UI tests stay deterministic.
Compass-owned accessibility-inspired tree: { id, role, value, actions, children }. Stable ids (e.g. greeting.label, greeting.caption) are the contract for:
- headless simulation asserts
- headed AX asserts when fidelity mode is on
- SwiftUI
.accessibilityIdentifier
Applies actions through update, records a trace (action + state + semantic snapshot), and supports queries by semantic id. Required UI proof lives in crates/ui #[cfg(test)] / integration tests and runs under cargo test.
Deterministic predicates over state/semantic trees, for example:
- every interactive node has a non-empty stable id
- required ids for the current screen are present
- no empty labels on text nodes that declare a value
Failures fail cargo test like any other assertion.
| Mode | Trigger | Role |
|---|---|---|
| Simulation (required) | cargo test --workspace (standard Rust verify) |
Primary UI acceptance |
| macOS adapter verify | bash scripts/verify-macos.sh |
UniFFI bindings + swift build / swift run FFIChecks |
| Headed fidelity (opt-in) | COMPASS_MACOS_UI_FIDELITY=1 |
Bundle, Aqua launch, AX assert, screenshot → apps/macos/dist/ui-smoke.png |
Unset / 0 / false means fidelity is off. Default verify does not require an Aqua session.
Set the env var on the Compass host (or prefix the guest command) for an occasional full-fidelity iteration. Compass also enables fidelity automatically every N successful Critic-approved ships (default N=5; override with PlanState.macosFidelityCadence) and when forcing a pre-full-audit check. Compass forwards COMPASS_MACOS_UI_FIDELITY=1 into the guest macOS verify command when enabled, and only then repairs guest auto-login for Desktop.
- Put UI policy, navigation, and copy selection in
crates/ui. - Put domain rules in
crates/core. - Change
apps/macosonly when adding binder widgets or wiring new semantic ids. - Prefer simulation tests over headed AX for proving behavior.
A future ios product should share crates/ui + UniFFI and add apps/ios as another dumb SwiftUI binder. Do not fork ViewState per platform.
Compass host remains Swift-owned (see CONTRIBUTING.md). After generated projects prove this contract, a later pilot may adopt the same conceptual runtime for one low-risk host surface. Full host rewrite is out of scope until Phase 1 is proven on generated apps.