refactor(commands): eliminate dead handlers and catalog duplicates

Dead code removed:
- ops.js: second 'rate' handler block (lines 248-256) — unreachable because
  the top-level import block at line 187 fires first and returns true
- autonomous.js: 'stop' handler (trimmed === 'stop') — /stop is in
  BASE_RUNTIME_COMMANDS, platform intercepts it before SF extension sees it
- core.js: 'session-rename' handler block — /rename is the canonical command;
  alias added zero value and created confusion

Catalog duplicates fixed:
- 'plan' appeared twice (line 85 + 248) with contradictory descriptions;
  merged into single entry describing both phase-trigger and artifact-promotion
- 'steer' appeared twice (line 72 + 167); removed the TUI-panel shortcut
  entry (Shift+Tab is a keyboard binding, not a slash command)

Discoverability fix:
- 'recover' was handled in ops.js but absent from catalog and manifest;
  added to both with accurate description (reconstruct DB hierarchy from
  markdown on disk)
- 'session-rename' removed from catalog and manifest; users use /rename

Check script improvements:
- HIDDEN_OR_ALIAS_SUBCOMMANDS now filters both directions of the catalog
  ↔ handler consistency check (was only filtering 'handled but missing from
  catalog', not 'catalog but no SF handler')
- Added 'stop' to HIDDEN_OR_ALIAS_SUBCOMMANDS with comment explaining it is
  platform-intercepted; removed 'recover' (now properly in catalog)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Mikael Hugo 2026-05-09 16:36:04 +02:00
parent aca13d1d9b
commit 6fb411df90
6 changed files with 14 additions and 34 deletions

View file

@ -42,8 +42,8 @@ const HIDDEN_OR_ALIAS_SUBCOMMANDS = new Set([
"auto",
"footer-config", // alias for /statusline
"h",
"recover",
"review-code", // alias for /rubber-duck
"stop", // platform-intercepted via BASE_RUNTIME_COMMANDS — never reaches SF handler
"undo-turn", // alias for /rewind
"wt",
]);
@ -304,7 +304,10 @@ function main() {
(command) => !catalogCommands.includes(command),
);
const unroutedCatalogCommands = catalogCommands.filter(
(command) => command !== "help" && !handledCommands.includes(command),
(command) =>
command !== "help" &&
!HIDDEN_OR_ALIAS_SUBCOMMANDS.has(command) &&
!handledCommands.includes(command),
);
if (missingCatalogCommands.length > 0) {
failures.push(

View file

@ -69,7 +69,6 @@ export const TOP_LEVEL_SUBCOMMANDS = [
{ cmd: "queue", desc: "Queue and reorder future milestones" },
{ cmd: "quick", desc: "Execute a quick task without full planning overhead" },
{ cmd: "discuss", desc: "Discuss architecture and decisions" },
{ cmd: "steer", desc: "Steerable autonomous panel (Shift+Tab)" },
{ cmd: "capture", desc: "Fire-and-forget thought capture" },
{ cmd: "debug", desc: "Create and inspect persistent /debug sessions" },
{ cmd: "scan", desc: "Run source and project scans" },
@ -82,7 +81,10 @@ export const TOP_LEVEL_SUBCOMMANDS = [
{ cmd: "todo", desc: "Triage root TODO.md dump into eval/backlog artifacts" },
{ cmd: "dispatch", desc: "Dispatch a specific phase directly" },
{ cmd: "research", desc: "Force research stage for current unit" },
{ cmd: "plan", desc: "Force planning stage for current unit" },
{
cmd: "plan",
desc: "Force planning stage; /plan promote|list|diff manages planning artifacts in docs/",
},
{ cmd: "implement", desc: "Force implementation stage for current unit" },
{ cmd: "history", desc: "View execution history" },
{
@ -165,6 +167,10 @@ export const TOP_LEVEL_SUBCOMMANDS = [
{ cmd: "migrate", desc: "Migrate a v1 .planning directory to .sf format" },
{ cmd: "remote", desc: "Configure remote question delivery" },
{ cmd: "steer", desc: "Hard-steer plan documents during execution" },
{
cmd: "recover",
desc: "Reconstruct DB hierarchy (milestones/slices/tasks) from rendered markdown on disk",
},
{ cmd: "inspect", desc: "Show SQLite DB diagnostics" },
{
cmd: "knowledge",
@ -244,10 +250,6 @@ export const TOP_LEVEL_SUBCOMMANDS = [
cmd: "eval-review",
desc: "Milestone-end evaluation review — audit slice coverage and infrastructure with scored EVAL-REVIEW.md",
},
{
cmd: "plan",
desc: "Promote planning artifacts from ~/.sf/ to docs/ (promote, list, diff)",
},
{
cmd: "experimental",
desc: "Toggle experimental feature flags (show/on/off/on <flag>/off <flag>)",
@ -255,10 +257,6 @@ export const TOP_LEVEL_SUBCOMMANDS = [
{ cmd: "diff", desc: "Show git diff (HEAD by default, --staged for staged)" },
{ cmd: "theme", desc: "Get or set the UI theme (dark/light/dim/auto)" },
{ cmd: "rename", desc: "Rename the current session (sets terminal title)" },
{
cmd: "session-rename",
desc: "Rename the current session by name (alias: /rename)",
},
{
cmd: "streamer-mode",
desc: "Toggle streamer mode — masks model names and quota details",

View file

@ -180,10 +180,6 @@ export async function handleAutonomousCommand(trimmed, ctx, pi) {
}
return true;
}
if (trimmed === "stop") {
await stopAutonomousRun(ctx, pi);
return true;
}
if (trimmed === "pause") {
await pauseAutonomousRun(ctx, pi);
return true;

View file

@ -851,14 +851,6 @@ export async function handleCoreCommand(trimmed, ctx, pi) {
);
return true;
}
if (trimmed === "session-rename" || trimmed.startsWith("session-rename ")) {
// Alias for /rename
await handleRenameCommand(
trimmed.replace(/^session-rename\s*/, "").trim(),
ctx,
);
return true;
}
if (trimmed === "sidekicks" || trimmed.startsWith("sidekicks ")) {
await handleSidekicksCommand(ctx);
return true;

View file

@ -245,15 +245,6 @@ export async function handleOpsCommand(trimmed, ctx, pi) {
await handleTodo(trimmed.replace(/^todo\s*/, "").trim(), ctx, pi);
return true;
}
if (trimmed === "rate" || trimmed.startsWith("rate ")) {
const { handleRate } = await import("../../commands-rate.js");
await handleRate(
trimmed.replace(/^rate\s*/, "").trim(),
ctx,
process.cwd(),
);
return true;
}
if (trimmed === "config") {
await handleConfig(ctx);
return true;

View file

@ -105,6 +105,7 @@
"queue",
"quick",
"rate",
"recover",
"remote",
"rename",
"repair",
@ -118,7 +119,6 @@
"scan",
"schedule",
"search",
"session-rename",
"session-report",
"setup",
"ship",