Skip to content

feat(workflows): add JSON output for workflow run resume and status#2814

Open
doquanghuy wants to merge 1 commit into
github:mainfrom
doquanghuy:feat/2811-workflow-json
Open

feat(workflows): add JSON output for workflow run resume and status#2814
doquanghuy wants to merge 1 commit into
github:mainfrom
doquanghuy:feat/2811-workflow-json

Conversation

@doquanghuy
Copy link
Copy Markdown
Contributor

@doquanghuy doquanghuy commented Jun 2, 2026

Description

Closes #2811.

Adds an opt-in --json flag to workflow run, workflow resume, and workflow status, giving automation a machine-readable view of workflow terminal states (completed / paused / failed / aborted) and the run id, instead of scraping human prose or reading internal state.json files.

// specify workflow run wf.yml --json
{ "run_id": "662bf791", "workflow_id": "smoke", "status": "paused",
  "current_step_id": "ask", "current_step_index": 0 }

status --json additionally reports per-step states (single run) or a runs list (no run id).

What changed

  • --json option on the three commands; a shared _workflow_run_payload() builder for run/resume and a shared _emit_workflow_json() emitter.
  • JSON is emitted via plain stdout (not console.print) so Rich markup, highlighting, and line-wrapping can never alter the object — verified by a test asserting the output contains no ANSI/markup and round-trips. (This is intentionally not routed through Rich the way version --features --json is.)
  • When --json is set, the step-progress callback and banners are suppressed so stdout is a single parseable object.
  • Reference docs updated (docs/reference/workflows.md).

Compatibility

  • Default (no --json) output and exit codes are unchanged.
  • Usage/lookup errors (e.g. run not found) remain human-readable on the existing path — the JSON object represents a run outcome, not error reporting. Happy to extend to JSON errors if you'd prefer.

Testing

  • Tested locally with uv run specify --help
  • uv sync --extra test && uv run pytest — 3313 passed, 40 skipped; ruff check src/ clean
  • Manually verified run/status (single + list)/resume --json produce parseable output and that default output is unchanged

Tests in tests/test_workflows.py::TestWorkflowJsonOutput cover completed/paused run JSON, status (single + list), resume JSON, default output staying human (non-JSON), and that --json output carries no markup/ANSI.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Used Claude to implement the flag, tests, and docs. Behaviour was verified locally and the diff reviewed before submission.


Per CONTRIBUTING.md (new CLI arguments should be agreed first), #2811 is the discussion issue and this PR is the concrete proposal — happy to adjust the payload shape or hold it. @mnriem a steer on whether this is wanted and on the field set would be appreciated.

Adds an opt-in `--json` flag to `workflow run`, `workflow resume`, and
`workflow status` that emits a single machine-readable object (run_id,
workflow_id, status, current step; status also reports per-step states
and a runs list) for automation and external orchestrators.

JSON is written via a small `_emit_workflow_json` helper using plain
stdout, so Rich markup, highlighting, and line-wrapping can never alter
the emitted object. Default human-readable output and exit codes are
unchanged when `--json` is omitted. Reference docs updated.

Closes github#2811.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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 an opt-in --json flag to specify workflow run, workflow resume, and workflow status so automation can consume machine-readable workflow outcomes (run id + terminal status) without scraping Rich-formatted text.

Changes:

  • Added shared JSON payload/emission helpers and a --json option to the three workflow CLI commands.
  • Added pytest coverage for JSON output shape and for “no Rich markup/ANSI” on the JSON path.
  • Updated workflow reference docs to describe the new flag.
Show a summary per file
File Description
src/specify_cli/__init__.py Implements --json options and emits JSON payloads for run/resume/status.
tests/test_workflows.py Adds CLI-level tests validating JSON output and ensuring it round-trips without ANSI/markup.
docs/reference/workflows.md Documents the new --json flags for run/resume/status.

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/init.py:4253

  • --json mode currently doesn't ensure stdout remains a single parseable JSON object because workflow steps can still stream output to stdout during execution. In particular, command steps call IntegrationBase.dispatch_command(..., stream=True) by default (streams subprocess stdout/stderr directly to the terminal), and prompt steps run subprocess.run(...) without capturing output—both will interleave human output before the final JSON and break json.loads() for real workflows like workflows/speckit/workflow.yml that use command: steps.
    try:
        state = engine.execute(definition, inputs)
    except ValueError as exc:
        console.print(f"[red]Error:[/red] {exc}")
        raise typer.Exit(1)
  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment on lines +27 to +30
specify workflow run wf.yml --json
# {"run_id": "662bf791", "workflow_id": "wf", "status": "paused",
# "current_step_id": "review", "current_step_index": 0}
```
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]: Machine-readable output for workflow run, resume, and status

3 participants