# Explicit Terminal Stop Model Contract

Status: approved migration contract for Omagy workflow runtime, hooks, MCP state,
and plugin skill surfaces.

## Purpose

This document locks the canonical terminal stop vocabulary for active Omagy
workflows. It exists so runtime code, Antigravity Stop hooks, MCP state, and
user-facing handoff guidance describe the same end-of-turn semantics.

## Canonical terminal lifecycle outcomes

These are the only canonical user-facing terminal lifecycle outcomes for the
explicit stop model:

| Outcome | Meaning | Continuation rule | User-facing expectation |
| --- | --- | --- | --- |
| `finished` | The workflow completed successfully. | Do not auto-continue. | Report completion evidence and resulting artifacts. |
| `blocked` | Progress cannot continue because a non-user prerequisite is missing. | Do not auto-continue until the blocker changes. | Report the blocker, why it matters, and the required handoff. |
| `failed` | The workflow or verification failed. | Do not auto-continue until the failure is addressed. | Report failure evidence, impact, and recommended recovery. |
| `userinterlude` | The user intentionally interrupted or paused the run. | Do not auto-continue unless the user explicitly restarts it. | Report that the stop was user-originated, not model-originated. |
| `askuserQuestion` | Omagy must ask the user a blocking question before safe progress can continue. | Do not auto-continue until the question is answered. | Ask one concrete blocking question and record the question metadata. |

`askuserQuestion` and `userinterlude` are intentionally distinct:

- `askuserQuestion` is model-originated and should be backed by `omagy question`
  or equivalent machine-readable question metadata.
- `userinterlude` is user-originated interruption or stop intent.

## Legacy compatibility rules

Legacy values may appear in persisted state during migration, but they are
compatibility inputs, not the public canonical vocabulary.

| Legacy value | Canonical interpretation |
| --- | --- |
| `finish`, `complete`, `completed`, `done` | normalize to `finished` |
| `blocked_on_user` | normalize to `askuserQuestion` only when question metadata proves Omagy asked a blocking question; otherwise normalize to `blocked` |
| `cancelled`, `canceled`, `abort`, `aborted` | normalize to `userinterlude` |

`cancelled` remains valid for legacy administrative teardown and
backward-compatible reads. It is not a canonical user-facing terminal lifecycle
outcome in the explicit stop model.

## State precedence

Terminal lifecycle metadata must be interpreted in this order:

1. canonical `lifecycle_outcome`
2. legacy `run_outcome`
3. fallback inference from `current_phase`, question metadata, and persisted
   context

`current_phase` and lifecycle outcome are related but not identical. A workflow
can keep legacy phase names while still exposing canonical lifecycle metadata.
If both canonical lifecycle metadata and legacy `run_outcome` are present,
`lifecycle_outcome` wins.

## Stop hook rules

Stop hooks prefer explicit lifecycle metadata over assistant prose. They must:

- honor `finished`, `blocked`, `failed`, `userinterlude`, and `askuserQuestion`
  first
- keep honoring legacy phase names as compatibility inputs
- avoid treating optional assistant prose as lifecycle authority
- never present `cancelled`, `complete`, or `blocked_on_user` as canonical
  lifecycle outcomes

## Terminal handoff contract

When an active workflow produces a terminal user-facing message, the handoff must
include:

1. **Outcome** - one explicit lifecycle label
2. **Evidence** - concrete verification output, failure evidence, or the missing
   dependency/question
3. **Artifacts / state** - changed files, saved artifacts, or recorded question
   identifiers when relevant
4. **Handoff** - the exact next owner or required answer, without optional
   permission-seeking phrasing

Do not end active workflow terminal handoffs with optional softeners such as
`If you want`, `If you'd like`, or `Would you like me to continue?`.

## Non-goals

This contract does not require every legacy internal phase name to be renamed
immediately. It requires every migrated surface to expose and prefer the
canonical terminal lifecycle concepts above.
