# Pipeline Policies and Lifecycle Hooks ## Why this exists `PipelineExecutor` previously handled DAG traversal, failure heuristics, state persistence, and domain-event emission in one execution loop. This made behavior harder to isolate and test. ## Current structure - `FailurePolicy` (`src/agents/failure-policy.ts`) - Owns hard vs soft failure classification. - Determines whether a sequence of hard failures should abort execution. - `PersistenceLifecycleObserver` (`src/agents/lifecycle-observer.ts`) - Handles state patching, project-context updates, and domain-event publishing for each node attempt. - `PipelineExecutor` (`src/agents/pipeline.ts`) - Coordinates DAG traversal and retry behavior. - Computes aggregate run status from executed terminal nodes plus critical-path failures. - Applies dedicated `SecurityViolationError` handling policy (`hard_abort` or `validation_fail` mapping). - Resolves per-attempt `ResolvedExecutionContext` (phase/model/tool/security contract) and injects it into actor executors. ## Aggregate status semantics Run status is `success` only when both are true: 1. All executed terminal nodes (leaves in the executed subgraph) have final status `success`. 2. No executed node in the critical path has final status `failure`. Otherwise status is `failure`. ## Persistence guarantees State and project-context writes are now atomic via temp-file + rename. Project-context patch/write operations are serialized both in-process (promise queue) and cross-process (lock file). ## Tool enforcement guarantees - Pipeline resolves a flat `allowedTools` list per node attempt. - MCP config exposed to executors is pre-filtered to `allowedTools`. - Claude tool callbacks are expected to use the provided policy handler so unsupported shared MCP tool filters cannot bypass enforcement.