Skip to content

Commit 4291acf

Browse files
committed
fixup: upsert notification_mode in add_notify_sub
INSERT OR IGNORE silently dropped notification_mode (and origin_*) on duplicate (task_id, platform, chat_id, thread_id) keys, so a tool-driven 'synthesize' subscribe arriving after a slash-command 'direct' subscribe left the original mode in place. Switch to ON CONFLICT DO UPDATE; preserve existing user_id / origin_* via COALESCE so a partial re-subscribe never clears context fields the first call established. Add regression test in tests/tools/test_kanban_tools.py.
1 parent 55bc6d5 commit 4291acf

2 files changed

Lines changed: 57 additions & 1 deletion

File tree

hermes_cli/kanban_db.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4227,11 +4227,17 @@ def add_notify_sub(
42274227
with write_txn(conn):
42284228
conn.execute(
42294229
"""
4230-
INSERT OR IGNORE INTO kanban_notify_subs
4230+
INSERT INTO kanban_notify_subs
42314231
(task_id, platform, chat_id, thread_id, user_id,
42324232
notification_mode, origin_session_id, origin_profile,
42334233
origin_context, created_at)
42344234
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
4235+
ON CONFLICT(task_id, platform, chat_id, thread_id) DO UPDATE SET
4236+
notification_mode = excluded.notification_mode,
4237+
user_id = COALESCE(excluded.user_id, user_id),
4238+
origin_session_id = COALESCE(excluded.origin_session_id, origin_session_id),
4239+
origin_profile = COALESCE(excluded.origin_profile, origin_profile),
4240+
origin_context = COALESCE(excluded.origin_context, origin_context)
42354241
""",
42364242
(
42374243
task_id, platform, chat_id, thread_id or "", user_id,

tests/tools/test_kanban_tools.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,56 @@ def test_orchestrator_complete_any_task_allowed(monkeypatch, tmp_path):
795795
assert d.get("ok") is True and d.get("task_id") == tid
796796

797797

798+
def test_add_notify_sub_upserts_notification_mode_on_duplicate(worker_env):
799+
"""Re-registering a subscription must update notification_mode and preserve
800+
origin context fields. Regression: prior `INSERT OR IGNORE` silently
801+
dropped a `synthesize`-mode tool-driven subscribe when a `direct`-mode
802+
slash-command subscribe already existed for the same (task,platform,
803+
chat,thread) tuple — leaving agent-created tasks with the wrong notifier."""
804+
from hermes_cli import kanban_db as kb
805+
806+
with kb.connect() as conn:
807+
# Slash-command path lands first with direct mode + origin context.
808+
kb.add_notify_sub(
809+
conn,
810+
task_id=worker_env,
811+
platform="discord",
812+
chat_id="chat-1",
813+
thread_id="thread-1",
814+
user_id="user-1",
815+
notification_mode="direct",
816+
origin_session_id="sess-1",
817+
origin_profile="default",
818+
origin_context="original message",
819+
)
820+
# Tool-driven create then upgrades the same subscription to synthesize
821+
# without re-supplying the origin context (which it doesn't carry).
822+
kb.add_notify_sub(
823+
conn,
824+
task_id=worker_env,
825+
platform="discord",
826+
chat_id="chat-1",
827+
thread_id="thread-1",
828+
user_id=None,
829+
notification_mode="synthesize",
830+
origin_session_id=None,
831+
origin_profile=None,
832+
origin_context=None,
833+
)
834+
subs = kb.list_notify_subs(conn, task_id=worker_env)
835+
836+
assert len(subs) == 1, "upsert must not create a duplicate row"
837+
row = subs[0]
838+
assert row["notification_mode"] == "synthesize", (
839+
"notification_mode must reflect the latest subscribe call"
840+
)
841+
# Origin context fields populated by the first call must survive.
842+
assert row["user_id"] == "user-1"
843+
assert row["origin_session_id"] == "sess-1"
844+
assert row["origin_profile"] == "default"
845+
assert row["origin_context"] == "original message"
846+
847+
798848
def test_create_worker_root_task_inherits_current_origin_subscription(worker_env):
799849
"""Parentless worker-created follow-up tasks keep the interactive origin."""
800850
from hermes_cli import kanban_db as kb

0 commit comments

Comments
 (0)