Skip to content

feat(workflows): add --dry-run flag to specify workflow run - #2704

Closed
fuleinist wants to merge 5 commits into
github:mainfrom
fuleinist:feat/2661-dry-run
Closed

fuleinist wants to merge 5 commits into
github:mainfrom
fuleinist:feat/2661-dry-run

Conversation

@fuleinist

@fuleinist fuleinist commented May 26, 2026

Copy link
Copy Markdown

Summary

Implements issue #2661 — add a --dry-run flag to specify workflow run that previews each step's resolved inputs, prompt, and command invocation without spawning the underlying coding-agent CLI or making any AI calls. Use it to verify what a workflow would dispatch before running for real.

What ships

Engine

  • src/specify_cli/workflows/base.py: StepContext gains dry_run: bool = False
  • src/specify_cli/workflows/engine.py:
    • WorkflowEngine.execute(..., dry_run=False) propagates the flag to every step
    • Persists dry_run on RunState (save/load) and restores it in resume() so an interrupted dry-run does not silently become a real run
    • dry_run semantics documented in the execute() docstring

Step behavior

  • CommandStep (workflows/steps/command/): dry_run=True renders the integration's build_command_invocation(command, args) preview, sets exit_code=0, returns COMPLETED without spawning the CLI
  • GateStep (workflows/steps/gate/): dry_run=True returns COMPLETED immediately with a short DRY RUN message; no interactive prompt
  • Graceful fallback when an integration does not implement build_command_invocation: preview includes the command name and a one-line note explaining the fallback
  • except clause narrowed from bare Exception to (ImportError, AttributeError, KeyError, TypeError, ValueError) so dry-run failures stay debuggable

CLI

  • specify workflow run --dry-run (in-module, in __init__.py) — the only place the flag is exposed. After the run, the CLI prints any output['dry_run'] messages so the rendered previews surface in the terminal.

What does not ship (intentional)

Per design review, the specify CLI is scaffolding + workflow orchestration only. The per-stage surface (/speckit.specify, /speckit.plan, ...) belongs to the agent, not the CLI. A previous draft of this PR added specify spec / specify plan preview commands; those have been removed along with the supporting start_at / stop_after step filtering in the engine. Issue #2661's wording has been re-scoped to --dry-run on specify workflow run.

Tests

  • Existing dry-run coverage in tests/test_workflows.py
  • test_dry_run_persisted_in_run_state: dry_run survives save/load round-trip
  • test_resume_restores_dry_run: resume() rebuilds StepContext with the persisted flag so an interrupted dry-run stays a dry-run
  • test_dry_run_returns_completed_without_dispatch: CommandStep returns COMPLETED with the rendered preview; no CLI is spawned; uses tmp_path for portability
  • test_dry_run_skips_interactive_gate: GateStep short-circuits with a DRY RUN message

Usage

specify workflow run speckit --input spec='Build a kanban board' --dry-run
specify workflow run ./my-workflow.yml --input spec='Photo album app' --dry-run

Closes #2661

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add dry-run flag to preview spec output without AI invocation

3 participants