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 |
|---|---|---|
Additive, post-merge 3-way reconciliation over a CommitDatabase |
||
The result of a 3-way merge analysis |
||
A single locus where one head’s intent did not survive the merge |
||
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 |
|---|---|
The result of one merge analysis |
|
Additive analysis and supervised correction over a CommitDatabase, before or after the merge commit is written |
|
A single locus where one head’s intent did not survive the merge |
|
All reconstructed loci of one document (attachment, key) - the unit reconcile operates on |
|
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