Communitygithub.com

boucle-d-approbation-operator

Contrat d'approbation par un opérateur humain avec avis internes pour les messages sortants rédigés par un agent, incluant des brouillons hachés, des décisions horodatées, des revendications de livraison durables et un registre de preuves, ainsi qu'un garde-fou de base avant rédaction.

Qu'est-ce que boucle-d-approbation-operator ?

Cette compétence définit un contrat strict pour les agents qui rédigent des messages à destination de contreparties externes (clients, fournisseurs, investisseurs, etc.) et qui nécessitent une approbation humaine avant envoi. Elle garantit qu'aucun message ne part sans avoir été examiné et approuvé ou rejeté par un opérateur. Le système enregistre chaque brouillon comme une obligation, suit son statut (rédigé, approuvé, rejeté, envoyé), et conserve une piste d'audit immuable reliant le texte exact approuvé, l'opérateur et l'horodatage de la décision. Il inclut un registre de livraison qui prouve quel message a été envoyé et quand, évitant les doublons ou les envois non autorisés. Le garde-fou de base vérifie l'existence de contrats signés avec la contrepartie avant d'autoriser la rédaction, empêchant les questions intempestives après signature. Un mécanisme optionnel d'auto-approbation temporisée permet aux brouillons sans décision après un délai d'être automatiquement approuvés, tout en restant soumis à l'emport de l'opérateur humain. La compétence est implémentée via des références SQL (approval-ledger.sql) et Python (approval_claims.py) et se concentre sur la logique métier, laissant le transport des messages à d'autres couches.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/operator-approval-loop

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Boucle d'approbation opérateur

Un agent qui communique avec des contreparties externes ne doit jamais envoyer de message de son propre chef et doit tenir l'opérateur informé en interne. Cette compétence définit le contrat : chaque brouillon sortant est déposé comme une obligation, un opérateur décide du texte exact, et un registre de livraison prouve ce qui est parti.

Quand l'utiliser

  • Un agent rédige des réponses à des clients, fournisseurs, investisseurs ou partenaires dans un canal partagé, un e-mail ou un chat, et un humain doit approuver avant l'envoi.
  • Vous avez besoin d'une piste d'audit liant chaque message envoyé au texte exact du brouillon, à l'opérateur qui l'a approuvé et au moment de la décision.
  • Vous avez constaté qu'une approbation périmée libère un brouillon réécrit, ou que deux employés livrent le même message approuvé deux fois.
  • Les brouillons redemandent à la contrepartie des informations que le registre contient déjà.

Fonctionnement

Objets

ObjetSignification
ObligationUne chose due à une contrepartie. Statuts : rédigé, approuvé, rejeté, envoyé. Comporte direction, contrepartie, canal et un horodatage updated_at.
BrouillonLigne satellite contenant le texte exact du brouillon, son empreinte sha256, les coordonnées d'origine (plateforme, canal, fil, utilisateur) et une priorité (P0 à P3). Un par obligation, remplacé en cas de nouvelle soumission.
DécisionApprobation ou rejet d'un opérateur, enregistré avec l'identifiant de l'opérateur, un nonce et l'horodatage du brouillon concerné.
Instantané d'approbationTexte immuable, empreinte, horodatage et destination enregistrés par le rédacteur de décision autorisé. Les instantanés manquants ne peuvent pas autoriser l'envoi.
RevendicationRéservation durable avec un jeton aléatoire et un état ; au plus une revendication active par obligation.
LivraisonLigne de registre prouvant un envoi ou un avis pour un couple (obligation, décision).

Le schéma de référence se trouve dans references/approval-ledger.sql.

Dépôt d'un brouillon

  1. Nettoyer les entrées. Supprimer les caractères de contrôle, réduire les espaces blancs dans les champs sur une seule ligne, et appliquer des limites de longueur (brouillon, résumé, contexte, contrepartie). Les champs vides ou surdimensionnés sont refusés, pas tronqués silencieusement.
  2. Exécuter le garde-fou de base (ci-dessous). Il peut refuser le dépôt.
  3. Hacher le texte du brouillon avec sha256. Le préfixe de l'empreinte est ajouté au résumé pour que le panneau d'approbation montre quel texte il approuve.
  4. Mise à jour ou insertion. Si une obligation déjà rédigée existe pour la même (contrepartie, canal), remplacer le satellite du brouillon et avancer le updated_at de l'obligation. Cet avancement est la rotation d'horodatage : toute décision indexée sur l'ancien horodatage ne peut plus libérer le nouveau texte. Sinon, insérer une nouvelle obligation avec le statut rédigé.
  5. Acheminer l'accusé de réception du dépôt uniquement vers une destination interne opérationnelle configurée et vérifiée. Si l'origine est cette destination interne, accuser réception sur place. Jamais silencieux signifie un rapport interne, pas une réponse externe automatique. Garder les empreintes de brouillon, le statut d'approbation, l'identité de l'opérateur et les métadonnées du flux de travail hors des canaux visibles par la contrepartie. Les origines inconnues ou non classifiées restent silencieuses ; un message direct n'est pas automatiquement interne.

Si une destination interne vérifiée n'est pas disponible, conserver le résultat du dépôt dans le résultat de l'outil interne ou la surface opérateur. Ne jamais revenir à une origine externe ou inconnue. Un résultat d'outil exposé à des tiers n'est pas une surface interne.

Déposer un brouillon n'autorise pas une réponse externe. Toute question de clarification ou réponse neutre autorisée par la politique est une décision sortante distincte, soumise aux contraintes existantes de mention, de canal, de brouillon uniquement, de gel et de jamais dans la discipline de canal-contrepartie. Elle ne doit pas divulguer de métadonnées d'approbation internes.

Garde-fou de base

Avant de déposer un brouillon, interroger la base actuelle pour la contrepartie (un registre temporel, un stock de contrats ou un CRM) :

  • Contrat signé ou livré enregistré : refuser le dépôt avec les preuves et une recommandation. Demander à une contrepartie des spécifications après signature est exactement l'échec que ce garde-fou vise à empêcher.
  • Remplacement par l'opérateur : force_despite_signed_contract laisse passer le dépôt et ajoute [BASELINE_OVERRIDE_SIGNED_CONTRACT] dans le contexte du brouillon.
  • Service de garde-fou injoignable : le dépôt est effectué et le contexte est marqué [BASELINE_CHECK_UNAVAILABLE]. Le panneau voit que la protection était désactivée. Les échecs ne désactivent jamais silencieusement le garde-fou.
  • Lorsque des faits sont disponibles, joindre les plus récents au contexte sous forme de résumé [BASELINE FACTS: ...] pour que le brouillon atterrisse avec des informations actuelles.

Prise de décision

Le panneau d'approbation liste les obligations avec le statut rédigé et la direction nous_leur_devons. Approuver ou rejeter écrit une ligne de décision portant l'horodatage du brouillon (draft_updated_ts) et change le statut de l'obligation dans la même transaction. Une décision dont l'horodatage ne correspond pas au updated_at actuel est périmée et ne doit rien libérer.

Pour une décision d'approbation déjà autorisée, la même transaction insère une ligne immuable obligation_approval_snapshots : identifiants de la décision et de l'obligation, horodatage actuel du brouillon, texte exact et SHA-256, plateforme/canal/fil, et type draft_sent. Le rédacteur de décision doit établir l'autorisation avant d'écrire ; la référence n'authentifie jamais un opérateur ni ne fabrique de décision. La politique d'approbation automatique n'est ni activée ni étendue par la référence. Les décisions héritées sans instantané nécessitent une réconciliation explicite ou une nouvelle approbation ; ne jamais rétro céder d'autorisation à partir du brouillon mutable actuel.

Livraison

La référence SQLite est references/approval_claims.py. Elle accorde l'autorisation d'envoi mais n'appelle jamais le transport. Utiliser une base de données de référence locale existante initialisée à partir du fichier SQL ; le module n'applique pas de schéma ni de migrations de production. Seul un rédacteur de décision de confiance peut remplir les enregistrements d'approbation. Tous les rédacteurs doivent activer les clés étrangères et les déclencheurs récursifs et respecter les gardes du schéma ; la falsification administrative de la base de données est hors de ce modèle.

  1. Découvrir les brouillons approuvés liés. La découverte n'est pas une permission. claim() ouvre sa propre transaction BEGIN IMMEDIATE, valide l'horodatage approuvé actuel, le texte exact, le SHA-256 calculé et la destination complète par rapport à l'instantané, et insère une revendication unique avant de retourner son jeton. Un conflit arrête le travailleur avant le transport. Les accusés de réception complétés ne peuvent pas être réclamés.
  2. begin_dispatch() revalide la liaison et change atomiquement revendiqué en en cours d'envoi en utilisant le jeton. Seul son appelant gagnant reçoit le draft_text exact et la destination après validation. Ne jamais régénérer le texte, relire un satellite mutable pour le transport, ni réutiliser la charge utile pour une autre tentative. Une transaction d'appelant imbriquée est refusée ; l'autorisation ne peut pas dépendre d'une validation ultérieure de l'appelant. Aucune transaction de base de données ne reste ouverte pendant le transport.
  3. Un résultat confirmé réussi va à complete(), qui enregistre atomiquement la coordonnée de livraison, marque la revendication comme livrée et change le statut de l'obligation en envoyé. Une réalisation identique est une opération nulle ; des coordonnées conflictuelles échouent. La clé UNIQUE de l'accusé de réception déduplique les enregistrements, pas les effets externes antérieurs.
  4. Les exceptions, les dépassements de délai, la mort du travailleur après begin-dispatch, ou la persistance d'accusé de réception échouée laissent une tentative bloquée. mark_unknown() enregistre l'incertitude. Les revendications inconnues n'expirent jamais, ne se rouvrent jamais, ne se réessayent jamais et ne permettent pas à une autre décision pour cette obligation de les contourner. Un appelant de confiance peut utiliser reconcile() avec une coordonnée et une preuve de succès confirmée ; le module ne vérifie pas cette preuve. Un accusé de réception absent n'est pas une preuve de non-livraison.

La garantie est une tentative d'envoi automatique par décision approuvée, pas une livraison externe exactement une fois. Un crash après begin-dispatch mais avant transport peut laisser zéro envoi et une revendication bloquée. Libérer un résultat inconnu pour une nouvelle tentative nécessiterait d'isoler l'exécuteur original et de vérifier la sémantique du fournisseur ; cette référence ne fournit délibérément aucune opération de réessai.

État de la revendicationÉtats suivants autorisés
revendiquéen cours d'envoi ou annulé avant envoi
en cours d'envoilivré ou inconnu
inconnulivré uniquement via une réconciliation de confiance
livré, annuléterminal ; la clé de décision ne peut pas être réutilisée

Pendant qu'une revendication est active, les gardes de la base de données gèlent les écritures sur l'obligation, le brouillon et la décision, y compris les remplacements. Les instantanés et les revendications ne peuvent pas être effacés. Annuler une opération revendiquée avec son jeton avant de la redéposer ; le jeton périmé n'accorde alors rien. Une fois l'envoi commencé, garder les nouvelles modifications ou révocations pour la réconciliation. Cela sérialise les modifications au lieu de prétendre rappeler une opération en cours.

Les décisions rejetées et les lignes héritées sans satellites de brouillon/instantanés n'entrent jamais dans ce chemin d'envoi de brouillon externe. Les signaler sur la surface opérateur interne pour traitement manuel. Les pieds de page des accusés de réception internes restent internes : approuvé par <opérateur> · accusé <decision_id> · empreinte sha256 <prefix>. Ne jamais modifier le texte externe déjà approuvé pour y ajouter des métadonnées de flux de travail.

La validation locale ciblée utilise des bases de données temporaires, des connexions séparées et un compteur de tentatives simulé, pas un fournisseur ou un message réel : python3 -m unittest discover -s tests/skills -p 'test_approval_delivery_claims.py'. Les tests nécessitent Python 3.11+ avec le support de sérialisation SQLite ; la référence n'utilise que la bibliothèque standard. Les vérifications de contrat de modèle de bureau existantes restent un contrôle de compatibilité distinct.

Auto-approbation temporisée (optionnelle)

Un brouillon peut porter auto_send_after (secondes depuis l'époque). Une tâche de balayage approuve les brouillons dont le délai est dépassé sans décision, en enregistrant l'opérateur auto-ttl, puis la livraison suit le chemin normal. Les actions de l'opérateur gagnent toujours : une décision change le statut avant que le balayage ne le voie, et une nouvelle soumission fait tourner l'horodatage et déplace ou efface le délai. Le balayage revérifie le statut et l'horodatage à l'intérieur de la transaction d'écriture, de sorte qu'une condition de course se résout en opération nulle. Les brouillons sans délai restent bloqués pour toujours.

Liaison de signal

Un brouillon peut nommer l'obligation entrante à laquelle il répond (signal_obligation_id). C'est le seul lien véridique pour la mesure de latence (signal entrant vers réponse rédigée) et permet à l'analyse SLA de considérer cet élément entrant comme traité. Rejeter le dépôt si la ligne référencée n'existe pas.

Exemples

Déposer un brouillon

file_request(
  draft="Merci, nous pouvons garder le créneau jusqu'à vendredi. Quelle date de début vous conviendrait ?",
  counterparty="fournisseur-acme",
  context="réponse à la question sur la fenêtre de livraison",
  origin_platform="slack", origin_channel="#acme-partagé",
  origin_thread="1712345678.000100", priority="P1",
  signal_obligation_id=412)
-> {obligation_id: 431, draft_sha256: "9f2c...", refiled: false}

La destination interne opérationnelle configurée et vérifiée voit : Brouillon déposé pour approbation (P1, sha 9f2c8a1b). En attente de l'opérateur. Le canal d'origine visible par la contrepartie ne reçoit aucun avis de dépôt. Si aucune destination interne vérifiée n'est disponible, l'accusé de réception reste dans le résultat de l'outil interne ou la surface opérateur, sans recours externe.

Redéposer après une réorientation

L'opérateur demande un brouillon plus court. Une nouvelle soumission pour la même (contrepartie, canal) renvoie refiled: true, le texte et l'empreinte du satellite changent, et updated_at avance. Une approbation cliquée sur l'ancienne ligne du panneau porte l'ancien horodatage et est ignorée.

Refus du garde-fou

DeskApprovalError: le garde-fou de base a refusé ce brouillon : le registre montre un
contrat signé pour 'fournisseur-acme'. Preuve : contrat principal exécuté
2026-08-14. Recommandation : ne pas demander. Redéposer avec
force_despite_signed_contract=true s'il s'agit véritablement d'un nouveau fil.

Pied de page de livraison dans un canal interne

Confirmé pour vendredi, date de début 2026-09-08.
approuvé par opérateur-a · accusé 118 · empreinte sha256 9f2c8a1b2d3e4f50

Invariants à tester

  • Les accusés de réception de dépôt vont uniquement aux opérations internes configurées et vérifiées ; l'origine n'en reçoit un que lorsqu'elle est cette destination interne vérifiée.
  • Une origine inconnue reste silencieuse. Une destination interne indisponible utilise le résultat de l'outil interne ou la surface opérateur, sans recours externe.
  • Même (contrepartie, canal) déposé deux fois donne une seule obligation, deux horodatages.
  • Une décision avec un horodatage périmé n'entraîne jamais de ligne de livraison.
  • Deux revendicateurs concurrents donnent une seule autorisation d'envoi ; les perdants ne tentent jamais le transport.
  • Les résultats inconnus et la persistance d'accusé de réception échouée n'activent jamais de réessai automatique.
  • Une réalisation réussie enregistre l'accusé de réception et le statut envoyé en une seule transaction.
  • Un horodatage, un texte, une empreinte ou une destination modifiés ne peuvent pas acquérir ou commencer une revendication.
  • Les revendications actives bloquent une nouvelle soumission ; seule une annulation avant envoi peut libérer ce blocage.
  • Le garde-fou indisponible ajoute le marqueur ; le garde-fou avec contrat signé refuse sans force.
  • Auto-ttl ne se déclenche jamais contre un texte que l'opérateur a depuis redéposé.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Skills associés