@@ -54,24 +54,29 @@ type Story struct {
5454
5555// StorySpec defines what the workflow does and how it should run
5656type StorySpec struct {
57- // Pattern defines the execution strategy for this Story.
58- // ' batch' (default): Runs the story as a series of ephemeral jobs. Good for asynchronous tasks .
59- // ' streaming': Deploys the story as a persistent pipeline of services for real-time, low-latency workloads .
57+ // Pattern specifies the execution model for the Story.
58+ // " batch" stories are run to completion via a StoryRun .
59+ // " streaming" stories create long-running workloads that process data continuously .
6060 // +kubebuilder:validation:Enum=batch;streaming
6161 // +kubebuilder:default=batch
6262 Pattern enums.StoryPattern `json:"pattern,omitempty"`
6363
64- // What inputs does this Story expect?
65- // Define the data structure that triggers (Impulses) or users need to provide
66- // Example: {"repository": "string", "branch": "string", "commit": "string"}
67- // +kubebuilder:pruning:PreserveUnknownFields
64+ // StreamingStrategy defines the deployment strategy for long-running engrams in a streaming story.
65+ // "PerStory" creates a single, shared set of long-running engrams for the Story.
66+ // "PerStoryRun" creates a dedicated set of long-running engrams for each StoryRun.
67+ // This field is only applicable when `pattern` is "streaming".
68+ // +kubebuilder:validation:Enum=PerStory;PerStoryRun
69+ // +kubebuilder:default=PerStory
70+ // +optional
71+ StreamingStrategy enums.StreamingStrategy `json:"streamingStrategy,omitempty"`
72+
73+ // InputsSchema defines the schema for the data required to start a StoryRun.
74+ // +optional
6875 InputsSchema * runtime.RawExtension `json:"inputsSchema,omitempty"`
6976
70- // What outputs does this Story produce?
71- // Define the data structure this workflow will return upon completion
72- // Example: {"buildArtifact": "string", "testResults": "object", "deploymentUrl": "string"}
73- // +kubebuilder:pruning:PreserveUnknownFields
74- OutputSchema * runtime.RawExtension `json:"outputSchema,omitempty"`
77+ // OutputsSchema defines the schema for the data this Story is expected to produce.
78+ // +optional
79+ OutputsSchema * runtime.RawExtension `json:"outputsSchema,omitempty"`
7580
7681 // The actual workflow steps - this is where the magic happens!
7782 // Steps run in sequence unless you use parallel/condition logic
@@ -84,25 +89,34 @@ type StorySpec struct {
8489 Policy * StoryPolicy `json:"policy,omitempty"`
8590}
8691
87- // Step represents a single action in a story
88- // Steps are the building blocks of stories - each step does one specific thing
92+ // Step defines a single unit of work within a Story.
93+ // Steps are the building blocks of stories, defining everything from custom logic
94+ // to control flow like loops, conditions, and parallel execution.
8995type Step struct {
90- // Human-readable name for this step
91- // Examples: "fetch-data", "process-payment", "send-notification"
96+ // Name is a human-readable identifier for the step.
97+ // It's used to reference this step's outputs in other steps.
98+ // e.g., '{{ steps.my-step-name.outputs.some_field }}'
9299 // +kubebuilder:validation:Required
93100 // +kubebuilder:validation:MinLength=1
94101 // +kubebuilder:validation:MaxLength=63
95102 // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
96103 Name string `json:"name"`
97104
98- // Optional unique identifier for referencing this step's outputs
99- // Useful for complex stories where later steps need data from specific earlier steps
105+ // ID is an optional, unique identifier for a step instance.
106+ // While 'name' identifies the step in logs and outputs, 'id' can be used
107+ // programmatically to reference a specific node in the workflow graph.
100108 // +kubebuilder:validation:MaxLength=63
101109 // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
110+ // +optional
102111 ID string `json:"id,omitempty"`
103112
104- // What type of action should this step perform?
105- // Use built-in types for common patterns, or reference an Engram for custom logic
113+ // Needs explicitly defines a list of step names that must be completed before this step can run.
114+ // This is used to create an execution order for steps that don't have an implicit data dependency.
115+ // +optional
116+ Needs []string `json:"needs,omitempty"`
117+
118+ // Type determines the kind of operation this step performs.
119+ // Use built-in types for common patterns. If omitted and 'ref' is present, the step is an 'engram' step.
106120 //
107121 // Built-in primitive types:
108122 // - condition: if/then/else logic
@@ -113,37 +127,42 @@ type Step struct {
113127 // - switch: multi-way branching like switch/case
114128 // - filter: filter arrays or objects based on conditions
115129 // - transform: modify data structure or format
116- // - wait: wait for external conditions or events
117- // - throttle: rate limiting and flow control
118- // - batch: group operations for efficiency
119130 // - executeStory: run another story as a sub-story
120131 // - setData: set variables or update context
121132 // - mergeData: combine data from multiple sources
122- Type * enums. StepType `json:"type,omitempty"`
123-
124- // Reference to an Engram for custom logic (alternative to Type)
125- // Use this when you need functionality that's not covered by built-in types
126- Ref * refs. EngramReference `json:"ref ,omitempty"`
133+ // - wait: wait for external conditions
134+ // - throttle: rate limiting
135+ // - batch: group operations
136+ // +optional
137+ Type enums. StepType `json:"type ,omitempty"`
127138
128- // When should this step run? (CEL expression)
129- // Examples: "inputs.environment == 'production'", "steps.validate.outputs.success == true"
139+ // If provides a condition for executing this step.
140+ // The step is only executed if the CEL expression evaluates to true.
141+ // +optional
130142 If * string `json:"if,omitempty"`
131143
132- // How to configure this step (works for both built-in types and Engrams)
133- // The structure depends on what Type or Ref you're using
144+ // Ref points to an Engram to execute.
145+ // This is a shortcut for a step of type 'engram'.
146+ // If 'ref' is used, 'type' should be omitted.
147+ // +optional
148+ Ref * refs.EngramReference `json:"ref,omitempty"`
149+
150+ // With provides the configuration for the step. The expected structure of this block
151+ // is determined by the step 'type'. For example:
152+ // - for 'engram': the inputs to the engram.
153+ // - for 'executeStory': contains 'storyRef', 'waitForCompletion', and 'with'.
154+ // - for 'loop': contains 'items' and 'template'.
155+ // The structure is validated at runtime by the controller.
134156 // +kubebuilder:pruning:PreserveUnknownFields
157+ // +optional
135158 With * runtime.RawExtension `json:"with,omitempty"`
136159
137- // Maps template secret definitions to actual Kubernetes secrets for this step
160+ // Secrets maps template secret definitions to actual Kubernetes secrets for this step.
161+ // This is only applicable to 'engram' steps and overrides any secret mappings on the Engram itself.
138162 // Example: {"apiKey": "openai-credentials", "database": "postgres-creds"}
163+ // +optional
139164 Secrets map [string ]string `json:"secrets,omitempty"`
140165
141- // Launch another story as a sub-story (using same 'with' pattern for arguments)
142- // Useful for breaking complex stories into smaller, reusable pieces
143- // +kubebuilder:validation:MaxLength=253
144- // +kubebuilder:validation:Pattern=^([a-z0-9]([-a-z0-9]*[a-z0-9])?/)?[a-z0-9]([-a-z0-9]*[a-z0-9])?$
145- StoryRef * string `json:"storyRef,omitempty"`
146-
147166 // Override execution settings for this specific step
148167 // Use sparingly - most configuration should be at the story or engram level
149168 Execution * ExecutionOverrides `json:"execution,omitempty"`
@@ -154,6 +173,10 @@ type StoryPolicy struct {
154173 // Timeouts
155174 Timeouts * StoryTimeouts `json:"timeouts,omitempty"`
156175
176+ // With provides the inputs for the sub-story, mirroring the 'with' field in an Engram step.
177+ // +kubebuilder:pruning:PreserveUnknownFields
178+ // +optional
179+ With * runtime.RawExtension `json:"with,omitempty"`
157180 // Retry behavior
158181 Retries * StoryRetries `json:"retries,omitempty"`
159182
@@ -183,9 +206,9 @@ type StoryRetries struct {
183206 ContinueOnStepFailure * bool `json:"continueOnStepFailure,omitempty"`
184207}
185208
209+ // StoryStatus defines the observed state of a Story.
186210type StoryStatus struct {
187- // observedGeneration is the most recent generation observed for this Story. It corresponds to the
188- // Story's generation, which is updated on mutation by the API Server.
211+ // ObservedGeneration is the most recent generation observed for this Story.
189212 // +optional
190213 ObservedGeneration int64 `json:"observedGeneration,omitempty"`
191214
0 commit comments