CDX-301h · Module 2

Partial Completion & Graceful Degradation

3 min read

Not every pipeline failure requires a full abort. Graceful degradation means accepting partial results when some agents succeed and others fail. If three out of five agents complete their tasks successfully, the pipeline delivers 60% of the value rather than 0%. This requires that the decomposition produces independently valuable units — each agent's output must be usable on its own, not just as input to the next agent.

Implementing graceful degradation requires three design decisions. First, which tasks are mandatory (pipeline aborts if they fail) and which are optional (pipeline continues without them)? A core implementation is mandatory; documentation is optional. Second, what is the minimum viable output? If the test writer fails but the implementer succeeds, is untested code acceptable as a partial result? Third, how does the pipeline report partial completion — which deliverables were produced and which were skipped?

from dataclasses import dataclass
from enum import Enum

class TaskPriority(Enum):
    MANDATORY = "mandatory"  # Pipeline fails without this
    IMPORTANT = "important"  # Degrades quality if missing
    OPTIONAL = "optional"    # Nice-to-have, skip if failed

@dataclass
class TaskResult:
    agent: str
    priority: TaskPriority
    succeeded: bool
    output: str

def evaluate_pipeline(results: list[TaskResult]) -> dict:
    """Determine if partial results are acceptable."""
    mandatory_failures = [
        r for r in results
        if r.priority == TaskPriority.MANDATORY and not r.succeeded
    ]
    if mandatory_failures:
        return {
            "status": "abort",
            "reason": f"Mandatory tasks failed: "
                      f"{[r.agent for r in mandatory_failures]}",
        }

    succeeded = [r for r in results if r.succeeded]
    skipped = [r for r in results if not r.succeeded]
    return {
        "status": "partial" if skipped else "complete",
        "delivered": [r.agent for r in succeeded],
        "skipped": [r.agent for r in skipped],
    }

Do This

  • Classify every task as mandatory, important, or optional before the pipeline runs
  • Design decompositions that produce independently valuable units — not just inputs to the next step
  • Report partial completion clearly — list what was delivered and what was skipped
  • Accept partial results as progress — 60% delivered is better than 0% from a full abort

Avoid This

  • Treat all tasks as mandatory — this makes the pipeline fragile and all-or-nothing
  • Accept partial results that are internally inconsistent — partial output must still compile and pass checks
  • Hide skipped tasks from the final report — the user needs to know what is missing
  • Design pipelines where every task depends on every other task — this eliminates any possibility of graceful degradation