Skip to content

fix(forge): use hyphen notation for command refs in Forge integration#2462

Open
ericnoam wants to merge 2 commits intogithub:mainfrom
toxicafunk:fix/forge-dot-notation-command-refs
Open

fix(forge): use hyphen notation for command refs in Forge integration#2462
ericnoam wants to merge 2 commits intogithub:mainfrom
toxicafunk:fix/forge-dot-notation-command-refs

Conversation

@ericnoam
Copy link
Copy Markdown
Contributor

@ericnoam ericnoam commented May 6, 2026

Problem

Dot-notation command invocations (e.g. /speckit.specify) generated inside Forge command files are misinterpreted by ZSH as file-path operations, breaking the workflow for ZSH users.

Root Cause

The ForgeIntegration class was not declaring an invoke_separator, so it fell back to the default "." (dot) separator used by all other agents. As a result, every __SPECKIT_COMMAND_*__ token and any hard-coded /speckit.foo reference in extension templates resolved to dot-notation inside Forge's generated .forge/commands/ files.

Changes

src/specify_cli/integrations/forge/__init__.py

  • Add invoke_separator = "-" class attribute to ForgeIntegration so effective_invoke_separator() returns "-" for shared-template installs.
  • Add "invoke_separator": "-" to ForgeIntegration.registrar_config so agents.py CommandRegistrar can resolve refs with the correct separator.
  • Pass invoke_separator to process_template() in ForgeIntegration.setup() so all .forge/commands/*.md bodies use /speckit-foo notation.

extensions/git/commands/speckit.git.feature.md

  • Replace the literal /speckit.specify reference with the __SPECKIT_COMMAND_SPECIFY__ token so every agent resolves the reference through its own separator (dot for most agents, hyphen for Forge).

src/specify_cli/agents.py

  • Apply resolve_command_refs re.sub in register_commands() after argument-placeholder substitution so extension commands registered for Forge get /speckit-foo refs; all other agents continue to get /speckit.foo.

tests/integrations/test_integration_forge.py

  • Add test_command_refs_use_hyphen_notation: asserts all generated Forge command files contain /speckit-<cmd> and none contain /speckit.<cmd>.
  • Add test_git_extension_command_uses_hyphen_notation: end-to-end test via CommandRegistrar that the git extension's speckit.git.feature command resolves to /speckit-specify when installed for Forge.
  • Extend test_templates_are_processed with an inline assertion that no dot-notation refs survive template processing.

Testing

All 25 Forge integration tests pass:

pytest tests/integrations/test_integration_forge.py -v
25 passed in 0.23s

ZSH Compatibility

Hyphen-notation (/speckit-specify) works correctly in all shells. Dot-notation (/speckit.specify) causes ZSH to interpret the token as a file-path lookup, silently failing the command invocation.

- Add invoke_separator = "-" class attribute to ForgeIntegration so
  effective_invoke_separator() returns "-" for shared-template installs
- Add "invoke_separator": "-" to ForgeIntegration.registrar_config so
  agents.py CommandRegistrar can resolve refs with the correct separator
- Pass invoke_separator to process_template() in ForgeIntegration.setup()
  so all .forge/commands/*.md bodies use /speckit-foo notation
- Replace literal /speckit.specify with __SPECKIT_COMMAND_SPECIFY__ in
  extensions/git/commands/speckit.git.feature.md so every agent resolves
  the reference through its own separator
- Apply resolve_command_refs re.sub in agents.py register_commands() after
  argument-placeholder substitution so extension commands registered for
  Forge get /speckit-foo refs; all other agents continue to get /speckit.foo

Fixes ZSH compatibility: dot-notation command invocations (/speckit.specify)
are misinterpreted by ZSH as file-path operations; hyphen notation
(/speckit-specify) works correctly in all shells.
Copilot AI review requested due to automatic review settings May 6, 2026 07:28
@ericnoam ericnoam requested a review from mnriem as a code owner May 6, 2026 07:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Forge integration to emit hyphen-based slash command references (e.g., /speckit-plan) instead of dot notation (e.g., /speckit.plan) to avoid ZSH misinterpreting dotted invocations. It also introduces token-based command references in an extension command and updates the command registrar to resolve those tokens per-agent.

Changes:

  • Set Forge’s invoke separator to - and pass it through template processing so generated .forge/commands/*.md files use /speckit-<cmd> references.
  • Replace a hard-coded /speckit.specify reference in the git extension with a __SPECKIT_COMMAND_SPECIFY__ token.
  • Add command-ref token resolution to CommandRegistrar.register_commands() and extend Forge tests to ensure dot notation does not appear in generated Forge commands.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/specify_cli/integrations/forge/__init__.py Configures Forge to use - as the invoke separator and passes it into template processing.
src/specify_cli/agents.py Adds __SPECKIT_COMMAND_*__ token resolution during extension command registration.
extensions/git/commands/speckit.git.feature.md Switches from a hard-coded command ref to a tokenized ref for agent-specific resolution.
tests/integrations/test_integration_forge.py Adds/extends tests to assert Forge command refs are hyphenated and extension command refs resolve correctly for Forge.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/specify_cli/agents.py Outdated
…GENT_CONFIGS

Skills-based agents (claude, codex, kimi, …) inherit invoke_separator="-"
from SkillsIntegration but do not repeat it in their registrar_config dicts.
_build_agent_configs() was copying registrar_config verbatim, so
register_commands() fell back to "." when resolving __SPECKIT_COMMAND_*__
tokens for those agents — emitting /speckit.specify instead of the correct
/speckit-specify for extension commands like speckit.git.feature.

Fix: after copying registrar_config, inject invoke_separator from the
integration's class attribute when it is not already declared explicitly.
This makes the integration class the single source of truth for all agents,
without requiring each SkillsIntegration subclass to duplicate the field.

Also replace the inline re.sub in register_commands() with a call to
IntegrationBase.resolve_command_refs() (deferred import to avoid the
existing circular dependency) so token-resolution logic is not duplicated.

Adds two tests in test_agent_config_consistency.py:
- test_skills_agents_have_hyphen_invoke_separator_in_agent_configs: asserts
  every /SKILL.md agent has invoke_separator="-" in AGENT_CONFIGS.
- test_skills_agent_command_token_resolves_with_hyphen: end-to-end check via
  CommandRegistrar that the git extension's speckit.git.feature command is
  installed for Claude with /speckit-specify (not /speckit.specify).

Addresses review comment on PR github#2462.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

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.

2 participants