Skip to content

feat(workflows): support file-backed inputs#2420

Open
Adr1an04 wants to merge 4 commits intogithub:mainfrom
Adr1an04:feat/workflow-input-file-refs
Open

feat(workflows): support file-backed inputs#2420
Adr1an04 wants to merge 4 commits intogithub:mainfrom
Adr1an04:feat/workflow-input-file-refs

Conversation

@Adr1an04
Copy link
Copy Markdown
Contributor

Refs #2405

Summary

This PR adds support for passing workflow inputs from files.

You can still pass inputs inline with repeated --input key=value flags. For longer values, you can now use key=@path, and for multiple values you can use a JSON file with --input-file.

This is handled generically for workflow inputs/parameters, not just for spec.

What changed

  • Added CLI-side parsing for workflow inputs.
  • Added support for --input key=@path for any workflow input key.
  • Added --input-file payload.json to load multiple inputs from a JSON object.
  • Made direct --input values override values loaded from --input-file.
  • Added clear errors for missing input files, invalid JSON, and non-object JSON.
  • Updated the workflow docs with generic examples.

Examples

specify workflow run ./workflow.yml --input prompt=@docs/prompt.md
specify workflow run ./workflow.yml --input-file payload.json
specify workflow run ./workflow.yml --input-file payload.json --input scope=full

Notes

File references are not spec-specific. They work for any workflow input key.

Values starting with @ are only read from a file when that file exists. This keeps literal values like @alice or @ working as normal strings.

--input-file values are loaded first, then direct --input values are applied after that. This lets command-line values override the JSON file.

What did not change

  • No changes to WorkflowEngine behavior.
  • No new workflow execution semantics.
  • Workflow definitions were not made Spec Kit-specific.
  • --input-file only accepts a JSON object.
  • File-backed --input key=@path values are read as UTF-8 text.

Testing

I ran focused workflow input regression tests:

uv run python -m pytest tests/test_workflows.py -k WorkflowCliInputs -v
# 12 passed, 126 deselected in 0.15s

I also ran the full workflow test file:

uv run python -m pytest tests/test_workflows.py -v
# 138 passed in 0.30s

I used the existing agent config consistency test:

uv run python -m pytest tests/test_agent_config_consistency.py -q
# 24 passed in 0.13s

I ran the full test suite:

uv run python -m pytest -q
# 1833 passed, 29 skipped, 18 warnings in 20.25s

CLI-level validation

I tested the workflow CLI directly in a temporary Spec Kit project.

Covered cases:

  • --input key=@path reads an existing UTF-8 text file.
  • File references work for generic input keys like prompt and description, not only spec.
  • Repeated --input key=value values still work.
  • Literal values like @alice and bare @ stay unchanged.
  • Missing @path values stay literal.
  • --input-file payload.json loads multiple inputs from a JSON object.
  • Direct --input values override values loaded from --input-file.
  • Direct overrides can also use key=@path.
  • Missing --input-file exits cleanly with code 1.
  • Invalid JSON exits cleanly with code 1.
  • Non-object JSON exits cleanly with code 1.

Smoke test output:

PASS direct file refs and literal @ values
PASS input-file values with CLI override precedence
PASS missing @path remains literal
PASS missing --input-file exits 1
PASS invalid JSON exits 1
PASS non-object JSON exits 1
CLI smoke tests passed

I also checked the command help and confirmed the new CLI options are exposed:

uv run specify workflow run --help
# shows --input / -i with key=@path help
# shows --input-file for JSON object input files
Screenshot 2026-04-29 at 11 35 48 PM CLI smoke test screenshot showing successful file-backed inputs, JSON input-file overrides, literal `@` handling, and clean error cases for missing/invalid input files.

AI assistance note

I used ChatGPT to help think through edge cases and wording. I wrote, reviewed, and tested the code locally before opening this PR.

Copilot AI review requested due to automatic review settings April 30, 2026 03:39
@Adr1an04 Adr1an04 requested a review from mnriem as a code owner April 30, 2026 03: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 generic CLI support for providing workflow inputs from files (single values via key=@path and bulk values via --input-file JSON), keeping existing inline --input key=value behavior and defining clear precedence/validation at the CLI boundary.

Changes:

  • Added _parse_workflow_inputs (plus helpers) to normalize --input and --input-file into the workflow engine input dict.
  • Extended workflow run CLI options with --input-file and --input key=@path semantics (CLI values override file values).
  • Added regression tests for parsing/precedence/error cases and updated workflow CLI documentation examples.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/specify_cli/__init__.py Implements file-backed input parsing helpers and wires them into workflow run via new CLI options.
tests/test_workflows.py Adds targeted tests covering @file inputs, --input-file JSON loading, precedence, and failure modes.
docs/reference/workflows.md Updates CLI reference docs with the new options and usage examples.

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

Comment thread src/specify_cli/__init__.py Outdated
Comment on lines +5070 to +5071
if file_ref and _resolve_workflow_cli_path(file_ref).exists():
_, value = _read_workflow_cli_file(file_ref, f"input {key!r}")
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

@path handling checks only Path.exists() before treating the value as a file reference. This means values like --input x=@. or --input x=@some_dir (existing directories) will be interpreted as file refs and then fail with “is not a file”, instead of staying literal as intended for non-file @ values. Consider requiring is_file() (or catching the non-file case and leaving the value unchanged) before calling _read_workflow_cli_file().

Suggested change
if file_ref and _resolve_workflow_cli_path(file_ref).exists():
_, value = _read_workflow_cli_file(file_ref, f"input {key!r}")
if file_ref:
candidate_path = _resolve_workflow_cli_path(file_ref)
if candidate_path.exists() and candidate_path.is_file():
_, value = _read_workflow_cli_file(
file_ref, f"input {key!r}"
)

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


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

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


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

Comment thread docs/reference/workflows.md Outdated
| `--input-file` | Load workflow inputs/parameters from a JSON object file; repeatable `--input` values override file values |

Runs a workflow from a catalog ID, URL, or local file path. Inputs declared by the workflow can be provided via `--input` or will be prompted interactively.
Runs a workflow from a catalog ID, URL, or local file path. Inputs/parameters declared by the workflow can be provided via `--input` or will be prompted interactively.
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

The docs claim specify workflow run accepts a "URL", but the current implementation routes source to WorkflowEngine.load_workflow(), which only supports an installed workflow ID or a local .yml/.yaml path. Consider updating this sentence to avoid implying URL support for workflow run (URL support appears to apply to workflow add, not run).

Suggested change
Runs a workflow from a catalog ID, URL, or local file path. Inputs/parameters declared by the workflow can be provided via `--input` or will be prompted interactively.
Runs a workflow from an installed workflow ID or a local `.yml`/`.yaml` file path. Inputs/parameters declared by the workflow can be provided via `--input` or will be prompted interactively.

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.


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

Comment thread src/specify_cli/__init__.py Outdated
None,
"--input",
"-i",
help="Input values as key=value pairs; use key=@path to read a text file",
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

The --input help text implies key=@path will read a file, but the implementation only reads when the referenced file exists; otherwise the value stays literal (by design for values like @alice). Consider reflecting that nuance in the help string to avoid silent surprises when users typo a path.

Suggested change
help="Input values as key=value pairs; use key=@path to read a text file",
help=(
"Input values as key=value pairs; use key=@path to read a text "
"file when the path exists, otherwise the value is treated "
"literally"
),

Copilot uses AI. Check for mistakes.
Comment thread docs/reference/workflows.md Outdated
Comment on lines +13 to +16
| `-i` / `--input` | Pass workflow inputs/parameters as `key=value` (repeatable); use `key=@path` to read text files |
| `--input-file` | Load workflow inputs/parameters from a JSON object file; repeatable `--input` values override file values |

Runs a workflow from a catalog ID, URL, or local file path. Inputs declared by the workflow can be provided via `--input` or will be prompted interactively.
Runs a workflow from an installed workflow ID or a local `.yml`/`.yaml` file path. Inputs/parameters declared by the workflow can be provided via `--input` or will be prompted interactively.
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

Docs describe key=@path as reading text files, but the CLI only reads from a file when that path exists; otherwise the value is treated as a literal string. Also, the paragraph below the table mentions only --input even though --input-file is now supported—consider mentioning both for clarity.

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


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

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


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

@Adr1an04
Copy link
Copy Markdown
Contributor Author

@mnriem I handled Copilots feedback and made sure to take into account your message in the issue. Let me know if you need me to edit anything! :D

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.

2 participants