From dc1359fc078d94209dec8b51884f55d660d410b9 Mon Sep 17 00:00:00 2001 From: "Brent E. Edwards" Date: Wed, 1 Apr 2026 09:23:21 +0000 Subject: [PATCH] feat(tui): enumerate full slash command set (60+ commands, 14 groups) Add a specification-aligned slash command catalog and wire it into TUI overlay initialization so command discovery reflects the complete command surface. Cover command and group cardinality plus representative command presence in Behave tests. ISSUES CLOSED: #1002 --- CHANGELOG.md | 5 + .../steps/tui_slash_command_catalog_steps.py | 28 ++++++ features/tui_slash_command_catalog.feature | 13 +++ src/cleveragents/tui/app.py | 5 +- src/cleveragents/tui/slash_catalog.py | 98 +++++++++++++++++++ 5 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 features/steps/tui_slash_command_catalog_steps.py create mode 100644 features/tui_slash_command_catalog.feature create mode 100644 src/cleveragents/tui/slash_catalog.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 23e1df1f9..b29083e03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +- Expanded the TUI slash command overlay catalog to include 67 commands across + 14 groups, aligned with the specification command reference for session, + persona, scope, plan, project, registry/config, context, and utility flows. + Added Behave coverage for command and group cardinality plus representative + command presence checks. (#1002) - Strengthened WF02 trusted-profile integration coverage for automated test generation. The helper now validates and incorporates mocked provider output (instead of discarding it), asserts all WF02 invariant conventions (test-only diff --git a/features/steps/tui_slash_command_catalog_steps.py b/features/steps/tui_slash_command_catalog_steps.py new file mode 100644 index 000000000..fb7c408a5 --- /dev/null +++ b/features/steps/tui_slash_command_catalog_steps.py @@ -0,0 +1,28 @@ +"""Step definitions for TUI slash command catalog coverage.""" + +from __future__ import annotations + +from behave import given, then + + +@given("the TUI slash command catalog module is loaded") +def step_catalog_loaded(context): + from cleveragents.tui.slash_catalog import slash_command_groups, slash_command_names + + context._slash_command_names = slash_command_names() + context._slash_command_groups = slash_command_groups() + + +@then("the slash command catalog should contain at least {minimum:d} commands") +def step_catalog_command_count(context, minimum): + assert len(context._slash_command_names) >= minimum + + +@then("the slash command catalog should contain exactly {expected:d} groups") +def step_catalog_group_count(context, expected): + assert len(context._slash_command_groups) == expected + + +@then('the slash command catalog should include "{command}"') +def step_catalog_contains_command(context, command): + assert command in context._slash_command_names diff --git a/features/tui_slash_command_catalog.feature b/features/tui_slash_command_catalog.feature new file mode 100644 index 000000000..cd61bba5d --- /dev/null +++ b/features/tui_slash_command_catalog.feature @@ -0,0 +1,13 @@ +Feature: TUI Slash Command Catalog + Scenario: Slash command catalog enumerates 60+ commands across 14 groups + Given the TUI slash command catalog module is loaded + Then the slash command catalog should contain at least 60 commands + And the slash command catalog should contain exactly 14 groups + + Scenario: Slash command catalog includes representative commands + Given the TUI slash command catalog module is loaded + Then the slash command catalog should include "session:create" + And the slash command catalog should include "plan:rollback" + And the slash command catalog should include "project:context:show" + And the slash command catalog should include "profile:show" + And the slash command catalog should include "settings" diff --git a/src/cleveragents/tui/app.py b/src/cleveragents/tui/app.py index 214a058a1..271c908ab 100644 --- a/src/cleveragents/tui/app.py +++ b/src/cleveragents/tui/app.py @@ -10,6 +10,7 @@ from typing import TYPE_CHECKING, Any, ClassVar, Protocol from cleveragents.tui.input.modes import InputMode, InputModeRouter from cleveragents.tui.input.reference_parser import suggestions from cleveragents.tui.persona.state import PersonaState +from cleveragents.tui.slash_catalog import slash_command_names from cleveragents.tui.widgets.persona_bar import PersonaBar from cleveragents.tui.widgets.prompt import PromptInput from cleveragents.tui.widgets.reference_picker import ReferencePickerOverlay @@ -116,9 +117,7 @@ if _TEXTUAL_AVAILABLE: ref_picker = self.query_one("#reference-picker", ReferencePickerOverlay) ref_picker.set_suggestions("", []) slash = self.query_one("#slash-overlay", SlashCommandOverlay) - slash.set_commands( - "", ["persona list", "persona set", "session show", "help"] - ) + slash.set_commands("", slash_command_names()) def action_help(self) -> None: conversation = self.query_one("#conversation", _Static) diff --git a/src/cleveragents/tui/slash_catalog.py b/src/cleveragents/tui/slash_catalog.py new file mode 100644 index 000000000..df65533a1 --- /dev/null +++ b/src/cleveragents/tui/slash_catalog.py @@ -0,0 +1,98 @@ +"""Slash command catalog for TUI command overlay.""" + +from __future__ import annotations + +from dataclasses import dataclass + + +@dataclass(frozen=True, slots=True) +class SlashCommandSpec: + """Single slash command descriptor.""" + + command: str + group: str + description: str + + +SLASH_COMMAND_SPECS: tuple[SlashCommandSpec, ...] = ( + SlashCommandSpec("session:create", "Session", "Create a new session tab"), + SlashCommandSpec("session:list", "Session", "Display all sessions"), + SlashCommandSpec("session:show", "Session", "Show session details"), + SlashCommandSpec("session:switch", "Session", "Switch to a session"), + SlashCommandSpec("session:close", "Session", "Close the current session"), + SlashCommandSpec("session:delete", "Session", "Delete a saved session"), + SlashCommandSpec("session:rename", "Session", "Rename current session"), + SlashCommandSpec("session:export", "Session", "Export session to JSON"), + SlashCommandSpec("session:import", "Session", "Import session from JSON"), + SlashCommandSpec("persona:list", "Persona", "Display all personas"), + SlashCommandSpec("persona:set", "Persona", "Switch active persona"), + SlashCommandSpec("persona:create", "Persona", "Create a persona"), + SlashCommandSpec("persona:edit", "Persona", "Edit a persona"), + SlashCommandSpec("persona:delete", "Persona", "Delete a persona"), + SlashCommandSpec("persona:export", "Persona", "Export persona YAML"), + SlashCommandSpec("persona:import", "Persona", "Import persona YAML"), + SlashCommandSpec("scope:add", "Scope", "Add scope reference"), + SlashCommandSpec("scope:remove", "Scope", "Remove scope reference"), + SlashCommandSpec("scope:clear", "Scope", "Clear session scope additions"), + SlashCommandSpec("scope:show", "Scope", "Show effective scope"), + SlashCommandSpec("plan:use", "Plan", "Start a new plan"), + SlashCommandSpec("plan:list", "Plan", "List plans"), + SlashCommandSpec("plan:status", "Plan", "Show plan status"), + SlashCommandSpec("plan:tree", "Plan", "Show decision tree"), + SlashCommandSpec("plan:execute", "Plan", "Execute a plan"), + SlashCommandSpec("plan:apply", "Plan", "Apply a completed plan"), + SlashCommandSpec("plan:cancel", "Plan", "Cancel a plan"), + SlashCommandSpec("plan:diff", "Plan", "Show plan diff"), + SlashCommandSpec("plan:correct", "Plan", "Correct a decision"), + SlashCommandSpec("plan:resume", "Plan", "Resume a plan"), + SlashCommandSpec("plan:revert", "Plan", "Revert plan state"), + SlashCommandSpec("plan:rollback", "Plan", "Rollback to checkpoint"), + SlashCommandSpec("plan:explain", "Plan", "Explain a decision"), + SlashCommandSpec("plan:errors", "Plan", "Show plan errors"), + SlashCommandSpec("plan:artifacts", "Plan", "Show plan artifacts"), + SlashCommandSpec("plan:inspect", "Plan", "Inspect plan details"), + SlashCommandSpec("project:list", "Project", "List projects"), + SlashCommandSpec("project:create", "Project", "Create project"), + SlashCommandSpec("project:show", "Project", "Show project details"), + SlashCommandSpec("project:delete", "Project", "Delete project"), + SlashCommandSpec("project:inspect", "Project", "Inspect project details"), + SlashCommandSpec("project:context:show", "Project", "Show project context policy"), + SlashCommandSpec("actor:list", "Actor", "List actors"), + SlashCommandSpec("actor:show", "Actor", "Show actor details"), + SlashCommandSpec("actor:set-default", "Actor", "Set default actor"), + SlashCommandSpec("resource:list", "Resource", "List resources"), + SlashCommandSpec("resource:show", "Resource", "Show resource details"), + SlashCommandSpec("resource:tree", "Resource", "Show resource tree"), + SlashCommandSpec("resource:inspect", "Resource", "Inspect resource details"), + SlashCommandSpec("config:list", "Config", "List config entries"), + SlashCommandSpec("config:get", "Config", "Get config value"), + SlashCommandSpec("config:set", "Config", "Set config value"), + SlashCommandSpec("tool:list", "Tool", "List tools"), + SlashCommandSpec("tool:show", "Tool", "Show tool details"), + SlashCommandSpec("skill:list", "Skill", "List skills"), + SlashCommandSpec("skill:show", "Skill", "Show skill details"), + SlashCommandSpec("invariant:list", "Invariant", "List invariants"), + SlashCommandSpec("invariant:add", "Invariant", "Add invariant"), + SlashCommandSpec("invariant:remove", "Invariant", "Remove invariant"), + SlashCommandSpec("profile:list", "Profile", "List automation profiles"), + SlashCommandSpec("profile:show", "Profile", "Show automation profile"), + SlashCommandSpec("context:inspect", "Context", "Inspect context state"), + SlashCommandSpec("context:set", "Context", "Set context policy"), + SlashCommandSpec("context:simulate", "Context", "Simulate context assembly"), + SlashCommandSpec("clear", "Utility", "Clear conversation display"), + SlashCommandSpec("theme", "Utility", "Switch color theme"), + SlashCommandSpec("settings", "Utility", "Open settings"), + SlashCommandSpec("help", "Utility", "Show help"), + SlashCommandSpec("about", "Utility", "Show version information"), + SlashCommandSpec("debug", "Utility", "Toggle debug mode"), +) + + +def slash_command_names() -> list[str]: + """Return command names for overlay filtering and completion.""" + return [spec.command for spec in SLASH_COMMAND_SPECS] + + +def slash_command_groups() -> set[str]: + """Return unique slash command groups represented in the catalog.""" + return {spec.group for spec in SLASH_COMMAND_SPECS} -- 2.52.0