feat: drawer edits with manual_edit event capture
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
"""Handler for ``manual_edit`` events (T25, §6.4 final paragraph).
|
||||
|
||||
A ``manual_edit`` event captures a user override of a projected field — its
|
||||
payload snapshots both the prior value and the new value so any edit can
|
||||
be reversed by emitting an inverse ``manual_edit`` later. This module
|
||||
applies the new value to the appropriate target table; the snapshot of
|
||||
``prior_value`` is taken by the route handler before this fires.
|
||||
|
||||
Phase 1 covers three target kinds:
|
||||
- ``edge_affinity`` and ``edge_trust`` — slider edits on a specific edge,
|
||||
clamped to 0..100.
|
||||
- ``memory_significance`` — dropdown edit, clamped to 0..3.
|
||||
- ``memory_pov_summary`` — textarea edit (string).
|
||||
|
||||
Other §6.4 editable fields (activity verb / attention / posture, edge
|
||||
summary, knowledge_facts list manipulation) are deferred to Phase 1.5.
|
||||
|
||||
Pin toggles intentionally use the existing ``memory_pin_changed`` event
|
||||
(registered in :mod:`chat.state.memory`) rather than ``manual_edit`` so
|
||||
the projection writes both ``pinned`` and ``auto_pinned`` atomically.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlite3 import Connection
|
||||
|
||||
from chat.eventlog.log import Event
|
||||
from chat.eventlog.projector import on
|
||||
|
||||
|
||||
def _clamp(value: int, lo: int, hi: int) -> int:
|
||||
return max(lo, min(hi, value))
|
||||
|
||||
|
||||
@on("manual_edit")
|
||||
def _apply_manual_edit(conn: Connection, e: Event) -> None:
|
||||
p = e.payload
|
||||
kind = p["target_kind"]
|
||||
target_id = p["target_id"]
|
||||
new_value = p["new_value"]
|
||||
|
||||
if kind == "edge_affinity":
|
||||
conn.execute(
|
||||
"UPDATE edges SET affinity = ? "
|
||||
"WHERE source_id = ? AND target_id = ?",
|
||||
(
|
||||
_clamp(int(new_value), 0, 100),
|
||||
target_id["source_id"],
|
||||
target_id["target_id"],
|
||||
),
|
||||
)
|
||||
elif kind == "edge_trust":
|
||||
conn.execute(
|
||||
"UPDATE edges SET trust = ? "
|
||||
"WHERE source_id = ? AND target_id = ?",
|
||||
(
|
||||
_clamp(int(new_value), 0, 100),
|
||||
target_id["source_id"],
|
||||
target_id["target_id"],
|
||||
),
|
||||
)
|
||||
elif kind == "memory_significance":
|
||||
conn.execute(
|
||||
"UPDATE memories SET significance = ? WHERE id = ?",
|
||||
(_clamp(int(new_value), 0, 3), int(target_id)),
|
||||
)
|
||||
elif kind == "memory_pov_summary":
|
||||
conn.execute(
|
||||
"UPDATE memories SET pov_summary = ? WHERE id = ?",
|
||||
(str(new_value), int(target_id)),
|
||||
)
|
||||
# Unknown target_kind: silently no-op for v1. Future kinds (activity
|
||||
# fields, edge summary, knowledge_facts) extend the dispatch above.
|
||||
Reference in New Issue
Block a user