tui: Allow extra o's in /goal command (#27814)

## Why

The TUI rejected playful `/goal` spellings such as `/goooooooooooal`,
even though Codex Apps accepts them for the World Cup promotion. This
keeps the TUI behavior consistent without changing how the canonical
command is presented.

## How it works

Built-in command lookup recognizes lowercase `go+al` as the existing
`goal` command after normal exact-name parsing fails. The command
catalog remains unchanged, so autocomplete continues to advertise
`/goal` normally.

## Verification

Added lookup-level and end-to-end TUI coverage for the flexible
spelling. The focused tests, scoped Clippy checks, and formatting pass.
The full `codex-tui` suite passed 2,833 of 2,835 tests; the two failing
guardian feature-flag tests reproduce unchanged on fresh `origin/main`.
This commit is contained in:
Brent Traut
2026-06-12 09:30:25 -07:00
committed by GitHub
Unverified
parent 096e5e76a2
commit d735ef162f
2 changed files with 17 additions and 5 deletions
+15 -3
View File
@@ -106,12 +106,16 @@ pub(crate) fn commands_for_input(
.collect()
}
/// Find a single built-in command by exact name, after applying feature gating.
/// Find a single built-in command by a recognized name or alias, after applying feature gating.
///
/// Side-conversation gating is intentionally enforced by dispatch rather than exact lookup so a
/// Side-conversation gating is intentionally enforced by dispatch rather than command lookup so a
/// typed command can produce a side-specific unavailable message while the popup still hides it.
pub(crate) fn find_builtin_command(name: &str, flags: BuiltinCommandFlags) -> Option<SlashCommand> {
let cmd = SlashCommand::from_str(name).ok()?;
let cmd = SlashCommand::from_str(name).ok().or_else(|| {
let repeated_os = name.strip_prefix('g')?.strip_suffix("al")?;
(!repeated_os.is_empty() && repeated_os.bytes().all(|byte| byte == b'o'))
.then_some(SlashCommand::Goal)
})?;
builtins_for_input(BuiltinCommandFlags {
side_conversation_active: false,
..flags
@@ -187,6 +191,14 @@ mod tests {
);
}
#[test]
fn goal_command_allows_extra_os_for_dispatch() {
assert_eq!(
find_builtin_command("goooooooooooal", all_enabled_flags()),
Some(SlashCommand::Goal)
);
}
#[test]
fn stop_command_resolves_for_dispatch() {
assert_eq!(
@@ -599,12 +599,12 @@ async fn inline_slash_command_is_available_from_local_recall_after_dispatch() {
}
#[tokio::test]
async fn goal_slash_command_emits_set_goal_event() {
async fn goal_slash_command_with_extra_os_emits_set_goal_event() {
let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
chat.set_feature_enabled(Feature::Goals, /*enabled*/ true);
let thread_id = ThreadId::new();
chat.thread_id = Some(thread_id);
let command = "/goal --tokens 98.5K improve benchmark coverage";
let command = "/goooooooooooal --tokens 98.5K improve benchmark coverage";
submit_composer_text(&mut chat, command);