Composition Metadata
Composition Metadata¶
Prodigy tracks metadata about workflow composition for debugging and dependency analysis. This metadata provides visibility into how workflows are composed, what dependencies exist, and when composition occurred.
Implementation Status: The composition metadata types and dependency tracking are fully implemented in the core composition system. These features are accessible programmatically via the WorkflowComposer API. CLI integration for viewing composition metadata in workflows is under development (Spec 131-133).
CompositionMetadata Structure¶
Every composed workflow includes metadata tracking all composition operations:
Source: src/cook/workflow/composition/mod.rs:153-170
/// Metadata about workflow composition
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompositionMetadata {
/// Source files involved in composition
pub sources: Vec<PathBuf>,
/// Templates used
pub templates: Vec<String>,
/// Parameters applied
pub parameters: HashMap<String, Value>,
/// Composition timestamp
pub composed_at: chrono::DateTime<chrono::Utc>,
/// Dependency graph
pub dependencies: Vec<DependencyInfo>,
}
Field Details:
- sources: File paths of all workflow files involved in composition (as PathBuf objects)
- templates: Template names/sources used during composition
- parameters: Final parameter values applied to the workflow (as serde_json::Value)
- composed_at: ISO 8601 timestamp when composition occurred (UTC timezone)
- dependencies: Complete dependency graph with all imports, extends, templates, and sub-workflows
Dependency Tracking¶
Each dependency includes detailed information:
Source: src/cook/workflow/composition/mod.rs:172-183
/// Information about workflow dependencies
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DependencyInfo {
/// Source of the dependency
pub source: PathBuf,
/// Type of dependency
pub dep_type: DependencyType,
/// Resolved path or name
pub resolved: String,
}
Field Details:
- source: Source file path of the dependency (as PathBuf)
- dep_type: Type of dependency (Import, Extends, Template, or SubWorkflow)
- resolved: Resolved file path or template name (as String)
Dependency Types¶
Prodigy tracks four types of dependencies:
Source: src/cook/workflow/composition/mod.rs:185-193
/// Type of workflow dependency
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DependencyType {
Import,
Extends,
Template,
SubWorkflow,
}
Import Dependencies:
imports:
- path: "shared/utilities.yml"
# Creates DependencyInfo:
# dep_type: DependencyType::Import
# source: PathBuf::from("shared/utilities.yml")
# resolved: "/full/path/to/shared/utilities.yml"
Extends Dependencies:
extends: "base-config.yml"
# Creates DependencyInfo:
# dep_type: DependencyType::Extends
# source: PathBuf::from("base-config.yml")
# resolved: "/full/path/to/base-config.yml"
Template Dependencies:
template:
source:
registry: "ci-pipeline"
# Creates DependencyInfo:
# dep_type: DependencyType::Template
# source: PathBuf::from("registry:ci-pipeline")
# resolved: "~/.prodigy/templates/ci-pipeline.yml"
SubWorkflow Dependencies:
sub_workflows:
- name: "tests"
source: "workflows/test.yml"
# Creates DependencyInfo:
# dep_type: DependencyType::SubWorkflow
# source: PathBuf::from("workflows/test.yml")
# resolved: "/full/path/to/workflows/test.yml"
Viewing Composition Metadata¶
Note: CLI commands for viewing composition metadata in workflow execution are under development. Currently, metadata can be accessed programmatically via the WorkflowComposer API (see Programmatic Access below).
Future CLI Usage (planned):
Expected Output:
Composition Metadata:
Composed at: 2025-01-11T20:00:00Z
Sources (3):
- /path/to/workflow.yml
- /path/to/base-config.yml
- /path/to/shared/utilities.yml
Templates (1):
- registry:ci-pipeline
Dependencies (3):
[Import] shared/utilities.yml -> /path/to/shared/utilities.yml
[Extends] base-config.yml -> /path/to/base-config.yml
[Template] registry:ci-pipeline -> ~/.prodigy/templates/ci-pipeline.yml
Parameters (2):
environment: "production"
timeout: 600
Programmatic Access¶
Access metadata in code using the WorkflowComposer API:
Source: src/cook/workflow/composition/composer.rs:21-37
use prodigy::cook::workflow::composition::{WorkflowComposer, TemplateRegistry};
use std::collections::HashMap;
use std::sync::Arc;
use std::path::Path;
// Create composer with template registry
let registry = Arc::new(TemplateRegistry::new());
let composer = WorkflowComposer::new(registry);
// Compose workflow with parameters
let params = HashMap::new();
let composed = composer.compose(Path::new("workflow.yml"), params).await?;
// Access metadata
let metadata = &composed.metadata;
// Inspect dependencies
for dep in &metadata.dependencies {
println!("{:?}: {} -> {}",
dep.dep_type,
dep.source.display(),
dep.resolved
);
}
// Check composition timestamp
println!("Composed at: {}", metadata.composed_at);
// View final parameters
for (name, value) in &metadata.parameters {
println!("Parameter {}: {:?}", name, value);
}
// List source files
println!("Sources:");
for source in &metadata.sources {
println!(" - {}", source.display());
}
// List templates used
println!("Templates:");
for template in &metadata.templates {
println!(" - {}", template);
}
Real-World Example (from src/cook/workflow/composition/composer.rs:45-51):
// Metadata is created during composition
let mut metadata = CompositionMetadata {
sources: vec![source.to_path_buf()],
templates: Vec::new(),
parameters: params.clone(),
composed_at: chrono::Utc::now(),
dependencies: Vec::new(),
};
Dependency Graph Visualization¶
Metadata enables dependency visualization:
workflow.yml
├─ [Extends] base-config.yml
│ └─ [Import] shared/setup.yml
├─ [Import] shared/utilities.yml
└─ [Template] registry:ci-pipeline
└─ [SubWorkflow] workflows/test.yml
Use Cases¶
Debugging Composition Issues: - Verify which files were loaded - Check parameter resolution order - Identify circular dependencies - Trace inheritance chains
Dependency Analysis: - Find all workflows using a template - Identify shared imports - Map workflow relationships - Audit composition complexity
Change Impact Assessment:
# Before changing base-config.yml, find all dependents
grep -r "extends.*base-config" workflows/
# View composition metadata programmatically
# (CLI integration for --show-composition is under development)
Compliance and Auditing: - Track template versions used - Record composition timestamps - Document parameter sources - Verify configuration origins
Metadata in Composed Workflows¶
Composed workflows carry metadata through the composition process:
Source: src/cook/workflow/composition/mod.rs:143-151
// ComposedWorkflow structure
pub struct ComposedWorkflow {
/// The composed workflow
pub workflow: ComposableWorkflow,
/// Metadata about the composition
pub metadata: CompositionMetadata,
}
// Access metadata from composed workflow
let composed = composer.compose(source, params).await?;
println!("This workflow was composed from {} sources",
composed.metadata.sources.len());
Circular Dependency Detection¶
Metadata enables circular dependency detection:
Detection:
Error: Circular dependency detected
workflow-a.yml -> workflow-b.yml -> workflow-a.yml
Dependency chain:
1. workflow-a.yml (extends workflow-b.yml)
2. workflow-b.yml (extends workflow-a.yml) <- Circular!
Parameter Tracking¶
Metadata tracks final parameter values applied during composition:
# workflow.yml
parameters:
definitions:
environment:
type: string
required: true
timeout:
type: integer
default: 600
Metadata captures:
The parameters field in CompositionMetadata stores the final resolved parameter values as a HashMap<String, Value>. This enables reproducibility and debugging of composed workflows.
Caching and Performance¶
Composition metadata enables future caching optimizations:
composed_attimestamp can be used for cache invalidationsourceslist enables dependency-based cache bustingdependenciesgraph supports incremental compositionparametershash can detect identical compositions
Note: Workflow caching is a planned feature. Currently, metadata is generated fresh on each composition.
Data Structure Properties¶
CompositionMetadata uses standard Rust types for broad compatibility:
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompositionMetadata {
// All fields use standard types
pub sources: Vec<PathBuf>, // Cloneable
pub templates: Vec<String>, // Cloneable
pub parameters: HashMap<String, Value>, // Cloneable
pub composed_at: chrono::DateTime<chrono::Utc>, // Copy
pub dependencies: Vec<DependencyInfo>, // Cloneable
}
The struct derives Clone, making it easy to share metadata across components without requiring explicit synchronization primitives.
Related Topics¶
- Template System - Template caching and loading
- Workflow Extension - Inheritance tracking