github / github/spec-kit

[Feature]: structured output from shell steps (opt-in output_format: json)

オープン
#2,962 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る
stale
主要言語
Python
スター
137k
フォーク
12.3k
平均マージ
2日 12時間
マージ済み PR(30日)
159

説明

### Problem Statement

No workflow step that runs external code can hand a **typed** value to a later step. Shell steps expose only `{exit_code, stdout, stderr}` (`src/specify_cli/workflows/steps/shell/__init__.py:42-44`), command steps the same (and their stdout streams, so it's empty in run state — see SK-style discussions around streaming), and workflow inputs are scalar-only (`string`/`number`/`boolean`). The practical consequence: a `fan-out` can never consume a dynamically-computed collection — there is no end-to-end path from "a script computed a list" to "`items:` receives a list".

#2960 (`from_json` filter) covers the consumption side for shell stdout, but a structural opt-in on the step itself would make the contract explicit and also benefit steps whose stdout isn't reliably capturable.

### Proposed Solution

An **opt-in** `output_format: json` on shell steps:

```yaml
- id: emit
type: shell
run: "python extract.py"
output_format: json
```

When set, stdout is parsed and exposed under `output.data` (raw `stdout`/`stderr`/`exit_code` keys unchanged — no merge/clobber ambiguity), so later steps can use `{{ steps.emit.output.data.items }}`. A parse failure **fails the step** with a clear error — declaring the format is a contract, and silence would hide wiring bugs. Fully backward-compatible: without the key, behavior is byte-identical.

This is a **proposal with a reference implementation** — happy to rework toward whichever direction you prefer.

### Alternatives Considered

- `output_file: ` — the step writes JSON to a file the engine reads into `output.*`; better for large payloads and streaming-stdout steps, slightly more machinery.
- A declared named-`outputs:` schema (map output names to JSON paths) — the most expressive, biggest API surface.
- Status quo + `#2960`'s `from_json` — works for shell stdout only, and leaves the contract implicit.

### Component

Workflow engine (shell step)

### AI Agent (if applicable)

n/a

### Use Cases

- Fan-out over runtime-computed items (extract → `items: {{ steps.emit.output.data.items }}`).
- Conditions/args consuming structured tool results without string hacks.

---

**Coordination note:** I'm aware open PR #2443 also touches `steps/shell/__init__.py` (security opt-in) — this change is isolated to the structured-output addition and I'm happy to rebase/coordinate in whichever order suits.

**AI disclosure (per CONTRIBUTING.md):** this issue and the accompanying reference PR were authored with AI assistance (Claude); verified by running the repo's test suite locally.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

まず src/specify_cli/workflows/steps/shell/__init__.py の 42-44 行目から始め、shell step の出力が後続の step と fan-out 項目によってどのように消費されるかを追跡します。関連する #2960 の from_json 作業と、既存の workflow 出力契約を確認します。opt-in の JSON stdout が output.data 配下で公開され、パース失敗が明確に失敗し、output_format を指定しない場合の動作が変更されないことが完了条件です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
backend
issue の種類
機能追加
難易度
4/5
見積もり時間
3〜5日
活発さ
活発
明瞭さ
おおむね明確
初心者へのやさしさ
52/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。