fix(extensions): hyphenate command names in the Forge post-install listing (#3669)

After `specify extension add`, the "Provided commands" summary hyphenated
command names only for Cline. For a Forge project the names were printed in
dotted form (e.g. `speckit.test-ext.hello`), but Forge registers them
hyphenated (`speckit-test-ext-hello`), so the printed names didn't match
what the user actually invokes in Forge.

Extend the existing Cline handling to Forge via `format_forge_command_name`,
completing the Forge command-name parity already fixed for hook invocations
(#3641) and the init next-steps panel (#3642).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ali jawwad
2026-07-23 19:36:04 +05:00
committed by GitHub
parent f5be0fffc8
commit 88b3230e2e
2 changed files with 38 additions and 1 deletions

View File

@@ -623,16 +623,22 @@ def extension_add(
for warning in manifest.warnings:
console.print(f"\n[yellow]⚠ Compatibility warning:[/yellow] {_escape_markup(str(warning))}")
is_cline = load_init_options(project_root).get("ai") == "cline"
selected_ai = load_init_options(project_root).get("ai")
is_cline = selected_ai == "cline"
is_forge = selected_ai == "forge"
if is_cline:
from specify_cli.integrations.cline import format_cline_command_name
if is_forge:
from specify_cli.integrations.forge import format_forge_command_name
console.print("\n[bold cyan]Provided commands:[/bold cyan]")
for cmd in manifest.commands:
cmd_name = cmd['name']
if is_cline:
cmd_name = format_cline_command_name(cmd_name)
elif is_forge:
cmd_name = format_forge_command_name(cmd_name)
console.print(f"{_escape_markup(str(cmd_name))} - {_escape_markup(str(cmd.get('description', '')))}")
# Report agent skills registration

View File

@@ -9010,3 +9010,34 @@ class TestConfigManagerCrossExtensionEnvLeak:
# Must not raise; must fall back to the "no siblings" path.
cfg = ConfigManager(tmp_path, "testext")._get_env_config()
assert cfg == {"url": "v"}
def test_forge_extension_install_listing_hyphenates_command_names(
extension_dir, project_dir
):
"""The post-install 'Provided commands' listing must show hyphenated
/speckit-<name> command names for a Forge project (Forge registers
hyphenated names), mirroring the existing Cline handling."""
import json
import os
from typer.testing import CliRunner
from specify_cli import app
init_options = project_dir / ".specify" / "init-options.json"
init_options.write_text(json.dumps({"ai": "forge", "script": "sh"}))
old_cwd = os.getcwd()
try:
os.chdir(project_dir)
result = CliRunner().invoke(
app, ["extension", "add", str(extension_dir), "--dev"]
)
finally:
os.chdir(old_cwd)
assert result.exit_code == 0, result.output
# Forge registers hyphenated command names, so the summary must match.
assert "speckit-test-ext-hello" in result.output
assert "speckit.test-ext.hello" not in result.output