feat: event_status_reverted event kind + projector handler (T114.2)
Adds the inverse projection used by T114.3's regenerate rollback. The
new ``event_status_reverted`` event kind carries
``{event_id, prior_status}`` and the handler unconditionally sets
``events.status = prior_status`` for the row.
Unlike the forward transitions (event_started / event_completed /
event_cancelled), this handler does NOT guard against terminal
statuses — its entire purpose is to reverse a transition, including
walking back from a terminal status to a non-terminal one. Without
that, rolling back an event_completed (status='completed' is terminal
for the forward handlers) would silently no-op and leave the row in
the post-superseded state.
The handler registers via the existing ``@on(kind)`` decorator pattern
in chat/eventlog/projector.py, so future replays of an event_log that
contains event_status_reverted rows pick it up automatically.
Test exercises completed→active, active→planned, and cancelled→active
round-trips.
This commit is contained in:
@@ -67,6 +67,29 @@ def _apply_event_expired(conn: Connection, e: Event) -> None:
|
||||
)
|
||||
|
||||
|
||||
@on("event_status_reverted")
|
||||
def _apply_event_status_reverted(conn: Connection, e: Event) -> None:
|
||||
"""T114.2: Revert an event row's status to ``prior_status``.
|
||||
|
||||
Emitted by ``regenerate_assistant_turn`` when a superseded turn had
|
||||
triggered a lifecycle transition (event_started / event_completed /
|
||||
event_cancelled). The rollback step needs an inverse projection that
|
||||
sets the row's status back to whatever it was *before* the now-
|
||||
superseded transition fired.
|
||||
|
||||
Unlike the forward transitions (which guard against terminal-status
|
||||
overwrites) this handler is unconditional — the entire purpose is to
|
||||
reverse a transition, including reverting from a terminal status
|
||||
(completed/cancelled) back to a non-terminal one.
|
||||
"""
|
||||
p = e.payload
|
||||
conn.execute(
|
||||
"UPDATE events SET status = ?, updated_at = datetime('now') "
|
||||
"WHERE event_id = ?",
|
||||
(p["prior_status"], p["event_id"]),
|
||||
)
|
||||
|
||||
|
||||
def get_event(conn: Connection, event_id: str) -> dict | None:
|
||||
row = conn.execute(
|
||||
"SELECT event_id, chat_id, kind, status, props_json, planned_for, "
|
||||
|
||||
Reference in New Issue
Block a user