ADR-0005: Declarative YAML Markup-Verb Workflows
Amended by ADR-0015: verbs are one of the three primitives resolved across the three-level
.stettopology (user / org / project).
Context and Problem Statement
Stet's markup is a command language: 🐛 means "investigate this, I think it's
wrong," 🎨 means "works but ugly, refactor," ❓ means "explain this," and so
on. Comment types and suggestions carry similar intent. Each of these verbs must
translate into concrete agent behavior when a review is submitted.
We must decide whether these verb→behavior bindings are hardcoded in Swift or expressed declaratively. We also want a path toward multi-step workflows (e.g., "refactor, then add tests, then update the doc"), and the user has an existing Temporal-style YAML workflow schema worth reusing.
Decision Drivers
- Editable without a recompile. Adding or tuning a verb should not require an app release; power users should be able to author their own.
- Toward multi-step workflows. Some intents are pipelines, not single actions.
- Reuse a known shape. A Temporal-style YAML workflow schema is a proven, legible structure.
- Local and lightweight. This runs on a Mac for a handful of concurrent dispatches — not a distributed cluster.
- Harness-agnostic. Workflows describe intent; they invoke the harness (ADR-0004) abstractly.
Considered Options
- Option A: YAML workflow definitions run by a lightweight local executor (borrow the Temporal-YAML shape, not the engine).
- Option B: Hardcode a fixed verb set in Swift now; extract config later.
- Option C: Run a real Temporal engine locally for durable, resumable workflows.
Decision Outcome
Chosen option: Option A — emoji and comment types bind to declarative YAML workflow definitions, executed by a lightweight local workflow runner. Verbs map to named workflows; a workflow is an ordered set of steps (each step targets the harness with a templated instruction, optionally gated on prior results). Stet ships a curated default verb pack; users can override or add packs. The runner is a small in-process executor modeled on the shape of the user's Temporal YAML schema — not the Temporal engine itself.
Consequences
- Good, because verbs are data, not code — tunable and extensible without a release, and user-authorable.
- Good, because the YAML shape scales naturally from single-step to multi-step workflows.
- Good, because reusing a known schema shortens design time and gives users a familiar mental model.
- Bad, because we own a small workflow executor (parsing, validation, step sequencing, error handling) — more than a hardcoded switch statement.
- Bad, because user-authored workflows are a trust/safety surface (they drive agents that write code); packs need validation and sensible sandbox limits.
- Neutral, because durable/resumable execution (a Temporal strength) is explicitly out of scope for v1; dispatches are treated as re-runnable, not checkpoint-resumable.
Confirmation
- Emoji/comment verbs resolve to YAML workflow definitions loaded from a default pack (plus user packs), not from hardcoded Swift bindings.
- The local runner executes single-step and at least one multi-step workflow
end-to-end, invoking the
Harness(ADR-0004) per step. - Invalid workflow YAML is rejected with a clear, located error.
Pros and Cons of the Options
Option A: YAML defs + lightweight local executor
- Good, editable, extensible, multi-step-ready, familiar shape.
- Bad, we own a small executor; user packs are a safety surface.
Option B: Hardcoded verbs now
- Good, fastest to ship the core loop.
- Bad, every verb change is a release; no user extensibility; a migration debt later.
Option C: Full Temporal engine locally
- Good, durable, resumable, battle-tested.
- Bad, heavyweight for a local Mac app; operational overhead unjustified at v1 scale.
More Information
Borrows the YAML workflow shape from the user's existing Temporal YAML library. See ADR-0006 (how a submitted review compiles into workflow invocations), ADR-0004 (harness the steps call), and SPEC-0002 / SPEC-0003.