pub struct MergeSession {
pub merge_id: MergeSessionId,
pub src_head: Option<OpId>,
pub dst_head: Option<OpId>,
pub lca: Option<OpId>,
pub auto_resolved: Vec<MergeOutcome>,
/* private fields */
}Expand description
Stateful merge in flight. Hold one per active merge between
start and commit. Sessions are not thread-safe; the HTTP
wrapper is expected to wrap them in a Mutex keyed by
MergeSessionId.
Fields§
§merge_id: MergeSessionId§src_head: Option<OpId>§dst_head: Option<OpId>§lca: Option<OpId>§auto_resolved: Vec<MergeOutcome>Outcomes the engine resolved unilaterally — Both (both
sides agreed) and one-sided (Src / Dst). The agent sees
these for audit but doesn’t need to act on them.
Implementations§
Source§impl MergeSession
impl MergeSession
Sourcepub fn start(
merge_id: impl Into<MergeSessionId>,
op_log: &OpLog,
src_head: Option<&OpId>,
dst_head: Option<&OpId>,
) -> Result<Self>
pub fn start( merge_id: impl Into<MergeSessionId>, op_log: &OpLog, src_head: Option<&OpId>, dst_head: Option<&OpId>, ) -> Result<Self>
Start a merge session. Runs the engine in crate::merge
and partitions the outcomes into auto-resolved and
conflicts-needing-attention.
Sourcepub fn attach_file_conflicts(
&mut self,
conflicts: Vec<FileConflict>,
needs_setfiles: bool,
)
pub fn attach_file_conflicts( &mut self, conflicts: Vec<FileConflict>, needs_setfiles: bool, )
Attach the files dimension of the merge (#1007 PR 7): the
conflicts a 3-way manifest diff surfaced (paths edited
differently on both sides — see FileConflict) and whether
the merge needs a SetFiles op at all. Called once, right
after Self::start, by the caller that holds the store (the
same layering ResolutionChecker uses: this crate tracks the
session’s state machine, the caller computes the domain-specific
diff). A no-op call with an empty conflicts and
needs_setfiles: false — the default — leaves a session with
no files dimension, exactly as before this feature existed.
Sourcepub fn needs_setfiles(&self) -> bool
pub fn needs_setfiles(&self) -> bool
Whether the merge needs a SetFiles op appended on commit, per
MergeCommitOutput::needs_setfiles.
Sourcepub fn remaining_file_conflicts(&self) -> Vec<&FileConflict>
pub fn remaining_file_conflicts(&self) -> Vec<&FileConflict>
Pending file conflicts (those without a non-defer resolution).
Mirrors Self::remaining_conflicts.
Sourcepub fn resolve_files(
&mut self,
resolutions: Vec<(FilePath, FileResolution)>,
) -> Vec<FileResolveVerdict>
pub fn resolve_files( &mut self, resolutions: Vec<(FilePath, FileResolution)>, ) -> Vec<FileResolveVerdict>
Submit file resolutions in batch. Mirrors Self::resolve:
unlike sig resolutions there is no type-check to run (SetFiles
carries no program semantics), so this is the only resolve path
files need — no resolve_files_checked counterpart.
Sourcepub fn remaining_conflicts(&self) -> Vec<&ConflictRecord>
pub fn remaining_conflicts(&self) -> Vec<&ConflictRecord>
Pending conflicts (those without a non-defer resolution).
Sourcepub fn resolve(
&mut self,
resolutions: Vec<(ConflictId, Resolution)>,
) -> Vec<ResolveVerdict>
pub fn resolve( &mut self, resolutions: Vec<(ConflictId, Resolution)>, ) -> Vec<ResolveVerdict>
Submit resolutions in batch. Returns one verdict per input. Accepted resolutions are recorded; rejected ones leave the previous resolution (if any) in place so partial submissions don’t clobber earlier good work.
Sourcepub fn resolve_checked(
&mut self,
resolutions: Vec<(ConflictId, Resolution)>,
checker: &dyn ResolutionChecker,
) -> Vec<ResolveVerdict>
pub fn resolve_checked( &mut self, resolutions: Vec<(ConflictId, Resolution)>, checker: &dyn ResolutionChecker, ) -> Vec<ResolveVerdict>
Submit resolutions in batch, type-checking each against the composed program before accepting it (#834).
This is the loop the session was built for — “submit N
resolutions, see which broke type-checking, fix them, retry” —
made real. Structural validation (Self::validate_resolution)
runs first; a structurally-valid resolution is then overlaid on
dst’s head together with every resolution accepted so far, and
the injected ResolutionChecker type-checks the result. A
resolution whose composed program doesn’t type-check is rejected
with ResolutionRejection::TypeError and not recorded, so
the session’s accepted set stays type-correct at every step.
Resolutions are processed in order and accumulate: a later
resolution is checked against the program the earlier accepted
ones already produced. Interdependent picks (two conflicts that
only compose together) should therefore be submitted in
dependency order, or a rejected one resubmitted after its
partner lands — the same way git needs both halves of an
intertwined conflict resolved before the tree builds. Unresolved
conflicts contribute nothing to the projection: they leave dst’s
(always-valid) side standing, so a partial batch still composes.
Sourcepub fn validate_resolution(
&self,
conflict_id: &ConflictId,
resolution: &Resolution,
) -> Result<(), ResolutionRejection>
pub fn validate_resolution( &self, conflict_id: &ConflictId, resolution: &Resolution, ) -> Result<(), ResolutionRejection>
Validate a single resolution against the session’s pending conflicts. Pure (no side effects); the caller decides whether to accept.
Sourcepub fn commit(self) -> Result<MergeCommitOutput, CommitError>
pub fn commit(self) -> Result<MergeCommitOutput, CommitError>
Finalize the merge. On success returns the resolved sig and
file resolutions, in id order, plus whether the caller must
append a SetFiles. The caller is responsible for synthesizing
the final Operation::Merge (and, if needs_setfiles, the
follow-up SetFiles) op against the store and persisting them;
this function returns the engine’s view of “what to land,” not
the persisted op ids.
Sig conflicts are checked before file conflicts: a session with
both kinds pending reports CommitError::ConflictsRemaining
first, exactly the precedence #977’s merge gate already used for
dependency conflicts vs. type errors — one blocker surfaced at a
time keeps the agent’s retry loop simple.