Coder preparations
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# orchestrator/step_result.py
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Literal
|
||||
|
||||
# Terminal reasons are strings, not an enum, so you can add domain-specific
|
||||
# reasons (e.g. "escalated:ci_infra") without touching this module.
|
||||
TerminalReason = str
|
||||
AwaitState = str # must be one of the AWAITING_* names, or "ABANDONED"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StepResult:
|
||||
"""
|
||||
The outcome of a step handler.
|
||||
|
||||
This is control flow, not data. The step's contract *output* lives in
|
||||
`output`; the fields here tell the runner what to do next. The runner
|
||||
is the only thing that reads these fields; handlers only construct them.
|
||||
"""
|
||||
kind: Literal["continue", "await", "terminal"]
|
||||
next_step: str | None = None # set iff kind == "continue"
|
||||
await_state: AwaitState | None = None # set iff kind == "await"
|
||||
terminal_reason: TerminalReason | None = None # set iff kind == "terminal"
|
||||
output: Any = None # the step's contract output
|
||||
|
||||
# ── constructors ─────────────────────────────────────────────
|
||||
|
||||
@classmethod
|
||||
def continue_to(cls, step: str, output: Any = None) -> "StepResult":
|
||||
"""Advance to another step in the pipeline."""
|
||||
return cls(kind="continue", next_step=step, output=output)
|
||||
|
||||
@classmethod
|
||||
def awaiting(cls, state: AwaitState, output: Any = None) -> "StepResult":
|
||||
"""Stop this call; resume when the await trigger fires."""
|
||||
if not (state.startswith("AWAITING_") or state == "ABANDONED"):
|
||||
raise ValueError(f"not an await state: {state!r}")
|
||||
return cls(kind="await", await_state=state, output=output)
|
||||
|
||||
@classmethod
|
||||
def complete(cls, output: Any = None) -> "StepResult":
|
||||
"""Terminal: MR merged and task closed."""
|
||||
return cls(kind="terminal", terminal_reason="completed", output=output)
|
||||
|
||||
@classmethod
|
||||
def abandoned(cls, output: Any = None) -> "StepResult":
|
||||
"""Terminal: no response within the timeout window."""
|
||||
return cls(kind="terminal", terminal_reason="abandoned", output=output)
|
||||
|
||||
@classmethod
|
||||
def escalated(cls, reason: str, output: Any = None) -> "StepResult":
|
||||
"""Terminal: stopping because a human must intervene."""
|
||||
return cls(kind="terminal", terminal_reason=f"escalated:{reason}",
|
||||
output=output)
|
||||
Reference in New Issue
Block a user