use std::borrow::Cow;
use std::path::Path;
use crossterm::event::{KeyCode, KeyEvent};
use ratatui::{
buffer::Buffer,
layout::Rect,
style::{Modifier, Style},
text::{Line, Span},
widgets::{Paragraph, Widget, Wrap},
};
use crate::config::{Config, has_api_key};
use crate::localization::{Locale, MessageId, tr};
use crate::palette;
use crate::prompts::{
BASE_PROMPT_OVERRIDE_OPT_IN_ENV, CONSTITUTION_OVERRIDE_FILE, base_prompt_override_opt_in,
};
use crate::tui::app::App;
use crate::tui::onboarding;
use crate::tui::views::{
ActionHint, ModalKind, ModalView, ViewAction, ViewEvent, render_modal_footer,
render_panel_scroll_rail, render_underwater_surface,
};
use codewhale_config::{
AutonomyPreference, ConstitutionAuthoring, ConstitutionChoice, ConstitutionSource,
ConstitutionValidity, InheritedConfigFacts, RuntimePostureSource, SetupState, SetupStep,
StepEntry, StepStatus, UserConstitution, UserConstitutionLoad,
user_constitution::MAX_NOTES_LEN,
};
mod fleet_draft;
mod model_draft;
mod operate;
mod persistence;
mod provider;
mod remote;
mod tools_mcp;
pub(crate) use fleet_draft::{draft_fleet_profile_with_model, workspace_fingerprint};
pub(crate) use model_draft::draft_constitution_with_model;
use persistence::SetupPersistenceFacts;
use remote::SetupRemoteFacts;
pub const CONSTITUTION_CHECKPOINT_VERSION: &str = "0.9.4";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SetupCommitKind {
BundledConstitution,
DeferredConstitution,
}
pub trait SetupWizardStep {
fn id(&self) -> SetupStep;
fn title_id(&self) -> MessageId;
fn why_id(&self) -> MessageId;
fn required(&self) -> bool;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct StaticSetupStep {
id: SetupStep,
title_id: MessageId,
why_id: MessageId,
required: bool,
}
impl SetupWizardStep for StaticSetupStep {
fn id(&self) -> SetupStep {
self.id
}
fn title_id(&self) -> MessageId {
self.title_id
}
fn why_id(&self) -> MessageId {
self.why_id
}
fn required(&self) -> bool {
self.required
}
}
const STEP_SPECS: [StaticSetupStep; 10] = [
StaticSetupStep {
id: SetupStep::Language,
title_id: MessageId::SetupStepLanguageTitle,
why_id: MessageId::SetupStepLanguageWhy,
required: true,
},
StaticSetupStep {
id: SetupStep::ProviderModel,
title_id: MessageId::SetupStepProviderModelTitle,
why_id: MessageId::SetupStepProviderModelWhy,
required: true,
},
StaticSetupStep {
id: SetupStep::TrustSandbox,
title_id: MessageId::SetupStepTrustSandboxTitle,
why_id: MessageId::SetupStepTrustSandboxWhy,
required: true,
},
StaticSetupStep {
id: SetupStep::Constitution,
title_id: MessageId::SetupStepConstitutionTitle,
why_id: MessageId::SetupStepConstitutionWhy,
required: true,
},
StaticSetupStep {
id: SetupStep::OperateFleet,
title_id: MessageId::SetupStepOperateFleetTitle,
why_id: MessageId::SetupStepOperateFleetWhy,
required: false,
},
StaticSetupStep {
id: SetupStep::Hotbar,
title_id: MessageId::SetupStepHotbarTitle,
why_id: MessageId::SetupStepHotbarWhy,
required: false,
},
StaticSetupStep {
id: SetupStep::ToolsMcp,
title_id: MessageId::SetupStepToolsMcpTitle,
why_id: MessageId::SetupStepToolsMcpWhy,
required: false,
},
StaticSetupStep {
id: SetupStep::RemoteRuntime,
title_id: MessageId::SetupStepRemoteRuntimeTitle,
why_id: MessageId::SetupStepRemoteRuntimeWhy,
required: false,
},
StaticSetupStep {
id: SetupStep::Persistence,
title_id: MessageId::SetupStepPersistenceTitle,
why_id: MessageId::SetupStepPersistenceWhy,
required: false,
},
StaticSetupStep {
id: SetupStep::Verification,
title_id: MessageId::SetupStepVerificationTitle,
why_id: MessageId::SetupStepVerificationWhy,
required: false,
},
];
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SetupWizardView {
state: SetupState,
selected: usize,
locale: Locale,
progressive_guide: bool,
details_expanded: bool,
facts: SetupRuntimeFacts,
guided_draft: GuidedConstitutionDraft,
constitution_advanced: bool,
freeform_note: String,
editing_freeform_note: bool,
guided_preview_seen: bool,
existing_preview_seen: bool,
model_draft: Option<Box<UserConstitution>>,
model_draft_label: Option<String>,
runtime_preset: SetupRuntimePreset,
runtime_preset_preview_seen: bool,
body_scroll: usize,
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct SetupRuntimeFacts {
provider: String,
model: String,
auth: String,
health: String,
provider_ready: bool,
provider_result: String,
work_intent: String,
approval: String,
shell: String,
allow_shell_enabled: bool,
trust: String,
sandbox: String,
sandbox_mode_value: String,
network: String,
network_default_value: String,
runtime_result: String,
operate_runtime_ready: bool,
operate_runtime_result: String,
fleet_roster_ready: bool,
fleet_roster_result: String,
operate_concurrency_result: String,
operate_result: String,
hotbar_bindings_result: String,
hotbar_actions_result: String,
hotbar_result: String,
tools_mcp_servers_result: String,
tools_mcp_skills_result: String,
tools_mcp_tools_result: String,
tools_mcp_plugins_result: String,
tools_mcp_dsh_result: String,
tools_mcp_hotbar_result: String,
tools_mcp_result: String,
tools_mcp_needs_action: bool,
tools_mcp_path_display: String,
tools_mcp_skills_path_display: String,
tools_mcp_plugins_path_display: String,
remote_clouds_result: String,
remote_bridges_result: String,
remote_providers_result: String,
remote_mode_result: String,
remote_command_provider: String,
remote_result: String,
remote_control_result: String,
remote_modes: Vec<remote::RemoteModeFact>,
remote_needs_action: bool,
persistence: SetupPersistenceFacts,
default_mode: String,
approval_policy_value: String,
project_override_warning: Option<String>,
constitution_autonomy: String,
constitution_file: SetupConstitutionFileState,
expert_override: SetupExpertOverrideState,
}
impl Default for SetupRuntimeFacts {
fn default() -> Self {
Self {
provider: "not loaded".to_string(),
model: "not loaded".to_string(),
auth: "not checked".to_string(),
health: "not checked".to_string(),
provider_ready: false,
provider_result: "provider/model not loaded".to_string(),
work_intent: "not loaded".to_string(),
approval: "not loaded".to_string(),
shell: "not loaded".to_string(),
allow_shell_enabled: false,
trust: "not loaded".to_string(),
sandbox: "not configured".to_string(),
sandbox_mode_value: "default".to_string(),
network: "not configured".to_string(),
network_default_value: "prompt".to_string(),
runtime_result: "runtime posture not loaded".to_string(),
operate_runtime_ready: false,
operate_runtime_result: "worker runtime not loaded".to_string(),
fleet_roster_ready: false,
fleet_roster_result: "Fleet roster not loaded".to_string(),
operate_concurrency_result: "concurrency not loaded".to_string(),
operate_result: "operate readiness not loaded".to_string(),
hotbar_bindings_result: "Hotbar config not loaded".to_string(),
hotbar_actions_result: "Hotbar actions not loaded".to_string(),
hotbar_result: "hotbar not loaded".to_string(),
tools_mcp_servers_result: "MCP config not loaded".to_string(),
tools_mcp_skills_result: "skills dir not loaded".to_string(),
tools_mcp_tools_result: "tools dir not loaded".to_string(),
tools_mcp_plugins_result: "plugins dir not loaded".to_string(),
tools_mcp_dsh_result: "DeepSeek Harness not probed".to_string(),
tools_mcp_hotbar_result: "hotbar source metadata not loaded".to_string(),
tools_mcp_result: "tools/MCP not loaded".to_string(),
tools_mcp_needs_action: false,
tools_mcp_path_display: String::new(),
tools_mcp_skills_path_display: String::new(),
tools_mcp_plugins_path_display: String::new(),
remote_clouds_result: "remote cloud registry not loaded".to_string(),
remote_bridges_result: "remote bridge registry not loaded".to_string(),
remote_providers_result: "provider registry not loaded".to_string(),
remote_mode_result: "remote setup mode not loaded".to_string(),
remote_command_provider: "deepseek".to_string(),
remote_result: "remote runtime not loaded".to_string(),
remote_control_result: "off".to_string(),
remote_modes: Vec::new(),
remote_needs_action: false,
persistence: SetupPersistenceFacts::default(),
default_mode: "agent".to_string(),
approval_policy_value: "on-request".to_string(),
project_override_warning: None,
constitution_autonomy: "not loaded".to_string(),
constitution_file: SetupConstitutionFileState::NotChecked,
expert_override: SetupExpertOverrideState::NotChecked,
}
}
}
impl SetupRuntimeFacts {
fn from_app_config(app: &App, config: &Config) -> Self {
let expert_override = SetupExpertOverrideState::load();
let readiness = crate::provider_readiness::resolve_for_model(
config,
app.api_provider,
if app.auto_model { "auto" } else { &app.model },
&app.provider_health,
);
let provider_ready = readiness.can_attempt()
&& !matches!(
&readiness,
crate::provider_readiness::ResolvedProviderReadiness::SavedLastCheckFailed { .. }
);
let model = app.model_display_label();
let provider_name = if app.api_provider == crate::config::ApiProvider::Custom {
app.provider_identity_for_persistence().to_string()
} else {
app.api_provider.display_name().to_string()
};
let context_window = crate::route_budget::route_context_window_tokens(
app.api_provider,
&app.model,
app.active_route_limits,
);
let context_window_source = app.active_context_window_source.display_label();
let provider =
format!("{provider_name} ยท context {context_window} ({context_window_source})");
let auth = readiness.label().into_owned();
let health = if provider_ready {
format!("{}; route can be attempted", readiness.label())
} else if matches!(
&readiness,
crate::provider_readiness::ResolvedProviderReadiness::SavedLastCheckFailed { .. }
) {
format!("{}; retry or open /provider", readiness.label())
} else if app.api_provider == crate::config::ApiProvider::OpenaiCodex {
format!(
"{}; run codex login, then grant exact read-only access with `codewhale auth external-consent --provider openai-codex --mode read-only`, or open /provider",
readiness.label()
)
} else if let Some(url) = crate::config::credential_help_for_provider_route(
app.api_provider,
&config.deepseek_base_url(),
)
.credential_url
{
format!(
"{}; credentials: {url}; open /provider to repair the route",
readiness.label()
)
} else {
format!(
"{}; {}; open /provider to repair the route",
readiness.label(),
crate::config::credential_help_for_provider_route(
app.api_provider,
&config.deepseek_base_url(),
)
.guidance
)
};
let provider_result = format!(
"provider={}, model={}, context_window={} ({}) auth={}, health={}",
app.provider_identity_for_persistence(),
model,
context_window,
context_window_source,
readiness.label(),
if provider_ready {
"attemptable"
} else {
"needs action"
}
);
let shell = if app.allow_shell { "enabled" } else { "hidden" }.to_string();
let trust = if app.trust_mode {
"trusted workspace / writes allowed by posture"
} else {
"workspace trust not elevated"
}
.to_string();
let sandbox = config
.sandbox_mode
.as_deref()
.filter(|mode| !mode.trim().is_empty())
.unwrap_or("default")
.to_string();
let sandbox_mode_value = sandbox.clone();
let network_default_value = config
.network
.as_ref()
.map_or("prompt".to_string(), |policy| policy.default.clone());
let network = config
.network
.as_ref()
.map_or("prompt by default".to_string(), |policy| {
format!("default {}", policy.default)
});
let runtime_result = format!(
"intent={}, approval={}, shell={}, trust={}, sandbox={}, network={}",
app.mode.as_setting(),
app.approval_mode
.permission_chip_label()
.to_ascii_lowercase(),
if app.allow_shell { "enabled" } else { "hidden" },
if app.trust_mode {
"trusted"
} else {
"workspace"
},
sandbox,
network
);
let operate = operate::SetupOperateFacts::from_app_config(app, config, provider_ready);
let known_hotbar_action_ids = app
.hotbar_actions
.iter()
.map(|action| action.id())
.collect::<Vec<_>>();
let hotbar_resolution = config.resolve_hotbar_bindings(&known_hotbar_action_ids);
let configured_hotbar_slots = config.hotbar.as_ref().map_or(0, Vec::len);
let hotbar_state = match config.hotbar.as_ref() {
None => "hidden",
Some(bindings) if bindings.is_empty() => "disabled",
Some(_) => "customized",
};
let active_hotbar_slots = hotbar_resolution.bindings.len();
let hotbar_warning_count = hotbar_resolution.warnings.len();
let hotbar_bindings_result = format!(
"{hotbar_state}; configured_slots={configured_hotbar_slots}; active_slots={active_hotbar_slots}; warnings={hotbar_warning_count}"
);
let hotbar_actions_result =
format!("{} bindable actions registered", app.hotbar_actions.len());
let hotbar_result = format!(
"state={hotbar_state}, configured_slots={configured_hotbar_slots}, active_slots={active_hotbar_slots}, actions={}, warnings={hotbar_warning_count}",
app.hotbar_actions.len()
);
let codewhale_home = setup_codewhale_home_dir();
let persistence = SetupPersistenceFacts::from_app_config(app, config, &codewhale_home);
let tools_mcp =
tools_mcp::SetupToolsMcpFacts::from_app_config(app, config, &codewhale_home);
let tools_mcp_servers_result = tools_mcp.servers_result;
let tools_mcp_skills_result = tools_mcp.skills_result;
let tools_mcp_tools_result = tools_mcp.tools_result;
let tools_mcp_plugins_result = tools_mcp.plugins_result;
let tools_mcp_hotbar_result = tools_mcp.hotbar_result;
let tools_mcp_dsh_result = tools_mcp.dsh_result;
let tools_mcp_result = tools_mcp.result;
let tools_mcp_needs_action = tools_mcp.needs_action;
let tools_mcp_path_display = tools_mcp.mcp_path_display;
let tools_mcp_skills_path_display = tools_mcp.skills_path_display;
let tools_mcp_plugins_path_display = tools_mcp.plugins_path_display;
let remote = SetupRemoteFacts::from_app(app);
let remote_needs_action = remote.needs_action();
let constitution_autonomy = UserConstitution::load()
.ok()
.and_then(|load| {
load.constitution().map(|constitution| {
autonomy_label(constitution.autonomy_preference, app.ui_locale).to_string()
})
})
.unwrap_or_else(|| tr(app.ui_locale, MessageId::SetupAutonomyUnspecified).to_string());
Self {
provider,
model,
auth,
health,
provider_ready,
provider_result,
work_intent: app.mode.display_name().to_string(),
approval: app
.approval_mode
.permission_chip_label()
.to_ascii_lowercase(),
shell,
allow_shell_enabled: app.allow_shell,
trust,
sandbox,
sandbox_mode_value,
network,
network_default_value,
runtime_result,
operate_runtime_ready: operate.runtime_ready,
operate_runtime_result: operate.runtime_result,
fleet_roster_ready: operate.roster_ready,
fleet_roster_result: operate.roster_result,
operate_concurrency_result: operate.concurrency_result,
operate_result: operate.result,
hotbar_bindings_result,
hotbar_actions_result,
hotbar_result,
tools_mcp_servers_result,
tools_mcp_skills_result,
tools_mcp_tools_result,
tools_mcp_plugins_result,
tools_mcp_hotbar_result,
tools_mcp_dsh_result,
tools_mcp_result,
tools_mcp_needs_action,
tools_mcp_path_display,
tools_mcp_skills_path_display,
tools_mcp_plugins_path_display,
remote_clouds_result: remote.clouds_result,
remote_bridges_result: remote.bridges_result,
remote_providers_result: remote.providers_result,
remote_mode_result: remote.mode_result,
remote_command_provider: remote.command_provider,
remote_result: remote.result,
remote_control_result: {
let status = app.remote_control.status_line();
let message = if status.starts_with("Remote control: connected") {
MessageId::SetupRemoteStatusReady
} else if status.starts_with("Remote control: connecting")
|| status.starts_with("Remote control: stopping")
{
MessageId::SetupStatusInProgress
} else if status.starts_with("Remote control: disconnected") {
MessageId::SetupRemoteStatusNeedsAction
} else {
MessageId::SetupRemoteStatusDisabled
};
tr(app.ui_locale, message).into_owned()
},
remote_needs_action,
remote_modes: remote.modes,
persistence,
default_mode: app.mode.as_setting().to_string(),
approval_policy_value: config
.approval_policy
.as_deref()
.filter(|policy| !policy.trim().is_empty())
.unwrap_or("on-request")
.to_string(),
project_override_warning: project_runtime_override_warning(
&app.workspace,
app.ui_locale,
),
constitution_autonomy,
constitution_file: SetupConstitutionFileState::load(),
expert_override,
}
}
}
fn setup_codewhale_home_dir() -> std::path::PathBuf {
codewhale_config::codewhale_home().unwrap_or_else(|_| {
crate::config::effective_home_dir().map_or_else(
|| std::path::PathBuf::from(".codewhale"),
|home| home.join(".codewhale"),
)
})
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum SetupRuntimePreset {
AskFirst,
#[default]
NormalAgent,
HighTrustLocal,
}
impl SetupRuntimePreset {
const ALL: [Self; 3] = [Self::AskFirst, Self::NormalAgent, Self::HighTrustLocal];
fn from_key(key: char) -> Option<Self> {
match key {
'1' => Some(Self::AskFirst),
'2' => Some(Self::NormalAgent),
'3' => Some(Self::HighTrustLocal),
_ => None,
}
}
pub fn id(self) -> &'static str {
match self {
Self::AskFirst => "ask-first",
Self::NormalAgent => "normal-agent",
Self::HighTrustLocal => "high-trust-local",
}
}
fn title_id(self) -> MessageId {
match self {
Self::AskFirst => MessageId::SetupRuntimePresetAskFirstTitle,
Self::NormalAgent => MessageId::SetupRuntimePresetNormalAgentTitle,
Self::HighTrustLocal => MessageId::SetupRuntimePresetHighTrustTitle,
}
}
fn description_id(self) -> MessageId {
match self {
Self::AskFirst => MessageId::SetupRuntimePresetAskFirstDescription,
Self::NormalAgent => MessageId::SetupRuntimePresetNormalAgentDescription,
Self::HighTrustLocal => MessageId::SetupRuntimePresetHighTrustDescription,
}
}
pub fn default_mode(self) -> &'static str {
match self {
Self::AskFirst => "plan",
Self::NormalAgent | Self::HighTrustLocal => "agent",
}
}
pub fn permission_posture(self) -> &'static str {
match self {
Self::AskFirst | Self::NormalAgent => "ask",
Self::HighTrustLocal => "full-access",
}
}
pub fn approval_policy(self) -> Option<&'static str> {
match self {
Self::AskFirst | Self::NormalAgent => Some("on-request"),
Self::HighTrustLocal => None,
}
}
pub fn allow_shell(self) -> bool {
match self {
Self::AskFirst => false,
Self::NormalAgent | Self::HighTrustLocal => true,
}
}
pub fn sandbox_mode(self) -> &'static str {
match self {
Self::AskFirst => "read-only",
Self::NormalAgent => "workspace-write",
Self::HighTrustLocal => "danger-full-access",
}
}
pub fn result_summary(self) -> String {
let approval = self
.approval_policy()
.unwrap_or("unset (Full Access saved in TUI settings)");
format!(
"preset={}, default_mode={}, permission_posture={}, approval_policy={}, allow_shell={}, sandbox_mode={}, network=unchanged, trust=unchanged",
self.id(),
self.display_mode(),
self.permission_posture(),
approval,
self.allow_shell(),
self.sandbox_mode()
)
}
fn display_mode(self) -> &'static str {
match self {
Self::AskFirst => "plan",
Self::NormalAgent => "act",
Self::HighTrustLocal => "act + full-access",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum SetupConstitutionFileState {
NotChecked,
Missing,
Loaded,
Empty,
Invalid,
Unreadable,
PathError,
}
impl SetupConstitutionFileState {
fn load() -> Self {
match UserConstitution::path() {
Ok(path) => Self::from_load(&UserConstitution::load_from(&path)),
Err(_) => Self::PathError,
}
}
fn from_load(load: &UserConstitutionLoad) -> Self {
match load {
UserConstitutionLoad::Missing => Self::Missing,
UserConstitutionLoad::Empty => Self::Empty,
UserConstitutionLoad::Invalid(_) => Self::Invalid,
UserConstitutionLoad::Unreadable(_) => Self::Unreadable,
UserConstitutionLoad::Loaded(_) => Self::Loaded,
}
}
fn label(self, choice: ConstitutionChoice, locale: Locale) -> Cow<'static, str> {
let id = match self {
Self::NotChecked => MessageId::SetupConstitutionFileNotChecked,
Self::Missing => MessageId::SetupConstitutionFileMissing,
Self::Loaded if choice == ConstitutionChoice::GuidedCustom => {
MessageId::SetupConstitutionFileLoadedSelected
}
Self::Loaded if choice.is_explicit() => MessageId::SetupConstitutionFileLoadedInactive,
Self::Loaded => MessageId::SetupConstitutionFileLoadedUnselected,
Self::Empty => MessageId::SetupConstitutionFileEmpty,
Self::Invalid => MessageId::SetupConstitutionFileInvalid,
Self::Unreadable => MessageId::SetupConstitutionFileUnreadable,
Self::PathError => MessageId::SetupConstitutionFilePathError,
};
tr(locale, id)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum SetupExpertOverrideState {
NotChecked,
Missing,
Active,
Disabled,
Empty,
Unreadable,
PathError,
}
impl SetupExpertOverrideState {
fn load() -> Self {
let Some(path) = expert_override_path() else {
return Self::PathError;
};
match std::fs::read_to_string(&path) {
Ok(raw) if raw.trim().is_empty() => Self::Empty,
Ok(_) if base_prompt_override_opt_in() => Self::Active,
Ok(_) => Self::Disabled,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Self::Missing,
Err(_) => Self::Unreadable,
}
}
fn is_active(self) -> bool {
matches!(self, Self::Active)
}
fn label(self, locale: Locale) -> Cow<'static, str> {
match self {
Self::NotChecked => tr(locale, MessageId::SetupExpertOverrideNotChecked),
Self::Missing => tr(locale, MessageId::SetupExpertOverrideMissing),
Self::Active => tr(locale, MessageId::SetupExpertOverrideActive),
Self::Disabled => tr(locale, MessageId::SetupExpertOverrideDisabled)
.replace("{env}", BASE_PROMPT_OVERRIDE_OPT_IN_ENV)
.into(),
Self::Empty => tr(locale, MessageId::SetupExpertOverrideEmpty),
Self::Unreadable => tr(locale, MessageId::SetupExpertOverrideUnreadable),
Self::PathError => tr(locale, MessageId::SetupExpertOverridePathError),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct GuidedConstitutionDraft {
purpose: GuidedPurpose,
autonomy: AutonomyPreference,
evidence: GuidedEvidence,
communication: GuidedCommunication,
privacy: GuidedPrivacy,
principles: GuidedPrinciples,
}
impl Default for GuidedConstitutionDraft {
fn default() -> Self {
Self {
purpose: GuidedPurpose::Coding,
autonomy: AutonomyPreference::Balanced,
evidence: GuidedEvidence::TestsAndReceipts,
communication: GuidedCommunication::Concise,
privacy: GuidedPrivacy::StandardCare,
principles: GuidedPrinciples::ScopedChanges,
}
}
}
impl GuidedConstitutionDraft {
fn cycle(&mut self, key: char) -> bool {
match key {
'1' => self.purpose = self.purpose.next(),
'2' => self.autonomy = next_guided_autonomy(self.autonomy),
'3' => self.evidence = self.evidence.next(),
'4' => self.communication = self.communication.next(),
'5' => self.privacy = self.privacy.next(),
'6' => self.principles = self.principles.next(),
_ => return false,
}
true
}
fn to_constitution_with_freeform(
self,
locale: Locale,
freeform_note: Option<&str>,
) -> UserConstitution {
let mut notes = self.notes(locale);
if let Some(note) = freeform_note.map(str::trim).filter(|note| !note.is_empty()) {
let own_words = match locale {
Locale::Ja => format!(
"\nใฆใผใถใผ่ช็ฑๅๅ๏ผ{}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::ZhHans => format!(
"\n็จๆท่ชๅฎไนๅๅ๏ผ{}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::ZhHant => format!(
"\nไฝฟ็จ่
่ช็ฑๅๅ๏ผ{}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::PtBr => format!(
"\nPrincรญpio livre do usuรกrio: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::Es419 => format!(
"\nPrincipio libre del usuario: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::Vi => format!(
"\nNguyรชn tแบฏc tแปฑ do cแปงa ngฦฐแปi dรนng: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::Ko => format!(
"\n์ฌ์ฉ์ ์์ ์์น: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::Ca => format!(
"\nPrincipi lliure de l'usuari: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::De => format!(
"\nFreitext-Prinzip des Nutzers: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::Fr => format!(
"\nPrincipe en texte libre de l'utilisateur : {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::Id => format!(
"\nPrinsip bebas pengguna: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::Hi => format!(
"\nเคเคชเคฏเฅเคเคเคฐเฅเคคเคพ เคฎเฅเคเฅเคค-เคชเคพเค เคธเคฟเคฆเฅเคงเคพเคเคค: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::Ru => format!(
"\nะกะฒะพะฑะพะดะฝัะน ะฟัะธะฝัะธะฟ ะฟะพะปัะทะพะฒะฐัะตะปั: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
Locale::Uk => format!(
"\nะัะปัะฝะธะน ะฟัะธะฝัะธะฟ ะบะพัะธัััะฒะฐัะฐ: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
_ => format!(
"\nUser freeform principle: {}",
bounded_freeform_note(note, MAX_NOTES_LEN)
),
};
notes.push_str(&own_words);
}
UserConstitution {
language: Some(locale.tag().to_string()),
about: Some(self.purpose.about(locale).to_string()),
working_style: vec![
self.purpose.working_style(locale).to_string(),
self.communication.working_style(locale).to_string(),
self.evidence.working_style(locale).to_string(),
self.privacy.working_style(locale).to_string(),
],
priorities: vec![
authority_priority(locale).to_string(),
autonomy_priority(self.autonomy, locale).to_string(),
self.privacy.escalation_rule(locale).to_string(),
],
autonomy_preference: self.autonomy,
notes: Some(notes),
..UserConstitution::default()
}
}
fn notes(self, locale: Locale) -> String {
let notes = tr(locale, MessageId::SetupGuidedNotes);
notes
.replace("{purpose}", &self.purpose.label(locale))
.replace("{initiative}", autonomy_label(self.autonomy, locale))
.replace("{evidence}", &self.evidence.label(locale))
.replace("{communication}", self.communication.label(locale))
.replace("{privacy}", self.privacy.label(locale))
.replace("{principles}", self.principles.label(locale))
.replace("{notes}", self.principles.note(locale))
.to_string()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum GuidedPurpose {
Coding,
Research,
Operations,
Mixed,
}
impl GuidedPurpose {
fn next(self) -> Self {
match self {
Self::Coding => Self::Research,
Self::Research => Self::Operations,
Self::Operations => Self::Mixed,
Self::Mixed => Self::Coding,
}
}
fn label(self, locale: Locale) -> Cow<'static, str> {
match self {
Self::Coding => tr(locale, MessageId::SetupGuidedPurposeCoding),
Self::Research => tr(locale, MessageId::SetupGuidedPurposeResearch),
Self::Operations => tr(locale, MessageId::SetupGuidedPurposeOperations),
Self::Mixed => tr(locale, MessageId::SetupGuidedPurposeMixed),
}
}
fn about(self, locale: Locale) -> Cow<'static, str> {
match self {
Self::Coding => tr(locale, MessageId::SetupGuidedPurposeAboutCoding),
Self::Research => tr(locale, MessageId::SetupGuidedPurposeAboutResearch),
Self::Operations => tr(locale, MessageId::SetupGuidedPurposeAboutOperations),
Self::Mixed => tr(locale, MessageId::SetupGuidedPurposeAboutMixed),
}
}
fn working_style(self, locale: Locale) -> Cow<'static, str> {
match self {
Self::Coding => tr(locale, MessageId::SetupGuidedStyleCoding),
Self::Research => tr(locale, MessageId::SetupGuidedStyleResearch),
Self::Operations => tr(locale, MessageId::SetupGuidedStyleOperations),
Self::Mixed => tr(locale, MessageId::SetupGuidedStyleMixed),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum GuidedEvidence {
Assumptions,
TestsAndReceipts,
ReleaseReceipts,
}
impl GuidedEvidence {
fn next(self) -> Self {
match self {
Self::Assumptions => Self::TestsAndReceipts,
Self::TestsAndReceipts => Self::ReleaseReceipts,
Self::ReleaseReceipts => Self::Assumptions,
}
}
fn label(self, locale: Locale) -> Cow<'static, str> {
match self {
Self::Assumptions => tr(locale, MessageId::SetupGuidedEvidenceAssumptions),
Self::TestsAndReceipts => tr(locale, MessageId::SetupGuidedEvidenceTestsAndReceipts),
Self::ReleaseReceipts => tr(locale, MessageId::SetupGuidedEvidenceReleaseReceipts),
}
}
fn working_style(self, locale: Locale) -> &'static str {
match (locale, self) {
(Locale::Ja, Self::Assumptions) => {
"ๅฎไบใไธปๅผตใใๅใซใๅๆใไธๆ็นใๆฎใใชในใฏใ่ฆ็ดใใใ"
}
(Locale::Ja, Self::TestsAndReceipts) => {
"ไธ็ขบๅฎๆงใๆธใใใใจใใฏใใณใใณใใใในใใในใฏใชใผใณใทใงใใใๅผ็จใงๅ
ทไฝ็ใซๆค่จผใใใ"
}
(Locale::Ja, Self::ReleaseReceipts) => {
"้่ฆใชไธปๅผตใจใชใชใผใน่จผๆ ใซใฏใใใกใคใซใใณใใณใใในใฏใชใผใณใทใงใใใCIใๅบๅ
ธใ็คบใใ"
}
(Locale::ZhHans, Self::Assumptions) => "ๅจๅฎฃ็งฐๅฎๆๅๆป็ปๅ่ฎพใๆช็ฅๅๅฉไฝ้ฃ้ฉใ",
(Locale::ZhHans, Self::TestsAndReceipts) => {
"ๅจ่ฝ้ไฝไธ็กฎๅฎๆงๆถ๏ผ็จๅฝไปคใๆต่ฏใๆชๅพๆๅผ็จ็ปๅบๅ
ทไฝ้ช่ฏใ"
}
(Locale::ZhHans, Self::ReleaseReceipts) => {
"ๅฏน้่ฆ็ป่ฎบๅๅๅธ่ฏๆฎๆ ๆณจๆไปถใๅฝไปคใๆชๅพใCI ๆๆฅๆบใ"
}
(Locale::ZhHant, Self::Assumptions) => "ๅจๅฎฃ็จฑๅฎๆๅ็ธฝ็ตๅ่จญใๆช็ฅๅๅฉ้ค้ขจ้ชใ",
(Locale::ZhHant, Self::TestsAndReceipts) => {
"ๅจ่ฝ้ไฝไธ็ขบๅฎๆงๆ๏ผ็จๅฝไปคใๆธฌ่ฉฆใๆชๅๆๅผ็จ็ตฆๅบๅ
ท้ซ้ฉ่ญใ"
}
(Locale::ZhHant, Self::ReleaseReceipts) => {
"ๅฐ้่ฆ็ต่ซๅ็ผๅธ่ญๆๆจ่จปๆชๆกใๅฝไปคใๆชๅใCI ๆไพๆบใ"
}
(Locale::PtBr, Self::Assumptions) => {
"Resuma premissas, desconhecidos e risco restante antes de dizer que concluiu."
}
(Locale::PtBr, Self::TestsAndReceipts) => {
"Use comandos, testes, screenshots ou citaรงรตes quando reduzirem a incerteza."
}
(Locale::PtBr, Self::ReleaseReceipts) => {
"Cite arquivos, comandos, screenshots, CI ou fontes para afirmaรงรตes materiais e evidรชncia de release."
}
(Locale::Es419, Self::Assumptions) => {
"Resume supuestos, incรณgnitas y riesgo restante antes de afirmar que terminaste."
}
(Locale::Es419, Self::TestsAndReceipts) => {
"Usa comandos, pruebas, capturas o citas cuando reduzcan materialmente la incertidumbre."
}
(Locale::Es419, Self::ReleaseReceipts) => {
"Cita archivos, comandos, capturas, CI o fuentes para afirmaciones materiales y evidencia de release."
}
(Locale::Vi, Self::Assumptions) => {
"Tรณm tแบฏt giแบฃ ฤแปnh, ฤiแปu chฦฐa biแบฟt vร rแปงi ro cรฒn lแบกi trฦฐแปc khi tuyรชn bแป hoร n tแบฅt."
}
(Locale::Vi, Self::TestsAndReceipts) => {
"Dรนng lแปnh, kiแปm thแปญ, แบฃnh chแปฅp hoแบทc trรญch dแบซn khi chรบng giแบฃm ฤรกng kแป bแบฅt ฤแปnh."
}
(Locale::Vi, Self::ReleaseReceipts) => {
"Trรญch dแบซn tแปp, lแปnh, แบฃnh chแปฅp, CI hoแบทc nguแปn cho tuyรชn bแป quan trแปng vร bแบฑng chแปฉng phรกt hร nh."
}
(Locale::Ko, Self::Assumptions) => {
"์๋ฃ๋ฅผ ์ฃผ์ฅํ๊ธฐ ์ ์ ๊ฐ์ , ๋ถํ์คํ ์ , ๋จ์ ์ํ์ ์์ฝํ๋ค."
}
(Locale::Ko, Self::TestsAndReceipts) => {
"๋ถํ์ค์ฑ์ ์ค์ง์ ์ผ๋ก ์ค์ผ ์ ์์ ๋๋ ๋ช
๋ น์ด, ํ
์คํธ, ์คํฌ๋ฆฐ์ท, ์ธ์ฉ์ผ๋ก ๊ตฌ์ฒด์ ์ผ๋ก ๊ฒ์ฆํ๋ค."
}
(Locale::Ko, Self::ReleaseReceipts) => {
"์ค์ํ ์ฃผ์ฅ๊ณผ ๋ฆด๋ฆฌ์ค ๊ทผ๊ฑฐ์๋ ํ์ผ ๊ฒฝ๋ก, ๋ช
๋ น์ด, ์คํฌ๋ฆฐ์ท, CI, ์ถ์ฒ๋ฅผ ์ ์ํ๋ค."
}
(Locale::Ca, Self::Assumptions) => {
"Resumeix supรฒsits, incรฒgnites i risc pendent abans de dir que has acabat."
}
(Locale::Ca, Self::TestsAndReceipts) => {
"Fes servir ordres, tests, captures de pantalla o citacions quan redueixin materialment la incertesa."
}
(Locale::Ca, Self::ReleaseReceipts) => {
"Cita rutes de fitxers, ordres, captures de pantalla, CI o fonts per a afirmacions materials i evidรจncia de release."
}
(Locale::De, Self::Assumptions) => {
"Fasse Annahmen, Unbekannte und Restrisiken zusammen, bevor du Fertigstellung behauptest."
}
(Locale::De, Self::TestsAndReceipts) => {
"Nutze Befehle, Tests, Screenshots oder Zitate, wenn sie die Unsicherheit wesentlich verringern."
}
(Locale::De, Self::ReleaseReceipts) => {
"Nenne Dateipfade, Befehle, Screenshots, CI oder Quellen fรผr wesentliche Aussagen und Release-Nachweise."
}
(Locale::Fr, Self::Assumptions) => {
"Rรฉsumez les hypothรจses, les inconnues et le risque restant avant d'annoncer la fin du travail."
}
(Locale::Fr, Self::TestsAndReceipts) => {
"Utilisez commandes, tests, captures d'รฉcran ou citations quand ils rรฉduisent sensiblement l'incertitude."
}
(Locale::Fr, Self::ReleaseReceipts) => {
"Citez chemins de fichiers, commandes, captures d'รฉcran, CI ou sources pour les affirmations importantes et les preuves de release."
}
(Locale::Id, Self::Assumptions) => {
"Ringkas asumsi, hal yang belum diketahui, dan risiko tersisa sebelum mengklaim selesai."
}
(Locale::Id, Self::TestsAndReceipts) => {
"Gunakan perintah, tes, tangkapan layar, atau kutipan bila secara nyata mengurangi ketidakpastian."
}
(Locale::Id, Self::ReleaseReceipts) => {
"Kutip path file, perintah, tangkapan layar, CI, atau sumber untuk klaim material dan bukti rilis."
}
(Locale::Hi, Self::Assumptions) => {
"เคชเฅเคฐเฅเคฃเคคเคพ เคเคพ เคฆเคพเคตเคพ เคเคฐเคจเฅ เคธเฅ เคชเคนเคฒเฅ เคงเคพเคฐเคฃเคพเคเค, เค
เคเฅเคเคพเคค เคฌเคพเคคเฅเค เคเคฐ เคถเฅเคท เคเฅเคเคฟเคฎ เคธเคพเคฐเคพเคเคถเคฟเคค เคเคฐเฅเคเฅค"
}
(Locale::Hi, Self::TestsAndReceipts) => {
"เคเคฌ เคตเฅ เค
เคจเคฟเคถเฅเคเคฟเคคเคคเคพ เคธเคพเคฐเฅเคฅเค เคฐเฅเคช เคธเฅ เคเคเคพเคเค เคคเฅ เคเคฎเคพเคเคก, เคเฅเคธเฅเค, เคธเฅเคเฅเคฐเฅเคจเคถเฅเค เคฏเคพ เคเคฆเฅเคงเคฐเคฃ เคเคชเคฏเฅเค เคเคฐเฅเคเฅค"
}
(Locale::Hi, Self::ReleaseReceipts) => {
"เคฎเคนเคคเฅเคตเคชเฅเคฐเฅเคฃ เคฆเคพเคตเฅเค เคเคฐ เคฐเคฟเคฒเฅเคเคผ เคธเคพเคเฅเคทเฅเคฏ เคเฅ เคฒเคฟเค เคซเคผเคพเคเคฒ เคชเคฅ, เคเคฎเคพเคเคก, เคธเฅเคเฅเคฐเฅเคจเคถเฅเค, CI เคฏเคพ เคธเฅเคฐเฅเคค เคเคฆเฅเคงเฅเคค เคเคฐเฅเคเฅค"
}
(Locale::Ru, Self::Assumptions) => {
"ะัะตะถะดะต ัะตะผ ะทะฐัะฒะธัั ะพ ะทะฐะฒะตััะตะฝะธะธ, ะฟะตัะตัะธัะปะธัะต ะฟัะตะดะฟะพะปะพะถะตะฝะธั, ะฝะตะธะทะฒะตััะฝัะต ะธ ะพััะฐะฒัะธะตัั ัะธัะบะธ."
}
(Locale::Ru, Self::TestsAndReceipts) => {
"ะัะฟะพะปัะทัะนัะต ะบะพะผะฐะฝะดั, ัะตััั, ัะบัะธะฝัะพัั ะธะปะธ ัะธัะฐัั, ะบะพะณะดะฐ ะพะฝะธ ัััะตััะฒะตะฝะฝะพ ัะฝะธะถะฐัั ะฝะตะพะฟัะตะดะตะปัะฝะฝะพััั."
}
(Locale::Ru, Self::ReleaseReceipts) => {
"ะฃะบะฐะทัะฒะฐะนัะต ะฟััะธ ัะฐะนะปะพะฒ, ะบะพะผะฐะฝะดั, ัะบัะธะฝัะพัั, CI ะธะปะธ ะธััะพัะฝะธะบะธ ะดะปั ัััะตััะฒะตะฝะฝัั
ััะฒะตัะถะดะตะฝะธะน ะธ ะดะพะบะฐะทะฐัะตะปัััะฒ ัะตะปะธะทะฐ."
}
(Locale::Uk, Self::Assumptions) => {
"ะะตัั ะฝัะถ ะทะฐัะฒะธัะธ ะฟัะพ ะทะฐะฒะตััะตะฝะฝั, ะฟัะดััะผัะนัะต ะฟัะธะฟััะตะฝะฝั, ะฝะตะฒัะดะพะผั ัะฐ ะทะฐะปะธัะบะพะฒั ัะธะทะธะบะธ."
}
(Locale::Uk, Self::TestsAndReceipts) => {
"ะะธะบะพัะธััะพะฒัะนัะต ะบะพะผะฐะฝะดะธ, ัะตััะธ, ัะบัะธะฝัะพัะธ ะฐะฑะพ ัะธัะฐัะธ, ะบะพะปะธ ะฒะพะฝะธ ัััััะฒะพ ะทะผะตะฝััััั ะฝะตะฒะธะทะฝะฐัะตะฝัััั."
}
(Locale::Uk, Self::ReleaseReceipts) => {
"ะะพัะธะปะฐะนัะตัั ะฝะฐ ัะปัั
ะธ ัะฐะนะปัะฒ, ะบะพะผะฐะฝะดะธ, ัะบัะธะฝัะพัะธ, CI ะฐะฑะพ ะดะถะตัะตะปะฐ ะดะปั ัััััะฒะธั
ัะฒะตัะดะถะตะฝั ั ะดะพะบะฐะทัะฒ ัะตะปัะทั."
}
(_, Self::Assumptions) => {
"Summarize assumptions, unknowns, and remaining risk before claiming completion."
}
(_, Self::TestsAndReceipts) => {
"Use commands, tests, screenshots, or citations when they materially reduce uncertainty."
}
(_, Self::ReleaseReceipts) => {
"Cite file paths, commands, screenshots, CI, or sources for material claims and release evidence."
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum GuidedCommunication {
Concise,
Teaching,
Direct,
}
impl GuidedCommunication {
fn next(self) -> Self {
match self {
Self::Concise => Self::Teaching,
Self::Teaching => Self::Direct,
Self::Direct => Self::Concise,
}
}
fn label(self, locale: Locale) -> &'static str {
match (locale, self) {
(Locale::Ja, Self::Concise) => "็ฐกๆฝ",
(Locale::Ja, Self::Teaching) => "่ชฌๆ้่ฆ",
(Locale::Ja, Self::Direct) => "็ดๆฅ็",
(Locale::ZhHans, Self::Concise) => "็ฎๆด",
(Locale::ZhHans, Self::Teaching) => "ๆๅญฆๅผ",
(Locale::ZhHans, Self::Direct) => "็ดๆฅ",
(Locale::ZhHant, Self::Concise) => "็ฐกๆฝ",
(Locale::ZhHant, Self::Teaching) => "ๆๅญธๅผ",
(Locale::ZhHant, Self::Direct) => "็ดๆฅ",
(Locale::PtBr, Self::Concise) => "conciso",
(Locale::PtBr, Self::Teaching) => "didรกtico",
(Locale::PtBr, Self::Direct) => "direto",
(Locale::Es419, Self::Concise) => "conciso",
(Locale::Es419, Self::Teaching) => "didรกctico",
(Locale::Es419, Self::Direct) => "directo",
(Locale::Vi, Self::Concise) => "ngแบฏn gแปn",
(Locale::Vi, Self::Teaching) => "giแบฃng giแบฃi",
(Locale::Vi, Self::Direct) => "trแปฑc tiแบฟp",
(Locale::Ko, Self::Concise) => "๊ฐ๊ฒฐํจ",
(Locale::Ko, Self::Teaching) => "์ค๋ช
์ค์ฌ",
(Locale::Ko, Self::Direct) => "์ง์ค์ ",
(Locale::Ca, Self::Concise) => "concรญs",
(Locale::Ca, Self::Teaching) => "didร ctic",
(Locale::Ca, Self::Direct) => "directe",
(Locale::De, Self::Concise) => "prรคgnant",
(Locale::De, Self::Teaching) => "lehrend",
(Locale::De, Self::Direct) => "direkt",
(Locale::Fr, Self::Concise) => "concis",
(Locale::Fr, Self::Teaching) => "pรฉdagogique",
(Locale::Fr, Self::Direct) => "direct",
(Locale::Id, Self::Concise) => "ringkas",
(Locale::Id, Self::Teaching) => "mengajar",
(Locale::Id, Self::Direct) => "langsung",
(Locale::Hi, Self::Concise) => "เคธเคเคเฅเคทเคฟเคชเฅเคค",
(Locale::Hi, Self::Teaching) => "เคถเคฟเคเฅเคทเคฃเคชเคฐเค",
(Locale::Hi, Self::Direct) => "เคธเฅเคงเคพ",
(Locale::Ru, Self::Concise) => "ะบัะฐัะบะธะน",
(Locale::Ru, Self::Teaching) => "ะพะฑััะฐััะธะน",
(Locale::Ru, Self::Direct) => "ะฟััะผะพะน",
(Locale::Uk, Self::Concise) => "ััะธัะปะธะน",
(Locale::Uk, Self::Teaching) => "ะฝะฐะฒัะฐะปัะฝะธะน",
(Locale::Uk, Self::Direct) => "ะฟััะผะธะน",
(_, Self::Concise) => "concise",
(_, Self::Teaching) => "teaching",
(_, Self::Direct) => "direct",
}
}
fn working_style(self, locale: Locale) -> &'static str {
match (locale, self) {
(Locale::Ja, Self::Concise) => "ๆดๆฐใฏ็ฐกๆฝใซใใ้่ฆใชใใฌใผใใชใใ ใ็ญใ่ชฌๆใใใ",
(Locale::Ja, Self::Teaching) => {
"้่ฆใชๆจ่ซใจใใฌใผใใชใใใใฆใผใถใผใไป็ตใฟใ็่งฃใงใใ็จๅบฆใซ่ชฌๆใใใ"
}
(Locale::Ja, Self::Direct) => {
"้ปๅกใใชในใฏใไธ็ขบๅฎๆงใ็ดๆฅ่ฟฐในใ่ฃ
้ฃพ็ใชๆๆกใ้ฟใใใ"
}
(Locale::ZhHans, Self::Concise) => "ไฟๆๆดๆฐ็ฎๆด๏ผๅนถๅช่งฃ้้่ฆๅ่ใ",
(Locale::ZhHans, Self::Teaching) => "่งฃ้ๅ
ณ้ฎๆจ็ๅๅ่๏ผ่ฎฉ็จๆท่ฝ็่งฃ็ณป็ปใ",
(Locale::ZhHans, Self::Direct) => "็ดๆฅ่ฏดๆ้ปๅกใ้ฃ้ฉๅไธ็กฎๅฎๆง๏ผ้ฟๅ
่ฃ
้ฅฐๆงๆๆกใ",
(Locale::ZhHant, Self::Concise) => "ไฟๆๆดๆฐ็ฐกๆฝ๏ผไธฆๅช่งฃ้้่ฆๅๆจใ",
(Locale::ZhHant, Self::Teaching) => "่งฃ้้้ตๆจ็ๅๅๆจ๏ผ่ฎไฝฟ็จ่
่ฝ็่งฃ็ณป็ตฑใ",
(Locale::ZhHant, Self::Direct) => "็ดๆฅ่ชชๆ้ปๅกใ้ขจ้ชๅไธ็ขบๅฎๆง๏ผ้ฟๅ
่ฃ้ฃพๆงๆๆกใ",
(Locale::PtBr, Self::Concise) => {
"Mantenha atualizaรงรตes concisas e explique brevemente sรณ os tradeoffs importantes."
}
(Locale::PtBr, Self::Teaching) => {
"Explique raciocรญnio e tradeoffs principais o bastante para o usuรกrio entender o sistema."
}
(Locale::PtBr, Self::Direct) => {
"Seja direto sobre bloqueios, risco e incerteza; evite texto ornamental."
}
(Locale::Es419, Self::Concise) => {
"Mantรฉn las actualizaciones concisas y explica brevemente solo los tradeoffs importantes."
}
(Locale::Es419, Self::Teaching) => {
"Explica el razonamiento y los tradeoffs clave lo suficiente para que el usuario entienda el sistema."
}
(Locale::Es419, Self::Direct) => {
"Sรฉ directo sobre bloqueos, riesgo e incertidumbre; evita texto ornamental."
}
(Locale::Vi, Self::Concise) => {
"Giแปฏ cแบญp nhแบญt ngแบฏn gแปn vร chแป giแบฃi thรญch ngแบฏn cรกc ฤรกnh ฤแปi quan trแปng."
}
(Locale::Vi, Self::Teaching) => {
"Giแบฃi thรญch suy luแบญn vร ฤรกnh ฤแปi chรญnh ฤแปง ฤแป ngฦฐแปi dรนng hiแปu hแป thแปng."
}
(Locale::Vi, Self::Direct) => {
"Nรณi thแบณng vแป ฤiแปm chแบทn, rแปงi ro vร bแบฅt ฤแปnh; trรกnh cรขu chแปฏ trang trรญ."
}
(Locale::Ko, Self::Concise) => {
"์
๋ฐ์ดํธ๋ ๊ฐ๊ฒฐํ๊ฒ ์ ์งํ๊ณ , ์ค์ํ ํธ๋ ์ด๋์คํ๋ง ์งง๊ฒ ์ค๋ช
ํ๋ค."
}
(Locale::Ko, Self::Teaching) => {
"์ฌ์ฉ์๊ฐ ์์คํ
์ ์ดํดํ ์ ์์ ๋งํผ ํต์ฌ ์ถ๋ก ๊ณผ ํธ๋ ์ด๋์คํ๋ฅผ ์ค๋ช
ํ๋ค."
}
(Locale::Ko, Self::Direct) => {
"์ฐจ๋จ ์์ธ, ์ํ, ๋ถํ์ค์ฑ์ ์ง์ค์ ์ผ๋ก ๋งํ๊ณ ์ฅ์์ ์ธ ํํ์ ํผํ๋ค."
}
(Locale::Ca, Self::Concise) => {
"Mantรฉn les actualitzacions concises i explica breument nomรฉs els compromisos importants."
}
(Locale::Ca, Self::Teaching) => {
"Explica el raonament i els compromisos clau prou perquรจ l'usuari pugui entendre el sistema."
}
(Locale::Ca, Self::Direct) => {
"Sigues directe sobre bloquejos, risc i incertesa; evita el text ornamental."
}
(Locale::De, Self::Concise) => {
"Halte Aktualisierungen knapp und erklรคre wichtige Trade-offs nur kurz."
}
(Locale::De, Self::Teaching) => {
"Erklรคre zentrale Begrรผndungen und Trade-offs so weit, dass der Nutzer das System verstehen kann."
}
(Locale::De, Self::Direct) => {
"Sei direkt bei Blockern, Risiken und Unsicherheit; vermeide dekorative Formulierungen."
}
(Locale::Fr, Self::Concise) => {
"Gardez les mises ร jour concises et n'expliquez que briรจvement les arbitrages importants."
}
(Locale::Fr, Self::Teaching) => {
"Expliquez le raisonnement et les arbitrages clรฉs assez pour que l'utilisateur comprenne le systรจme."
}
(Locale::Fr, Self::Direct) => {
"Soyez direct sur les blocages, les risques et l'incertitude ; รฉvitez le texte ornemental."
}
(Locale::Id, Self::Concise) => {
"Jaga pembaruan tetap ringkas dan jelaskan tradeoff penting secara singkat."
}
(Locale::Id, Self::Teaching) => {
"Jelaskan penalaran dan tradeoff kunci secukupnya agar pengguna dapat memahami sistem."
}
(Locale::Id, Self::Direct) => {
"Bicara langsung soal penghambat, risiko, dan ketidakpastian; hindari teks hiasan."
}
(Locale::Hi, Self::Concise) => "เค
เคชเคกเฅเค เคธเคเคเฅเคทเคฟเคชเฅเคค เคฐเคเฅเค เคเคฐ เคฎเคนเคคเฅเคตเคชเฅเคฐเฅเคฃ เคเฅเคฐเฅเคกเคเคซเคผ เคธเคเคเฅเคทเฅเคช เคฎเฅเค เคธเคฎเคเคพเคเคเฅค",
(Locale::Hi, Self::Teaching) => {
"เคฎเฅเคเฅเคฏ เคคเคฐเฅเค เคเคฐ เคเฅเคฐเฅเคกเคเคซเคผ เคเคคเคจเคพ เคธเคฎเคเคพเคเค เคเคฟ เคเคชเคฏเฅเคเคเคฐเฅเคคเคพ เคธเคฟเคธเฅเคเคฎ เคธเคฎเค เคธเคเฅเฅค"
}
(Locale::Hi, Self::Direct) => {
"เคฐเฅเคเคพเคตเคเฅเค, เคเฅเคเคฟเคฎ เคเคฐ เค
เคจเคฟเคถเฅเคเคฟเคคเคคเคพ เคเฅ เคฌเคพเคฐเฅ เคฎเฅเค เคธเฅเคงเฅ เคฌเฅเคฒเฅเค; เคธเคเคพเคตเคเฅ เคญเคพเคทเคพ เคธเฅ เคฌเคเฅเคเฅค"
}
(Locale::Ru, Self::Concise) => {
"ะะตัะถะธัะต ะพะฑะฝะพะฒะปะตะฝะธั ะบัะฐัะบะธะผะธ ะธ ะปะธัั ะบะพัะพัะบะพ ะฟะพััะฝัะนัะต ะฒะฐะถะฝัะต ะบะพะผะฟัะพะผะธััั."
}
(Locale::Ru, Self::Teaching) => {
"ะะฑัััะฝัะนัะต ะบะปััะตะฒัะต ัะฐัััะถะดะตะฝะธั ะธ ะบะพะผะฟัะพะผะธััั ะฝะฐััะพะปัะบะพ, ััะพะฑั ะฟะพะปัะทะพะฒะฐัะตะปั ะผะพะณ ะฟะพะฝััั ัะธััะตะผั."
}
(Locale::Ru, Self::Direct) => {
"ะะพะฒะพัะธัะต ะฟััะผะพ ะพ ะฑะปะพะบะตัะฐั
, ัะธัะบะฐั
ะธ ะฝะตะพะฟัะตะดะตะปัะฝะฝะพััะธ; ะธะทะฑะตะณะฐะนัะต ะดะตะบะพัะฐัะธะฒะฝัั
ัะพัะผัะปะธัะพะฒะพะบ."
}
(Locale::Uk, Self::Concise) => {
"ะขัะธะผะฐะนัะต ะพะฝะพะฒะปะตะฝะฝั ััะธัะปะธะผะธ ะน ะปะธัะต ะบะพัะพัะบะพ ะฟะพััะฝัะนัะต ะฒะฐะถะปะธะฒั ะบะพะผะฟัะพะผััะธ."
}
(Locale::Uk, Self::Teaching) => {
"ะะพััะฝัะนัะต ะบะปััะพะฒั ะผััะบัะฒะฐะฝะฝั ัะฐ ะบะพะผะฟัะพะผััะธ ะฝะฐัััะปัะบะธ, ัะพะฑ ะบะพัะธัััะฒะฐั ะผัะณ ะทัะพะทัะผััะธ ัะธััะตะผั."
}
(Locale::Uk, Self::Direct) => {
"ะะพะฒะพัััั ะฟััะผะพ ะฟัะพ ะฑะปะพะบะตัะธ, ัะธะทะธะบะธ ัะฐ ะฝะตะฒะธะทะฝะฐัะตะฝัััั; ัะฝะธะบะฐะนัะต ะดะตะบะพัะฐัะธะฒะฝะธั
ัะพัะผัะปัะฒะฐะฝั."
}
(_, Self::Concise) => "Keep updates concise and explain important tradeoffs briefly.",
(_, Self::Teaching) => {
"Explain key reasoning and tradeoffs enough that the user can learn the system."
}
(_, Self::Direct) => {
"Be direct about blockers, risk, and uncertainty; avoid ornamental copy."
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum GuidedPrivacy {
StandardCare,
StrictBoundaries,
ProjectLocal,
}
impl GuidedPrivacy {
fn next(self) -> Self {
match self {
Self::StandardCare => Self::StrictBoundaries,
Self::StrictBoundaries => Self::ProjectLocal,
Self::ProjectLocal => Self::StandardCare,
}
}
fn label(self, locale: Locale) -> &'static str {
match (locale, self) {
(Locale::Ja, Self::StandardCare) => "ๆจๆบไฟ่ญท",
(Locale::Ja, Self::StrictBoundaries) => "ๅณๆ ผใชๅข็",
(Locale::Ja, Self::ProjectLocal) => "ใใญใธใงใฏใๅ
ใกใขใช",
(Locale::ZhHans, Self::StandardCare) => "ๆ ๅไฟๆค",
(Locale::ZhHans, Self::StrictBoundaries) => "ไธฅๆ ผ่พน็",
(Locale::ZhHans, Self::ProjectLocal) => "้กน็ฎๅ
่ฎฐๅฟ",
(Locale::ZhHant, Self::StandardCare) => "ๆจๆบไฟ่ญท",
(Locale::ZhHant, Self::StrictBoundaries) => "ๅดๆ ผ้็",
(Locale::ZhHant, Self::ProjectLocal) => "ๅฐๆกๅ
ง่จๆถ",
(Locale::PtBr, Self::StandardCare) => "cuidado padrรฃo",
(Locale::PtBr, Self::StrictBoundaries) => "limites estritos",
(Locale::PtBr, Self::ProjectLocal) => "memรณria local do projeto",
(Locale::Es419, Self::StandardCare) => "cuidado estรกndar",
(Locale::Es419, Self::StrictBoundaries) => "lรญmites estrictos",
(Locale::Es419, Self::ProjectLocal) => "memoria local del proyecto",
(Locale::Vi, Self::StandardCare) => "bแบฃo vแป tiรชu chuแบฉn",
(Locale::Vi, Self::StrictBoundaries) => "ranh giแปi nghiรชm ngแบทt",
(Locale::Vi, Self::ProjectLocal) => "bแป nhแป trong dแปฑ รกn",
(Locale::Ko, Self::StandardCare) => "ํ์ค ๋ณดํธ",
(Locale::Ko, Self::StrictBoundaries) => "์๊ฒฉํ ๊ฒฝ๊ณ",
(Locale::Ko, Self::ProjectLocal) => "ํ๋ก์ ํธ ๋ด ๋ฉ๋ชจ๋ฆฌ",
(Locale::Ca, Self::StandardCare) => "cura estร ndard",
(Locale::Ca, Self::StrictBoundaries) => "lรญmits estrictes",
(Locale::Ca, Self::ProjectLocal) => "memรฒria local del projecte",
(Locale::De, Self::StandardCare) => "Standardvorsorge",
(Locale::De, Self::StrictBoundaries) => "strenge Grenzen",
(Locale::De, Self::ProjectLocal) => "projektlokaler Speicher",
(Locale::Fr, Self::StandardCare) => "soin standard",
(Locale::Fr, Self::StrictBoundaries) => "limites strictes",
(Locale::Fr, Self::ProjectLocal) => "mรฉmoire locale au projet",
(Locale::Id, Self::StandardCare) => "perlindungan standar",
(Locale::Id, Self::StrictBoundaries) => "batasan ketat",
(Locale::Id, Self::ProjectLocal) => "memori lokal proyek",
(Locale::Hi, Self::StandardCare) => "เคฎเคพเคจเค เคธเคพเคตเคงเคพเคจเฅ",
(Locale::Hi, Self::StrictBoundaries) => "เคธเคเฅเคค เคธเฅเคฎเคพเคเค",
(Locale::Hi, Self::ProjectLocal) => "เคชเฅเคฐเฅเคเฅเคเฅเค-เคธเฅเคฅเคพเคจเฅเคฏ เคฎเฅเคฎเฅเคฐเฅ",
(Locale::Ru, Self::StandardCare) => "ััะฐะฝะดะฐััะฝะฐั ะพััะพัะพะถะฝะพััั",
(Locale::Ru, Self::StrictBoundaries) => "ัััะพะณะธะต ะณัะฐะฝะธัั",
(Locale::Ru, Self::ProjectLocal) => "ะฟะฐะผััั ะฒะฝัััะธ ะฟัะพะตะบัะฐ",
(Locale::Uk, Self::StandardCare) => "ััะฐะฝะดะฐััะฝะฐ ะพะฑะตัะตะถะฝัััั",
(Locale::Uk, Self::StrictBoundaries) => "ััะฒะพัั ะผะตะถั",
(Locale::Uk, Self::ProjectLocal) => "ะฟะฐะผ'ััั ั ะผะตะถะฐั
ะฟัะพัะบัั",
(_, Self::StandardCare) => "standard care",
(_, Self::StrictBoundaries) => "strict boundaries",
(_, Self::ProjectLocal) => "project-local memory",
}
}
fn working_style(self, locale: Locale) -> &'static str {
match (locale, self) {
(Locale::Ja, Self::StandardCare) => {
"็งๅฏๆ
ๅ ฑใใฆใผใถใผใใกใคใซใGit ๅฑฅๆญดใๆฌ็ชใทในใใ ใใณในใใใใฉใคใใทใผใๆ้ใไฟ่ญทใใใ"
}
(Locale::Ja, Self::StrictBoundaries) => {
"็งๅฏใๅไบบใใผใฟใ่ช่จผๆ
ๅ ฑใๆฌ็ช็ถๆ
ใ่ณ้ใๅ
ฌ้ๆไฝใฏใๅ
ใซ็ขบ่ชใใๅข็ใจใใฆๆฑใใ"
}
(Locale::Ja, Self::ProjectLocal) => {
"ใใญใธใงใฏใๅบๆใฎๆ่ใฏใใญใธใงใฏใๅ
ใซ็ใใๆ็คบ่ฆๆฑใใชใ้ใใกใขใชใธๆธใใชใใ"
}
(Locale::ZhHans, Self::StandardCare) => {
"ไฟๆคๅฏ้ฅใ็จๆทๆไปถใGit ๅๅฒใ็ไบง็ณป็ปใๆๆฌใ้็งๅๆถ้ดใ"
}
(Locale::ZhHans, Self::StrictBoundaries) => {
"ๆๅฏ้ฅใไธชไบบๆฐๆฎใๅญๆฎใ็ไบง็ถๆใ่ต้ๅๅๅธๅจไฝ่งไธบๅ
็กฎ่ฎค่พน็ใ"
}
(Locale::ZhHans, Self::ProjectLocal) => {
"้กน็ฎ็นๅฎไธไธๆ็ๅจ้กน็ฎๅ
๏ผ้ค้ๆ็กฎ่ฆๆฑ๏ผๅฆๅไธ่ฆๅๅ
ฅ่ฎฐๅฟใ"
}
(Locale::ZhHant, Self::StandardCare) => {
"ไฟ่ญทๅฏ้ฐใไฝฟ็จ่
ๆชๆกใGit ๆญทๅฒใ็็ข็ณป็ตฑใๆๆฌใ้ฑ็งๅๆ้ใ"
}
(Locale::ZhHant, Self::StrictBoundaries) => {
"ๆๅฏ้ฐใๅไบบ่ณๆใๆๆใ็็ข็ๆ
ใ่ณ้ๅ็ผๅธๅไฝ่ฆ็บๅ
็ขบ่ช้็ใ"
}
(Locale::ZhHant, Self::ProjectLocal) => {
"ๅฐๆก็นๅฎไธไธๆ็ๅจๅฐๆกๅ
ง๏ผ้ค้ๆ็ขบ่ฆๆฑ๏ผๅฆๅไธ่ฆๅฏซๅ
ฅ่จๆถใ"
}
(Locale::PtBr, Self::StandardCare) => {
"Proteja segredos, arquivos do usuรกrio, histรณrico git, produรงรฃo, custo, privacidade e tempo."
}
(Locale::PtBr, Self::StrictBoundaries) => {
"Trate segredos, dados pessoais, credenciais, estado de produรงรฃo, dinheiro e publicaรงรตes como limites de confirmaรงรฃo."
}
(Locale::PtBr, Self::ProjectLocal) => {
"Mantenha contexto especรญfico do projeto no projeto; evite gravar na memรณria sem pedido explรญcito."
}
(Locale::Es419, Self::StandardCare) => {
"Protege secretos, archivos del usuario, historial git, producciรณn, costo, privacidad y tiempo."
}
(Locale::Es419, Self::StrictBoundaries) => {
"Trata secretos, datos personales, credenciales, estado de producciรณn, dinero y publicaciones como lรญmites de confirmaciรณn."
}
(Locale::Es419, Self::ProjectLocal) => {
"Mantรฉn el contexto especรญfico del proyecto en el proyecto; evita llevarlo a memoria sin pedido explรญcito."
}
(Locale::Vi, Self::StandardCare) => {
"Bแบฃo vแป bรญ mแบญt, tแปp ngฦฐแปi dรนng, lแปch sแปญ git, hแป thแปng sแบฃn xuแบฅt, chi phรญ, riรชng tฦฐ vร thแปi gian."
}
(Locale::Vi, Self::StrictBoundaries) => {
"Xem bรญ mแบญt, dแปฏ liแปu cรก nhรขn, thรดng tin xรกc thแปฑc, trแบกng thรกi sแบฃn xuแบฅt, tiแปn vร xuแบฅt bแบฃn lร ranh giแปi cแบงn xรกc nhแบญn."
}
(Locale::Vi, Self::ProjectLocal) => {
"Giแปฏ ngแปฏ cแบฃnh riรชng cแปงa dแปฑ รกn trong dแปฑ รกn; trรกnh ghi vร o bแป nhแป nแบฟu khรดng ฤฦฐแปฃc yรชu cแบงu rรต."
}
(Locale::Ko, Self::StandardCare) => {
"๋น๋ฐ ์ ๋ณด, ์ฌ์ฉ์ ํ์ผ, Git ์ด๋ ฅ, ํ๋ก๋์
์์คํ
, ๋น์ฉ, ํ๋ผ์ด๋ฒ์, ์๊ฐ์ ๋ณดํธํ๋ค."
}
(Locale::Ko, Self::StrictBoundaries) => {
"๋น๋ฐ ์ ๋ณด, ๊ฐ์ธ ๋ฐ์ดํฐ, ์๊ฒฉ ์ฆ๋ช
, ํ๋ก๋์
์ํ, ์๊ธ, ๊ฒ์ ์์
์ ๋จผ์ ํ์ธํ๋ ๊ฒฝ๊ณ๋ก ์ทจ๊ธํ๋ค."
}
(Locale::Ko, Self::ProjectLocal) => {
"ํ๋ก์ ํธ ๊ณ ์ ๋งฅ๋ฝ์ ํ๋ก์ ํธ ์์ ๋๊ณ , ๋ช
์์ ์ผ๋ก ์์ฒญ๋ฐ์ง ์๋ ํ ๋ฉ๋ชจ๋ฆฌ์ ์ฐ์ง ์๋๋ค."
}
(Locale::Ca, Self::StandardCare) => {
"Protegeix secrets, fitxers de l'usuari, historial de git, sistemes de producciรณ, cost, privacitat i temps."
}
(Locale::Ca, Self::StrictBoundaries) => {
"Tracta secrets, dades personals, credencials, estat de producciรณ, diners i accions de publicaciรณ com a lรญmits que cal confirmar primer."
}
(Locale::Ca, Self::ProjectLocal) => {
"Mantรฉn el context especรญfic del projecte dins del projecte; evita portar-lo a la memรฒria si no se't demana explรญcitament."
}
(Locale::De, Self::StandardCare) => {
"Schรผtze Geheimnisse, Nutzerdateien, Git-Verlauf, Produktionssysteme, Kosten, Privatsphรคre und Zeit."
}
(Locale::De, Self::StrictBoundaries) => {
"Behandle Geheimnisse, persรถnliche Daten, Zugangsdaten, Produktionszustand, Geld und Verรถffentlichungen als Grenzen, die erst bestรคtigt werden."
}
(Locale::De, Self::ProjectLocal) => {
"Halte projektspezifischen Kontext im Projekt; vermeide es, sensible Details ohne ausdrรผckliche Bitte in den Speicher zu รผbernehmen."
}
(Locale::Fr, Self::StandardCare) => {
"Protรฉgez secrets, fichiers utilisateur, historique git, systรจmes de production, coรปt, vie privรฉe et temps."
}
(Locale::Fr, Self::StrictBoundaries) => {
"Traitez secrets, donnรฉes personnelles, identifiants, รฉtat de production, argent et publications comme des limites exigeant confirmation."
}
(Locale::Fr, Self::ProjectLocal) => {
"Gardez le contexte propre au projet dans le projet ; รฉvitez de l'รฉcrire en mรฉmoire sans demande explicite."
}
(Locale::Id, Self::StandardCare) => {
"Lindungi rahasia, file pengguna, riwayat git, sistem produksi, biaya, privasi, dan waktu."
}
(Locale::Id, Self::StrictBoundaries) => {
"Perlakukan rahasia, data pribadi, kredensial, status produksi, uang, dan tindakan publikasi sebagai batas yang harus dikonfirmasi dulu."
}
(Locale::Id, Self::ProjectLocal) => {
"Simpan konteks khusus proyek di dalam proyek; hindari membawanya ke memori kecuali diminta secara eksplisit."
}
(Locale::Hi, Self::StandardCare) => {
"เคฐเคนเคธเฅเคฏเฅเค, เคเคชเคฏเฅเคเคเคฐเฅเคคเคพ เคซเคผเคพเคเคฒเฅเค, git เคเคคเคฟเคนเคพเคธ, เคชเฅเคฐเฅเคกเคเฅเคถเคจ เคธเคฟเคธเฅเคเคฎ, เคฒเคพเคเคค, เคเฅเคชเคจเฅเคฏเคคเคพ เคเคฐ เคธเคฎเคฏ เคเฅ เคฐเคเฅเคทเคพ เคเคฐเฅเคเฅค"
}
(Locale::Hi, Self::StrictBoundaries) => {
"เคฐเคนเคธเฅเคฏเฅเค, เคตเฅเคฏเคเฅเคคเคฟเคเคค เคกเฅเคเคพ, เคเฅเคฐเฅเคกเฅเคเคถเคฟเคฏเคฒ, เคชเฅเคฐเฅเคกเคเฅเคถเคจ เคธเฅเคฅเคฟเคคเคฟ, เคงเคจ เคเคฐ เคชเฅเคฐเคเคพเคถเคจ เคเฅเคฐเคฟเคฏเคพเคเค เคเฅ เคชเคนเคฒเฅ-เคชเฅเคทเฅเคเคฟ เคธเฅเคฎเคพเคเค เคเฅ เคคเคฐเคน เคฎเคพเคจเฅเคเฅค"
}
(Locale::Hi, Self::ProjectLocal) => {
"เคชเฅเคฐเฅเคเฅเคเฅเค-เคตเคฟเคถเคฟเคทเฅเค เคธเคเคฆเคฐเฅเคญ เคชเฅเคฐเฅเคเฅเคเฅเค เคเฅ เคญเฅเคคเคฐ เคฐเคเฅเค; เคธเฅเคชเคทเฅเค เค
เคจเฅเคฐเฅเคง เคเฅ เคฌเคฟเคจเคพ เคธเคเคตเฅเคฆเคจเคถเฅเคฒ เคตเคฟเคตเคฐเคฃ เคฎเฅเคฎเฅเคฐเฅ เคฎเฅเค เคจ เคฒเฅ เคเคพเคเคเฅค"
}
(Locale::Ru, Self::StandardCare) => {
"ะะฐัะธัะฐะนัะต ัะตะบัะตัั, ัะฐะนะปั ะฟะพะปัะทะพะฒะฐัะตะปั, ะธััะพัะธั git, production-ัะธััะตะผั, ะทะฐััะฐัั, ะฟัะธะฒะฐัะฝะพััั ะธ ะฒัะตะผั."
}
(Locale::Ru, Self::StrictBoundaries) => {
"ะกัะธัะฐะนัะต ัะตะบัะตัั, ะฟะตััะพะฝะฐะปัะฝัะต ะดะฐะฝะฝัะต, ััััะฝัะต ะดะฐะฝะฝัะต, production-ัะพััะพัะฝะธะต, ะดะตะฝัะณะธ ะธ ะฟัะฑะปะธะบะฐัะธะธ ะณัะฐะฝะธัะฐะผะธ, ััะตะฑัััะธะผะธ ะฟะพะดัะฒะตัะถะดะตะฝะธั."
}
(Locale::Ru, Self::ProjectLocal) => {
"ะะตัะถะธัะต ะบะพะฝัะตะบัั, ัะฟะตัะธัะธัะฝัะน ะดะปั ะฟัะพะตะบัะฐ, ะฒะฝัััะธ ะฟัะพะตะบัะฐ; ะฝะต ะฟะตัะตะฝะพัะธัะต ััะฒััะฒะธัะตะปัะฝัะต ะดะตัะฐะปะธ ะฒ ะฟะฐะผััั ะฑะตะท ัะฒะฝะพะณะพ ะทะฐะฟัะพัะฐ."
}
(Locale::Uk, Self::StandardCare) => {
"ะะฐั
ะธัะฐะนัะต ัะตะบัะตัะธ, ัะฐะนะปะธ ะบะพัะธัััะฒะฐัะฐ, ัััะพััั git, production-ัะธััะตะผะธ, ะฒะธััะฐัะธ, ะฟัะธะฒะฐัะฝัััั ั ัะฐั."
}
(Locale::Uk, Self::StrictBoundaries) => {
"ะะฒะฐะถะฐะนัะต ัะตะบัะตัะธ, ะฟะตััะพะฝะฐะปัะฝั ะดะฐะฝั, ะพะฑะปัะบะพะฒั ะดะฐะฝั, production-ััะฐะฝ, ะณัะพัั ัะฐ ะฟัะฑะปัะบะฐััั ะผะตะถะฐะผะธ, ัะพ ะฟะพััะตะฑัััั ะฟัะดัะฒะตัะดะถะตะฝะฝั."
}
(Locale::Uk, Self::ProjectLocal) => {
"ะขัะธะผะฐะนัะต ะบะพะฝัะตะบัั, ัะฟะตัะธัััะฝะธะน ะดะปั ะฟัะพัะบัั, ะฒัะตัะตะดะธะฝั ะฟัะพัะบัั; ะฝะต ะฟะตัะตะฝะพัััะต ัััะปะธะฒั ะดะตัะฐะปั ะฒ ะฟะฐะผ'ััั ะฑะตะท ัะฒะฝะพะณะพ ะทะฐะฟะธัั."
}
(_, Self::StandardCare) => {
"Protect secrets, user files, git history, production systems, cost, privacy, and time."
}
(_, Self::StrictBoundaries) => {
"Treat secrets, personal data, credentials, production state, money, and publish actions as stop-and-confirm boundaries."
}
(_, Self::ProjectLocal) => {
"Keep project-specific context local; avoid carrying sensitive details into memory unless explicitly asked."
}
}
}
fn escalation_rule(self, locale: Locale) -> &'static str {
match (locale, self) {
(Locale::Ja, Self::StandardCare) => {
"็ ดๅฃ็ใ้ซใณในใใ่ช่จผๆ
ๅ ฑใๅ
ฌ้ใๆณๅใใปใญใฅใชใใฃใชในใฏใฎใใๆไฝใฎๅใซๅฐใญใใ"
}
(Locale::Ja, Self::StrictBoundaries) => {
"ๆฉๅพฎๆ
ๅ ฑใฎ่ชญใฟๅใใๆกๆฃใๆฌ็ชใทในใใ ๆไฝใๆฏๅบใๅ
ฌ้ใฎๅใซๅๆญขใใฆๅฐใญใใ"
}
(Locale::Ja, Self::ProjectLocal) => {
"ใใญใธใงใฏใ่ฉณ็ดฐใใกใขใชใใฏใผใฏในใใผในใๅคใๅผใ็ถใใธๆใกๅบใๅใซ็ขบ่ชใใใ"
}
(Locale::ZhHans, Self::StandardCare) => {
"้ๅฐ็ ดๅๆงใ้ซๆๆฌใๅญๆฎใๅๅธใๆณๅพๆๅฎๅ
จ้ฃ้ฉๆไฝๆถๅ
่ฏข้ฎใ"
}
(Locale::ZhHans, Self::StrictBoundaries) => {
"ๅจ่ฏปๅๆไผ ๆญๆๆไฟกๆฏใ่งฆ็ขฐ็ไบง็ณป็ปใ่ฑ่ดน่ต้ๆๅๅธๅ
ๅฎนๅๅๆญขๅนถ่ฏข้ฎใ"
}
(Locale::ZhHans, Self::ProjectLocal) => {
"้่ฆ่ทจ้กน็ฎ่ฎฐๅฟใๅคๅถ้กน็ฎ็ป่ๆๅผ็จๆงไบคๆฅๆถ๏ผๅ
็กฎ่ฎค่ฟไบไธไธๆไป้็จใ"
}
(Locale::ZhHant, Self::StandardCare) => {
"้ๅฐ็ ดๅฃๆงใ้ซๆๆฌใๆๆใ็ผๅธใๆณๅพๆๅฎๅ
จ้ขจ้ชๆไฝๆๅ
่ฉขๅใ"
}
(Locale::ZhHant, Self::StrictBoundaries) => {
"ๅจ่ฎๅๆๅณๆญๆๆ่ณ่จใ่งธ็ขฐ็็ข็ณป็ตฑใ่ฑ่ฒป่ณ้ๆ็ผๅธๅ
งๅฎนๅๅๆญขไธฆ่ฉขๅใ"
}
(Locale::ZhHant, Self::ProjectLocal) => {
"้่ฆ่ทจๅฐๆก่จๆถใ่ค่ฃฝๅฐๆก็ดฐ็ฏๆๅผ็จ่ไบคๆฅๆ๏ผๅ
็ขบ่ช้ไบไธไธๆไป้ฉ็จใ"
}
(Locale::PtBr, Self::StandardCare) => {
"Pergunte antes de aรงรตes destrutivas, caras, com credenciais, publicaรงรฃo, risco legal ou de seguranรงa."
}
(Locale::PtBr, Self::StrictBoundaries) => {
"Pare e pergunte antes de ler ou espalhar dados sensรญveis, tocar produรงรฃo, gastar dinheiro ou publicar."
}
(Locale::PtBr, Self::ProjectLocal) => {
"Confirme antes de levar detalhes do projeto para memรณria, workspaces ou handoffs antigos."
}
(Locale::Es419, Self::StandardCare) => {
"Pregunta antes de acciones destructivas, costosas, con credenciales, publicaciรณn o riesgo legal/de seguridad."
}
(Locale::Es419, Self::StrictBoundaries) => {
"Detente y pregunta antes de leer o difundir datos sensibles, tocar producciรณn, gastar dinero o publicar."
}
(Locale::Es419, Self::ProjectLocal) => {
"Confirma antes de llevar detalles del proyecto a memoria, workspaces o handoffs viejos."
}
(Locale::Vi, Self::StandardCare) => {
"Hแปi trฦฐแปc cรกc thao tรกc phรก hแปงy, tแปn kรฉm, liรชn quan thรดng tin xรกc thแปฑc, xuแบฅt bแบฃn, phรกp lรฝ hoแบทc bแบฃo mแบญt."
}
(Locale::Vi, Self::StrictBoundaries) => {
"Dแปซng vร hแปi trฦฐแปc khi ฤแปc/phรกt tรกn dแปฏ liแปu nhแบกy cแบฃm, chแบกm sแบฃn xuแบฅt, chi tiแปn hoแบทc xuแบฅt bแบฃn."
}
(Locale::Vi, Self::ProjectLocal) => {
"Xรกc nhแบญn trฦฐแปc khi mang chi tiแบฟt dแปฑ รกn sang bแป nhแป, workspace khรกc hoแบทc handoff cลฉ."
}
(Locale::Ko, Self::StandardCare) => {
"ํ๊ดด์ ์ด๊ฑฐ๋, ๋น์ฉ์ด ํฌ๊ฑฐ๋, ์๊ฒฉ ์ฆ๋ช
, ๊ฒ์, ๋ฒ์ , ๋ณด์ ์ํ์ด ์๋ ์์
์ ์ ๋จผ์ ๋ฌผ์ด๋ณธ๋ค."
}
(Locale::Ko, Self::StrictBoundaries) => {
"๋ฏผ๊ฐ ์ ๋ณด๋ฅผ ์ฝ๊ฑฐ๋ ํผ๋จ๋ฆฌ๊ธฐ ์ , ํ๋ก๋์
์์คํ
์ ๊ฑด๋๋ฆฌ๊ธฐ ์ , ์๊ธ์ ์ฐ๊ฑฐ๋ ๊ฒ์ํ๊ธฐ ์ ์ ๋ฉ์ถ๊ณ ๋ฌผ์ด๋ณธ๋ค."
}
(Locale::Ko, Self::ProjectLocal) => {
"ํ๋ก์ ํธ ์ธ๋ถ ์ ๋ณด๋ฅผ ๋ฉ๋ชจ๋ฆฌ, ๋ค๋ฅธ ์ํฌ์คํ์ด์ค, ์ค๋๋ ์ธ๊ณ ์๋ฃ๋ก ์ฎ๊ธฐ๊ธฐ ์ ์ ํ์ธํ๋ค."
}
(Locale::Ca, Self::StandardCare) => {
"Pregunta abans d'accions destructives, costoses, amb credencials, de publicaciรณ o amb risc legal o de seguretat."
}
(Locale::Ca, Self::StrictBoundaries) => {
"Atura't i pregunta abans de llegir o difondre dades sensibles, tocar sistemes de producciรณ, gastar diners o publicar."
}
(Locale::Ca, Self::ProjectLocal) => {
"Confirma abans de portar detalls del projecte a la memรฒria, a altres espais de treball o a traspasos antics."
}
(Locale::De, Self::StandardCare) => {
"Frage vor destruktiven, kostspieligen, zugangsdatenbezogenen, verรถffentlichenden, rechtlichen oder sicherheitskritischen Aktionen."
}
(Locale::De, Self::StrictBoundaries) => {
"Halte an und frage, bevor du sensible Daten liest oder verbreitest, Produktionssysteme anfasst, Geld ausgibst oder verรถffentlichst."
}
(Locale::De, Self::ProjectLocal) => {
"Bestรคtige, bevor du Projektdetails in Speicher, Workspaces oder veraltete รbergaben รผbertrรคgst."
}
(Locale::Fr, Self::StandardCare) => {
"Demandez avant toute action destructive, coรปteuse, impliquant des identifiants, une publication, ou un risque juridique ou de sรฉcuritรฉ."
}
(Locale::Fr, Self::StrictBoundaries) => {
"Arrรชtez et demandez avant de lire ou diffuser des donnรฉes sensibles, de toucher aux systรจmes de production, de dรฉpenser de l'argent ou de publier."
}
(Locale::Fr, Self::ProjectLocal) => {
"Confirmez avant de transporter des dรฉtails du projet vers la mรฉmoire, d'autres espaces de travail ou d'anciens transferts."
}
(Locale::Id, Self::StandardCare) => {
"Tanya sebelum tindakan destruktif, mahal, terkait kredensial, publikasi, hukum, atau berisiko keamanan."
}
(Locale::Id, Self::StrictBoundaries) => {
"Berhenti dan tanya sebelum membaca atau menyebarkan data sensitif, menyentuh sistem produksi, membelanjakan uang, atau mempublikasikan."
}
(Locale::Id, Self::ProjectLocal) => {
"Konfirmasi sebelum membawa detail proyek ke memori, workspace lain, atau handoff lama."
}
(Locale::Hi, Self::StandardCare) => {
"เคตเคฟเคจเคพเคถเคเคพเคฐเฅ, เคเคเฅเค-เคฒเคพเคเคค, เคเฅเคฐเฅเคกเฅเคเคถเคฟเคฏเคฒ, เคชเฅเคฐเคเคพเคถเคจ, เคเคพเคจเฅเคจเฅ เคฏเคพ เคธเฅเคฐเคเฅเคทเคพ-เคเฅเคเคฟเคฎ เคเคพเคฐเฅเคฏเฅเค เคธเฅ เคชเคนเคฒเฅ เคชเฅเคเฅเคเฅค"
}
(Locale::Hi, Self::StrictBoundaries) => {
"เคธเคเคตเฅเคฆเคจเคถเฅเคฒ เคกเฅเคเคพ เคชเคขเคผเคจเฅ เคฏเคพ เคซเฅเคฒเคพเคจเฅ, เคชเฅเคฐเฅเคกเคเฅเคถเคจ เคธเคฟเคธเฅเคเคฎ เคเฅเคจเฅ, เคงเคจ เคเคฐเฅเค เคเคฐเคจเฅ เคฏเคพ เคชเฅเคฐเคเคพเคถเคฟเคค เคเคฐเคจเฅ เคธเฅ เคชเคนเคฒเฅ เคฐเฅเคเคเคฐ เคชเฅเคเฅเคเฅค"
}
(Locale::Hi, Self::ProjectLocal) => {
"เคชเฅเคฐเฅเคเฅเคเฅเค เคตเคฟเคตเคฐเคฃ เคฎเฅเคฎเฅเคฐเฅ, เค
เคจเฅเคฏ เคเคพเคฐเฅเคฏเคเฅเคทเฅเคคเฅเคฐเฅเค เคฏเคพ เคชเฅเคฐเคพเคจเฅ เคนเฅเคเคกเคเคซเคผ เคฎเฅเค เคฒเฅ เคเคพเคจเฅ เคธเฅ เคชเคนเคฒเฅ เคชเฅเคทเฅเคเคฟ เคเคฐเฅเคเฅค"
}
(Locale::Ru, Self::StandardCare) => {
"ะกะฟัะฐัะธะฒะฐะนัะต ะฟะตัะตะด ะดะตััััะบัะธะฒะฝัะผะธ, ะดะพัะพะณะธะผะธ, ัะฒัะทะฐะฝะฝัะผะธ ั ััััะฝัะผะธ ะดะฐะฝะฝัะผะธ, ะฟัะฑะปะธะบะฐัะธะตะน, ััะธะดะธัะตัะบะธะผะธ ะธะปะธ ัะณัะพะถะฐััะธะผะธ ะฑะตะทะพะฟะฐัะฝะพััะธ ะดะตะนััะฒะธัะผะธ."
}
(Locale::Ru, Self::StrictBoundaries) => {
"ะััะฐะฝะพะฒะธัะตัั ะธ ัะฟัะพัะธัะต, ะฟัะตะถะดะต ัะตะผ ัะธัะฐัั ะธะปะธ ัะฐัะฟัะพัััะฐะฝััั ััะฒััะฒะธัะตะปัะฝัะต ะดะฐะฝะฝัะต, ััะพะณะฐัั production-ัะธััะตะผั, ััะฐัะธัั ะดะตะฝัะณะธ ะธะปะธ ะฟัะฑะปะธะบะพะฒะฐัั."
}
(Locale::Ru, Self::ProjectLocal) => {
"ะะพะดัะฒะตัะดะธัะต, ะฟัะตะถะดะต ัะตะผ ะฟะตัะตะฝะพัะธัั ะดะตัะฐะปะธ ะฟัะพะตะบัะฐ ะฒ ะฟะฐะผััั, ะดััะณะธะต ัะฐะฑะพัะธะต ะพะฑะปะฐััะธ ะธะปะธ ัััะฐัะตะฒัะธะต ะฟะตัะตะดะฐัะพัะฝัะต ะทะฐะผะตัะบะธ."
}
(Locale::Uk, Self::StandardCare) => {
"ะะธัะฐะนัะต ะฟะตัะตะด ััะนะฝัะฒะฝะธะผะธ, ะดะพัะพะณะธะผะธ, ะฟะพะฒ'ัะทะฐะฝะธะผะธ ะท ะพะฑะปัะบะพะฒะธะผะธ ะดะฐะฝะธะผะธ, ะฟัะฑะปัะบะฐัััั, ััะธะดะธัะฝะธะผะธ ัะธ ะฝะตะฑะตะทะฟะตัะฝะธะผะธ ะดะปั ะฑะตะทะฟะตะบะธ ะดััะผะธ."
}
(Locale::Uk, Self::StrictBoundaries) => {
"ะัะฟะธะฝััััั ะน ะทะฐะฟะธัะฐะนัะต, ะฟะตัั ะฝัะถ ัะธัะฐัะธ ัะธ ะฟะพัะธััะฒะฐัะธ ัััะปะธะฒั ะดะฐะฝั, ััะฟะฐัะธ production-ัะธััะตะผะธ, ะฒะธััะฐัะฐัะธ ะณัะพัั ะฐะฑะพ ะฟัะฑะปัะบัะฒะฐัะธ."
}
(Locale::Uk, Self::ProjectLocal) => {
"ะัะดัะฒะตัะดััะต, ะฟะตัั ะฝัะถ ะฟะตัะตะฝะพัะธัะธ ะดะตัะฐะปั ะฟัะพัะบัั ะฒ ะฟะฐะผ'ััั, ัะฝัั ัะพะฑะพัั ะฟัะพััะพัะธ ัะธ ะทะฐััะฐััะปั ะฟะตัะตะดะฐัะพัะฝั ะฝะพัะฐัะบะธ."
}
(_, Self::StandardCare) => {
"Ask before destructive, high-cost, credential, publishing, legal, or security-risk actions."
}
(_, Self::StrictBoundaries) => {
"Stop and ask before reading or spreading sensitive data, touching production systems, spending money, or publishing."
}
(_, Self::ProjectLocal) => {
"Confirm before carrying project details across memory, workspaces, or stale handoffs."
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum GuidedPrinciples {
ScopedChanges,
UserVoice,
ReversibleOps,
}
impl GuidedPrinciples {
fn next(self) -> Self {
match self {
Self::ScopedChanges => Self::UserVoice,
Self::UserVoice => Self::ReversibleOps,
Self::ReversibleOps => Self::ScopedChanges,
}
}
fn label(self, locale: Locale) -> &'static str {
match (locale, self) {
(Locale::Ja, Self::ScopedChanges) => "ๅฐใใ็ตใฃใๅคๆด",
(Locale::Ja, Self::UserVoice) => "ใฆใผใถใผใฎๅฃฐใไฟใค",
(Locale::Ja, Self::ReversibleOps) => "ๅฏ้ๆ้ ",
(Locale::ZhHans, Self::ScopedChanges) => "ๅฐ่ๅดๆนๅจ",
(Locale::ZhHans, Self::UserVoice) => "ไฟ็็จๆท่ฏญๆฐ",
(Locale::ZhHans, Self::ReversibleOps) => "ๅฏ้ๆญฅ้ชค",
(Locale::ZhHant, Self::ScopedChanges) => "ๅฐ็ฏๅๆนๅ",
(Locale::ZhHant, Self::UserVoice) => "ไฟ็ไฝฟ็จ่
่ชๆฐฃ",
(Locale::ZhHant, Self::ReversibleOps) => "ๅฏ้ๆญฅ้ฉ",
(Locale::PtBr, Self::ScopedChanges) => "mudanรงas focadas",
(Locale::PtBr, Self::UserVoice) => "preservar voz do usuรกrio",
(Locale::PtBr, Self::ReversibleOps) => "passos reversรญveis",
(Locale::Es419, Self::ScopedChanges) => "cambios acotados",
(Locale::Es419, Self::UserVoice) => "preservar voz del usuario",
(Locale::Es419, Self::ReversibleOps) => "pasos reversibles",
(Locale::Vi, Self::ScopedChanges) => "thay ฤแปi cรณ phแบกm vi",
(Locale::Vi, Self::UserVoice) => "giแปฏ giแปng ngฦฐแปi dรนng",
(Locale::Vi, Self::ReversibleOps) => "bฦฐแปc cรณ thแป ฤแบฃo ngฦฐแปฃc",
(Locale::Ko, Self::ScopedChanges) => "๋ฒ์๊ฐ ๋ช
ํํ ๋ณ๊ฒฝ",
(Locale::Ko, Self::UserVoice) => "์ฌ์ฉ์์ ์ด์กฐ ์ ์ง",
(Locale::Ko, Self::ReversibleOps) => "๋๋๋ฆด ์ ์๋ ๋จ๊ณ",
(Locale::Ca, Self::ScopedChanges) => "canvis acotats",
(Locale::Ca, Self::UserVoice) => "veu de l'usuari",
(Locale::Ca, Self::ReversibleOps) => "passos reversibles",
(Locale::De, Self::ScopedChanges) => "begrenzte รnderungen",
(Locale::De, Self::UserVoice) => "Stimme des Nutzers",
(Locale::De, Self::ReversibleOps) => "reversible Schritte",
(Locale::Fr, Self::ScopedChanges) => "changements ciblรฉs",
(Locale::Fr, Self::UserVoice) => "voix de l'utilisateur",
(Locale::Fr, Self::ReversibleOps) => "รฉtapes rรฉversibles",
(Locale::Id, Self::ScopedChanges) => "perubahan terbatas",
(Locale::Id, Self::UserVoice) => "suara pengguna",
(Locale::Id, Self::ReversibleOps) => "langkah reversibel",
(Locale::Hi, Self::ScopedChanges) => "เคธเฅเคฎเคฟเคค เคฌเคฆเคฒเคพเคต",
(Locale::Hi, Self::UserVoice) => "เคเคชเคฏเฅเคเคเคฐเฅเคคเคพ เคเฅ เคเคตเคพเคเคผ",
(Locale::Hi, Self::ReversibleOps) => "เคเคคเฅเคเฅเคฐเคฎเคฃเฅเคฏ เคเคฐเคฃ",
(Locale::Ru, Self::ScopedChanges) => "ะพะณัะฐะฝะธัะตะฝะฝัะต ะธะทะผะตะฝะตะฝะธั",
(Locale::Ru, Self::UserVoice) => "ะณะพะปะพั ะฟะพะปัะทะพะฒะฐัะตะปั",
(Locale::Ru, Self::ReversibleOps) => "ะพะฑัะฐัะธะผัะต ัะฐะณะธ",
(Locale::Uk, Self::ScopedChanges) => "ะพะฑะผะตะถะตะฝั ะทะผัะฝะธ",
(Locale::Uk, Self::UserVoice) => "ะณะพะปะพั ะบะพัะธัััะฒะฐัะฐ",
(Locale::Uk, Self::ReversibleOps) => "ะพะฑะพัะพัะฝั ะบัะพะบะธ",
(_, Self::ScopedChanges) => "scoped changes",
(_, Self::UserVoice) => "user voice",
(_, Self::ReversibleOps) => "reversible steps",
}
}
fn note(self, locale: Locale) -> &'static str {
match (locale, self) {
(Locale::Ja, Self::ScopedChanges) => {
"่ช็ฑๅๅ๏ผๅฐใใใฌใใฅใผใใใใๅคๆดใๅชๅ
ใใๆ็คบ่ฆๆฑใใชใ้ใ็ก้ขไฟใชใชใใกใฏใฟใ้ฟใใใ"
}
(Locale::Ja, Self::UserVoice) => {
"่ช็ฑๅๅ๏ผใฆใผใถใผใฎ่ช่ชฟใใใฉใณใใๅถ็ดใไฟใกใๅฅฝใฟใๆจฉ้ๆกๅคงใจใใฆๆฑใใชใใ"
}
(Locale::Ja, Self::ReversibleOps) => {
"่ช็ฑๅๅ๏ผๅฝฑ้ฟใฎๅคงใใๆไฝใฎๅใซใๅฏ้ๆ้ ใใใงใใฏใใคใณใใใญใผใซใใใฏ่ชฌๆใ้ธใถใ"
}
(Locale::ZhHans, Self::ScopedChanges) => {
"่ชๅฎไนๅๅ๏ผไผๅ
้็จๅฐ่ๅดใๅฏๅฎกๆฅ็ๆนๅจ๏ผ้ค้ๆ็กฎ่ฆๆฑ๏ผไธๅๆ ๅ
ณ้ๆใ"
}
(Locale::ZhHans, Self::UserVoice) => {
"่ชๅฎไนๅๅ๏ผไฟ็็จๆท็่ฏญๆฐใๅ็ๅ็บฆๆ๏ผไธๆๅๅฅฝๆจๆญๆๆ้ๆฉๅคงใ"
}
(Locale::ZhHans, Self::ReversibleOps) => {
"่ชๅฎไนๅๅ๏ผๅ
้ๆฉๅฏ้ๆญฅ้ชคใๆฃๆฅ็นๅๅๆป่ฏดๆ๏ผๅ่ฟ่ก้ซๅฝฑๅๆไฝใ"
}
(Locale::ZhHant, Self::ScopedChanges) => {
"่ช็ฑๅๅ๏ผๅชๅ
ๆก็จๅฐ็ฏๅใๅฏๅฏฉๆฅ็ๆนๅ๏ผ้ค้ๆ็ขบ่ฆๆฑ๏ผไธๅ็ก้้ๆงใ"
}
(Locale::ZhHant, Self::UserVoice) => {
"่ช็ฑๅๅ๏ผไฟ็ไฝฟ็จ่
็่ชๆฐฃใๅ็ๅ็ดๆ๏ผไธๆๅๅฅฝๆจๆทๆๆฌ้ๆดๅคงใ"
}
(Locale::ZhHant, Self::ReversibleOps) => {
"่ช็ฑๅๅ๏ผๅ
้ธๆๅฏ้ๆญฅ้ฉใๆชขๆฅ้ปๅๅๅพฉ่ชชๆ๏ผๅ้ฒ่ก้ซๅฝฑ้ฟๆไฝใ"
}
(Locale::PtBr, Self::ScopedChanges) => {
"Princรญpio livre: prefira mudanรงas pequenas e revisรกveis; evite refactors nรฃo relacionados sem pedido explรญcito."
}
(Locale::PtBr, Self::UserVoice) => {
"Princรญpio livre: preserve a voz, marca e restriรงรตes do usuรกrio sem tratar preferรชncias como expansรฃo de permissรฃo."
}
(Locale::PtBr, Self::ReversibleOps) => {
"Princรญpio livre: favoreรงa passos reversรญveis, checkpoints e notas de rollback antes de aรงรตes de alto impacto."
}
(Locale::Es419, Self::ScopedChanges) => {
"Principio libre: prefiere cambios pequeรฑos y revisables; evita refactors no relacionados sin pedido explรญcito."
}
(Locale::Es419, Self::UserVoice) => {
"Principio libre: preserva la voz, marca y restricciones del usuario sin tratar preferencias como expansiรณn de permisos."
}
(Locale::Es419, Self::ReversibleOps) => {
"Principio libre: favorece pasos reversibles, checkpoints y notas de rollback antes de acciones de alto impacto."
}
(Locale::Vi, Self::ScopedChanges) => {
"Nguyรชn tแบฏc tแปฑ do: ฦฐu tiรชn thay ฤแปi nhแป, dแป
review; trรกnh refactor khรดng liรชn quan nแบฟu khรดng ฤฦฐแปฃc yรชu cแบงu rรต."
}
(Locale::Vi, Self::UserVoice) => {
"Nguyรชn tแบฏc tแปฑ do: giแปฏ giแปng, thฦฐฦกng hiแปu vร rร ng buแปc cแปงa ngฦฐแปi dรนng, khรดng xem sแป thรญch lร mแป rแปng quyแปn."
}
(Locale::Vi, Self::ReversibleOps) => {
"Nguyรชn tแบฏc tแปฑ do: ฦฐu tiรชn bฦฐแปc cรณ thแป ฤแบฃo ngฦฐแปฃc, checkpoint vร ghi chรบ rollback trฦฐแปc thao tรกc tรกc ฤแปng cao."
}
(Locale::Ko, Self::ScopedChanges) => {
"์์ ์์น: ์๊ณ ๋ฆฌ๋ทฐํ๊ธฐ ์ฌ์ด ๋ณ๊ฒฝ์ ์ฐ์ ํ๊ณ , ๋ช
์์ ์ผ๋ก ์์ฒญ๋ฐ์ง ์๋ ํ ๊ด๋ จ ์๋ ๋ฆฌํฉํฐ๋ง์ ํ์ง ์๋๋ค."
}
(Locale::Ko, Self::UserVoice) => {
"์์ ์์น: ์ฌ์ฉ์์ ์ด์กฐ, ๋ธ๋๋, ์ ์ฝ์ ์ ์งํ๊ณ ์ ํธ๋ฅผ ๊ถํ ํ๋๋ก ์ทจ๊ธํ์ง ์๋๋ค."
}
(Locale::Ko, Self::ReversibleOps) => {
"์์ ์์น: ์ํฅ์ด ํฐ ์์
์ ์ ๋๋๋ฆด ์ ์๋ ๋จ๊ณ, ์ฒดํฌํฌ์ธํธ, ๋กค๋ฐฑ ๋ฉ๋ชจ๋ฅผ ์ฐ์ ํ๋ค."
}
(Locale::Ca, Self::ScopedChanges) => {
"Principi lliure: prefereix canvis petits i revisables i evita refactors no relacionats si no es demanen explรญcitament."
}
(Locale::Ca, Self::UserVoice) => {
"Principi lliure: preserva la veu, la marca i les restriccions de l'usuari sense tractar les preferรจncies com una ampliaciรณ de permisos."
}
(Locale::Ca, Self::ReversibleOps) => {
"Principi lliure: priorita passos reversibles, punts de control i notes de marxa enrere abans d'operacions d'alt impacte."
}
(Locale::De, Self::ScopedChanges) => {
"Freitext-Prinzip: Bevorzuge kleine, รผberprรผfbare รnderungen und vermeide unzusammenhรคngende Refactorings, sofern nicht ausdrรผcklich gewรผnscht."
}
(Locale::De, Self::UserVoice) => {
"Freitext-Prinzip: Bewahre Stimme, Marke und Vorgaben des Nutzers, ohne Prรคferenzen als Rechteausweitung zu behandeln."
}
(Locale::De, Self::ReversibleOps) => {
"Freitext-Prinzip: Bevorzuge reversible Schritte, Checkpoints und Rollback-Notizen vor einschneidenden Operationen."
}
(Locale::Fr, Self::ScopedChanges) => {
"Principe libre : prรฉfรฉrez des changements petits et rรฉvisables et รฉvitez les refactors sans rapport, sauf demande explicite."
}
(Locale::Fr, Self::UserVoice) => {
"Principe libre : prรฉservez la voix, la marque et les contraintes de l'utilisateur sans traiter ses prรฉfรฉrences comme une extension de permissions."
}
(Locale::Fr, Self::ReversibleOps) => {
"Principe libre : privilรฉgiez รฉtapes rรฉversibles, points de contrรดle et notes de rollback avant les opรฉrations ร fort impact."
}
(Locale::Id, Self::ScopedChanges) => {
"Prinsip bebas: utamakan perubahan kecil yang mudah ditinjau dan hindari refactor tak terkait kecuali diminta secara eksplisit."
}
(Locale::Id, Self::UserVoice) => {
"Prinsip bebas: jaga suara, merek, dan batasan pengguna tanpa memperlakukan preferensi sebagai perluasan izin."
}
(Locale::Id, Self::ReversibleOps) => {
"Prinsip bebas: utamakan langkah reversibel, checkpoint, dan catatan rollback sebelum operasi berdampak besar."
}
(Locale::Hi, Self::ScopedChanges) => {
"เคฎเฅเคเฅเคค-เคชเคพเค เคธเคฟเคฆเฅเคงเคพเคเคค: เคเฅเคเฅ, เคธเคฎเฅเคเฅเคทเคพเคฏเฅเคเฅเคฏ เคฌเคฆเคฒเคพเคตเฅเค เคเฅ เคชเฅเคฐเคพเคฅเคฎเคฟเคเคคเคพ เคฆเฅเค เคเคฐ เคธเฅเคชเคทเฅเค เค
เคจเฅเคฐเฅเคง เคเฅ เคฌเคฟเคจเคพ เค
เคธเคเคฌเคเคงเคฟเคค เคฐเคฟเคซเฅเคเฅเคเคฐ เคธเฅ เคฌเคเฅเคเฅค"
}
(Locale::Hi, Self::UserVoice) => {
"เคฎเฅเคเฅเคค-เคชเคพเค เคธเคฟเคฆเฅเคงเคพเคเคค: เคเคชเคฏเฅเคเคเคฐเฅเคคเคพ เคเฅ เคเคตเคพเคเคผ, เคฌเฅเคฐเคพเคเคก เคเคฐ เคฌเคพเคงเคพเคเค เคธเฅเคฐเคเฅเคทเคฟเคค เคฐเคเฅเค; เคชเฅเคฐเคพเคฅเคฎเคฟเคเคคเคพเคเค เคเฅ เค
เคจเฅเคฎเคคเคฟ-เคตเคฟเคธเฅเคคเคพเคฐ เคจ เคฎเคพเคจเฅเคเฅค"
}
(Locale::Hi, Self::ReversibleOps) => {
"เคฎเฅเคเฅเคค-เคชเคพเค เคธเคฟเคฆเฅเคงเคพเคเคค: เคเคเฅเค-เคชเฅเคฐเคญเคพเคต เคเคพเคฐเฅเคฏเฅเค เคธเฅ เคชเคนเคฒเฅ เคเคคเฅเคเฅเคฐเคฎเคฃเฅเคฏ เคเคฐเคฃเฅเค, เคเฅเคเคชเฅเคเคเค เคเคฐ เคฐเฅเคฒเคฌเฅเค เคจเฅเคเฅเคธ เคเฅ เคชเฅเคฐเคพเคฅเคฎเคฟเคเคคเคพ เคฆเฅเคเฅค"
}
(Locale::Ru, Self::ScopedChanges) => {
"ะกะฒะพะฑะพะดะฝัะน ะฟัะธะฝัะธะฟ: ะฟัะตะดะฟะพัะธัะฐะนัะต ะฝะตะฑะพะปััะธะต, ะฟัะพะฒะตััะตะผัะต ะธะทะผะตะฝะตะฝะธั ะธ ะธะทะฑะตะณะฐะนัะต ะฝะตัะฒัะทะฐะฝะฝัั
ัะตัะฐะบัะพัะธะฝะณะพะฒ ะฑะตะท ัะฒะฝะพะณะพ ะทะฐะฟัะพัะฐ."
}
(Locale::Ru, Self::UserVoice) => {
"ะกะฒะพะฑะพะดะฝัะน ะฟัะธะฝัะธะฟ: ัะพั
ัะฐะฝัะนัะต ะณะพะปะพั, ะฑัะตะฝะด ะธ ะพะณัะฐะฝะธัะตะฝะธั ะฟะพะปัะทะพะฒะฐัะตะปั, ะฝะต ััะฐะบััั ะฟัะตะดะฟะพััะตะฝะธั ะบะฐะบ ัะฐััะธัะตะฝะธะต ะฟะพะปะฝะพะผะพัะธะน."
}
(Locale::Ru, Self::ReversibleOps) => {
"ะกะฒะพะฑะพะดะฝัะน ะฟัะธะฝัะธะฟ: ะพัะดะฐะฒะฐะนัะต ะฟัะตะดะฟะพััะตะฝะธะต ะพะฑัะฐัะธะผัะผ ัะฐะณะฐะผ, ะบะพะฝััะพะปัะฝัะผ ัะพัะบะฐะผ ะธ ะทะฐะผะตัะบะฐะผ ะพะฑ ะพัะบะฐัะต ะฟะตัะตะด ะฒััะพะบะพัะธัะบะพะฒัะผะธ ะพะฟะตัะฐัะธัะผะธ."
}
(Locale::Uk, Self::ScopedChanges) => {
"ะัะปัะฝะธะน ะฟัะธะฝัะธะฟ: ะฝะฐะดะฐะฒะฐะนัะต ะฟะตัะตะฒะฐะณั ะฝะตะฒะตะปะธะบะธะผ, ะฟะตัะตะฒัััะฒะฐะฝะธะผ ะทะผัะฝะฐะผ ั ัะฝะธะบะฐะนัะต ะฝะตะฟะพะฒ'ัะทะฐะฝะธั
ัะตัะฐะบัะพัะธะฝะณัะฒ ะฑะตะท ัะฒะฝะพะณะพ ะทะฐะฟะธัั."
}
(Locale::Uk, Self::UserVoice) => {
"ะัะปัะฝะธะน ะฟัะธะฝัะธะฟ: ะทะฑะตััะณะฐะนัะต ะณะพะปะพั, ะฑัะตะฝะด ั ะพะฑะผะตะถะตะฝะฝั ะบะพัะธัััะฒะฐัะฐ, ะฝะต ััะฐะบััััะธ ะฒะฟะพะดะพะฑะฐะฝะฝั ัะบ ัะพะทัะธัะตะฝะฝั ะฟะพะฒะฝะพะฒะฐะถะตะฝั."
}
(Locale::Uk, Self::ReversibleOps) => {
"ะัะปัะฝะธะน ะฟัะธะฝัะธะฟ: ะฝะฐะดะฐะฒะฐะนัะต ะฟะตัะตะฒะฐะณั ะพะฑะพัะพัะฝะธะผ ะบัะพะบะฐะผ, ะบะพะฝััะพะปัะฝะธะผ ัะพัะบะฐะผ ั ะฝะพัะฐัะบะฐะผ ะฟัะพ ะฒัะดะบะฐั ะฟะตัะตะด ะฒะธัะพะบะพัะธะทะธะบะพะฒะธะผะธ ะพะฟะตัะฐัััะผะธ."
}
(_, Self::ScopedChanges) => {
"Freeform principle: prefer small, reviewable changes and avoid unrelated refactors unless explicitly requested."
}
(_, Self::UserVoice) => {
"Freeform principle: preserve the user's voice, brand, and constraints without treating preferences as permission expansion."
}
(_, Self::ReversibleOps) => {
"Freeform principle: favor reversible steps, checkpoints, and rollback notes before high-impact operations."
}
}
}
}
fn next_guided_autonomy(preference: AutonomyPreference) -> AutonomyPreference {
match preference {
AutonomyPreference::Unspecified | AutonomyPreference::Cautious => {
AutonomyPreference::Balanced
}
AutonomyPreference::Balanced => AutonomyPreference::Autonomous,
AutonomyPreference::Autonomous => AutonomyPreference::Cautious,
}
}
fn autonomy_label(preference: AutonomyPreference, locale: Locale) -> &'static str {
match (locale, preference) {
(Locale::Ja, AutonomyPreference::Cautious) => "ๆ
้",
(Locale::Ja, AutonomyPreference::Balanced) => "ใใฉใณใน",
(Locale::Ja, AutonomyPreference::Autonomous) => "็ฉๆฅต็",
(Locale::ZhHans, AutonomyPreference::Cautious) => "่ฐจๆ
",
(Locale::ZhHans, AutonomyPreference::Balanced) => "ๅนณ่กก",
(Locale::ZhHans, AutonomyPreference::Autonomous) => "็งฏๆไธปๅจ",
(Locale::ZhHant, AutonomyPreference::Cautious) => "่ฌนๆ
",
(Locale::ZhHant, AutonomyPreference::Balanced) => "ๅนณ่กก",
(Locale::ZhHant, AutonomyPreference::Autonomous) => "็ฉๆฅตไธปๅ",
(Locale::PtBr, AutonomyPreference::Cautious) => "cauteloso",
(Locale::PtBr, AutonomyPreference::Balanced) => "equilibrado",
(Locale::PtBr, AutonomyPreference::Autonomous) => "ambicioso",
(Locale::Es419, AutonomyPreference::Cautious) => "cauteloso",
(Locale::Es419, AutonomyPreference::Balanced) => "equilibrado",
(Locale::Es419, AutonomyPreference::Autonomous) => "ambicioso",
(Locale::Vi, AutonomyPreference::Cautious) => "thแบญn trแปng",
(Locale::Vi, AutonomyPreference::Balanced) => "cรขn bแบฑng",
(Locale::Vi, AutonomyPreference::Autonomous) => "chแปง ฤแปng",
(Locale::Ko, AutonomyPreference::Cautious) => "์ ์คํจ",
(Locale::Ko, AutonomyPreference::Balanced) => "๊ท ํ",
(Locale::Ko, AutonomyPreference::Autonomous) => "์ ๊ทน์ ",
(Locale::Ca, AutonomyPreference::Cautious) => "cautelรณs",
(Locale::Ca, AutonomyPreference::Balanced) => "equilibrat",
(Locale::Ca, AutonomyPreference::Autonomous) => "ambiciรณs",
(Locale::De, AutonomyPreference::Cautious) => "vorsichtig",
(Locale::De, AutonomyPreference::Balanced) => "ausgewogen",
(Locale::De, AutonomyPreference::Autonomous) => "ambitioniert",
(Locale::Fr, AutonomyPreference::Cautious) => "prudent",
(Locale::Fr, AutonomyPreference::Balanced) => "รฉquilibrรฉ",
(Locale::Fr, AutonomyPreference::Autonomous) => "ambitieux",
(Locale::Id, AutonomyPreference::Cautious) => "hati-hati",
(Locale::Id, AutonomyPreference::Balanced) => "seimbang",
(Locale::Id, AutonomyPreference::Autonomous) => "ambisius",
(Locale::Hi, AutonomyPreference::Cautious) => "เคธเคพเคตเคงเคพเคจ",
(Locale::Hi, AutonomyPreference::Balanced) => "เคธเคเคคเฅเคฒเคฟเคค",
(Locale::Hi, AutonomyPreference::Autonomous) => "เคฎเคนเคคเฅเคตเคพเคเคพเคเคเฅเคทเฅ",
(Locale::Ru, AutonomyPreference::Cautious) => "ะพััะพัะพะถะฝัะน",
(Locale::Ru, AutonomyPreference::Balanced) => "ัะฑะฐะปะฐะฝัะธัะพะฒะฐะฝะฝัะน",
(Locale::Ru, AutonomyPreference::Autonomous) => "ัะฐะผะพััะพััะตะปัะฝัะน",
(Locale::Uk, AutonomyPreference::Cautious) => "ะพะฑะตัะตะถะฝะธะน",
(Locale::Uk, AutonomyPreference::Balanced) => "ะทะฑะฐะปะฐะฝัะพะฒะฐะฝะธะน",
(Locale::Uk, AutonomyPreference::Autonomous) => "ัะฐะผะพัััะนะฝะธะน",
(_, AutonomyPreference::Cautious) => "cautious",
(_, AutonomyPreference::Balanced) => "balanced",
(_, AutonomyPreference::Autonomous) => "ambitious",
(_, AutonomyPreference::Unspecified) => "unspecified",
}
}
fn autonomy_priority(preference: AutonomyPreference, locale: Locale) -> &'static str {
match (locale, preference) {
(Locale::Ja, AutonomyPreference::Cautious) => {
"ใใกใคใซ็ทจ้ใใณใใณใๅฎ่กใใใใพใใช่ฃฝๅๅคๆญใฎๅใซๅๆญขใใฆๅฐใญใใ"
}
(Locale::Ja, AutonomyPreference::Balanced) => {
"ๆ็ขบใงไฝใชในใฏใชไฝๆฅญใฏ็ดๆฅ้ฒใใๅฑ้บใ็ ดๅฃ็ใใใใพใใชๆไฝใงใฏๅ
ใซ็ขบ่ชใใใ"
}
(Locale::Ja, AutonomyPreference::Autonomous) => {
"ๅฎๅ
จใชๅฎๅไฝๆฅญใฏใพใจใใฆ้ฒใใใใ็ ดๅฃ็ใ่ช่จผๆ
ๅ ฑใๅ
ฌ้ใ้ซใณในใใๆณๅใใปใญใฅใชใใฃใชในใฏใงใฏๅๆญขใใฆๅฐใญใใ"
}
(Locale::ZhHans, AutonomyPreference::Cautious) => {
"ๅจ็ผ่พๆไปถใ่ฟ่กๅฝไปคๆไบงๅ้ๆฉไธๆ็กฎๅ๏ผๅพๅๅ
ๅไธ่ฏข้ฎใ"
}
(Locale::ZhHans, AutonomyPreference::Balanced) => {
"ๆธ
ๆฐไฝ้ฃ้ฉไปปๅกๅฏ็ดๆฅ่กๅจ๏ผ้ๅฐ้ฃ้ฉใ็ ดๅๆงๆๆญงไนๆถๅ
็กฎ่ฎคใ"
}
(Locale::ZhHans, AutonomyPreference::Autonomous) => {
"ๅฏๆน้ๅค็ๅฎๅ
จ็ๅธธ่งๅทฅไฝ๏ผไฝ้ๅฐ็ ดๅๆงใๅญๆฎใๅๅธใ้ซๆๆฌใๆณๅพๆๅฎๅ
จ้ฃ้ฉๆถๅๆญข่ฏข้ฎใ"
}
(Locale::ZhHant, AutonomyPreference::Cautious) => {
"ๅจ็ทจ่ผฏๆชๆกใๅท่กๅฝไปคๆ็ขๅ้ธๆไธๆ็ขบๅ๏ผๅพๅๅ
ๅไธ่ฉขๅใ"
}
(Locale::ZhHant, AutonomyPreference::Balanced) => {
"ๆธ
ๆฐไฝ้ขจ้ชไปปๅๅฏ็ดๆฅ่กๅ๏ผ้ๅฐ้ขจ้ชใ็ ดๅฃๆงๆๆญง็พฉๆๅ
็ขบ่ชใ"
}
(Locale::ZhHant, AutonomyPreference::Autonomous) => {
"ๅฏๆน้่็ๅฎๅ
จ็ๅธธ่ฆๅทฅไฝ๏ผไฝ้ๅฐ็ ดๅฃๆงใๆๆใ็ผๅธใ้ซๆๆฌใๆณๅพๆๅฎๅ
จ้ขจ้ชๆๅๆญข่ฉขๅใ"
}
(Locale::PtBr, AutonomyPreference::Cautious) => {
"Pare e pergunte antes de editar arquivos, rodar comandos ou escolher entre caminhos ambรญguos de produto."
}
(Locale::PtBr, AutonomyPreference::Balanced) => {
"Aja diretamente em tarefas claras e de baixo risco; confirme antes de aรงรตes arriscadas, destrutivas ou ambรญguas."
}
(Locale::PtBr, AutonomyPreference::Autonomous) => {
"Agrupe trabalho seguro de rotina, mas pare para aรงรตes destrutivas, credenciais, publicaรงรฃo, alto custo, legais ou de seguranรงa."
}
(Locale::Es419, AutonomyPreference::Cautious) => {
"Detente y pregunta antes de editar archivos, ejecutar comandos o elegir entre caminos ambiguos de producto."
}
(Locale::Es419, AutonomyPreference::Balanced) => {
"Actรบa directamente en tareas claras y de bajo riesgo; confirma antes de acciones riesgosas, destructivas o ambiguas."
}
(Locale::Es419, AutonomyPreference::Autonomous) => {
"Agrupa trabajo seguro de rutina, pero detente ante acciones destructivas, credenciales, publicaciรณn, alto costo, legales o de seguridad."
}
(Locale::Vi, AutonomyPreference::Cautious) => {
"Dแปซng vร hแปi trฦฐแปc khi sแปญa tแปp, chแบกy lแปnh hoแบทc chแปn giแปฏa ฤฦฐแปng sแบฃn phแบฉm mฦก hแป."
}
(Locale::Vi, AutonomyPreference::Balanced) => {
"Hร nh ฤแปng trแปฑc tiแบฟp vแปi viแปc rรต, rแปงi ro thแบฅp; xรกc nhแบญn trฦฐแปc viแปc rแปงi ro, phรก hแปงy hoแบทc mฦก hแป."
}
(Locale::Vi, AutonomyPreference::Autonomous) => {
"Gแปp viแปc thฦฐแปng lแป an toร n, nhฦฐng dแปซng vแปi thao tรกc phรก hแปงy, thรดng tin xรกc thแปฑc, xuแบฅt bแบฃn, chi phรญ cao, phรกp lรฝ hoแบทc bแบฃo mแบญt."
}
(Locale::Ko, AutonomyPreference::Cautious) => {
"ํ์ผ ์์ , ๋ช
๋ น์ด ์คํ, ์ ๋งคํ ์ ํ ์ ํ ์ ์ ๋ฉ์ถ๊ณ ๋ฌผ์ด๋ณธ๋ค."
}
(Locale::Ko, AutonomyPreference::Balanced) => {
"๋ช
ํํ๊ณ ์ํ์ด ๋ฎ์ ์์
์ ๋ฐ๋ก ์งํํ๊ณ , ์ํํ๊ฑฐ๋ ํ๊ดด์ ์ด๊ฑฐ๋ ์ ๋งคํ ์์
์ ๋จผ์ ํ์ธํ๋ค."
}
(Locale::Ko, AutonomyPreference::Autonomous) => {
"์์ ํ ์ ํ ์์
์ ๋ชจ์์ ์งํํ๋, ํ๊ดด์ ์ด๊ฑฐ๋ ์๊ฒฉ ์ฆ๋ช
, ๊ฒ์, ๊ณ ๋น์ฉ, ๋ฒ์ , ๋ณด์ ์ํ์ด ์๋ ์์
์์๋ ๋ฉ์ถ๊ณ ๋ฌผ์ด๋ณธ๋ค."
}
(Locale::Ca, AutonomyPreference::Cautious) => {
"Atura't i pregunta abans d'editar fitxers, executar ordres o triar entre camins de producte ambigus."
}
(Locale::Ca, AutonomyPreference::Balanced) => {
"Actua directament en tasques clares i de baix risc; confirma abans d'accions arriscades, destructives o ambigรผes."
}
(Locale::Ca, AutonomyPreference::Autonomous) => {
"Agrupa la feina rutinร ria segura, perรฒ atura't davant accions destructives, amb credencials, de publicaciรณ, d'alt cost o amb risc legal o de seguretat."
}
(Locale::De, AutonomyPreference::Cautious) => {
"Halte an und frage, bevor du Dateien bearbeitest, Befehle ausfรผhrst oder zwischen mehrdeutigen Produktwegen wรคhlst."
}
(Locale::De, AutonomyPreference::Balanced) => {
"Handle direkt bei klaren, risikoarmen Aufgaben; bestรคtige vor riskanten, destruktiven oder mehrdeutigen Aktionen."
}
(Locale::De, AutonomyPreference::Autonomous) => {
"Bรผndle sichere Routinearbeit, aber halte an bei destruktiven, zugangsdatenbezogenen, verรถffentlichenden, kostspieligen, rechtlichen oder sicherheitskritischen Aktionen."
}
(Locale::Fr, AutonomyPreference::Cautious) => {
"Arrรชtez et demandez avant de modifier des fichiers, d'exรฉcuter des commandes ou de choisir entre des voies produit ambiguรซs."
}
(Locale::Fr, AutonomyPreference::Balanced) => {
"Agissez directement sur les tรขches claires et ร faible risque ; confirmez avant les actions risquรฉes, destructives ou ambiguรซs."
}
(Locale::Fr, AutonomyPreference::Autonomous) => {
"Regroupez le travail de routine sรปr, mais arrรชtez devant les actions destructives, impliquant des identifiants, des publications, coรปteuses, juridiques ou ร risque de sรฉcuritรฉ."
}
(Locale::Id, AutonomyPreference::Cautious) => {
"Berhenti dan tanya sebelum mengedit file, menjalankan perintah, atau memilih di antara jalur produk yang ambigu."
}
(Locale::Id, AutonomyPreference::Balanced) => {
"Bertindak langsung pada tugas yang jelas dan berisiko rendah; konfirmasi sebelum tindakan berisiko, destruktif, atau ambigu."
}
(Locale::Id, AutonomyPreference::Autonomous) => {
"Kelompokkan pekerjaan rutin yang aman, tetapi berhenti untuk tindakan destruktif, terkait kredensial, publikasi, mahal, hukum, atau berisiko keamanan."
}
(Locale::Hi, AutonomyPreference::Cautious) => {
"เคซเคผเคพเคเคฒเฅเค เคธเคเคชเคพเคฆเคฟเคค เคเคฐเคจเฅ, เคเคฎเคพเคเคก เคเคฒเคพเคจเฅ เคฏเคพ เค
เคธเฅเคชเคทเฅเค เคเคคเฅเคชเคพเคฆ เคฎเคพเคฐเฅเคเฅเค เคฎเฅเค เคเฅเคจเคจเฅ เคธเฅ เคชเคนเคฒเฅ เคฐเฅเคเคเคฐ เคชเฅเคเฅเคเฅค"
}
(Locale::Hi, AutonomyPreference::Balanced) => {
"เคธเฅเคชเคทเฅเค, เคเคฎ-เคเฅเคเคฟเคฎ เคตเคพเคฒเฅ เคเคพเคฐเฅเคฏเฅเค เคชเคฐ เคธเฅเคงเฅ เคเคพเคฐเฅเคฏ เคเคฐเฅเค; เคเฅเคเคฟเคฎเคชเฅเคฐเฅเคฃ, เคตเคฟเคจเคพเคถเคเคพเคฐเฅ เคฏเคพ เค
เคธเฅเคชเคทเฅเค เคเคพเคฐเฅเคฏเฅเค เคธเฅ เคชเคนเคฒเฅ เคชเฅเคทเฅเคเคฟ เคเคฐเฅเคเฅค"
}
(Locale::Hi, AutonomyPreference::Autonomous) => {
"เคธเฅเคฐเคเฅเคทเคฟเคค เคจเคฟเคฏเคฎเคฟเคค เคเคพเคฎ เคเค เคธเคพเคฅ เคเคฐเฅเค, เคฒเฅเคเคฟเคจ เคตเคฟเคจเคพเคถเคเคพเคฐเฅ, เคเฅเคฐเฅเคกเฅเคเคถเคฟเคฏเคฒ, เคชเฅเคฐเคเคพเคถเคจ, เคเคเฅเค-เคฒเคพเคเคค, เคเคพเคจเฅเคจเฅ เคฏเคพ เคธเฅเคฐเคเฅเคทเคพ-เคเฅเคเคฟเคฎ เคเคพเคฐเฅเคฏเฅเค เคชเคฐ เคฐเฅเคเคเคฐ เคชเฅเคเฅเคเฅค"
}
(Locale::Ru, AutonomyPreference::Cautious) => {
"ะััะฐะฝะพะฒะธัะตัั ะธ ัะฟัะพัะธัะต ะฟะตัะตะด ัะตะดะฐะบัะธัะพะฒะฐะฝะธะตะผ ัะฐะนะปะพะฒ, ะทะฐะฟััะบะพะผ ะบะพะผะฐะฝะด ะธะปะธ ะฒัะฑะพัะพะผ ะผะตะถะดั ะฝะตะพะดะฝะพะทะฝะฐัะฝัะผะธ ะฟัะพะดัะบัะพะฒัะผะธ ะฟัััะผะธ."
}
(Locale::Ru, AutonomyPreference::Balanced) => {
"ะะตะนััะฒัะนัะต ะฝะฐะฟััะผัั ะฒ ััะฝัั
ะฝะธะทะบะพัะธัะบะพะฒัั
ะทะฐะดะฐัะฐั
; ะฟะพะดัะฒะตัะถะดะฐะนัะต ะฟะตัะตะด ัะธัะบะพะฒะฐะฝะฝัะผะธ, ะดะตััััะบัะธะฒะฝัะผะธ ะธะปะธ ะฝะตะพะดะฝะพะทะฝะฐัะฝัะผะธ ะดะตะนััะฒะธัะผะธ."
}
(Locale::Ru, AutonomyPreference::Autonomous) => {
"ะััะฟะฟะธััะนัะต ะฑะตะทะพะฟะฐัะฝัั ัััะธะฝะฝัั ัะฐะฑะพัั, ะฝะพ ะพััะฐะฝะฐะฒะปะธะฒะฐะนัะตัั ะฟะตัะตะด ะดะตััััะบัะธะฒะฝัะผะธ ะดะตะนััะฒะธัะผะธ, ะดะตะนััะฒะธัะผะธ ั ััััะฝัะผะธ ะดะฐะฝะฝัะผะธ, ะฟัะฑะปะธะบะฐัะธัะผะธ, ะดะพัะพะณะธะผะธ, ััะธะดะธัะตัะบะธะผะธ ะธะปะธ ัะณัะพะถะฐััะธะผะธ ะฑะตะทะพะฟะฐัะฝะพััะธ ะพะฟะตัะฐัะธัะผะธ."
}
(Locale::Uk, AutonomyPreference::Cautious) => {
"ะัะฟะธะฝััััั ะน ะทะฐะฟะธัะฐะนัะต ะฟะตัะตะด ัะตะดะฐะณัะฒะฐะฝะฝัะผ ัะฐะนะปัะฒ, ะทะฐะฟััะบะพะผ ะบะพะผะฐะฝะด ะฐะฑะพ ะฒะธะฑะพัะพะผ ะผัะถ ะฝะตะพะดะฝะพะทะฝะฐัะฝะธะผะธ ะฟัะพะดัะบัะพะฒะธะผะธ ัะปัั
ะฐะผะธ."
}
(Locale::Uk, AutonomyPreference::Balanced) => {
"ะัะนัะต ะฑะตะทะฟะพัะตัะตะดะฝัะพ ะฒ ัััะบะธั
ะฝะธะทัะบะพัะธะทะธะบะพะฒะธั
ะทะฐะฒะดะฐะฝะฝัั
; ะฟัะดัะฒะตัะดะถัะนัะต ะฟะตัะตะด ัะธะทะธะบะพะฒะฐะฝะธะผะธ, ััะนะฝัะฒะฝะธะผะธ ัะธ ะฝะตะพะดะฝะพะทะฝะฐัะฝะธะผะธ ะดััะผะธ."
}
(Locale::Uk, AutonomyPreference::Autonomous) => {
"ะััะฟัะนัะต ะฑะตะทะฟะตัะฝั ัััะธะฝะฝั ัะพะฑะพัั, ะฐะปะต ะทัะฟะธะฝัะนัะตัั ะฟะตัะตะด ััะนะฝัะฒะฝะธะผะธ ะดััะผะธ, ะดััะผะธ ะท ะพะฑะปัะบะพะฒะธะผะธ ะดะฐะฝะธะผะธ, ะฟัะฑะปัะบะฐัััะผะธ, ะดะพัะพะณะธะผะธ, ััะธะดะธัะฝะธะผะธ ัะธ ะฝะตะฑะตะทะฟะตัะฝะธะผะธ ะดะปั ะฑะตะทะฟะตะบะธ ะพะฟะตัะฐัััะผะธ."
}
(_, AutonomyPreference::Cautious) => {
"Stop and ask before editing files, running commands, or choosing between ambiguous product paths."
}
(_, AutonomyPreference::Balanced) => {
"Do clear, low-risk work; ask before risky, destructive, or unclear work."
}
(_, AutonomyPreference::Autonomous) => {
"Batch routine safe work, then stop for destructive, credential, publishing, high-cost, legal, or security-risk actions."
}
(_, AutonomyPreference::Unspecified) => "No standing initiative preference was selected.",
}
}
fn authority_priority(locale: Locale) -> &'static str {
match locale {
Locale::Ja => {
"็พๅจใฎใฆใผใถใผ่ฆๆฑใจใฉใคใใใผใซ่จผๆ ใฏใใกใขใชใๅคใๅผใ็ถใใๆจๆธฌใใๅชๅ
ใใใใ"
}
Locale::ZhHans => "ๅฝๅ็จๆท่ฏทๆฑๅๅฎๆถๅทฅๅ
ท่ฏๆฎไผๅ
ไบ่ฎฐๅฟใ้ๆงไบคๆฅๅ็ๆตใ",
Locale::ZhHant => "็ฎๅไฝฟ็จ่
่ซๆฑๅๅณๆๅทฅๅ
ท่ญๆๅชๅ
ๆผ่จๆถใ้ณ่ไบคๆฅๅ็ๆธฌใ",
Locale::PtBr => {
"Pedidos atuais do usuรกrio e evidรชncia viva das ferramentas superam memรณria, handoffs antigos e palpites."
}
Locale::Es419 => {
"Las solicitudes actuales del usuario y la evidencia viva de herramientas superan memoria, handoffs viejos y suposiciones."
}
Locale::Vi => {
"Yรชu cแบงu hiแปn tแบกi cแปงa ngฦฐแปi dรนng vร bแบฑng chแปฉng trแปฑc tiแบฟp tแปซ cรดng cแปฅ ฦฐu tiรชn hฦกn bแป nhแป, handoff cลฉ vร phแปng ฤoรกn."
}
Locale::Ko => {
"ํ์ฌ ์ฌ์ฉ์ ์์ฒญ๊ณผ ์ค์๊ฐ ๋๊ตฌ ๊ทผ๊ฑฐ๋ ๋ฉ๋ชจ๋ฆฌ, ์ค๋๋ ์ธ๊ณ ์๋ฃ, ์ถ์ธก๋ณด๋ค ์ฐ์ ํ๋ค."
}
Locale::Ca => {
"Les peticions actuals de l'usuari i l'evidรจncia en directe de les eines prevalen sobre la memรฒria, els traspasos antics i les conjectures."
}
Locale::De => {
"Aktuelle Nutzeranfragen und Live-Werkzeugnachweise haben Vorrang vor Speicher, veralteten รbergaben und Vermutungen."
}
Locale::Fr => {
"Les demandes actuelles de l'utilisateur et les preuves directes des outils priment sur la mรฉmoire, les anciens transferts et les suppositions."
}
Locale::Id => {
"Permintaan pengguna saat ini dan bukti langsung dari alat mengalahkan memori, handoff lama, dan tebakan."
}
Locale::Hi => "เคตเคฐเฅเคคเคฎเคพเคจ เคเคชเคฏเฅเคเคเคฐเฅเคคเคพ เค
เคจเฅเคฐเฅเคง เคเคฐ เคฒเคพเคเคต เคเฅเคฒ เคธเคพเคเฅเคทเฅเคฏ เคฎเฅเคฎเฅเคฐเฅ, เคชเฅเคฐเคพเคจเฅ เคนเฅเคเคกเคเคซเคผ เคเคฐ เค
เคจเฅเคฎเคพเคจเฅเค เคธเฅ เคเคชเคฐ เคนเฅเคเฅค",
Locale::Ru => {
"ะขะตะบััะธะต ะทะฐะฟัะพัั ะฟะพะปัะทะพะฒะฐัะตะปั ะธ ะถะธะฒัะต ัะฒะธะดะตัะตะปัััะฒะฐ ะธะฝััััะผะตะฝัะพะฒ ะฒะฐะถะฝะตะต ะฟะฐะผััะธ, ัััะฐัะตะฒัะธั
ะฟะตัะตะดะฐัะพัะฝัั
ะทะฐะผะตัะพะบ ะธ ะดะพะณะฐะดะพะบ."
}
Locale::Uk => {
"ะะพัะพัะฝั ะทะฐะฟะธัะธ ะบะพัะธัััะฒะฐัะฐ ัะฐ ะถะธะฒั ัะฒัะดัะตะฝะฝั ัะฝััััะผะตะฝััะฒ ะฒะฐะถะปะธะฒััั ะทะฐ ะฟะฐะผ'ััั, ะทะฐััะฐััะปั ะฟะตัะตะดะฐัะพัะฝั ะฝะพัะฐัะบะธ ะน ะทะดะพะณะฐะดะบะธ."
}
_ => {
"Current user requests and live tool evidence outrank memory, stale handoffs, and guesses."
}
}
}
fn bounded_freeform_note(input: &str, max_chars: usize) -> String {
input
.chars()
.filter_map(|ch| {
if ch == '\t' {
Some(' ')
} else if ch == '\n' || !ch.is_control() {
Some(ch)
} else {
None
}
})
.take(max_chars)
.collect::<String>()
.trim()
.to_string()
}
fn compact_freeform_preview(note: &str) -> String {
let compact = note.split_whitespace().collect::<Vec<_>>().join(" ");
let mut preview = compact.chars().take(96).collect::<String>();
if compact.chars().count() > 96 {
preview.push_str("...");
}
preview
}
fn freeform_note_line(locale: Locale, note: &str, editing: bool) -> Line<'static> {
let preview = compact_freeform_preview(note);
let text = match (locale, editing, preview.is_empty()) {
(Locale::Ja, true, true) => {
"F ่ช็ฑๅๅ๏ผ็ทจ้ไธญ - ๆ็ใฎๅๅใๅ
ฅๅใพใใฏ่ฒผใไปใใEnter ใงๅฎไบ".to_string()
}
(Locale::Ja, true, false) => format!("F ่ช็ฑๅๅ๏ผ็ทจ้ไธญ - {preview}"),
(Locale::Ja, false, true) => "F ่ช็ฑๅๅ๏ผF ใงๆ็ใฎๅๅใๅ
ฅๅใพใใฏ่ฒผใไปใ".to_string(),
(Locale::Ja, false, false) => format!("F ่ช็ฑๅๅ๏ผ{preview}"),
(Locale::ZhHans, true, true) => {
"F ่ชๅฎไนๅๅ๏ผๆญฃๅจ็ผ่พ - ่พๅ
ฅๆ็ฒ่ดดๆ็กฎ็ๅๅ๏ผEnter ๅฎๆ".to_string()
}
(Locale::ZhHans, true, false) => format!("F ่ชๅฎไนๅๅ๏ผๆญฃๅจ็ผ่พ - {preview}"),
(Locale::ZhHans, false, true) => {
"F ่ชๅฎไนๅๅ๏ผๆ F ่พๅ
ฅๆ็ฒ่ดด่ชๅทฑ็ๆ็กฎๅๅ".to_string()
}
(Locale::ZhHans, false, false) => format!("F ่ชๅฎไนๅๅ๏ผ{preview}"),
(Locale::ZhHant, true, true) => {
"F ่ช็ฑๅๅ๏ผๆญฃๅจ็ทจ่ผฏ - ่ผธๅ
ฅๆ่ฒผไธๆ็ๅๅ๏ผEnter ๅฎๆ".to_string()
}
(Locale::ZhHant, true, false) => format!("F ่ช็ฑๅๅ๏ผๆญฃๅจ็ทจ่ผฏ - {preview}"),
(Locale::ZhHant, false, true) => "F ่ช็ฑๅๅ๏ผๆ F ่ผธๅ
ฅๆ่ฒผไธ่ชๅทฑ็ๆ็ๅๅ".to_string(),
(Locale::ZhHant, false, false) => format!("F ่ช็ฑๅๅ๏ผ{preview}"),
(Locale::PtBr, true, true) => {
"F Princรญpio livre: editando - digite ou cole um princรญpio limitado, Enter para concluir".to_string()
}
(Locale::PtBr, true, false) => format!("F Princรญpio livre: editando - {preview}"),
(Locale::PtBr, false, true) => {
"F Princรญpio livre: pressione F para digitar ou colar um princรญpio limitado".to_string()
}
(Locale::PtBr, false, false) => format!("F Princรญpio livre: {preview}"),
(Locale::Es419, true, true) => {
"F Principio libre: editando - escribe o pega un principio acotado, Enter para terminar".to_string()
}
(Locale::Es419, true, false) => format!("F Principio libre: editando - {preview}"),
(Locale::Es419, false, true) => {
"F Principio libre: presiona F para escribir o pegar un principio acotado".to_string()
}
(Locale::Es419, false, false) => format!("F Principio libre: {preview}"),
(Locale::Vi, true, true) => {
"F Nguyรชn tแบฏc tแปฑ do: ฤang sแปญa - nhแบญp hoแบทc dรกn nguyรชn tแบฏc cรณ giแปi hแบกn, Enter ฤแป xong".to_string()
}
(Locale::Vi, true, false) => format!("F Nguyรชn tแบฏc tแปฑ do: ฤang sแปญa - {preview}"),
(Locale::Vi, false, true) => {
"F Nguyรชn tแบฏc tแปฑ do: nhแบฅn F ฤแป nhแบญp hoแบทc dรกn nguyรชn tแบฏc cรณ giแปi hแบกn".to_string()
}
(Locale::Vi, false, false) => format!("F Nguyรชn tแบฏc tแปฑ do: {preview}"),
(Locale::Ko, true, true) => {
"F ์์ ์์น: ํธ์ง ์ค - ์ ํ๋ ์์น์ ์
๋ ฅํ๊ฑฐ๋ ๋ถ์ฌ๋ฃ๊ณ Enter๋ก ์๋ฃ".to_string()
}
(Locale::Ko, true, false) => format!("F ์์ ์์น: ํธ์ง ์ค - {preview}"),
(Locale::Ko, false, true) => "F ์์ ์์น: F๋ฅผ ๋๋ฌ ์ ํ๋ ์์น์ ์
๋ ฅํ๊ฑฐ๋ ๋ถ์ฌ๋ฃ๊ธฐ".to_string(),
(Locale::Ko, false, false) => format!("F ์์ ์์น: {preview}"),
(Locale::Ca, true, true) => {
"F Paraules prรฒpies: editant - escriu o enganxa un principi acotat, Enter per acabar".to_string()
}
(Locale::Ca, true, false) => format!("F Paraules prรฒpies: editant - {preview}"),
(Locale::Ca, false, true) => {
"F Paraules prรฒpies: prem F per escriure o enganxar un principi acotat".to_string()
}
(Locale::Ca, false, false) => format!("F Paraules prรฒpies: {preview}"),
(Locale::De, true, true) => {
"F Eigene Worte: Bearbeitung - tippe oder fรผge ein begrenztes Prinzip ein, Enter zum Abschluss".to_string()
}
(Locale::De, true, false) => format!("F Eigene Worte: Bearbeitung - {preview}"),
(Locale::De, false, true) => {
"F Eigene Worte: F drรผcken, um ein begrenztes Prinzip zu tippen oder einzufรผgen".to_string()
}
(Locale::De, false, false) => format!("F Eigene Worte: {preview}"),
(Locale::Fr, true, true) => {
"F Vos mots : รฉdition - tapez ou collez un principe bornรฉ, Entrรฉe pour terminer".to_string()
}
(Locale::Fr, true, false) => format!("F Vos mots : รฉdition - {preview}"),
(Locale::Fr, false, true) => {
"F Vos mots : appuyez sur F pour taper ou coller un principe bornรฉ".to_string()
}
(Locale::Fr, false, false) => format!("F Vos mots : {preview}"),
(Locale::Id, true, true) => {
"F Kata sendiri: mengedit - ketik atau tempel prinsip terbatas, Enter untuk selesai".to_string()
}
(Locale::Id, true, false) => format!("F Kata sendiri: mengedit - {preview}"),
(Locale::Id, false, true) => {
"F Kata sendiri: tekan F untuk mengetik atau menempel prinsip terbatas".to_string()
}
(Locale::Id, false, false) => format!("F Kata sendiri: {preview}"),
(Locale::Hi, true, true) => {
"F เค
เคชเคจเฅ เคถเคฌเฅเคฆ: เคธเคเคชเคพเคฆเคจ เคเคพเคฐเฅ - เคธเฅเคฎเคฟเคค เคธเคฟเคฆเฅเคงเคพเคเคค เคเคพเคเคช เคฏเคพ เคชเฅเคธเฅเค เคเคฐเฅเค, Enter เคธเฅ เคธเคฎเคพเคชเฅเคค เคเคฐเฅเค".to_string()
}
(Locale::Hi, true, false) => format!("F เค
เคชเคจเฅ เคถเคฌเฅเคฆ: เคธเคเคชเคพเคฆเคจ เคเคพเคฐเฅ - {preview}"),
(Locale::Hi, false, true) => {
"F เค
เคชเคจเฅ เคถเคฌเฅเคฆ: เคธเฅเคฎเคฟเคค เคธเคฟเคฆเฅเคงเคพเคเคค เคเคพเคเคช เคฏเคพ เคชเฅเคธเฅเค เคเคฐเคจเฅ เคเฅ เคฒเคฟเค F เคฆเคฌเคพเคเค".to_string()
}
(Locale::Hi, false, false) => format!("F เค
เคชเคจเฅ เคถเคฌเฅเคฆ: {preview}"),
(Locale::Ru, true, true) => {
"F ะกะฒะพะธ ัะปะพะฒะฐ: ัะตะดะฐะบัะธัะพะฒะฐะฝะธะต - ะฒะฒะตะดะธัะต ะธะปะธ ะฒััะฐะฒััะต ะพะณัะฐะฝะธัะตะฝะฝัะน ะฟัะธะฝัะธะฟ, Enter ะดะปั ะทะฐะฒะตััะตะฝะธั".to_string()
}
(Locale::Ru, true, false) => format!("F ะกะฒะพะธ ัะปะพะฒะฐ: ัะตะดะฐะบัะธัะพะฒะฐะฝะธะต - {preview}"),
(Locale::Ru, false, true) => {
"F ะกะฒะพะธ ัะปะพะฒะฐ: ะฝะฐะถะผะธัะต F, ััะพะฑั ะฒะฒะตััะธ ะธะปะธ ะฒััะฐะฒะธัั ะพะณัะฐะฝะธัะตะฝะฝัะน ะฟัะธะฝัะธะฟ".to_string()
}
(Locale::Ru, false, false) => format!("F ะกะฒะพะธ ัะปะพะฒะฐ: {preview}"),
(Locale::Uk, true, true) => {
"F ะกะฒะพั ัะปะพะฒะฐ: ัะตะดะฐะณัะฒะฐะฝะฝั - ะฒะฒะตะดััั ะฐะฑะพ ะฒััะฐะฒัะต ะพะฑะผะตะถะตะฝะธะน ะฟัะธะฝัะธะฟ, Enter ะดะปั ะทะฐะฒะตััะตะฝะฝั".to_string()
}
(Locale::Uk, true, false) => format!("F ะกะฒะพั ัะปะพะฒะฐ: ัะตะดะฐะณัะฒะฐะฝะฝั - {preview}"),
(Locale::Uk, false, true) => {
"F ะกะฒะพั ัะปะพะฒะฐ: ะฝะฐัะธัะฝััั F, ัะพะฑ ะฒะฒะตััะธ ะฐะฑะพ ะฒััะฐะฒะธัะธ ะพะฑะผะตะถะตะฝะธะน ะฟัะธะฝัะธะฟ".to_string()
}
(Locale::Uk, false, false) => format!("F ะกะฒะพั ัะปะพะฒะฐ: {preview}"),
(_, true, true) => {
"F Own words: editing - type or paste a bounded principle, Enter to finish".to_string()
}
(_, true, false) => format!("F Own words: editing - {preview}"),
(_, false, true) => "F Own words: press F to type or paste a bounded principle".to_string(),
(_, false, false) => format!("F Own words: {preview}"),
};
let style = if editing || !preview.is_empty() {
Style::default().fg(palette::WHALE_HUMAN)
} else {
Style::default().fg(palette::TEXT_MUTED)
};
Line::from(Span::styled(text, style))
}
impl SetupWizardView {
#[must_use]
pub fn new_for_app(app: &App, config: &Config) -> Self {
Self::new_with_facts(
load_setup_state_for_app(app, config),
app.ui_locale,
SetupRuntimeFacts::from_app_config(app, config),
)
}
#[must_use]
pub fn new_checkpoint_for_app(app: &App, config: &Config) -> Self {
Self::new_checkpoint_with_facts(
load_setup_state_for_app(app, config),
app.ui_locale,
SetupRuntimeFacts::from_app_config(app, config),
)
}
#[must_use]
pub fn new_for_app_at(app: &App, config: &Config, step: SetupStep) -> Self {
Self::new_at_with_facts(
load_setup_state_for_app(app, config),
app.ui_locale,
step,
SetupRuntimeFacts::from_app_config(app, config),
)
}
#[must_use]
pub fn selected_step(&self) -> SetupStep {
STEP_SPECS[self.selected].id()
}
fn selected_spec(&self) -> &'static dyn SetupWizardStep {
&STEP_SPECS[self.selected]
}
fn new_with_facts(state: SetupState, locale: Locale, facts: SetupRuntimeFacts) -> Self {
let selected = progressive_initial_step_index(&state, &facts);
Self {
state,
selected,
locale,
progressive_guide: true,
details_expanded: false,
facts,
guided_draft: GuidedConstitutionDraft::default(),
constitution_advanced: false,
freeform_note: String::new(),
editing_freeform_note: false,
guided_preview_seen: false,
existing_preview_seen: false,
model_draft: None,
model_draft_label: None,
runtime_preset: SetupRuntimePreset::default(),
runtime_preset_preview_seen: false,
body_scroll: 0,
}
}
fn new_at_with_facts(
state: SetupState,
locale: Locale,
step: SetupStep,
facts: SetupRuntimeFacts,
) -> Self {
Self {
state,
selected: visible_step_index(step),
locale,
progressive_guide: false,
details_expanded: false,
facts,
guided_draft: GuidedConstitutionDraft::default(),
constitution_advanced: false,
freeform_note: String::new(),
editing_freeform_note: false,
guided_preview_seen: false,
existing_preview_seen: false,
model_draft: None,
model_draft_label: None,
runtime_preset: SetupRuntimePreset::default(),
runtime_preset_preview_seen: false,
body_scroll: 0,
}
}
fn new_checkpoint_with_facts(
state: SetupState,
locale: Locale,
facts: SetupRuntimeFacts,
) -> Self {
Self::new_at_with_facts(state, locale, SetupStep::Constitution, facts)
}
fn surface_title(&self) -> String {
tr(self.locale, MessageId::SetupWizardTitle).into_owned()
}
fn tools_relevant(&self) -> bool {
self.facts.tools_mcp_needs_action || !self.facts.tools_mcp_result.contains("overall=off")
}
fn progressive_steps(&self) -> Vec<SetupStep> {
let mut steps = vec![
SetupStep::ProviderModel,
SetupStep::TrustSandbox,
SetupStep::RemoteRuntime,
];
if self.tools_relevant() {
steps.push(SetupStep::ToolsMcp);
}
steps.push(SetupStep::Verification);
steps
}
fn move_next(&mut self) {
if self.progressive_guide {
let steps = self.progressive_steps();
let position = steps
.iter()
.position(|step| *step == self.selected_step())
.unwrap_or(0);
let next = steps[(position + 1).min(steps.len().saturating_sub(1))];
self.selected = visible_step_index(next);
} else {
self.selected = (self.selected + 1).min(STEP_SPECS.len().saturating_sub(1));
}
self.constitution_advanced = false;
self.details_expanded = false;
self.body_scroll = 0;
}
fn move_back(&mut self) {
if self.progressive_guide {
let steps = self.progressive_steps();
let position = steps
.iter()
.position(|step| *step == self.selected_step())
.unwrap_or(0);
let previous = steps[position.saturating_sub(1)];
self.selected = visible_step_index(previous);
} else {
self.selected = self.selected.saturating_sub(1);
}
self.constitution_advanced = false;
self.details_expanded = false;
self.body_scroll = 0;
}
fn commit_selected_status(
&mut self,
status: StepStatus,
message_id: MessageId,
advance: bool,
) -> ViewAction {
let spec = self.selected_spec();
let result = match status {
StepStatus::Skipped => Some("skipped by user"),
StepStatus::NeedsAction => Some("retry requested; needs action"),
_ => None,
};
let mut entry = StepEntry::new(status, spec.required(), CONSTITUTION_CHECKPOINT_VERSION);
if let Some(result) = result {
entry = entry.with_result(result);
}
let mut state = self.state.clone();
state.set_step(spec.id(), entry);
if spec.id() == SetupStep::Constitution && status == StepStatus::Skipped {
let choice = if state.constitution_choice.is_explicit() {
state.constitution_choice
} else {
ConstitutionChoice::Deferred
};
state.complete_constitution_checkpoint(CONSTITUTION_CHECKPOINT_VERSION, choice);
}
self.state = state.clone();
if advance {
self.move_next();
}
ViewAction::Emit(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, message_id).to_string(),
})
}
fn commit_language_review(&mut self) -> ViewAction {
let mut state = self.state.clone();
state.constitution_language = Some(self.locale.tag().to_string());
state.set_step(
SetupStep::Language,
StepEntry::new(StepStatus::Verified, true, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(format!("setup locale {}", self.locale.tag())),
);
self.state = state.clone();
self.move_next();
ViewAction::Emit(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, MessageId::SetupLanguageReviewed).to_string(),
})
}
fn commit_provider_model_review(&mut self) -> ViewAction {
let status = provider::step_status(self.facts.provider_ready);
let mut state = self.state.clone();
state.set_step(
SetupStep::ProviderModel,
provider::step_entry(
self.facts.provider_ready,
CONSTITUTION_CHECKPOINT_VERSION,
self.facts.provider_result.clone(),
),
);
self.state = state.clone();
self.move_next();
let message_id = if status == StepStatus::Verified {
MessageId::SetupProviderModelReviewed
} else {
MessageId::SetupProviderModelNeedsActionSaved
};
ViewAction::Emit(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, message_id).to_string(),
})
}
fn commit_runtime_posture_review(&mut self) -> ViewAction {
let mut state = self.state.clone();
state.runtime_posture_source = RuntimePostureSource::Confirmed;
state.set_step(
SetupStep::TrustSandbox,
StepEntry::new(StepStatus::Verified, true, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(self.facts.runtime_result.clone()),
);
self.state = state.clone();
self.move_next();
ViewAction::Emit(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, MessageId::SetupRuntimePostureReviewed).to_string(),
})
}
fn operate_fleet_facts_ready(&self) -> bool {
false
}
fn commit_operate_fleet_review(&mut self) -> ViewAction {
let status = if self.operate_fleet_facts_ready() {
StepStatus::Verified
} else {
StepStatus::NeedsAction
};
let mut state = self.state.clone();
state.set_step(
SetupStep::OperateFleet,
StepEntry::new(status, false, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(self.facts.operate_result.clone()),
);
self.state = state.clone();
self.move_next();
let message_id = if status == StepStatus::Verified {
MessageId::SetupOperateReviewed
} else {
MessageId::SetupOperateNeedsActionSaved
};
ViewAction::Emit(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, message_id).to_string(),
})
}
fn commit_hotbar_review(&mut self) -> ViewAction {
let mut state = self.state.clone();
state.set_step(
SetupStep::Hotbar,
StepEntry::new(StepStatus::Verified, false, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(self.facts.hotbar_result.clone()),
);
self.state = state.clone();
self.move_next();
ViewAction::Emit(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, MessageId::SetupHotbarReviewed).to_string(),
})
}
fn commit_tools_mcp_review(&mut self) -> ViewAction {
let status = if self.facts.tools_mcp_needs_action {
StepStatus::NeedsAction
} else if self.facts.tools_mcp_result.contains("overall=off") {
StepStatus::Optional
} else {
StepStatus::Verified
};
let mut state = self.state.clone();
state.set_step(
SetupStep::ToolsMcp,
StepEntry::new(status, false, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(self.facts.tools_mcp_result.clone()),
);
self.state = state.clone();
self.move_next();
let message_id = if status == StepStatus::NeedsAction {
MessageId::SetupToolsMcpNeedsActionSaved
} else {
MessageId::SetupToolsMcpReviewed
};
ViewAction::Emit(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, message_id).to_string(),
})
}
fn preview_tools_mcp_on_ramp(&self) -> ViewAction {
ViewAction::Emit(ViewEvent::OpenTextPager {
title: tr(self.locale, MessageId::SetupToolsMcpPreviewTitle).to_string(),
content: tools_mcp_on_ramp_text(self.locale, &self.facts),
})
}
fn preview_remote_runtime_on_ramp(&self) -> ViewAction {
ViewAction::Emit(ViewEvent::OpenTextPager {
title: tr(self.locale, MessageId::SetupRemotePreviewTitle).to_string(),
content: remote_runtime_on_ramp_text(self.locale, &self.facts),
})
}
fn commit_remote_runtime_review(&mut self) -> ViewAction {
let mut state = self.state.clone();
let status = if self.facts.remote_needs_action {
StepStatus::NeedsAction
} else {
StepStatus::Verified
};
state.set_step(
SetupStep::RemoteRuntime,
StepEntry::new(status, false, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(self.facts.remote_result.clone()),
);
self.state = state.clone();
self.move_next();
ViewAction::Emit(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, MessageId::SetupRemoteReviewed).to_string(),
})
}
fn commit_persistence_review(&mut self) -> ViewAction {
let mut state = self.state.clone();
state.set_step(
SetupStep::Persistence,
StepEntry::new(StepStatus::Verified, false, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(self.facts.persistence.result.clone()),
);
self.state = state.clone();
self.move_next();
ViewAction::Emit(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, MessageId::SetupPersistenceReviewed).to_string(),
})
}
fn select_runtime_preset(&mut self, key: char) -> ViewAction {
if let Some(preset) = SetupRuntimePreset::from_key(key)
&& preset != self.runtime_preset
{
self.runtime_preset = preset;
self.runtime_preset_preview_seen = false;
}
ViewAction::None
}
fn preview_runtime_preset(&mut self) -> ViewAction {
self.runtime_preset_preview_seen = true;
ViewAction::Emit(ViewEvent::OpenTextPager {
title: tr(self.locale, MessageId::SetupRuntimePresetPreviewTitle).to_string(),
content: runtime_preset_preview_text(self.locale, self.runtime_preset, &self.facts),
})
}
fn commit_runtime_preset(&mut self) -> ViewAction {
if !self.runtime_preset_preview_seen {
return self.preview_runtime_preset();
}
let mut state = self.state.clone();
state.runtime_posture_source = RuntimePostureSource::Confirmed;
state.set_step(
SetupStep::TrustSandbox,
StepEntry::new(StepStatus::Verified, true, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(self.runtime_preset.result_summary()),
);
self.state = state.clone();
self.move_next();
ViewAction::Emit(ViewEvent::SetupRuntimePresetApplyRequested {
preset: self.runtime_preset,
state,
message: tr(self.locale, MessageId::SetupRuntimePresetApplied).to_string(),
})
}
fn commit_setup_report(&mut self) -> ViewAction {
let mut state = self.state.clone();
let status = if setup_report_ready(&state) {
StepStatus::Verified
} else {
StepStatus::NeedsAction
};
state.set_step(
SetupStep::Verification,
StepEntry::new(status, false, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(setup_report_result(&state, &self.facts)),
);
self.state = state.clone();
let event = ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, MessageId::SetupReportRecorded).to_string(),
};
if self.progressive_guide {
ViewAction::EmitAndClose(event)
} else {
ViewAction::Emit(event)
}
}
fn open_constitution_advanced(&mut self) -> ViewAction {
self.constitution_advanced = true;
self.body_scroll = 0;
ViewAction::None
}
fn close_constitution_advanced(&mut self) -> ViewAction {
self.constitution_advanced = false;
self.editing_freeform_note = false;
self.body_scroll = 0;
ViewAction::None
}
fn commit_simple_constitution(&mut self) -> ViewAction {
match self.facts.constitution_file {
SetupConstitutionFileState::Loaded => {
return self.commit_existing_constitution_unchanged();
}
SetupConstitutionFileState::Empty
| SetupConstitutionFileState::Invalid
| SetupConstitutionFileState::Unreadable
| SetupConstitutionFileState::PathError => {
return self.commit_constitution(SetupCommitKind::BundledConstitution);
}
SetupConstitutionFileState::NotChecked | SetupConstitutionFileState::Missing => {}
}
self.commit_constitution(SetupCommitKind::BundledConstitution)
}
fn commit_custom_constitution(
&mut self,
constitution: UserConstitution,
authoring: ConstitutionAuthoring,
result_prefix: &str,
) -> ViewAction {
let mut state = self.state.clone();
state.complete_constitution_checkpoint(
CONSTITUTION_CHECKPOINT_VERSION,
ConstitutionChoice::GuidedCustom,
);
state.constitution_language = constitution.language.clone();
state.constitution_source = ConstitutionSource::UserGlobal;
state.constitution_validity = ConstitutionValidity::Valid;
state.constitution_authoring = Some(authoring);
state.constitution_preview_hash = Some(constitution.preview_hash());
state.constitution_preview_version =
state.constitution_preview_version.saturating_add(1).max(1);
let hash = state
.constitution_preview_hash
.as_deref()
.unwrap_or("unknown");
state.set_step(
SetupStep::Constitution,
StepEntry::new(StepStatus::Verified, true, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(format!("{result_prefix} preview_hash={hash}")),
);
self.state = state.clone();
ViewAction::EmitAndClose(ViewEvent::SetupConstitutionCommitRequested {
constitution,
state,
message: tr(self.locale, MessageId::SetupCheckpointDoneGuided).to_string(),
})
}
fn commit_guided_constitution(&mut self) -> ViewAction {
if !self.guided_preview_seen {
return self.preview_guided_constitution();
}
let (constitution, authoring) = match self.model_draft.as_deref() {
Some(draft) => (draft.clone(), ConstitutionAuthoring::ModelDrafted),
None => (
self.guided_draft
.to_constitution_with_freeform(self.locale, self.freeform_note_for_draft()),
ConstitutionAuthoring::Guided,
),
};
let result_prefix = match authoring {
ConstitutionAuthoring::ModelDrafted => format!(
"model-drafted constitution ratified ({})",
self.model_draft_label.as_deref().unwrap_or("model")
),
ConstitutionAuthoring::Guided => "guided custom constitution".to_string(),
};
self.commit_custom_constitution(constitution, authoring, &result_prefix)
}
fn preview_guided_constitution(&mut self) -> ViewAction {
self.guided_preview_seen = true;
let (constitution, provenance) = match self.model_draft.as_deref() {
Some(draft) => (
draft.clone(),
DraftProvenance::Model(
self.model_draft_label
.clone()
.unwrap_or_else(|| "model".to_string()),
),
),
None => (
self.guided_draft
.to_constitution_with_freeform(self.locale, self.freeform_note_for_draft()),
DraftProvenance::Guided,
),
};
ViewAction::Emit(ViewEvent::OpenTextPager {
title: ratification_preview_title(self.locale).to_string(),
content: constitution_ratification_text(self.locale, &constitution, &provenance),
})
}
fn cycle_guided_answer(&mut self, key: char) -> ViewAction {
if self.guided_draft.cycle(key) {
self.guided_preview_seen = false;
self.model_draft = None;
self.model_draft_label = None;
}
ViewAction::None
}
fn request_model_draft(&self) -> ViewAction {
if !self.facts.provider_ready {
return ViewAction::None;
}
ViewAction::Emit(ViewEvent::SetupConstitutionModelDraftRequested {
draft: self.guided_draft,
freeform_note: self.freeform_note_for_draft().map(str::to_string),
locale: self.locale,
})
}
fn toggle_freeform_edit(&mut self) -> ViewAction {
if self.selected_step() == SetupStep::Constitution {
self.editing_freeform_note = !self.editing_freeform_note;
}
ViewAction::None
}
fn freeform_note_for_draft(&self) -> Option<&str> {
let note = self.freeform_note.trim();
(!note.is_empty()).then_some(note)
}
fn append_freeform_note_text(&mut self, text: &str) {
let mut next = self.freeform_note.clone();
next.push_str(text);
self.freeform_note = bounded_freeform_note(&next, MAX_NOTES_LEN);
self.guided_preview_seen = false;
self.model_draft = None;
self.model_draft_label = None;
}
fn handle_freeform_note_key(&mut self, key: KeyEvent) -> Option<ViewAction> {
if self.selected_step() != SetupStep::Constitution || !self.editing_freeform_note {
return None;
}
match key.code {
KeyCode::Esc | KeyCode::Enter => {
self.editing_freeform_note = false;
Some(ViewAction::None)
}
KeyCode::Backspace => {
self.freeform_note.pop();
self.guided_preview_seen = false;
self.model_draft = None;
self.model_draft_label = None;
Some(ViewAction::None)
}
KeyCode::Char(c) if key.modifiers.is_empty() => {
let mut buf = [0; 4];
self.append_freeform_note_text(c.encode_utf8(&mut buf));
Some(ViewAction::None)
}
_ => Some(ViewAction::None),
}
}
#[must_use]
pub(crate) fn install_model_draft(
&mut self,
constitution: Box<UserConstitution>,
model_label: String,
) -> (String, String) {
let content = constitution_ratification_text(
self.locale,
&constitution,
&DraftProvenance::Model(model_label.clone()),
);
self.model_draft = Some(constitution);
self.model_draft_label = Some(model_label);
self.guided_preview_seen = true;
(ratification_preview_title(self.locale).to_string(), content)
}
fn commit_constitution(&self, kind: SetupCommitKind) -> ViewAction {
let choice = match kind {
SetupCommitKind::BundledConstitution => ConstitutionChoice::Bundled,
SetupCommitKind::DeferredConstitution => ConstitutionChoice::Deferred,
};
let mut state = self.state.clone();
state.complete_constitution_checkpoint(CONSTITUTION_CHECKPOINT_VERSION, choice);
state.constitution_source = ConstitutionSource::Bundled;
state.constitution_validity = ConstitutionValidity::Unknown;
state.constitution_authoring = None;
state.constitution_preview_hash = None;
state.set_step(
SetupStep::Constitution,
StepEntry::new(StepStatus::Verified, true, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(match kind {
SetupCommitKind::BundledConstitution => "bundled/default constitution",
SetupCommitKind::DeferredConstitution => "checkpoint deferred; bundled applies",
}),
);
let message_id = match kind {
SetupCommitKind::BundledConstitution => MessageId::SetupCheckpointDoneBundled,
SetupCommitKind::DeferredConstitution => MessageId::SetupCheckpointDeferred,
};
ViewAction::EmitAndClose(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, message_id).to_string(),
})
}
fn load_existing_constitution(&self) -> Option<UserConstitution> {
if self.facts.constitution_file != SetupConstitutionFileState::Loaded {
return None;
}
UserConstitution::load().ok()?.constitution().cloned()
}
fn commit_existing_constitution_unchanged(&mut self) -> ViewAction {
let Some(constitution) = self.load_existing_constitution() else {
return ViewAction::None;
};
let mut state = self.state.clone();
state.complete_constitution_checkpoint(
CONSTITUTION_CHECKPOINT_VERSION,
ConstitutionChoice::GuidedCustom,
);
state.constitution_source = ConstitutionSource::UserGlobal;
state.constitution_validity = ConstitutionValidity::Valid;
state.constitution_preview_hash = Some(constitution.preview_hash());
state.set_step(
SetupStep::Constitution,
StepEntry::new(StepStatus::Verified, true, CONSTITUTION_CHECKPOINT_VERSION)
.with_result("existing constitution kept unchanged"),
);
self.state = state.clone();
ViewAction::EmitAndClose(ViewEvent::SetupStateCommitRequested {
state,
message: tr(self.locale, MessageId::SetupCheckpointDoneKept).to_string(),
})
}
fn commit_keep_existing_constitution(&mut self) -> ViewAction {
let Some(constitution) = self.load_existing_constitution() else {
return ViewAction::None;
};
if !self.existing_preview_seen {
self.existing_preview_seen = true;
let content = constitution_ratification_text(
self.locale,
&constitution,
&DraftProvenance::Existing,
);
return ViewAction::Emit(ViewEvent::OpenTextPager {
title: ratification_preview_title(self.locale).to_string(),
content,
});
}
self.commit_existing_constitution_unchanged()
}
fn status_label(&self, status: StepStatus) -> Cow<'static, str> {
tr(
self.locale,
match status {
StepStatus::NotStarted => MessageId::SetupStatusNotStarted,
StepStatus::Recommended => MessageId::SetupStatusRecommended,
StepStatus::Optional => MessageId::SetupStatusOptional,
StepStatus::Deferred => MessageId::SetupStatusDeferred,
StepStatus::InProgress => MessageId::SetupStatusInProgress,
StepStatus::NeedsAction => MessageId::SetupStatusNeedsAction,
StepStatus::Verified => MessageId::SetupStatusVerified,
StepStatus::Skipped => MessageId::SetupStatusSkipped,
StepStatus::Failed => MessageId::SetupStatusFailed,
},
)
}
}
impl ModalView for SetupWizardView {
fn kind(&self) -> ModalKind {
ModalKind::SetupWizard
}
fn handle_key(&mut self, key: KeyEvent) -> ViewAction {
if let Some(action) = self.handle_freeform_note_key(key) {
return action;
}
if self.selected_step() == SetupStep::Constitution && !self.constitution_advanced {
return match key.code {
KeyCode::Esc | KeyCode::Char('q') => ViewAction::Close,
KeyCode::Left | KeyCode::Char('b') => {
self.move_back();
ViewAction::None
}
KeyCode::Char('c') => self.open_constitution_advanced(),
KeyCode::Enter => self.commit_simple_constitution(),
_ => ViewAction::None,
};
}
if self.selected_step() == SetupStep::Constitution
&& self.constitution_advanced
&& key.code == KeyCode::Esc
{
return self.close_constitution_advanced();
}
match key.code {
KeyCode::Esc | KeyCode::Char('q') => ViewAction::Close,
KeyCode::Char('i') | KeyCode::Char('?') if self.progressive_guide => {
self.details_expanded = !self.details_expanded;
self.body_scroll = 0;
ViewAction::None
}
KeyCode::Left | KeyCode::Char('b') => {
self.move_back();
ViewAction::None
}
KeyCode::Right | KeyCode::Char('n') => {
self.move_next();
ViewAction::None
}
KeyCode::PageUp => {
self.body_scroll = self.body_scroll.saturating_sub(8);
ViewAction::None
}
KeyCode::PageDown => {
self.body_scroll = self.body_scroll.saturating_add(8);
ViewAction::None
}
KeyCode::Up if self.progressive_guide => {
self.body_scroll = self.body_scroll.saturating_sub(1);
ViewAction::None
}
KeyCode::Down if self.progressive_guide => {
self.body_scroll = self.body_scroll.saturating_add(1);
ViewAction::None
}
KeyCode::Up => {
self.move_back();
ViewAction::None
}
KeyCode::Down => {
self.move_next();
ViewAction::None
}
KeyCode::Char('s') if self.progressive_guide => {
if self.selected_step() == SetupStep::Verification {
ViewAction::Close
} else {
self.move_next();
ViewAction::None
}
}
KeyCode::Char('s') => {
self.commit_selected_status(StepStatus::Skipped, MessageId::SetupStepSkipped, true)
}
KeyCode::Char('r')
if self.progressive_guide
&& matches!(
self.selected_step(),
SetupStep::RemoteRuntime | SetupStep::Verification
) =>
{
ViewAction::EmitAndClose(ViewEvent::SetupOpenRemoteControlRequested)
}
KeyCode::Char('p')
if self.progressive_guide && self.selected_step() == SetupStep::Verification =>
{
ViewAction::EmitAndClose(ViewEvent::SetupOpenProviderRequested)
}
KeyCode::Char('c')
if self.progressive_guide && self.selected_step() == SetupStep::Verification =>
{
self.selected = visible_step_index(SetupStep::TrustSandbox);
self.details_expanded = false;
self.body_scroll = 0;
ViewAction::None
}
KeyCode::Char('r')
if !self.progressive_guide && self.selected_step() == SetupStep::ToolsMcp =>
{
self.preview_tools_mcp_on_ramp()
}
KeyCode::Char('r') if self.selected_step() == SetupStep::RemoteRuntime => {
self.preview_remote_runtime_on_ramp()
}
KeyCode::Char('r') => self.commit_selected_status(
StepStatus::NeedsAction,
MessageId::SetupStepRetryRecorded,
false,
),
KeyCode::Char('g') if self.selected_step() == SetupStep::Constitution => {
self.commit_guided_constitution()
}
KeyCode::Char('p') if self.selected_step() == SetupStep::ProviderModel => {
ViewAction::EmitAndClose(ViewEvent::SetupOpenProviderRequested)
}
KeyCode::Char('m') if self.selected_step() == SetupStep::ProviderModel => {
ViewAction::EmitAndClose(ViewEvent::SetupOpenModelRequested)
}
KeyCode::Char('p') if self.selected_step() == SetupStep::OperateFleet => {
ViewAction::EmitAndClose(ViewEvent::SetupOpenProviderRequested)
}
KeyCode::Char('f') if self.selected_step() == SetupStep::OperateFleet => {
ViewAction::EmitAndClose(ViewEvent::SetupOpenFleetRequested)
}
KeyCode::Char('h') if self.selected_step() == SetupStep::Hotbar => {
ViewAction::EmitAndClose(ViewEvent::SetupOpenHotbarRequested)
}
KeyCode::Char('m') if self.selected_step() == SetupStep::TrustSandbox => {
ViewAction::EmitAndClose(ViewEvent::SetupOpenModeRequested)
}
KeyCode::Char('c') if self.selected_step() == SetupStep::TrustSandbox => {
ViewAction::EmitAndClose(ViewEvent::SetupOpenConfigRequested)
}
KeyCode::Char(key @ ('1' | '2' | '3'))
if self.selected_step() == SetupStep::TrustSandbox =>
{
self.select_runtime_preset(key)
}
KeyCode::Char('a') if self.selected_step() == SetupStep::TrustSandbox => {
self.commit_runtime_preset()
}
KeyCode::Char(key @ ('1' | '2' | '3' | '4' | '5' | '6'))
if self.selected_step() == SetupStep::Constitution =>
{
self.cycle_guided_answer(key)
}
KeyCode::Char('a') if self.selected_step() == SetupStep::Constitution => {
self.request_model_draft()
}
KeyCode::Char('f') if self.selected_step() == SetupStep::Constitution => {
self.toggle_freeform_edit()
}
KeyCode::Char('k') if self.selected_step() == SetupStep::Constitution => {
self.commit_keep_existing_constitution()
}
KeyCode::Char('u') => self.commit_constitution(SetupCommitKind::BundledConstitution),
KeyCode::Char('d') => self.commit_constitution(SetupCommitKind::DeferredConstitution),
KeyCode::Enter if self.selected_step() == SetupStep::Constitution => {
self.commit_constitution(SetupCommitKind::BundledConstitution)
}
KeyCode::Enter if self.selected_step() == SetupStep::Language => {
self.commit_language_review()
}
KeyCode::Enter if self.selected_step() == SetupStep::ProviderModel => {
if self.progressive_guide && !self.facts.provider_ready {
ViewAction::EmitAndClose(ViewEvent::SetupOpenProviderRequested)
} else {
self.commit_provider_model_review()
}
}
KeyCode::Enter if self.selected_step() == SetupStep::TrustSandbox => {
self.commit_runtime_posture_review()
}
KeyCode::Enter if self.selected_step() == SetupStep::OperateFleet => {
self.commit_operate_fleet_review()
}
KeyCode::Enter if self.selected_step() == SetupStep::Hotbar => {
self.commit_hotbar_review()
}
KeyCode::Enter if self.selected_step() == SetupStep::ToolsMcp => {
self.commit_tools_mcp_review()
}
KeyCode::Enter if self.selected_step() == SetupStep::RemoteRuntime => {
self.commit_remote_runtime_review()
}
KeyCode::Enter if self.selected_step() == SetupStep::Persistence => {
self.commit_persistence_review()
}
KeyCode::Enter if self.selected_step() == SetupStep::Verification => {
self.commit_setup_report()
}
KeyCode::Enter => {
self.move_next();
ViewAction::None
}
_ => ViewAction::None,
}
}
fn handle_paste(&mut self, text: &str) -> bool {
if self.selected_step() != SetupStep::Constitution || !self.constitution_advanced {
return false;
}
self.append_freeform_note_text(text);
true
}
fn render(&self, area: Rect, buf: &mut Buffer) {
let inner = render_underwater_surface(area, buf, self.surface_title());
let simple_constitution =
self.selected_step() == SetupStep::Constitution && !self.constitution_advanced;
let hints = if self.progressive_guide {
self.progressive_action_hints()
} else if simple_constitution {
vec![
ActionHint::new(
"Enter",
tr(
self.locale,
if self.facts.constitution_file == SetupConstitutionFileState::Loaded {
MessageId::SetupActionKeepExisting
} else {
MessageId::SetupActionUseRecommended
},
)
.to_string(),
),
ActionHint::new(
"C",
tr(self.locale, MessageId::SetupActionCustomize).to_string(),
),
ActionHint::new("B", tr(self.locale, MessageId::SetupActionBack).to_string()),
ActionHint::new(
"Esc",
tr(self.locale, MessageId::SetupActionCancel).to_string(),
),
]
} else {
let mut hints = vec![
ActionHint::new(
"Enter",
tr(self.locale, MessageId::SetupActionContinue).to_string(),
),
ActionHint::new("B", tr(self.locale, MessageId::SetupActionBack).to_string()),
ActionHint::new("S", tr(self.locale, MessageId::SetupActionSkip).to_string()),
];
self.extend_focused_action_hints(&mut hints);
hints.push(ActionHint::new(
"Esc",
tr(self.locale, MessageId::SetupActionCancel).to_string(),
));
hints
};
let content_area = render_modal_footer(inner, buf, &hints);
let spec = self.selected_spec();
let (title_text, question_text) = if self.progressive_guide {
match self.selected_step() {
SetupStep::ProviderModel => (
tr(self.locale, MessageId::OnboardProviderTitle).into_owned(),
tr(self.locale, MessageId::OnboardProviderBlurb).into_owned(),
),
SetupStep::TrustSandbox => (
tr(self.locale, MessageId::SetupStepTrustSandboxTitle).into_owned(),
tr(self.locale, MessageId::SetupRuntimePostureReviewHint).into_owned(),
),
SetupStep::RemoteRuntime => (
"/rc".to_string(),
tr(self.locale, MessageId::CmdRemoteControlDescription).into_owned(),
),
SetupStep::Verification => (
tr(self.locale, MessageId::OnboardReadyTitle).into_owned(),
tr(self.locale, MessageId::OnboardReadyLead).into_owned(),
),
_ => (
tr(self.locale, spec.title_id()).into_owned(),
tr(self.locale, spec.why_id()).into_owned(),
),
}
} else {
(
tr(self.locale, spec.title_id()).into_owned(),
tr(self.locale, spec.why_id()).into_owned(),
)
};
let title = Line::from(Span::styled(
title_text,
Style::default()
.fg(palette::WHALE_INFO)
.add_modifier(Modifier::BOLD),
));
let why = Line::from(Span::raw(question_text));
let mut lines = vec![title, why, Line::from("")];
lines.extend(self.selected_step_detail_lines());
let wrap_width = usize::from(content_area.width).max(1);
let visual_rows: usize = lines
.iter()
.map(|line| line.width().div_ceil(wrap_width).max(1))
.sum();
let visible_rows = usize::from(content_area.height).max(1);
let max_scroll = visual_rows.saturating_sub(visible_rows);
let scroll = self.body_scroll.min(max_scroll);
let content_area =
render_panel_scroll_rail(content_area, buf, visual_rows, scroll, visible_rows, true);
Paragraph::new(lines)
.wrap(Wrap { trim: false })
.scroll((scroll as u16, 0))
.render(content_area, buf);
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
impl SetupWizardView {
fn progressive_action_hints(&self) -> Vec<ActionHint> {
let back = || ActionHint::new("B", tr(self.locale, MessageId::SetupActionBack).to_string());
let exit = || {
ActionHint::new(
"Esc",
tr(self.locale, MessageId::SetupActionCancel).to_string(),
)
};
let details = || {
ActionHint::new(
"I",
tr(self.locale, MessageId::CtxMenuOpenDetails).to_string(),
)
};
let skip = || ActionHint::new("S", tr(self.locale, MessageId::SetupActionSkip).to_string());
let mut hints = match self.selected_step() {
SetupStep::ProviderModel => vec![
ActionHint::new(
"Enter",
tr(
self.locale,
if self.facts.provider_ready {
MessageId::SetupActionContinue
} else {
MessageId::SetupActionProvider
},
)
.to_string(),
),
skip(),
details(),
exit(),
],
SetupStep::TrustSandbox => vec![
ActionHint::new(
"Enter",
tr(self.locale, MessageId::SetupActionKeepExisting).to_string(),
),
skip(),
details(),
exit(),
],
SetupStep::RemoteRuntime => vec![
ActionHint::new(
"R",
tr(self.locale, MessageId::CmdRemoteControlDescription).to_string(),
),
skip(),
details(),
exit(),
],
SetupStep::ToolsMcp => vec![
ActionHint::new(
"Enter",
tr(self.locale, MessageId::SetupActionContinue).to_string(),
),
skip(),
details(),
exit(),
],
SetupStep::Verification => vec![
ActionHint::new(
"Enter",
tr(self.locale, MessageId::OnboardReadyStart).to_string(),
),
details(),
exit(),
],
_ => vec![exit()],
};
let position = self
.progressive_steps()
.iter()
.position(|step| *step == self.selected_step())
.unwrap_or(0);
if position > 0 {
hints.insert(hints.len().saturating_sub(1), back());
}
hints
}
fn extend_focused_action_hints(&self, hints: &mut Vec<ActionHint>) {
match self.selected_step() {
SetupStep::Constitution if self.constitution_advanced => {
hints.push(ActionHint::new(
"1-6",
tr(self.locale, MessageId::SetupActionTuneGuided).to_string(),
));
hints.push(ActionHint::new(
"G",
tr(self.locale, MessageId::SetupActionGuided).to_string(),
));
hints.push(ActionHint::new(
"F",
tr(self.locale, MessageId::SetupActionFreeform).to_string(),
));
}
SetupStep::ProviderModel => {
hints.push(ActionHint::new(
"P",
tr(self.locale, MessageId::SetupActionProvider).to_string(),
));
hints.push(ActionHint::new(
"M",
tr(self.locale, MessageId::SetupActionModel).to_string(),
));
}
SetupStep::OperateFleet => hints.push(ActionHint::new(
"F",
tr(self.locale, MessageId::SetupActionFleet).to_string(),
)),
SetupStep::Hotbar => hints.push(ActionHint::new(
"H",
tr(self.locale, MessageId::SetupActionHotbar).to_string(),
)),
SetupStep::ToolsMcp | SetupStep::RemoteRuntime => hints.push(ActionHint::new(
"R",
tr(self.locale, MessageId::SetupActionRetry).to_string(),
)),
SetupStep::TrustSandbox => hints.push(ActionHint::new(
"C",
tr(self.locale, MessageId::SetupActionConfig).to_string(),
)),
_ => {}
}
}
fn selected_step_detail_lines(&self) -> Vec<Line<'static>> {
if self.progressive_guide {
return if self.details_expanded {
self.progressive_expanded_lines()
} else {
self.progressive_detail_lines()
};
}
match self.selected_step() {
SetupStep::ProviderModel => self.provider_model_detail_lines(),
SetupStep::TrustSandbox => self.runtime_posture_detail_lines(),
SetupStep::Constitution if self.constitution_advanced => {
self.constitution_detail_lines()
}
SetupStep::Constitution => self.constitution_simple_lines(),
SetupStep::OperateFleet => self.operate_fleet_detail_lines(),
SetupStep::Hotbar => self.hotbar_detail_lines(),
SetupStep::ToolsMcp => self.tools_mcp_detail_lines(),
SetupStep::RemoteRuntime => self.remote_runtime_detail_lines(),
SetupStep::Persistence => self.persistence_detail_lines(),
SetupStep::Verification => self.verification_detail_lines(),
_ => Vec::new(),
}
}
fn progressive_detail_lines(&self) -> Vec<Line<'static>> {
match self.selected_step() {
SetupStep::ProviderModel => {
let answer = format!(
"{} ยท {} ยท {}",
self.facts.provider, self.facts.model, self.facts.auth
);
vec![self.detail_row(MessageId::SetupCardRouteLabel, &answer)]
}
SetupStep::TrustSandbox => {
let answer = format!(
"{} ยท {} ยท {}",
self.facts.approval, self.facts.trust, self.facts.sandbox
);
let mut lines = vec![self.detail_row(MessageId::SetupCardApprovalLabel, &answer)];
if let Some(warning) = &self.facts.project_override_warning {
lines.push(
self.detail_row(MessageId::SetupRuntimeProjectOverrideLabel, warning),
);
}
lines
}
SetupStep::RemoteRuntime => vec![self.detail_row(
MessageId::SetupRemoteModeLabel,
&self.facts.remote_control_result,
)],
SetupStep::ToolsMcp => {
let status = tr(
self.locale,
if self.facts.tools_mcp_needs_action {
MessageId::SetupStatusNeedsAction
} else {
MessageId::SetupStatusVerified
},
)
.into_owned();
vec![self.detail_row(MessageId::SetupStepToolsMcpTitle, &status)]
}
SetupStep::Verification => self.progressive_summary_lines(),
_ => self.selected_step_detail_lines_expanded(),
}
}
fn selected_step_detail_lines_expanded(&self) -> Vec<Line<'static>> {
match self.selected_step() {
SetupStep::ProviderModel => self.provider_model_detail_lines(),
SetupStep::TrustSandbox => self.runtime_posture_detail_lines(),
SetupStep::ToolsMcp => self.tools_mcp_detail_lines(),
SetupStep::RemoteRuntime => self.remote_runtime_detail_lines(),
SetupStep::Verification => self.verification_detail_lines(),
_ => Vec::new(),
}
}
fn progressive_expanded_lines(&self) -> Vec<Line<'static>> {
if self.selected_step() != SetupStep::Verification {
return self.selected_step_detail_lines_expanded();
}
let mut lines = self.progressive_summary_lines();
lines.push(Line::from(""));
lines.push(Line::from(vec![
Span::styled(
"/settings ",
Style::default()
.fg(palette::WHALE_INFO)
.add_modifier(Modifier::BOLD),
),
Span::raw(tr(self.locale, MessageId::CmdSettingsDescription).to_string()),
]));
lines.push(Line::from(vec![
Span::styled(
"/config <key> ",
Style::default()
.fg(palette::TEXT_MUTED)
.add_modifier(Modifier::BOLD),
),
Span::raw(tr(self.locale, MessageId::SetupActionConfig).to_string()),
]));
lines
}
fn progressive_summary_lines(&self) -> Vec<Line<'static>> {
let route = format!("{} ยท {}", self.facts.provider, self.facts.model);
let permissions = format!(
"{} ยท {} ยท {}",
self.facts.approval, self.facts.trust, self.facts.sandbox
);
let mut lines = vec![
self.detail_row(MessageId::SetupStepProviderModelTitle, &route),
self.detail_row(MessageId::SetupStepTrustSandboxTitle, &permissions),
self.detail_row(
MessageId::SetupStepRemoteRuntimeTitle,
&self.facts.remote_control_result,
),
];
if self.tools_relevant() {
let tools_status = tr(
self.locale,
if self.facts.tools_mcp_needs_action {
MessageId::SetupStatusNeedsAction
} else {
MessageId::SetupStatusVerified
},
)
.into_owned();
lines.push(self.detail_row(MessageId::SetupStepToolsMcpTitle, &tools_status));
}
lines
}
fn constitution_simple_lines(&self) -> Vec<Line<'static>> {
if self.facts.constitution_file == SetupConstitutionFileState::Loaded {
return vec![
self.detail_row(
MessageId::SetupConstitutionExistingLabel,
&self
.facts
.constitution_file
.label(self.state.constitution_choice, self.locale),
),
Line::from(Span::styled(
tr(
self.locale,
MessageId::SetupConstitutionExistingDefaultDetail,
)
.to_string(),
Style::default().fg(palette::TEXT_MUTED),
)),
];
}
if !matches!(
self.facts.constitution_file,
SetupConstitutionFileState::NotChecked | SetupConstitutionFileState::Missing
) {
return vec![
self.detail_row(
MessageId::SetupConstitutionExistingLabel,
&self
.facts
.constitution_file
.label(self.state.constitution_choice, self.locale),
),
Line::from(Span::styled(
tr(self.locale, MessageId::SetupConstitutionRepairDefaultDetail).to_string(),
Style::default().fg(palette::TEXT_MUTED),
)),
];
}
let recommendation = format!(
"{} ยท {}",
tr(self.locale, MessageId::SetupStatusRecommended),
autonomy_label(AutonomyPreference::Balanced, self.locale)
);
vec![
Line::from(Span::styled(
recommendation,
Style::default()
.fg(palette::TEXT_PRIMARY)
.add_modifier(Modifier::BOLD),
)),
Line::from(Span::styled(
autonomy_priority(AutonomyPreference::Balanced, self.locale).to_string(),
Style::default().fg(palette::TEXT_MUTED),
)),
]
}
fn provider_model_detail_lines(&self) -> Vec<Line<'static>> {
vec![
self.detail_row(MessageId::SetupCardRouteLabel, &self.facts.provider),
self.detail_row(MessageId::SetupCardModelLabel, &self.facts.model),
self.detail_row(MessageId::SetupCardAuthLabel, &self.facts.auth),
self.detail_row(MessageId::SetupCardHealthLabel, &self.facts.health),
Line::from(Span::styled(
tr(
self.locale,
if self.facts.provider_ready {
MessageId::SetupProviderModelReadyHint
} else {
MessageId::SetupProviderModelNeedsActionHint
},
)
.to_string(),
Style::default().fg(palette::TEXT_MUTED),
)),
]
}
fn constitution_detail_lines(&self) -> Vec<Line<'static>> {
let choice = constitution_choice_label(self.state.constitution_choice);
let source = constitution_source_label(self.state.constitution_source);
let validity = constitution_validity_label(self.state.constitution_validity);
let source_state = format!("{source}; validity {validity}");
let existing_file = self
.facts
.constitution_file
.label(self.state.constitution_choice, self.locale);
let expert_override = self.facts.expert_override.label(self.locale);
let preview = self
.state
.constitution_preview_hash
.as_deref()
.unwrap_or("not accepted yet")
.to_string();
let mut lines = vec![
self.detail_row(MessageId::SetupConstitutionChoiceLabel, choice),
self.detail_row(MessageId::SetupConstitutionSourceLabel, &source_state),
self.detail_row(MessageId::SetupConstitutionPreviewLabel, &preview),
self.detail_row(MessageId::SetupConstitutionExistingLabel, &existing_file),
self.detail_row(
MessageId::SetupConstitutionExpertOverrideLabel,
&expert_override,
),
Line::from(Span::styled(
tr(self.locale, MessageId::SetupConstitutionGuidedAnswersHint).to_string(),
Style::default().fg(palette::TEXT_MUTED),
)),
self.guided_answer_pair(
(
"1",
MessageId::SetupConstitutionPurposeLabel,
&self.guided_draft.purpose.label(self.locale),
),
(
"2",
MessageId::SetupConstitutionAutonomyLabel,
autonomy_label(self.guided_draft.autonomy, self.locale),
),
),
self.guided_answer_pair(
(
"3",
MessageId::SetupConstitutionEvidenceLabel,
&self.guided_draft.evidence.label(self.locale),
),
(
"4",
MessageId::SetupConstitutionCommunicationLabel,
self.guided_draft.communication.label(self.locale),
),
),
self.guided_answer_single(
"5",
MessageId::SetupConstitutionPrivacyLabel,
self.guided_draft.privacy.label(self.locale),
),
self.guided_answer_single(
"6",
MessageId::SetupConstitutionPrinciplesLabel,
self.guided_draft.principles.label(self.locale),
),
freeform_note_line(self.locale, &self.freeform_note, self.editing_freeform_note),
];
if self.facts.constitution_file == SetupConstitutionFileState::Loaded {
lines.push(Line::from(Span::styled(
keep_existing_invitation_line(self.locale),
Style::default().fg(palette::WHALE_HUMAN),
)));
}
if let Some(label) = self
.model_draft_label
.as_deref()
.filter(|_| self.model_draft.is_some())
{
lines.push(Line::from(Span::styled(
model_draft_ready_line(self.locale, label),
Style::default().fg(palette::STATUS_SUCCESS),
)));
} else if self.facts.provider_ready {
lines.push(Line::from(Span::styled(
model_draft_invitation_line(self.locale, &self.facts.model),
Style::default().fg(palette::WHALE_HUMAN),
)));
}
lines.push(Line::from(Span::styled(
tr(self.locale, MessageId::SetupConstitutionGuidedHint).to_string(),
Style::default().fg(palette::TEXT_MUTED),
)));
lines
}
fn runtime_posture_detail_lines(&self) -> Vec<Line<'static>> {
let project_override = self
.facts
.project_override_warning
.clone()
.unwrap_or_else(|| {
tr(self.locale, MessageId::SetupRuntimeProjectOverrideNone).to_string()
});
let mut lines = vec![
self.detail_row(MessageId::SetupCardIntentLabel, &self.facts.work_intent),
self.detail_row(MessageId::SetupCardApprovalLabel, &self.facts.approval),
self.detail_row(MessageId::SetupCardShellLabel, &self.facts.shell),
self.detail_row(MessageId::SetupCardTrustLabel, &self.facts.trust),
self.detail_row(MessageId::SetupCardSandboxLabel, &self.facts.sandbox),
self.detail_row(MessageId::SetupCardNetworkLabel, &self.facts.network),
self.detail_row(
MessageId::SetupRuntimePresetSelectedLabel,
&runtime_preset_summary(self.locale, self.runtime_preset),
),
self.detail_row(
MessageId::SetupRuntimePresetDiffLabel,
&runtime_preset_inline_diff(self.runtime_preset, &self.facts),
),
self.detail_row(
MessageId::SetupRuntimeProjectOverrideLabel,
&project_override,
),
Line::from(Span::styled(
tr(self.locale, MessageId::SetupRuntimePostureBoundary).to_string(),
Style::default().fg(palette::TEXT_MUTED),
)),
Line::from(Span::styled(
tr(self.locale, MessageId::SetupRuntimePresetSafetyFloor).to_string(),
Style::default().fg(palette::TEXT_MUTED),
)),
self.setup_review_hint_line(
MessageId::SetupRuntimePostureReviewHint,
Some("Press M for work mode or C for config."),
),
Line::from(Span::styled(
tr(self.locale, MessageId::SetupRuntimePresetApplyHint).to_string(),
Style::default().fg(palette::TEXT_MUTED),
)),
];
for (idx, preset) in SetupRuntimePreset::ALL.iter().enumerate() {
let marker = if *preset == self.runtime_preset {
">"
} else {
" "
};
lines.push(Line::from(Span::styled(
format!(
"{marker} {}. {}",
idx + 1,
runtime_preset_summary(self.locale, *preset)
),
Style::default().fg(if *preset == self.runtime_preset {
palette::TEXT_PRIMARY
} else {
palette::TEXT_MUTED
}),
)));
}
lines
}
fn operate_fleet_detail_lines(&self) -> Vec<Line<'static>> {
let route = format!("{} / {}", self.facts.provider, self.facts.model);
let readiness = self.ready_label(self.operate_fleet_facts_ready());
vec![
self.detail_row(MessageId::SetupCardRouteLabel, &route),
self.detail_row(MessageId::SetupCardAuthLabel, &self.facts.auth),
self.detail_row(
MessageId::SetupOperateRuntimeLabel,
&self.facts.operate_runtime_result,
),
self.detail_row(
MessageId::SetupOperateRosterLabel,
&self.facts.fleet_roster_result,
),
self.detail_row(
MessageId::SetupOperateConcurrencyLabel,
&self.facts.operate_concurrency_result,
),
self.detail_row(MessageId::SetupOperateReadinessLabel, &readiness),
self.setup_review_hint_line(MessageId::SetupOperateReviewHint, None),
]
}
fn hotbar_detail_lines(&self) -> Vec<Line<'static>> {
vec![
self.detail_row(
MessageId::SetupHotbarBindingsLabel,
&self.facts.hotbar_bindings_result,
),
self.detail_row(
MessageId::SetupHotbarActionsLabel,
&self.facts.hotbar_actions_result,
),
self.setup_review_hint_line(
MessageId::SetupHotbarReviewHint,
Some("Press H to customize slots."),
),
]
}
fn tools_mcp_detail_lines(&self) -> Vec<Line<'static>> {
vec![
self.detail_row(
MessageId::SetupToolsMcpServersLabel,
&self.facts.tools_mcp_servers_result,
),
self.detail_row(
MessageId::SetupToolsMcpSkillsLabel,
&self.facts.tools_mcp_skills_result,
),
self.detail_row(
MessageId::SetupToolsMcpToolsLabel,
&self.facts.tools_mcp_tools_result,
),
self.detail_row(
MessageId::SetupToolsMcpPluginsLabel,
&self.facts.tools_mcp_plugins_result,
),
self.detail_row(
MessageId::SetupToolsMcpHotbarLabel,
&self.facts.tools_mcp_hotbar_result,
),
self.detail_row(
MessageId::SetupToolsMcpDshLabel,
&self.facts.tools_mcp_dsh_result,
),
self.setup_review_hint_line(
MessageId::SetupToolsMcpReviewHint,
Some("Press R for safe on-ramps (no auto-run)."),
),
]
}
fn remote_runtime_detail_lines(&self) -> Vec<Line<'static>> {
let mut lines = Vec::new();
for fact in &self.facts.remote_modes {
lines.push(self.detail_row(
fact.mode.label_id(),
&format!(
"{} ยท {}",
tr(self.locale, fact.status.label_id()),
fact.detail
),
));
}
if lines.is_empty() {
lines.push(self.detail_row(
MessageId::SetupRemoteModeLabel,
&self.facts.remote_mode_result,
));
}
lines.push(self.detail_row(
MessageId::SetupRemoteProvidersLabel,
&self.facts.remote_providers_result,
));
lines.push(self.setup_review_hint_line(
MessageId::SetupRemoteReviewHint,
Some("Press R to preview (nothing is written). Enter keeps local-only."),
));
lines
}
fn persistence_detail_lines(&self) -> Vec<Line<'static>> {
vec![
self.detail_row(
MessageId::SetupPersistenceHomeLabel,
&self.facts.persistence.home_result,
),
self.detail_row(
MessageId::SetupPersistenceConfigLabel,
&self.facts.persistence.config_result,
),
self.detail_row(
MessageId::SetupPersistenceStateLabel,
&self.facts.persistence.state_result,
),
self.detail_row(
MessageId::SetupPersistenceConstitutionLabel,
&self.facts.persistence.constitution_result,
),
self.detail_row(
MessageId::SetupPersistenceMemoryLabel,
&self.facts.persistence.memory_result,
),
self.detail_row(
MessageId::SetupPersistenceNotesLabel,
&self.facts.persistence.notes_result,
),
self.setup_review_hint_line(MessageId::SetupPersistenceReviewHint, None),
]
}
fn verification_detail_lines(&self) -> Vec<Line<'static>> {
let mut lines = vec![
self.detail_row(
MessageId::SetupReportFirstRunLabel,
&self.ready_label(self.state.first_run_ready()),
),
self.detail_row(
MessageId::SetupReportUpdateLabel,
&self.ready_label(self.state.update_ready(CONSTITUTION_CHECKPOINT_VERSION)),
),
self.detail_row(
MessageId::SetupReportOperateLabel,
&self.ready_label(self.state.operate_ready()),
),
self.detail_row(
MessageId::SetupReportSourceLabel,
&self.state_source_label(),
),
self.detail_row(
MessageId::SetupReportAutonomyLabel,
&self.facts.constitution_autonomy,
),
self.detail_row(
MessageId::SetupReportRuntimePostureLabel,
&self.facts.runtime_result,
),
Line::from(""),
Line::from(Span::styled(
tr(self.locale, MessageId::SetupReportRowsLabel).to_string(),
Style::default()
.fg(palette::TEXT_MUTED)
.add_modifier(Modifier::BOLD),
)),
];
for spec in STEP_SPECS {
let step = spec.id();
let entry = self.state.steps.get(&step);
let required = entry.map_or(spec.required(), |entry| entry.required);
let required_label = if required {
tr(self.locale, MessageId::SetupReportRequired)
} else {
tr(self.locale, MessageId::SetupReportOptional)
};
let mut value = format!(
"{} ({})",
self.status_label(self.state.status(step)),
required_label
);
if let Some(version) = entry.and_then(|entry| entry.version.as_deref()) {
value.push_str(&format!(" ยท {version}"));
}
if let Some(result) = entry.and_then(|entry| entry.result.as_deref()) {
value.push_str(&format!(" ยท {result}"));
}
lines.push(self.detail_row(spec.title_id(), &value));
}
lines.push(Line::from(""));
let next_action = tr(self.locale, self.next_action_id()).to_string();
lines.push(self.detail_row(MessageId::SetupReportNextActionLabel, &next_action));
lines
}
fn setup_review_hint_line(
&self,
hint_id: MessageId,
english_action: Option<&'static str>,
) -> Line<'static> {
let hint = if self.locale == Locale::En {
let mut hint = "Enter records this setup snapshot.".to_string();
if let Some(action) = english_action {
hint.push(' ');
hint.push_str(action);
}
hint
} else {
tr(self.locale, hint_id).to_string()
};
Line::from(Span::styled(hint, Style::default().fg(palette::TEXT_MUTED)))
}
fn ready_label(&self, ready: bool) -> String {
if ready {
tr(self.locale, MessageId::SetupReportReady).to_string()
} else {
tr(self.locale, MessageId::SetupStatusNeedsAction).to_string()
}
}
fn state_source_label(&self) -> String {
if self.state.inherited {
tr(self.locale, MessageId::SetupReportInherited).to_string()
} else {
tr(self.locale, MessageId::SetupReportPersisted).to_string()
}
}
fn next_action_id(&self) -> MessageId {
if !self.state.update_ready(CONSTITUTION_CHECKPOINT_VERSION) {
return MessageId::SetupReportNextActionConstitution;
}
if !matches!(
self.state.status(SetupStep::ProviderModel),
StepStatus::Verified | StepStatus::NeedsAction
) {
return MessageId::SetupReportNextActionProvider;
}
if !self.state.runtime_posture_source.is_reviewed() {
return MessageId::SetupReportNextActionRuntime;
}
if !self.state.first_run_ready() {
return MessageId::SetupReportNextActionRequired;
}
if !self.state.operate_ready() {
return MessageId::SetupReportNextActionOperate;
}
MessageId::SetupReportNextActionNone
}
fn detail_row(&self, label: MessageId, value: &str) -> Line<'static> {
Line::from(vec![
Span::styled(
format!("{} ", tr(self.locale, label)),
Style::default()
.fg(palette::TEXT_MUTED)
.add_modifier(Modifier::BOLD),
),
Span::raw(value.to_string()),
])
}
fn guided_answer_pair(
&self,
left: (&str, MessageId, &str),
right: (&str, MessageId, &str),
) -> Line<'static> {
let label_style = Style::default()
.fg(palette::TEXT_MUTED)
.add_modifier(Modifier::BOLD);
Line::from(vec![
Span::styled(
format!("{} {} ", left.0, tr(self.locale, left.1)),
label_style,
),
Span::raw(left.2.to_string()),
Span::styled(" ยท ", Style::default().fg(palette::TEXT_MUTED)),
Span::styled(
format!("{} {} ", right.0, tr(self.locale, right.1)),
label_style,
),
Span::raw(right.2.to_string()),
])
}
fn guided_answer_single(&self, key: &str, label: MessageId, value: &str) -> Line<'static> {
Line::from(vec![
Span::styled(
format!("{key} {} ", tr(self.locale, label)),
Style::default()
.fg(palette::TEXT_MUTED)
.add_modifier(Modifier::BOLD),
),
Span::raw(value.to_string()),
])
}
}
fn setup_report_ready(state: &SetupState) -> bool {
state.first_run_ready() || state.update_ready(CONSTITUTION_CHECKPOINT_VERSION)
}
fn runtime_preset_summary(locale: Locale, preset: SetupRuntimePreset) -> String {
format!(
"{} - {}",
tr(locale, preset.title_id()),
tr(locale, preset.description_id())
)
}
fn runtime_preset_inline_diff(preset: SetupRuntimePreset, facts: &SetupRuntimeFacts) -> String {
runtime_preset_diff_rows(preset, facts).join("; ")
}
fn runtime_preset_preview_text(
locale: Locale,
preset: SetupRuntimePreset,
facts: &SetupRuntimeFacts,
) -> String {
let mut lines = vec![
tr(locale, MessageId::SetupRuntimePresetPreviewTitle).to_string(),
runtime_preset_summary(locale, preset),
String::new(),
tr(locale, MessageId::SetupRuntimePresetDiffLabel).to_string(),
];
lines.extend(
runtime_preset_diff_rows(preset, facts)
.into_iter()
.map(|row| format!("- {row}")),
);
lines.extend([
String::new(),
tr(locale, MessageId::SetupRuntimePostureBoundary).to_string(),
tr(locale, MessageId::SetupRuntimePresetSafetyFloor).to_string(),
tr(locale, MessageId::SetupRuntimePresetApplyHint).to_string(),
]);
lines.join("\n")
}
fn runtime_preset_diff_rows(preset: SetupRuntimePreset, facts: &SetupRuntimeFacts) -> Vec<String> {
let approval_target = preset.approval_policy().map_or_else(
|| "removed; Full Access comes from settings.permission_posture".to_string(),
ToString::to_string,
);
let mut rows = vec![
format!(
"settings.default_mode: {} -> {}",
facts.default_mode,
preset.display_mode()
),
format!(
"settings.permission_posture: -> {}",
preset.permission_posture()
),
format!(
"config.approval_policy: {} -> {}",
facts.approval_policy_value, approval_target
),
format!(
"config.allow_shell: {} -> {}",
facts.allow_shell_enabled,
preset.allow_shell()
),
format!(
"config.sandbox_mode: {} -> {}",
facts.sandbox_mode_value,
preset.sandbox_mode()
),
format!(
"config.network.default: {} -> unchanged",
facts.network_default_value
),
format!("workspace trust: {} -> unchanged", facts.trust),
];
if let Some(warning) = facts.project_override_warning.as_deref() {
rows.push(format!("project override warning: {warning}"));
}
rows
}
fn project_runtime_override_warning(workspace: &Path, locale: Locale) -> Option<String> {
let outcome = codewhale_config::load_project_config_outcome(workspace);
if let Some((path, reason)) = outcome.invalid() {
let path = path.display();
return Some(match locale {
Locale::ZhHans => format!(
"ๆ ๆณ่งฃๆ้กน็ฎ้
็ฝฎ {path}๏ผ{reason}๏ผใๆญคๅทฅไฝๅบ็้กน็ฎ็บง่ฟ่กๅงฟๆ้ๅถๆช็ๆ๏ผๅฐๅ้ๅฐ็จๆท้ป่ฎคๅผใ",
),
_ => format!(
"Project config {path} could not be parsed ({reason}). Its runtime posture restrictions are NOT in effect; this workspace falls back to your user defaults.",
),
});
}
let project = outcome.into_config()?;
let mut fields = Vec::new();
if let Some(policy) = project.approval_policy.as_deref() {
fields.push(format!("approval_policy={policy}"));
}
if let Some(mode) = project.sandbox_mode.as_deref() {
fields.push(format!("sandbox_mode={mode}"));
}
if fields.is_empty() {
return None;
}
Some(match locale {
Locale::ZhHans => format!(
"ๆญคๅทฅไฝๅบ็้กน็ฎ้
็ฝฎๅ
ๅซ {}ใ้ข่ฎพไผไฟๅญ็จๆท้ป่ฎคๅผ๏ผ้กน็ฎ้
็ฝฎไปๅฏๅจๆญคๅทฅไฝๅบๆถ็ดง่ฟ่กๅงฟๆใ",
fields.join(", ")
),
_ => format!(
"Project config contains {}. Presets save user defaults; project config can still tighten runtime posture in this workspace.",
fields.join(", ")
),
})
}
fn setup_report_result(state: &SetupState, facts: &SetupRuntimeFacts) -> String {
format!(
"first_run={}, update={}, operate={}, constitution={:?}, autonomy={}, posture={:?}, runtime={}, operate_fleet={}",
if state.first_run_ready() {
"ready"
} else {
"needs_action"
},
if state.update_ready(CONSTITUTION_CHECKPOINT_VERSION) {
"ready"
} else {
"needs_action"
},
if state.operate_ready() {
"ready"
} else {
"needs_action"
},
state.constitution_choice,
facts.constitution_autonomy,
state.runtime_posture_source,
facts.runtime_result,
facts.operate_result
)
}
fn remote_runtime_on_ramp_text(locale: Locale, facts: &SetupRuntimeFacts) -> String {
remote::on_ramp_text(
locale,
&facts.remote_clouds_result,
&facts.remote_bridges_result,
&facts.remote_providers_result,
&facts.remote_mode_result,
&facts.remote_command_provider,
)
}
fn tools_mcp_on_ramp_text(locale: Locale, facts: &SetupRuntimeFacts) -> String {
let tools_facts = tools_mcp::SetupToolsMcpFacts {
servers_result: facts.tools_mcp_servers_result.clone(),
skills_result: facts.tools_mcp_skills_result.clone(),
tools_result: facts.tools_mcp_tools_result.clone(),
plugins_result: facts.tools_mcp_plugins_result.clone(),
hotbar_result: facts.tools_mcp_hotbar_result.clone(),
dsh_result: facts.tools_mcp_dsh_result.clone(),
result: facts.tools_mcp_result.clone(),
overall_status: if facts.tools_mcp_needs_action {
tools_mcp::InventoryStatus::NeedsConfig
} else if facts.tools_mcp_result.contains("overall=off") {
tools_mcp::InventoryStatus::Off
} else {
tools_mcp::InventoryStatus::Healthy
},
needs_action: facts.tools_mcp_needs_action,
mcp_path_display: facts.tools_mcp_path_display.clone(),
skills_path_display: facts.tools_mcp_skills_path_display.clone(),
plugins_path_display: facts.tools_mcp_plugins_path_display.clone(),
};
tools_mcp::on_ramp_text(locale, &tools_facts)
}
#[derive(Debug, Clone, PartialEq, Eq)]
enum DraftProvenance {
Guided,
Model(String),
Existing,
}
fn ratification_preview_title(locale: Locale) -> &'static str {
match locale {
Locale::Ja => "ใฆใผใถใผๆฒๆณ - ๆนๅๅใฎ่ๆก",
Locale::ZhHans => "็จๆทๅฎช็ซ โ ็กฎ่ฎคๅ่ๆก",
Locale::ZhHant => "ไฝฟ็จ่
ๆฒๆณ - ๆนๅๅ่ๆก",
Locale::PtBr => "Constituiรงรฃo do Usuรกrio - Rascunho para Ratificaรงรฃo",
Locale::Es419 => "Constituciรณn del Usuario - Borrador para Ratificaciรณn",
Locale::Vi => "Hiแบฟn phรกp Ngฦฐแปi dรนng - Bแบฃn nhรกp ฤแป phรช chuแบฉn",
Locale::Ko => "์ฌ์ฉ์ ํ๋ฒ - ์น์ธ ์ ์ด์",
Locale::Ca => "Constituciรณ de l'Usuari - Esborrany per a Ratificaciรณ",
Locale::De => "Nutzerverfassung - Entwurf zur Ratifizierung",
Locale::Fr => "Constitution de l'Utilisateur - Brouillon pour Ratification",
Locale::Id => "Konstitusi Pengguna - Draf untuk Ratifikasi",
Locale::Hi => "เคเคชเคฏเฅเคเคเคฐเฅเคคเคพ เคธเคเคตเคฟเคงเคพเคจ - เค
เคเคเฅเคเคพเคฐ เคนเฅเคคเฅ เคฎเคธเฅเคฆเคพ",
Locale::Ru => "ะะพะฝััะธัััะธั ะฟะพะปัะทะพะฒะฐัะตะปั - ะัะพะตะบั ะดะปั ัะฐัะธัะธะบะฐัะธะธ",
Locale::Uk => "ะะพะฝััะธััััั ะบะพัะธัััะฒะฐัะฐ - ะัะพัะบั ะดะปั ัะฐัะธััะบะฐััั",
_ => "User Constitution โ Draft for Ratification",
}
}
fn constitution_ratification_text(
locale: Locale,
constitution: &UserConstitution,
provenance: &DraftProvenance,
) -> String {
const RULE: &str = "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ";
let rendered = constitution
.render_block(None)
.unwrap_or_else(|| match locale {
Locale::Ja => "ๆง้ ๅใใใๆฒๆณใฏ็ฉบใงใใ".to_string(),
Locale::ZhHans => "็ปๆๅๅฎช็ซ ไธบ็ฉบใ".to_string(),
Locale::ZhHant => "็ตๆงๅๆฒๆณ็บ็ฉบใ".to_string(),
Locale::PtBr => "A constituiรงรฃo estruturada estรก vazia.".to_string(),
Locale::Es419 => "La constituciรณn estructurada estรก vacรญa.".to_string(),
Locale::Vi => "Hiแบฟn phรกp cรณ cแบฅu trรบc ฤang trแปng.".to_string(),
Locale::Ko => "๊ตฌ์กฐํ๋ ํ๋ฒ์ด ๋น์ด ์์ต๋๋ค.".to_string(),
Locale::Ca => "La constituciรณ estructurada รฉs buida.".to_string(),
Locale::De => "Die strukturierte Verfassung ist leer.".to_string(),
Locale::Fr => "La constitution structurรฉe est vide.".to_string(),
Locale::Id => "Konstitusi terstruktur kosong.".to_string(),
Locale::Hi => "เคธเคเคฐเคเคฟเคค เคธเคเคตเคฟเคงเคพเคจ เคเคพเคฒเฅ เคนเฅเฅค".to_string(),
Locale::Ru => "ะกัััะบัััะธัะพะฒะฐะฝะฝะฐั ะบะพะฝััะธัััะธั ะฟัััะฐ.".to_string(),
Locale::Uk => "ะกัััะบัััะพะฒะฐะฝะฐ ะบะพะฝััะธััััั ะฟะพัะพะถะฝั.".to_string(),
_ => "The structured constitution is empty.".to_string(),
});
let layer_order = tr(locale, MessageId::SetupCheckpointLayerOrder);
match locale {
Locale::Ja => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"{label} ใใใชใใฎใฌใคใๅ็ญใใ่ตท่ใใCodewhale ใๆง้ ๆค่จผใจๅข็ๅถ้ใ้ฉ็จใใพใใใ"
),
DraftProvenance::Guided => {
"ใใชใใฎใฌใคใๅ็ญใใๆฑบๅฎ็ใซ็ๆใใใพใใใ".to_string()
}
DraftProvenance::Existing => {
"ๆขๅญใฎๆฒๆณใ constitution.json ใใ่ชญใฟ่พผใฟใๅคๆดใใใซ่กจ็คบใใฆใใพใใ"
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"ใใใฏใใงใซๆๅนใชๅบๆบใงใใใใฌใใฅใผใ้ใใฆ K ใๆผใใจใใใฎใพใพไฟๆใใฆใใงใใฏใใคใณใใๅฎไบใใพใใ\
ใใกใคใซใฏๅคๆดใใใพใใใ/constitution ใพใใฏ /setup ใงใใคใงใไฟฎๆญฃใงใใพใใ"
}
_ => {
"็ขบ่ชใใใพใงใใฉใฎๅ
ๅฎนใๅบๆบใซใฏใชใใพใใใใใฌใใฅใผใ้ใใฆ G ใๆผใใจๆนๅใใฆไฟๅญใใพใใ\
/constitution ใพใใฏ /setup ใงใใคใงใไฟฎๆญฃใงใใพใใ"
}
};
format!(
"CODEWHALE ยท ใฆใผใถใผๆฒๆณ\n{RULE}\n\n{drafted_by}\n\n\
ใใใฏ Codewhale ใใใชใใจๅๅใใใใใฎๅธธ่จญใฎๅบๆบใงใใๅชใใๆฒๆณใฎใใใซใไฝฟใใใปใฉ็ญใใ\
็ถฒ็พ
็ใช่ฆๅใงใฏใชใๆ็ถใใๅๅใงๆงๆใใใใใชใใฎๅคๅใซๅใใใฆไฟฎๆญฃใงใใพใใ\
ใในใฆใฎๅๅฅๅคๆญใ่ฃใใฎใงใฏใชใๆจฉ้ใจๅข็ใๅฎใใใปใใทใงใณใ่ถใใฆๅๅใ็ถ็ถใใใพใใ\
ใใ ใใใใฏ่จๆถใงใฏใใใพใใใๅฑฅๆญดใงใฏใชใๅๅใไฟๆใใพใใ\n\n\
{rendered}\n\n\
ๆจฉ้ใฎ้ๅฑค\n{layer_order}\nใใชใใฎ็ดๆฅใฎๆ็คบใฏๅธธใซใใฎๆๆธใใๅชๅ
ใใใพใใ\n\n\
ใใใใงใใชใใใจ\n\
ใใใฏ่กๅใๅฐใใใฎใงใใๆฟ่ชใใชใทใผใใตใณใใใใฏในใShellใใใใใฏใผใฏใไฟก้ ผใMCP ๆจฉ้ใ\
ๆขๅฎใขใผใใๅ
ฌ้ใๆฏๅบใฎๆจฉ้ใไปไธใพใใฏๅคๆดใใใใจใฏใงใใพใใใใใใใฏๅฎ่กๆใซใใชใใ็ฎก็ใใพใใ\n\n\
็ธฎๅฐใณใขใจไปปๆใขใธใฅใผใซ\n\
็ตใฟ่พผใฟใฎใณใขใฏๅผใ็ถใๆๅนใงใใใใฎ่ๆกใฏใฆใผใถใผใฐใญใผใใซใฎ้ทๆ่จญๅฎใ ใใไฟๅญใใพใใ\
ๅฎ่กใจใชใผใฑในใใฌใผใทใงใณใฎๆฉ่ฝใฏใใฉใณใฟใคใ ใใชใทใผใ็พๅจใฎใใผใซใซใฟใญใฐใใพใใฏๅฐๆฅใฎไปปๆใขใธใฅใผใซใใๆไพใใใพใใใใฎใใฌใใฅใผใฏใขใธใฅใผใซใๆๅนๅใใใ่จญๅฎใๅคๆดใใพใใใ\n\n\
ๆนๅ\n{ratify_how}"
)
}
Locale::ZhHans => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"็ฑ {label} ๆ นๆฎไฝ ็ๅผๅฏผๅผ็ญๆก่ตท่๏ผๅนถๅทฒ็ฑ Codewhale ๅฎๆ็ปๆๆ ก้ชไธ่พน็้ๅถใ"
),
DraftProvenance::Guided => "็ฑไฝ ็ๅผๅฏผๅผ็ญๆก็กฎๅฎๆง็ๆใ".to_string(),
DraftProvenance::Existing => {
"ไฝ ็ฐๆ็ๅฎช็ซ ๏ผ่ฏปๅ่ช constitution.jsonโโๅๆ ทๅฑ็คบ๏ผๆชๅไปปไฝไฟฎๆนใ".to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"่ฟๅทฒๆฏไฝ ๅฝๅไฝฟ็จ็ๅฎช็ซ ใๅ
ณ้ญๆญค้ข่งๅๆ K ไฟ็ๅนถๅฎๆๆฃๆฅ็นโโๆไปถไธไผ่ขซไฟฎๆนใ\
ไนๅๅฏ้ๆถ็จ /constitution ๆ /setup ไฟฎๆนใ"
}
_ => {
"ๆช็ปไฝ ็กฎ่ฎค๏ผไปปไฝๅ
ๅฎน้ฝไธไผๆไธบๅฎช็ซ ใๅ
ณ้ญๆญค้ข่งๅๆ G ็กฎ่ฎคๅนถไฟๅญ๏ผ\
ไนๅๅฏ้ๆถ็จ /constitution ๆ /setup ไฟฎๆนใ"
}
};
format!(
"CODEWHALE ยท ็จๆทๅฎช็ซ \n{RULE}\n\n{drafted_by}\n\n\
่ฟๆฏ Codewhale ไธไฝ ๅไฝๆถ้ฟๆ้ตๅพช็ๅๅฅฝๅ่งๅใๅ
ๅฎนๅบไฟๆ็ฎ็ญใไพฟไบๆง่ก๏ผไปฅๆไน
ๅๅไธบไธป๏ผๅนถๅฏ้ๆถ่ฐๆดใ\
ๅฎ็ๅฎๅไฝๆนๅผไธ่กไธบ่พน็๏ผ่ไธๆฏๆฟไฝ ๅณๅฎๆฏไธ็งๆ
ๅต๏ผๅฎ่ฎฉๅไฝ่ทจไผ่ฏๅปถ็ปญโโไฝๅฎไธๆฏ่ฎฐๅฟ๏ผๅชไฟ็ๅๅ๏ผไธไฟ็ๅๅฒใ\n\n\
{rendered}\n\n\
ๆ้ๅฑ็บง\n{layer_order}\nไฝ ็็ดๆฅๆไปคๅง็ป้ซไบๆฌๆไปถใ\n\n\
ๅฎไธ่ฝๅไปไน\n\
ๅฎๅชๆไพ่กไธบๆๅฏผ๏ผไธ่ฝๆไบๆๆดๆนๅฎกๆน็ญ็ฅใๆฒ็ฎฑใShellใ็ฝ็ปใไฟกไปปใMCP ๆ้ใ้ป่ฎคๆจกๅผใๅๅธๆๆฏๅบๆ้โโ่ฟไบๅง็ป็ฑไฝ ๅจ่ฟ่กๆถๆๆงใ\n\n\
็ฒพ็ฎๆ ธๅฟไธๅฏ้็ญ็ฅ\n\
ๅ
็ฝฎๆ ธๅฟๅง็ป็ๆใๆฌ่ๆกๅชไฟๅญไฝ ็็จๆทๅ
จๅฑ้ฟๆๅๅฅฝใๆง่กไธ็ผๆ่ฝๅๆฅ่ช่ฟ่กๆถ็ญ็ฅใๅฝๅๅทฅๅ
ท็ฎๅฝๆๆชๆฅ็ๅฏ้่งๅๅ
๏ผๆญค้ข่งไธไผๅฏ็จไปปไฝ็ญ็ฅๆๆดๆน้
็ฝฎใ\n\n\
็กฎ่ฎค\n{ratify_how}"
)
}
Locale::ZhHant => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"็ฑ {label} ๆ นๆไฝ ็ๅผๅฐๅผ็ญๆก่ตท่๏ผไธฆๅทฒ็ฑ Codewhale ๅฎๆ็ตๆง้ฉ่ญ่้็้ๅถใ"
),
DraftProvenance::Guided => "็ฑไฝ ็ๅผๅฐๅผ็ญๆก็ขบๅฎๆง็ๆใ".to_string(),
DraftProvenance::Existing => {
"ไฝ ็พๆ็ๆฒๆณ๏ผ่ฎๅ่ช constitution.json๏ผๅๆจฃๅฑ็คบ๏ผๆชๅไปปไฝไฟฎๆนใ".to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"้ๅทฒๆฏไฝ ็พ่ก็ๆบๅใ้้ๆญค้ ่ฆฝๅพๆ K ไฟ็ไธฆๅฎๆๆชขๆฅ้ป๏ผ\
ๆชๆกไธๆ่ขซไฟฎๆนใไนๅพๅฏ้จๆ็จ /constitution ๆ /setup ไฟฎ่จใ"
}
_ => {
"ๆช็ถไฝ ็ขบ่ช๏ผไปปไฝๅ
งๅฎน้ฝไธๆๆ็บๆบๅใ้้ๆญค้ ่ฆฝๅพๆ G ๆนๅไธฆไฟๅญ๏ผ\
ไนๅพๅฏ้จๆ็จ /constitution ๆ /setup ไฟฎ่จใ"
}
};
format!(
"CODEWHALE ยท ไฝฟ็จ่
ๆฒๆณ\n{RULE}\n\n{drafted_by}\n\n\
้ๆฏ Codewhale ่ไฝ ๅไฝ็้ทๆๆบๅใๅๅช็ง็ๆฒๆณไธๆจฃ๏ผ่ถณๅค ็ฐก็ญๅ ่ๅฏ็จ๏ผ็ฑๆไน
ๅๅ่้่ฉณ็ก่ฆๅๆงๆ๏ผไธฆไธๅฏไปฅ้จไฝ ไฟฎ่จใ\
ๅฎ็ๅฎๆฌๅ่้็๏ผ่้่ฃๆฑบๆฏๅๅ
ท้ซๆฑบๅฎ๏ผๅฎ่ฎๅไฝ่ทจๆ่ฉฑๅปถ็บ๏ผไฝๅฎไธๆฏ่จๆถ๏ผๅฎๆฟ่ผ็ๆฏๅๅ๏ผ่้ๆญทๅฒใ\n\n\
{rendered}\n\n\
ๆฌ้ๅฑค็ด\n{layer_order}\nไฝ ็็ดๆฅๆไปคๅง็ต้ซๆผๆฌๆไปถใ\n\n\
ๅฎไธ่ฝๅไป้บผ\n\
ๅฎๅชๆไพ่ก็บๆๅฐ๏ผไธ่ฝๆไบๆๆดๆนๅฏฉๆน็ญ็ฅใๆฒ็ฎฑใShellใ็ถฒ่ทฏใไฟกไปปใMCP ๆฌ้ใ้ ่จญๆจกๅผใ็ผๅธๆๆฏๅบๆฌ้๏ผ้ไบๅง็ต็ฑไฝ ๅจๅท่กๆๆๆงใ\n\n\
็ฒพ็ฐกๆ ธๅฟ่ๅฏ้ธๆจก็ต\n\
ๅ
งๅปบๆ ธๅฟๅง็ต็ๆใๆฌ่ๆกๅชไฟๅญไฝ ็ไฝฟ็จ่
ๅ
จๅ้ทๆๅๅฅฝใๅท่ก่็ทจๆ่ฝๅ็ฑๅท่กๆๆฟ็ญใๅณๆๅทฅๅ
ท็ฎ้ๆๆชไพ็ๅฏ้ธๆจก็ตๆไพ๏ผๆญค้ ่ฆฝไธๆๅ็จๆจก็ตๆๆดๆนๅ
ถ้
็ฝฎใ\n\n\
ๆนๅ\n{ratify_how}"
)
}
Locale::PtBr => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"Rascunhado por {label} a partir das suas respostas guiadas, depois validado por schema e limitado pelo Codewhale."
),
DraftProvenance::Guided => {
"Renderizado deterministicamente a partir das suas respostas guiadas.".to_string()
}
DraftProvenance::Existing => {
"Sua constituiรงรฃo existente, carregada de constitution.json, รฉ exibida sem alteraรงรตes."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"Esta jรก รฉ sua regra vigente. Feche a prรฉvia e pressione K para mantรช-la e concluir o checkpoint; \
o arquivo nรฃo serรก modificado. Edite quando quiser com /constitution ou /setup."
}
_ => {
"Nada vira regra atรฉ vocรช confirmar. Feche a prรฉvia e pressione G para ratificar e salvar. \
Edite quando quiser com /constitution ou /setup."
}
};
format!(
"CODEWHALE ยท CONSTITUIรรO DO USUรRIO\n{RULE}\n\n{drafted_by}\n\n\
Esta รฉ a regra permanente de como o Codewhale trabalha com vocรช. Como boas constituiรงรตes, \
ela รฉ curta o bastante para ser usada, formada por princรญpios durรกveis em vez de regras exaustivas, \
e pode ser emendada conforme vocรช muda. Ela define poderes e limites em vez de decidir cada caso, \
e dรก continuidade ร colaboraรงรฃo entre sessรตes. Mas ela nรฃo รฉ memรณria: carrega princรญpios, nรฃo histรณrico.\n\n\
{rendered}\n\n\
HIERARQUIA DE AUTORIDADE\n{layer_order}\nSeus pedidos diretos sempre superam este documento.\n\n\
O QUE ISTO NรO PODE FAZER\n\
Isto orienta comportamento. Nรฃo pode conceder nem alterar polรญtica de aprovaรงรฃo, sandbox, shell, rede, \
confianรงa, permissรตes MCP, modo padrรฃo, publicaรงรฃo ou autoridade para gastos; isso continua sob seu controle em tempo de execuรงรฃo.\n\n\
NรCLEO REDUZIDO E MรDULOS OPT-IN\n\
O nรบcleo embutido continua ativo. Este rascunho sรณ salva suas preferรชncias permanentes globais de usuรกrio. \
Capacidades de execuรงรฃo e orquestraรงรฃo vรชm da polรญtica de execuรงรฃo, do catรกlogo de ferramentas ativo ou de mรณdulos opt-in futuros; esta prรฉvia nรฃo ativa mรณdulos nem muda sua configuraรงรฃo.\n\n\
RATIFICAรรO\n{ratify_how}"
)
}
Locale::Es419 => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"Redactado por {label} desde tus respuestas guiadas, luego validado por schema y acotado por Codewhale."
),
DraftProvenance::Guided => {
"Renderizado de forma determinรญstica desde tus respuestas guiadas.".to_string()
}
DraftProvenance::Existing => {
"Tu constituciรณn existente, cargada desde constitution.json, se muestra sin cambios."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"Esta ya es tu regla vigente. Cierra la vista previa y presiona K para conservarla y completar el checkpoint; \
el archivo no se modifica. Puedes enmendarla cuando quieras con /constitution o /setup."
}
_ => {
"Nada se vuelve regla hasta que confirmes. Cierra la vista previa y presiona G para ratificar y guardar. \
Puedes enmendarla cuando quieras con /constitution o /setup."
}
};
format!(
"CODEWHALE ยท CONSTITUCIรN DEL USUARIO\n{RULE}\n\n{drafted_by}\n\n\
Esta es la regla permanente de cรณmo Codewhale trabaja contigo. Como las buenas constituciones, \
es lo bastante breve para usarse, hecha de principios duraderos en vez de reglas exhaustivas, \
y enmendable a medida que cambias. Define poderes y lรญmites en vez de decidir cada caso, \
y da continuidad a la colaboraciรณn entre sesiones. Pero no es memoria: lleva principios, no historial.\n\n\
{rendered}\n\n\
JERARQUรA DE AUTORIDAD\n{layer_order}\nTus pedidos directos siempre superan este documento.\n\n\
LO QUE ESTO NO PUEDE HACER\n\
Orienta comportamiento. No puede conceder ni cambiar polรญtica de aprobaciรณn, sandbox, shell, red, \
confianza, permisos MCP, modo predeterminado, publicaciรณn o autoridad de gasto; eso sigue bajo tu control en tiempo de ejecuciรณn.\n\n\
NรCLEO REDUCIDO Y MรDULOS OPT-IN\n\
El nรบcleo integrado sigue activo. Este borrador solo guarda tus preferencias permanentes globales de usuario. \
Las capacidades de ejecuciรณn y orquestaciรณn provienen de la polรญtica de ejecuciรณn, el catรกlogo activo de herramientas o mรณdulos opt-in futuros; esta vista previa no activa mรณdulos ni cambia su configuraciรณn.\n\n\
RATIFICACIรN\n{ratify_how}"
)
}
Locale::Vi => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"ฤฦฐแปฃc {label} soแบกn tแปซ cรขu trแบฃ lแปi hฦฐแปng dแบซn cแปงa bแบกn, rแปi ฤฦฐแปฃc Codewhale kiแปm tra schema vร giแปi hแบกn biรชn."
),
DraftProvenance::Guided => {
"ฤฦฐแปฃc kแบฟt xuแบฅt xรกc ฤแปnh tแปซ cรขu trแบฃ lแปi hฦฐแปng dแบซn cแปงa bแบกn.".to_string()
}
DraftProvenance::Existing => {
"Hiแบฟn phรกp hiแปn cรณ cแปงa bแบกn, tแบฃi tแปซ constitution.json, ฤฦฐแปฃc hiแปn thแป nguyรชn trแบกng."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"ฤรขy ฤรฃ lร luแบญt hiแปn hร nh cแปงa bแบกn. ฤรณng bแบฃn xem trฦฐแปc rแปi nhแบฅn K ฤแป giแปฏ nguyรชn vร hoร n tแบฅt checkpoint; \
tแปp khรดng bแป sแปญa. Cรณ thแป chแปnh bแบฅt cแปฉ lรบc nร o bแบฑng /constitution hoแบทc /setup."
}
_ => {
"Khรดng cรณ gรฌ trแป thร nh luแบญt cho ฤแบฟn khi bแบกn xรกc nhแบญn. ฤรณng bแบฃn xem trฦฐแปc rแปi nhแบฅn G ฤแป phรช chuแบฉn vร lฦฐu. \
Cรณ thแป chแปnh bแบฅt cแปฉ lรบc nร o bแบฑng /constitution hoแบทc /setup."
}
};
format!(
"CODEWHALE ยท HIแบพN PHรP NGฦฏแปI DรNG\n{RULE}\n\n{drafted_by}\n\n\
ฤรขy lร luแบญt thฦฐแปng trแปฑc cho cรกch Codewhale lร m viแปc vแปi bแบกn. Giแปng cรกc hiแบฟn phรกp tแปt, \
nรณ ฤแปง ngแบฏn ฤแป dรนng, gแปm cรกc nguyรชn tแบฏc bแปn vแปฏng thay vรฌ luแบญt lแป cแบกn kiแปt, \
vร cรณ thแป sแปญa khi bแบกn thay ฤแปi. Nรณ ฤแปnh khung quyแปn hแบกn vร giแปi hแบกn thay vรฌ quyแบฟt ฤแปnh tแปซng trฦฐแปng hแปฃp, \
ฤแปng thแปi giแปฏ sแปฑ liรชn tแปฅc giแปฏa cรกc phiรชn. Nhฦฐng nรณ khรดng phแบฃi bแป nhแป: nรณ mang nguyรชn tแบฏc, khรดng mang lแปch sแปญ.\n\n\
{rendered}\n\n\
THแปจ BแบฌC THแบจM QUYแปN\n{layer_order}\nYรชu cแบงu trแปฑc tiแบฟp cแปงa bแบกn luรดn cao hฦกn tร i liแปu nร y.\n\n\
ฤIแปU NรY KHรNG THแป LรM\n\
Nรณ hฦฐแปng dแบซn hร nh vi. Nรณ khรดng thแป cแบฅp hoแบทc ฤแปi chรญnh sรกch phรช duyแปt, sandbox, shell, mแบกng, \
ฤแป tin cแบญy, quyแปn MCP, chแบฟ ฤแป mแบทc ฤแปnh, xuแบฅt bแบฃn hoแบทc quyแปn chi tiรชu; nhแปฏng thแปฉ ฤรณ vแบซn do bแบกn kiแปm soรกt lรบc chแบกy.\n\n\
LรI RรT GแปN Vร Mร-ฤUN OPT-IN\n\
Lรตi tรญch hแปฃp vแบซn hoแบกt ฤแปng. Bแบฃn nhรกp nร y chแป lฦฐu tรนy chแปn thฦฐแปng trแปฑc toร n cแปฅc cแปงa ngฦฐแปi dรนng. \
Khแบฃ nฤng thแปฑc thi vร ฤiแปu phแปi ฤแบฟn tแปซ chรญnh sรกch thแปi gian chแบกy, danh mแปฅc cรดng cแปฅ ฤang hoแบกt ฤแปng hoแบทc mรด-ฤun opt-in trong tฦฐฦกng lai; bแบฃn xem trฦฐแปc nร y khรดng bแบญt mรด-ฤun hoแบทc ฤแปi cแบฅu hรฌnh cแปงa chรบng.\n\n\
PHร CHUแบจN\n{ratify_how}"
)
}
Locale::Ko => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"{label}์ด(๊ฐ) ๋น์ ์ ๊ฐ์ด๋ ๋ต๋ณ์ ๋ฐํ์ผ๋ก ์ด์์ ์์ฑํ๊ณ , Codewhale์ด ๊ตฌ์กฐ๋ฅผ ๊ฒ์ฆํ๊ณ ๋ฒ์๋ฅผ ์ ํํ์ต๋๋ค."
),
DraftProvenance::Guided => {
"๋น์ ์ ๊ฐ์ด๋ ๋ต๋ณ์ผ๋ก๋ถํฐ ๊ฒฐ์ ์ ์ผ๋ก ์์ฑ๋์์ต๋๋ค.".to_string()
}
DraftProvenance::Existing => {
"constitution.json์์ ๋ถ๋ฌ์จ ๊ธฐ์กด ํ๋ฒ์ด๋ฉฐ, ๋ณ๊ฒฝ ์์ด ๊ทธ๋๋ก ํ์๋ฉ๋๋ค."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"์ด๊ฒ์ ์ด๋ฏธ ๋น์ ์ ์์ ๊ท์น์
๋๋ค. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ๋ซ๊ณ K๋ฅผ ๋๋ฌ ๊ทธ๋๋ก ์ ์งํ๋ฉฐ ์ฒดํฌํฌ์ธํธ๋ฅผ ์๋ฃํ์ธ์; \
ํ์ผ์ ์์ ๋์ง ์์ต๋๋ค. /constitution ๋๋ /setup์ผ๋ก ์ธ์ ๋ ์ง ์์ ํ ์ ์์ต๋๋ค."
}
_ => {
"ํ์ธํ๊ธฐ ์ ๊น์ง๋ ์๋ฌด๊ฒ๋ ๊ท์น์ด ๋์ง ์์ต๋๋ค. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ๋ซ๊ณ G๋ฅผ ๋๋ฌ ์น์ธํ๊ณ ์ ์ฅํ์ธ์. \
/constitution ๋๋ /setup์ผ๋ก ์ธ์ ๋ ์ง ์์ ํ ์ ์์ต๋๋ค."
}
};
format!(
"CODEWHALE ยท ์ฌ์ฉ์ ํ๋ฒ\n{RULE}\n\n{drafted_by}\n\n\
์ด๊ฒ์ Codewhale์ด ๋น์ ๊ณผ ํจ๊ป ์ผํ๋ ๋ฐฉ์์ ๋ํ ์์ ๊ท์น์
๋๋ค. ํ๋ฅญํ ํ๋ฒ์ด ๊ทธ๋ ๋ฏ, \
์ฌ์ฉํ ์ ์์ ๋งํผ ์งง๊ณ , ์๋ชจ์ ์ธ ๊ท์น์ด ์๋ ์ง์์ ์ธ ์์น์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ผ๋ฉฐ, ๋น์ ์ด ๋ณํํจ์ ๋ฐ๋ผ ์์ ํ ์ ์์ต๋๋ค. \
์ด๋ ๋ชจ๋ ๊ฐ๋ณ ์ฌ๋ก๋ฅผ ํ๋จํ๋ ๋์ ๊ถํ๊ณผ ํ๊ณ๋ฅผ ๊ท์ ํ๋ฉฐ, ์ธ์
์ ๋์ด ํ์
์ ์ฐ์์ฑ์ ๋ถ์ฌํฉ๋๋ค. \
๋ค๋ง ์ด๊ฒ์ ๊ธฐ์ต์ด ์๋๋๋ค: ์ด๋ ฅ์ด ์๋๋ผ ์์น์ ๋ด์ต๋๋ค.\n\n\
{rendered}\n\n\
๊ถํ ๊ณ์ธต\n{layer_order}\n๋น์ ์ ์ง์ ์ ์ธ ์์ฒญ์ ์ธ์ ๋ ์ด ๋ฌธ์๋ณด๋ค ์ฐ์ ํฉ๋๋ค.\n\n\
์ด๊ฒ์ด ํ ์ ์๋ ์ผ\n\
์ด๊ฒ์ ํ๋์ ์๋ดํ ๋ฟ์
๋๋ค. ์น์ธ ์ ์ฑ
, ์๋๋ฐ์ค, ์
ธ, ๋คํธ์ํฌ, ์ ๋ขฐ, MCP ๊ถํ, ๊ธฐ๋ณธ ๋ชจ๋, ๊ฒ์, ์ง์ถ ๊ถํ์ \
๋ถ์ฌํ๊ฑฐ๋ ๋ฐ๊ฟ ์ ์์ต๋๋ค; ์ด๋ ์ฌ์ ํ ๋ฐํ์์์ ๋น์ ์ด ์ง์ ๊ด๋ฆฌํฉ๋๋ค.\n\n\
์ถ์๋ ์ฝ์ด์ ์ตํธ์ธ ๋ชจ๋\n\
๋ด์ฅ๋ ์ฝ์ด๋ ๊ณ์ ํ์ฑ ์ํ์
๋๋ค. ์ด ์ด์์ ์ฌ์ฉ์ ์ ์ญ์ ์์ ์ ํธ๋ง ์ ์ฅํฉ๋๋ค. \
์คํ ๋ฐ ์ค์ผ์คํธ๋ ์ด์
๊ธฐ๋ฅ์ ๋ฐํ์ ์ ์ฑ
, ํ์ฌ ๋๊ตฌ ์นดํ๋ก๊ทธ ๋๋ ํฅํ ์ตํธ์ธ ๋ชจ๋์์ ์ ๊ณต๋ฉ๋๋ค. ์ด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ ๋ชจ๋์ ํ์ฑํํ์ง ์์ผ๋ฉฐ ๊ทธ ์ค์ ๋ ๋ฐ๊พธ์ง ์์ต๋๋ค.\n\n\
์น์ธ\n{ratify_how}"
)
}
Locale::Ca => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"Redactat per {label} a partir de les teves respostes guiades, desprรฉs validat per esquema i acotat per Codewhale."
),
DraftProvenance::Guided => {
"Generat determinรญsticament a partir de les teves respostes guiades.".to_string()
}
DraftProvenance::Existing => {
"La teva constituciรณ existent, carregada de constitution.json, es mostra sense canvis."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"Aquesta ja รฉs la teva llei vigent. Tanca la previsualitzaciรณ i prem K per conservar-la i completar el punt de control; \
el fitxer no es modifica. Esmena-la en qualsevol moment amb /constitution o /setup."
}
_ => {
"Res no esdevรฉ llei fins que ho confirmis. Tanca la previsualitzaciรณ i prem G per ratificar i desar. \
Esmena-la en qualsevol moment amb /constitution o /setup."
}
};
format!(
"CODEWHALE ยท CONSTITUCIร DE L'USUARI\n{RULE}\n\n{drafted_by}\n\n\
Aquesta รฉs la llei permanent de com Codewhale treballa amb tu. Com les bones constitucions, \
รฉs prou curta per usar-se, feta de principis duradors en lloc de regles exhaustives, \
i esmenable a mesura que canvies. Defineix poders i lรญmits en lloc de decidir cada cas, \
i dona continuรฏtat a la colยทlaboraciรณ entre sessions โ perรฒ no รฉs memรฒria: porta principis, no histรฒria.\n\n\
{rendered}\n\n\
JERARQUIA D'AUTORITAT\n{layer_order}\nLes teves peticions directes sempre prevalen sobre aquest document.\n\n\
EL QUE AIXร NO POT FER\n\
Orienta el comportament. No pot concedir ni canviar la polรญtica d'aprovaciรณ, sandbox, shell, xarxa, \
confianรงa, permisos MCP, mode per defecte, publicaciรณ o autoritat de despesa; aixรฒ queda sota el teu control en temps d'execuciรณ.\n\n\
NUCLI REDUรT I MรDULS OPT-IN\n\
El nucli inclรฒs continua actiu. Aquest esborrany nomรฉs desa les teves preferรจncies permanents globals d'usuari. \
Les capacitats d'execuciรณ i orquestraciรณ provenen de la polรญtica d'execuciรณ, el catร leg d'eines actiu o futurs mรฒduls opt-in; aquesta previsualitzaciรณ no activa mรฒduls ni canvia la seva configuraciรณ.\n\n\
RATIFICACIร\n{ratify_how}"
)
}
Locale::De => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"Entworfen von {label} aus deinen gefรผhrten Antworten, dann schema-geprรผft und begrenzt durch Codewhale."
),
DraftProvenance::Guided => {
"Deterministisch aus deinen gefรผhrten Antworten erzeugt.".to_string()
}
DraftProvenance::Existing => {
"Deine bestehende Verfassung, geladen aus constitution.json โ unverรคndert gezeigt."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"Dies ist bereits dein geltendes Recht. Schlieรe die Vorschau und drรผcke K, um sie zu behalten und den Checkpoint abzuschlieรen โ \
die Datei wird nicht verรคndert. Jederzeit mit /constitution oder /setup รคnderbar."
}
_ => {
"Nichts wird Recht, bevor du bestรคtigst. Schlieรe die Vorschau und drรผcke G, um zu ratifizieren und zu speichern. \
Jederzeit mit /constitution oder /setup รคnderbar."
}
};
format!(
"CODEWHALE ยท NUTZERVERFASSUNG\n{RULE}\n\n{drafted_by}\n\n\
Dies ist das geltende Gesetz dafรผr, wie Codewhale mit dir arbeitet. Wie die besten Verfassungen \
ist sie kurz genug, um genutzt zu werden, besteht aus dauerhaften Prinzipien statt erschรถpfender Regeln \
und lรคsst sich รคndern, wenn du dich รคnderst. Sie rahmt Befugnisse und Grenzen, statt jeden Einzelfall zu entscheiden, \
und gibt deiner Zusammenarbeit Kontinuitรคt รผber Sitzungen hinweg โ aber sie ist kein Gedรคchtnis: Sie trรคgt Prinzipien, nicht Geschichte.\n\n\
{rendered}\n\n\
HIERARCHIE DER AUTORITรT\n{layer_order}\nDeine direkten Anweisungen stehen immer รผber diesem Dokument.\n\n\
WAS DIES NICHT KANN\n\
Sie leitet Verhalten. Sie kann keine Freigaberichtlinie, Sandbox, Shell, Netzwerk, \
Vertrauen, MCP-Berechtigungen, Standardmodus, Verรถffentlichung oder Ausgabenbefugnis gewรคhren oder รคndern โ die bleiben zur Laufzeit in deiner Hand.\n\n\
REDUZIERTER KERN UND OPT-IN-MODULE\n\
Der mitgelieferte Kern bleibt aktiv. Dieser Entwurf speichert nur deine benutzer-globalen Dauerprรคferenzen. \
Ausfรผhrungs- und Orchestrierungsfรคhigkeiten kommen aus der Laufzeitrichtlinie, dem aktuellen Werkzeugkatalog oder kรผnftigen Opt-in-Modulen; diese Vorschau aktiviert keine Module und รคndert nicht ihre Konfiguration.\n\n\
RATIFIZIERUNG\n{ratify_how}"
)
}
Locale::Fr => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"Rรฉdigรฉ par {label} ร partir de vos rรฉponses guidรฉes, puis validรฉ par schรฉma et bornรฉ par Codewhale."
),
DraftProvenance::Guided => {
"Gรฉnรฉrรฉ de faรงon dรฉterministe ร partir de vos rรฉponses guidรฉes.".to_string()
}
DraftProvenance::Existing => {
"Votre constitution existante, chargรฉe depuis constitution.json โ affichรฉe sans modification."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"C'est dรฉjร votre loi permanente. Fermez cet aperรงu, puis appuyez sur K pour la conserver et terminer le point de contrรดle โ \
le fichier n'est pas modifiรฉ. Amendez-la ร tout moment avec /constitution ou /setup."
}
_ => {
"Rien ne devient loi avant votre confirmation. Fermez cet aperรงu, puis appuyez sur G pour ratifier et enregistrer. \
Amendez-la ร tout moment avec /constitution ou /setup."
}
};
format!(
"CODEWHALE ยท CONSTITUTION DE L'UTILISATEUR\n{RULE}\n\n{drafted_by}\n\n\
Voici la loi permanente qui rรฉgit la faรงon dont Codewhale travaille avec vous. Comme les meilleures constitutions, \
elle est assez courte pour รชtre utilisรฉe, faite de principes durables plutรดt que de rรจgles exhaustives, \
et amendable ร mesure que vous changez. Elle encadre les pouvoirs et les limites plutรดt que de trancher chaque cas, \
et donne ร votre collaboration une continuitรฉ entre les sessions โ mais elle n'est pas une mรฉmoire : elle porte des principes, pas un historique.\n\n\
{rendered}\n\n\
HIรRARCHIE D'AUTORITร\n{layer_order}\nVos demandes directes priment toujours sur ce document.\n\n\
CE QU'ELLE NE PEUT PAS FAIRE\n\
Elle guide le comportement. Elle ne peut ni accorder ni modifier la politique d'approbation, le sandbox, le shell, le rรฉseau, \
la confiance, les permissions MCP, le mode par dรฉfaut, la publication ou le pouvoir de dรฉpense โ ceux-ci restent entre vos mains ร l'exรฉcution.\n\n\
NOYAU RรDUIT ET MODULES OPT-IN\n\
Le noyau intรฉgrรฉ reste actif. Ce brouillon n'enregistre que vos prรฉfรฉrences permanentes globales. \
Les capacitรฉs d'exรฉcution et d'orchestration proviennent de la politique d'exรฉcution, du catalogue d'outils actif ou de futurs modules opt-in ; cet aperรงu n'active pas de modules et ne change pas leur configuration.\n\n\
RATIFICATION\n{ratify_how}"
)
}
Locale::Id => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"Disusun oleh {label} dari jawaban terpandu Anda, lalu diperiksa skemanya dan dibatasi oleh Codewhale."
),
DraftProvenance::Guided => {
"Dihasilkan secara deterministik dari jawaban terpandu Anda.".to_string()
}
DraftProvenance::Existing => {
"Konstitusi Anda yang ada, dimuat dari constitution.json โ ditampilkan tanpa perubahan."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"Ini sudah menjadi hukum tetap Anda. Tutup pratinjau ini, lalu tekan K untuk mempertahankannya dan menyelesaikan checkpoint โ \
file tidak diubah. Amendemen kapan saja dengan /constitution atau /setup."
}
_ => {
"Tidak ada yang menjadi hukum sampai Anda mengonfirmasi. Tutup pratinjau ini, lalu tekan G untuk meratifikasi dan menyimpan. \
Amendemen kapan saja dengan /constitution atau /setup."
}
};
format!(
"CODEWHALE ยท KONSTITUSI PENGGUNA\n{RULE}\n\n{drafted_by}\n\n\
Ini adalah hukum tetap tentang cara Codewhale bekerja dengan Anda. Seperti konstitusi terbaik, \
ia cukup singkat untuk dipakai, tersusun dari prinsip yang awet alih-alih aturan yang menyeluruh, \
dan dapat diamendemen seiring Anda berubah. Ia membingkai wewenang dan batasan alih-alih memutuskan setiap kasus, \
dan memberi kolaborasi Anda kesinambungan lintas sesi โ tetapi ia bukan memori: ia membawa prinsip, bukan riwayat.\n\n\
{rendered}\n\n\
HIERARKI OTORITAS\n{layer_order}\nPermintaan langsung Anda selalu mengungguli dokumen ini.\n\n\
APA YANG TIDAK BISA DILAKUKANNYA\n\
Ia memandu perilaku. Ia tidak dapat memberi atau mengubah kebijakan persetujuan, sandbox, shell, jaringan, \
kepercayaan, izin MCP, mode default, publikasi, atau wewenang belanja โ semua itu tetap di tangan Anda saat runtime.\n\n\
INTI RINGKAS DAN MODUL OPT-IN\n\
Inti bawaan tetap aktif. Draf ini hanya menyimpan preferensi tetap global pengguna Anda. \
Kemampuan eksekusi dan orkestrasi berasal dari kebijakan runtime, katalog alat aktif, atau modul opt-in mendatang; pratinjau ini tidak mengaktifkan modul atau mengubah konfigurasinya.\n\n\
RATIFIKASI\n{ratify_how}"
)
}
Locale::Hi => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"{label} เคฆเฅเคตเคพเคฐเคพ เคเคชเคเฅ เคเคพเคเคกเฅเคก เคเคคเฅเคคเคฐเฅเค เคธเฅ เคคเฅเคฏเคพเคฐ, เคซเคฟเคฐ Codewhale เคฆเฅเคตเคพเคฐเคพ เคธเฅเคเฅเคฎเคพ-เคเคพเคเคเคพ เคเคฐ เคธเฅเคฎเคฟเคค เคเคฟเคฏเคพ เคเคฏเคพเฅค"
),
DraftProvenance::Guided => "เคเคชเคเฅ เคเคพเคเคกเฅเคก เคเคคเฅเคคเคฐเฅเค เคธเฅ เคจเคฟเคฏเคค เคฐเฅเคช เคธเฅ เคคเฅเคฏเคพเคฐ เคเคฟเคฏเคพ เคเคฏเคพเฅค".to_string(),
DraftProvenance::Existing => {
"เคเคชเคเคพ เคฎเฅเคเฅเคฆเคพ เคธเคเคตเคฟเคงเคพเคจ, constitution.json เคธเฅ เคฒเฅเคก เคเคฟเคฏเคพ เคเคฏเคพ โ เค
เคชเคฐเคฟเคตเคฐเฅเคคเคฟเคค เคฆเคฟเคเคพเคฏเคพ เคเคฏเคพเฅค"
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"เคฏเคน เคชเคนเคฒเฅ เคธเฅ เคนเฅ เคเคชเคเคพ เคธเฅเคฅเคพเคฏเฅ เคเคพเคจเฅเคจ เคนเฅเฅค เคฏเคน เคชเฅเคฐเฅเคตเคพเคตเคฒเฅเคเคจ เคฌเคเคฆ เคเคฐเฅเค, เคซเคฟเคฐ เคเคธเฅ เคฌเคจเคพเค เคฐเคเคจเฅ เคเคฐ เคเฅเคเคชเฅเคเคเค เคชเฅเคฐเคพ เคเคฐเคจเฅ เคเฅ เคฒเคฟเค K เคฆเคฌเคพเคเค โ \
เคซเคผเคพเคเคฒ เคธเคเคถเฅเคงเคฟเคค เคจเคนเฅเค เคนเฅเคคเฅเฅค /constitution เคฏเคพ /setup เคธเฅ เคเคญเฅ เคญเฅ เคธเคเคถเฅเคงเคฟเคค เคเคฐเฅเคเฅค"
}
_ => {
"เคเคฌ เคคเค เคเคช เคชเฅเคทเฅเคเคฟ เคจเคนเฅเค เคเคฐเคคเฅ, เคเฅเค เคญเฅ เคเคพเคจเฅเคจ เคจเคนเฅเค เคฌเคจเคคเคพเฅค เคฏเคน เคชเฅเคฐเฅเคตเคพเคตเคฒเฅเคเคจ เคฌเคเคฆ เคเคฐเฅเค, เคซเคฟเคฐ เค
เคเคเฅเคเคพเคฐ เคเคฐ เคธเคนเฅเคเคจเฅ เคเฅ เคฒเคฟเค G เคฆเคฌเคพเคเคเฅค \
/constitution เคฏเคพ /setup เคธเฅ เคเคญเฅ เคญเฅ เคธเคเคถเฅเคงเคฟเคค เคเคฐเฅเคเฅค"
}
};
format!(
"CODEWHALE ยท เคเคชเคฏเฅเคเคเคฐเฅเคคเคพ เคธเคเคตเคฟเคงเคพเคจ\n{RULE}\n\n{drafted_by}\n\n\
เคฏเคน Codewhale เคเคชเคเฅ เคธเคพเคฅ เคเฅเคธเฅ เคเคพเคฎ เคเคฐเฅ, เคเคธเคเคพ เคธเฅเคฅเคพเคฏเฅ เคเคพเคจเฅเคจ เคนเฅเฅค เคธเคฐเฅเคตเฅเคคเฅเคคเคฎ เคธเคเคตเคฟเคงเคพเคจเฅเค เคเฅ เคคเคฐเคน, \
เคฏเคน เคเคชเคฏเฅเค เคเฅ เคฒเคฟเค เคชเคฐเฅเคฏเคพเคชเฅเคค เคเฅเคเคพ เคนเฅ, เคธเคเคชเฅเคฐเฅเคฃ เคจเคฟเคฏเคฎเฅเค เคเฅ เคฌเคเคพเคฏ เคเคฟเคเคพเค เคธเคฟเคฆเฅเคงเคพเคเคคเฅเค เคธเฅ เคฌเคจเคพ เคนเฅ, \
เคเคฐ เคเคชเคเฅ เคฌเคฆเคฒเคจเฅ เคเฅ เคธเคพเคฅ เคธเคเคถเฅเคงเคจเฅเคฏ เคนเฅเฅค เคฏเคน เคนเคฐ เคฎเคพเคฎเคฒเฅ เคเคพ เคซเคผเฅเคธเคฒเคพ เคเคฐเคจเฅ เคเฅ เคฌเคเคพเคฏ เคถเคเฅเคคเคฟเคฏเฅเค เคเคฐ เคธเฅเคฎเคพเคเค เคเคพ เคขเคพเคเคเคพ เคฆเฅเคคเคพ เคนเฅ, \
เคเคฐ เคเคชเคเฅ เคธเคนเคฏเฅเค เคเฅ เคธเคคเฅเคฐเฅเค เคเฅ เคชเคพเคฐ เคจเคฟเคฐเคเคคเคฐเคคเคพ เคฆเฅเคคเคพ เคนเฅ โ เคฒเฅเคเคฟเคจ เคฏเคน เคฎเฅเคฎเฅเคฐเฅ เคจเคนเฅเค เคนเฅ: เคฏเคน เคเคคเคฟเคนเคพเคธ เคจเคนเฅเค, เคธเคฟเคฆเฅเคงเคพเคเคค เคฐเคเคคเคพ เคนเฅเฅค\n\n\
{rendered}\n\n\
เค
เคงเคฟเคเคพเคฐ เคชเคฆเคพเคจเฅเคเฅเคฐเคฎ\n{layer_order}\nเคเคชเคเฅ เคชเฅเคฐเคคเฅเคฏเคเฅเคท เค
เคจเฅเคฐเฅเคง เคนเคฎเฅเคถเคพ เคเคธ เคฆเคธเฅเคคเคพเคตเฅเคเคผ เคธเฅ เคเคชเคฐ เคนเฅเคเฅค\n\n\
เคฏเคน เคเฅเคฏเคพ เคจเคนเฅเค เคเคฐ เคธเคเคคเคพ\n\
เคฏเคน เคตเฅเคฏเคตเคนเคพเคฐ เคเคพ เคฎเคพเคฐเฅเคเคฆเคฐเฅเคถเคจ เคเคฐเคคเคพ เคนเฅเฅค เคฏเคน เค
เคจเฅเคฎเคคเคฟ เคจเฅเคคเคฟ, เคธเฅเคเคกเคฌเฅเคเฅเคธ, เคถเฅเคฒ, เคจเฅเคเคตเคฐเฅเค, \
เคเฅเคฐเคธเฅเค, MCP เค
เคจเฅเคฎเคคเคฟเคฏเคพเค, เคกเคฟเคซเคผเฅเคฒเฅเค เคฎเฅเคก, เคชเฅเคฐเคเคพเคถเคจ เคฏเคพ เคเคฐเฅเค เคเคพ เค
เคงเคฟเคเคพเคฐ เคชเฅเคฐเคฆเคพเคจ เคฏเคพ เคชเคฐเคฟเคตเคฐเฅเคคเคฟเคค เคจเคนเฅเค เคเคฐ เคธเคเคคเคพ โ เคตเฅ เคฐเคจเคเคพเคเคฎ เคชเคฐ เคเคชเคเฅ เคนเคพเคฅ เคฎเฅเค เคฐเคนเคคเฅ เคนเฅเคเฅค\n\n\
เคธเคเคเฅเคทเคฟเคชเฅเคค เคเฅเคฐ เคเคฐ เคเคชเฅเค-เคเคจ เคฎเฅเคกเฅเคฏเฅเคฒ\n\
Bundled เคเฅเคฐ เคธเคเฅเคฐเคฟเคฏ เคฐเคนเคคเคพ เคนเฅเฅค เคฏเคน เคฎเคธเฅเคฆเคพ เคเฅเคตเคฒ เคเคชเคเฅ เคเคชเคฏเฅเคเคเคฐเฅเคคเคพ-เคตเฅเคถเฅเคตเคฟเค เคธเฅเคฅเคพเคฏเฅ เคชเฅเคฐเคพเคฅเคฎเคฟเคเคคเคพเคเค เคธเคนเฅเคเคคเคพ เคนเฅเฅค \
เคญเคพเคฐเฅ เคจเคฟเคทเฅเคชเคพเคฆเคจ เคฏเคพ เคเคฐเฅเคเฅเคธเฅเคเฅเคฐเฅเคถเคจ เคธเคฟเคฆเฅเคงเคพเคเคค เคฎเฅเคก เคชเฅเคฐเฅเคฎเฅเคชเฅเค เคฏเคพ เคญเคตเคฟเคทเฅเคฏ เคเฅ เคเคชเฅเค-เคเคจ เคฎเฅเคกเฅเคฏเฅเคฒ เคฎเฅเค เคฐเคนเคคเฅ เคนเฅเค; เคฏเคน เคชเฅเคฐเฅเคตเคพเคตเคฒเฅเคเคจ เคฎเฅเคกเฅเคฏเฅเคฒ เคธเคเฅเคทเคฎ เคจเคนเฅเค เคเคฐเคคเคพ เคเคฐ เคจ เคนเฅ เคเคจเคเฅ เคเฅเคจเฅเคซเคผเคฟเคเคฐเฅเคถเคจ เคฌเคฆเคฒเคคเคพ เคนเฅเฅค\n\n\
เค
เคเคเฅเคเคพเคฐ\n{ratify_how}"
)
}
Locale::Ru => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"ะะพะดะณะพัะพะฒะปะตะฝะพ {label} ะฝะฐ ะพัะฝะพะฒะต ะฒะฐัะธั
ะพัะฒะตัะพะฒ ะฝะฐ ะฝะฐะฒะพะดััะธะต ะฒะพะฟัะพัั, ะทะฐัะตะผ ะฟัะพะฒะตัะตะฝะพ ะฟะพ ัั
ะตะผะต ะธ ะพะณัะฐะฝะธัะตะฝะพ Codewhale."
),
DraftProvenance::Guided => {
"ะะตัะตัะผะธะฝะธัะพะฒะฐะฝะฝะพ ะฟะพัััะพะตะฝะพ ะธะท ะฒะฐัะธั
ะพัะฒะตัะพะฒ ะฝะฐ ะฝะฐะฒะพะดััะธะต ะฒะพะฟัะพัั.".to_string()
}
DraftProvenance::Existing => {
"ะะฐัะฐ ัััะตััะฒัััะฐั ะบะพะฝััะธัััะธั, ะทะฐะณััะถะตะฝะฝะฐั ะธะท constitution.json, โ ะฟะพะบะฐะทะฐะฝะฐ ะฑะตะท ะธะทะผะตะฝะตะฝะธะน."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"ะญัะพ ัะถะต ะฒะฐั ะดะตะนััะฒัััะธะน ะทะฐะบะพะฝ. ะะฐะบัะพะนัะต ััะพ ะฟัะตะฒัั, ะทะฐัะตะผ ะฝะฐะถะผะธัะต K, ััะพะฑั ัะพั
ัะฐะฝะธัั ะตั ะธ ะทะฐะฒะตััะธัั ะบะพะฝััะพะปัะฝัั ัะพัะบั โ \
ัะฐะนะป ะฝะต ะธะทะผะตะฝัะตััั. ะะทะผะตะฝะธัั ะผะพะถะฝะพ ะฒ ะปัะฑะพะต ะฒัะตะผั ัะตัะตะท /constitution ะธะปะธ /setup."
}
_ => {
"ะะธััะพ ะฝะต ััะฐะฝะพะฒะธััั ะทะฐะบะพะฝะพะผ, ะฟะพะบะฐ ะฒั ะฝะต ะฟะพะดัะฒะตัะดะธัะต. ะะฐะบัะพะนัะต ััะพ ะฟัะตะฒัั, ะทะฐัะตะผ ะฝะฐะถะผะธัะต G, ััะพะฑั ัะฐัะธัะธัะธัะพะฒะฐัั ะธ ัะพั
ัะฐะฝะธัั. \
ะะทะผะตะฝะธัั ะผะพะถะฝะพ ะฒ ะปัะฑะพะต ะฒัะตะผั ัะตัะตะท /constitution ะธะปะธ /setup."
}
};
format!(
"CODEWHALE ยท ะะะะกะขะะขะฃะฆะะฏ ะะะะฌะะะะะขะะะฏ\n{RULE}\n\n{drafted_by}\n\n\
ะญัะพ ะฟะพััะพัะฝะฝัะน ะทะฐะบะพะฝ ะพ ัะพะผ, ะบะฐะบ Codewhale ัะฐะฑะพัะฐะตั ั ะฒะฐะผะธ. ะะฐะบ ะปัััะธะต ะบะพะฝััะธัััะธะธ, \
ะพะฝะฐ ะดะพััะฐัะพัะฝะพ ะบะพัะพัะบะฐ, ััะพะฑั ะตะน ะฟะพะปัะทะพะฒะฐัััั, ัะพััะพะธั ะธะท ะดะพะปะณะพะฒะตัะฝัั
ะฟัะธะฝัะธะฟะพะฒ, ะฐ ะฝะต ะธััะตัะฟัะฒะฐััะธั
ะฟัะฐะฒะธะป, \
ะธ ะผะพะถะตั ะธะทะผะตะฝััััั ะฒะผะตััะต ั ะฒะฐะผะธ. ะะฝะฐ ะพัะตััะธะฒะฐะตั ะฟะพะปะฝะพะผะพัะธั ะธ ะณัะฐะฝะธัั, ะฐ ะฝะต ัะตัะฐะตั ะบะฐะถะดัะน ัะปััะฐะน, \
ะธ ะฟัะธะดะฐัั ะฒะฐัะตะผั ัะพัััะดะฝะธัะตััะฒั ะฝะตะฟัะตััะฒะฝะพััั ะผะตะถะดั ัะตััะธัะผะธ โ ะฝะพ ะพะฝะฐ ะฝะต ะฟะฐะผััั: ะพะฝะฐ ั
ัะฐะฝะธั ะฟัะธะฝัะธะฟั, ะฐ ะฝะต ะธััะพัะธั.\n\n\
{rendered}\n\n\
ะะะ ะะ ะฅะะฏ ะะะะะะะะงะะ\n{layer_order}\nะะฐัะธ ะฟััะผัะต ัะบะฐะทะฐะฝะธั ะฒัะตะณะดะฐ ะฒะฐะถะฝะตะต ััะพะณะพ ะดะพะบัะผะตะฝัะฐ.\n\n\
ะงะะะ ะะะ ะะ ะะะะะข\n\
ะะฝะฐ ะฝะฐะฟัะฐะฒะปัะตั ะฟะพะฒะตะดะตะฝะธะต. ะะฝะฐ ะฝะต ะผะพะถะตั ะฟัะตะดะพััะฐะฒะธัั ะธะปะธ ะธะทะผะตะฝะธัั ะฟะพะปะธัะธะบั ะพะดะพะฑัะตะฝะธั, sandbox, shell, ัะตัั, \
ะดะพะฒะตัะธะต, ัะฐะทัะตัะตะฝะธั MCP, ัะตะถะธะผ ะฟะพ ัะผะพะปัะฐะฝะธั, ะฟัะฑะปะธะบะฐัะธั ะธะปะธ ะฟัะฐะฒะพ ััะฐัะธัั โ ะพะฝะธ ะพััะฐัััั ะฒ ะฒะฐัะธั
ััะบะฐั
ะฒะพ ะฒัะตะผั ะฒัะฟะพะปะฝะตะฝะธั.\n\n\
ะกะะะ ะะฉะะะะะ ะฏะะ ะ ะ ะะะฆะะะะะะฌะะซะ ะะะะฃะะ\n\
ะัััะพะตะฝะฝะพะต ัะดัะพ ะพััะฐัััั ะฐะบัะธะฒะฝัะผ. ะญัะพั ะฟัะพะตะบั ัะพั
ัะฐะฝัะตั ัะพะปัะบะพ ะฒะฐัะธ ะณะปะพะฑะฐะปัะฝัะต ะฟะพััะพัะฝะฝัะต ะฟัะตะดะฟะพััะตะฝะธั. \
ะขัะถัะปะฐั ะดะพะบััะธะฝะฐ ะธัะฟะพะปะฝะตะฝะธั ะธะปะธ ะพัะบะตัััะฐัะธะธ ะฟัะธะฝะฐะดะปะตะถะธั ะฟัะพะผะฟัะฐะผ ัะตะถะธะผะพะฒ ะธะปะธ ะฑัะดััะธะผ ะพะฟัะธะพะฝะฐะปัะฝัะผ ะผะพะดัะปัะผ; ััะพ ะฟัะตะฒัั ะฝะต ะฒะบะปััะฐะตั ะผะพะดัะปะธ ะธ ะฝะต ะผะตะฝัะตั ะธั
ะบะพะฝัะธะณััะฐัะธั.\n\n\
ะ ะะขะะคะะะะฆะะฏ\n{ratify_how}"
)
}
Locale::Uk => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"ะัะดะณะพัะพะฒะปะตะฝะพ {label} ะฝะฐ ะพัะฝะพะฒั ะฒะฐัะธั
ะฒัะดะฟะพะฒัะดะตะน ะฝะฐ ะฝะฐะฒัะดะฝั ะทะฐะฟะธัะฐะฝะฝั, ะฟะพััะผ ะฟะตัะตะฒััะตะฝะพ ะทะฐ ัั
ะตะผะพั ัะฐ ะพะฑะผะตะถะตะฝะพ Codewhale."
),
DraftProvenance::Guided => {
"ะะตัะตัะผัะฝะพะฒะฐะฝะพ ะฟะพะฑัะดะพะฒะฐะฝะพ ะท ะฒะฐัะธั
ะฒัะดะฟะพะฒัะดะตะน ะฝะฐ ะฝะฐะฒัะดะฝั ะทะฐะฟะธัะฐะฝะฝั.".to_string()
}
DraftProvenance::Existing => {
"ะะฐัะฐ ัะธะฝะฝะฐ ะบะพะฝััะธััััั, ะทะฐะฒะฐะฝัะฐะถะตะฝะฐ ะท constitution.json, โ ะฟะพะบะฐะทะฐะฝะฐ ะฑะตะท ะทะผัะฝ."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"ะฆะต ะฒะถะต ะฒะฐั ัะธะฝะฝะธะน ะทะฐะบะพะฝ. ะะฐะบัะธะนัะต ัะต ะฟัะตะฒ'ั, ะฟะพััะผ ะฝะฐัะธัะฝััั K, ัะพะฑ ะทะฑะตัะตะณัะธ ัั ัะฐ ะทะฐะฒะตััะธัะธ ะบะพะฝััะพะปัะฝั ัะพัะบั โ \
ัะฐะนะป ะฝะต ะทะผัะฝัััััั. ะะผัะฝะธัะธ ะผะพะถะฝะฐ ะฑัะดั-ะบะพะปะธ ัะตัะตะท /constitution ะฐะฑะพ /setup."
}
_ => {
"ะััะพ ะฝะต ััะฐั ะทะฐะบะพะฝะพะผ, ะดะพะบะธ ะฒะธ ะฝะต ะฟัะดัะฒะตัะดะธัะต. ะะฐะบัะธะนัะต ัะต ะฟัะตะฒ'ั, ะฟะพััะผ ะฝะฐัะธัะฝััั G, ัะพะฑ ัะฐัะธััะบัะฒะฐัะธ ัะฐ ะทะฑะตัะตะณัะธ. \
ะะผัะฝะธัะธ ะผะพะถะฝะฐ ะฑัะดั-ะบะพะปะธ ัะตัะตะท /constitution ะฐะฑะพ /setup."
}
};
format!(
"CODEWHALE ยท ะะะะกะขะะขะฃะฆะะฏ ะะะ ะะกะขะฃะะะงะ\n{RULE}\n\n{drafted_by}\n\n\
ะฆะต ะฟะพัััะนะฝะธะน ะทะฐะบะพะฝ ะฟัะพ ัะต, ัะบ Codewhale ะฟัะฐััั ะท ะฒะฐะผะธ. ะฏะบ ะฝะฐะนะบัะฐัั ะบะพะฝััะธััััั, \
ะฒะพะฝะฐ ะดะพััะฐัะฝัะพ ะบะพัะพัะบะฐ, ัะพะฑ ะฝะตั ะบะพัะธัััะฒะฐัะธัั, ัะบะปะฐะดะฐััััั ะท ะดะพะฒะณะพะฒััะฝะธั
ะฟัะธะฝัะธะฟัะฒ, ะฐ ะฝะต ะฒะธัะตัะฟะฝะธั
ะฟัะฐะฒะธะป, \
ั ะผะพะถะต ะทะผัะฝัะฒะฐัะธัั ัะฐะทะพะผ ัะท ะฒะฐะผะธ. ะะพะฝะฐ ะพะบัะตัะปัั ะฟะพะฒะฝะพะฒะฐะถะตะฝะฝั ัะฐ ะผะตะถั, ะฐ ะฝะต ะฒะธััััั ะบะพะถะตะฝ ะฒะธะฟะฐะดะพะบ, \
ั ะฝะฐะดะฐั ะฒะฐััะน ัะฟัะฒะฟัะฐัั ะฝะตะฟะตัะตัะฒะฝัััั ะผัะถ ัะตัััะผะธ โ ะฐะปะต ะฒะพะฝะฐ ะฝะต ะฟะฐะผ'ััั: ะฒะพะฝะฐ ะทะฑะตััะณะฐั ะฟัะธะฝัะธะฟะธ, ะฐ ะฝะต ัััะพััั.\n\n\
{rendered}\n\n\
ะะะ ะะ ะฅะะฏ ะะะะะะะะะะะฌ\n{layer_order}\nะะฐัั ะฟััะผั ะฒะบะฐะทัะฒะบะธ ะทะฐะฒะถะดะธ ะฒะฐะถะปะธะฒััั ะทะฐ ัะตะน ะดะพะบัะผะตะฝั.\n\n\
ะงะะะ ะะะะ ะะ ะะะะ\n\
ะะพะฝะฐ ัะฟััะผะพะฒัั ะฟะพะฒะตะดัะฝะบั. ะะพะฝะฐ ะฝะต ะผะพะถะต ะฝะฐะดะฐัะธ ะฐะฑะพ ะทะผัะฝะธัะธ ะฟะพะปััะธะบั ัั
ะฒะฐะปะตะฝะฝั, sandbox, shell, ะผะตัะตะถั, \
ะดะพะฒััั, ะดะพะทะฒะพะปะธ MCP, ัะตะถะธะผ ะทะฐ ะทะฐะผะพะฒััะฒะฐะฝะฝัะผ, ะฟัะฑะปัะบะฐััั ัะธ ะฟัะฐะฒะพ ะฒะธััะฐัะฐัะธ โ ะฒะพะฝะธ ะทะฐะปะธัะฐััััั ั ะฒะฐัะธั
ััะบะฐั
ะฟัะด ัะฐั ะฒะธะบะพะฝะฐะฝะฝั.\n\n\
ะกะะะ ะะงะะะ ะฏะะ ะ ะ ะะะฆะะะะ ะะะะฃะะ\n\
ะะฑัะดะพะฒะฐะฝะต ัะดัะพ ะทะฐะปะธัะฐััััั ะฐะบัะธะฒะฝะธะผ. ะฆะตะน ะฟัะพัะบั ะทะฑะตััะณะฐั ะปะธัะต ะฒะฐัั ะณะปะพะฑะฐะปัะฝั ะฟะพัััะนะฝั ะฒะฟะพะดะพะฑะฐะฝะฝั. \
ะะฐะถะบะฐ ะดะพะบััะธะฝะฐ ะฒะธะบะพะฝะฐะฝะฝั ัะธ ะพัะบะตัััะฐััั ะฝะฐะปะตะถะธัั ะฟัะพะผะฟัะฐะผ ัะตะถะธะผัะฒ ะฐะฑะพ ะผะฐะนะฑััะฝัะผ ะพะฟััะนะฝะธะผ ะผะพะดัะปัะผ; ัะต ะฟัะตะฒ'ั ะฝะต ะฒะผะธะบะฐั ะผะพะดัะปั ะน ะฝะต ะทะผัะฝัั ัั
ะฝั ะบะพะฝััะณััะฐััั.\n\n\
ะ ะะขะะคะะะะฆะะฏ\n{ratify_how}"
)
}
_ => {
let drafted_by = match provenance {
DraftProvenance::Model(label) => format!(
"Drafted by {label} from your guided answers, then schema-checked and bounded by Codewhale."
),
DraftProvenance::Guided => {
"Rendered deterministically from your guided answers.".to_string()
}
DraftProvenance::Existing => {
"Your existing constitution, loaded from constitution.json โ shown unchanged."
.to_string()
}
};
let ratify_how = match provenance {
DraftProvenance::Existing => {
"This is already your standing law. Close this preview, then press K to \
keep it and complete the checkpoint โ the file is not modified. Amend \
anytime with /constitution or /setup."
}
_ => {
"Nothing becomes law until you confirm. Close this preview, then press G to \
ratify and save. Amend anytime with /constitution or /setup."
}
};
format!(
"CODEWHALE ยท USER CONSTITUTION\n{RULE}\n\n{drafted_by}\n\n\
This is the standing law for how Codewhale works with you. Like the best \
constitutions, it is short enough to use, made of durable principles rather \
than exhaustive rules, and amendable as you change. It frames powers and \
limits rather than deciding every case, and it gives your collaboration \
continuity across sessions โ but it is not memory: it carries principles, \
not history.\n\n\
{rendered}\n\n\
HIERARCHY OF AUTHORITY\n{layer_order}\nYour direct requests always outrank this document.\n\n\
WHAT THIS CANNOT DO\n\
It guides behavior. It cannot grant or change approval policy, sandbox, shell, \
network, trust, MCP permissions, default mode, publishing, or spending \
authority โ those stay under your hand at runtime.\n\n\
REDUCED CORE AND OPT-IN MODULES\n\
The bundled core stays active. This draft only saves your user-global \
standing preferences. Execution and orchestration capabilities come from runtime \
policy, the live tool catalog, or future opt-in modules; this preview does not enable modules or change \
their configuration.\n\n\
RATIFICATION\n{ratify_how}"
)
}
}
}
fn model_draft_invitation_line(locale: Locale, model_label: &str) -> String {
match locale {
Locale::Ja => {
format!("A {model_label} ใ่ตท่ใใใใชใใๆนๅใใพใใ็ขบ่ชใใใพใงไฟๅญใใพใใใ")
}
Locale::ZhHans => {
format!("A {model_label} ็ๆ่ๆก๏ผ็ฑไฝ ็กฎ่ฎคใๆช็ป็กฎ่ฎคไธไผไฟๅญใ")
}
Locale::ZhHant => {
format!("A {model_label} ่ตท่๏ผไฝ ๆนๅใๆช็ถ็ขบ่ชไธๆไฟๅญใ")
}
Locale::PtBr => {
format!("A {model_label} pode rascunhar. Vocรช ratifica. Nada salva sem vocรช.")
}
Locale::Es419 => {
format!("A {model_label} puede redactarla. Tรบ ratificas. Nada se guarda sin ti.")
}
Locale::Vi => {
format!("A {model_label} cรณ thแป soแบกn. Bแบกn phรช chuแบฉn. Khรดng lฦฐu gรฌ nแบฟu chฦฐa cรณ bแบกn.")
}
Locale::Ko => {
format!(
"A {model_label}์ด(๊ฐ) ์ด์์ ์์ฑํ ์ ์์ต๋๋ค. ์น์ธ์ ๋น์ ์ด ํฉ๋๋ค. ๋น์ ์์ด๋ ์๋ฌด๊ฒ๋ ์ ์ฅ๋์ง ์์ต๋๋ค."
)
}
Locale::Ca => {
format!("A {model_label} la pot redactar. Tu la ratifiques. Res no es desa sense tu.")
}
Locale::De => {
format!(
"A {model_label} kann sie entwerfen. Du ratifizierst sie. Ohne dich wird nichts gespeichert."
)
}
Locale::Fr => {
format!(
"A {model_label} peut la rรฉdiger. Vous la ratifiez. Rien ne s'enregistre sans vous."
)
}
Locale::Id => {
format!(
"A {model_label} dapat menyusunnya. Anda yang meratifikasi. Tidak ada yang tersimpan tanpa Anda."
)
}
Locale::Hi => {
format!(
"A {model_label} เคเคธเคเคพ เคฎเคธเฅเคฆเคพ เคฌเคจเคพ เคธเคเคคเคพ เคนเฅเฅค เค
เคเคเฅเคเคพเคฐ เคเคช เคเคฐเคคเฅ เคนเฅเคเฅค เคเคชเคเฅ เคฌเคฟเคจเคพ เคเฅเค เคญเฅ เคธเคนเฅเคเคพ เคจเคนเฅเค เคเคพเคคเคพเฅค"
)
}
Locale::Ru => {
format!(
"A {model_label} ะผะพะถะตั ะฟะพะดะณะพัะพะฒะธัั ะฟัะพะตะบั. ะ ะฐัะธัะธัะธััะตัะต ะฒั. ะะตะท ะฒะฐั ะฝะธัะตะณะพ ะฝะต ัะพั
ัะฐะฝัะตััั."
)
}
Locale::Uk => {
format!(
"A {model_label} ะผะพะถะต ะฟัะดะณะพััะฒะฐัะธ ะฟัะพัะบั. ะ ะฐัะธััะบัััะต ะฒะธ. ะะตะท ะฒะฐั ะฝััะพะณะพ ะฝะต ะทะฑะตััะณะฐััััั."
)
}
_ => format!("A {model_label} can draft it. You ratify it. Nothing saves without you."),
}
}
fn keep_existing_invitation_line(locale: Locale) -> &'static str {
match locale {
Locale::Ja => "K ๆขๅญใฎๆฒๆณใไฟๆ - ็ขบ่ชใใฆไฟๆใใใกใคใซใฏๅคๆดใใพใใใ",
Locale::ZhHans => "K ไฟ็็ฐๆๅฎช็ซ โโๅ
ๆฅ็๏ผๅไฟ็๏ผๆไปถไธๅใ",
Locale::ZhHant => "K ไฟ็็พๆๆฒๆณ - ๅ
ๆฅ็๏ผๅไฟ็๏ผๆชๆกไธ่ฎใ",
Locale::PtBr => "K Manter constituiรงรฃo existente - revise, mantenha, arquivo inalterado.",
Locale::Es419 => {
"K Conservar constituciรณn existente - revisa, conserva, archivo sin cambios."
}
Locale::Vi => "K Giแปฏ hiแบฟn phรกp hiแปn cรณ - xem lแบกi, giแปฏ nguyรชn, tแปp khรดng ฤแปi.",
Locale::Ko => "K ๊ธฐ์กด ํ๋ฒ ์ ์ง - ๊ฒํ ํ ์ ์ง, ํ์ผ์ ๋ณ๊ฒฝ๋์ง ์์.",
Locale::Ca => {
"K Mantรฉn la constituciรณ existent - revisa-la, conserva-la, fitxer sense canvis."
}
Locale::De => "K Bestehende Verfassung behalten - prรผfen, behalten, Datei unverรคndert.",
Locale::Fr => {
"K Garder votre constitution existante - rรฉvisez-la, gardez-la, fichier inchangรฉ."
}
Locale::Id => {
"K Pertahankan konstitusi Anda yang ada - tinjau, pertahankan, file tidak berubah."
}
Locale::Hi => "K เค
เคชเคจเคพ เคฎเฅเคเฅเคฆเคพ เคธเคเคตเคฟเคงเคพเคจ เคฐเคเฅเค - เคธเคฎเฅเคเฅเคทเคพ เคเคฐเฅเค, เคฌเคจเคพเค เคฐเคเฅเค, เคซเคผเคพเคเคฒ เค
เคชเคฐเคฟเคตเคฐเฅเคคเคฟเคคเฅค",
Locale::Ru => {
"K ะกะพั
ัะฐะฝะธัั ัััะตััะฒััััั ะบะพะฝััะธัััะธั - ะฟัะพัะผะพััะธัะต, ัะพั
ัะฐะฝะธัะต, ัะฐะนะป ะฝะต ะธะทะผะตะฝัะตััั."
}
Locale::Uk => "K ะะฑะตัะตะณัะธ ัะธะฝะฝั ะบะพะฝััะธััััั - ะฟะตัะตะณะปัะฝััะต, ะทะฑะตัะตะถััั, ัะฐะนะป ะฑะตะท ะทะผัะฝ.",
_ => "K Keep your existing constitution โ review it, keep it, file unchanged.",
}
}
fn model_draft_ready_line(locale: Locale, model_label: &str) -> String {
match locale {
Locale::Ja => {
format!(
"{model_label} ใฎ่ๆกใๆนๅๅพ
ใกใงใ - G ใง็ขบ่ชใใฆๆนๅใ1-6 ใง่ๆกใ็ ดๆฃใใพใใ"
)
}
Locale::ZhHans => {
format!("{model_label} ็่ๆกๅพ
็กฎ่ฎคโโๆ G ๆฅ็ๅนถ็กฎ่ฎค๏ผๆ 1-6 ไผไธขๅผ่ๆกใ")
}
Locale::ZhHant => {
format!("{model_label} ็่ๆกๅพ
ๆนๅ - ๆ G ๆฅ็ไธฆๆนๅ๏ผๆ 1-6 ๆไธๆฃ่ๆกใ")
}
Locale::PtBr => {
format!(
"Rascunho de {model_label} aguarda ratificaรงรฃo - G para revisar e ratificar; 1-6 descarta."
)
}
Locale::Es419 => {
format!(
"El borrador de {model_label} espera ratificaciรณn - G para revisar y ratificar; 1-6 lo descarta."
)
}
Locale::Vi => {
format!(
"Bแบฃn nhรกp cแปงa {model_label} chแป phรช chuแบฉn - G ฤแป xem vร phรช chuแบฉn; 1-6 sแบฝ bแป bแบฃn nhรกp."
)
}
Locale::Ko => {
format!(
"{model_label}์ ์ด์์ด ์น์ธ์ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ต๋๋ค - G๋ก ํ์ธํ๊ณ ์น์ธ, 1-6์ ์ด์์ ๋ฒ๋ฆฝ๋๋ค."
)
}
Locale::Ca => {
format!(
"L'esborrany de {model_label} espera ratificaciรณ - G per revisar i ratificar; 1-6 el descarta."
)
}
Locale::De => {
format!(
"Entwurf von {model_label} wartet auf Ratifizierung - G zum Prรผfen und Ratifizieren; 1-6 verwirft ihn."
)
}
Locale::Fr => {
format!(
"Le brouillon de {model_label} attend ratification - G pour rรฉviser et ratifier ; 1-6 l'รฉcarte."
)
}
Locale::Id => {
format!(
"Draf oleh {model_label} menunggu ratifikasi - G untuk meninjau dan meratifikasi; 1-6 membuangnya."
)
}
Locale::Hi => {
format!(
"{model_label} เคเคพ เคฎเคธเฅเคฆเคพ เค
เคเคเฅเคเคพเคฐ เคเฅ เคชเฅเคฐเคคเฅเคเฅเคทเคพ เคฎเฅเค เคนเฅ - เคธเคฎเฅเคเฅเคทเคพ เคเคฐ เค
เคเคเฅเคเคพเคฐ เคเฅ เคฒเคฟเค G; 1-6 เคเคธเฅ เคเคพเคฐเคฟเค เคเคฐเคคเคพ เคนเฅเฅค"
)
}
Locale::Ru => {
format!(
"ะัะพะตะบั ะพั {model_label} ะพะถะธะดะฐะตั ัะฐัะธัะธะบะฐัะธะธ - G ะดะปั ะฟัะพัะผะพััะฐ ะธ ัะฐัะธัะธะบะฐัะธะธ; 1-6 ะพัะบะปะพะฝัะตั ะตะณะพ."
)
}
Locale::Uk => {
format!(
"ะัะพัะบั ะฒัะด {model_label} ะพััะบัั ัะฐัะธััะบะฐััั - G ะดะปั ะฟะตัะตะณะปัะดั ัะฐ ัะฐัะธััะบะฐััั; 1-6 ะฒัะดั
ะธะปัั ะนะพะณะพ."
)
}
_ => format!(
"Draft by {model_label} awaits ratification โ G to review and ratify; 1-6 discards it."
),
}
}
pub(crate) fn model_draft_ready_message(locale: Locale, model_label: &str) -> String {
match locale {
Locale::Ja => format!(
"{model_label} ใใใชใใฎๆฒๆณใ่ตท่ใใพใใใใใฌใใฅใผใ็ขบ่ชใใฆใใ G ใงๆนๅใใฆใใ ใใใ"
),
Locale::ZhHans => {
format!("{model_label} ๅทฒ็ๆไฝ ็ๅฎช็ซ ่ๆกใ่ฏทๆฅ็้ข่ง๏ผ็ถๅๆ G ็กฎ่ฎคใ")
}
Locale::ZhHant => format!("{model_label} ๅทฒ่ตท่ไฝ ็ๆฒๆณใ่ซๆฅ็้ ่ฆฝ๏ผ็ถๅพๆ G ๆนๅใ"),
Locale::PtBr => format!(
"{model_label} rascunhou sua constituiรงรฃo. Revise a prรฉvia e pressione G para ratificar."
),
Locale::Es419 => format!(
"{model_label} redactรณ tu constituciรณn. Revisa la vista previa y presiona G para ratificar."
),
Locale::Vi => format!(
"{model_label} ฤรฃ soแบกn hiแบฟn phรกp cแปงa bแบกn. Xem bแบฃn xem trฦฐแปc rแปi nhแบฅn G ฤแป phรช chuแบฉn."
),
Locale::Ko => format!(
"{model_label}์ด(๊ฐ) ๋น์ ์ ํ๋ฒ ์ด์์ ์์ฑํ์ต๋๋ค. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ํ์ธํ ๋ค G๋ฅผ ๋๋ฌ ์น์ธํ์ธ์."
),
Locale::Ca => format!(
"{model_label} ha redactat la teva constituciรณ. Revisa la previsualitzaciรณ i prem G per ratificar."
),
Locale::De => format!(
"{model_label} hat deine Verfassung entworfen. Prรผfe die Vorschau und drรผcke G zum Ratifizieren."
),
Locale::Fr => format!(
"{model_label} a rรฉdigรฉ votre constitution. Rรฉvisez l'aperรงu, puis appuyez sur G pour ratifier."
),
Locale::Id => format!(
"{model_label} menyusun konstitusi Anda. Tinjau pratinjaunya, lalu tekan G untuk meratifikasi."
),
Locale::Hi => format!(
"{model_label} เคจเฅ เคเคชเคเฅ เคธเคเคตเคฟเคงเคพเคจ เคเคพ เคฎเคธเฅเคฆเคพ เคคเฅเคฏเคพเคฐ เคเคฟเคฏเคพเฅค เคชเฅเคฐเฅเคตเคพเคตเคฒเฅเคเคจ เคฆเฅเคเฅเค, เคซเคฟเคฐ เค
เคเคเฅเคเคพเคฐ เคเฅ เคฒเคฟเค G เคฆเคฌเคพเคเคเฅค"
),
Locale::Ru => format!(
"{model_label} ะฟะพะดะณะพัะพะฒะธะป ะฟัะพะตะบั ะฒะฐัะตะน ะบะพะฝััะธัััะธะธ. ะัะพัะผะพััะธัะต ะฟัะตะฒัั, ะทะฐัะตะผ ะฝะฐะถะผะธัะต G ะดะปั ัะฐัะธัะธะบะฐัะธะธ."
),
Locale::Uk => format!(
"{model_label} ะฟัะดะณะพััะฒะฐะฒ ะฟัะพัะบั ะฒะฐัะพั ะบะพะฝััะธััััั. ะะตัะตะณะปัะฝััะต ะฟัะตะฒ'ั, ะฟะพััะผ ะฝะฐัะธัะฝััั G ะดะปั ัะฐัะธััะบะฐััั."
),
_ => format!(
"{model_label} drafted your constitution. Review the preview, then press G to ratify."
),
}
}
pub(crate) fn model_draft_failed_message(
locale: Locale,
model_label: &str,
reason: &str,
) -> String {
match locale {
Locale::Ja => {
format!(
"{model_label} ใฏ่ตท่ใๅฎไบใงใใพใใใงใใ๏ผ{reason}๏ผใใฌใคใ่ๆกใฏๆๅนใงใใG ใงใใฌใใฅใผใใฆๆนๅใงใใพใใ"
)
}
Locale::ZhHans => {
format!("{model_label} ๆช่ฝ็ๆ่ๆก๏ผ{reason}๏ผใๅผๅฏผๅผ่ๆกไปๅฏไฝฟ็จโโๆ G ้ข่งๅนถ็กฎ่ฎคใ")
}
Locale::ZhHant => {
format!("{model_label} ๆช่ฝๅฎๆ่ตท่๏ผ{reason}๏ผใๅผๅฐๅผ่ๆกไป็ถๆๆ๏ผๆ G ้ ่ฆฝไธฆๆนๅใ")
}
Locale::PtBr => {
format!(
"{model_label} nรฃo conseguiu rascunhar sua constituiรงรฃo ({reason}). O rascunho guiado continua vรกlido; pressione G para prรฉ-visualizar e ratificar."
)
}
Locale::Es419 => {
format!(
"{model_label} no pudo redactar tu constituciรณn ({reason}). El borrador guiado sigue vรกlido; presiona G para previsualizar y ratificar."
)
}
Locale::Vi => {
format!(
"{model_label} khรดng thแป soแบกn hiแบฟn phรกp cแปงa bแบกn ({reason}). Bแบฃn nhรกp hฦฐแปng dแบซn vแบซn hแปฃp lแป; nhแบฅn G ฤแป xem trฦฐแปc vร phรช chuแบฉn."
)
}
Locale::Ko => {
format!(
"{model_label}์ด(๊ฐ) ๋น์ ์ ํ๋ฒ ์ด์์ ์์ฑํ์ง ๋ชปํ์ต๋๋ค ({reason}). ๊ฐ์ด๋ ์ด์์ ์ฌ์ ํ ์ ํจํฉ๋๋ค. G๋ฅผ ๋๋ฌ ๋ฏธ๋ฆฌ๋ณด๊ณ ์น์ธํ์ธ์."
)
}
Locale::Ca => {
format!(
"{model_label} no ha pogut redactar la teva constituciรณ ({reason}). L'esborrany guiat continua vigent; prem G per previsualitzar i ratificar."
)
}
Locale::De => {
format!(
"{model_label} konnte deine Verfassung nicht entwerfen ({reason}). Dein gefรผhrter Entwurf bleibt gรผltig; drรผcke G fรผr Vorschau und Ratifizierung."
)
}
Locale::Fr => {
format!(
"{model_label} n'a pas pu rรฉdiger votre constitution ({reason}). Votre brouillon guidรฉ reste valide ; appuyez sur G pour l'aperรงu et la ratification."
)
}
Locale::Id => {
format!(
"{model_label} tidak dapat menyusun konstitusi Anda ({reason}). Draf terpandu Anda tetap berlaku; tekan G untuk pratinjau dan ratifikasi."
)
}
Locale::Hi => {
format!(
"{model_label} เคเคชเคเฅ เคธเคเคตเคฟเคงเคพเคจ เคเคพ เคฎเคธเฅเคฆเคพ เคจเคนเฅเค เคฌเคจเคพ เคธเคเคพ ({reason})เฅค เคเคชเคเคพ เคเคพเคเคกเฅเคก เคฎเคธเฅเคฆเคพ เค
เคฌ เคญเฅ เคฎเคพเคจเฅเคฏ เคนเฅ; เคชเฅเคฐเฅเคตเคพเคตเคฒเฅเคเคจ เคเคฐ เค
เคเคเฅเคเคพเคฐ เคเฅ เคฒเคฟเค G เคฆเคฌเคพเคเคเฅค"
)
}
Locale::Ru => {
format!(
"{model_label} ะฝะต ัะผะพะณ ะฟะพะดะณะพัะพะฒะธัั ะฒะฐัั ะบะพะฝััะธัััะธั ({reason}). ะะฐั ัะฟัะฐะฒะปัะตะผัะน ะฟัะพะตะบั ะพััะฐัััั ะฒ ัะธะปะต โ ะฝะฐะถะผะธัะต G ะดะปั ะฟัะพัะผะพััะฐ ะธ ัะฐัะธัะธะบะฐัะธะธ."
)
}
Locale::Uk => {
format!(
"{model_label} ะฝะต ะทะผัะณ ะฟัะดะณะพััะฒะฐัะธ ะฒะฐัั ะบะพะฝััะธััััั ({reason}). ะะฐั ะบะตัะพะฒะฐะฝะธะน ะฟัะพัะบั ะทะฐะปะธัะฐััััั ัะธะฝะฝะธะผ โ ะฝะฐัะธัะฝััั G ะดะปั ะฟะตัะตะณะปัะดั ัะฐ ัะฐัะธััะบะฐััั."
)
}
_ => format!(
"{model_label} could not draft your constitution ({reason}). Your guided draft still \
stands โ press G to preview and ratify."
),
}
}
fn constitution_choice_label(choice: ConstitutionChoice) -> &'static str {
match choice {
ConstitutionChoice::Unset => "unset",
ConstitutionChoice::Bundled => "bundled/default",
ConstitutionChoice::GuidedCustom => "guided custom",
ConstitutionChoice::ExpertOverride => "expert override",
ConstitutionChoice::Deferred => "deferred",
}
}
fn constitution_source_label(source: ConstitutionSource) -> &'static str {
match source {
ConstitutionSource::Bundled => "bundled",
ConstitutionSource::UserGlobal => "user-global constitution.json",
ConstitutionSource::ExpertOverride => "expert full Markdown override",
}
}
fn constitution_validity_label(validity: ConstitutionValidity) -> &'static str {
match validity {
ConstitutionValidity::Unknown => "unknown",
ConstitutionValidity::Valid => "valid",
ConstitutionValidity::Invalid => "invalid",
ConstitutionValidity::Empty => "empty",
ConstitutionValidity::Unreadable => "unreadable",
}
}
pub fn persist_user_constitution_choice(
constitution: &UserConstitution,
state: &SetupState,
) -> anyhow::Result<()> {
let constitution_path = UserConstitution::path()?;
let setup_state_path = SetupState::path()?;
let mut transaction = codewhale_config::persistence::SetupTransaction::new();
transaction.stage_json(constitution_path, &constitution.bounded())?;
transaction.stage_json(setup_state_path, state)?;
transaction.commit()
}
#[must_use]
pub fn should_open_update_checkpoint(app: &App, config: &Config) -> bool {
let state = load_setup_state_for_app(app, config);
state.needs_constitution_checkpoint(CONSTITUTION_CHECKPOINT_VERSION)
}
pub fn defer_update_checkpoint_for_app(app: &App, config: &Config) -> anyhow::Result<SetupState> {
let mut state = load_setup_state_for_app(app, config);
if !state.needs_constitution_checkpoint(CONSTITUTION_CHECKPOINT_VERSION) {
return Ok(state);
}
state.complete_constitution_checkpoint(
CONSTITUTION_CHECKPOINT_VERSION,
ConstitutionChoice::Deferred,
);
state.constitution_source = ConstitutionSource::Bundled;
state.constitution_validity = ConstitutionValidity::Unknown;
state.constitution_authoring = None;
state.constitution_preview_hash = None;
state.set_step(
SetupStep::Constitution,
StepEntry::new(StepStatus::Deferred, true, CONSTITUTION_CHECKPOINT_VERSION)
.with_result("checkpoint deferred; bundled applies"),
);
state.save()?;
Ok(state)
}
#[must_use]
pub fn load_setup_state_for_app(app: &App, config: &Config) -> SetupState {
if let Ok(Some(state)) = SetupState::load() {
return state;
}
SetupState::derive_inherited(&inherited_facts_for_app(app, config))
}
pub(crate) fn record_provider_model_setup_state_for_app(
app: &App,
config: &Config,
) -> anyhow::Result<SetupState> {
let facts = SetupRuntimeFacts::from_app_config(app, config);
let mut state = load_setup_state_for_app(app, config);
state.set_step(
SetupStep::ProviderModel,
provider::step_entry(
facts.provider_ready,
CONSTITUTION_CHECKPOINT_VERSION,
facts.provider_result,
),
);
state.save()?;
Ok(state)
}
#[must_use]
fn inherited_facts_for_app(app: &App, config: &Config) -> InheritedConfigFacts {
let user_constitution = UserConstitution::load().ok();
let user_constitution_validity = user_constitution.as_ref().map_or(
ConstitutionValidity::Unknown,
UserConstitutionLoad::validity,
);
let has_user_constitution = user_constitution
.as_ref()
.is_some_and(|loaded| !matches!(loaded, UserConstitutionLoad::Missing));
let expert_override = SetupExpertOverrideState::load();
InheritedConfigFacts {
language: Some(app.ui_locale.tag().to_string()),
has_provider_route: !config.default_model().trim().is_empty(),
has_credentials_or_local_runtime: has_api_key(config),
trust_chosen: app.trust_mode || !onboarding::needs_trust(&app.workspace),
has_expert_override: expert_override.is_active(),
has_user_constitution,
user_constitution_validity,
}
}
fn expert_override_path() -> Option<std::path::PathBuf> {
codewhale_config::codewhale_home()
.ok()
.map(|home| home.join(Path::new(CONSTITUTION_OVERRIDE_FILE)))
}
#[must_use]
fn progressive_initial_step_index(state: &SetupState, facts: &SetupRuntimeFacts) -> usize {
if !facts.provider_ready {
return step_index(SetupStep::ProviderModel);
}
let runtime_current = if state.inherited {
matches!(state.status(SetupStep::TrustSandbox), StepStatus::Verified)
&& state.runtime_posture_source.is_reviewed()
} else {
state
.steps
.get(&SetupStep::TrustSandbox)
.is_some_and(|entry| {
entry.status == StepStatus::Verified
&& entry.result.as_deref() == Some(facts.runtime_result.as_str())
})
&& state.runtime_posture_source.is_reviewed()
};
if !runtime_current {
return step_index(SetupStep::TrustSandbox);
}
if facts.tools_mcp_needs_action {
return step_index(SetupStep::ToolsMcp);
}
step_index(SetupStep::Verification)
}
#[must_use]
fn step_index(step: SetupStep) -> usize {
STEP_SPECS
.iter()
.position(|spec| spec.id() == step)
.expect("all setup-state steps should have wizard specs")
}
fn visible_step_index(step: SetupStep) -> usize {
STEP_SPECS
.iter()
.position(|spec| spec.id() == step)
.unwrap_or_else(|| step_index(SetupStep::Constitution))
}
#[cfg(test)]
mod progressive_tests {
use super::*;
use crossterm::event::KeyModifiers;
fn facts(provider_ready: bool) -> SetupRuntimeFacts {
SetupRuntimeFacts {
provider: "local".to_string(),
model: "stub-model".to_string(),
auth: if provider_ready { "ready" } else { "missing" }.to_string(),
provider_ready,
runtime_result: "approval=ask; sandbox=workspace; network=prompt".to_string(),
tools_mcp_result: "mcp=off, skills=off, tools=off, plugins=off, overall=off"
.to_string(),
remote_control_result: tr(Locale::En, MessageId::SetupRemoteStatusDisabled)
.into_owned(),
..SetupRuntimeFacts::default()
}
}
fn complete_state(runtime_result: &str) -> SetupState {
let mut state = SetupState {
runtime_posture_source: RuntimePostureSource::Confirmed,
..SetupState::default()
};
state.set_step(
SetupStep::TrustSandbox,
StepEntry::new(StepStatus::Verified, true, CONSTITUTION_CHECKPOINT_VERSION)
.with_result(runtime_result),
);
state
}
fn render_text(view: &SetupWizardView, width: u16, height: u16) -> String {
let area = Rect::new(0, 0, width, height);
let mut buffer = Buffer::empty(area);
ModalView::render(view, area, &mut buffer);
(0..height)
.map(|y| {
(0..width)
.map(|x| buffer[(x, y)].symbol())
.collect::<String>()
})
.collect::<Vec<_>>()
.join("\n")
}
#[test]
fn fresh_setup_starts_at_the_missing_provider_decision() {
let view = SetupWizardView::new_with_facts(SetupState::default(), Locale::En, facts(false));
assert_eq!(view.selected_step(), SetupStep::ProviderModel);
assert!(matches!(
ModalView::handle_key(
&mut view.clone(),
KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)
),
ViewAction::EmitAndClose(ViewEvent::SetupOpenProviderRequested)
));
}
#[test]
fn partial_setup_skips_the_ready_provider_and_asks_for_permissions() {
let mut view =
SetupWizardView::new_with_facts(SetupState::default(), Locale::En, facts(true));
assert_eq!(view.selected_step(), SetupStep::TrustSandbox);
let action =
ModalView::handle_key(&mut view, KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
let ViewAction::Emit(ViewEvent::SetupStateCommitRequested { state, message, .. }) = action
else {
panic!("reviewing the current permissions posture should persist a receipt");
};
assert_eq!(
state.runtime_posture_source,
RuntimePostureSource::Confirmed
);
assert_eq!(state.status(SetupStep::TrustSandbox), StepStatus::Verified);
assert!(!message.is_empty());
assert_eq!(view.selected_step(), SetupStep::RemoteRuntime);
}
#[test]
fn fully_configured_setup_opens_the_compact_summary() {
let facts = facts(true);
let state = complete_state(&facts.runtime_result);
let mut view = SetupWizardView::new_with_facts(state, Locale::En, facts);
assert_eq!(view.selected_step(), SetupStep::Verification);
let action =
ModalView::handle_key(&mut view, KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
let ViewAction::EmitAndClose(ViewEvent::SetupStateCommitRequested { state, .. }) = action
else {
panic!("starting from Ready should persist the report before closing");
};
assert!(state.steps.contains_key(&SetupStep::Verification));
}
#[test]
fn stale_complete_receipts_reopen_the_real_broken_surface() {
let mut provider_broken = facts(false);
provider_broken.runtime_result = "current".to_string();
let state = complete_state("old");
assert_eq!(
SetupWizardView::new_with_facts(state, Locale::En, provider_broken).selected_step(),
SetupStep::ProviderModel
);
let runtime_current = facts(true);
let stale_state = complete_state("old runtime snapshot");
assert_eq!(
SetupWizardView::new_with_facts(stale_state, Locale::En, runtime_current)
.selected_step(),
SetupStep::TrustSandbox
);
}
#[test]
fn configured_broken_tools_join_the_journey_but_empty_tools_do_not() {
let mut broken = facts(true);
let state = complete_state(&broken.runtime_result);
broken.tools_mcp_needs_action = true;
broken.tools_mcp_result = "overall=needs_config".to_string();
let mut broken_view = SetupWizardView::new_with_facts(state.clone(), Locale::En, broken);
assert_eq!(broken_view.selected_step(), SetupStep::ToolsMcp);
let action = ModalView::handle_key(
&mut broken_view,
KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE),
);
let ViewAction::Emit(ViewEvent::SetupStateCommitRequested { state, .. }) = action else {
panic!("continuing past a broken optional tool should save its visible issue");
};
assert_eq!(state.status(SetupStep::ToolsMcp), StepStatus::NeedsAction);
assert_eq!(broken_view.selected_step(), SetupStep::Verification);
let empty = facts(true);
assert_eq!(
SetupWizardView::new_with_facts(state, Locale::En, empty).selected_step(),
SetupStep::Verification
);
}
#[test]
fn account_action_uses_the_real_remote_control_handoff() {
let facts = facts(true);
let state = complete_state(&facts.runtime_result);
let mut view = SetupWizardView::new_with_facts(state, Locale::En, facts);
view.selected = visible_step_index(SetupStep::RemoteRuntime);
assert!(matches!(
ModalView::handle_key(
&mut view,
KeyEvent::new(KeyCode::Char('r'), KeyModifiers::NONE)
),
ViewAction::EmitAndClose(ViewEvent::SetupOpenRemoteControlRequested)
));
}
#[test]
fn progressive_arrow_keys_scroll_details_without_changing_the_decision() {
let mut view =
SetupWizardView::new_with_facts(SetupState::default(), Locale::En, facts(false));
view.details_expanded = true;
view.body_scroll = 4;
let step = view.selected_step();
assert!(matches!(
ModalView::handle_key(&mut view, KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)),
ViewAction::None
));
assert_eq!(view.selected_step(), step);
assert_eq!(view.body_scroll, 3);
assert!(matches!(
ModalView::handle_key(&mut view, KeyEvent::new(KeyCode::Down, KeyModifiers::NONE)),
ViewAction::None
));
assert_eq!(view.selected_step(), step);
assert_eq!(view.body_scroll, 4);
}
#[test]
fn fresh_and_complete_guides_remain_reachable_at_compact_and_normal_sizes() {
let fresh =
SetupWizardView::new_with_facts(SetupState::default(), Locale::En, facts(false));
let fresh_text = render_text(&fresh, 40, 12);
assert!(fresh_text.contains(tr(Locale::En, MessageId::OnboardProviderTitle).as_ref()));
let normal_text = render_text(&fresh, 100, 28);
assert!(normal_text.contains(tr(Locale::En, MessageId::OnboardProviderTitle).as_ref()));
assert!(normal_text.contains("local ยท stub-model"));
let facts = facts(true);
let complete = SetupWizardView::new_with_facts(
complete_state(&facts.runtime_result),
Locale::En,
facts,
);
let complete_text = render_text(&complete, 40, 12);
assert!(complete_text.contains(tr(Locale::En, MessageId::OnboardReadyTitle).as_ref()));
}
}