Skip to content

feat(kanban): route notifications via owning profile + wake creator agent - #54872

Closed
zmlgit wants to merge 2 commits into
NousResearch:mainfrom
zmlgit:feat/kanban-profile-routing-and-wakeup
Closed

feat(kanban): route notifications via owning profile + wake creator agent#54872
zmlgit wants to merge 2 commits into
NousResearch:mainfrom
zmlgit:feat/kanban-profile-routing-and-wakeup

Conversation

@zmlgit

@zmlgit zmlgit commented Jun 29, 2026

Copy link
Copy Markdown

Problem

In a multiplex_profiles gateway, kanban task notifications were always delivered via the default profile's adapter — even when the task was created by a different profile (e.g. CEO). This caused two failures:

  1. Bot not in chat: The default bot may not be in the group where the task was created, so adapter.send() fails with [230002] Bot/User can NOT be out of the chat.
  2. No agent follow-up: The creating agent has no way to know the task finished — the notification is fire-and-forget text, not a conversation turn trigger.

Root Cause

  1. _maybe_auto_subscribe read os.environ.get("HERMES_PROFILE") to stamp notifier_profile — but in the gateway main process this env var is unset (multiplex profiles use ContextVars, not env vars).
  2. Notifier profile filter skipped any subscription whose notifier_profile differs from the gateway's active profile.
  3. Notifier adapter selection always used self.adapters[plat] (default profile only).

Changes

1. Session profile propagation (session_context.py, run.py, kanban_tools.py)

  • Add HERMES_SESSION_PROFILE ContextVar
  • Gateway stamps source.profile at dispatch time
  • _maybe_auto_subscribe reads from ContextVar first, falls back to os.environ

2. Notifier profile-aware routing (kanban_watchers.py)

  • Profile filter: skip only when the gateway has no adapter for the owning profile
  • Adapter selection: prefer _profile_adapters[sub.notifier_profile]
  • TERMINAL_KINDS: extend with status, archived, unblocked

3. Creator agent wakeup on terminal events (kanban_watchers.py)

After delivering completed/blocked/gave_up/crashed/timed_out notifications, inject a synthetic MessageEvent into the creator's session via adapter.handle_message() to trigger their agent loop.

Verification

End-to-end tested in a 10-profile multiplex gateway:

User @Jensen in feishu group -> Jensen creates kanban task
-> Task completed by worker
-> Notifier delivers via CEO adapter (not default)
-> Synthetic message injected into CEO session
-> Jensen agent loop fires, calls kanban_show, replies in group

Backward Compatibility

  • os.environ fallback preserved for kanban workers
  • Single-profile gateways unaffected (falls through to self.adapters)
  • archived/unblocked notify but do not wake (no creator action needed)

…gent

Three connected changes that fix kanban notifications in multiplex_profile
gateways and enable event-driven agent collaboration:

1. Session profile propagation
   - Add HERMES_SESSION_PROFILE ContextVar (session_context.py)
   - Gateway stamps source.profile at dispatch time (run.py)
   - _maybe_auto_subscribe reads profile from ContextVar instead of
     os.environ which is unset in the gateway main process (kanban_tools.py)

2. Notifier profile-aware routing (kanban_watchers.py)
   - Adapter selection: prefer _profile_adapters[sub.notifier_profile]
     so each profile's bot delivers its own task notifications
   - Relax profile skip-filter: process cross-profile subscriptions when
     the gateway has an adapter for the owning profile
   - Extend TERMINAL_KINDS with status/archived/unblocked

3. Creator agent wakeup on terminal events (kanban_watchers.py)
   - After delivering completed/blocked/gave_up/crashed/timed_out
     notifications, inject a synthetic MessageEvent into the creator's
     session via adapter.handle_message to trigger their agent loop
   - SessionSource built from subscription metadata — no session_store
     lookup needed
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cron Cron scheduler and job management comp/gateway Gateway runner, session dispatch, delivery sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jun 29, 2026

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment: The profile-based notification routing and wake-creator-agent feature is well-designed, but the hardcoded Chinese text in the wake messages (lines 118-128 of the diff) should be replaced with English or internationalized. The rest of the codebase uses English for user-facing messages, and hardcoded Chinese will confuse non-Chinese users. Consider using a constants dict or the existing i18n infrastructure.

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: LGTM — clean kanban profile routing.

Well-structured implementation for profile-based notification routing and agent wake on task completion.


Reviewed by Hermes Agent

…arch#54872

Addresses @tonydwb's review on PR NousResearch#54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
@zmlgit

zmlgit commented Jun 29, 2026

Copy link
Copy Markdown
Author

@tonydwb Thanks for the review — good catch on the hardcoded Chinese.

Pushed 0d60a1ae to address it. Used the existing i18n infrastructure you suggested (agent/i18n.py::t(), the same surface gateway/run.py and slash_commands.py already use) rather than a one-off constants dict:

  • New gateway.kanban.wake.* keys in locales/en.yaml (baseline) + locales/zh.yaml (preserves the original Chinese phrasing, so existing zh users see no visible change).
  • The other 14 catalogs got the same key set with English fallback values — required by the i18n invariant test (tests/agent/test_i18n.py::test_catalog_keys_match_english) and lets native translations land incrementally.
  • gateway/kanban_watchers.py imports t and replaces the hardcoded strings; behavior unchanged for zh users.

Full test suite passes: i18n parity (47) + kanban notifier (13) = 60 tests, 0 failures.

zmlgit pushed a commit to zmlgit/hermes-agent that referenced this pull request Jun 30, 2026
…arch#54872

Addresses @tonydwb's review on PR NousResearch#54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
kshitijk4poor added a commit that referenced this pull request Jul 1, 2026
chore: add AUTHOR_MAP entry for zmlgit (PR #54872 salvage)
kshitijk4poor pushed a commit to kshitijk4poor/hermes-agent that referenced this pull request Jul 1, 2026
…arch#54872

Addresses @tonydwb's review on PR NousResearch#54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
kshitijk4poor added a commit to kshitijk4poor/hermes-agent that referenced this pull request Jul 1, 2026
…w findings

Follow-up review fixes on the salvage of NousResearch#54872 (原作者 张满良/@zmlgit):

1. [HIGH] Adapter selection now goes through the shared
   _authorization_adapter chokepoint (gateway/authz_mixin.py) instead of a
   local inline lookup that fell back to the DEFAULT profile's same-platform
   adapter when the owning profile had a registry entry but no adapter for
   that platform. That fallback re-introduced the exact cross-profile
   mis-delivery ([230002] Bot can NOT be out of the chat) this change exists
   to fix. Adds a mutation-verified guard test
   (test_notifier_owning_profile_adapter_no_default_fallback).

2. [HIGH→documented] The creator-wake SessionSource cannot faithfully
   reconstruct a DM/thread creator's session key because chat_type is neither
   persisted on the subscription nor carried on the session-context bridge.
   Documented the limitation inline; behavior degrades to a fresh group
   session (never an exception). The end-to-end fix (stamp + persist
   chat_type) is a scoped follow-up, not bundled into this salvage.

3. [MED] Documented that archived/unblocked are intentionally claimed (cursor
   hygiene) but silent, and excluded from wake kinds.

4. [MED] Wake-injection failure now logs at WARNING with exc_info=True (the
   cursor has already advanced, so a broken wake must not be a silent no-op).
kshitijk4poor pushed a commit that referenced this pull request Jul 1, 2026
Addresses @tonydwb's review on PR #54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
kshitijk4poor added a commit that referenced this pull request Jul 1, 2026
…w findings

Follow-up review fixes on the salvage of #54872 (原作者 张满良/@zmlgit):

1. [HIGH] Adapter selection now goes through the shared
   _authorization_adapter chokepoint (gateway/authz_mixin.py) instead of a
   local inline lookup that fell back to the DEFAULT profile's same-platform
   adapter when the owning profile had a registry entry but no adapter for
   that platform. That fallback re-introduced the exact cross-profile
   mis-delivery ([230002] Bot can NOT be out of the chat) this change exists
   to fix. Adds a mutation-verified guard test
   (test_notifier_owning_profile_adapter_no_default_fallback).

2. [HIGH→documented] The creator-wake SessionSource cannot faithfully
   reconstruct a DM/thread creator's session key because chat_type is neither
   persisted on the subscription nor carried on the session-context bridge.
   Documented the limitation inline; behavior degrades to a fresh group
   session (never an exception). The end-to-end fix (stamp + persist
   chat_type) is a scoped follow-up, not bundled into this salvage.

3. [MED] Documented that archived/unblocked are intentionally claimed (cursor
   hygiene) but silent, and excluded from wake kinds.

4. [MED] Wake-injection failure now logs at WARNING with exc_info=True (the
   cursor has already advanced, so a broken wake must not be a silent no-op).
@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Thanks for this, @zmlgit (张满良) — landed on main via #56531. 🎉

Your two commits were rebase-merged with authorship preserved, so this ships as your work:

  • feat(kanban): route notifications via owning profile + wake creator agent
  • fix(kanban): i18n wake messages (addressing @tonydwb's review)

I added one follow-up review commit on top (correctness hardening surfaced during review):

  • Adapter selection now routes through the shared _authorization_adapter chokepoint (gateway/authz_mixin.py) instead of the inline lookup, so a secondary profile's notification can't fall back to the default profile's bot when the owning profile has a registry entry but no adapter for that platform — closing the exact cross-profile mis-delivery ([230002] Bot can NOT be out of the chat) this change targets. Added a mutation-verified regression test.
  • Wake-injection failures now log at WARNING with exc_info (the notifier cursor has already advanced, so a broken wake mustn't be a silent no-op), plus a clarifying comment on the intentionally-silent archived/unblocked kinds.

One known limitation tracked as a follow-up (not a regression): the creator-wake SessionSource hardcodes chat_type="group", because the subscription row doesn't persist the creator's chat_type and it isn't carried on the session-context bridge — so DM/thread-originated creators can be woken in a fresh session rather than their original one. Fixing that properly needs stamping + persisting chat_type end-to-end (a small schema + bridge change), which I've kept out of this PR to preserve its scope.

Closing this in favor of #56531. Thanks again for the fix and for iterating on the i18n feedback!

hashbender added a commit to hashbender/hermes-agent that referenced this pull request Jul 1, 2026
#446)

Co-authored-by: qbit-mirror-bot <qbit-mirror-bot@users.noreply.github.com>
hashbender added a commit to hashbender/hermes-agent that referenced this pull request Jul 1, 2026
…ent (salvage NousResearch#54872) (#447)

Co-authored-by: qbit-mirror-bot <qbit-mirror-bot@users.noreply.github.com>
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…map-54872

chore: add AUTHOR_MAP entry for zmlgit (PR NousResearch#54872 salvage)
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…arch#54872

Addresses @tonydwb's review on PR NousResearch#54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…w findings

Follow-up review fixes on the salvage of NousResearch#54872 (原作者 张满良/@zmlgit):

1. [HIGH] Adapter selection now goes through the shared
   _authorization_adapter chokepoint (gateway/authz_mixin.py) instead of a
   local inline lookup that fell back to the DEFAULT profile's same-platform
   adapter when the owning profile had a registry entry but no adapter for
   that platform. That fallback re-introduced the exact cross-profile
   mis-delivery ([230002] Bot can NOT be out of the chat) this change exists
   to fix. Adds a mutation-verified guard test
   (test_notifier_owning_profile_adapter_no_default_fallback).

2. [HIGH→documented] The creator-wake SessionSource cannot faithfully
   reconstruct a DM/thread creator's session key because chat_type is neither
   persisted on the subscription nor carried on the session-context bridge.
   Documented the limitation inline; behavior degrades to a fresh group
   session (never an exception). The end-to-end fix (stamp + persist
   chat_type) is a scoped follow-up, not bundled into this salvage.

3. [MED] Documented that archived/unblocked are intentionally claimed (cursor
   hygiene) but silent, and excluded from wake kinds.

4. [MED] Wake-injection failure now logs at WARNING with exc_info=True (the
   cursor has already advanced, so a broken wake must not be a silent no-op).
Jasper6439 pushed a commit to Jasper6439/hermes-agent that referenced this pull request Jul 5, 2026
Jasper6439 pushed a commit to Jasper6439/hermes-agent that referenced this pull request Jul 5, 2026
…arch#54872

Addresses @tonydwb's review on PR NousResearch#54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
Jasper6439 pushed a commit to Jasper6439/hermes-agent that referenced this pull request Jul 5, 2026
…w findings

Follow-up review fixes on the salvage of NousResearch#54872 (原作者 张满良/@zmlgit):

1. [HIGH] Adapter selection now goes through the shared
   _authorization_adapter chokepoint (gateway/authz_mixin.py) instead of a
   local inline lookup that fell back to the DEFAULT profile's same-platform
   adapter when the owning profile had a registry entry but no adapter for
   that platform. That fallback re-introduced the exact cross-profile
   mis-delivery ([230002] Bot can NOT be out of the chat) this change exists
   to fix. Adds a mutation-verified guard test
   (test_notifier_owning_profile_adapter_no_default_fallback).

2. [HIGH→documented] The creator-wake SessionSource cannot faithfully
   reconstruct a DM/thread creator's session key because chat_type is neither
   persisted on the subscription nor carried on the session-context bridge.
   Documented the limitation inline; behavior degrades to a fresh group
   session (never an exception). The end-to-end fix (stamp + persist
   chat_type) is a scoped follow-up, not bundled into this salvage.

3. [MED] Documented that archived/unblocked are intentionally claimed (cursor
   hygiene) but silent, and excluded from wake kinds.

4. [MED] Wake-injection failure now logs at WARNING with exc_info=True (the
   cursor has already advanced, so a broken wake must not be a silent no-op).
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…map-54872

chore: add AUTHOR_MAP entry for zmlgit (PR NousResearch#54872 salvage)
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…arch#54872

Addresses @tonydwb's review on PR NousResearch#54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…w findings

Follow-up review fixes on the salvage of NousResearch#54872 (原作者 张满良/@zmlgit):

1. [HIGH] Adapter selection now goes through the shared
   _authorization_adapter chokepoint (gateway/authz_mixin.py) instead of a
   local inline lookup that fell back to the DEFAULT profile's same-platform
   adapter when the owning profile had a registry entry but no adapter for
   that platform. That fallback re-introduced the exact cross-profile
   mis-delivery ([230002] Bot can NOT be out of the chat) this change exists
   to fix. Adds a mutation-verified guard test
   (test_notifier_owning_profile_adapter_no_default_fallback).

2. [HIGH→documented] The creator-wake SessionSource cannot faithfully
   reconstruct a DM/thread creator's session key because chat_type is neither
   persisted on the subscription nor carried on the session-context bridge.
   Documented the limitation inline; behavior degrades to a fresh group
   session (never an exception). The end-to-end fix (stamp + persist
   chat_type) is a scoped follow-up, not bundled into this salvage.

3. [MED] Documented that archived/unblocked are intentionally claimed (cursor
   hygiene) but silent, and excluded from wake kinds.

4. [MED] Wake-injection failure now logs at WARNING with exc_info=True (the
   cursor has already advanced, so a broken wake must not be a silent no-op).
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…map-54872

chore: add AUTHOR_MAP entry for zmlgit (PR NousResearch#54872 salvage)
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…arch#54872

Addresses @tonydwb's review on PR NousResearch#54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…w findings

Follow-up review fixes on the salvage of NousResearch#54872 (原作者 张满良/@zmlgit):

1. [HIGH] Adapter selection now goes through the shared
   _authorization_adapter chokepoint (gateway/authz_mixin.py) instead of a
   local inline lookup that fell back to the DEFAULT profile's same-platform
   adapter when the owning profile had a registry entry but no adapter for
   that platform. That fallback re-introduced the exact cross-profile
   mis-delivery ([230002] Bot can NOT be out of the chat) this change exists
   to fix. Adds a mutation-verified guard test
   (test_notifier_owning_profile_adapter_no_default_fallback).

2. [HIGH→documented] The creator-wake SessionSource cannot faithfully
   reconstruct a DM/thread creator's session key because chat_type is neither
   persisted on the subscription nor carried on the session-context bridge.
   Documented the limitation inline; behavior degrades to a fresh group
   session (never an exception). The end-to-end fix (stamp + persist
   chat_type) is a scoped follow-up, not bundled into this salvage.

3. [MED] Documented that archived/unblocked are intentionally claimed (cursor
   hygiene) but silent, and excluded from wake kinds.

4. [MED] Wake-injection failure now logs at WARNING with exc_info=True (the
   cursor has already advanced, so a broken wake must not be a silent no-op).
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…map-54872

chore: add AUTHOR_MAP entry for zmlgit (PR NousResearch#54872 salvage)
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…arch#54872

Addresses @tonydwb's review on PR NousResearch#54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…w findings

Follow-up review fixes on the salvage of NousResearch#54872 (原作者 张满良/@zmlgit):

1. [HIGH] Adapter selection now goes through the shared
   _authorization_adapter chokepoint (gateway/authz_mixin.py) instead of a
   local inline lookup that fell back to the DEFAULT profile's same-platform
   adapter when the owning profile had a registry entry but no adapter for
   that platform. That fallback re-introduced the exact cross-profile
   mis-delivery ([230002] Bot can NOT be out of the chat) this change exists
   to fix. Adds a mutation-verified guard test
   (test_notifier_owning_profile_adapter_no_default_fallback).

2. [HIGH→documented] The creator-wake SessionSource cannot faithfully
   reconstruct a DM/thread creator's session key because chat_type is neither
   persisted on the subscription nor carried on the session-context bridge.
   Documented the limitation inline; behavior degrades to a fresh group
   session (never an exception). The end-to-end fix (stamp + persist
   chat_type) is a scoped follow-up, not bundled into this salvage.

3. [MED] Documented that archived/unblocked are intentionally claimed (cursor
   hygiene) but silent, and excluded from wake kinds.

4. [MED] Wake-injection failure now logs at WARNING with exc_info=True (the
   cursor has already advanced, so a broken wake must not be a silent no-op).
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…map-54872

chore: add AUTHOR_MAP entry for zmlgit (PR NousResearch#54872 salvage)
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…arch#54872

Addresses @tonydwb's review on PR NousResearch#54872 (12:05 UTC, 2026-06-29):

  > the hardcoded Chinese text in the wake messages (lines 118-128 of
  > the diff) should be replaced with English or internationalized.
  > The rest of the codebase uses English for user-facing messages,
  > and hardcoded Chinese will confuse non-Chinese users. Consider
  > using a constants dict or the existing i18n infrastructure.

Used the existing i18n infrastructure (agent/i18n.py::t()) — the same
surface gateway/run.py and slash_commands.py already use for static
user-facing strings.

## Changes

- gateway/kanban_watchers.py: import `t` from agent.i18n; replace the
  hardcoded Chinese strings in the synthetic wake-up message with
  t("gateway.kanban.wake.*") lookups. Behavior unchanged for zh users
  (zh catalog preserves the original Chinese phrasing).

- locales/en.yaml: new `gateway.kanban.wake.*` baseline keys (English):
  completed / gave_up / crashed / timed_out / blocked / status_default
  / status_joiner / message (with {task_id} {status} {title}
  {assignee} {board} placeholders).

- locales/zh.yaml: Chinese translation of the new keys, preserving the
  exact wording the original code used (so existing zh users see no
  visible change).

- locales/{zh-hant,ja,de,es,fr,tr,uk,af,ko,it,ga,pt,ru,hu}.yaml: added
  the same key set with English fallback values. The i18n invariant
  test (tests/agent/test_i18n.py::test_catalog_keys_match_english)
  requires every catalog to carry the same key set as en.yaml; native
  translations can land incrementally without breaking users (the
  loader falls back to en.yaml per-key when a translation is missing,
  but the key must still exist).

## Verification

- scripts/run_tests.sh tests/agent/test_i18n.py
  tests/gateway/test_kanban_watchers_mixin.py
  tests/gateway/test_kanban_notifier.py
  tests/gateway/test_kanban_notifier_watcher_dispatch_gate.py
  → 60 passed, 0 failed (i18n catalog parity + placeholders parity +
  existing kanban notifier behavior).

- Manual: with HERMES_LANGUAGE=en, t("gateway.kanban.wake.completed")
  returns "completed"; with HERMES_LANGUAGE=zh, returns "已完成";
  with HERMES_LANGUAGE=ja (translation pending), falls back to
  "completed" per-key.
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…w findings

Follow-up review fixes on the salvage of NousResearch#54872 (原作者 张满良/@zmlgit):

1. [HIGH] Adapter selection now goes through the shared
   _authorization_adapter chokepoint (gateway/authz_mixin.py) instead of a
   local inline lookup that fell back to the DEFAULT profile's same-platform
   adapter when the owning profile had a registry entry but no adapter for
   that platform. That fallback re-introduced the exact cross-profile
   mis-delivery ([230002] Bot can NOT be out of the chat) this change exists
   to fix. Adds a mutation-verified guard test
   (test_notifier_owning_profile_adapter_no_default_fallback).

2. [HIGH→documented] The creator-wake SessionSource cannot faithfully
   reconstruct a DM/thread creator's session key because chat_type is neither
   persisted on the subscription nor carried on the session-context bridge.
   Documented the limitation inline; behavior degrades to a fresh group
   session (never an exception). The end-to-end fix (stamp + persist
   chat_type) is a scoped follow-up, not bundled into this salvage.

3. [MED] Documented that archived/unblocked are intentionally claimed (cursor
   hygiene) but silent, and excluded from wake kinds.

4. [MED] Wake-injection failure now logs at WARNING with exc_info=True (the
   cursor has already advanced, so a broken wake must not be a silent no-op).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cron Cron scheduler and job management comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants