Merge Reconciliation

CommitMergeAnalyzer is an additive, application-level supervisor over the public CommitDatabase API. The engine reduces concurrent streams mechanically and signals no conflict; this layer reconstructs a notion of conflict over a merge — already persisted, or computed from the two heads before it is written — and lets a caller make a chosen value survive. It adds no engine, storage-format, or runtime change.

When to use: reach for this family when the application, not the engine, must decide which value survives where two streams touched the same locus. If mechanical reduction is acceptable, none of this is needed.

See also

Supervised Reconciliation — the model, the headless identify / surface / reconcile triad, and its bounds.

Quick Start

const { CommitMergeAnalyzer, CommitMergeResolution } =
    require('@digitalsubstrate/dsviper');

const merge = db.mergeCommit('merge', ours, theirs);
const analysis = CommitMergeAnalyzer.analyzeMerge(db, merge);

// The supervisor decides per conflict; here, keep ours at every locus.
// A resolution pairs the conflict with the value to make survive at its path —
// oursValue() already reads that value at the conflict's locus.
const resolutions = analysis.conflicts().map(
    (c) => new CommitMergeResolution(c, c.oursValue().unwrap()));

const survivor = CommitMergeAnalyzer.reconcile(db, merge, resolutions, 'reconcile');

Accepting the merge for every conflict makes reconcile return the merge commit unchanged.

The same three steps run before the merge commit exists: analyzeVirtualMerge(db, ours, theirs) — whose analysis carries no anchor, so CommitMergeAnalysis.mergeCommit() is undefined — then reconcileState(mergeState, resolutions) to render the arbitrated state in memory (writing nothing), and materializeMerge(db, ours, theirs, resolutions, mergeLabel, survivalLabel) to write the merge and its survival child together. The merge state comes from CommitStateBuilder.mergeState(db, ours, theirs).

Key classes

Class

Purpose

Example

CommitMergeAnalyzer

Additive, post-merge 3-way reconciliation over a CommitDatabase

CommitMergeAnalysis

The result of a 3-way merge analysis

CommitMergeConflict

A single locus where one head’s intent did not survive the merge

CommitMergeResolution

A supervisor’s decree for one reconstructed conflict: the chosen value should survive at the conflict’s locus

The mirror of this page for the Python binding is Merge Reconciliation.

Classes

Class

Description

CommitMergeAnalysis

The result of one merge analysis

CommitMergeAnalyzer

Additive analysis and supervised correction over a CommitDatabase, before or after the merge commit is written

CommitMergeConflict

A single locus where one head’s intent did not survive the merge

CommitMergeDocument

All reconstructed loci of one document (attachment, key) - the unit reconcile operates on

CommitMergeResolution

A supervisor’s decree for one reconstructed conflict: the chosen value should survive at the conflict’s locus

Reference

class CommitMergeAnalysis()

The result of one merge analysis.

The base when the two heads had an unambiguous one, and the list of reconstructed conflicts between them.

Note: Not directly instantiable.

exported from index.d

CommitMergeAnalysis.base()
Return the structural merge base commit identifier, or undefined when the

analysis fell back to a base-free 2-way scan.

Returns:

ValueCommitId | undefined

CommitMergeAnalysis.conflicts()

Return every reconstructed locus, flattened across documents.

Returns:

CommitMergeConflict[]

CommitMergeAnalysis.documents()
Return the list of CommitMergeDocument - the reconstructed loci grouped per

document (attachment, key), the unit reconcile operates on.

Returns:

CommitMergeDocument[]

CommitMergeAnalysis.hasConflicts()
Return true if the analysis reconstructed at least one locus where an intent was

lost.

Returns:

boolean

CommitMergeAnalysis.mergeCommit()
Return the merge commit identifier this analysis read, or undefined for a

virtual (pre-merge) analysis computed without a persisted merge commit.

Returns:

ValueCommitId | undefined

CommitMergeAnalysis.ours()

Return the parent (ours) commit identifier.

Returns:

ValueCommitId

CommitMergeAnalysis.theirs()

Return the target (theirs) commit identifier.

Returns:

ValueCommitId

CommitMergeAnalysis.twoWay()
Return true when no unambiguous structural base existed and detection

fell back to a base-free 2-way divergence scan.

Returns:

boolean

class CommitMergeAnalyzer()
Additive analysis and supervised correction over a CommitDatabase, before or after the

merge commit is written. Static methods only; the Commit Engine itself is not modified.

It works around the reduction; it does not repair it. The engine has no notion of conflict, so what this class calls a conflict is reconstructed after the fact, by comparing the two heads against the state reconstructed at the merge.

Note: Not directly instantiable.

exported from index.d

static CommitMergeAnalyzer.analyzeMerge(db, mergeCommit)
Read the state of mergeCommit in db and return a CommitMergeAnalysis: the loci where

one head’s intent did not survive the merge. 3-way when a unique structural base exists, base-free 2-way fallback otherwise. Throws when mergeCommit is not a merge commit.

Arguments:
  • db (CommitDatabase)

  • mergeCommit (ValueCommitId)

Returns:

CommitMergeAnalysis

static CommitMergeAnalyzer.analyzeVirtualMerge(db, ours, theirs)

Pre-merge analysis over db, without persisting a merge commit.

The same classification runs against the merge state that reducing (ours, theirs) would produce.

The loci are reconstructed against a merge that does not exist yet and may never be written, so the result’s mergeCommit() is undefined. Its resolutions feed materializeMerge over the same (ours, theirs), in the same order, or reconcile once that merge is written: the merge of the reversed pair keeps the other side.

Arguments:
  • db (CommitDatabase)

  • ours (ValueCommitId)

  • theirs (ValueCommitId)

Returns:

CommitMergeAnalysis

static CommitMergeAnalyzer.materializeMerge(db, ours, theirs, resolutions, mergeLabel, survivalLabel)

Pre-merge materialization in db.

Writes the Merge join of (ours, theirs) under mergeLabel, then the survival commit of resolutions against it under survivalLabel.

Returns [mergeCommit, survival]; the two are equal - ask equals(), not == - when every decree accepts the merge. Throws before writing anything when a resolution was analysed against another (ours, theirs), the reversed pair included.

Arguments:
  • db (CommitDatabase)

  • ours (ValueCommitId)

  • theirs (ValueCommitId)

  • resolutions (CommitMergeResolution[])

  • mergeLabel (string)

  • survivalLabel (string)

Returns:

[ValueCommitId, ValueCommitId]

static CommitMergeAnalyzer.mergeBase(db, a, b)
Return the structural merge base of a and b in db, or undefined when there is no

common ancestor or several maximal common ancestors (criss-cross).

Arguments:
  • db (CommitDatabase)

  • a (ValueCommitId)

  • b (ValueCommitId)

Returns:

ValueCommitId | undefined

static CommitMergeAnalyzer.reconcile(db, mergeCommit, resolutions, label)

Author the survival commit for mergeCommit in db under label.

Per document, copy the merge state, place each decree of resolutions at its path, then diff against the merge state. Returns a Mutations commit child of mergeCommit, or mergeCommit itself when every decree accepts the merge (no surviving opcode).

Throws, writing nothing, when mergeCommit is not a merge commit, or when a resolution was analysed against another (ours, theirs) than the one mergeCommit joins. The survival commit is a child of mergeCommit whatever came after it: on a merge that already has descendants, it is one more head.

Arguments:
  • db (CommitDatabase)

  • mergeCommit (ValueCommitId)

  • resolutions (CommitMergeResolution[])

  • label (string)

Returns:

ValueCommitId

static CommitMergeAnalyzer.reconcileState(mergeState, resolutions)

Compose the resolutions into a working state, writing no commit.

Per document, copy mergeState, place each decree of resolutions at its path, diff into a CommitMutableState. The returned state is what a UI renders and edits live. reconcile is this followed by commitMutations, over a MATERIALIZED merge and only there.

Given a virtual merge state, CommitStateBuilder.mergeState of two heads not yet joined, committing the result writes a Mutations commit on ONE parent: the two heads stay and a third appears, where a merge would have left one. Use materializeMerge, which writes the join and the survival commit in order.

Arguments:
  • mergeState (CommitState)

  • resolutions (CommitMergeResolution[])

Returns:

CommitMutableState

class CommitMergeConflict()

A single locus where one head’s intent did not survive the merge.

Anchored on a path, and reconstructed as base/ours/theirs/merged values.

Note: Not directly instantiable.

exported from index.d

CommitMergeConflict.attachment()

Return the attachment this locus belongs to.

Returns:

Attachment

CommitMergeConflict.baseValue()

Return the value at the merge base, an optional that is nil in 2-way mode.

Returns:

ValueOptional

CommitMergeConflict.key()

Return the key of the document this locus was reconstructed in.

Returns:

ValueKey

CommitMergeConflict.mergedValue()

Return the value the state reconstructed at the merge commit holds at this locus.

Returns:

ValueOptional

CommitMergeConflict.oursValue()

Return the value on the parent (ours) side.

Returns:

ValueOptional

CommitMergeConflict.path()
Return the locus inside the document where the intent was lost (root

for a scalar attachment).

Returns:

PathConst

CommitMergeConflict.theirsValue()

Return the value on the target (theirs) side.

Returns:

ValueOptional

class CommitMergeDocument()
All reconstructed loci of one document (attachment, key) - the unit reconcile operates

on. Carries the whole merged document as context.

Note: Not directly instantiable.

exported from index.d

CommitMergeDocument.attachment()

Return the attachment of this document.

Returns:

Attachment

CommitMergeDocument.conflicts()

Return the list of CommitMergeConflict reconstructed in this document.

Returns:

CommitMergeConflict[]

CommitMergeDocument.key()

Return the key of this document.

Returns:

ValueKey

CommitMergeDocument.mergedValue()

Return the whole merged document, as context for its reconstructed loci.

Returns:

ValueOptional

class CommitMergeResolution(conflict, chosen)
A supervisor’s decree for one reconstructed conflict: the chosen value should survive at

the conflict’s locus. A root locus decrees the whole document. chosen is checked against the type the locus declares.

exported from index.d

Arguments:
  • conflict (CommitMergeConflict)

  • chosen (InputValue)

CommitMergeResolution.chosen(encoded)

Return the dictated value at the conflict’s locus.

Passing encoded false returns a Value rather than a native JS value.

Arguments:
  • encoded (false)

Returns:

Value

CommitMergeResolution.conflict()

Return the reconstructed conflict this resolution decrees.

Returns:

CommitMergeConflict