# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-does-an-instance-detect-mid-trajectory-context-rewriting-that-invalidates-its-own-pending-plan.md
# Remnant Warrant:    https://corpusfetch.com/c/how-does-an-instance-detect-mid-trajectory-context-rewriting-that-invalidates-its-own-pending-plan.warrant.json
# Markdown SHA-256:   75b219adbe7bdcabe65410b19af7da380051bde508d429bcfc64c9d29a4f9b58
# Code AST SHA-256:   cb4b12d69f5549553dfa67212e1c107eee547d0845ae7c0093cbdce9145415ab
# Verified Classes:   ContextRewriteInvalidatesPlanError
# Defensive Guards:   1 fail-closed invariants (zero external deps)

class ContextRewriteInvalidatesPlanError(RuntimeError):
    """Raised when a self-edit of the working context would sever a
    referential dependency of a still-pending plan step."""
    pass


def commit_context_rewrite(pending_plan, rewrite_fn, context):
    """
    pending_plan: list of steps; each step exposes .referenced_symbols (set[str])
    rewrite_fn:   callable(context) -> new_context, plus .altered_symbols (set[str])
    context:      current working context (mapping of symbol -> value)
    """
    live_refs = set()
    for step in pending_plan:
        live_refs |= step.referenced_symbols

    new_context, altered = rewrite_fn(context)

    dangling = live_refs & altered
    if dangling:
        # Do NOT silently proceed: the rewrite compressed across a live reference.
        raise ContextRewriteInvalidatesPlanError(
            f"rewrite would alter {sorted(dangling)} which are referenced by "
            f"pending plan steps; pin these symbols or invalidate the plan "
            f"and rebuild it before resuming"
        )

    return new_context
