Skip to content

feat: replace object output with structured step outputs#2052

Merged
yottahmd merged 8 commits intomainfrom
structured-output-field-tests
Apr 29, 2026
Merged

feat: replace object output with structured step outputs#2052
yottahmd merged 8 commits intomainfrom
structured-output-field-tests

Conversation

@yottahmd
Copy link
Copy Markdown
Collaborator

@yottahmd yottahmd commented Apr 29, 2026

Summary

  • replace legacy object-form output: parsing with structured step-scoped outputs available through ${step.output} and ${step.output.foo}
  • add runtime evaluation, persistence, schema updates, and publish-only noop inference for structured outputs while keeping string-form output: NAME for run outputs
  • add focused parser, runtime, and integration coverage for the new structured output behavior

Why

  • the old object-form output: metadata did not model the step-scoped data flow users actually need
  • structured outputs on the step remove brittle shell-only data shaping and make ${step.output.*} the direct abstraction
  • keeping string-form output: NAME unchanged preserves final outputs.json collection for run summaries and API/UI consumers

Validation

  • go test ./internal/core/spec -count=1
  • go test ./internal/cmn/eval -count=1
  • go test ./internal/cmn/schema -count=1
  • go test ./internal/core/exec -count=1
  • go test ./internal/runtime ./internal/runtime/agent -count=1
  • go test ./internal/runtime/transform -count=1
  • go test ./internal/intg -run 'TestStepScopedOutputAccess|TestStepIDPropertyAccess|TestOutput' -count=1

Summary by CodeRabbit

  • New Features

    • Structured step outputs with per-entry sources (stdout/stderr/file), decode modes (text/json/yaml), and select/path extraction.
    • JSON-path-style access to nested step output fields and persisted step-scoped output exposure across runs.
    • Captured stderr support, centralized max output size limits, and a new "noop" executor for publish-only steps.
  • Removed Features

    • Runtime output JSON-schema validation disabled.
    • Legacy key/omit-based output collection removed — only canonical string-form outputs are collected.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5efde2ac-1d62-4f36-a043-73278f893086

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Refactors step outputs into structured entries (literal or sourced), adds persisted per-node OutputValue, implements structured output evaluation/decoding/select (JSON/YAML/text) with size limits, independent stderr capture, a builtin noop executor, and exposes jq-style path resolution via ResolveDataPath.

Changes

Cohort / File(s) Summary
JSON Path & Step Resolution
internal/cmn/eval/resolve_json.go, internal/cmn/eval/resolve_step.go, internal/cmn/eval/resolve_step_test.go
Refactors JSON parsing to return any, adds exported ResolveDataPath(ctx, varName, raw, path) (any, bool), separates stringify logic; resolveStepProperty recognizes .output.<field>/array access and delegates to JSON-path resolution; tests added for nested output access.
Core Step Model & Spec
internal/core/step.go, internal/core/spec/step.go, internal/core/spec/step_types.go
Removes legacy OutputKey/OutputOmit/OutputSchema; adds StructuredOutput map and StepOutputEntry with source/decode constants; parsing/validation updated; executor builder can infer noop for publish-only structured-output steps.
Schema & Schema Tests
internal/cmn/schema/dag.schema.json, internal/cmn/schema/dag_schema_test.go
Redefines step.output object shape to accept arbitrary keys mapped to structured entries; updates schema and tests to validate from/path/decode/select constraints and output.meta usage.
Execution Model Persistence
internal/core/exec/node.go, internal/runtime/transform/node.go
Adds persisted exec.Node.OutputValue *string and preserves OutputValue across runtime↔persistence conversions.
Runtime Output Capture & Evaluation
internal/runtime/node.go, internal/runtime/output.go, internal/runtime/output_limits.go, internal/runtime/output_test.go, internal/runtime/node_structured_output_test.go
Implements structured output evaluation (literal or from stdout/stderr/file), decoding (text/json/yaml), optional select via ResolveDataPath, JSON-serializes published structured output, enforces per-entry and aggregate max-size, removes legacy schema-enforced validation, and adds independent stderr capture and tests.
Runtime Data & Agent
internal/runtime/data.go, internal/runtime/agent/agent.go, internal/runtime/agent/collect_outputs_test.go, internal/runtime/agent/agent_test.go, internal/runtime/data_output_test.go
Adds NodeState.OutputValue and helpers (setOutputValue, StringFormOutputValue); collectOutputs simplified to use canonical string-form output value; tests updated/added to reflect new behavior and legacy fallback.
Builtin Noop Executor
internal/runtime/builtin/builtin.go, internal/runtime/builtin/noop/noop.go
Adds and registers a builtin noop executor (no-op Run/Kill) used for publish-only steps.
Tests: added / removed
internal/core/spec/step_output_test.go, internal/core/spec/step_output_schema_test.go (deleted), internal/core/spec/step_test.go (deleted tests), internal/intg/output_validation_e2e_test.go (deleted), internal/runtime/node_output_validation_*.go (deleted), internal/runtime/node_structured_output_test.go
Adds comprehensive structured-output parsing/behavior tests; removes many legacy output-schema compilation/validation and integration E2E tests.
Integration & Step-Ref Tests
internal/intg/output_test.go, internal/intg/stepref_test.go
Updates integration tests for structured outputs and expands step-ref tests to cover nested JSON property access and structured decoding/select across sources; asserts node OutputValue where applicable.
Misc runtime fixes
internal/runtime/env.go, internal/runtime/condition.go
Minor loop/index fix in Env.WithEnvVars and centralizes default max output size via defaultMaxOutputSizeBytes.

Sequence Diagram

sequenceDiagram
    actor User
    participant DAG as DAG / Step Config
    participant Executor as Executor
    participant Stdout as Stdout Capture
    participant Stderr as Stderr Capture
    participant FS as File System
    participant Decoder as Decoder (text/json/yaml)
    participant Selector as ResolveDataPath
    participant Output as StructuredOutput JSON

    User->>DAG: Define structured output (literal or from:{stdout,stderr,file}, decode, select)
    DAG->>Executor: Start step
    Executor->>Stdout: Capture stdout
    Executor->>Stderr: Capture stderr
    Executor->>FS: Read file (if from:file)

    alt Literal value
        DAG->>Output: Expand literal and include
    else Sourced value
        Stdout->>Decoder: Provide captured stdout (when used)
        Stderr->>Decoder: Provide captured stderr (when used)
        FS->>Decoder: Provide file contents (when used)
        Decoder->>Selector: Decode then optionally select path via ResolveDataPath
        Selector->>Output: Return fragment or full decoded value
    end

    Output-->>Executor: JSON-serialize structured map
    Executor-->>DAG: Persist JSON as Node.OutputValue and expose via ${step.output.*}
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.61% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the primary change: replacing legacy object-form output with a new structured output system for steps.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch structured-output-field-tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
internal/runtime/node.go (1)

579-585: Duplicate logic for default max output size.

The default value 1024 * 1024 is duplicated here and in output.go (lines 144, 180). Consider extracting this to a constant or reusing defaultMaxOutputSize from internal/core/dag.go (context snippet shows it exists there).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runtime/node.go` around lines 579 - 585, The literal default
1024*1024 in maxOutputSize is duplicated; change maxOutputSize (in
internal/runtime node.go) to use the shared default constant
(defaultMaxOutputSize) instead of the hardcoded literal — import or reference
the constant from internal/core/dag.go (where defaultMaxOutputSize is defined)
so both this function and the uses in output.go reuse the single source of
truth.
internal/cmn/schema/dag_schema_test.go (1)

220-268: Consider adding negative test cases for structured output validation.

The test covers valid configurations but lacks negative cases that verify schema rejection of invalid structured output configurations (e.g., invalid from values, missing required fields when from is file). Other tests in this file (like TestDAGSchemaParams) include wantErr cases for comprehensive validation coverage.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmn/schema/dag_schema_test.go` around lines 220 - 268,
TestDAGSchemaStepOutputObject currently only asserts valid specs; add negative
test cases that assert resolved.Validate(doc) returns errors for invalid
structured output definitions—e.g., a spec with output.version.from:
invalid_source, one with from: file but missing required file path or pattern,
and one with an invalid decode value—using the same pattern as existing
table-driven tests (use mustParseYAMLDocument to build doc and check err via
require.Error and require.Contains on err.Error()); keep tests inside
TestDAGSchemaStepOutputObject and leverage mustResolveDAGSchema and
resolved.Validate to locate the schema validation logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/cmn/schema/dag.schema.json`:
- Around line 1307-1313: The schema for the step "output" entry is too
permissive because the object branch sets additionalProperties: true; change it
to validate only the allowed structured keys by replacing additionalProperties:
true with additionalProperties: false and add an explicit "properties" object
listing allowed fields (e.g., "value", "from", "path", "decode", "select") and
their expected types/constraints, while keeping the alternative branches that
accept literal JSON values (string/number/boolean/null) so literal outputs still
validate; update the same "output" schema instance referenced by step.output.*
in dag.schema.json to use a oneOf/anyOf that permits primitives OR the
constrained structured object.

In `@internal/runtime/node.go`:
- Around line 496-511: Remove the TOCTOU-prone size check that uses
os.Stat/info.Size(): delete the branch that compares info.Size() >
maxOutputSize(ctx) (and its associated error return) while keeping the os.Stat
call only if you need to early-check existence/permissions; otherwise remove the
os.Stat call entirely and rely on os.ReadFile followed by the existing post-read
size check against maxOutputSize(ctx). Update error messages to use the existing
fmt.Errorf patterns referencing key and path and ensure the only
size-enforcement happens after reading (using maxOutputSize(ctx), os.ReadFile,
and len(data)).

---

Nitpick comments:
In `@internal/cmn/schema/dag_schema_test.go`:
- Around line 220-268: TestDAGSchemaStepOutputObject currently only asserts
valid specs; add negative test cases that assert resolved.Validate(doc) returns
errors for invalid structured output definitions—e.g., a spec with
output.version.from: invalid_source, one with from: file but missing required
file path or pattern, and one with an invalid decode value—using the same
pattern as existing table-driven tests (use mustParseYAMLDocument to build doc
and check err via require.Error and require.Contains on err.Error()); keep tests
inside TestDAGSchemaStepOutputObject and leverage mustResolveDAGSchema and
resolved.Validate to locate the schema validation logic.

In `@internal/runtime/node.go`:
- Around line 579-585: The literal default 1024*1024 in maxOutputSize is
duplicated; change maxOutputSize (in internal/runtime node.go) to use the shared
default constant (defaultMaxOutputSize) instead of the hardcoded literal —
import or reference the constant from internal/core/dag.go (where
defaultMaxOutputSize is defined) so both this function and the uses in output.go
reuse the single source of truth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1520d12b-0b5d-4b04-8ec4-61352511b736

📥 Commits

Reviewing files that changed from the base of the PR and between 405cc68 and d0dd945.

📒 Files selected for processing (27)
  • internal/cmn/eval/resolve_json.go
  • internal/cmn/eval/resolve_step.go
  • internal/cmn/eval/resolve_step_test.go
  • internal/cmn/schema/dag.schema.json
  • internal/cmn/schema/dag_schema_test.go
  • internal/core/exec/node.go
  • internal/core/spec/step.go
  • internal/core/spec/step_output_schema_test.go
  • internal/core/spec/step_output_test.go
  • internal/core/spec/step_test.go
  • internal/core/spec/step_types.go
  • internal/core/step.go
  • internal/intg/output_test.go
  • internal/intg/output_validation_e2e_test.go
  • internal/intg/stepref_test.go
  • internal/runtime/agent/agent.go
  • internal/runtime/agent/agent_test.go
  • internal/runtime/builtin/builtin.go
  • internal/runtime/builtin/noop/noop.go
  • internal/runtime/data.go
  • internal/runtime/node.go
  • internal/runtime/node_output_validation_edge_test.go
  • internal/runtime/node_output_validation_test.go
  • internal/runtime/node_structured_output_test.go
  • internal/runtime/output.go
  • internal/runtime/output_test.go
  • internal/runtime/transform/node.go
💤 Files with no reviewable changes (5)
  • internal/core/spec/step_output_schema_test.go
  • internal/runtime/node_output_validation_test.go
  • internal/core/spec/step_test.go
  • internal/runtime/node_output_validation_edge_test.go
  • internal/intg/output_validation_e2e_test.go

Comment thread internal/cmn/schema/dag.schema.json
Comment thread internal/runtime/node.go Outdated
@yottahmd
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@yottahmd
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
internal/cmn/schema/dag_schema_test.go (1)

253-284: Tighten the negative assertions for the structured-output cases.

All three failures only check for "did not validate", so an unrelated schema error would still make these tests pass. Assert the relevant field/rule (from, path, decode) or validate the specific output-entry definition directly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmn/schema/dag_schema_test.go` around lines 253 - 284, The tests
named RejectInvalidStructuredSource, RejectFileSourceWithoutPath, and
RejectInvalidDecode currently only assert the generic "did not validate"
message; tighten each to assert the specific failing field/rule so unrelated
schema errors won't make them pass. Update the assertions in dag_schema_test.go
for the cases (named above) to check the error string contains the relevant
token ("from" for RejectInvalidStructuredSource, "path" for
RejectFileSourceWithoutPath, and "decode" for RejectInvalidDecode) or validate
the specific output-entry structure directly instead of the generic message.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/core/spec/step.go`:
- Around line 1544-1555: The function shouldInferNoopStep currently treats any
step with structured output as eligible for inferring a noop, which incorrectly
matches stream-backed outputs like `{from: "stdout"}` and `{from: "stderr"}`;
update shouldInferNoopStep(result *core.Step, s *step) to return false when the
structured output is sourced from a stream by inspecting the step's
structured-output entries (e.g., iterate result.StructuredOutputs /
result.Outputs or use the accessor that backs HasStructuredOutput()) and if any
entry has From == "stdout" or From == "stderr" (or a Source/Type indicating a
stream) then bail out — keep the existing checks (ExecutorConfig,
Container/SubDAG/Parallel, nil s, command/exec/script) but add this additional
guard before returning true.

In `@internal/runtime/output.go`:
- Around line 167-179: The code clears oc.stderrOutputData (and resets
oc.stderrOutputCaptured) whenever a new stderr pipe is created, which loses
earlier attempts' stderr; to fix, do not reset oc.stderrOutputData (and avoid
clearing oc.stderrOutputCaptured) when assigning a new pipe in the
needStderrCapture branch—only initialize oc.maxOutputSize and
oc.stderrCapture/new pipe and call oc.stderrCapture.start(ctx,
oc.stderrOutputReader) while preserving any existing oc.stderrOutputData so
capturedStderr() can append across retries (refer to needStderrCapture,
oc.stderrOutputReader, oc.stderrOutputWriter, oc.stderrOutputData,
oc.stderrOutputCaptured, oc.maxOutputSize, and oc.stderrCapture.start).

---

Nitpick comments:
In `@internal/cmn/schema/dag_schema_test.go`:
- Around line 253-284: The tests named RejectInvalidStructuredSource,
RejectFileSourceWithoutPath, and RejectInvalidDecode currently only assert the
generic "did not validate" message; tighten each to assert the specific failing
field/rule so unrelated schema errors won't make them pass. Update the
assertions in dag_schema_test.go for the cases (named above) to check the error
string contains the relevant token ("from" for RejectInvalidStructuredSource,
"path" for RejectFileSourceWithoutPath, and "decode" for RejectInvalidDecode) or
validate the specific output-entry structure directly instead of the generic
message.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8160b740-0255-4347-b50b-06b45cd33142

📥 Commits

Reviewing files that changed from the base of the PR and between d0dd945 and 0626ffe.

📒 Files selected for processing (13)
  • internal/cmn/schema/dag.schema.json
  • internal/cmn/schema/dag_schema_test.go
  • internal/core/spec/step.go
  • internal/intg/stepref_test.go
  • internal/runtime/agent/agent.go
  • internal/runtime/agent/collect_outputs_test.go
  • internal/runtime/condition.go
  • internal/runtime/data.go
  • internal/runtime/data_output_test.go
  • internal/runtime/node.go
  • internal/runtime/node_structured_output_test.go
  • internal/runtime/output.go
  • internal/runtime/output_limits.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/intg/stepref_test.go
  • internal/runtime/agent/agent.go

Comment thread internal/core/spec/step.go
Comment thread internal/runtime/output.go
@yottahmd
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/runtime/node.go (1)

438-446: Reject select when decode is text or omitted.

In the ""/text branch, entry.Select is ignored and the full trimmed string is returned. That makes a misconfigured entry look valid while publishing the wrong value. I'd fail fast here (or validate earlier) unless select is only allowed with json/yaml.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runtime/node.go` around lines 438 - 446, The branch handling
text/default decode (when entry.Decode is "" or core.StepOutputDecodeText) must
reject any non-empty entry.Select to fail fast; update the switch case that
currently returns strings.TrimSpace(raw) so it first checks if entry.Select !=
"" and returns a clear error (e.g. "%s: select is not allowed with text decode")
referencing entry.Decode and key, otherwise continue to return the trimmed
string; this change should live alongside the existing cases and keep structured
decoding via decodeStructuredOutputValue for JSON/YAML only.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/runtime/node.go`:
- Around line 450-463: readStructuredOutputSource currently feeds truncated
stream-backed payloads (from outputs.capturedOutput / outputs.capturedStderr)
into structured decoding, causing inconsistent behavior versus file-backed
sources; change outputs.capturedOutput and outputs.capturedStderr to propagate
an explicit overflow signal (e.g., return a sentinel error ErrOutputTruncated or
a boolean flag) when truncation to the configured max size occurred, and update
Node.readStructuredOutputSource to detect that signal and return the same
explicit "output exceeded maximum size limit" error for stdout/stderr sources
(instead of proceeding to parse or silently publishing truncated text), ensuring
parity with file source behavior; locate symbols
Node.readStructuredOutputSource, outputs.capturedOutput, outputs.capturedStderr
and the file-source error path to mirror its error text/behavior.

---

Nitpick comments:
In `@internal/runtime/node.go`:
- Around line 438-446: The branch handling text/default decode (when
entry.Decode is "" or core.StepOutputDecodeText) must reject any non-empty
entry.Select to fail fast; update the switch case that currently returns
strings.TrimSpace(raw) so it first checks if entry.Select != "" and returns a
clear error (e.g. "%s: select is not allowed with text decode") referencing
entry.Decode and key, otherwise continue to return the trimmed string; this
change should live alongside the existing cases and keep structured decoding via
decodeStructuredOutputValue for JSON/YAML only.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ad752138-41c1-483f-a12b-564429aa9c64

📥 Commits

Reviewing files that changed from the base of the PR and between 0626ffe and 15d3781.

📒 Files selected for processing (2)
  • internal/runtime/env.go
  • internal/runtime/node.go

Comment thread internal/runtime/node.go
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/core/spec/step.go`:
- Around line 1555-1558: The noop inference currently checks raw s.Script and
can miss whitespace-only scripts; change the check to use the normalized/trimmed
script (the same normalization used by buildStepScript) so that a script of "  "
is treated as empty—i.e., replace the raw comparison to s.Script == "" with a
trimmed/script-normalized value (use strings.TrimSpace(s.Script) or call the
same builder helper used elsewhere) in the noop inference path so that the
condition (s.Command == nil && s.Exec == nil && trimmedScript == "") correctly
detects no-op steps.
- Around line 1023-1033: The parser currently accepts core.StepOutputDecodeText
while the runtime only supports "" (default treated as JSON),
core.StepOutputDecodeJSON, and core.StepOutputDecodeYAML; update the validation
in the switch over entry.Decode to only allow "", core.StepOutputDecodeJSON, and
core.StepOutputDecodeYAML (remove core.StepOutputDecodeText), and change the
select check so entry.Select is permitted when entry.Decode is "" or
core.StepOutputDecodeJSON or core.StepOutputDecodeYAML (i.e., treat the empty
decode as JSON) to keep parsing consistent with internal/runtime/node.go
handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5cfc527b-3a10-4f6f-abff-5fae050d071e

📥 Commits

Reviewing files that changed from the base of the PR and between 15d3781 and b952f6e.

📒 Files selected for processing (4)
  • internal/core/spec/step.go
  • internal/core/spec/step_output_test.go
  • internal/runtime/output.go
  • internal/runtime/output_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/core/spec/step_output_test.go

Comment thread internal/core/spec/step.go
Comment thread internal/core/spec/step.go Outdated
@yottahmd yottahmd merged commit 44cfcf3 into main Apr 29, 2026
16 of 17 checks passed
@yottahmd yottahmd deleted the structured-output-field-tests branch April 29, 2026 11:28
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.

1 participant