Skip to content

Commit fe971dc

Browse files
RaycarlLeiclaude
andauthored
fix(integrations): pass the Junie dispatch prompt via --task (#5065)
JunieIntegration inherited MarkdownIntegration.build_exec_args(), which passes the prompt as -p <prompt>. Junie's -p is the short form of --project <path>, so every dispatch, including the built-in workflow command and prompt steps in text mode, asked Junie to run in a project directory named after the prompt and gave it no task. Junie takes a non-interactive task as a positional argument or --task. Override build_exec_args() to pass the prompt with --task. The base requires_cli guard and argument order (EXTRA_ARGS before --model) are unchanged, and --model and --output-format json are flags Junie documents. docs/integrations/junie.md named -p and now names --task. Assisted-by: Claude Code (model: Claude Opus 5.5, autonomous) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 758e8d5 commit fe971dc

3 files changed

Lines changed: 91 additions & 1 deletion

File tree

‎docs/integrations/junie.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ hyphenated names.
2929

3030
## Workflow Dispatch
3131

32-
Workflow steps use `junie -p <prompt>`, with `--model` when configured and
32+
Workflow steps use `junie --task <prompt>`, with `--model` when configured and
3333
`--output-format json` when structured output is requested.
3434
There are no integration-specific setup options.

‎src/specify_cli/integrations/junie/__init__.py‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66

77
import re
8+
from collections.abc import Mapping, Sequence
89
from pathlib import Path
910
from typing import Any
1011

@@ -178,3 +179,31 @@ def setup(
178179
self.record_file_in_manifest(path, project_root, manifest)
179180

180181
return created
182+
183+
def build_exec_args(
184+
self,
185+
prompt: str,
186+
*,
187+
model: str | None = None,
188+
output_json: bool = True,
189+
integration_args: Sequence[str] | None = None,
190+
integration_options: Mapping[str, Any] | None = None,
191+
project_root: Path | None = None,
192+
) -> list[str] | None:
193+
"""Build CLI arguments for non-interactive ``junie`` execution.
194+
195+
``MarkdownIntegration``'s default passes the prompt as ``-p <prompt>``,
196+
but Junie's ``-p`` is ``--project <path>``, so the prompt would be
197+
taken as the project directory and no task would be given. Junie
198+
takes a non-interactive task as a positional argument or ``--task``.
199+
"""
200+
self.validate_runtime_config(integration_args, integration_options)
201+
if not self.config or not self.config.get("requires_cli"):
202+
return None
203+
args = [self._resolve_executable(), "--task", prompt]
204+
self._apply_extra_args_env_var(args)
205+
if model:
206+
args.extend(["--model", model])
207+
if output_json:
208+
args.extend(["--output-format", "json"])
209+
return args

‎tests/integrations/test_integration_junie.py‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,67 @@ def test_init_next_steps_show_hyphenated_commands(self, tmp_path):
133133
assert "/speckit-plan" in result.output
134134
assert "/speckit.plan" not in result.output
135135

136+
def test_build_exec_args_passes_prompt_as_task(self):
137+
"""Junie's `-p` is `--project <path>`; the prompt goes to `--task`."""
138+
integration = get_integration(self.KEY)
139+
140+
args = integration.build_exec_args(
141+
"/speckit-specify build a login page",
142+
output_json=False,
143+
)
144+
145+
assert args == ["junie", "--task", "/speckit-specify build a login page"]
146+
assert "-p" not in args
147+
148+
def test_build_exec_args_requests_json_output(self):
149+
integration = get_integration(self.KEY)
150+
151+
args = integration.build_exec_args("/speckit-plan add OAuth", output_json=True)
152+
153+
assert args == [
154+
"junie",
155+
"--task",
156+
"/speckit-plan add OAuth",
157+
"--output-format",
158+
"json",
159+
]
160+
161+
def test_build_exec_args_forwards_model(self):
162+
integration = get_integration(self.KEY)
163+
164+
args = integration.build_exec_args(
165+
"/speckit-specify build a login page",
166+
model="sonnet",
167+
output_json=False,
168+
)
169+
170+
assert args == [
171+
"junie",
172+
"--task",
173+
"/speckit-specify build a login page",
174+
"--model",
175+
"sonnet",
176+
]
177+
178+
def test_build_exec_args_applies_extra_args(self, monkeypatch):
179+
monkeypatch.setenv("SPECKIT_INTEGRATION_JUNIE_EXTRA_ARGS", "--skip-update-check")
180+
integration = get_integration(self.KEY)
181+
182+
args = integration.build_exec_args(
183+
"check the build", model="sonnet", output_json=True
184+
)
185+
186+
assert args == [
187+
"junie",
188+
"--task",
189+
"check the build",
190+
"--skip-update-check",
191+
"--model",
192+
"sonnet",
193+
"--output-format",
194+
"json",
195+
]
196+
136197
# -- Overrides for MarkdownIntegrationTests ---------------------------
137198

138199
def test_setup_creates_files(self, tmp_path):

0 commit comments

Comments
 (0)