fix(whatsapp): multi-user session isolation and bridge message handling - #75
Merged
teknium1 merged 2 commits intoFeb 27, 2026
Merged
Conversation
satelerd
force-pushed
the
fix/whatsapp-multi-user-sessions
branch
from
February 26, 2026 17:54
82299cd to
f02f647
Compare
Contributor
|
LGTM |
angelburgosrosado
pushed a commit
to angelburgosrosado/hermes-agent
that referenced
this pull request
Apr 27, 2026
…ser-sessions fix(whatsapp): multi-user session isolation and bridge message handling
4 tasks
jarvis-stark-ops
pushed a commit
to 1Team-Engineering/hermes-agent
that referenced
this pull request
Jun 11, 2026
… document edit-result caveat Independent review of v6.8 Part 2 flagged 3 polish items. All addressed. ## Regex tightening (NousResearch#75 follow-up) The bullet-not-applicable regex `\S.{6,}` was accepting reasons of 7 chars (1 + 6) but the docstring and tests asserted ≥8 chars to match the `imports_match_deliverable_entrypoints` invariant. Tightened to `\S.{7,}` so 1 + 7 = 8 chars minimum. Same as the imports_match length check, no off-by-one. ## Integration test gaps (NousResearch#74 follow-up) Reviewer flagged two missing integration cases: - Bare `verdict: reject` with no test_quality fields: floor bypasses (because verdict IS reject) but reviewer-fields gate catches the missing discipline. New test asserts the gate that catches it is MissingReviewerFieldViolation, NOT RuntimeFloorViolation. This proves the bypass doesn't accidentally green-light no-evidence rejects. - No verdict at all: parsed_verdict is None, is_honest_reject is False, floor fires normally. New test asserts a result like "Just my thoughts, no verdict line." doesn't silently bypass the floor. ## edit_completed_task_result documentation The reviewer noted this function exists at kanban_db.py:4180 to back- fill results on done tasks (via `hermes kanban edit`). It bypasses EVERY v6.7/v6.8 gate. If a future maintainer wires it into a worker tool surface, every gate becomes bypassable: complete with low- discipline, edit to high-discipline, or flip approve↔reject after the gate already ran. Added a multi-line .warning:: docstring listing every gate it bypasses and the specific attacks a worker-accessible wiring would enable. No code change — this is a comment-level guard for human ops. 107/107 in test_kanban_completion_gates.py pass (105 + 2 new). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jarvis-stark-ops
added a commit
to 1Team-Engineering/hermes-agent
that referenced
this pull request
Jun 11, 2026
…_applicable evidence (NousResearch#74, NousResearch#75) Two precision fixes for the v6.7 completion gates surfaced by the 2026-06-10 validation chain on hermes-dashboard. Both touch kanban_completion_gates.py and ship together. Closes hermes-jarvis#74 (honest-reject floor bypass) Closes hermes-jarvis#75 (bullet not_applicable for evidence) NousResearch#74: verify_runtime_floor gains is_honest_reject kwarg. When True AND worker is in REVIEW_ROLES, floor bypassed. Build/orchestration roles unaffected — a friday 60-second 'implementation' that ends in reject still warrants the 5-min floor. Verdict parsed once at top of _v6_7_run_completion_gates via existing _v6_7_parse_verdict. NousResearch#75: _field_present for test_quality.evidence accepts '- not_applicable: <reason>' bullet with reason ≥8 chars (regex tightened from \\S.{6,} to \\S.{7,} per self-review). Same code_change_context rule — code-touching reviews require real citations. Polish from self-reviews: - Tightened bullet regex to enforce ≥8 chars - Added 2 integration tests (bare reject hits reviewer-fields, null verdict still subject to floor) - Documented edit_completed_task_result as bypassing every gate - Removed stale dangling reference in kanban_tools.py (_enforce_kanban_complete_hygiene call) that would NameError 107 tests in test_kanban_completion_gates.py. 191/191 across full v6.7+v6.8 + adjacent regression set, zero failures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
waefrebeorn
pushed a commit
to waefrebeorn/slermes
that referenced
this pull request
Jul 2, 2026
…ser-sessions fix(whatsapp): multi-user session isolation and bridge message handling
ohungerCH
added a commit
to ohungerCH/hermes-agent
that referenced
this pull request
Jul 11, 2026
VaultStore.recall() + vault_shadow_recall() + memory(action='recall'), flag-gated (recall_enabled, default aus), dark. tsvector-first -- exakt-KNN ist inert bis DLP+Embedding+Zone 52 (jede confirmed Zeile hat embedding=NULL). - Vollständiger WHERE-Kontrakt (verlustfreie Inverse des Write-Provenienz- Pfads): lifecycle_status='confirmed' AND deleted_at/quarantined_at/ superseded_at IS NULL AND tsvector-Match; tenant/owner via RLS-GUCs, NICHT im Query-Text. - Untrusted-Wrap am Modell-Rand (entity-encode &,<,>): recalled Text ist DATEN, keine Anweisung -- Security-Vokabular bleibt abrufbar (NousResearch#75 warn-vs- block), Wrap-Escape unmöglich (Task NousResearch#34). Kein sanitization_state-Filter. - Fail-soft + Ehrlichkeits-Klausel: leer != Abwesenheit; Fehler/tote DB -> available=False, NIE als "kein Gedächtnis". - Read-only unter vault_transaction (RLS), fetchall innerhalb der Txn. Beweis: 197 Unit-Tests grün (WHERE-Korrektheit, RLS-GUC-Reihenfolge, Wrap- Escape, fail-soft, Ehrlichkeit). recall_enabled bleibt aus (kein Deploy). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ohungerCH
added a commit
to ohungerCH/hermes-agent
that referenced
this pull request
Jul 11, 2026
Macht die Recall-Bedingung self-contained: der ungefilterte FTS-Index heisst, die Query trägt die ganze Korrektheit -- sie darf sich nicht still auf die Schreibseiten-Invariante confirmed⟹sanitisiert verlassen (wie deleted/ quarantined/superseded auch explizit stehen). Heute redundant (scanner-tot -> stage -> candidate), aber fail-closed gegen einen künftigen Confirm-Promotion- Flow, der Scanner-Liveness umginge. KEINE Kastration: Security-Vokabular ist warn-only (NousResearch#75) -> scanner-gesund -> 'applied'. Test-Assertion + self-test- Zeile (confirmed+pending -> ausgeschlossen) beweisen das Prädikat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Meraniya
pushed a commit
to Meraniya/hermes-agent
that referenced
this pull request
Aug 6, 2026
…nd dispatch (NousResearch#75) service_manager.py (added in NousResearch#73, 1123 lines) shipped with zero test coverage despite being on the gateway lifecycle critical path. Adds unit tests for detect/get_service_manager backend selection, the S6ServiceManager start/stop/restart/is_running/register paths, systemd+launchd restart, the _dispatch_via_service_manager_if_s6 CLI wiring, and write_platform_config_field. All system calls (s6-svc/systemctl/launchctl) are mocked — no real services touched. Claude-Session: https://claude.ai/code/session_01PQKCc5mDedYAiCNyXnTezh Co-authored-by: Claude <noreply@anthropic.com>
Meraniya
pushed a commit
to Meraniya/hermes-agent
that referenced
this pull request
Aug 6, 2026
…ousResearch#77) service_manager.py's S6ServiceManager._render_finish_script() imports GATEWAY_FATAL_CONFIG_EXIT_CODE from gateway.restart, but the constant was never defined there — only GATEWAY_SERVICE_RESTART_EXIT_CODE existed. This raises ImportError on the real register_profile_gateway path, breaking s6 profile-gateway registration in production. Surfaced by test coverage added in NousResearch#75 but left unfixed there. Value chosen: 78 (EX_CONFIG in sysexits.h), distinct from GATEWAY_SERVICE_RESTART_EXIT_CODE=75 so the s6 finish script can tell a fatal config error (do not respawn) apart from a normal restart request. Co-authored-by: Claude <noreply@anthropic.com>
sijav
added a commit
to sijav/sijav-agent
that referenced
this pull request
Aug 7, 2026
… 5/Fable 5 no longer price as 'unknown' (NousResearch#75) [roast 9.7/9.6/9.6] _OFFICIAL_DOCS_PRICING was missing the current Claude 5 models, so Opus 5 (the default) and Fable 5 sessions resolved to unknown cost. Adds first-party claude-opus-5 ($5/$25), claude-opus-5-fast ($10/$50), claude-fable-5 ($10/$50), claude-mythos-5 ($10/$50), dated claude-haiku-4-5-20251001 ($1/$5), and Bedrock anthropic.claude-opus-5 / anthropic.claude-fable-5. Cache rates follow the file convention (read 0.1x, write 1.25x input). Prices cross-checked against the claude-api skill; all 7 models verified real (incl. Mythos 5 = Project Glasswing). Pure additions (0 deletions). 4 new resolver tests; fail-before/pass-after proven.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I opened #31 about WhatsApp not working, and after the bridge was added and the gateway auth was fixed I started testing and found three issues. So I patched them locally and it's been working well. Sharing in case it's useful to merge upstream. Awesome project btw.
Summary
scripts/whatsapp-bridge/bridge.js: When
WHATSAPP_ALLOWED_USERSis empty,fromMemessages in DMs were never filtered. Every agent reply got picked up as a new incoming message, causing interrupts and feedback loops. Fix: skip allfromMeexcept self-chat, detected by comparingremoteJidtosock.user.id.gateway/session.py:
_generate_session_key()returnedagent:main:whatsapp:dmfor every DM regardless of who's writing. Two people messaging at the same time shared conversation history and interrupted each other. Fix: WhatsApp DM keys now include thechat_id(agent:main:whatsapp:dm:{chat_id}). Other platforms unchanged.gateway/session.py + gateway/run.py: Added user name/ID to the session context prompt so the agent knows who it's talking to. Updated approval session key to match the new format.
Also noticed that
provider: autoinconfig.yamlisn't handled by the gateway credential resolution inrun.py— it only checksprovider == "nous", soautofalls through to OpenRouter. Didn't include that here since it's a different flow.Test plan