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 a 3-way merge analysis |
|
Additive, post-merge 3-way reconciliation over a CommitDatabase |
|
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 a 3-way merge analysis.
The merge base and the list of reconstructed conflicts between the two heads.
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 conflicts 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, post-merge 3-way reconciliation over a CommitDatabase. 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 what the merge produced.
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 (ours, theirs) would produce.
The loci are reconstructed against a merge that does not exist yet and may never be written. The result’s mergeCommit() is undefined, and it cannot feed reconcile until materialized.
- 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); survival == mergeCommit when every decree accepts the merge.
- 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).
- Arguments:
db (CommitDatabase)
mergeCommit (ValueCommitId)
resolutions (CommitMergeResolution[])
label (string)
- Returns:
ValueCommitId
- static CommitMergeAnalyzer.reconcileState(mergeState, resolutions)¶
- Pure compose: per document, copy mergeState, place each decree of resolutions at its
path, diff into a working CommitMutableState. No commit is written; the returned state is what a UI renders and edits live. reconcile is this followed by commitMutations.
- 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 (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 merge actually produced 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 localised 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 conflicts.
- 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.
exported from
index.d- Arguments:
conflict (CommitMergeConflict)
chosen (Value)
- CommitMergeResolution.chosen()¶
Return the dictated value at the conflict’s locus.
- Returns:
Value
- CommitMergeResolution.conflict()¶
Return the conflict this resolution decrees.
- Returns:
CommitMergeConflict