prodigy 0.4.4

Turn ad-hoc Claude sessions into reproducible development pipelines with parallel AI agents
Documentation
## Workflow Extension (Inheritance)

Extend a base workflow to inherit its configuration. Child workflows override parent values, allowing you to customize specific aspects while maintaining common configuration. This enables environment-specific variations and layered configuration management.

### Basic Extension Syntax

```yaml
# production.yml
name: production-deployment
mode: standard

# Inherit from base workflow
extends: "base-deployment.yml"

# Override specific values
env:
  ENVIRONMENT: "production"
  REPLICAS: "5"
```

### How Extension Works

When a workflow extends a base workflow:

1. **Base workflow is loaded** from the specified path
2. **Child values override parent** for matching keys
3. **Parent values are preserved** where child doesn't override
4. **Merging is deep** - nested objects merge recursively
5. **Arrays are replaced** - child arrays replace parent arrays entirely

### Extension vs Imports

| Feature | Extension (`extends`) | Imports |
|---------|----------------------|---------|
| **Purpose** | Inherit and customize base workflow | Reuse workflow components |
| **Relationship** | Parent-child hierarchy | Modular composition |
| **Override behavior** | Child overrides parent | Imports merge with main |
| **Use case** | Environment variations | Shared utilities |

### Multi-Environment Example

**base-deployment.yml** (shared configuration):
```yaml
name: base-deployment
mode: standard

env:
  APP_NAME: "my-service"
  REPLICAS: "1"
  LOG_LEVEL: "info"

commands:
  - shell: "docker build -t ${APP_NAME}:${VERSION} ."
  - shell: "kubectl apply -f k8s/${ENVIRONMENT}/deployment.yml"
  - shell: "kubectl scale deployment ${APP_NAME} --replicas=${REPLICAS}"
```

**dev.yml** (development environment):
```yaml
name: dev-deployment
extends: "base-deployment.yml"

env:
  ENVIRONMENT: "dev"
  REPLICAS: "1"
  LOG_LEVEL: "debug"

# Inherits all commands from base
```

**staging.yml** (staging environment):
```yaml
name: staging-deployment
extends: "base-deployment.yml"

env:
  ENVIRONMENT: "staging"
  REPLICAS: "3"
  LOG_LEVEL: "info"

# Additional staging-specific commands
commands:
  - shell: "run-smoke-tests.sh"
```

**production.yml** (production environment):
```yaml
name: production-deployment
extends: "base-deployment.yml"

env:
  ENVIRONMENT: "production"
  REPLICAS: "5"
  LOG_LEVEL: "warn"
  ENABLE_MONITORING: "true"

# Additional production safeguards
commands:
  - shell: "verify-release-notes.sh"
  - shell: "notify-team 'Deploying to production'"
```

### Merge Behavior

**Scalar Values** - Child replaces parent:
```yaml
# base.yml
timeout: 300

# child.yml
extends: "base.yml"
timeout: 600  # Replaces 300 with 600
```

**Objects** - Deep merge:
```yaml
# base.yml
env:
  APP_NAME: "service"
  LOG_LEVEL: "info"

# child.yml
extends: "base.yml"
env:
  LOG_LEVEL: "debug"  # Overrides
  NEW_VAR: "value"     # Adds

# Result:
env:
  APP_NAME: "service"     # From base
  LOG_LEVEL: "debug"      # Overridden
  NEW_VAR: "value"        # Added
```

**Environment Variables** - Deep merge with selective override:
```yaml
# base.yml
env:
  APP_NAME: "service"
  LOG_LEVEL: "info"
  REPLICAS: "3"

# child.yml
extends: "base.yml"
env:
  LOG_LEVEL: "debug"  # Overrides parent value
  NEW_VAR: "value"     # Adds new variable

# Result:
env:
  APP_NAME: "service"     # Preserved from parent
  LOG_LEVEL: "debug"      # Overridden by child
  REPLICAS: "3"           # Preserved from parent
  NEW_VAR: "value"        # Added by child
```

**Source**: Environment variables inherit the object deep merge behavior (src/cook/workflow/composition/composer.rs:325-355)

**Arrays (Commands)** - Child replaces parent:
```yaml
# base.yml
commands:
  - shell: "step1"
  - shell: "step2"

# child.yml
extends: "base.yml"
commands:
  - shell: "custom-step"  # Completely replaces base commands

# Result: Only custom-step runs
```

**Source**: In inheritance mode (`extends`), non-empty child command arrays replace parent arrays entirely (src/cook/workflow/composition/composer.rs:335-337)

**Note**: This behavior differs from imports, where `merge_workflows` extends arrays instead of replacing them (src/cook/workflow/composition/composer.rs:275-323). See [Workflow Imports](index.md#workflow-imports) for comparison.

### Layered Extension

Workflows can extend workflows that themselves extend other workflows:

```yaml
# base.yml
name: base-config
timeout: 300

# intermediate.yml
extends: "base.yml"
timeout: 600
max_parallel: 5

# final.yml
extends: "intermediate.yml"
max_parallel: 10

# Result: timeout=600 (from intermediate), max_parallel=10 (from final)
```

### Path Resolution

When resolving base workflow paths, Prodigy searches the following locations in order:

1. `./bases/{name}.yml`
2. `./templates/{name}.yml`
3. `./workflows/{name}.yml`
4. `./{name}.yml` (current directory)

**Source**: Path resolution implementation in src/cook/workflow/composition/composer.rs:625-642

Extension paths can be:
- **Relative**: Resolved from workflow file's directory
- **Absolute**: Full filesystem path
- **Registry**: Future support for template registry paths

```yaml
# Name-based lookup (searches standard directories)
extends: "base-deployment"  # Searches bases/, templates/, workflows/, ./

# Relative path
extends: "../shared/base.yml"

# Absolute path
extends: "/etc/prodigy/workflows/base.yml"
```

**Search Order Example:**
```bash
# For extends: "ci-base"
# Prodigy searches:
./bases/ci-base.yml       # First
./templates/ci-base.yml   # Second
./workflows/ci-base.yml   # Third
./ci-base.yml             # Fourth (current directory)
# Error if not found in any location
```

### Use Cases

**Environment-Specific Deployments:**
- Share common deployment steps
- Override environment variables per environment
- Customize resource limits (replicas, memory, CPU)

**Testing Variations:**
```yaml
# base-test.yml
name: base-test
commands:
  - shell: "cargo build"
  - shell: "cargo test"

# integration-test.yml
extends: "base-test.yml"
env:
  DATABASE_URL: "postgres://localhost/test"
commands:
  - shell: "setup-test-db.sh"
  # Runs instead of base commands

# unit-test.yml
extends: "base-test.yml"
env:
  RUST_TEST_THREADS: "1"
```

**Progressive Configuration:**
- Start with minimal base config
- Add complexity in child workflows
- Keep each layer focused on specific concerns

### Circular Dependency Protection

Prodigy detects and prevents circular dependencies:

```yaml
# workflow-a.yml
extends: "workflow-b.yml"

# workflow-b.yml
extends: "workflow-a.yml"

# Error: Circular dependency detected
```

### Complete Example

**base-ci.yml:**
```yaml
name: base-ci
mode: standard

env:
  RUST_BACKTRACE: "1"

commands:
  - shell: "cargo fmt --check"
  - shell: "cargo clippy"
  - shell: "cargo test"
```

**pr-ci.yml** (runs on pull requests):
```yaml
name: pr-ci
extends: "base-ci.yml"

env:
  CARGO_INCREMENTAL: "0"  # Faster CI builds

# Inherits format, clippy, test from base
```

**release-ci.yml** (runs on release):
```yaml
name: release-ci
extends: "base-ci.yml"

env:
  CARGO_INCREMENTAL: "0"

commands:
  - shell: "cargo build --release"
  - shell: "cargo test --release"
  - shell: "cargo publish --dry-run"
```

### Debugging Extensions

**Current Method** - Enable verbose logging to see composition details:

```bash
# Use -vvv for trace-level logging showing composition process
prodigy run workflow.yml -vvv

# Combine with --dry-run to preview without execution
prodigy run workflow.yml --dry-run -vvv
```

Verbose logging output includes:
- Base workflow loading events
- Inheritance chain resolution
- Merge operations for each configuration section
- Circular dependency checks
- Path resolution steps

**Source**: Composition events logged via `tracing::debug!()` macros throughout src/cook/workflow/composition/composer.rs

**Planned Feature** - Dedicated composition inspection flag (not yet implemented):

```bash
# Future: --show-composition flag (Spec 131-133)
prodigy run workflow.yml --dry-run --show-composition
```

This will display structured composition metadata including:
- Sources and dependency types
- Complete inheritance chain
- Applied parameters and templates
- Resolved paths for all dependencies

See [Composition Metadata](composition-metadata.md) for details on the metadata structure.

### Implementation Status

- ✅ Base workflow loading
- ✅ Deep merge of child and parent configurations
- ✅ Circular dependency detection
- ✅ Path resolution (relative and absolute)
- ✅ Composition metadata tracking
- ✅ Workflow caching - Files are cached during composition to improve performance and avoid redundant file system reads (src/cook/workflow/composition/composer.rs:662-698)

### Related Topics

- [Workflow Imports]index.md#workflow-imports - Modular composition
- [Template System]template-system.md - Parameterized workflows
- [Composition Metadata]composition-metadata.md - Inspect composition details