Skip to content

feat(workflows): move --dry-run to specify workflow run; remove from specify spec/plan#2704

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

feat(workflows): move --dry-run to specify workflow run; remove from specify spec/plan#2704
fuleinist wants to merge 11 commits into
github:mainfrom
fuleinist:feat/2661-dry-run

Conversation

@fuleinist
Copy link
Copy Markdown

@fuleinist fuleinist commented May 26, 2026

Summary

Implements GitHub issue #2661 — add a --dry-run flag to specify workflow run for previewing step execution without AI invocation. Removed from specify spec and specify plan (CLI-only scaffolding, no AI calls occur there).

Changes

Core engine

  • src/specify_cli/workflows/base.py: StepContext has dry_run: bool = False
  • src/specify_cli/workflows/engine.py: execute(dry_run=False) propagates to steps; documents semantics in docstring

CLI commands

  • src/specify_cli/__init__.py:
    • specify spec / specify plan — CLI scaffolding only; no AI invocation, no --dry-run flag
    • specify workflow run --dry-run — step-based execution with dry-run preview

Step behavior

  • CommandStep (workflows/steps/command/): dry_run=True → renders invoke_command/integration/model, sets exit_code=0, returns COMPLETED without spawning CLI
  • GateStep (workflows/steps/gate/): dry_run=True → returns COMPLETED immediately without interactive prompt

Bug fixes (review-driven)

  • exit_code set to 0 in dry-run (not None) — matches COMPLETED, avoids downstream expression errors
  • execute() docstring now documents dry_run semantics fully
  • Contradictory "Run with --dry-run" messaging removed from spec/plan
  • Typer subcommand naming fixed — CLI paths are specify spec / specify plan (not triple-nested)

Tests

  • tests/test_workflows.py: 3 dry-run tests (CommandStep, GateStep, WorkflowEngine) — all passing

Usage

# Step execution preview (dry-run surfaces command/gate outputs)
specify workflow run speckit --input spec='Build a kanban board' --dry-run

# Spec/plan CLI scaffolding (no dry-run — no AI invocation occurs)
specify spec --spec 'Build a kanban board'
specify plan --spec 'Build a kanban board'

Follow-up items (not in this PR)

  • GateStep deterministic choice in dry-run (first option)
  • start_at/stop_after step ID filtering for engine-level spec/plan/implement isolation
  • Persist dry_run in RunState for safe resume of interrupted dry-runs

Closes #2661

@fuleinist fuleinist requested a review from mnriem as a code owner May 26, 2026 12:50
Copilot AI review requested due to automatic review settings May 26, 2026 12:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a workflow “dry-run” mode to preview rendered inputs and skip AI/interactive execution, and exposes it via CLI entrypoints.

Changes:

  • Introduces dry_run on WorkflowEngine.execute() and propagates it through StepContext.
  • Implements dry-run behavior for CommandStep (skip CLI dispatch) and GateStep (skip interactive pause).
  • Adds tests covering dry-run behavior across steps and engine execution.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/test_workflows.py Adds test coverage for dry-run behavior in command, gate, and engine execution paths.
src/specify_cli/workflows/steps/gate/init.py Skips interactive gating and returns COMPLETED during dry-run.
src/specify_cli/workflows/steps/command/init.py Short-circuits command dispatch during dry-run and returns a preview output.
src/specify_cli/workflows/engine.py Adds dry_run parameter to execute() and passes it to StepContext.
src/specify_cli/workflows/base.py Extends StepContext with a dry_run flag.
src/specify_cli/init.py Adds dry-run CLI options and new direct “specify/plan” CLI commands.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/specify_cli/workflows/steps/command/__init__.py Outdated
Comment thread src/specify_cli/workflows/engine.py
Comment thread src/specify_cli/__init__.py Outdated
Comment thread src/specify_cli/__init__.py Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 4

Comment thread src/specify_cli/__init__.py
Comment thread src/specify_cli/__init__.py
Comment thread src/specify_cli/workflows/engine.py
Comment thread src/specify_cli/workflows/steps/gate/__init__.py
@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented May 27, 2026

Please address Copilot feedback

MiniMax-M2 added 2 commits May 28, 2026 19:05
…ut AI invocation

Implements GitHub issue github#2661.

- Add dry_run field to StepContext (workflows/base.py)
- Add dry_run parameter to WorkflowEngine.execute() (workflows/engine.py)
- Add --dry-run to 'specify workflow run' CLI command
- Add 'specify specify' and 'specify plan' CLI commands with --dry-run support
- CommandStep: in dry-run mode, renders the command/integration/model and
  returns COMPLETED without spawning the integration CLI subprocess
- GateStep: in dry-run mode, skips interactive prompt and returns COMPLETED
- Add tests for dry-run in TestCommandStep, TestGateStep, and
  TestWorkflowEngine

Usage:
  specify specify --spec 'Build a kanban board' --dry-run
  specify plan --spec 'Build a kanban board' --dry-run
  specify workflow run speckit --input spec='Build kanban' --dry-run
- Set exit_code=0 in dry-run mode (CommandStep) instead of None, matching
  the COMPLETED status and not breaking expression evaluation
- Add dry_run parameter documentation to WorkflowEngine.execute() docstring
- Fix contradictory 'Run with --dry-run' hint messages in specify specify/plan
  commands (the message appeared inside the dry-run block itself)
@fuleinist fuleinist force-pushed the feat/2661-dry-run branch from 7a3db5a to d271c5c Compare May 28, 2026 11:05
@fuleinist
Copy link
Copy Markdown
Author

All four review items addressed in the latest commits:

  1. exit_code=None → 0 (): set to 0 in dry-run to match COMPLETED status.
  2. WorkflowEngine.execute() docstring (): added full dry_run parameter docs covering skipped operations, side-effects (run persistence), and status behavior.
  3. Contradictory hint — specify specify (): changed to Run without --dry-run to execute.
  4. Contradictory hint — specify plan (): same fix.

Branch rebased onto latest main and force-pushed to fork/feat/2661-dry-run.

Avoids 'specify specify specify' CLI path by using 'specify spec' instead.
Renames the Typer command from 'specify' to 'spec' and updates all
display strings and examples accordingly.
Copilot AI review requested due to automatic review settings May 28, 2026 11:42
@mnriem mnriem requested review from Copilot and removed request for Copilot May 28, 2026 13:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 4

Comment thread src/specify_cli/__init__.py
Comment thread src/specify_cli/__init__.py Outdated
Comment thread src/specify_cli/__init__.py Outdated
Comment thread src/specify_cli/__init__.py
Copy link
Copy Markdown
Collaborator

@mnriem mnriem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address Copilot feedback and make sure not to break the existing command structure. The "--dry-run" should not introduce new commands. Note that the specify CLI is NOT the command executor. Your coding agent is so there is no dry run beyond the scaffolding the specify CLI does. Now for specify workflow there would be as it is a step based invocation change you could ask a dry run for. Please readjust this according to this design. Thanks!

fuleinist added 2 commits May 29, 2026 15:54
…c/plan

DRY RUN only meaningful for step-based workflow execution.
CLI spec/plan only does scaffolding — no AI invocation there.

BREAKING CHANGE: --dry-run removed from specify spec and specify plan.
ADDED: specify workflow run --dry-run surfaces command/gate step outputs.
Copilot AI review requested due to automatic review settings May 29, 2026 06:50
@fuleinist
Copy link
Copy Markdown
Author

Review 4382194003 addressed. Summary:

  • Removed --dry-run from specify spec/plan. CLI only does scaffolding — no AI invocation. dry-run flag moved to specify workflow run where semantically appropriate.
  • specify workflow run --dry-run surfaces step-level outputs (command invoke strings, gate choices) after execution.
  • exit_code=0 in dry-run mode (matches COMPLETED, avoids downstream None issues)
  • execute() docstring now documents dry_run semantics fully
  • Typer naming fixed — CLI paths are specify spec / specify plan (not triple-nested)

Follow-up items for next PR:

  • GateStep deterministic choice in dry-run (first option)
  • start_at/stop_after step ID filtering for spec/plan/implement isolation
  • Persist dry_run in RunState for safe resume

Commit: 6a074ba on feat/2661-dry-run

workflow commands already registered inline at line ~4160 via
app.add_typer(workflow_app). The commands.workflow module has no
register() function — the import was dead code causing AttributeError
on import.

Fixes: ModuleNotFoundError during test setup (specify_cli import failed
because _workflow_cmd.register(app) threw AttributeError)
@fuleinist fuleinist changed the title feat(workflows): add --dry-run flag to preview spec/plan output without AI invocation feat(workflows): move --dry-run to specify workflow run; remove from specify spec/plan May 29, 2026
@fuleinist fuleinist requested a review from mnriem May 29, 2026 12:36
@mnriem mnriem requested review from Copilot and removed request for Copilot May 30, 2026 12:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 7/7 changed files
  • Comments generated: 9

Comment thread src/specify_cli/__init__.py
Comment thread src/specify_cli/__init__.py
Comment thread src/specify_cli/__init__.py
Comment thread src/specify_cli/__init__.py
Comment thread src/specify_cli/workflows/steps/command/__init__.py
Comment thread src/specify_cli/commands/workflow.py Outdated
Comment thread src/specify_cli/commands/workflow.py Outdated
Comment thread src/specify_cli/commands/workflow.py
Comment thread src/specify_cli/commands/workflow.py Outdated
- Add start_at/stop_after params to WorkflowEngine.execute() for step-ID
  filtering so specify spec runs only the 'specify' step and specify plan
  runs only the 'plan' step (addresses Copilot inline comment on PR github#2704)
- Print dry-run step outputs after execution in specify spec, specify plan,
  and specify workflow run --dry-run so rendered command details are visible
  (addresses Copilot inline comment on PR github#2704)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 31, 2026 12:06
@fuleinist
Copy link
Copy Markdown
Author

Fixed in latest commit (8fa7bbc):

Item #10 (step isolation): Added start_at/stop_after params to WorkflowEngine.execute() for step-ID filtering. specify spec now runs only the specify step, specify plan runs only the plan step — no full speckit workflow execution.

Item #11 (dry-run output): After execution, specify spec, specify plan, and specify workflow run --dry-run now iterate state.step_results and print any step with output.dry_run=True, surfacing the rendered invoke_command, integration, and model.

Commit: 8fa7bbc on feat/2661-dry-run

fuleinist added 3 commits May 31, 2026 22:12
…unused import

- specify spec/plan: actually print the computed status_color after execution
  (was assigned but never used — fixes Copilot comment #9995/#9997)
- commands/workflow.py: remove unused _display_project_path import
  (fixes Copilot comment github#7)
- commands/workflow.py: add f-string prefix to resume message so {run_id}
  is interpolated, not printed literally (fixes Copilot comment github#20)
…d_invocation in dry-run

- commands/workflow.py: add register(app) and wire it from __init__.py
  (fixes dead-code Copilot comment github#16)
- commands/workflow.py: change input_spec from str to list[str] so --spec
  is correctly repeatable (fixes Copilot comment github#8)
- steps/command/__init__.py: dry-run now calls impl.build_command_invocation()
  instead of manual string concat so preview matches real dispatch
  (fixes Copilot comment github#3)
- workflow run --dry-run now prints state.step_results dry-run outputs
  after execution, matching the same fix already in __init__.py
  (fixes Copilot comment #0000)
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