From 47adc3c19e65f79f75e6055d8f699a9946f32253 Mon Sep 17 00:00:00 2001 From: kartsan03 Date: Tue, 29 Sep 2026 11:11:57 +0000 Subject: [PATCH] fix(integrations): drop invalid --model/--output-format flags from Vibe dispatch The Mistral Vibe CLI has no --model and no --output-format flag, so the inherited SkillsIntegration.build_exec_args() made a dispatched step exit 2 at argument parsing whenever a model was configured or JSON output was requested. Keep -p, map output_json to Vibe's own --output json, and drop model: Vibe picks its model from active_model in its config. Assisted-by: Claude Code (model: Claude Opus 5.5, autonomous) --- src/specify_cli/integrations/vibe/__init__.py | 28 +++++++++++ tests/integrations/test_integration_vibe.py | 48 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/src/specify_cli/integrations/vibe/__init__.py b/src/specify_cli/integrations/vibe/__init__.py index 44ae6f96df..e0d0957d9a 100644 --- a/src/specify_cli/integrations/vibe/__init__.py +++ b/src/specify_cli/integrations/vibe/__init__.py @@ -6,6 +6,7 @@ from __future__ import annotations +from collections.abc import Mapping, Sequence from pathlib import Path from typing import Any @@ -79,6 +80,33 @@ def options(cls) -> list[IntegrationOption]: ) return opts + def build_exec_args( + self, + prompt: str, + *, + model: str | None = None, + output_json: bool = True, + integration_args: Sequence[str] | None = None, + integration_options: Mapping[str, Any] | None = None, + project_root: Path | None = None, + ) -> list[str] | None: + """Build CLI arguments for non-interactive ``vibe`` execution. + + ``SkillsIntegration``'s default appends ``--model`` and + ``--output-format``, neither of which exists in the Vibe CLI, so a + dispatched step exits 2 at argument parsing whenever either flag ends + up appended (a configured ``model``, or ``output_json=True``). Vibe's + structured output is ``--output json``. ``model`` is deliberately + dropped: Vibe has no per-invocation model flag and selects its model + out of band via ``active_model`` in its config (or ``VIBE_ACTIVE_MODEL``). + """ + self.validate_runtime_config(integration_args, integration_options) + args = [self._resolve_executable(), "-p", prompt] + self._apply_extra_args_env_var(args) + if output_json: + args.extend(["--output", "json"]) + return args + def _render_skill(self, template_name: str, frontmatter: dict[str, Any], body: str) -> str: """Render a processed command template as a Vibe skill.""" skill_name = f"speckit-{template_name.replace('.', '-')}" diff --git a/tests/integrations/test_integration_vibe.py b/tests/integrations/test_integration_vibe.py index 8bd26fe75f..c2189a4b84 100644 --- a/tests/integrations/test_integration_vibe.py +++ b/tests/integrations/test_integration_vibe.py @@ -128,6 +128,54 @@ def test_skills_do_not_have_argument_hint(self, tmp_path): f"{f.parent.name}/SKILL.md unexpectedly has argument-hint frontmatter" ) + def test_build_exec_args_uses_prompt_mode(self): + integration = get_integration("vibe") + + args = integration.build_exec_args( + "/speckit-specify build a login page", + output_json=False, + ) + + assert args == ["vibe", "-p", "/speckit-specify build a login page"] + + def test_build_exec_args_requests_json_output(self): + """Vibe's structured output is `--output json`; it has no `--output-format`.""" + integration = get_integration("vibe") + + args = integration.build_exec_args("/speckit-plan add OAuth", output_json=True) + + assert args == ["vibe", "-p", "/speckit-plan add OAuth", "--output", "json"] + assert "--output-format" not in args + + def test_build_exec_args_omits_model_flag(self): + """Vibe has no model flag; passing `--model` exits 2 at argument parsing.""" + integration = get_integration("vibe") + + args = integration.build_exec_args( + "explain this repository", + model="mistral-medium-latest", + output_json=False, + ) + + assert args == ["vibe", "-p", "explain this repository"] + assert "--model" not in args + assert "mistral-medium-latest" not in args + + def test_build_exec_args_applies_extra_args(self, monkeypatch): + monkeypatch.setenv("SPECKIT_INTEGRATION_VIBE_EXTRA_ARGS", "--auto-approve") + integration = get_integration("vibe") + + args = integration.build_exec_args("check the build", output_json=True) + + assert args == [ + "vibe", + "-p", + "check the build", + "--auto-approve", + "--output", + "json", + ] + class TestVibeTomlMerging: """Behavioral tests for the toml-vibe hooks.toml generation and cleanup."""