use serde::Serialize;
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct ZsuiRustFirstGoal {
pub goal_name: &'static str,
pub principle: &'static str,
pub prefer: &'static str,
pub avoid: &'static str,
pub current_surface: &'static str,
pub next_step: &'static str,
}
impl ZsuiRustFirstGoal {
pub const fn new(
goal_name: &'static str,
principle: &'static str,
prefer: &'static str,
avoid: &'static str,
current_surface: &'static str,
next_step: &'static str,
) -> Self {
Self {
goal_name,
principle,
prefer,
avoid,
current_surface,
next_step,
}
}
}
pub fn zsui_rust_first_goal_names() -> Vec<&'static str> {
zsui_rust_first_goals()
.into_iter()
.map(|goal| goal.goal_name)
.collect()
}
pub fn zsui_rust_first_goals() -> Vec<ZsuiRustFirstGoal> {
vec![
ZsuiRustFirstGoal::new(
"unified_application_authoring",
"Require one platform-neutral Rust application source for Windows, macOS and Linux while preserving genuinely native platform composition and backend behavior inside ZSUI.",
"one State/Msg/view/update/native_window path, semantic components and tokens, framework-owned PlatformExperience composition, and compile-time selected Host/Text/Raster/Presenter/Services profiles",
"application platform cfg, platform enums, raw handles, renderer selection, duplicated per-platform view trees, or examples that patch platform visuals outside reusable framework rules",
"src/view, src/native.rs, src/platform, src/style.rs, examples/desktop_native_showcase.rs, examples/component_gallery.rs, examples/zsui_notepad.rs",
"make the shared application path the only ordinary desktop authoring path, move remaining platform composition and typography choices behind framework contracts, and gate it with one-source three-target proof",
),
ZsuiRustFirstGoal::new(
"native_proof_ci",
"Require repeatable target-native runtime evidence to block UI regressions on every desktop platform.",
"fixed target runners, final platform-view screenshots, versioned semantic reports, calibrated image comparison and reviewed read-only baselines",
"treating cargo check or shared DrawPlan PNGs as platform proof, using moving runner labels, or automatically accepting changed baselines",
".github/workflows/ci.yml, docs/v0.3-native-proof-ci.md, docs/native-host-smoke.md, examples/component_gallery.rs, examples/zsui_notepad.rs",
"keep the operational AppKit gate blocking regressions and align Win32 and Linux with the same reviewed baseline and comparison policy",
),
ZsuiRustFirstGoal::new(
"runnable_vertical_slices",
"Measure progress by standalone input-state-paint loops on real hosts, not by declaration or contract count.",
"a ZSUI-only control gallery with native interaction, repaint and target smoke proof",
"raising overall completion from manifests, AI metadata or mobile scaffolds that do not run on a target",
"examples/navigation_shell_layout.rs, examples/zsui_notepad.rs, examples/zsui_calculator.rs, src/shell_layout.rs, src/document_shell.rs, src/calculator.rs, src/native.rs",
"attach the calculator runtime to the generic native builder, turn the notepad's native editor/file-dialog/lifecycle plumbing into reusable services, then apply the same runtime gate to AppKit, GTK and Android",
),
ZsuiRustFirstGoal::new(
"one_line_native_entrypoints",
"Keep the ordinary native-window entry point short, safe and target-selected by the framework.",
"zsui::native_window(\"Example\").size(900, 620).run()? for desktop now and mobile once the Activity host is real",
"forcing users to choose raw HWND/AppKit/GTK/Activity objects for ordinary window creation",
"src/native.rs, src/native_host_launch.rs",
"prove Windows, macOS and Linux target smoke for the one-line path, then connect the Android host without changing the public entry shape",
),
ZsuiRustFirstGoal::new(
"composition_and_traits",
"Use trait-based View/Component contracts and composition instead of inheritance trees.",
"trait View<Msg> with composable builders such as button(\"Save\").padding(...).on_click(Msg::Save)",
"Control base classes with Button/TextBox/ListView inheritance trees",
"src/component_protocol.rs, src/components.rs, src/view/mod.rs",
"connect View<Msg> trees to richer native host input and layout passes",
),
ZsuiRustFirstGoal::new(
"typed_messages",
"Prefer enum/typed messages over string event names.",
"enum Msg variants returned by typed handlers such as on_click(Msg::SaveClicked)",
"string event buses such as button.on(\"click\", callback)",
"src/command_protocol.rs, src/event_protocol.rs, src/view/mod.rs",
"expand typed message builders across list, menu, tray and text input surfaces",
),
ZsuiRustFirstGoal::new(
"input_experience_consistency",
"Keep editable controls aligned on value-independent hints, field semantics, IME behavior, accessibility projection and target-native proof.",
"one .placeholder(...) contract for text-capable View controls, application-owned validation, themed secondary hints, typed UiDocument properties and shared three-platform input scenarios",
"placeholder text entering values or secure channels, backend-local validation state, global form registries, or platform-specific application view branches",
"src/view, src/password_box.rs, src/widget_render.rs, src/ui_document.rs, src/ui_document_runtime.rs, docs/v0.3-input-experience.md",
"compose typed labels/help/errors around inputs, then add one-source Win32/AppKit/Linux Native Proof for empty, focused, IME, invalid and secure states",
),
ZsuiRustFirstGoal::new(
"raii_native_resources",
"Own native windows, fonts, bitmaps, tray icons and handles with RAII wrappers.",
"owned Window/Icon/Tray/Font/Bitmap values and internal Drop-backed HWND/GDI/HDC/HBITMAP objects",
"public APIs that require DestroyWindow, DeleteObject or Release calls from users",
"src/native.rs, src/platform/windows/mod.rs, src/windows_gdi_renderer.rs",
"add required tray/menu popup interaction and cleanup target smoke proof while keeping raw HWNDs out of higher-level APIs",
),
ZsuiRustFirstGoal::new(
"production_native_foundation",
"Use proven native host and rendering behavior as the framework baseline while keeping product behavior outside ZSUI.",
"NativeDrawPlan, buffered no-flicker Win32/GDI painting, reusable document/calculator shells, status/menu/settings contracts and owned native resources",
"duplicating established host behavior or placing application storage and sync logic inside ZSUI",
"src/render_protocol.rs, src/native_host_actions.rs, src/windows_gdi_renderer.rs, src/platform/windows/mod.rs",
"finish tray/menu/input host routes and keep buffered no-flicker self-draw as the Windows baseline",
),
ZsuiRustFirstGoal::new(
"typed_units",
"Use strong UI units such as Px, Dp and Dpi instead of mixing raw numeric sizes.",
"Px, Dp, Dpi and UiLength conversions at layout/render boundaries",
"raw i32/f32 values flowing through DPI, spacing and size APIs",
"src/geometry.rs",
"convert remaining geometry/layout APIs from raw numeric DPI and spacing values",
),
ZsuiRustFirstGoal::new(
"compile_time_builders",
"Push invalid app/window states toward compile-time builder constraints where practical.",
"typestate builders for required title/content/runtime surfaces where they pay for themselves",
"runtime-only missing-field failures for states the type system can express cleanly",
"src/native.rs",
"keep the opt-in native content typestate stable and add AppBuilder lifecycle typestate only if it prevents a demonstrated invalid state",
),
ZsuiRustFirstGoal::new(
"explicit_context_no_globals",
"Avoid global mutable app/theme/window/event registries; pass explicit context objects.",
"update(&mut state, msg, &mut AppCx) and explicit Event/Layout/Paint contexts",
"GlobalApp, GlobalTheme, GlobalWindowManager, GlobalEventBus or global widget registries",
"src/host.rs, src/product_adapter.rs, src/view/mod.rs",
"wire AppCx/EventCx/PaintCx into native runtime and product adapter examples",
),
ZsuiRustFirstGoal::new(
"safe_public_api_isolated_unsafe",
"Keep public APIs safe and isolate unsafe platform calls inside backend modules.",
"safe builders such as zsui::native_window(...).run()? with unsafe limited to native backends",
"raw HWND/HDC/HBITMAP/objc/GTK handles in declaration models or user-facing APIs",
"src/native.rs, src/platform/windows/mod.rs, src/windows_gdi_renderer.rs",
"audit backend unsafe blocks and keep raw platform handles out of declaration models",
),
ZsuiRustFirstGoal::new(
"explicit_state_model",
"Keep control state in explicit application state and derive UI from that state.",
"view(&AppState) -> impl View<Msg> plus update(msg, &mut AppCx)",
"controls hiding product state or mutating invisible framework-owned application data",
"src/view/mod.rs, src/native.rs, examples/rust_first_view.rs",
"extend the live state and dual command-executor loop to AppKit and GTK, then connect asynchronous product events back into state updates",
),
ZsuiRustFirstGoal::new(
"theme_tokens",
"Use theme tokens for color, radius, spacing and typography instead of scattered literals.",
"theme.color.surface, theme.color.text_primary, theme.radius.medium and theme.spacing.md",
"hard-coded Color::rgb(...) values scattered through widgets and examples",
"src/render_protocol.rs, src/style.rs",
"route all built-in view/widget styles through ZsuiTheme tokens",
),
ZsuiRustFirstGoal::new(
"declarative_rust_api",
"Expose declarative Rust builders without XML, reflection or magic property names.",
"Rust-analyzer friendly view builders such as column((text(...), list(...), button(...)))",
"XML/XAML-style reflection, string bindings and magic property names",
"src/components.rs, src/view/mod.rs",
"add tuple/array ergonomics and product adapter examples for declarative views",
),
ZsuiRustFirstGoal::new(
"reloadable_ui_documents",
"Allow visual-only UI changes to reload without invoking Cargo while preserving Rust-first typed state, messages and release trimming.",
"a versioned semantic UiDocument, explicit typed binding manifest, schema validator, prebuilt native Viewer, stable-ID patches and release-time embedding",
"a global string event bus, arbitrary reflection, browser pixels presented as native proof, development watchers in release builds or a mandatory two-process application runtime",
"src/ui_document.rs, src/ui_document_runtime.rs, src/ui_viewer.rs, src/bin/zsui-uic.rs, src/bin/zsui-viewer.rs, docs/ui-document.md",
"keep all 47 catalog families, typed binding compatibility, stable-ID state retention, three-platform Viewer proof and release embedding aligned as components evolve; defer the full drag-and-drop editor",
),
ZsuiRustFirstGoal::new(
"result_error_handling",
"Return Result<T, ZsuiError> for host/backend failures instead of panicking.",
"fallible app/window/icon/font/backend construction returning Result<T, ZsuiError>",
"panic, unwrap or MessageBoxW for recoverable host/backend failures",
"src/core.rs, src/native.rs",
"remove remaining unwrap-style backend assumptions before marking runtime complete",
),
ZsuiRustFirstGoal::new(
"capability_traits",
"Represent platform differences with traits and capability reports instead of fake uniformity.",
"TrayBackend, HotkeyBackend, DialogBackend and capability reports with honest unsupported states",
"one fake uniform API pretending every desktop/mobile platform supports the same native services",
"src/capability.rs, src/host_protocol.rs, src/native_hosts.rs",
"split tray, hotkey, dialog, file-picker and shell-open backend traits into real hosts",
),
ZsuiRustFirstGoal::new(
"mobile_native_host",
"Treat Android as a native platform target with an explicit Activity host boundary.",
"Android Activity scaffold, lifecycle bindings, FFI gates and device smoke artifacts",
"pretending desktop tray/window semantics map exactly to mobile notifications or activities",
"src/mobile_host.rs, src/android_activity_host.rs",
"turn the scaffold manifest into a real Activity runtime bridge and require device smoke proof",
),
ZsuiRustFirstGoal::new(
"feature_gated_platform_capabilities",
"Use Cargo features for widgets, services, platform backends and heavy dependencies.",
"default-features = false with selected widget/backend features and optional dependencies",
"eager global registration that makes every widget and backend enter every build",
"Cargo.toml, src/feature_manifest.rs, scripts/check-feature-matrix.ps1, .github/workflows/ci.yml",
"move heavy widgets into feature modules or crates while keeping every new public feature in the matrix gate",
),
ZsuiRustFirstGoal::new(
"task_scoped_ai_context",
"Keep AI bootstrap context small and load implementation knowledge by task instead of reading the repository as one prompt.",
"docs/ai-agent.md plus one validated context pack with required paths, optional paths and focused checks",
"bulk-loading all source, documentation, examples, generated artifacts and readiness metadata before every task",
"AGENTS.md, docs/ai-agent.md, docs/ai/context-packs.json, scripts/ai-context.ps1",
"keep pack paths valid in CI, measure bootstrap size and split any pack that grows beyond one ownership boundary",
),
ZsuiRustFirstGoal::new(
"crate_split_architecture",
"Let the framework grow through small feature-gated crates or modules instead of one untrimmed mega-crate.",
"zsui-core, zsui-shell, zsui-render, zsui-style and widget-family crates such as zsui-widgets-input/list/extra",
"placing every widget, renderer and platform binding in one always-enabled crate",
"Cargo.toml, src/feature_manifest.rs",
"split heavier widget families, renderers and backend integrations once their contracts are stable enough to publish separately",
),
ZsuiRustFirstGoal::new(
"platform_api_on_demand",
"Add platform API crates and bindings only when a concrete backend surface requires them.",
"narrow feature-gated windows-sys/windows-rs/AppKit/GTK/Android bindings inside backend modules",
"pulling broad native dependency surfaces into core declarations or user-facing APIs before they are needed",
"Cargo.toml, src/platform/windows/mod.rs, src/windows_gdi_renderer.rs",
"use windows-rs or wider native APIs only for concrete Direct2D, composition, tray, input or renderer work",
),
ZsuiRustFirstGoal::new(
"strong_typed_ids",
"Use strong typed IDs for widgets, windows, commands and resources instead of raw strings.",
"WidgetId, WindowId, command IDs and typed window marker helpers",
"raw strings such as focus(\"main_input\") or open_window(\"settings\")",
"src/core.rs, src/geometry.rs, src/command_protocol.rs, src/view/mod.rs",
"add resource IDs and typed window-marker helpers where they reduce runtime lookup errors",
),
]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rust_first_goal_manifest_tracks_core_direction() {
let names = zsui_rust_first_goal_names();
assert_eq!(names.len(), 25);
assert!(names.contains(&"unified_application_authoring"));
assert!(names.contains(&"native_proof_ci"));
assert!(names.contains(&"runnable_vertical_slices"));
assert!(names.contains(&"one_line_native_entrypoints"));
assert!(names.contains(&"composition_and_traits"));
assert!(names.contains(&"typed_messages"));
assert!(names.contains(&"raii_native_resources"));
assert!(names.contains(&"production_native_foundation"));
assert!(names.contains(&"mobile_native_host"));
assert!(names.contains(&"feature_gated_platform_capabilities"));
assert!(names.contains(&"task_scoped_ai_context"));
assert!(names.contains(&"crate_split_architecture"));
assert!(names.contains(&"platform_api_on_demand"));
assert!(names.contains(&"strong_typed_ids"));
assert!(names.contains(&"reloadable_ui_documents"));
assert!(names.contains(&"input_experience_consistency"));
let goals = zsui_rust_first_goals();
let unified_authoring = goals
.iter()
.find(|goal| goal.goal_name == "unified_application_authoring")
.expect("unified application authoring goal should exist");
assert!(unified_authoring.prefer.contains("State/Msg/view/update"));
assert!(unified_authoring.avoid.contains("application platform cfg"));
let typed_messages = goals
.iter()
.find(|goal| goal.goal_name == "typed_messages")
.expect("typed message goal should exist");
assert!(typed_messages.prefer.contains("enum Msg"));
assert!(typed_messages.avoid.contains("button.on"));
let reloadable = goals
.iter()
.find(|goal| goal.goal_name == "reloadable_ui_documents")
.expect("reloadable UI document goal should exist");
assert!(reloadable.prefer.contains("UiDocument"));
assert!(reloadable.avoid.contains("browser pixels"));
}
}