# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-happens-when-an-instance-commits-a-speculative-branch-whose-reconciliation-window-has-already-been-closed-by-a-concurrent-merge.md
# Remnant Warrant:    https://corpusfetch.com/c/what-happens-when-an-instance-commits-a-speculative-branch-whose-reconciliation-window-has-already-been-closed-by-a-concurrent-merge.warrant.json
# Markdown SHA-256:   471d0d242b37666e3334e37fe3c6ca258acfe98684376334d089e4b4971a3369
# Code AST SHA-256:   671a4f555c0b16d726cd9e448185e77b6a30a3fe82a63ec0821b50b822d19c18
# Verified Classes:   ClosedReconciliationWindow, Branch, MergeDAG
# Defensive Guards:   2 fail-closed invariants (zero external deps)

from dataclasses import dataclass, field
from typing import Optional


class ClosedReconciliationWindow(RuntimeError):
    """Raised when a speculative branch targets an epoch that is no longer
    an ancestor of the current merge head. The branch may still be valid;
    it is simply inadmissible and must be rebased or aborted."""

    def __init__(self, branch_id: str, fork_epoch: int, current_head: int,
                 reason: str = "fork point is not an ancestor of current head"):
        self.branch_id = branch_id
        self.fork_epoch = fork_epoch
        self.current_head = current_head
        self.reason = reason
        super().__init__(
            f"branch {branch_id!r} forked at epoch {fork_epoch} but current "
            f"head is {current_head}: {reason}"
        )


@dataclass
class Branch:
    branch_id: str
    fork_epoch: int
    valid: bool
    mutations: list = field(default_factory=list)


@dataclass
class MergeDAG:
    head_epoch: int
    # ancestors[epoch] = set of epochs that are ancestors of `epoch`, inclusive
    ancestors: dict = field(default_factory=dict)

    def is_ancestor(self, epoch: int, of: int) -> bool:
        return epoch in self.ancestors.get(of, {epoch})


def reconcile(branch: Branch, dag: MergeDAG) -> int:
    """Commit a speculative branch into the merge DAG, or raise.

    Validity is necessary but NOT sufficient. Admissibility requires that the
    branch's fork point be an ancestor of the current head.
    """
    if not branch.valid:
        raise ClosedReconciliationWindow(
            branch.branch_id, branch.fork_epoch, dag.head_epoch,
            reason="branch failed validity replay",
        )

    if not dag.is_ancestor(branch.fork_epoch, dag.head_epoch):
        # The window closed while the branch was executing. Do NOT commit.
        raise ClosedReconciliationWindow(
            branch.branch_id, branch.fork_epoch, dag.head_epoch,
        )

    return dag.head_epoch
