ADR-049: Unified Workflow DSL for Lifecycle / Step / Task Definitions¶
| Attribute | Value |
|---|---|
| Status | Proposed |
| Date | 2026-06-12 |
| Deciders | Architecture Team |
| Extends | ADR-044 (Content-Driven Lifecycle Engine), ADR-034 (Pipeline Executor) |
| Related ADRs | ADR-023 (Content Sync), ADR-036 ยง2.5 (Pipeline/Workflow coexistence), ADR-047, ADR-022 |
| Superseded (in part) | ADR-057 supersedes the inline tasks: body shape of ยง2.1 with the JobDefinition step DAG, and supplies the closed scenarioFunction primitive set. ADR-058 supplies the data-flow scopes. |
1. Context¶
Two consumers read the same content package (PAv1/) at different abstraction levels
(ADR-044 ยง1.2):
- LCM (CPA / controllers) reads top-level orchestration โ which lifecycle phases exist,
in what order, with which engine (
pipelinevsworkflow), and gating. - SE reads low-level task definitions โ the adapter calls a job actually performs (Collect โ Evaluate โ Report).
Today these are described by different shapes in different files (pipeline YAML with steps,
workflow refs, scenario/grading YAML). The same concept โ "a unit of work bound to a phase" โ is
expressed inconsistently, which makes content authoring error-prone and prevents a single
validator. As the resource tree generalizes (ADR-036 ยง2.6), every resource level
(Session, SessionPart, PodInstance, Host) can carry lifecycle phases, so the DSL must be
uniform across levels and across both consumers.
2. Decision¶
2.1 One DSL, three nested concepts¶
Define a single declarative DSL with a consistent shape at three levels:
| Concept | Owned/ordered by | Bound to |
|---|---|---|
| Lifecycle | the resource (LCM) | a TimedResource kind / profile |
| Step (phase) | LCM (ordering, gating, engine selection) | a LifecyclePhase |
| Task | SE (when engine = workflow) |
the job's Collect/Evaluate/Report units |
lifecycle:
phases:
- name: instantiate
engine: pipeline # native LCM steps
steps: [worker_lab_resolve, pod_locator, ports_alloc, lds_register, mark_ready]
- name: grade
engine: workflow # delegated to SE
trigger_on_status: submitted
workflow: { name: grade-lab, version: "0.1.0" }
tasks: # read by SE, ignored by LCM
- collect: { scenario: collect-evidence }
- evaluate: { ruleset: rubric }
- report: { kind: score_report }
- name: teardown
engine: pipeline
steps: [archive, release_host]
Superseded body shape. The inline
tasks:triad above is superseded by ADR-057: a phase'sworkflowjob now references aJobDefinitionfile (definition: name@versionโjobs/<name>.yaml) whose body is an ordered DAG of steps, each calling a versionedscenarioFunctionfrom the closed primitive set. This ADR's ยง2.1โยง2.2 framing (one document, two readers; native steps vs SE jobs) stands.
2.2 Layered consumption (one document, two readers)¶
The same document is ingested by both consumers on content sync (ADR-023):
- LCM reads
lifecycle.phases[].{name, engine, order, gates_next, trigger_on_status, steps, workflow}to build a resource'sManagedLifecycleand drive reconciliation (ADR-047). It ignorestasks. - SE reads
phases[].tasks(and the referenced scenario/ruleset/report definitions) to execute a job. It ignores nativesteps.
Neither consumer needs the other's section; the DSL is a superset both can parse without coupling.
2.3 Validation and versioning¶
- A shared schema (published from
lcm_core) validates the DSL at sync time; an invalid document fails the sync (no partial ingestion). The concrete schema location and shape are defined in ADR-057 ยง2.7 โsrc/core/lcm_core/schemas/(lifecycle.schema.json,job-definition.schema.json,connector-model.schema.json,evaluation-ruleset.schema.json,process-report-spec.schema.json), plus ascenario-functions.catalog.jsongenerated from the SE@scenarioregistry souses:references are validated against primitives that actually exist. - Phases, workflows, and tasks are versioned (
name@version) so content changes are explicit and reproducible (aligns with ADR-027 auto-increment).
2.4 Applies at every resource level¶
Because the DSL is attached to a ManagedLifecycle, the same shape describes a Session's
phases, a SessionPart's phases, and a PodInstance's phases โ no per-level DSL.
3. Consequences¶
Positive
- One authoring shape, one validator, one mental model across LCM and SE and across all resource levels.
pipelinesteps andworkflowjobs are described uniformly (resolves ADR-036 ยง2.5's three-way lookup ambiguity into one declarative form).- Content sync can reject malformed lifecycles before they reach runtime.
Negative / trade-offs
- Requires a shared schema package and a one-time conversion of existing pipeline/workflow YAML to the unified shape (clean cut; no dual-format support โ authors supply the new shape).
- The DSL is a superset; each consumer must clearly document which keys it honours.
Neutral
- Existing
PipelineExecutor(ADR-034) and SE job execution (ADR-044) are unchanged in mechanics โ only the ingested definition shape is unified.
4. Related¶
- unified-resource-management.md โ the LCM/SE seam.
- generic-pattern.md โ Collect โ Evaluate โ Report tasks.
- flow-content-sync.md โ sync fan-out to LCM + SE.