ADR-0011: Silent pipeline halt via EarlyAbort
ACCEPTED
Context
ADR-0010 introduced EarlyExitResponse for intentional short-circuits that still owe the user a message, plus a catch-all for unexpected exceptions. A third case emerged: the pipeline must stop entirely, and sending any response or running terminal stages would be wrong. The clearest example is platform-level consent revocation — if a participant has blocked the bot or withdrawn consent, delivering a response would fail or violate their intent, and persisting a message could mislead the audit trail.
EarlyExitResponse always routes a message through terminal stages including ResponseSendingStage, so a distinct mechanism is needed for a true silent halt.
Decision
We will introduce EarlyAbort as a second pipeline control-flow exception.
- When any core stage raises
EarlyAbort, the pipeline returns immediately: noctx.early_exit_responseis set, no terminal stages run, and no user-facing message is generated. - It is distinct from
EarlyExitResponse(runs terminal stages) and from unexpected exceptions (generate an error message and run terminal stages before re-raising). EarlyAbortis reserved for cases where the channel has determined that any further activity — including sending and persisting — would be incorrect. UseEarlyExitResponsewhenever the user should receive a message.
Consequences
- Stages can halt completely without triggering sending or persistence, as needed for platform-layer consent and reachability failures.
- Stage authors must understand the
EarlyAbortvs.EarlyExitResponsedistinction; the wrong one silently skips either the response or the audit trail. - Terminal stages such as
ActivityTrackingStageandPersistenceStagedo not run onEarlyAbort, so session state is not updated for aborted interactions.
Alternatives considered
- Reuse
EarlyExitResponsewith a sentinel message → still runs terminal stages, causingResponseSendingStageto attempt delivery to an unreachable participant. - Boolean flag on context (
ctx.abort) → requires every terminal stage to check the flag, rejected for the same reason as the flag-based approach in ADR-0010.