fix(cli): stop circular 'Did you mean /X?' for spec commands with no parse arm

23 spec-registered commands had no parse arm in validate_slash_command_input,
causing the circular error 'Unknown slash command: /X — Did you mean /X?'
when users typed them in --resume mode.

Two fixes:
1. Add the 23 confirmed parse-armless commands to STUB_COMMANDS (excluded
   from REPL completions and help output).
2. In resume dispatch, intercept STUB_COMMANDS before SlashCommand::parse
   and emit a clean '{error: "/X is not yet implemented in this build"}'
   instead of the confusing error from the Err parse path.

Affected: /allowed-tools, /bookmarks, /workspace, /reasoning, /budget,
/rate-limit, /changelog, /diagnostics, /metrics, /tool-details, /focus,
/unfocus, /pin, /unpin, /language, /profile, /max-tokens, /temperature,
/system-prompt, /notifications, /telemetry, /env, /project, plus ~40
additional unreachable spec names.

159 CLI tests pass.
This commit is contained in:
YeonGyu-Kim 2026-04-10 04:05:41 +09:00
parent 11e2353585
commit 1e14d59a71

View File

@ -2246,6 +2246,33 @@ fn resume_session(session_path: &Path, commands: &[String], output_format: CliOu
let mut session = session;
for raw_command in commands {
// Intercept spec commands that have no parse arm before calling
// SlashCommand::parse — they return Err(SlashCommandParseError) which
// formats as the confusing circular "Did you mean /X?" message.
// STUB_COMMANDS covers both completions-filtered stubs and parse-less
// spec entries; treat both as unsupported in resume mode.
{
let cmd_root = raw_command
.trim_start_matches('/')
.split_whitespace()
.next()
.unwrap_or("");
if STUB_COMMANDS.contains(&cmd_root) {
if output_format == CliOutputFormat::Json {
eprintln!(
"{}",
serde_json::json!({
"type": "error",
"error": format!("/{cmd_root} is not yet implemented in this build"),
"command": raw_command,
})
);
} else {
eprintln!("/{cmd_root} is not yet implemented in this build");
}
std::process::exit(2);
}
}
let command = match SlashCommand::parse(raw_command) {
Ok(Some(command)) => command,
Ok(None) => {
@ -7355,6 +7382,77 @@ const STUB_COMMANDS: &[&str] = &[
"tag",
"output-style",
"add-dir",
// Spec entries with no parse arm — produce circular "Did you mean" error
// without this guard. Adding here routes them to the proper unsupported
// message and excludes them from REPL completions / help.
"allowed-tools",
"bookmarks",
"workspace",
"reasoning",
"budget",
"rate-limit",
"changelog",
"diagnostics",
"metrics",
"tool-details",
"focus",
"unfocus",
"pin",
"unpin",
"language",
"profile",
"max-tokens",
"temperature",
"system-prompt",
"notifications",
"telemetry",
"env",
"project",
"terminal-setup",
"api-key",
"reset",
"undo",
"stop",
"retry",
"paste",
"screenshot",
"image",
"search",
"listen",
"speak",
"format",
"test",
"lint",
"build",
"run",
"git",
"stash",
"blame",
"log",
"cron",
"team",
"benchmark",
"migrate",
"templates",
"explain",
"refactor",
"docs",
"fix",
"perf",
"chat",
"web",
"map",
"symbols",
"references",
"definition",
"hover",
"autofix",
"multi",
"macro",
"alias",
"parallel",
"subagent",
"agent",
];
fn slash_command_completion_candidates_with_sessions(