Skip to content

Reserve built-in slash-command names from prompt templates - #767

Open
baixinghao wants to merge 1 commit into
huggingface:mainfrom
baixinghao:fix/issue-460
Open

baixinghao wants to merge 1 commit into
huggingface:mainfrom
baixinghao:fix/issue-460

Conversation

@baixinghao

Copy link
Copy Markdown

Summary

Prompt templates are expanded before slash-command dispatch in CodingSession.handle_command(), so a template named new.md shadowed the built-in /new command (and likewise for every other built-in). Only prompts.md, skills.md, tools.md, and reload.md were previously reserved via a hard-coded list that could drift from the command registry.

This PR reserves every built-in command name and alias at resource-loading time: the reserved set is derived from create_default_command_registry() so it cannot drift, matching is case-insensitive on the filename stem, and each rejected template emits a resource diagnostic naming the file and the conflicting command (e.g. prompt template name is reserved by the built-in /exit command; template ignored). Non-conflicting templates keep the existing expansion-first behavior, at startup and after /reload.

Command-first dispatch was deliberately avoided: it would silently turn an existing new.md from a prompt expansion into a session reset. Load-time reservation makes the collision visible and deterministic instead.

Fixes #460.

Supersedes #468 (stale for ~3 months and conflicting with current main).

Changes

  • src/tau_coding/prompt_templates.py: replace the hard-coded _RESERVED_TEMPLATE_NAMES frozenset with a cached builtin_prompt_template_reservations() mapping (stem -> "/command") derived from create_default_command_registry() (names and aliases, case-folded). is_prompt_template_candidate() and the directory loader both consult it; the loader reports the exact conflicting invocation in the diagnostic. The registry import is lazy because tau_coding.commands already imports PromptTemplate from this module.
  • tests/test_prompt_templates.py: extend the reserved-name parametrization to new, quit, exit (and reload), keep the uppercase-filename case-insensitivity coverage, and add a drift guard asserting the reservation mapping covers every registry command name and alias.
  • tests/test_coding_session.py: add session-level tests proving /new still requests a new session and /quit//exit still exit while new.md, quit.md, and exit.md are rejected with diagnostics; that a non-conflicting template keeps expanding; and that the behavior holds after /reload. Since TUI autocomplete and the /prompts picker consume session.prompt_templates, a rejected template can never be advertised.
  • website/content/guides/skills-and-prompts.md: document the unified reservation policy (all built-in names and aliases, case-insensitive) and the migration path (new.md → rename to new-feature.md, invoke with /new-feature).
  • dev-notes/reserved-prompt-template-names.md: beginner-friendly note covering the resolution order, why silent command-first dispatch was avoided, why extension commands are out of scope (they are dynamic across /reload), and how to validate.

Tests

  • uv run pytest tests/test_prompt_templates.py tests/test_coding_session.py tests/test_commands.py tests/test_tui_autocomplete.py tests/test_project_trust.py — 333 passed, 5 skipped, 4 failed. The 4 failures (test_prompt_logs_unexpected_agent_call_exception, test_session_loads_tau_native_system_prompt_files, test_store_round_trip_is_sorted_and_nearest_decision_wins, test_tui_trust_modal_shows_boundary_parent_and_keyboard_cancel) reproduce identically on the clean base commit on Windows (verified via git stash); they are pre-existing and unrelated.
  • uv run pytest ... -k reserved — 13 passed (loader-level parametrized cases for 7 reserved stems including the exit alias, the registry drift guard, and 5 session-level startup//reload tests).
  • uv run ruff check . — all checks passed.
  • uv run ruff format --check . — 199 files already formatted.
  • uv run mypy — no new errors; the 14 reported errors are pre-existing Windows-only issues in tau_agent/session/storage.py and tau_coding/project_trust.py (msvcrt/fcntl platform APIs), and src/tau_coding/prompt_templates.py itself is clean.

Derive the reserved prompt-template stems from
create_default_command_registry() so every built-in command name and
alias (for example new, quit, exit) cannot be shadowed by a markdown
template. Colliding templates are skipped at load time with a resource
diagnostic naming the file and the conflicting command, keeping /new
and friends reachable at startup and after /reload. Non-conflicting
templates keep the existing expansion-first behavior.

Fixes huggingface#460.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reserve built-in slash-command names from prompt templates

1 participant