:5191 → relais → Chronos :4344 → Fil :4477. Chaque affirmation de cette page = une commande rejouable (datée 2026-10-05, 01:15→01:50 locales).VFG-Agent-Presence (déclencheur logon) → doctor 12/12. Fil « Ready in 544ms », checkpoint Chronos avance.vfgate.out.log s'arrête pile à l'heure de winget install OpenJS.NodeJS.LTS (v22.14.0 → v24.19.0, session précédente). L'installeur tue tous les node.exe — seul Ollama survit (process séparé).chronos.err.log : ERR_DLOPEN_FAILED — better-sqlite3 (compilé ABI Node 22, runtime ABI 24). Chronos ne peut pas se relancer.20:20:51Z → 23:43:50Z, session test visible dans le contrat live v2, spool→replay livré (23:44:23Z), Fil 200.Le module natif better-sqlite3 de Chronos, compilé pour Node 22, refuse de se charger sous Node 24 :
// chronos.err.log
Error: ERR_DLOPEN_FAILED
at new Database (better-sqlite3/database.js:48)
at initDb (src/db.js:20)
Node.js v24.19.0
Même un redémarrage parfait de la garde n'aurait rien changé : le process **mort** ne pouvait pas renaître. La panne avait deux verrous, pas un.
La tâche planifiée qui relance toute la chaîne n'avait aucun intervalle :
PS> Get-ScheduledTask VFG-Agent-Presence | > triggers
Trigger type : MSFT_TaskLogonTrigger
Repetition : Interval='' Duration=''
Une garde qui ne garde que le logon = une chaîne qui ne survit pas au premier accident de session. C'est la leçon la plus chère : la panne n'était pas « VFGate a gelé » (correctif du 02/10 toujours en place), c'était une seule mort sans filet.
npm rebuild better-sqlite3
# rebuilt dependencies successfully
node src/server.js
# Server listening at http://127.0.0.1:4344
Le rebuild charge le prebuild pour l'ABI 24. Chronos réécoute.
$t = Get-ScheduledTask 'VFG-Agent-Presence'
$t.Triggers[0].Repetition.Interval = 'PT15M'
$t.Triggers[0].Repetition.Duration = ''
Set-ScheduledTask -InputObject $t
Toutes les 15 min, le script idempotent vérifie chaque service (Test-Http) et ne relance que ce qui est mort. Plus de mort silencieuse possible.
| Preuve | Commande rejouable | Résultat réel |
|---|---|---|
| Santé complète | doctor-agent-presence.ps1 | 12/12 OK — gate, Chronos, Fil, relais, spool, 4 configs hooks, tâche |
| Émission réelle | pipe JSON → emit-agent-event.mjs --event PostToolUse | checkpoint avance : 20:20:51Z → 23:43:50Z |
| Visible en aval | curl :4344/v1/query/agents/active | session e2e-presence-reparation-20261005 active, visible (contrat live v2) |
| Fil sert | curl :4477 | HTTP 200 (page « Fil — chronarbre de pensée ») |
| Fail-open | émettre vers porte morte :5999, puis forward-spool.mjs | spoulé puis livré au retour (checkpoint 23:44:23Z, spool purgé) |
| Zéro doublon | Get-CimInstance node.exe · forward-spool | 1 seul daemon résident (PID 32772) |
| Trace de secours | ~/.claude/vfg-journal/journal-2026-10-04.jsonl | 92 lignes, journal actif pendant toute la panne |
Deux pièges de mesure ont failli fausser le diagnostic — les deux sont dans la méthode (règle 4 de l'audit par la mesure) :
20:20:51Z semblait « fraîchement écrit » : en fait c'était la dernière écriture avant la mort (les tests E2E d'hier, le même soir qui a tué la chaîne)spool.processing.jsonl, déplacé avant publicationLa preuve n'est jamais le log d'un seul instant : c'est la réconciliation de 3 sources indépendantes (log gate, checkpoint Chronos, journal local) qui raconte la même histoire d'horloge.
| Élément | Verdict | Pourquoi |
|---|---|---|
| Chaîne de présence | VIVANTE | doctor 12/12 + E2E visible, daté 01:44 |
| Cause « mort en silence » | ÉLIMINÉE | garde 15 min posée, script idempotent vérifié |
| 2 adaptateurs gate (hero, whatsapp) | HORS PÉRIMÈTRE | santé 4/6, préexistant, impacte pas la présence |
Push commit gate 121cee4 | DÉCISION HUMAINE | déclenche un code-deploy production |
| F06 « réactiver télémétrie » | SATISFAITE | hooks + E2E + fail-open prouvés — reste le marquage du protocole |