orchai/docs/superpowers/specs/2026-04-17-graylog-auto-resolve-design.md

13 KiB

Orchai - Design Graylog Auto-Resolve (V1)

Date: 2026-04-17 Statut: Validé en session de brainstorming

1. Objectif

Ajouter un module projet Graylog qui:

  1. Interroge Graylog à intervalle régulier.
  2. Détecte des sujets d'erreur récurrents à partir des logs récents.
  3. Attribue un score déterministe à chaque sujet (sévérité + fréquence + récence).
  4. Déclenche automatiquement le pipeline agent existant analyst -> developer pour les sujets au-dessus d'un seuil.
  5. Crée une branche/worktree locale de correction via le flux actuel Orchai.

Le module doit rester isolé par projet avec des credentials Graylog propres à chaque projet.

2. Décisions validées

  1. Exécution automatique au-dessus du seuil: oui.
  2. Pipeline de traitement: réutilisation stricte du pipeline existant analyst -> developer.
  3. Scoring: formule déterministe uniquement.
  4. Définition d'un sujet: source/service + message normalisé.
  5. Déduplication: stricte, une seule branche active par sujet.
  6. Portée de la configuration Graylog: par projet.
  7. Approche d'architecture: extension ciblée sans refonte complète du modèle Tuleap.

3. Architecture cible

3.1 Module projet

Nouveau module dans project_modules:

  • module_key: graylog_polling_auto_resolve
  • name: Polling Graylog + auto-resolve
  • description: surveillance Graylog, scoring, déclenchement automatique du pipeline agent.

3.2 Composants backend

  1. graylog_client
    • Appelle l'API Graylog (requêtes de recherche, filtres, stream éventuel).
    • Transforme les réponses en événements de logs exploitables.
  2. graylog_scoring
    • Normalise les messages.
    • Regroupe par sujet.
    • Calcule le score déterministe.
  3. graylog_poller
    • Boucle périodique (comme les services de fond existants).
    • Charge la configuration de chaque projet.
    • Applique dédup et seuil.
  4. graylog_to_queue_bridge
    • Insère un item de traitement dans la file existante pour réutiliser l'orchestrateur.

3.3 Réutilisation du pipeline actuel

Le traitement des sujets Graylog utilise:

  1. processed_tickets comme file de traitement commune.
  2. services/orchestrator.rs pour exécuter analyst -> developer.
  3. services/worktree_manager.rs pour créer la branche/worktree locale.

Le poller Graylog détecte et pousse en file; il ne lance pas directement de correction.

4. Modèle de données

4.1 Nouvelles tables

  1. graylog_credentials (unique par projet)

    • id TEXT PRIMARY KEY
    • project_id TEXT NOT NULL UNIQUE REFERENCES projects(id) ON DELETE CASCADE
    • base_url TEXT NOT NULL
    • api_token_encrypted TEXT NOT NULL
    • analyst_agent_id TEXT NOT NULL REFERENCES agents(id)
    • developer_agent_id TEXT NOT NULL REFERENCES agents(id)
    • stream_id TEXT (optionnel)
    • query_filter TEXT NOT NULL DEFAULT ''
    • polling_interval_minutes INTEGER NOT NULL DEFAULT 10
    • lookback_minutes INTEGER NOT NULL DEFAULT 30
    • score_threshold INTEGER NOT NULL DEFAULT 70
    • created_at TEXT NOT NULL
    • updated_at TEXT NOT NULL
  2. graylog_subjects (état courant d'un sujet)

    • id TEXT PRIMARY KEY
    • project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE
    • subject_key TEXT NOT NULL
    • source TEXT NOT NULL
    • normalized_message TEXT NOT NULL
    • first_seen_at TEXT NOT NULL
    • last_seen_at TEXT NOT NULL
    • last_score INTEGER NOT NULL DEFAULT 0
    • active_ticket_id TEXT REFERENCES processed_tickets(id)
    • status TEXT NOT NULL DEFAULT 'idle' (idle|queued|processing|done|error|cancelled)
    • created_at TEXT NOT NULL
    • updated_at TEXT NOT NULL
  3. graylog_detections (historique des cycles)

    • id TEXT PRIMARY KEY
    • subject_id TEXT NOT NULL REFERENCES graylog_subjects(id) ON DELETE CASCADE
    • window_start TEXT NOT NULL
    • window_end TEXT NOT NULL
    • critical_count INTEGER NOT NULL DEFAULT 0
    • error_count INTEGER NOT NULL DEFAULT 0
    • warning_count INTEGER NOT NULL DEFAULT 0
    • total_count INTEGER NOT NULL DEFAULT 0
    • last_seen_at TEXT NOT NULL
    • score INTEGER NOT NULL
    • triggered INTEGER NOT NULL DEFAULT 0
    • triggered_ticket_id TEXT REFERENCES processed_tickets(id)
    • created_at TEXT NOT NULL

4.2 Évolution de processed_tickets

Ajouts:

  1. project_id TEXT REFERENCES projects(id) (renseigné pour tous les tickets)
  2. source TEXT NOT NULL DEFAULT 'tuleap'
  3. source_ref TEXT (référence externe, ici graylog_subjects.id)

Évolutions:

  1. tracker_id devient nullable pour supporter les sources non-Tuleap.
  2. Le code de lecture par projet ne dépend plus d'un JOIN obligatoire vers watched_trackers.
  3. Les tickets Tuleap continuent de renseigner tracker_id.
  4. Les tickets Graylog renseignent project_id et laissent tracker_id nul.

Rôle:

  • Distinguer les items Tuleap et Graylog.
  • Réutiliser l'orchestrateur sans dupliquer la mécanique de queue/worktree.

4.3 Index recommandés

  1. UNIQUE(project_id, subject_key) sur graylog_subjects.
  2. INDEX(subject_id, created_at DESC) sur graylog_detections.
  3. INDEX(source, source_ref) sur processed_tickets.
  4. INDEX(project_id, detected_at DESC) sur processed_tickets.
  5. Index unique Tuleap conservé en version partielle: UNIQUE(tracker_id, artifact_id) WHERE tracker_id IS NOT NULL.

4.4 Migration des données existantes

Ordre de migration recommandé:

  1. Ajouter project_id, source, source_ref sur processed_tickets.
  2. Backfill project_id pour les lignes existantes via JOIN watched_trackers.
  3. Rendre tracker_id nullable.
  4. Remplacer l'index unique historique (tracker_id, artifact_id) par l'index partiel Tuleap.
  5. Ajouter les nouvelles tables Graylog.

5. Définition d'un sujet et normalisation

5.1 Clé de regroupement

subject_key = source + '|' + normalized_message

source correspond au champ service applicatif si présent, sinon au champ source Graylog.

5.2 Normalisation V1

Transformation déterministe:

  1. Passage en minuscules.
  2. Remplacement des UUID par <uuid>.
  3. Remplacement des nombres longs/identifiants numériques par <num>.
  4. Remplacement des timestamps ISO par <ts>.
  5. Remplacement des adresses IP par <ip>.
  6. Remplacement des hash hexadécimaux longs par <hash>.
  7. Réduction des espaces multiples.

Objectif: regrouper des occurrences logiquement identiques malgré des valeurs dynamiques.

6. Scoring déterministe

Score total entre 0 et 100:

score_total = severity_score + frequency_score + recency_score

6.1 Sévérité (0..50)

  1. Si au moins un critical: 50
  2. Sinon si au moins un error: 35
  3. Sinon si au moins un warning: 20
  4. Sinon: 0

6.2 Fréquence (0..35)

Barème sur total_count dans la fenêtre du cycle:

  1. 1 -> 5
  2. 2-3 -> 12
  3. 4-7 -> 22
  4. 8-15 -> 30
  5. >=16 -> 35

6.3 Récence (0..15)

Barème sur l'âge du dernier événement du sujet:

  1. <=2 min -> 15
  2. <=10 min -> 12
  3. <=30 min -> 8
  4. <=120 min -> 4
  5. >120 min -> 0

6.4 Seuil

score_threshold est porté par projet dans graylog_credentials.

Valeur par défaut V1: 70.

7. Flux d'exécution

7.1 Cycle planifié

  1. Le scheduler Graylog se déclenche toutes les 60 secondes.
  2. Pour chaque projet:
    • vérifier module graylog_polling_auto_resolve activé;
    • charger credentials + config;
    • vérifier si polling_interval_minutes est atteint;
    • interroger Graylog sur la fenêtre lookback_minutes.
  3. Regrouper les logs en sujets.
  4. Calculer score par sujet.
  5. Persister détections et état des sujets.
  6. Décider du déclenchement.

7.2 Règle de déclenchement

  1. Si score < threshold:
    • triggered = 0 dans graylog_detections.
    • aucun item queue créé.
  2. Si score >= threshold:
    • si sujet sans traitement actif: créer un item processed_tickets de source graylog.
    • sinon: ne rien créer (dédup stricte), garder la trace en détection.

7.3 Dédup stricte

Un sujet est considéré actif si:

  1. graylog_subjects.active_ticket_id non nul, et
  2. le ticket lié est dans Pending|Analyzing|Developing.

Conséquence:

  • une seule branche active par sujet.
  • pas de duplication de branche tant que le ticket actif n'est pas terminé.

7.4 Nommage de branche

Format recommandé:

orchai/graylog/<subject_hash>

subject_hash est dérivé de subject_key pour conserver un nom stable et compact.

8. Intégration orchestrateur/worktree

8.1 Représentation queue Graylog

Lors du trigger:

  1. créer un processed_tickets avec:
    • project_id = <project_id>
    • tracker_id = NULL
    • source = 'graylog'
    • source_ref = graylog_subjects.id
    • artifact_id: identifiant synthétique négatif (dérivé de hash de sujet, avec fallback anti-collision) pour compatibilité UI.
    • artifact_title: résumé court ([Graylog] <source> - <message normalisé>).
    • artifact_data: JSON détaillant métriques et exemples de logs.
  2. mettre graylog_subjects.status = 'queued' et active_ticket_id = <ticket_id>.

8.2 Transition de statut sujet

Synchroniser graylog_subjects.status avec le ticket lié:

  1. Pending -> queued
  2. Analyzing -> processing
  3. Developing -> processing
  4. Done -> done puis idle au cycle suivant si pas de nouveau dépassement
  5. Error -> error
  6. Cancelled -> cancelled

8.3 Sélection des agents Graylog

Pour un ticket source='graylog', l'orchestrateur charge les agents depuis graylog_credentials du projet:

  1. analyst_agent_id pour l'étape d'analyse.
  2. developer_agent_id pour l'étape de correction.

Comportement en cas de configuration invalide:

  1. le ticket passe en erreur explicite;
  2. l'événement d'erreur est émis;
  3. aucun worktree n'est créé.

9. Contrats Tauri (backend)

9.1 Credentials/config

  1. set_graylog_credentials(project_id, base_url, api_token, analyst_agent_id, developer_agent_id, stream_id, query_filter, polling_interval_minutes, lookback_minutes, score_threshold)
  2. get_graylog_credentials(project_id)
  3. test_graylog_connection(project_id)
  4. delete_graylog_credentials(project_id)
  5. Les commandes de configuration incluent analyst_agent_id et developer_agent_id.

9.2 Pilotage et visibilité

  1. manual_graylog_poll(project_id)
  2. list_graylog_subjects(project_id)
  3. list_graylog_detections(project_id, subject_id?)

10. Événements frontend

Événements Tauri ajoutés:

  1. graylog-polling-started
  2. graylog-subject-triggered
  3. graylog-polling-finished
  4. graylog-polling-error

Ces événements sont complémentaires des événements existants du pipeline ticket.

11. UI

11.1 Modules projet

Dans ProjectModules, afficher le module Graylog avec activation/désactivation.

11.2 Vue Graylog projet

Nouvelle page projet dédiée:

  1. Formulaire de configuration (URL, token, stream, query, intervalle, lookback, seuil).
  2. Bouton Tester la connexion.
  3. Liste des sujets:
    • source
    • message normalisé
    • score actuel
    • dernière occurrence
    • statut
    • ticket/branche liés s'ils existent
  4. Historique des détections par sujet.

11.3 Dashboard

Le dashboard projet affiche les événements Graylog récents au même titre que les événements de polling et d'orchestration actuels.

12. Gestion d'erreurs et robustesse

  1. Erreur API Graylog:
    • journaliser côté backend,
    • émettre graylog-polling-error,
    • reprendre au cycle suivant sans bloquer le reste.
  2. Credentials absents/invalides:
    • projet ignoré pour le cycle,
    • statut explicite côté UI.
  3. Aucune erreur Graylog ne doit arrêter:
    • le poller Tuleap,
    • l'orchestrateur,
    • le task runner.

13. Tests

13.1 Unit tests

  1. Normalisation de message.
  2. Calcul de score (cas limites inclus).
  3. Dédup stricte (pas de second ticket si sujet actif).

13.2 Intégration DB

  1. Migration vers le nouveau schéma.
  2. Création d'un ticket source='graylog'.
  3. Cohérence de active_ticket_id et des transitions de statut sujet.

13.3 Services

  1. Poll sous seuil -> pas de trigger.
  2. Poll au-dessus seuil -> trigger unique.
  3. Poll répété au-dessus seuil avec sujet actif -> pas de nouveau trigger.

13.4 UI

  1. Toggle module Graylog.
  2. Sauvegarde config + test connexion.
  3. Affichage des sujets et statut lié au ticket.

14. Critères d'acceptation

  1. Un sujet Graylog au-dessus du seuil crée automatiquement un traitement complet analyst -> developer.
  2. Les sujets sont regroupés par source + message normalisé.
  3. Tant qu'un sujet est actif, aucune branche supplémentaire n'est créée pour ce sujet.
  4. Les décisions (trigger/dédup) sont auditables via l'historique des détections.
  5. Désactiver le module Graylog coupe les nouveaux déclenchements sans perdre l'historique.

15. Plan de rollout

  1. Livrer backend (migrations, services, commandes).
  2. Livrer UI (module + écran Graylog + événements).
  3. Activer sur un projet pilote.
  4. Ajuster seuil et barèmes de scoring si nécessaire.
  5. Généraliser projet par projet.