From 0c37b9f22745e5a3422c91a93a965f73e6e0ede6 Mon Sep 17 00:00:00 2001 From: Chaoqi Date: Sat, 10 Oct 2026 12:01:01 +0800 Subject: [PATCH 1/2] test(integrations): cover command names shown for docker-agent and junie Assisted-by: Claude Code (model: Claude Opus 5, autonomous) --- .../test_integration_docker_agent.py | 24 +++++++++++++++++++ tests/integrations/test_integration_junie.py | 24 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/tests/integrations/test_integration_docker_agent.py b/tests/integrations/test_integration_docker_agent.py index fa2207927f..173f75efda 100644 --- a/tests/integrations/test_integration_docker_agent.py +++ b/tests/integrations/test_integration_docker_agent.py @@ -16,6 +16,30 @@ class TestDockerAgentIntegration(SkillsIntegrationTests): def test_multi_install_is_opt_in(self): assert DockerAgentIntegration().multi_install_safe is False + def test_is_slash_skills_agent(self): + """Docker Agent only installs `speckit-/SKILL.md` skills, so the + helper must agree with its own renderer with or without `ai_skills` + (always slash, like Zed and Muse Code, which share that layout).""" + from specify_cli._invocation_style import is_slash_skills_agent + + assert DockerAgentIntegration().build_command_invocation("plan") == "/speckit-plan" + assert is_slash_skills_agent("docker-agent", True) is True + assert is_slash_skills_agent("docker-agent", False) is True + + def test_hook_invocation_renders_the_hyphenated_form(self, tmp_path, monkeypatch): + import specify_cli + from specify_cli.extensions import HookExecutor + + monkeypatch.setattr( + specify_cli, + "load_init_options", + lambda _root: {"ai": "docker-agent", "ai_skills": True}, + ) + + rendered = HookExecutor(tmp_path)._render_hook_invocation("speckit.git.commit") + + assert rendered == "/speckit-git-commit" + def test_extra_args_are_applied_to_build_exec_args(monkeypatch): monkeypatch.setenv( diff --git a/tests/integrations/test_integration_junie.py b/tests/integrations/test_integration_junie.py index a6234ba734..e6fae0f69e 100644 --- a/tests/integrations/test_integration_junie.py +++ b/tests/integrations/test_integration_junie.py @@ -109,6 +109,30 @@ def test_junie_hook_instruction_injection_no_trailing_newline(self): # Instruction stays on its own line rather than being mashed onto the note. assert "\n- For each executable hook, output the following:" in injected + def test_init_next_steps_show_hyphenated_commands(self, tmp_path): + """Next Steps must list the `/speckit-` commands Junie installs.""" + from typer.testing import CliRunner + + from specify_cli import app + + result = CliRunner().invoke( + app, + [ + "init", + str(tmp_path / "junie-next-steps"), + "--integration", + self.KEY, + "--script", + "sh", + "--ignore-agent-tools", + ], + catch_exceptions=False, + ) + + assert result.exit_code == 0, result.output + assert "/speckit-plan" in result.output + assert "/speckit.plan" not in result.output + # -- Overrides for MarkdownIntegrationTests --------------------------- def test_setup_creates_files(self, tmp_path): From cba57604bbdf49aa689902fed9532407403b5bc4 Mon Sep 17 00:00:00 2001 From: Chaoqi Date: Sat, 10 Oct 2026 12:01:13 +0800 Subject: [PATCH 2/2] fix(integrations): show hyphenated command names for docker-agent and junie Both agents register `/speckit-` commands, and their own `build_command_invocation` returns that form, but Spec Kit showed users the dotted `/speckit.` names in two places: - docker-agent was missing from `ALWAYS_SLASH_AGENTS`, so the `init` next-steps banner and extension hook invocations used dotted names (#4137 fixed the same gap for alquimia). - The `init` banner special-cased cline and forge but not junie, which installs hyphenated commands the same way. Assisted-by: Claude Code (model: Claude Opus 5, autonomous) --- src/specify_cli/_invocation_style.py | 13 ++++++++++++- src/specify_cli/command_init.py | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/specify_cli/_invocation_style.py b/src/specify_cli/_invocation_style.py index 3c867cc026..86926e23ba 100644 --- a/src/specify_cli/_invocation_style.py +++ b/src/specify_cli/_invocation_style.py @@ -13,7 +13,18 @@ # Agents that always render /speckit-, regardless of ai_skills. ALWAYS_SLASH_AGENTS: frozenset[str] = frozenset( - {"devin", "droid", "dsh", "grok", "mcode", "muse", "qodercli", "trae", "zed"} + { + "devin", + "docker-agent", + "droid", + "dsh", + "grok", + "mcode", + "muse", + "qodercli", + "trae", + "zed", + } ) # Agents that render /speckit- only when ai_skills is enabled. diff --git a/src/specify_cli/command_init.py b/src/specify_cli/command_init.py index 605dd7ed92..d89835cc5f 100644 --- a/src/specify_cli/command_init.py +++ b/src/specify_cli/command_init.py @@ -1051,6 +1051,7 @@ def init( dsh_skill_mode = selected_ai == "dsh" and _is_skills_integration cline_skill_mode = selected_ai == "cline" forge_skill_mode = selected_ai == "forge" + junie_skill_mode = selected_ai == "junie" bob_skill_mode = selected_ai == "bob" and _is_skills_integration native_skill_mode = ( codex_skill_mode @@ -1146,6 +1147,7 @@ def _display_cmd(name: str) -> str: _is_slash_skills_agent(selected_ai, _ai_skills_enabled) or cline_skill_mode or forge_skill_mode + or junie_skill_mode ): return f"/speckit-{name}" return f"/speckit.{name}"