F060: Built-in jq Transform Operation
User Stories
US1: Apply jq Expression to JSON String Input (P1 - Must Have)
As a workflow author,
I want to apply a jq expression to a JSON string within an operation step,
So that I can filter, extract, and reshape JSON data between workflow steps without shelling out to external tools.
Acceptance Scenarios:
- Given a step with
operation: transform.jq and inputs.expression: ".name" and inputs.data: '{"name":"alice","age":30}', when the step executes, then the output contains result: "alice"
- Given a step with
operation: transform.jq and inputs.expression: ".items[] | select(.status == \"active\")" and valid JSON array input, when the step executes, then the output contains only the matching objects
- Given a step whose
inputs.data references a previous step output via {{states.fetch_api.output}}, when the step executes, then the jq expression is applied to the resolved JSON string
Independent Test: Create a workflow with a single transform.jq operation step using a hardcoded JSON string and verify {{states.step_name.result}} contains the expected filtered value.
US2: Chain Multiple Transformations Across Steps (P1 - Must Have)
As a workflow author,
I want to pipe the jq output of one step as input to another transform step,
So that I can build multi-stage data transformation pipelines within a workflow.
Acceptance Scenarios:
- Given step A outputs
result: '[{"id":1},{"id":2}]' and step B uses inputs.data: "{{states.step_a.result}}" with inputs.expression: ".[0].id", when step B executes, then result: "1"
- Given a three-step pipeline (fetch → filter → reshape), when all steps complete, then the final output reflects the composed transformation
Independent Test: Create a two-step workflow where step 1 extracts an array from a JSON object and step 2 selects an element from that array. Verify final output.
US3: Handle Invalid Input and Expression Errors (P2 - Should Have)
As a workflow author,
I want clear error messages when my jq expression is invalid or the input is not valid JSON,
So that I can diagnose and fix data transformation issues quickly.
Acceptance Scenarios:
- Given
inputs.data contains non-JSON text (e.g., "not json"), when the step executes, then the operation returns success: false with an error message containing "invalid JSON"
- Given
inputs.expression contains a syntax error (e.g., ".foo ||| bar"), when the step executes, then the operation returns success: false with an error message containing "invalid jq expression"
- Given
inputs.data is an empty string, when the step executes, then the operation returns success: false with an error describing the empty input
Independent Test: Create a workflow with intentionally invalid JSON input and verify the error output includes a descriptive message. Repeat with an invalid expression.
US4: Produce Compact or Pretty-Printed Output (P3 - Nice to Have)
As a workflow author,
I want to control whether the jq output is compact or pretty-printed,
So that I can optimize for readability in logs or compactness for downstream consumption.
Acceptance Scenarios:
- Given
inputs.compact: true (default), when the step executes, then result contains single-line JSON without extra whitespace
- Given
inputs.compact: false, when the step executes, then result contains indented, human-readable JSON
Independent Test: Execute the same jq expression with compact: true and compact: false and compare the output formatting.
Requirements
Functional Requirements
- FR-001: The system shall provide a
transform.jq operation accessible via operation: transform.jq in workflow step definitions.
- FR-002: The operation shall accept a
data input (string, required) containing valid JSON and an expression input (string, required) containing a valid jq expression.
- FR-003: The operation shall apply the jq expression to the parsed JSON input and return the result as a JSON string in the
result output field.
- FR-004: The operation shall accept an optional
compact input (boolean, default true) controlling output formatting.
- FR-005: The operation shall return
success: false with a descriptive error string when the input is not valid JSON.
- FR-006: The operation shall return
success: false with a descriptive error string when the expression is syntactically invalid.
- FR-007: The operation shall support standard jq features: field access, array indexing, pipe (
|), select, map, keys, length, type, to_entries, from_entries, object construction, and array slicing.
- FR-008: The operation shall be registered via
CompositeOperationProvider alongside existing github.* and notify.* providers.
- FR-009: The operation shall respect
context.Context cancellation for long-running expressions.
Non-Functional Requirements
- NFR-001: Expression evaluation shall complete in < 50ms for inputs up to 1 MB.
- NFR-002: The implementation shall use a pure-Go jq library (no CGO, no external
jq binary dependency) to maintain cross-platform portability.
- NFR-003: The operation shall not log or expose raw input data at INFO level to prevent accidental secret leakage; input data shall only appear at DEBUG level.
- NFR-004: The implementation shall follow the established
OperationProvider pattern from F054/F056 with infrastructure-internal types (no new domain entities).
Success Criteria
Key Entities
| Entity |
Description |
Attributes |
| TransformOperationProvider |
Implements ports.OperationProvider for transform.* namespace |
operations map, Execute dispatch |
| JqEvaluator |
Applies a jq expression to parsed JSON data |
expression string, input any, compact bool |
| TransformInput |
Validated input for transform.jq |
data (string), expression (string), compact (bool) |
Metadata
- Status: backlog
- Version: v0.4.0
- Priority: medium
- Estimation: M
Dependencies
- Blocked by: F057
- Unblocks: none
Clarifications
Section populated during clarify step with resolved ambiguities.
Notes
- Pure-Go jq library candidates:
itchyny/gojq (MIT, widely used, full jq compatibility). Evaluate at implementation time.
- Follow F054/F056 pattern:
internal/infrastructure/transform/ package with provider.go, operations.go, jq.go, jq_test.go, doc.go.
- Register in
CompositeOperationProvider in run.go alongside github and notify providers.
- Single operation initially (
transform.jq); namespace transform.* reserves space for future operations (e.g., transform.jsonpath, transform.xpath).
- No external binary dependency — unlike F054's
gh CLI fallback pattern, jq evaluation must be fully embedded.
F060: Built-in jq Transform Operation
User Stories
US1: Apply jq Expression to JSON String Input (P1 - Must Have)
As a workflow author,
I want to apply a jq expression to a JSON string within an operation step,
So that I can filter, extract, and reshape JSON data between workflow steps without shelling out to external tools.
Acceptance Scenarios:
operation: transform.jqandinputs.expression: ".name"andinputs.data: '{"name":"alice","age":30}', when the step executes, then the output containsresult: "alice"operation: transform.jqandinputs.expression: ".items[] | select(.status == \"active\")"and valid JSON array input, when the step executes, then the output contains only the matching objectsinputs.datareferences a previous step output via{{states.fetch_api.output}}, when the step executes, then the jq expression is applied to the resolved JSON stringIndependent Test: Create a workflow with a single
transform.jqoperation step using a hardcoded JSON string and verify{{states.step_name.result}}contains the expected filtered value.US2: Chain Multiple Transformations Across Steps (P1 - Must Have)
As a workflow author,
I want to pipe the jq output of one step as input to another transform step,
So that I can build multi-stage data transformation pipelines within a workflow.
Acceptance Scenarios:
result: '[{"id":1},{"id":2}]'and step B usesinputs.data: "{{states.step_a.result}}"withinputs.expression: ".[0].id", when step B executes, thenresult: "1"Independent Test: Create a two-step workflow where step 1 extracts an array from a JSON object and step 2 selects an element from that array. Verify final output.
US3: Handle Invalid Input and Expression Errors (P2 - Should Have)
As a workflow author,
I want clear error messages when my jq expression is invalid or the input is not valid JSON,
So that I can diagnose and fix data transformation issues quickly.
Acceptance Scenarios:
inputs.datacontains non-JSON text (e.g.,"not json"), when the step executes, then the operation returnssuccess: falsewith an error message containing "invalid JSON"inputs.expressioncontains a syntax error (e.g.,".foo ||| bar"), when the step executes, then the operation returnssuccess: falsewith an error message containing "invalid jq expression"inputs.datais an empty string, when the step executes, then the operation returnssuccess: falsewith an error describing the empty inputIndependent Test: Create a workflow with intentionally invalid JSON input and verify the error output includes a descriptive message. Repeat with an invalid expression.
US4: Produce Compact or Pretty-Printed Output (P3 - Nice to Have)
As a workflow author,
I want to control whether the jq output is compact or pretty-printed,
So that I can optimize for readability in logs or compactness for downstream consumption.
Acceptance Scenarios:
inputs.compact: true(default), when the step executes, thenresultcontains single-line JSON without extra whitespaceinputs.compact: false, when the step executes, thenresultcontains indented, human-readable JSONIndependent Test: Execute the same jq expression with
compact: trueandcompact: falseand compare the output formatting.Requirements
Functional Requirements
transform.jqoperation accessible viaoperation: transform.jqin workflow step definitions.datainput (string, required) containing valid JSON and anexpressioninput (string, required) containing a valid jq expression.resultoutput field.compactinput (boolean, defaulttrue) controlling output formatting.success: falsewith a descriptiveerrorstring when the input is not valid JSON.success: falsewith a descriptiveerrorstring when the expression is syntactically invalid.|),select,map,keys,length,type,to_entries,from_entries, object construction, and array slicing.CompositeOperationProvideralongside existinggithub.*andnotify.*providers.context.Contextcancellation for long-running expressions.Non-Functional Requirements
jqbinary dependency) to maintain cross-platform portability.OperationProviderpattern from F054/F056 with infrastructure-internal types (no new domain entities).Success Criteria
infra-transformcomponentKey Entities
ports.OperationProviderfortransform.*namespacetransform.jqMetadata
Dependencies
Clarifications
Section populated during clarify step with resolved ambiguities.
Notes
itchyny/gojq(MIT, widely used, full jq compatibility). Evaluate at implementation time.internal/infrastructure/transform/package withprovider.go,operations.go,jq.go,jq_test.go,doc.go.CompositeOperationProviderinrun.goalongside github and notify providers.transform.jq); namespacetransform.*reserves space for future operations (e.g.,transform.jsonpath,transform.xpath).ghCLI fallback pattern, jq evaluation must be fully embedded.