Wave Planning Strategies

Wave planning is the process of organizing tasks into execution groups (waves) that balance parallelism, dependencies, and resource constraints. This guide covers advanced strategies for optimal wave planning.

Table of Contents

Core Concepts

What is a Wave?

A wave is a group of tasks that can execute in parallel without violating dependency constraints. Orchex automatically organizes your manifest tasks into waves using topological sorting.

# Simple wave example
tasks:
  - id: setup
    prompt: "Initialize project structure"
    # Wave 0: No dependencies
  
  - id: implement
    prompt: "Implement feature"
    dependencies: [setup]
    # Wave 1: Depends on setup
  
  - id: test
    prompt: "Write tests"
    dependencies: [implement]
    # Wave 2: Depends on implement

Wave Properties

  • Wave Number: Sequential index (0, 1, 2, ...)
  • Parallelism: All tasks in a wave can execute simultaneously
  • Dependencies: No task depends on another task in the same wave
  • Blocking: A wave must complete before the next wave starts

Dependency Optimization

Minimize Dependency Chains

Problem: Long dependency chains create sequential bottlenecks.

# ❌ Bad: Artificial linear chain
tasks:
  - id: task1
    prompt: "Do A"
  - id: task2
    prompt: "Do B"  # Actually independent!
    dependencies: [task1]
  - id: task3
    prompt: "Do C"  # Actually independent!
    dependencies: [task2]
  - id: task4
    prompt: "Do D"
    dependencies: [task3]

This creates 4 waves when only 1 is needed.

# ✅ Good: Parallel execution
tasks:
  - id: task1
    prompt: "Do A"
  - id: task2
    prompt: "Do B"
  - id: task3
    prompt: "Do C"
  - id: task4
    prompt: "Do D"
  # All execute in Wave 0

Declare Only True Dependencies

Principle: A dependency exists only if Task B requires Task A's output or side effects.

# ❌ Bad: False dependency
tasks:
  - id: update-readme
    prompt: "Update README with new features"
  - id: add-tests
    prompt: "Add unit tests"
    dependencies: [update-readme]  # Tests don't need README!

# ✅ Good: Independent tasks
tasks:
  - id: update-readme
    prompt: "Update README with new features"
  - id: add-tests
    prompt: "Add unit tests"
  # Both execute in parallel

Use Partial Dependencies

When multiple tasks share some dependencies, find the minimal set.

# ❌ Bad: Over-specification
tasks:
  - id: models
    prompt: "Create database models"
  - id: api
    prompt: "Create API endpoints"
    dependencies: [models]
  - id: tests
    prompt: "Write API tests"
    dependencies: [models, api]  # models is redundant
  - id: docs
    prompt: "Document API"
    dependencies: [models, api]  # models is redundant

# ✅ Good: Minimal dependencies
tasks:
  - id: models
    prompt: "Create database models"
  - id: api
    prompt: "Create API endpoints"
    dependencies: [models]
  - id: tests
    prompt: "Write API tests"
    dependencies: [api]  # Implies models
  - id: docs
    prompt: "Document API"
    dependencies: [api]  # Implies models

Dependency Graph Metrics

Critical Path Length: The longest chain of dependencies

  • Target: Minimize this to reduce total execution time
  • Formula: max(wave_number) + 1

Average Wave Size: Tasks per wave

  • Target: Maximize this for better parallelism
  • Formula: total_tasks / number_of_waves

Parallelism Ratio: Actual vs potential parallelism

  • Target: Close to 1.0 for optimal planning
  • Formula: total_tasks / (critical_path_length * max_concurrent_tasks)

Parallel vs Sequential Trade-offs

When to Prefer Parallel Execution

Advantages:

  • Faster total execution time
  • Better resource utilization
  • Independent failure domains

Use cases:

# ✅ Parallel: Independent features
tasks:
  - id: feature-a
    prompt: "Implement feature A"
  - id: feature-b
    prompt: "Implement feature B"
  - id: feature-c
    prompt: "Implement feature C"

Advantages:

  • Clearer context for each task
  • Reduced file conflicts
  • Easier debugging

When to Prefer Sequential Execution

Advantages:

  • Consistent context across tasks
  • Simpler reasoning about state
  • Reduced merge conflicts

Use cases:

# ✅ Sequential: Building on previous work
tasks:
  - id: design-schema
    prompt: "Design database schema"
  - id: implement-models
    prompt: "Implement models based on schema"
    dependencies: [design-schema]
  - id: add-migrations
    prompt: "Create migrations for models"
    dependencies: [implement-models]

Hybrid Strategies

Combine parallel and sequential for optimal results.

# ✅ Hybrid: Parallel features, sequential implementation
tasks:
  # Wave 0: Setup (sequential foundation)
  - id: setup-db
    prompt: "Setup database structure"
  
  # Wave 1: Parallel feature streams
  - id: auth-models
    prompt: "Create auth models"
    dependencies: [setup-db]
  - id: billing-models
    prompt: "Create billing models"
    dependencies: [setup-db]
  - id: api-models
    prompt: "Create API models"
    dependencies: [setup-db]
  
  # Wave 2: Parallel services
  - id: auth-service
    prompt: "Implement auth service"
    dependencies: [auth-models]
  - id: billing-service
    prompt: "Implement billing service"
    dependencies: [billing-models]
  - id: api-service
    prompt: "Implement API service"
    dependencies: [api-models]
  
  # Wave 3: Integration (needs all services)
  - id: integration
    prompt: "Integrate all services"
    dependencies: [auth-service, billing-service, api-service]

Resource Considerations

Memory Constraints: Too much parallelism can exhaust memory

# Consider: Will these tasks fit in memory simultaneously?
tasks:
  - id: process-data-1
    prompt: "Process large dataset 1"  # 4GB RAM
  - id: process-data-2
    prompt: "Process large dataset 2"  # 4GB RAM
  - id: process-data-3
    prompt: "Process large dataset 3"  # 4GB RAM
  # 12GB total - may exceed available memory!

Solution: Add artificial dependencies to limit concurrency

tasks:
  - id: process-data-1
    prompt: "Process large dataset 1"
  - id: process-data-2
    prompt: "Process large dataset 2"
    dependencies: [process-data-1]  # Serialize to manage memory
  - id: process-data-3
    prompt: "Process large dataset 3"
    dependencies: [process-data-2]

API Rate Limits: Parallel tasks may hit rate limits

# If tasks make external API calls, consider rate limits
tasks:
  - id: fetch-data-batch-1
    prompt: "Fetch data from API (batch 1)"
  - id: fetch-data-batch-2
    prompt: "Fetch data from API (batch 2)"
    # Both parallel may exceed rate limit

Common Anti-patterns

1. The Monolith Task

Problem: One giant task that should be split into waves.

# ❌ Anti-pattern
tasks:
  - id: do-everything
    prompt: |
      1. Setup project structure
      2. Implement all features
      3. Write all tests
      4. Update documentation
      5. Add CI/CD

Solution: Break into logical waves

# ✅ Better
tasks:
  - id: setup
    prompt: "Setup project structure"
  
  - id: feature-1
    prompt: "Implement feature 1"
    dependencies: [setup]
  - id: feature-2
    prompt: "Implement feature 2"
    dependencies: [setup]
  
  - id: tests
    prompt: "Write comprehensive tests"
    dependencies: [feature-1, feature-2]
  - id: docs
    prompt: "Update documentation"
    dependencies: [feature-1, feature-2]
  
  - id: ci-cd
    prompt: "Add CI/CD pipeline"
    dependencies: [tests]

2. The Dependency Web

Problem: Every task depends on every other task.

# ❌ Anti-pattern: Circular or over-connected dependencies
tasks:
  - id: task-a
    dependencies: [task-b, task-c, task-d]
  - id: task-b
    dependencies: [task-a, task-c, task-d]
  - id: task-c
    dependencies: [task-a, task-b, task-d]
  - id: task-d
    dependencies: [task-a, task-b, task-c]

Solution: Identify true dependencies and create layers

# ✅ Better: Clear layering
tasks:
  - id: foundation
    prompt: "Create foundation"

  - id: layer-1-a
    prompt: "Build component A"
    dependencies: [foundation]
  - id: layer-1-b
    prompt: "Build component B"
    dependencies: [foundation]

  - id: integration
    prompt: "Integrate components"
    dependencies: [layer-1-a, layer-1-b]

Note on orchex learn auto-resolution: When cycles arise from mutual file-ownership (stream A reads stream B's file AND stream B reads stream A's file), orchex learn automatically drops these false dependencies — they represent context reads, not sequencing requirements. Cycles involving explicit deps or content-pattern dependencies are preserved and reported as errors. If orchex learn reports a cycle, restructure your plan to break the circular dependency chain.

3. The Premature Convergence

Problem: Forcing parallel work to converge too early.

# ❌ Anti-pattern
tasks:
  - id: feature-a-step-1
    prompt: "Start feature A"
  - id: feature-b-step-1
    prompt: "Start feature B"
  
  - id: checkpoint  # Unnecessary synchronization
    prompt: "Review progress"
    dependencies: [feature-a-step-1, feature-b-step-1]
  
  - id: feature-a-step-2
    prompt: "Continue feature A"
    dependencies: [checkpoint]
  - id: feature-b-step-2
    prompt: "Continue feature B"
    dependencies: [checkpoint]

Solution: Let parallel work complete independently

# ✅ Better
tasks:
  - id: feature-a-step-1
    prompt: "Start feature A"
  - id: feature-a-step-2
    prompt: "Continue feature A"
    dependencies: [feature-a-step-1]
  - id: feature-a-step-3
    prompt: "Complete feature A"
    dependencies: [feature-a-step-2]
  
  - id: feature-b-step-1
    prompt: "Start feature B"
  - id: feature-b-step-2
    prompt: "Continue feature B"
    dependencies: [feature-b-step-1]
  - id: feature-b-step-3
    prompt: "Complete feature B"
    dependencies: [feature-b-step-2]
  
  - id: final-integration  # Only converge when necessary
    prompt: "Integrate features A and B"
    dependencies: [feature-a-step-3, feature-b-step-3]

4. The Diamond Problem (Redundant Paths)

Problem: Multiple paths to the same dependency.

# ❌ Anti-pattern: Over-specification
tasks:
  - id: base
    prompt: "Create base"
  
  - id: middle
    prompt: "Build on base"
    dependencies: [base]
  
  - id: top
    prompt: "Complete feature"
    dependencies: [base, middle]  # base is redundant

Solution: Declare only direct dependencies

# ✅ Better
tasks:
  - id: base
    prompt: "Create base"
  
  - id: middle
    prompt: "Build on base"
    dependencies: [base]
  
  - id: top
    prompt: "Complete feature"
    dependencies: [middle]  # Implies base

5. The False Sequence

Problem: Adding dependencies for organizational purposes, not technical reasons.

# ❌ Anti-pattern: Grouping by category, not dependency
tasks:
  - id: frontend-1
    prompt: "Frontend task 1"
  - id: frontend-2
    prompt: "Frontend task 2"
    dependencies: [frontend-1]  # No actual dependency!
  - id: frontend-3
    prompt: "Frontend task 3"
    dependencies: [frontend-2]  # No actual dependency!
  
  - id: backend-1
    prompt: "Backend task 1"
    dependencies: [frontend-3]  # Why?

Solution: Use task names for organization, dependencies for requirements

# ✅ Better
tasks:
  - id: frontend-component-a
    prompt: "Build frontend component A"
  - id: frontend-component-b
    prompt: "Build frontend component B"
  - id: frontend-component-c
    prompt: "Build frontend component C"
  
  - id: backend-api
    prompt: "Build backend API"
  - id: backend-integration
    prompt: "Integrate frontend with backend"
    dependencies: [frontend-component-a, frontend-component-b, 
                   frontend-component-c, backend-api]

Best Practices

1. Design Waves Bottom-Up

Start with foundational tasks, then build up:

tasks:
  # Wave 0: Foundation
  - id: setup-project
    prompt: "Initialize project structure"
  - id: setup-config
    prompt: "Setup configuration"
  
  # Wave 1: Core components
  - id: core-types
    prompt: "Define core types"
    dependencies: [setup-project]
  - id: core-utils
    prompt: "Create utility functions"
    dependencies: [setup-project]
  
  # Wave 2: Features
  - id: feature-auth
    prompt: "Implement authentication"
    dependencies: [core-types, core-utils]
  - id: feature-api
    prompt: "Implement API layer"
    dependencies: [core-types, core-utils]
  
  # Wave 3: Testing & docs
  - id: tests
    prompt: "Add comprehensive tests"
    dependencies: [feature-auth, feature-api]
  - id: documentation
    prompt: "Write documentation"
    dependencies: [feature-auth, feature-api]

2. Use Meaningful Task IDs

Good task IDs communicate purpose and relationships:

# ✅ Clear naming convention
tasks:
  - id: db-schema-users
  - id: db-schema-posts
  - id: db-migrations-001
  - id: api-users-routes
  - id: api-posts-routes
  - id: test-api-users
  - id: test-api-posts

3. Document Wave Strategy

Add comments explaining your wave design:

tasks:
  # WAVE 0: Database Foundation
  # These must complete first as all features depend on them
  - id: db-schema
    prompt: "Design complete database schema"
  
  # WAVE 1: Parallel Feature Development
  # Each feature is independent and can be developed simultaneously
  - id: auth-feature
    prompt: "Implement authentication feature"
    dependencies: [db-schema]
  - id: billing-feature
    prompt: "Implement billing feature"
    dependencies: [db-schema]
  - id: analytics-feature
    prompt: "Implement analytics feature"
    dependencies: [db-schema]
  
  # WAVE 2: Integration Layer
  # Requires all features to be complete
  - id: feature-integration
    prompt: "Integrate all features"
    dependencies: [auth-feature, billing-feature, analytics-feature]

4. Validate Your Wave Plan

Before executing, check:

  • Can any sequential tasks be made parallel?
  • Are all dependencies truly necessary?
  • Is the critical path minimized?
  • Are wave sizes balanced?
  • Will resource constraints be respected?
  • Are task scopes reasonable?

5. Use Context Propagation Wisely

tasks:
  - id: design-api
    prompt: "Design RESTful API structure"
    context: ["docs/api-requirements.md"]
  
  - id: implement-api
    prompt: "Implement the API design"
    dependencies: [design-api]
    # Context automatically includes design-api's output
  
  - id: test-api
    prompt: "Write API tests"
    dependencies: [implement-api]
    # Context includes both design and implementation

Real-world Examples

Example 1: Full-Stack Feature

feature: "Add user profile management"

tasks:
  # Wave 0: Database
  - id: profile-schema
    prompt: "Design user profile database schema"
    context: ["src/db/schema.ts"]
  
  # Wave 1: Implementation layers (parallel)
  - id: profile-model
    prompt: "Implement profile data model"
    dependencies: [profile-schema]
    outputs: ["src/models/profile.ts"]
  
  - id: profile-api
    prompt: "Create profile API endpoints"
    dependencies: [profile-schema]
    outputs: ["src/api/profile.ts"]
  
  - id: profile-ui
    prompt: "Build profile UI components"
    dependencies: [profile-schema]
    outputs: ["src/components/Profile.tsx"]
  
  # Wave 2: Integration
  - id: profile-integration
    prompt: "Integrate model, API, and UI"
    dependencies: [profile-model, profile-api, profile-ui]
  
  # Wave 3: Quality (parallel)
  - id: profile-tests
    prompt: "Write comprehensive tests"
    dependencies: [profile-integration]
  
  - id: profile-docs
    prompt: "Document profile feature"
    dependencies: [profile-integration]

Wave breakdown:

  • Wave 0: 1 task (schema design)
  • Wave 1: 3 tasks (parallel implementation)
  • Wave 2: 1 task (integration)
  • Wave 3: 2 tasks (parallel quality)

Total: 7 tasks in 4 waves = 1.75 tasks/wave average

Example 2: Refactoring Project

feature: "Refactor authentication system"

tasks:
  # Wave 0: Analysis
  - id: analyze-current-auth
    prompt: "Analyze current authentication implementation"
    context: ["src/auth/"]
  
  # Wave 1: New implementation (parallel by component)
  - id: auth-tokens
    prompt: "Refactor token management"
    dependencies: [analyze-current-auth]
    outputs: ["src/auth/tokens.ts"]
  
  - id: auth-sessions
    prompt: "Refactor session handling"
    dependencies: [analyze-current-auth]
    outputs: ["src/auth/sessions.ts"]
  
  - id: auth-middleware
    prompt: "Refactor authentication middleware"
    dependencies: [analyze-current-auth]
    outputs: ["src/auth/middleware.ts"]
  
  # Wave 2: Integration & migration
  - id: auth-integration
    prompt: "Integrate new auth components"
    dependencies: [auth-tokens, auth-sessions, auth-middleware]
  
  - id: auth-migration
    prompt: "Create migration script for existing users"
    dependencies: [auth-integration]
  
  # Wave 3: Validation
  - id: auth-tests
    prompt: "Update and expand auth tests"
    dependencies: [auth-migration]
  
  - id: auth-cleanup
    prompt: "Remove old auth code"
    dependencies: [auth-tests]

Example 3: Multi-service System

feature: "Build microservices architecture"

tasks:
  # Wave 0: Shared foundation
  - id: shared-types
    prompt: "Define shared types and interfaces"
  - id: shared-config
    prompt: "Setup shared configuration"
  
  # Wave 1: Individual services (fully parallel)
  - id: user-service
    prompt: "Implement user service"
    dependencies: [shared-types, shared-config]
  
  - id: order-service
    prompt: "Implement order service"
    dependencies: [shared-types, shared-config]
  
  - id: payment-service
    prompt: "Implement payment service"
    dependencies: [shared-types, shared-config]
  
  - id: notification-service
    prompt: "Implement notification service"
    dependencies: [shared-types, shared-config]
  
  # Wave 2: Service communication
  - id: api-gateway
    prompt: "Setup API gateway"
    dependencies: [user-service, order-service, 
                   payment-service, notification-service]
  
  - id: service-mesh
    prompt: "Configure service mesh"
    dependencies: [user-service, order-service, 
                   payment-service, notification-service]
  
  # Wave 3: Operations
  - id: monitoring
    prompt: "Setup monitoring and logging"
    dependencies: [api-gateway, service-mesh]
  
  - id: deployment
    prompt: "Create deployment configurations"
    dependencies: [api-gateway, service-mesh]

Wave breakdown:

  • Wave 0: 2 tasks (shared foundation)
  • Wave 1: 4 tasks (parallel services)
  • Wave 2: 2 tasks (parallel infrastructure)
  • Wave 3: 2 tasks (parallel operations)

Parallelism ratio: 10 tasks / 4 waves = 2.5 tasks/wave

Conclusion

Effective wave planning is about finding the right balance between:

  • Speed (maximum parallelism)
  • Clarity (logical sequences)
  • Resources (practical constraints)
  • Maintainability (understandable structure)

Key takeaways:

  1. Minimize critical path length by maximizing parallelism
  2. Declare only true dependencies to avoid false sequences
  3. Balance wave sizes for consistent execution patterns
  4. Document your strategy for future maintainers
  5. Validate before executing to catch planning errors

When in doubt, prefer parallel execution unless there's a clear technical dependency. The Orchex planner will handle the complexity of orchestrating your tasks efficiently.