Close final native parity audit gaps

This commit is contained in:
ZacharyZhang-NY committed 2026-04-19 16:23:28 -04:00
1 parent d4c6056f5e
commit 7ef60d82bb
10 files changed
+555 -190

No files matched your search

@@ -88,13 +88,76 @@ impl AppRoot {
.items_center()
.justify_center()
.child(match step {
OnboardingStep::NodeCheck => self.render_nodecheck_panel(cx).into_any_element(),
OnboardingStep::Providers => self.render_providers_panel(cx).into_any_element(),
OnboardingStep::Company => self.render_company_setup_panel(cx).into_any_element(),
OnboardingStep::ModelPool => self.render_model_pool_panel(cx).into_any_element(),
OnboardingStep::ExecutionMode => {
self.render_execution_mode_panel(cx).into_any_element()
}
OnboardingStep::Mission => self.render_mission_setup_panel(cx).into_any_element(),
OnboardingStep::Launch => self.render_launch_summary_panel(cx).into_any_element(),
})
}
fn render_company_setup_panel(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
fn render_nodecheck_panel(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
let ready_connectors = self
.snapshot
.connectors
.iter()
.filter(|connector| connector.status == "ready" || connector.auth_state == "ready")
.count();
onboarding_card()
.child(step_counter("NODECHECK", 1, 7))
.child(card_title("Verify the local runtime boundary"))
.child(card_divider())
.child(
div()
.gap_4()
.child(onboarding_metric_row(
"Connector inventory",
format!("{} configured", self.snapshot.connectors.len()),
))
.child(onboarding_metric_row(
"Ready runtimes",
format!("{} ready", ready_connectors),
))
.child(onboarding_metric_row(
"Workspace binding",
if self.workspace_input.read(cx).value().trim().is_empty() {
"Set in company step".to_string()
} else {
"Path captured".to_string()
},
))
.child(
div()
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel_inset())
.p_4()
.text_sm()
.line_height(px(22.0))
.text_color(theme::text_secondary())
.child(
"The native desktop path boots a real local-first company profile. This step keeps the original wizard contract honest before provider and mission setup.",
),
),
)
.child(
div()
.mt(px(28.0))
.flex()
.justify_end()
.child(primary_button("Continue to providers", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::Providers;
cx.notify();
})),
)
}
fn render_providers_panel(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
let connector_options = primary_connector_options(&self.snapshot);
let selected_connector_id = self
.state
@@ -103,7 +166,81 @@ impl AppRoot {
.unwrap_or("anthropic");
onboarding_card()
.child(step_counter("COMPANY", 1, 3))
.child(step_counter("PROVIDERS", 2, 7))
.child(card_title("Choose the founding runtime"))
.child(card_divider())
.child(
div()
.gap_4()
.child(div().flex().flex_wrap().gap_2().children(
connector_options.into_iter().map(|connector| {
let active = connector.id == selected_connector_id;
let connector_id = connector.id.clone();
selectable_chip(
connector.label.as_str(),
active,
cx,
move |this, cx| {
this.state.onboarding_connector_id = Some(connector_id.clone());
cx.notify();
},
)
.into_any_element()
}),
))
.child(
div()
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel_inset())
.p_4()
.text_sm()
.line_height(px(22.0))
.text_color(theme::text_secondary())
.child(onboarding_connector_note(
&self.snapshot,
selected_connector_id,
)),
)
.child(
div()
.gap_3()
.child(
div()
.text_xs()
.text_color(theme::text_muted())
.child("READINESS"),
)
.children(
onboarding_readiness(
&self.snapshot,
self.state.onboarding_connector_id.as_deref(),
)
.iter()
.map(readiness_row),
),
),
)
.child(
div()
.mt(px(28.0))
.flex()
.justify_between()
.child(secondary_button("Back", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::NodeCheck;
cx.notify();
}))
.child(primary_button("Continue to company", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::Company;
cx.notify();
})),
)
}
fn render_company_setup_panel(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
onboarding_card()
.child(step_counter("COMPANY", 3, 7))
.child(card_title("Set up the company shell"))
.child(card_divider())
.child(
@@ -119,116 +256,77 @@ impl AppRoot {
.line_height(px(20.0))
.text_color(theme::text_muted())
.child("The workspace path becomes the default execution boundary for the first operating loop."),
)
.child(
div()
.mt(px(12.0))
.gap_3()
.child(
div()
.text_xs()
.text_color(theme::text_muted())
.child("CEO RUNTIME"),
)
.child(div().flex().flex_wrap().gap_2().children(
connector_options.into_iter().map(|connector| {
let active = connector.id == selected_connector_id;
let connector_id = connector.id.clone();
selectable_chip(
connector.label.as_str(),
active,
cx,
move |this, cx| {
this.state.onboarding_connector_id = Some(connector_id.clone());
cx.notify();
},
)
.into_any_element()
}),
))
.child(
div()
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel_inset())
.p_4()
.text_sm()
.line_height(px(22.0))
.text_color(theme::text_secondary())
.child(onboarding_connector_note(&self.snapshot, selected_connector_id)),
),
),
)
.child(
div()
.mt(px(28.0))
.flex()
.justify_end()
.child(primary_button("Continue to mission", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::Mission;
.justify_between()
.child(secondary_button("Back", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::Providers;
cx.notify();
}))
.child(primary_button("Continue to model pool", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::ModelPool;
cx.notify();
})),
)
}
fn render_mission_setup_panel(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
fn render_model_pool_panel(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
let connector = self
.state
.onboarding_connector_id
.as_deref()
.and_then(|connector_id| {
self.snapshot
.connectors
.iter()
.find(|connector| connector.id == connector_id)
});
onboarding_card()
.child(step_counter("MISSION", 2, 3))
.child(card_title("Define the founding mission"))
.child(step_counter("MODELPOOL", 4, 7))
.child(card_title("Review the active model pool"))
.child(card_divider())
.child(
div()
.gap_4()
.child(self.onboarding_goal_input.clone())
.child(self.onboarding_goal_detail_input.clone())
.child(onboarding_metric_row(
"Selected runtime",
connector
.map(|item| item.label.clone())
.unwrap_or_else(|| "No connector selected".to_string()),
))
.child(onboarding_metric_row(
"Default model",
connector
.and_then(|item| item.model.clone())
.unwrap_or_else(|| "Use connector default".to_string()),
))
.child(onboarding_metric_row(
"Status",
connector
.map(|item| {
if item.status.is_empty() {
"Unknown".to_string()
} else {
item.status.clone()
}
})
.unwrap_or_else(|| "Pending".to_string()),
))
.child(
div()
.mt(px(12.0))
.gap_3()
.child(
div()
.text_xs()
.text_color(theme::text_muted())
.child("EXECUTION MODE"),
)
.child(
div()
.flex()
.gap_2()
.child(selectable_chip(
"AI CEO",
self.state.onboarding_execution_mode == "ai_ceo",
cx,
|this, cx| {
this.state.onboarding_execution_mode = "ai_ceo";
cx.notify();
},
))
.child(selectable_chip(
"AI Co-Founder",
self.state.onboarding_execution_mode == "ai_cofounder",
cx,
|this, cx| {
this.state.onboarding_execution_mode = "ai_cofounder";
cx.notify();
},
)),
)
.child(
div()
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel_inset())
.p_4()
.text_sm()
.line_height(px(22.0))
.text_color(theme::text_secondary())
.child(onboarding_execution_mode_note(
self.state.onboarding_execution_mode,
)),
),
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel_inset())
.p_4()
.text_sm()
.line_height(px(22.0))
.text_color(theme::text_secondary())
.child("The original flow paused here to confirm the provider/model surface before execution mode. Native onboarding now preserves that pause with live connector data instead of a collapsed shortcut."),
),
)
.child(
@@ -240,6 +338,107 @@ impl AppRoot {
this.state.onboarding_step = OnboardingStep::Company;
cx.notify();
}))
.child(primary_button("Continue to execution mode", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::ExecutionMode;
cx.notify();
})),
)
}
fn render_execution_mode_panel(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
onboarding_card()
.child(step_counter("EXECUTIONMODE", 5, 7))
.child(card_title("Choose how the company executes"))
.child(card_divider())
.child(
div()
.gap_4()
.child(
div()
.flex()
.gap_2()
.child(selectable_chip(
"AI CEO",
self.state.onboarding_execution_mode == "ai_ceo",
cx,
|this, cx| {
this.state.onboarding_execution_mode = "ai_ceo";
cx.notify();
},
))
.child(selectable_chip(
"AI Co-Founder",
self.state.onboarding_execution_mode == "ai_cofounder",
cx,
|this, cx| {
this.state.onboarding_execution_mode = "ai_cofounder";
cx.notify();
},
)),
)
.child(
div()
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel_inset())
.p_4()
.text_sm()
.line_height(px(22.0))
.text_color(theme::text_secondary())
.child(onboarding_execution_mode_note(
self.state.onboarding_execution_mode,
)),
),
)
.child(
div()
.mt(px(28.0))
.flex()
.justify_between()
.child(secondary_button("Back", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::ModelPool;
cx.notify();
}))
.child(primary_button("Continue to mission", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::Mission;
cx.notify();
})),
)
}
fn render_mission_setup_panel(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
onboarding_card()
.child(step_counter("MISSION", 6, 7))
.child(card_title("Define the founding mission"))
.child(card_divider())
.child(
div()
.gap_4()
.child(self.onboarding_goal_input.clone())
.child(self.onboarding_goal_detail_input.clone())
.child(
div()
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel_inset())
.p_4()
.text_sm()
.line_height(px(22.0))
.text_color(theme::text_secondary())
.child("This mission becomes the first goal, kickoff project brief, and the queued launch run summary inside the local profile."),
),
)
.child(
div()
.mt(px(28.0))
.flex()
.justify_between()
.child(secondary_button("Back", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::ExecutionMode;
cx.notify();
}))
.child(primary_button("Review launch", cx, |this, cx| {
this.state.onboarding_step = OnboardingStep::Launch;
cx.notify();
@@ -271,14 +470,15 @@ impl AppRoot {
onboarding_card()
.child(success_badge())
.child(step_counter("LAUNCH", 7, 7))
.child(
div()
.mt(px(28.0))
.mt(px(20.0))
.text_size(px(32.0))
.line_height(px(38.0))
.text_color(theme::text_primary())
.child(if company_name.trim().is_empty() {
"Native control center is ready.".to_string()
"Company profile is ready to launch.".to_string()
} else {
format!("{} is ready to launch.", company_name.trim())
}),
@@ -417,28 +617,36 @@ fn onboarding_eyebrow(label: &'static str) -> impl IntoElement {
}
fn onboarding_stepper(step: OnboardingStep) -> impl IntoElement {
let steps = [
("Node check", OnboardingStep::NodeCheck),
("Providers", OnboardingStep::Providers),
("Company", OnboardingStep::Company),
("Model pool", OnboardingStep::ModelPool),
("Execution mode", OnboardingStep::ExecutionMode),
("Mission", OnboardingStep::Mission),
("Launch", OnboardingStep::Launch),
];
let active_index = steps
.iter()
.position(|(_, current)| *current == step)
.unwrap_or_default();
let mut children = Vec::new();
for (index, (label, current_step)) in steps.into_iter().enumerate() {
if index > 0 {
children.push(step_connector(index <= active_index).into_any_element());
}
children.push(
major_step_chip(label, step == current_step, index < active_index).into_any_element(),
);
}
div()
.mt(px(12.0))
.flex()
.gap_3()
.items_center()
.child(major_step_chip(
"Company",
matches!(step, OnboardingStep::Company),
true,
))
.child(step_connector())
.child(major_step_chip(
"Mission",
matches!(step, OnboardingStep::Mission),
!matches!(step, OnboardingStep::Company),
))
.child(step_connector())
.child(major_step_chip(
"Launch",
matches!(step, OnboardingStep::Launch),
false,
))
.children(children)
}
fn major_step_chip(label: &'static str, current: bool, complete: bool) -> impl IntoElement {
@@ -475,8 +683,29 @@ fn major_step_chip(label: &'static str, current: bool, complete: bool) -> impl I
}
}
fn step_connector() -> impl IntoElement {
div().w(px(42.0)).h(px(1.0)).bg(theme::panel_border())
fn step_connector(active: bool) -> impl IntoElement {
div().w(px(42.0)).h(px(1.0)).bg(if active {
theme::accent_teal_soft()
} else {
theme::panel_border()
})
}
fn onboarding_metric_row(label: &'static str, value: String) -> impl IntoElement {
div()
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel_inset())
.p_4()
.child(div().text_xs().text_color(theme::text_muted()).child(label))
.child(
div()
.mt(px(8.0))
.text_sm()
.text_color(theme::text_primary())
.child(value),
)
}
fn readiness_row(row: &ConnectorReadiness<'_>) -> impl IntoElement {