Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/specify_cli/workflows/steps/init/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,17 @@ def execute(self, config: dict[str, Any], context: StepContext) -> StepResult:

force = self._resolve_bool(config.get("force"), context)
# Workflows run unattended; skip the agent CLI presence check by default.
ignore_agent_tools = self._resolve_bool(
config.get("ignore_agent_tools", True), context
)
# ``config.get(key, True)`` applies that default only when the key is
# ABSENT: a bare ``ignore_agent_tools:`` in YAML parses to None, which
# ``_resolve_bool`` then turns into False -- flipping the documented
# default and re-enabling the agent-CLI presence check this step promises
# to skip, so an unattended run fails with "Agent Detection Error" for
# any integration whose CLI is not installed. Normalize an explicit null
# to the default, mirroring the while/do-while ``max_iterations`` handling.
raw_ignore_agent_tools = config.get("ignore_agent_tools")
if raw_ignore_agent_tools is None:
raw_ignore_agent_tools = True
ignore_agent_tools = self._resolve_bool(raw_ignore_agent_tools, context)

argv: list[str] = ["init"]
if here:
Expand Down
53 changes: 53 additions & 0 deletions tests/test_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -2173,6 +2173,59 @@ def test_builds_here_argv_and_bootstraps(self, tmp_path):
assert "--ignore-agent-tools" in argv
assert (tmp_path / ".specify").is_dir()

def test_explicit_null_ignore_agent_tools_keeps_documented_default(
self, tmp_path
):
"""A bare ``ignore_agent_tools:`` must keep the documented default.

The class docstring says "Because workflows run unattended, the step
defaults to ``--ignore-agent-tools``" and the field docs say "defaults to
``true``". But ``config.get(key, True)`` applies the default only when the
key is ABSENT — a bare ``ignore_agent_tools:`` in YAML parses to None,
which ``_resolve_bool`` turned into False, dropping the flag and
re-enabling the agent-CLI presence check for an unattended run.
"""
from specify_cli.workflows.steps.init import InitStep
from specify_cli.workflows.base import StepContext, StepStatus

step = InitStep()
ctx = StepContext(
project_root=str(tmp_path), default_integration="copilot"
)
result = step.execute(
{
"id": "bootstrap",
"here": True,
"script": "sh",
"ignore_agent_tools": None,
},
ctx,
)

assert result.status == StepStatus.COMPLETED
assert "--ignore-agent-tools" in result.output["argv"]

def test_explicit_false_ignore_agent_tools_is_honoured(self, tmp_path):
"""An explicit ``false`` must still opt in to the agent-CLI check."""
from specify_cli.workflows.steps.init import InitStep
from specify_cli.workflows.base import StepContext

step = InitStep()
ctx = StepContext(
project_root=str(tmp_path), default_integration="copilot"
)
result = step.execute(
{
"id": "bootstrap",
"here": True,
"script": "sh",
"ignore_agent_tools": False,
},
ctx,
)

assert "--ignore-agent-tools" not in result.output["argv"]

def test_default_integration_falls_back_to_workflow_default(self, tmp_path):
from specify_cli.workflows.steps.init import InitStep
from specify_cli.workflows.base import StepContext, StepStatus
Expand Down