Skip to content

feat(jb_outbound): plugin « rien ne part sans accord » (Jean-Billie) - #1

Merged
gabiar-maker merged 2 commits into
mainfrom
feat/jb-outbound-plugin
Jun 8, 2026
Merged

feat(jb_outbound): plugin « rien ne part sans accord » (Jean-Billie)#1
gabiar-maker merged 2 commits into
mainfrom
feat/jb-outbound-plugin

Conversation

@gabiar-maker

Copy link
Copy Markdown
Owner

jb_outbound — « rien ne part sans accord »

Greffe Jean-Billie sur Hermes Agent. Un seul plugin, zéro patch du cœur → suivi de l'upstream MIT trivial.

Ce que ça fait

Tout envoi sortant de l'assistant — Telegram (send_message) ou email/réseaux via Composio (mcp_composio_*) — est intercepté et transformé en proposition à valider. L'envoi réel n'a lieu qu'après accord du client. Les deux familles passent par le même tool_execution middleware → un seul point de greffe couvre tous les canaux et déclencheurs.

Boucle

  1. Interception (middleware.py) : court-circuite l'outil d'envoi. PASS (lecture/interne) · PROPOSE (envoi → proposition) · BLOCK (envoi composio non répertorié = fail-closed).
  2. ALLER : enregistre l'envoi (args complets) dans ~/.hermes/jb_pending/{jb_id}.json (local, jamais relayé), POST DraftRequest127.0.0.1:8442/v1/draft, rend un résultat synthétique au modèle. Pas de blocage du run (asynchrone).
  3. RETOUR (listener.py + replay.py) : le daemon pousse la DecisionItem approuvée sur 127.0.0.1:8444/jb/decision → replay via registry.dispatch (ne repasse pas par le middleware) → POST ResultRequest. Idempotent, survit au redémarrage (store persistant).

Garde-fous

  • Minimisation RGPD : les args complets restent locaux ; le DraftRequest ne porte que kind / titre / aperçu / destinataire d'affichage.
  • Loopback strict : le listener bind 127.0.0.1 uniquement (symétrique du daemon).
  • Passif hors box : sans JB_DECISION_PUSH_URL, le plugin ne fait rien (usage Hermes standard intact).
  • Opt-in via plugins.enabled: [jb_outbound].

Tests

plugins/jb_outbound/test_jb_outbound.py7 verts, autonomes (HTTP loopback + registre d'outils mockés, pas besoin d'un env Hermes complet). Couvre classification, mapping, interception (pass/propose/block), replay (exécution + idempotence).

Suite

Reste (côté monorepo Jean-Billie) : e2e avec stub daemon (A4) ; build → GHCR → digest → golden image (A3). Réseau host-mode + endpoints loopback déjà câblés (PR NousResearch#32).

🤖 Generated with Claude Code

gabiar-maker and others added 2 commits June 8, 2026 13:53
Greffe a diff minimal (un seul plugin, zero patch du coeur) qui impose la validation humaine sur tout envoi sortant de Hermes.

- tool_execution middleware : intercepte send_message (Telegram) ET mcp_composio_* (email/reseaux). PASS (lecture/interne) / PROPOSE (envoi -> proposition) / BLOCK (envoi composio non repertorie = fail-closed).

- Asynchrone : enregistre l'envoi (args complets) dans ~/.hermes/jb_pending/, POST DraftRequest au daemon loopback, rend un resultat synthetique. Pas de blocage du run.

- Listener loopback (bind 127.0.0.1 strict) : recoit la DecisionItem approuvee -> replay via registry.dispatch (ne repasse pas par le middleware) -> POST ResultRequest. Idempotent, survit au redemarrage.

- Minimisation : args complets restent locaux ; DraftRequest ne porte que kind/titre/apercu/destinataire. Passif hors box.

Tests : 7 verts, autonomes (HTTP + registre mockes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…decision)

Vrai listener du plugin + stub de control daemon (HTTP loopback). Prouve : envoi intercepte -> proposition deposee -> AUCUN envoi reel avant la decision -> apres push de decision approuvee, replay a l'identique + resultat remonte. 8 tests verts au total.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gabiar-maker
gabiar-maker merged commit 56cd352 into main Jun 8, 2026
@gabiar-maker
gabiar-maker deleted the feat/jb-outbound-plugin branch July 9, 2026 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant