Repository navigation
Reserve built-in slash-command names from prompt templates - #767
Open
baixinghao wants to merge 1 commit into
Open
baixinghao wants to merge 1 commit into
baixinghao wants to merge 1 commit into
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Prompt templates are expanded before slash-command dispatch in
CodingSession.handle_command(), so a template namednew.mdshadowed the built-in/newcommand (and likewise for every other built-in). Onlyprompts.md,skills.md,tools.md, andreload.mdwere 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.mdfrom 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_NAMESfrozenset with a cachedbuiltin_prompt_template_reservations()mapping (stem -> "/command") derived fromcreate_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 becausetau_coding.commandsalready importsPromptTemplatefrom this module.tests/test_prompt_templates.py: extend the reserved-name parametrization tonew,quit,exit(andreload), 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/newstill requests a new session and/quit//exitstill exit whilenew.md,quit.md, andexit.mdare rejected with diagnostics; that a non-conflicting template keeps expanding; and that the behavior holds after/reload. Since TUI autocomplete and the/promptspicker consumesession.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 tonew-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 viagit stash); they are pre-existing and unrelated.uv run pytest ... -k reserved— 13 passed (loader-level parametrized cases for 7 reserved stems including theexitalias, the registry drift guard, and 5 session-level startup//reloadtests).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 intau_agent/session/storage.pyandtau_coding/project_trust.py(msvcrt/fcntlplatform APIs), andsrc/tau_coding/prompt_templates.pyitself is clean.