Skip to content

Add workflow engine with catalog system#2158

Open
Copilot wants to merge 24 commits intomainfrom
copilot/add-workflow-engine-catalog-system
Open

Add workflow engine with catalog system#2158
Copilot wants to merge 24 commits intomainfrom
copilot/add-workflow-engine-catalog-system

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 10, 2026

Adds a workflow subsystem to Specify CLI for defining multi-step, resumable automation workflows in YAML. The engine dispatches commands to CLI-based integrations, evaluates control flow, and pauses at human review gates. Ships with a catalog system mirroring the existing extension/preset catalog pattern.

Workflow engine core (src/specify_cli/workflows/)

  • base.pyStepBase abstract class, StepContext, StepResult, status enums
  • __init__.pySTEP_REGISTRY with auto-discovery, mirrors INTEGRATION_REGISTRY
  • expressions.py — Sandboxed Jinja2-subset evaluator (variable interpolation, comparisons, boolean logic, filters like default, join, map, contains)
  • engine.pyWorkflowDefinition (YAML loader), validate_workflow(), WorkflowEngine (sequential executor with recursive nested step support), RunState (JSON state persistence for resume)
  • catalog.pyWorkflowCatalog (multi-catalog stack: env var → project → user → built-in), WorkflowRegistry (installed workflow tracking)

10 built-in step types (workflows/steps/)

command, prompt, shell, gate, if (then/else), switch, while, do-while, fan-out, fan-in — each a StepBase subclass in its own subpackage, same extensibility model as integrations.

CLI commands

specify workflow run|resume|status|list|add|remove|search|info plus specify workflow catalog list|add|remove.

Catalog files

workflows/catalog.json, workflows/catalog.community.json, and an example workflows/speckit/workflow.yml (full SDD cycle).

Example workflow definition

schema_version: "1.0"
workflow:
  id: "sdd-pipeline"
  name: "SDD Pipeline"
  version: "1.0.0"
  integration: claude

inputs:
  feature_name:
    type: string
    required: true

steps:
  - id: specify
    command: speckit.specify
    input:
      args: "{{ inputs.feature_name }}"

  - id: review-spec
    type: gate
    message: "Review the generated spec."
    options: [approve, reject]
    on_reject: abort

  - id: check-scope
    type: if
    condition: "{{ inputs.scope == 'full' }}"
    then:
      - id: full-plan
        command: speckit.plan
        integration: gemini
        model: gemini-2.5-pro
    else:
      - id: quick-plan
        command: speckit.plan

Tests

122 new tests covering step registry, expression engine, all step types, workflow validation, engine execution (including branching/gates/shell), state persistence, catalog resolution, and registry operations. Full suite passes (1362 total).

Copilot AI requested review from Copilot and removed request for Copilot April 10, 2026 16:30
Copilot AI linked an issue Apr 10, 2026 that may be closed by this pull request
…stem, and CLI commands

Agent-Logs-Url: https://github.com/github/spec-kit/sessions/72a7bb5d-071f-4d67-a507-7e1abae2384d

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot April 10, 2026 16:44
Copilot AI requested review from Copilot and removed request for Copilot April 10, 2026 16:48
Copilot AI requested review from Copilot and removed request for Copilot April 10, 2026 16:51
Copilot AI changed the title [WIP] Add workflow engine with catalog system to Specify CLI Add workflow engine with catalog system Apr 10, 2026
Copilot AI requested a review from mnriem April 10, 2026 16:54
@mnriem mnriem marked this pull request as ready for review April 13, 2026 19:39
Copilot AI review requested due to automatic review settings April 13, 2026 19:39
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

Adds a new workflow subsystem to Specify CLI that can load YAML workflow definitions, evaluate simple template expressions, execute step types, persist run state for resuming, and discover workflows via a catalog/registry model (similar to extensions/presets).

Changes:

  • Introduces specify_cli.workflows core modules (base types, expression evaluator, engine + run-state persistence, catalog + registry).
  • Adds 9 built-in step types (command/shell/gate + control-flow primitives) with auto-registration.
  • Adds specify workflow ... CLI commands plus initial workflow catalog JSONs and a sample speckit workflow, with a large new test suite.
Show a summary per file
File Description
workflows/speckit/workflow.yml Adds an example “Full SDD Cycle” workflow definition.
workflows/catalog.json Adds default workflow catalog stub (empty).
workflows/catalog.community.json Adds community workflow catalog stub (empty).
tests/test_workflows.py Adds comprehensive tests for workflow engine components and step types.
src/specify_cli/workflows/base.py Defines workflow step/run base types (StepBase, StepContext, StepResult, enums).
src/specify_cli/workflows/init.py Implements global step registry + registers built-in step implementations.
src/specify_cli/workflows/expressions.py Adds a sandboxed, Jinja-like expression/template evaluator.
src/specify_cli/workflows/engine.py Adds workflow YAML loader/validator, executor, and run-state persistence/resume.
src/specify_cli/workflows/catalog.py Adds catalog stack resolution, URL validation, caching, search, and installed registry.
src/specify_cli/workflows/steps/init.py Declares step auto-discovery package.
src/specify_cli/workflows/steps/command/init.py Adds the command step type.
src/specify_cli/workflows/steps/shell/init.py Adds the shell step type.
src/specify_cli/workflows/steps/gate/init.py Adds the gate step type.
src/specify_cli/workflows/steps/if_then/init.py Adds the if step type.
src/specify_cli/workflows/steps/switch/init.py Adds the switch step type.
src/specify_cli/workflows/steps/while_loop/init.py Adds the while step type.
src/specify_cli/workflows/steps/do_while/init.py Adds the do-while step type.
src/specify_cli/workflows/steps/fan_out/init.py Adds the fan-out step type.
src/specify_cli/workflows/steps/fan_in/init.py Adds the fan-in step type.
src/specify_cli/init.py Adds specify workflow CLI commands (run/resume/status/list/add/remove/search/info + catalog list/add/remove).

Copilot's findings

Tip

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

Comments suppressed due to low confidence (1)

src/specify_cli/workflows/engine.py:535

  • _execute_steps() treats result.next_steps as a one-time nested sequence. That means loop steps (while, do-while) and fan-out/fan-in currently can't implement their advertised semantics (re-evaluating conditions, enforcing max_iterations, running per-item dispatch, joining). If these step types are intended to work, the engine needs explicit handling for them here (or the step contract needs to change so the step implementation can drive iteration/execution).
            # Execute nested steps (from control flow)
            if result.next_steps:
                self._execute_steps(result.next_steps, context, state, registry)
                if state.status in (
                    RunStatus.PAUSED,
                    RunStatus.FAILED,
                    RunStatus.ABORTED,
                ):
                    return
  • Files reviewed: 20/20 changed files
  • Comments generated: 6

mnriem added 2 commits April 13, 2026 16:37
Review comments (7/7):
- Add explanatory comment to empty except block
- Implement workflow catalog download with cleanup on failure
- Add input type coercion for number/boolean/enum
- Fix example workflow to remove non-existent output references
- Fix while_loop and if_then condition defaults (string 'false' → bool False)
- Fix resume step index tracking with step_offset parameter

CLI dispatch:
- Add build_exec_args() and dispatch_command() to IntegrationBase
- Override for Claude (skills: /speckit-specify), Gemini (-m flag),
  Codex (codex exec), Copilot (--agent speckit.specify)
- CommandStep invokes installed commands by name via integration CLI
- Add PromptStep for arbitrary inline prompts (10th step type)
- Stream CLI output live to terminal (no silent blocking)
- Remove timeout when streaming (user can Ctrl+C)
- Ctrl+C saves state as PAUSED for clean resume

Interactive gates:
- Gate steps prompt [1] approve [2] reject in TTY
- Fall back to PAUSED in non-interactive environments
- Resume re-executes the gate for interactive prompting

Documentation:
- workflows/README.md — user guide
- workflows/ARCHITECTURE.md — internals with Mermaid diagrams
- workflows/PUBLISHING.md — catalog submission guide

Tests: 94 → 122 workflow tests, 1362 total (all passing)
Copilot AI review requested due to automatic review settings April 13, 2026 21:43
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

Introduces a new workflow subsystem to Specify CLI that can load YAML-defined workflows, execute step graphs with state persistence (run/resume/status), and manage workflow catalogs/installation—along with integration updates to support non-interactive CLI dispatch.

Changes:

  • Added specify_cli.workflows engine core (definition parsing, validation, expression evaluation, run state persistence, catalog/registry).
  • Added built-in workflow step types and corresponding tests.
  • Added specify workflow ... CLI commands plus integration enhancements (build_exec_args / dispatch support for Codex + Copilot).
Show a summary per file
File Description
workflows/speckit/workflow.yml Adds an example built-in workflow definition for a full SDD cycle.
workflows/catalog.json Adds an official workflow catalog skeleton file.
workflows/catalog.community.json Adds a community workflow catalog skeleton file.
workflows/README.md Adds end-user documentation for workflows, step types, catalogs, and resume.
workflows/PUBLISHING.md Adds workflow publishing guidance and catalog submission format.
workflows/ARCHITECTURE.md Documents workflow engine internals, step registry, and catalog resolution.
tests/test_workflows.py Adds a large test suite covering workflow parsing/validation/execution, steps, catalog, and registry.
src/specify_cli/workflows/base.py Introduces core workflow base types (StepBase, StepContext, StepResult, status enums).
src/specify_cli/workflows/init.py Implements STEP_REGISTRY and registers built-in step implementations.
src/specify_cli/workflows/expressions.py Implements the template/expression evaluator used by workflow YAML.
src/specify_cli/workflows/engine.py Implements workflow definition loading, validation, execution, resume, and run state persistence.
src/specify_cli/workflows/catalog.py Implements workflow catalog stacking, caching, searching, and installed workflow registry.
src/specify_cli/workflows/steps/init.py Adds steps package marker for built-in step types.
src/specify_cli/workflows/steps/command/init.py Adds command step type for dispatching Spec Kit commands via integration CLIs.
src/specify_cli/workflows/steps/shell/init.py Adds shell step type for running local shell commands.
src/specify_cli/workflows/steps/gate/init.py Adds gate step type for interactive/pause-based human review checkpoints.
src/specify_cli/workflows/steps/if_then/init.py Adds if branching step type producing nested step lists.
src/specify_cli/workflows/steps/switch/init.py Adds switch branching step type based on an evaluated expression.
src/specify_cli/workflows/steps/while_loop/init.py Adds while loop step type returning nested steps conditionally.
src/specify_cli/workflows/steps/do_while/init.py Adds do-while loop step type intended to repeat nested steps.
src/specify_cli/workflows/steps/fan_out/init.py Adds fan-out step type intended for parallel dispatch over a collection.
src/specify_cli/workflows/steps/fan_in/init.py Adds fan-in step type for aggregating results from prior steps.
src/specify_cli/workflows/steps/prompt/init.py Adds prompt step type for free-form prompts to integration CLIs.
src/specify_cli/init.py Adds the specify workflow CLI command group (run/resume/status/list/add/remove/search/info + catalog ops).
src/specify_cli/integrations/base.py Adds integration primitives for CLI execution and command dispatch (build_exec_args, dispatch_command, invocation helpers).
src/specify_cli/integrations/codex/init.py Adds Codex CLI exec argument builder for non-interactive dispatch.
src/specify_cli/integrations/copilot/init.py Adds GitHub Copilot CLI dispatch support (agent-based invocation + exec args).

Copilot's findings

Tip

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

  • Files reviewed: 27/27 changed files
  • Comments generated: 12

…op/fan-out execution, URL validation

- VALID_STEP_TYPES now queries STEP_REGISTRY dynamically
- Shell step returns FAILED on non-zero exit code
- Persist workflow YAML in run directory for reliable resume
- Resume loads from run copy, falls back to installed workflow
- Engine iterates while/do-while loops up to max_iterations
- Engine expands fan-out per item with context.item
- HTTPS URL validation for catalog workflow installs (HTTP allowed for localhost)
- Fix catalog merge priority docstring (lower number wins)
- Fix dispatch_command docstring (no build_exec_args_for_command)
- Gate on_reject=retry pauses for re-prompt on resume
- Update docs to 10 step types, add prompt step to tables and README
…validation

- Fan-out per-item step IDs use _fanout_{step_id}_{base}_{idx} namespace
  to avoid collisions with user-defined step IDs
- Early return after fan-out loop when state is paused/failed/aborted
- Catalog installs parse + validate downloaded YAML before registering,
  using definition metadata instead of catalog entry for registry
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

Introduces a new workflow subsystem in Specify CLI to run multi-step, resumable YAML-defined automation workflows, including built-in step types, a catalog/registry mechanism, and new specify workflow ... CLI commands.

Changes:

  • Added workflow engine core (definition parsing/validation, execution with nested control-flow steps, run-state persistence + resume).
  • Added workflow catalog + installed-workflow registry support, mirroring extension/preset catalog behavior.
  • Added built-in step implementations (command/prompt/shell/gate + control flow/looping/fan-out/fan-in) and a comprehensive test suite.
Show a summary per file
File Description
workflows/speckit/workflow.yml Adds an example “Full SDD Cycle” workflow definition.
workflows/catalog.json Adds the official workflow catalog scaffold.
workflows/catalog.community.json Adds the community workflow catalog scaffold.
workflows/README.md Documents workflow concepts, step types, and CLI usage.
workflows/PUBLISHING.md Adds workflow publishing guidelines and catalog submission rules.
workflows/ARCHITECTURE.md Documents workflow engine architecture and internals.
tests/test_workflows.py Adds extensive tests for engine, steps, catalogs, and integrations dispatch behavior.
src/specify_cli/workflows/base.py Defines workflow base types (StepBase/StepContext/StepResult) and status enums.
src/specify_cli/workflows/init.py Implements global step registry and registers built-in step types.
src/specify_cli/workflows/expressions.py Adds a sandboxed Jinja-like expression evaluator used by workflow templates.
src/specify_cli/workflows/engine.py Implements workflow loading, validation, execution, run-state persistence, and resume.
src/specify_cli/workflows/catalog.py Implements catalog stacking, caching, searching, and installed-workflow registry.
src/specify_cli/workflows/steps/init.py Adds step package marker for built-in step auto-discovery/organization.
src/specify_cli/workflows/steps/command/init.py Adds “command” step type to dispatch Spec Kit commands via integration CLIs.
src/specify_cli/workflows/steps/prompt/init.py Adds “prompt” step type to dispatch arbitrary prompts via integration CLIs.
src/specify_cli/workflows/steps/shell/init.py Adds “shell” step type for local shell execution.
src/specify_cli/workflows/steps/gate/init.py Adds “gate” step type for interactive human review/pause behavior.
src/specify_cli/workflows/steps/if_then/init.py Adds “if” step type for conditional branching to nested steps.
src/specify_cli/workflows/steps/switch/init.py Adds “switch” step type for multi-branch dispatch to nested steps.
src/specify_cli/workflows/steps/while_loop/init.py Adds “while” step type for pre-check looping of nested steps.
src/specify_cli/workflows/steps/do_while/init.py Adds “do-while” step type for post-check looping of nested steps.
src/specify_cli/workflows/steps/fan_out/init.py Adds “fan-out” step type for per-item expansion using a step template.
src/specify_cli/workflows/steps/fan_in/init.py Adds “fan-in” step type to aggregate outputs from prior steps.
src/specify_cli/integrations/base.py Adds generic CLI dispatch primitives (build_exec_args, dispatch_command) for integrations.
src/specify_cli/integrations/codex/init.py Adds Codex CLI argument builder for non-interactive execution.
src/specify_cli/integrations/copilot/init.py Expands Copilot integration to support CLI dispatch and agent selection.
src/specify_cli/init.py Adds specify workflow and specify workflow catalog CLI command groups.

Copilot's findings

Tip

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

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

…ADME

- Add speckit workflow entry to catalog.json so it's discoverable
- Fix shell step output dict indentation
- Catalog add_catalog priority derived from max existing + 1
- README Quick Start clarified with install + local file examples
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

Adds a new workflow subsystem to Specify CLI to run multi-step, resumable YAML workflows with control-flow steps, expression templating, state persistence, and a catalog/registry model similar to extensions/presets.

Changes:

  • Introduces workflow engine core (definition loading/validation, execution, resume state) and sandboxed expression evaluator.
  • Adds 10 built-in step types (command/prompt/shell/gate + branching/loops/fan-out/fan-in) with a global step registry.
  • Adds workflow CLI commands plus workflow catalog and registry management, along with documentation, catalogs, an example workflow, and comprehensive tests.
Show a summary per file
File Description
workflows/speckit/workflow.yml Adds an example “Full SDD Cycle” workflow definition.
workflows/catalog.json Adds the official workflow catalog with the built-in speckit entry.
workflows/catalog.community.json Adds an (empty) community workflow catalog scaffold.
workflows/README.md Documents workflow concepts, step types, expressions, state/resume, and catalogs.
workflows/PUBLISHING.md Adds workflow publishing guidance for the community catalog.
workflows/ARCHITECTURE.md Documents engine internals, execution model, registry, expressions, and catalog resolution.
tests/test_workflows.py Adds extensive unit/integration tests for workflows, steps, expressions, engine, state, and catalogs.
src/specify_cli/workflows/base.py Introduces core step/run datatypes (context, results, enums, base class).
src/specify_cli/workflows/init.py Adds STEP_REGISTRY and registers built-in step implementations.
src/specify_cli/workflows/expressions.py Adds a sandboxed, Jinja-like expression/template evaluator.
src/specify_cli/workflows/engine.py Implements workflow definition parsing, validation, execution, and resume state.
src/specify_cli/workflows/catalog.py Implements catalog stack resolution, caching, search, and installed workflow registry.
src/specify_cli/workflows/steps/init.py Adds step package auto-discovery module stub.
src/specify_cli/workflows/steps/command/init.py Implements the command-dispatch step.
src/specify_cli/workflows/steps/prompt/init.py Implements free-form prompt dispatch step.
src/specify_cli/workflows/steps/shell/init.py Implements local shell execution step.
src/specify_cli/workflows/steps/gate/init.py Implements interactive/non-interactive human approval gate step.
src/specify_cli/workflows/steps/if_then/init.py Implements if branching step.
src/specify_cli/workflows/steps/switch/init.py Implements switch multi-branch dispatch step.
src/specify_cli/workflows/steps/while_loop/init.py Implements while loop step.
src/specify_cli/workflows/steps/do_while/init.py Implements do-while loop step.
src/specify_cli/workflows/steps/fan_out/init.py Implements fan-out template expansion over item collections.
src/specify_cli/workflows/steps/fan_in/init.py Implements fan-in aggregation step.
src/specify_cli/integrations/base.py Adds CLI dispatch primitives (build_exec_args, dispatch_command, etc.) for integrations.
src/specify_cli/integrations/copilot/init.py Extends Copilot integration with CLI dispatch support.
src/specify_cli/integrations/codex/init.py Adds Codex CLI exec-args support for dispatch.
src/specify_cli/init.py Adds specify workflow ... CLI commands for running/managing workflows and catalogs.

Copilot's findings

Tip

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

Comments suppressed due to low confidence (1)

src/specify_cli/workflows/catalog.py:495

  • remove_catalog() also assumes the YAML config parses to a mapping. If .specify/workflow-catalogs.yml is malformed and loads as a non-dict, data.get('catalogs', ...) will crash with AttributeError. Validate the parsed type and raise WorkflowValidationError so the CLI can show a friendly error.

        data = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {}
        catalogs = data.get("catalogs", [])

  • Files reviewed: 27/27 changed files
  • Comments generated: 5

…, version alignment

- Validate max_iterations is int >= 1 in while and do-while steps
- Guard add_catalog against corrupted config (non-dict/non-list)
- Align speckit_version requirement to >=0.6.1 (current package version)
- Fan-out template validation uses separate seen_ids set to avoid
  false duplication errors with user-defined step IDs
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

Adds a new workflow subsystem to Specify CLI, enabling multi-step, resumable automation workflows defined in YAML, with built-in step types, persistence/resume, and a catalog/registry pattern similar to extensions/presets.

Changes:

  • Introduces workflow engine core (definition loading/validation, execution, state persistence, expression evaluation, catalog + registry).
  • Adds 10 built-in workflow step types (command/prompt/shell/gate + control-flow and fan-out/fan-in).
  • Adds specify workflow ... CLI commands and publishes initial workflow catalogs + built-in “speckit” workflow, with a comprehensive test suite.
Show a summary per file
File Description
src/specify_cli/workflows/base.py Adds core workflow datatypes (context/result/status) for step execution.
src/specify_cli/workflows/__init__.py Implements step registry and registers built-in step types.
src/specify_cli/workflows/expressions.py Adds sandboxed expression/template evaluator for YAML workflows.
src/specify_cli/workflows/engine.py Implements workflow definition parsing/validation, execution engine, and run state persistence/resume.
src/specify_cli/workflows/catalog.py Implements multi-source workflow catalog resolution, caching, and installed workflow registry.
src/specify_cli/workflows/steps/*/__init__.py Implements built-in step types (command, prompt, shell, gate, if, switch, while, do-while, fan-out, fan-in).
src/specify_cli/integrations/base.py Adds a CLI-dispatch abstraction (build_exec_args / dispatch_command) used by workflow steps.
src/specify_cli/integrations/copilot/__init__.py Adds Copilot CLI dispatch support for workflow step execution.
src/specify_cli/integrations/codex/__init__.py Adds Codex CLI exec arg builder for workflow dispatch.
src/specify_cli/__init__.py Adds workflow CLI commands: run/resume/status/list/add/remove/search/info + catalog list/add/remove.
workflows/catalog.json Adds official workflow catalog with built-in speckit workflow entry.
workflows/catalog.community.json Adds community workflow catalog scaffold.
workflows/speckit/workflow.yml Adds built-in “Full SDD Cycle” workflow definition.
workflows/README.md Documents workflow usage, step types, expressions, inputs, resume, and catalogs.
workflows/PUBLISHING.md Adds workflow publishing guidance and catalog submission rules.
workflows/ARCHITECTURE.md Adds architecture/design documentation for the workflow system.
tests/test_workflows.py Adds end-to-end and unit tests covering the workflow subsystem.

Copilot's findings

Tip

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

  • Files reviewed: 27/27 changed files
  • Comments generated: 3

…warning, state persistence

- Command step returns FAILED when CLI not installed (was silent COMPLETED)
- Catalog install warns on workflow ID vs catalog key mismatch
- Engine persists state.save() before returning on unknown step type
- Update tests to expect FAILED for command steps without CLI
- Integration tests use shell steps for CLI-independent execution
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

Adds a new workflow subsystem to Specify CLI, enabling YAML-defined multi-step automation runs with state persistence/resume, built-in control-flow steps, and a workflow catalog/installation model similar to extensions/presets.

Changes:

  • Introduces specify_cli.workflows engine core (definition loading/validation, execution, expression evaluation, run state persistence).
  • Adds 10 built-in step types (command/prompt/shell/gate + control-flow + fan-out/fan-in) and a global step registry.
  • Adds workflow catalog + registry management plus CLI commands (specify workflow ..., specify workflow catalog ...) and seed catalog/workflow docs/files.
Show a summary per file
File Description
workflows/speckit/workflow.yml Adds a built-in “Full SDD Cycle” workflow definition.
workflows/catalog.json Introduces the official workflow catalog with the built-in entry.
workflows/catalog.community.json Introduces an (empty) community workflow catalog scaffold.
workflows/README.md Documents workflow usage, step types, expressions, state/resume, catalogs.
workflows/PUBLISHING.md Adds community publishing guidance and catalog contribution rules.
workflows/ARCHITECTURE.md Adds internal architecture/spec for engine, steps, expressions, catalogs.
tests/test_workflows.py Adds a large test suite for workflow engine, steps, catalog/registry, and integration dispatch helpers.
src/specify_cli/workflows/base.py Adds core types: StepBase, StepContext, StepResult, status enums.
src/specify_cli/workflows/init.py Adds STEP_REGISTRY and registers built-in steps on import.
src/specify_cli/workflows/expressions.py Adds a sandboxed Jinja-like expression evaluator + filters.
src/specify_cli/workflows/engine.py Adds workflow definition parsing, validation, execution, run state persistence, resume.
src/specify_cli/workflows/catalog.py Adds catalog stack resolution, caching, workflow search, and installed workflow registry.
src/specify_cli/workflows/steps/init.py Adds steps package marker for built-in step types.
src/specify_cli/workflows/steps/command/init.py Adds the command-dispatch step type.
src/specify_cli/workflows/steps/prompt/init.py Adds the free-form prompt step type.
src/specify_cli/workflows/steps/shell/init.py Adds the local shell execution step type.
src/specify_cli/workflows/steps/gate/init.py Adds an interactive/non-interactive human gate step type.
src/specify_cli/workflows/steps/if_then/init.py Adds conditional branching step type.
src/specify_cli/workflows/steps/switch/init.py Adds switch/case branching step type.
src/specify_cli/workflows/steps/while_loop/init.py Adds while-loop step type.
src/specify_cli/workflows/steps/do_while/init.py Adds do-while loop step type.
src/specify_cli/workflows/steps/fan_out/init.py Adds fan-out step type (engine expands template per item).
src/specify_cli/workflows/steps/fan_in/init.py Adds fan-in aggregation step type.
src/specify_cli/integrations/base.py Adds a generic CLI dispatch surface (build_exec_args, dispatch_command, skills invocation).
src/specify_cli/integrations/copilot/init.py Adds Copilot CLI dispatch support and updates integration description.
src/specify_cli/integrations/codex/init.py Adds Codex CLI argument builder for non-interactive execution.
src/specify_cli/init.py Adds workflow CLI commands for running, resuming, listing, installing, and catalog management.

Copilot's findings

Tip

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

Comments suppressed due to low confidence (1)

workflows/PUBLISHING.md:180

  • This catalog entry example also uses "speckit_version": ">=0.15.0", which is higher than the current Spec Kit version declared in this repo. Align the example’s minimum version guidance with the actual project versioning so community submissions don’t get an incorrect constraint.
      "repository": "https://github.com/your-org/spec-kit-workflow-your-workflow",
      "license": "MIT",
      "requires": {
        "speckit_version": ">=0.15.0"
      },
  • Files reviewed: 27/27 changed files
  • Comments generated: 5

… docs, requires

- Fix workflow_search type annotations (str | None)
- PUBLISHING.md: speckit_version >=0.15.0 → >=0.6.1
- Document that exit_code is captured and referenceable by later steps
- Mark requires as declared-but-not-enforced (planned enhancement)
- Note full stdout/stderr capture as planned enhancement
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

Adds a new workflow subsystem to Specify CLI, enabling YAML-defined multi-step automation with resumable execution, control-flow steps, and a catalog/registry mechanism aligned with the existing catalog patterns.

Changes:

  • Introduces workflow engine primitives (definition loading/validation, expression evaluation, step registry, run state persistence, resume support).
  • Adds built-in workflow step types (command/prompt/shell/gate + control-flow and fan-out/fan-in).
  • Adds workflow CLI commands plus built-in/workflow community catalog files and documentation.
Show a summary per file
File Description
workflows/speckit/workflow.yml Adds an example built-in “Full SDD Cycle” workflow definition.
workflows/catalog.json Adds the official workflow catalog entry for speckit.
workflows/catalog.community.json Adds an (empty) community workflow catalog scaffold.
workflows/README.md Documents workflow usage, step types, expressions, state/resume, and catalogs.
workflows/PUBLISHING.md Adds workflow catalog submission/publishing instructions and conventions.
workflows/ARCHITECTURE.md Documents engine execution model, step registry, expression engine, and catalogs.
tests/test_workflows.py Adds comprehensive unit/integration tests for workflows subsystem.
src/specify_cli/workflows/base.py Defines core workflow types (context/result/status/base step).
src/specify_cli/workflows/init.py Implements the step registry and built-in step registration.
src/specify_cli/workflows/expressions.py Adds a sandboxed Jinja2-like expression evaluator and filters.
src/specify_cli/workflows/engine.py Implements workflow execution, nested steps, loops, fan-out, and run persistence/resume.
src/specify_cli/workflows/catalog.py Implements workflow catalog resolution/caching and installed workflow registry.
src/specify_cli/workflows/steps/*/init.py Implements built-in step types (command/prompt/shell/gate/if/switch/while/do-while/fan-out/fan-in).
src/specify_cli/integrations/base.py Adds generic CLI dispatch primitives used by workflow steps.
src/specify_cli/integrations/copilot/init.py Adds Copilot CLI dispatch support used by workflow command/prompt steps.
src/specify_cli/integrations/codex/init.py Adds Codex CLI argument builder for non-interactive dispatch.
src/specify_cli/init.py Adds specify workflow ... CLI commands and catalog management commands.

Copilot's findings

Tip

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

  • Files reviewed: 27/27 changed files
  • Comments generated: 1

mnriem added 2 commits April 13, 2026 20:00
- Add workflows/speckit to pyproject.toml force-include for wheel builds
- Add _locate_bundled_workflow() helper (mirrors _locate_bundled_extension)
- Auto-install speckit workflow during specify init (after git extension)
- Update all integration file inventory tests to expect workflow files
Copilot AI review requested due to automatic review settings April 14, 2026 01:07
- Keep both workflow and preset force-include in pyproject.toml
- Keep both _locate_bundled_workflow and _locate_bundled_preset helpers
- Add workflow files to yaml base inventory test (goose)
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

Adds a new workflow subsystem to Specify CLI, enabling YAML-defined multi-step, resumable automation workflows with built-in control-flow steps, CLI dispatch to integrations, run-state persistence, and a catalog/registry system consistent with existing catalog patterns.

Changes:

  • Introduces workflow engine core (definition loading/validation, execution, expressions, state persistence) plus 10 built-in step types.
  • Adds workflow catalog + registry management, CLI commands (specify workflow ...), and bundles an example “speckit” workflow into init/install flows.
  • Adds extensive test coverage for the workflow system and updates integration tests/file inventories accordingly.
Show a summary per file
File Description
workflows/speckit/workflow.yml Adds a bundled example “Full SDD Cycle” workflow definition.
workflows/catalog.json Adds official workflow catalog with the bundled workflow entry.
workflows/catalog.community.json Adds empty community workflow catalog scaffold.
workflows/README.md Documents workflow usage, step types, expressions, catalogs, and state/resume.
workflows/PUBLISHING.md Adds workflow publishing guidelines and community catalog rules.
workflows/ARCHITECTURE.md Documents workflow engine architecture, execution model, and catalog resolution.
tests/test_workflows.py Adds comprehensive tests for workflow engine, steps, expressions, catalog, and persistence.
tests/integrations/test_integration_generic.py Updates expected project inventory to include bundled workflow + registry.
tests/integrations/test_integration_copilot.py Updates expected project inventory to include bundled workflow + registry.
tests/integrations/test_integration_base_toml.py Updates expected inventory helper to include bundled workflow + registry.
tests/integrations/test_integration_base_skills.py Updates expected inventory helper to include bundled workflow + registry.
tests/integrations/test_integration_base_markdown.py Updates expected inventory helper to include bundled workflow + registry.
src/specify_cli/workflows/steps/while_loop/init.py Adds while control-flow step implementation + validation.
src/specify_cli/workflows/steps/switch/init.py Adds switch control-flow step implementation + validation.
src/specify_cli/workflows/steps/shell/init.py Adds shell step implementation (local shell execution).
src/specify_cli/workflows/steps/prompt/init.py Adds prompt step implementation (inline prompt dispatch).
src/specify_cli/workflows/steps/if_then/init.py Adds if step implementation (then/else branching).
src/specify_cli/workflows/steps/gate/init.py Adds gate step (interactive/CI pause + reject handling).
src/specify_cli/workflows/steps/fan_out/init.py Adds fan-out step (template expansion over items).
src/specify_cli/workflows/steps/fan_in/init.py Adds fan-in step (aggregation/join).
src/specify_cli/workflows/steps/do_while/init.py Adds do-while loop step implementation + validation.
src/specify_cli/workflows/steps/command/init.py Adds default command step (integration CLI dispatch).
src/specify_cli/workflows/steps/init.py Adds steps package marker for built-in step discovery.
src/specify_cli/workflows/expressions.py Adds sandboxed Jinja-like expression evaluator and filters.
src/specify_cli/workflows/engine.py Adds workflow definition/model, validation, execution engine, and run-state persistence.
src/specify_cli/workflows/catalog.py Adds catalog stack resolution, URL validation, caching, search, and registry management.
src/specify_cli/workflows/base.py Adds workflow base types: statuses, context, result, abstract step base.
src/specify_cli/workflows/init.py Registers built-in step types into a global registry.
src/specify_cli/integrations/copilot/init.py Extends Copilot integration to support CLI dispatch (workflows).
src/specify_cli/integrations/codex/init.py Adds Codex CLI exec-arg builder for dispatch support.
src/specify_cli/integrations/base.py Adds generic CLI-dispatch primitives to IntegrationBase + subclasses.
src/specify_cli/init.py Adds workflow CLI commands and installs bundled workflow during specify init.
pyproject.toml Bundles workflows/speckit into the wheel core pack.

Copilot's findings

Tip

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

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

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

Adds a new workflow subsystem to Specify CLI, enabling YAML-defined, multi-step, resumable automation (including control-flow steps) with a catalog/registry model similar to extensions/presets, plus new CLI commands to run/manage workflows.

Changes:

  • Introduces workflow engine core (definition loading/validation, step execution, expression evaluation, run-state persistence/resume).
  • Adds built-in step types (command/prompt/shell/gate + branching/loops + fan-out/fan-in) and a workflow catalog/registry layer.
  • Extends integrations with a CLI-dispatch interface and updates specify init + CLI surface area to bundle/install and manage workflows.
Show a summary per file
File Description
workflows/speckit/workflow.yml Adds a bundled “Full SDD Cycle” example workflow definition.
workflows/catalog.json Introduces official workflow catalog format and initial entry for speckit.
workflows/catalog.community.json Adds the community workflow catalog scaffold.
workflows/README.md Documents workflow concepts, step types, expressions, and catalog usage.
workflows/PUBLISHING.md Provides workflow publishing guidance and catalog entry requirements.
workflows/ARCHITECTURE.md Documents workflow engine internals and execution model.
tests/test_workflows.py Adds comprehensive unit/integration tests for the workflow subsystem.
tests/integrations/test_integration_generic.py Updates expected file inventories to include bundled workflow artifacts.
tests/integrations/test_integration_copilot.py Updates expected file inventories to include bundled workflow artifacts.
tests/integrations/test_integration_base_yaml.py Updates baseline inventory expectations for YAML integrations.
tests/integrations/test_integration_base_toml.py Updates baseline inventory expectations for TOML integrations.
tests/integrations/test_integration_base_skills.py Updates baseline inventory expectations for Skills integrations.
tests/integrations/test_integration_base_markdown.py Updates baseline inventory expectations for Markdown integrations.
src/specify_cli/workflows/init.py Adds step registry + built-in step registration.
src/specify_cli/workflows/base.py Defines workflow base types (context/result/status + step base).
src/specify_cli/workflows/expressions.py Implements a sandboxed, Jinja-like expression evaluator for templates/conditions.
src/specify_cli/workflows/engine.py Implements workflow loading, validation, execution, fan-out, loops, and run persistence.
src/specify_cli/workflows/catalog.py Implements catalog resolution/caching + installed workflow registry.
src/specify_cli/workflows/steps/init.py Adds steps package (auto-discovery placeholder).
src/specify_cli/workflows/steps/command/init.py Adds the command-dispatch step type (integration CLI dispatch).
src/specify_cli/workflows/steps/prompt/init.py Adds the prompt step type (free-form integration prompt).
src/specify_cli/workflows/steps/shell/init.py Adds the shell step type (local shell command execution).
src/specify_cli/workflows/steps/gate/init.py Adds the gate step type (interactive pause/approval).
src/specify_cli/workflows/steps/if_then/init.py Adds conditional branching step type.
src/specify_cli/workflows/steps/switch/init.py Adds switch/case branching step type.
src/specify_cli/workflows/steps/while_loop/init.py Adds pre-condition loop step type.
src/specify_cli/workflows/steps/do_while/init.py Adds post-condition loop step type.
src/specify_cli/workflows/steps/fan_out/init.py Adds fan-out step type (iterative expansion over items).
src/specify_cli/workflows/steps/fan_in/init.py Adds fan-in step type (aggregation/join behavior).
src/specify_cli/integrations/base.py Adds generic CLI dispatch hooks for integrations (exec args + dispatch).
src/specify_cli/integrations/copilot/init.py Adds Copilot CLI dispatch behavior and updates integration description.
src/specify_cli/integrations/codex/init.py Adds Codex CLI exec-args builder.
src/specify_cli/init.py Adds bundled workflow installation in init and new specify workflow ... CLI commands.
pyproject.toml Bundles workflows/speckit into the package core pack.

Copilot's findings

Tip

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

  • Files reviewed: 34/34 changed files
  • Comments generated: 5

Comment on lines +45 to +87
# Resolve integration (step → workflow default)
integration = config.get("integration") or context.default_integration
if integration and isinstance(integration, str) and "{{" in integration:
integration = evaluate_expression(integration, context)

# Resolve model
model = config.get("model") or context.default_model
if model and isinstance(model, str) and "{{" in model:
model = evaluate_expression(model, context)

# Attempt CLI dispatch
dispatch_result = self._try_dispatch(
prompt, integration, model, context
)

output: dict[str, Any] = {
"prompt": prompt,
"integration": integration,
"model": model,
}

if dispatch_result is not None:
output["exit_code"] = dispatch_result["exit_code"]
output["stdout"] = dispatch_result["stdout"]
output["stderr"] = dispatch_result["stderr"]
output["dispatched"] = True
if dispatch_result["exit_code"] != 0:
return StepResult(
status=StepStatus.FAILED,
output=output,
error=(
dispatch_result["stderr"]
or f"Prompt exited with code {dispatch_result['exit_code']}"
),
)
else:
output["exit_code"] = 0
output["dispatched"] = False

return StepResult(
status=StepStatus.COMPLETED,
output=output,
)
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

PromptStep returns COMPLETED with exit_code=0 when dispatch isn't possible (missing integration key/default, integration CLI not installed, or integration not found). This silently skips the step while the README describes prompt steps as being sent to an integration CLI. Consider failing (or pausing) when an integration is configured but dispatch cannot occur, and reserve the no-op behavior only for explicitly unsupported/disabled cases (with an explicit flag).

Copilot uses AI. Check for mistakes.
Comment on lines +533 to +539
# Record step results in context
step_data = {
"integration": step_config.get("integration")
or context.default_integration,
"model": step_config.get("model") or context.default_model,
"options": step_config.get("options", {}),
"input": step_config.get("input", {}),
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

When recording step_data, the engine stores raw config values for integration, model, options, and input rather than the resolved/actual values used by the step (which may be expression-derived or merged defaults). This can make steps.<id>.integration / steps.<id>.input misleading during later expression evaluation and after resume. Prefer persisting resolved values from result.output (when available) or from the step after resolution, and store resolved input/options rather than the unexpanded config.

Suggested change
# Record step results in context
step_data = {
"integration": step_config.get("integration")
or context.default_integration,
"model": step_config.get("model") or context.default_model,
"options": step_config.get("options", {}),
"input": step_config.get("input", {}),
# Record step results in context using resolved values when available.
resolved_output = result.output if isinstance(result.output, dict) else {}
step_data = {
"integration": resolved_output.get("integration")
or step_config.get("integration")
or context.default_integration,
"model": resolved_output.get("model")
or step_config.get("model")
or context.default_model,
"options": resolved_output.get("options", step_config.get("options", {})),
"input": resolved_output.get("input", step_config.get("input", {})),

Copilot uses AI. Check for mistakes.
Comment on lines +611 to +613
# Fan-out: execute nested step template per item with unique IDs
if step_type == "fan-out" and result.output.get("items"):
template = result.output.get("step_template", {})
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

Fan-out post-processing only runs when result.output.get('items') is truthy. If items resolves to an empty list, the step output never gets a results field, which makes downstream fan-in/templates inconsistent (sometimes steps.<id>.output.results exists, sometimes not). Consider always normalizing fan-out output to include results: [] even when there are zero items.

Copilot uses AI. Check for mistakes.
Comment on lines +177 to +188
if stream:
# No timeout when streaming — the user sees live output and
# can Ctrl+C at any time. The timeout parameter is only
# applied in the captured (non-streaming) branch below.
try:
result = subprocess.run(
exec_args,
stdout=sys.stdout,
stderr=sys.stderr,
text=True,
cwd=cwd,
)
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

dispatch_command(..., stream=True) pipes output via stdout=sys.stdout / stderr=sys.stderr. This can raise at runtime in environments where sys.stdout/sys.stderr lack a real fileno() (some embedding/capture setups), and it’s unnecessary because subprocess.run inherits parent stdout/stderr by default. Consider omitting stdout/stderr entirely in the streaming branch (or using None) to make streaming more robust.

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +105
def test_registry_populated(self):
from specify_cli.workflows import STEP_REGISTRY

assert len(STEP_REGISTRY) == 10

def test_all_step_types_registered(self):
from specify_cli.workflows import STEP_REGISTRY

expected = {
"command", "shell", "prompt", "gate", "if", "switch",
"while", "do-while", "fan-out", "fan-in",
}
assert set(STEP_REGISTRY.keys()) == expected

Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

The step registry tests assert len(STEP_REGISTRY) == 10 and set(STEP_REGISTRY.keys()) == expected. If the design is meant to be extensible (custom step types register into STEP_REGISTRY), these assertions will become brittle and fail as soon as another built-in or third-party step is added. Consider asserting that the expected built-in keys are a subset of the registry (and optionally that each expected key maps to the correct class), rather than requiring an exact match.

Copilot uses AI. Check for mistakes.
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.

Workflow Engine with Catalog System

3 participants