{
    "patterns": [
        {
            "name": "composite-registration-and-activation",
            "whenToUse": [
                "An app must run both standalone and as part of a composite deployment",
                "Registration, activation, or reconciliation should be orchestrated by the composite",
                "Autonomous startup behavior must be optionally disabled when composed",
                "Cross-deployment integration steps should be explicit and stable"
            ],
            "trigger": "deploymentAccess",
            "stepStructure": [
                {
                    "role": "register-step",
                    "description": "Publish capabilities such as tools, resources, or routes to another deployment",
                    "processors": ["resultsProcessor"]
                },
                {
                    "role": "activate-step",
                    "description": "Enable operational behavior only after composite orchestration completes",
                    "processors": ["resultsProcessor"]
                },
                {
                    "role": "reconcile-step",
                    "description": "Rebuild runtime state after reload or registry reset",
                    "processors": ["resultsProcessor"]
                },
                {
                    "role": "accept-step",
                    "description": "Handle the app's normal business traffic separately from composite concerns",
                    "processors": ["urlGenerator", "payloadGenerator", "authenticationProcessor", "resultsProcessor"]
                }
            ],
            "bootstrapHints": [
                "Keep composition knowledge in the composite bootstrap or orchestrator app rather than in sibling apps",
                "Expose explicit cross-deployment registration, activation, and reconciliation steps",
                "Make autonomous startup behavior disable-able through bootstrap data",
                "Design registration and activation steps to be safe for replay after reloads",
                "Use standalone auto-start only as a convenience layer over the explicit activation contract"
            ]
        },
        {
            "name": "default-step-properties",
            "whenToUse": [
                "Multiple steps share the same step-level properties and only a few fields differ",
                "A workflow file has coherent step groups with different shared defaults",
                "Repeated timeout, debug, concurrency, or processor settings should be centralized"
            ],
            "trigger": "varies",
            "stepStructure": [
                {
                    "role": "global-defaults",
                    "description": "Declare top-level defaultStepProperties when settings apply across every workflow in the file",
                    "processors": []
                },
                {
                    "role": "workflow-defaults",
                    "description": "Declare workflow-level defaultStepProperties when only one workflow group shares a common configuration",
                    "processors": []
                },
                {
                    "role": "step-overrides",
                    "description": "Override only the fields that differ on the individual step",
                    "processors": [
                        "urlGenerator",
                        "payloadGenerator",
                        "authenticationProcessor",
                        "resultsProcessor"
                    ]
                }
            ],
            "bootstrapHints": [
                "Top-level defaultStepProperties merges into every workflow before workflow-level defaults are applied",
                "Workflow-level defaultStepProperties then merges into each step in that workflow",
                "Step-local properties override both default layers",
                "Do not include stepId in defaultStepProperties",
                "If only a subset of steps share the same defaults, place them in a separate workflow rather than repeating the same properties on each step"
            ]
        },
        {
            "name": "synthesized-storage",
            "whenToUse": [
                "State must survive between workflow executions",
                "Related flows need to share stored values",
                "The workflow needs caching, counters, or stored configuration"
            ],
            "trigger": "varies",
            "stepStructure": [
                {
                    "role": "storage-writer",
                    "description": "Store data with a consistent persisted key naming convention",
                    "processors": ["resultsProcessor"]
                },
                {
                    "role": "storage-reader",
                    "description": "Load persisted data and use it in later workflow logic",
                    "processors": ["resultsProcessor"]
                }
            ],
            "bootstrapHints": [
                "Requires workflow persistence support",
                "Define persistence boundaries at bootstrap, not inside business logic",
                "Use stable key prefixes such as storage:{keyName}"
            ]
        },
        {
            "name": "controller",
            "whenToUse": [
                "One step should decide which worker path runs next",
                "Orchestration logic should be separated from implementation work",
                "Different operations share an entry point but need distinct handlers"
            ],
            "trigger": "varies",
            "stepStructure": [
                {
                    "role": "controller",
                    "description": "Evaluate conditions and call worker steps with sendToStep",
                    "processors": ["resultsProcessor"]
                },
                {
                    "role": "worker",
                    "description": "Perform a specific operation such as API access or transformation",
                    "processors": ["urlGenerator", "payloadGenerator", "authenticationProcessor", "resultsProcessor"]
                },
                {
                    "role": "finalizer",
                    "description": "Collect worker outcomes and make the final decision or output",
                    "processors": ["resultsProcessor"]
                }
            ],
            "bootstrapHints": [
                "Keep deployment permissions broad enough for every worker path the controller may invoke",
                "Prefer explicit step boundaries when responsibilities or failure handling differ"
            ]
        },
        {
            "name": "multiple-triggers",
            "whenToUse": [
                "The same logic should run from more than one entry point",
                "Manual and scheduled execution should reuse the same step behavior",
                "One step should accept either pushed or internally scheduled work"
            ],
            "trigger": "multiple",
            "stepStructure": [
                {
                    "role": "unified-entry",
                    "description": "Expose one step with multiple trigger types",
                    "processors": ["resultsProcessor"]
                },
                {
                    "role": "shared-logic",
                    "description": "Run the same processing path regardless of which trigger fired",
                    "processors": ["resultsProcessor"]
                }
            ],
            "bootstrapHints": [
                "Bootstrap must allow every trigger type used by the step",
                "Use this only when the shared logic genuinely matches across entry points"
            ]
        },
        {
            "name": "error-handling",
            "whenToUse": [
                "A step calls another step with sendToStep",
                "The workflow must distinguish user input failures from system failures",
                "Errors should be handled before downstream processing continues"
            ],
            "trigger": "varies",
            "stepStructure": [
                {
                    "role": "caller",
                    "description": "Invoke a helper step and inspect the returned context before continuing",
                    "processors": ["resultsProcessor"]
                },
                {
                    "role": "validator-or-helper",
                    "description": "Return user errors or system failures in a form the caller can propagate",
                    "processors": ["resultsProcessor"]
                }
            ],
            "bootstrapHints": [
                "Prefer schema-first validation with doc.inSchema and doc.asUserErrors when the contract is expressible",
                "Keep runtime lookups and non-schema rules in business logic only when schema cannot represent them cleanly"
            ]
        },
        {
            "name": "data-property",
            "whenToUse": [
                "Processors need reusable configuration through context.getData()",
                "Behavior should vary by bootstrap, workflow, step, or processor scope",
                "Shared resources need parameters instead of hard-coded values"
            ],
            "trigger": "varies",
            "stepStructure": [
                {
                    "role": "configuration-source",
                    "description": "Define data at bootstrap, workflow, step, or processor scope",
                    "processors": []
                },
                {
                    "role": "configured-processor",
                    "description": "Read merged data and apply behavior without embedding environment-specific values in code",
                    "processors": ["urlGenerator", "payloadGenerator", "authenticationProcessor", "resultsProcessor"]
                }
            ],
            "bootstrapHints": [
                "Place installer-controlled or deployment-specific values in bootstrap data",
                "Expect deeper scopes to override primitives and merge objects or arrays additively",
                "Use data to parameterize reusable resources rather than duplicating processor code"
            ]
        },
        {
            "name": "authentication",
            "whenToUse": [
                "Outbound HTTP requests require tokens, cookies, or authorization headers",
                "Restricted authentication data should be isolated from normal workflow logic",
                "Authentication must mutate a pending outbound request securely"
            ],
            "trigger": "http",
            "stepStructure": [
                {
                    "role": "http-caller",
                    "description": "Prepare the outbound request and invoke authentication immediately before the call",
                    "processors": ["urlGenerator", "payloadGenerator", "authenticationProcessor", "resultsProcessor"]
                },
                {
                    "role": "auth-step",
                    "description": "A dedicated scripted-auth step that applies restricted authentication data to the request",
                    "processors": ["resultsProcessor"]
                }
            ],
            "bootstrapHints": [
                "Mark the host as an authentication host",
                "Store secrets in host data rather than host headers",
                "Authentication flows may call only scripted-auth steps"
            ]
        },
        {
            "name": "http-event-normalization",
            "whenToUse": [
                "An HTTP-triggered step receives the full request wrapper but business logic expects only the payload",
                "Transport concerns should be separated from schema-validated domain logic",
                "The workflow should validate the normalized JSON body rather than the trigger wrapper"
            ],
            "trigger": "http",
            "stepStructure": [
                {
                    "role": "http-receiver",
                    "description": "Receive the inbound HTTP event wrapper",
                    "processors": ["resultsProcessor"]
                },
                {
                    "role": "normalizer",
                    "description": "Parse the wrapper, extract request.body, and write the normalized body back to context",
                    "processors": ["resultsProcessor"]
                },
                {
                    "role": "domain-processor",
                    "description": "Validate and process the normalized payload using a schema-aware processor resource",
                    "processors": ["resultsProcessor"]
                }
            ],
            "bootstrapHints": [
                "Requires an allowed HTTP listener in bootstrap",
                "If the same step builds the response, clear inherited request headers before setting response headers",
                "Keep transport normalization separate from business validation"
            ]
        },
        {
            "name": "packaged-server-bridge",
            "whenToUse": [
                "A packaged HTTP server already exists and should be exposed through a cross deployment call",
                "One app wants to talk via cross-deployment calls while the target app expects server access",
                "Cross-deployment adaptation should stay outside the packaged server workflow"
            ],
            "trigger": "deploymentAccess",
            "stepStructure": [
                {
                    "role": "packaged-server",
                    "description": "Own the normal HTTP routes while remaining unchanged as a packaged app",
                    "processors": []
                },
                {
                    "role": "bridge",
                    "description": "Receive transport-wrapper events, normalize the input, and forward to the packaged server",
                    "processors": ["urlGenerator", "resultsProcessor"]
                },
                {
                    "role": "response-wrapper",
                    "description": "Convert the server response into the response envelope expected by the wrapper transport",
                    "processors": ["resultsProcessor"]
                }
            ],
            "bootstrapHints": [
                "Set the packaged server http entry to inProcOnly when it should not bind an external port in the wrapped environment",
                "Use allowExternalHostAccess with transport=inProc and inProcServerId to call the packaged server",
                "Keep wrapper-event normalization and wrapper-response shaping in the bridge deployment rather than the packaged server"
            ]
        }
    ]
}
