diff --git a/src/specify_cli/integrations/cline/__init__.py b/src/specify_cli/integrations/cline/__init__.py index 248f44d54d..c3ea3cc409 100644 --- a/src/specify_cli/integrations/cline/__init__.py +++ b/src/specify_cli/integrations/cline/__init__.py @@ -138,8 +138,14 @@ def _rewrite_handoff_references(content: str) -> str: content, ) - def post_process_content(self, content: str) -> str: - """Apply Cline-specific transformations to command content.""" + def post_process_command_content(self, content: str) -> str: + """Apply Cline-specific transformations to command content. + + Overrides the ``IntegrationBase`` hook of the same name so that + ``CommandRegistrar.register_commands()`` (which dispatches to + ``post_process_command_content``) applies these transforms to + extension/preset command files too, not just core commands. + """ updated = self._inject_hook_command_note(content) updated = self._rewrite_handoff_references(updated) return updated @@ -169,7 +175,7 @@ def setup( content_bytes = path.read_bytes() content = content_bytes.decode("utf-8") - updated = self.post_process_content(content) + updated = self.post_process_command_content(content) if updated != content: path.write_bytes(updated.encode("utf-8")) diff --git a/tests/test_post_process.py b/tests/test_post_process.py index 34e947e9fb..12003f6a07 100644 --- a/tests/test_post_process.py +++ b/tests/test_post_process.py @@ -243,3 +243,34 @@ def test_plain_template_unchanged( assert output_file.exists(), f"Output file missing for {agent}" content = output_file.read_text(encoding="utf-8") assert body_text.strip() in content, f"Body text missing in {agent} output" + + +class TestClineRealPostProcess: + """Cline's real command-content transforms (hook-command note + handoff + dot->hyphen rewrite) must run for extension/preset commands registered via + CommandRegistrar. This exercises the REAL method (not a monkeypatched + marker), so it fails if Cline's override does not match the base hook name + the registrar dispatches to (post_process_command_content).""" + + def test_cline_transforms_applied_via_registrar( + self, tmp_path, registrar, ext_dir + ): + ext, cmd_dir = ext_dir + body = ( + "- For each executable hook, output the following:\n" + "agent: speckit.foo\n" + ) + _write_cmd(cmd_dir, body=body) + + commands = [{"name": "speckit.test.review", "file": "commands/review.md"}] + registrar.register_commands("cline", commands, "test-ext", ext, tmp_path) + + outputs = list((tmp_path / ".clinerules" / "workflows").rglob("*.md")) + assert outputs, "no cline command file was written" + content = outputs[0].read_text(encoding="utf-8") + + # _inject_hook_command_note fired (its note text contains "replace dots") + assert "replace dots" in content + # _rewrite_handoff_references rewrote the dotted agent handoff + assert "agent: speckit-foo" in content + assert "agent: speckit.foo" not in content