English summary
People running OpenFox sessions in the background (locally, in CI, or via CLI) need a way to know whether a session is working, progressing, waiting for input, stalled, blocked or finished without repeatedly asking "where is it?" or keeping an LLM active just to monitor progress. This request proposes a passive Watchdog layer — events, status snapshots and a simple read-only dashboard — strictly separate from the execution engine, with explicit limits on what the MVP should and should not do. This is a discussion, not a roadmap proposal; we are open to maintainers' feedback on architecture, transport and the smallest useful MVP.
Problème humain observé
Quand une session OpenFox tourne en arrière-plan (en local, en SSH, en CI, ou pilotée via la CLI évoquée dans l'Issue #199), on ne dispose pas d'un moyen simple et factuel de savoir :
- est-ce qu'elle travaille réellement en ce moment ;
- est-ce qu'elle progresse vraiment (vs. elle boucle / rature) ;
- est-ce qu'elle attend une action de l'utilisateur (question, confirmation, validation de plan) ;
- est-ce qu'elle est bloquée ou simplement inactive ;
- est-ce qu'elle est terminée (succès, échec, annulation).
Aujourd'hui, pour le savoir, on doit soit consulter l'UI, soit demander « où en est-on ? » au modèle, ce qui gaspille des tokens et donne une réponse en prose peu fiable. Maintenir un LLM dédié à la surveillance est également coûteux et redondant.
Distinction importante
Pour pouvoir distinguer « travaille » de « progresse réellement », deux horodatages doivent être exposés séparément :
lastActivityAt : dernière trace de vie brute (événement réseau, log, tick), même si le modèle boucle.
lastProgressAt : dernière avancée factuelle (critère validé, étape terminée, livrable produit, vérification passée).
L'absence de progrès depuis longtemps, alors que lastActivityAt est récent, est précisément le signal « stalled » observé dans l'issue #108.
États proposés (à discuter)
Vocabulaire indicatif, à aligner avec ce que les mainteneurs envisagent :
queued : en attente de démarrage.
running : active, mais sans garantie de progrès.
progressing : activité et progrès observés.
waiting_for_user : une action humaine est requise (question, confirmation, validation).
stalled : activité sans progrès depuis un seuil à définir.
blocked : bloquée par une dépendance interne (erreur, garde-fou, dépendance manquante).
completed : terminée avec succès.
failed : terminée en erreur.
cancelled : arrêtée explicitement.
Contrat JSON versionné
Pour que le dashboard et les agents externes (Hermes, CLI évoquée dans #199) puissent consommer les informations sans parser de la prose LLM, un contrat JSON versionné est nécessaire. Minimum attendu :
- version explicite (
schemaVersion).
- identifiant de session, identifiant de projet, mode (Plan / Build / Verify).
- phase courante, étape courante, critères (total / validés / en attente / échoués).
lastActivityAt, lastProgressAt, et un progress exprimé en preuves factuelles (critères validés, étapes terminées, vérifications passées) — pas un pourcentage ni une durée inventée.
actionRequired : description structurée d'attente, le cas échéant.
links : liens profonds vers l'UI OpenFox.
Événements de haut niveau (liste indicative)
À exposer via un flux public (WebSocket, SSE, fichier, ou hook HTTP) :
plan.ready
user.action_required
workflow.step.started
workflow.step.completed
session.stalled
session.blocked
verification.failed
task.completed
session.failed
Ces événements doivent être factuels et corrélés à un identifiant de session stable.
Hooks
Trois modes de réception, à choisir selon le contexte :
- flux public du serveur (WebSocket / SSE) ;
- commande locale (le watchdog est lui-même un consommateur du flux) ;
- hook HTTP sortant (pour des intégrations type tableau de bord distant ou alerting).
Le système doit prévoir :
- filtrage par projet, session, type d'événement ;
- corrélation (identifiant unique d'événement,
requestId / sessionId) ;
- reprise (le consommateur peut se reconnecter et rattraper un flux) ;
- déduplication côté consommateur ;
- garde-fous de sécurité (pas d'actions destructives via les hooks).
Dashboard simple (lecture seule)
Un premier palier pourrait être un tableau de bord HTML/CSS/JS en lecture seule, indiquant pour chaque session :
- carte projet + session ;
- phase, étape, critères ;
- dernier progrès et action requise ;
- sons limités (uniquement
user.action_required et session.failed) ;
- liens profonds vers l'UI OpenFox.
Ce dashboard est volontairement passif : il observe, il n'agit pas.
MVP : passif uniquement
Le MVP de cette Issue B est volontairement restreint à :
- observation (lecture de l'état structuré) ;
- émission d'événements ;
- dashboard read-only ;
- sons et liens ;
- aucune relance, aucun retry, aucun abort automatique.
Toute action de reprise, retry ou annulation doit passer par l'interface officielle de contrôle (GUI ou la CLI de l'Issue #199), pas par le watchdog.
Évolution ultérieure (à valider avec les mainteneurs)
- Reprise automatique d'une session stalled, sous contrôle explicite et via l'API officielle.
- Retry et abort, également via l'API officielle.
- Corrélation multi-sessions (projet, file d'attente).
Hors périmètre explicite
- Lecture directe de la base SQLite.
- Parsing de la prose LLM pour inférer un état.
- Faux pourcentage de progression ou durée estimée inventée.
- Toute tentative de faire du watchdog une nouvelle source de vérité.
Questions ouvertes aux mainteneurs
- Comment définir de façon prudente
lastProgressAt sans tomber dans le piège du « progrès simulé » ?
- Le watchdog doit-il être dans le dépôt OpenFox ou un consommateur externe (Discussion code-review-graph save 93x tokens per session #179 a déjà cette couleur) ?
- Quel transport pour les hooks : WebSocket, SSE, hook HTTP sortant, fichier ?
- Quel est, selon vous, le plus petit MVP réellement utile ?
Références
English summary
People running OpenFox sessions in the background (locally, in CI, or via CLI) need a way to know whether a session is working, progressing, waiting for input, stalled, blocked or finished without repeatedly asking "where is it?" or keeping an LLM active just to monitor progress. This request proposes a passive Watchdog layer — events, status snapshots and a simple read-only dashboard — strictly separate from the execution engine, with explicit limits on what the MVP should and should not do. This is a discussion, not a roadmap proposal; we are open to maintainers' feedback on architecture, transport and the smallest useful MVP.
Problème humain observé
Quand une session OpenFox tourne en arrière-plan (en local, en SSH, en CI, ou pilotée via la CLI évoquée dans l'Issue #199), on ne dispose pas d'un moyen simple et factuel de savoir :
Aujourd'hui, pour le savoir, on doit soit consulter l'UI, soit demander « où en est-on ? » au modèle, ce qui gaspille des tokens et donne une réponse en prose peu fiable. Maintenir un LLM dédié à la surveillance est également coûteux et redondant.
Distinction importante
Pour pouvoir distinguer « travaille » de « progresse réellement », deux horodatages doivent être exposés séparément :
lastActivityAt: dernière trace de vie brute (événement réseau, log, tick), même si le modèle boucle.lastProgressAt: dernière avancée factuelle (critère validé, étape terminée, livrable produit, vérification passée).L'absence de progrès depuis longtemps, alors que
lastActivityAtest récent, est précisément le signal « stalled » observé dans l'issue #108.États proposés (à discuter)
Vocabulaire indicatif, à aligner avec ce que les mainteneurs envisagent :
queued: en attente de démarrage.running: active, mais sans garantie de progrès.progressing: activité et progrès observés.waiting_for_user: une action humaine est requise (question, confirmation, validation).stalled: activité sans progrès depuis un seuil à définir.blocked: bloquée par une dépendance interne (erreur, garde-fou, dépendance manquante).completed: terminée avec succès.failed: terminée en erreur.cancelled: arrêtée explicitement.Contrat JSON versionné
Pour que le dashboard et les agents externes (Hermes, CLI évoquée dans #199) puissent consommer les informations sans parser de la prose LLM, un contrat JSON versionné est nécessaire. Minimum attendu :
schemaVersion).lastActivityAt,lastProgressAt, et unprogressexprimé en preuves factuelles (critères validés, étapes terminées, vérifications passées) — pas un pourcentage ni une durée inventée.actionRequired: description structurée d'attente, le cas échéant.links: liens profonds vers l'UI OpenFox.Événements de haut niveau (liste indicative)
À exposer via un flux public (WebSocket, SSE, fichier, ou hook HTTP) :
plan.readyuser.action_requiredworkflow.step.startedworkflow.step.completedsession.stalledsession.blockedverification.failedtask.completedsession.failedCes événements doivent être factuels et corrélés à un identifiant de session stable.
Hooks
Trois modes de réception, à choisir selon le contexte :
Le système doit prévoir :
requestId/sessionId) ;Dashboard simple (lecture seule)
Un premier palier pourrait être un tableau de bord HTML/CSS/JS en lecture seule, indiquant pour chaque session :
user.action_requiredetsession.failed) ;Ce dashboard est volontairement passif : il observe, il n'agit pas.
MVP : passif uniquement
Le MVP de cette Issue B est volontairement restreint à :
Toute action de reprise, retry ou annulation doit passer par l'interface officielle de contrôle (GUI ou la CLI de l'Issue #199), pas par le watchdog.
Évolution ultérieure (à valider avec les mainteneurs)
Hors périmètre explicite
Questions ouvertes aux mainteneurs
lastProgressAtsans tomber dans le piège du « progrès simulé » ?Références