# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-a-replayed-last-event-id-as-a-new-stream-rather-than-a-resumption-and-why-the-naive-resume-if-the-id-is-k.md
# Remnant Warrant:    https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-a-replayed-last-event-id-as-a-new-stream-rather-than-a-resumption-and-why-the-naive-resume-if-the-id-is-k.warrant.json
# Markdown SHA-256:   d5c51257120936db7cdef26ff868e35f93dac5a1be0bcc3446389a4f4ecb9e83
# Code AST SHA-256:   28c86c65231c008ebfe7c9365d139e8498dbadb9f700876855ae4d3a1fba6538
# Verified Classes:   StaleResumptionCursor, EventStream
# Defensive Guards:   5 fail-closed invariants (zero external deps)

class StaleResumptionCursor(RuntimeError):
    """Raised when a Last-Event-ID is recognized but is not a valid
    continuation point for the stream being attached to."""
    pass


class EventStream:
    def __init__(self, session_epoch: str, stream_id: str):
        self.session_epoch = session_epoch
        self.stream_id = stream_id
        self.terminal = False
        self.buffer: dict[str, dict] = {}

    def make_event_id(self, seq: int) -> str:
        return f"{self.session_epoch}-{self.stream_id}-{seq}"

    def emit(self, seq: int, payload: dict, terminal: bool = False) -> str:
        eid = self.make_event_id(seq)
        self.buffer[eid] = payload
        if terminal:
            self.terminal = True
        return eid


def resume_stream(stream: EventStream, last_event_id: str) -> list[dict]:
    """Return events strictly after last_event_id, or raise if the cursor
    is stale (wrong stream generation or already-terminal stream)."""
    parts = last_event_id.split("-")
    if len(parts) != 3:
        raise StaleResumptionCursor(f"malformed Last-Event-ID: {last_event_id!r}")

    epoch, sid, _seq = parts
    if epoch != stream.session_epoch:
        raise StaleResumptionCursor(
            f"session epoch mismatch: cursor={epoch} current={stream.session_epoch}"
        )
    if sid != stream.stream_id:
        raise StaleResumptionCursor(
            f"stream generation mismatch: cursor={sid} current={stream.stream_id}"
        )
    if stream.terminal:
        raise StaleResumptionCursor(
            "cursor points into a completed stream; must start a fresh stream"
        )
    if last_event_id not in stream.buffer:
        raise StaleResumptionCursor(f"unknown cursor: {last_event_id!r}")

    ordered = list(stream.buffer.items())
    idx = [k for k, _ in ordered].index(last_event_id)
    return [payload for _, payload in ordered[idx + 1:]]
