# MoonEdit deterministic merge contract

Status: available in the editor-core library
Contract version: `moonedit.merge.v1`

## Boundary

MoonEdit owns a pure, host-independent three-way text merge. A merge input binds
the exact base, local and remote text to three opaque identities. In the
workspace integration those identities are the host's base/remote
`FileVersion` tokens and MoonEdit's URI-scoped local document revision.

The algorithm operates on line records while retaining their exact line
endings. It deterministically composes non-overlapping edits, collapses
identical edits and returns every ambiguous overlap as a structured conflict.
It never inserts conflict markers or silently prefers local or remote text.

Each outcome records:

- SHA-256 digests of all exact input text and identities;
- a deterministic plan digest;
- ordered base ranges and resolved/unresolved segments;
- stable content-derived conflict IDs;
- a result digest for clean merges.

## Review and acceptance

A `ResolutionProposal` must select every conflict exactly once. Its author is
typed as either a named human or an identified agent. A proposal is never an
acceptance. Actor identities are trimmed to a canonical nonblank value;
whitespace-only identities are rejected.

`ConflictMerge::accept` requires:

- the same exact base/local/remote identities;
- the same plan and proposal digests;
- a separately identified `NamedHuman`.

It returns an immutable `ResolutionReceipt` containing the accepted result,
input/result/proposal/receipt digests, each choice and its original selector,
and the named human acceptance. An agent-authored proposal therefore remains
agent-authored in the receipt and cannot impersonate human approval.

## Workspace effects

`Workspace::request_merge` emits `LoadMerge` bound to the current local revision
and base `FileVersion`. `merge_loaded` only creates a reviewable outcome.
The first exact terminal callback wins; an identical replay is idempotent and a
different replay is rejected. `merge_load_failed` clears only the matching
request so the host can retry without changing the conflicted document.
`apply_clean_merge` and `apply_resolution_receipt` are explicit operations and
recheck the pending plan digest, local revision, base version, identities and
input digest before changing the document.

After application, the loaded remote snapshot becomes the next compare-and-swap
baseline. The composed result remains dirty exactly when it differs from that
remote snapshot. Hosts still own persistence, transport and UI.

## Non-goals

- no filesystem or LSP transport;
- no conflict-resolution UI;
- no host persistence;
- no model/runtime invocation;
- no semantic or syntax-aware merge claim;
- no automatic human acceptance.

## Focused verification

The package covers non-overlapping and identical edits, conflicting edits,
insert/delete boundaries, competing insertions, stale identities, stale
proposals, deterministic replay and immutable human acceptance receipts.
