Skip to content

fix(tui): deliver kanban notify subscriptions to TUI/desktop sessions (salvage #66435) - #72177

Merged
teknium1 merged 3 commits into
mainfrom
hermes/hermes-95fbffb1
Jul 26, 2026
Merged

fix(tui): deliver kanban notify subscriptions to TUI/desktop sessions (salvage #66435)#72177
teknium1 merged 3 commits into
mainfrom
hermes/hermes-95fbffb1

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

TUI/Desktop sessions now receive Kanban task notifications. kanban_create auto-subscribes the calling session with platform="tui" / chat_id=HERMES_SESSION_KEY, but no consumer ever read those rows back: the gateway notifier skips them (no "tui" messaging adapter) and the TUI notification poller only watched process completions — every subscription sat at last_event_id=0 forever.

Salvage of #66435 (@cucurigoo's current-main cherry-pick of @falkoro's #60085) with authorship preserved, plus a follow-up regression test resolving the sweeper's profile-routing concern.

Fixes #59890 (TUI half; also covers duplicates #59960, #70791).

Changes

  • tui_gateway/server.py: _collect_kanban_notifications() claims unseen terminal events for this session's platform="tui" subscriptions via the same atomic claim_unseen_events_for_sub cursor-claim the gateway notifier uses (no double delivery when a gateway polls the same board DB); _format_kanban_event_text() mirrors gateway wording; _notification_poller_loop polls every 5s, emits status.update, buffers while busy, chains an agent turn when idle; unsubscribe only at done/archived — cherry-picked from fix(tui): deliver Kanban notifications to TUI sessions #66435, authored by @falkoro
  • tests/tui_gateway/test_kanban_notify_poller.py: 10 tests from the original PR (collector, formatting, poller wiring incl. busy→idle buffer) + 1 new test proving the collector reads the shared board correctly while a foreign-profile set_hermes_home_override() is active

On the sweeper's profile_home concern (#66435 review)

The flagged binding is intentionally unnecessary: the kanban board is shared across profiles by designkanban_home() anchors on get_default_hermes_root(), which resolves the process env and deliberately ignores context-local profile overrides (see the hermes_cli/kanban_db.py module docstring: "Profiles intentionally collapse onto a shared board: it IS the cross-profile coordination primitive"). Verified empirically: kanban_db_path() returns the same path with and without a profile override active. The new regression test pins this behavior.

Validation

Check Result
tests/tui_gateway/test_kanban_notify_poller.py 11/11 pass
tests/tui_gateway/ + gateway notifier + kanban notify/tools suites (49 files) 642/642 pass
E2E (real temp HERMES_HOME): _maybe_auto_subscribeblock_task → collector delivers ⏸ → complete_task → collector delivers ✔ + unsubscribes → second poll empty pass
ruff check on both files clean

falkoro and others added 3 commits July 26, 2026 12:35
kanban_create auto-subscribes TUI/desktop sessions with platform="tui" and
chat_id=HERMES_SESSION_KEY, and tools/kanban_tools.py documents that the
TUI notification poller (tui_gateway/server.py) reads kanban_notify_subs
and posts completion messages into the running session — but that reader
was never implemented. The poller only watched process_registry completion
events, and the gateway notifier skips "tui" rows because no such
messaging adapter exists. Result: subscriptions accumulate with
last_event_id=0 forever and no task event is ever delivered (18 subs,
29 terminal events, 0 deliveries in the report).

Implement the missing delivery path in the TUI notification poller:

- every 5s, claim unseen terminal events for this session's
  platform="tui" subscriptions via claim_unseen_events_for_sub — the
  same atomic cursor-claim the gateway notifier uses, so an event is
  delivered exactly once even with a gateway polling the same board DB
- format events with the same wording as the gateway notifier
  (done/blocked/gave up/crashed/timed out/status; archived and
  unblocked are claimed but silent, so they can't wedge the cursor)
- emit a status.update for user visibility, then chain an agent turn
  when the session is idle — mirroring process-completion handling;
  claimed events buffer in the session until it goes idle since the
  cursor (unlike the process queue) cannot re-queue
- unsubscribe only at a truly final task status (done/archived),
  matching the gateway rule so respawned tasks keep notifying
- multi-board: iterate boards, polling each resolved DB path once

Fixes #59890
Covers the poller wiring above _collect_kanban_notifications, per the
hermes-sweeper review: status.update emission, agent-turn dispatch via
_run_prompt_submit when the session is idle, and the busy-session
pending buffer that flushes once the session goes idle.
… override

The sweeper review on #66435 flagged that the collector doesn't bind
session["profile_home"]. That binding is intentionally unnecessary: the
kanban board is shared across profiles by design — kanban_home() anchors
on get_default_hermes_root(), which resolves the process env and ignores
context-local profile overrides (see the kanban_db.py module docstring).
Add a regression test that claims a subscription while a foreign-profile
set_hermes_home_override() is active, proving delivery still works for
non-launch-profile Desktop sessions.
@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 3ba02f9

ℹ️ Info

Desktop E2E visual evidence · View test artifacts · View job

1 visual diff.

inline evidence upload failed.

Failed to upload diff-665a0833239e-onboarding-overlay-diff.png with gh image (exit code 1): Error uploading /home/runner/work/_temp/e2e-evidence/diff-665a0833239e-onboarding-overlay-diff.png: step 0 (get upload token): uploadToken not found on repo page — do you have write access to NousResearch/hermes-agent? (or, if NousResearch enforces SAML SSO, authorize at https://github.com/orgs/NousResearch/sso)

@alt-glitch alt-glitch added type/bug Something isn't working comp/tui Terminal UI (ui-tui/ + tui_gateway/) comp/cron Cron scheduler and job management area/sessions Session lifecycle, resume, persistence, history P3 Low — cosmetic, nice to have sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 26, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Supersedes #66435 as the current-main salvage of that delivery implementation, with added foreign-profile routing regression coverage. Related to #69035, which uses a distinct transaction/session-lifecycle design.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/cron Cron scheduler and job management comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Kanban task event notifications never delivered — all 18 subscriptions have last_event_id=0

3 participants