Home / Projects / Orchestrata Ultimate / Decisions / ADR index / ADR-0033

ADR-0033: No agent merges its own work; dispatch gates on duplication and staleness

field value
Status Accepted
Date 2026-07-24
Register factory (docs/adr, 4-digit ids)
Source docs/adr/0033-no-agent-merges-its-own-work.md — permalink at bdafa201a (unchanged on master since that commit)
Wiki register entry ADR-0033 (wiki status: Accepted)

← ADR-0032 · ADR-0034 →

The record

Context

The register already asserts author/judge separation in three specific places — ADR-0022 (the interpretation mutator may not adjudicate its own readings), ADR-0024 (the assumption enumerator may not adjudicate its own enumeration), ADR-0008 (structure, not self-reported intent). It is asserted per mechanism, and nowhere as a property of the pipeline itself.

That leaves the largest instance unaddressed: merge. Merge is promotion — ADR-0021 treats it as the moment a change becomes trunk reality. If the agent that authored a change can also merge it, every upstream separation is decorative, because the author holds the only irreversible privilege in the system. The autonomous-agent products that shipped this pattern converged on the same constraint independently: an agent may propose, and a distinct identity must promote.

Two adjacent dispatch-time failures share a root and are cheap to fix at the same point:

Both are pre-dispatch conditions, and both are silent when they fire.

Decision

1. No agent merges its own work. Merge requires an identity distinct from the authoring identity — enforced structurally by the three-UID execution model (ADR-0018), not by convention or by asking. This is stated once, as a pipeline property, superseding the need to restate separation at each new mechanism.

2. Dispatch gates on duplication. Before a task is handed to an agent, the dispatcher checks whether the same requirement/change is already in flight or already promoted. A duplicate is refused at dispatch, not adjudicated at merge.

3. Dispatch gates on staleness. A task carries the commit it was dispatched against. If trunk has moved in a way that touches the task's impact set, the task is re-based or re-dispatched, never validated against the stale fact set. "Trunk moved but not in our impact set" is the fast path and stays cheap.

4. All three failures are loud. A refused dispatch and a stale re-dispatch are recorded events, not silent no-ops — otherwise duplication and staleness look identical to "nothing happened".

Alternatives rejected

Consequences

Provenance

2026-07-24 prior-art research: the no-self-merge constraint as converged on by shipped autonomous coding agents, and the dispatch-time duplicate/staleness gate as a documented failure class. Merge was identified as the unguarded instance of a separation the register already asserts three times elsewhere.

Rulings cited

None.

Specs cited