Orchestrata Ultimate › Plans › design-escalation-absorption-2026-07-06
Escalation absorption design (D1-addendum-2) — 2026-07-06
Source: plans/design-escalation-absorption-2026-07-06.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-07-06 · 58 lines.
Prose pending.
Plan text
Escalation absorption design (D1-addendum-2) — 2026-07-06
The fork (from the W3.1 absorption map)
Kernel PipelineEscalationMixin does free-form hop routing (volk -> volk, with capability-mesh resolution, cycle/depth guards, human-approval workflow). The orchestrator runner executes a FIXED PipelineRouter.route() StageSpec sequence. Grafting free-hop routing onto a fixed sequence looked like a contradiction — that was the deferral reason.
Resolution: escalation is an INTERRUPT, not a route
The spec-backed core of escalation (specs/000 checklist, REQ-000-051..058) is the human-in-the-loop surface: review/approve/reject/respond traveling as CXP packets, human must explicitly approve, reject keeps the volk working with feedback. REQ-000-039..041 add respond-to-thread. Nothing in the spec mandates free-hop volk-to-volk re-routing as the orchestrator's normal-flow mechanism — the router owns the happy path; escalation is the exception path.
W3.1's absorption built exactly the substrate an interrupt needs:
- ESCALATE (volk requests human input / signals blocked): checkpoint the current stage (already saved on RESOLVED; add an ESCALATED checkpoint state carrying the escalation payload), emit the escalation CXP packet (reusing _build_escalation's per-target payload shaping), SUSPEND the run (return a PipelineResult with status=ESCALATED + thread_id).
- APPROVE/RESPOND (human, via session CLI / gateway): approve -> mark the escalated stage RESOLVED in the checkpoint store -> runner.resume(thread_id) continues the fixed sequence from the next stage. reject(reason)/respond(text) -> re-enter THE SAME stage with the feedback folded into the stage payload (retry-with-feedback), preserving REQ-000-056 "reject keeps volk working with feedback".
- CAPABILITY REQUESTS (needs_capability): resolve via the mixin's _CAPABILITY_PROVIDERS mesh, then INSERT the provider volk as a stage before the current stage in the remaining sequence (a bounded, router-visible amendment) instead of free-hopping. Cycle/depth safety comes for free: insertion count per run is capped (reuse the mixin's depth limit); the cycle detector guards repeated provider insertion.
What moves where
- PipelineEscalationMixin's _build_escalation, approve/_find_active_volk/ _dispatch_approval, cycle/depth guards: PORT into an orchestrator-side EscalationInterruptMixin (new file orchestrator/pipeline_escalation.py), adapted from packet-hop shape to stage-interrupt shape. Traces-union REQ-000-039..058 + REQ-005-FR10/AC11 ids onto the ported symbols (kernel keeps its stamps while its REPL still exercises them).
- Kernel mixin stays untouched until the port is proven (pipeline_cli REPL still uses it); kernel/pipeline.py demotes to boot shim in a final W3.1 closure task after this lands.
- session CLI:
pipeline respond/approve/reject --threadsubcommands wire to the checkpoint-store + resume path (REQ-000-039/053/055).
Acceptance
- A stage can escalate; the run suspends with a checkpointed ESCALATED state.
- approve resumes from the NEXT stage; reject re-runs the SAME stage with feedback in payload; respond delivers text mid-stage.
- needs_capability inserts the provider stage; insertion is depth-capped and cycle-guarded; unknown capability -> clean escalation to human.
- No auto-approval anywhere (REQ-000-058).
- Kernel suites untouched-green; gateway live path behavior unchanged when no escalation occurs (interrupt code dormant on the happy path).