fix(tui): green main CI — fmt, parking followup receipt, Windows path gate

Align turn-end parking assertions with the actionable followup Interrupted
receipt (agent_id + action=followup), strip Windows \\?\ verbatim prefixes
from snapshot size-gate diagnostics, and rustfmt the two lint offenders so
macOS/Windows CI stay green with Ubuntu.
This commit is contained in:
Hunter Bown committed 2026-09-10 05:56:52 +00:00
1 parent aade9361bb
commit dfa0f2d223
4 files changed
+61 -23

No files matched your search

+21 -6
View File
@@ -104,20 +104,30 @@ pub const GATE_TOO_LARGE_MARKER: &str = "workspace too large for snapshots";
pub const GATE_TOO_MANY_ENTRIES_MARKER: &str = "workspace has too many files for snapshots";
pub const GATE_UNSAFE_LOCATION_MARKER: &str = "workspace snapshots are disabled";
/// Display a workspace path in gate diagnostics without Windows verbatim
/// (`\\?\`) prefixes. `Path::canonicalize` embeds that prefix; users and
/// tests name the workspace without it, so leave it out of the message.
fn display_workspace_for_gate(workspace: &Path) -> String {
let raw = workspace.display().to_string();
raw.strip_prefix(r"\\?\")
.or_else(|| raw.strip_prefix("//?/"))
.unwrap_or(&raw)
.to_string()
}
impl WorkspaceGate {
/// One-line English diagnostic for logs, `/undo`, and the gate matcher.
/// The user-facing consequence and recovery are localized by the notice
/// surfaces; this string must not restate them.
fn describe(self, cap_bytes: u64, workspace: &Path) -> String {
let workspace = display_workspace_for_gate(workspace);
match self {
Self::TooLarge => format!(
"{GATE_TOO_LARGE_MARKER}: over {} bytes of snapshot-eligible content in {}",
"{GATE_TOO_LARGE_MARKER}: over {} bytes of snapshot-eligible content in {workspace}",
cap_bytes,
workspace.display()
),
Self::TooManyEntries => format!(
"{GATE_TOO_MANY_ENTRIES_MARKER}: over {SIZE_WALK_MAX_ENTRIES} snapshot-eligible entries in {}",
workspace.display()
"{GATE_TOO_MANY_ENTRIES_MARKER}: over {SIZE_WALK_MAX_ENTRIES} snapshot-eligible entries in {workspace}"
),
}
}
@@ -277,7 +287,7 @@ impl SnapshotRepo {
io::ErrorKind::InvalidInput,
format!(
"{GATE_UNSAFE_LOCATION_MARKER} for {reason}: {}",
work_tree.display()
display_workspace_for_gate(&work_tree)
),
));
}
@@ -1994,8 +2004,13 @@ mod tests {
msg.contains(GATE_TOO_LARGE_MARKER),
"error must call out the size cap; got: {msg}"
);
let named_owned = workspace.display().to_string();
let named = named_owned
.strip_prefix(r"\\?\")
.or_else(|| named_owned.strip_prefix("//?/"))
.unwrap_or(named_owned.as_str());
assert!(
msg.contains(&workspace.display().to_string()),
msg.contains(named),
"error must name the workspace it refused; got: {msg}"
);
// The remedy belongs to the localized notice. Repeating it here is
+1 -2
View File
@@ -2923,8 +2923,7 @@ async fn read_file_denies_ambient_home_config_even_when_codewhale_home_is_reloca
let _home = crate::test_support::EnvVarGuard::set("HOME", home.path());
let _userprofile = crate::test_support::EnvVarGuard::set("USERPROFILE", home.path());
// The override points somewhere else entirely — the ambient store must stay guarded.
let _codewhale_home =
crate::test_support::EnvVarGuard::set("CODEWHALE_HOME", relocated.path());
let _codewhale_home = crate::test_support::EnvVarGuard::set("CODEWHALE_HOME", relocated.path());
let _config_path = crate::test_support::EnvVarGuard::remove("CODEWHALE_CONFIG_PATH");
let _legacy_config_path = crate::test_support::EnvVarGuard::remove("DEEPSEEK_CONFIG_PATH");
+12 -6
View File
@@ -13297,7 +13297,9 @@ async fn turn_end_parking_preserves_a_step_zero_resumable_checkpoint() {
panic!("turn-end parking must interrupt resumably: {result:?}");
};
assert!(
reason.contains(&format!("resume_from=\"{agent_id}\"")),
reason.contains(&format!(
"agent(action=\"followup\", agent_id=\"{agent_id}\""
)),
"{reason}"
);
assert_eq!(result.steps_taken, 0);
@@ -13317,9 +13319,9 @@ async fn turn_end_parking_preserves_a_step_zero_resumable_checkpoint() {
.as_ref()
.expect("parked work must carry an actionable recovery instruction");
assert!(
recovery
.question
.contains(&format!("resume_from=\"{agent_id}\"")),
recovery.question.contains(&format!(
"agent(action=\"followup\", agent_id=\"{agent_id}\""
)),
"{}",
recovery.question
);
@@ -13329,7 +13331,9 @@ async fn turn_end_parking_preserves_a_step_zero_resumable_checkpoint() {
agent_id: ref delivered_agent_id,
reason: ref delivered_reason,
} if delivered_agent_id == agent_id
&& delivered_reason.contains(&format!("resume_from=\"{agent_id}\""))
&& delivered_reason.contains(&format!(
"agent(action=\"followup\", agent_id=\"{agent_id}\""
))
));
let (explicit_status, _, _, explicit_needs_input, explicit_worker_status, _) =
@@ -16260,7 +16264,9 @@ async fn queued_turn_owned_child_parks_without_a_false_start_transition() {
message,
MailboxMessage::Interrupted { agent_id, reason }
if agent_id == "agent_queued_turn_end_park"
&& reason.contains("resume_from=\"agent_queued_turn_end_park\"")
&& reason.contains(
"agent(action=\"followup\", agent_id=\"agent_queued_turn_end_park\""
)
)),
"parking must publish an actionable interrupted receipt: {messages:?}"
);
+27 -9
View File
@@ -70,15 +70,33 @@ pub fn visible_slash_menu_entries(app: &App, limit: usize) -> Vec<SlashMenuEntry
effort_entries.push(SlashMenuEntry {
name: format!("/effort {}", label),
description: match eff {
crate::reasoning_preference::ReasoningEffort::Auto => "choose per turn".into(),
crate::reasoning_preference::ReasoningEffort::Off => "no extra reasoning".into(),
crate::reasoning_preference::ReasoningEffort::Minimal => "minimal reasoning".into(),
crate::reasoning_preference::ReasoningEffort::Low => "lighter reasoning".into(),
crate::reasoning_preference::ReasoningEffort::Medium => "balanced reasoning".into(),
crate::reasoning_preference::ReasoningEffort::High => "deeper reasoning".into(),
crate::reasoning_preference::ReasoningEffort::XHigh => "extra-high reasoning".into(),
crate::reasoning_preference::ReasoningEffort::Ultra => "ultra reasoning".into(),
crate::reasoning_preference::ReasoningEffort::Max => "maximum reasoning".into(),
crate::reasoning_preference::ReasoningEffort::Auto => {
"choose per turn".into()
}
crate::reasoning_preference::ReasoningEffort::Off => {
"no extra reasoning".into()
}
crate::reasoning_preference::ReasoningEffort::Minimal => {
"minimal reasoning".into()
}
crate::reasoning_preference::ReasoningEffort::Low => {
"lighter reasoning".into()
}
crate::reasoning_preference::ReasoningEffort::Medium => {
"balanced reasoning".into()
}
crate::reasoning_preference::ReasoningEffort::High => {
"deeper reasoning".into()
}
crate::reasoning_preference::ReasoningEffort::XHigh => {
"extra-high reasoning".into()
}
crate::reasoning_preference::ReasoningEffort::Ultra => {
"ultra reasoning".into()
}
crate::reasoning_preference::ReasoningEffort::Max => {
"maximum reasoning".into()
}
},
is_skill: false,
alias_hint: None,