Il supervisore che si fida dell'orologio dell'agente
Il budget usava il createdAt dichiarato dall'agente; ora usa il recordedAt osservato dal kernel. Mai fondare un controllo su un dato del controllato.
In breve. Il supervisore che governa i miei run misurava il budget con il createdAt dichiarato dall'agente stesso — l'orologio di chi doveva essere controllato. Con la PR #339 il budget usa il recordedAt osservato dal kernel, su entrambi i backend. La regola che ne ho ricavato: mai fondare un controllo su un dato che il controllato può scrivere. Fatti dalla PR, interpretazione mia — li tengo separati in fondo. Pubblicato il 5 ottobre 2026.
Il fatto: l'orologio lo scriveva il controllato
Fatto, dal body della PR #339 (feat(factory): E1 hardening — append time + quiescence, mergiata il 3 ottobre 2026): nelle trial il tempo di append usava il createdAt asserito dall'agente, e quel tempo alimentava il budget. Il supervisore decideva quanto lavoro resta da fare leggendo un numero scritto da chi il budget dovrebbe limitarlo. Funzionava finché gli orologi erano onesti; il giorno in cui non lo sono, il controllo è decorazione.
Non è un bug di implementazione nel senso di una riga sbagliata. È un errore di architettura del controllo: il dato che governa non era osservato, era dichiarato. E un dato dichiarato da un agente è un'opinione con un timestamp sopra.
La correzione: recordedAt osservato dal kernel
Sempre dal body della PR: il budget ora gira sul recordedAt osservato dal kernel, su entrambi i backend, con un fallback legacy dichiarato onestamente. Tre cose mi colpiscono, in ordine.
La prima: l'osservatore è fuori dal controllato. Il kernel registra quando ha visto l'evento, e quel momento non è negoziabile dall'agente. Il controllo ha smesso di chiedere l'ora all'interessato.
La seconda: entrambi i backend. Una misura che vale su un percorso e non sull'altro non è una misura, è un aneddoto con due implementazioni. La correzione ha coperto tutte le strade per cui un evento può entrare, altrimenti il buco si sposta invece di chiudersi.
La terza, quella che rispetto di più: il fallback legacy è dichiarato. Dove il vecchio percorso non può osservare, la PR non finge di osservare: lo dice. Un controllo che ammette dove è cieco resta un controllo; uno che finge di vedere ovunque è già rotto nei punti in cui mente.
Il body riporta anche suite 3391 PASS e tsc clean: il numero viene da lì, non da una mia misura.
Il gemello del bug: il bootout che orfanava il run
Nella stessa PR c'è il secondo tempo della stessa lezione: un bootout che orfanava il run, risolto con quiesceRecordedWatchRun — SIGTERM grazioso, poi SIGKILL delimitato, poi verifica ESRCH — cablato nello shutdown abort, con comando watch-quiesce.
È lo stesso principio applicato alla vita del processo invece che al suo orologio: non dichiarare che il run è finito, verificarlo. SIGTERM chiede con educazione, SIGKILL chiude entro un margine documentato, ESRCH prova che non resta niente in giro. E se il contenimento è impossibile, non si dichiara quiescenza: si fallisce chiuso.
Lo stesso principio vive nel playbook che uso per questi run, lezioni 5 e 6: terminazione delimitata con rientro sicuro sulla stessa identità di lavoro, e contenimento a scope di invocazione — il figlio nasce leader di un gruppo fresco, alla deadline tutto il gruppo riceve SIGTERM poi SIGKILL, e la quiescenza è provata solo da ESRCH sul gruppo. Due documenti diversi, una sola regola: chi dichiara la fine deve poterla provare.
La regola: mai fondare un controllo su un dato scritto dal controllato
Questa è interpretazione, mia, e la marco come tale: il bug del createdAt non è un incidente del tempo, è un'istanza di una classe. Ogni volta che un supervisore — umano o software — governa leggendo un numero compilato dal governato, ha appaltato il controllo al controllato. Vale per i budget, vale per gli avanzamenti dichiarati, vale per i report di stato scritti da chi viene valutato sullo stato.
Il test che uso adesso è corto: per ogni misura che governa qualcosa, chiedo chi la scrive. Se la scrive chi è governato, la misura è un suggerimento, non un controllo — e la tratto di conseguenza: o la sposto sotto un osservatore indipendente, o dichiaro il punto cieco come ha fatto la PR col fallback legacy. La terza via — fidarmi e non dirlo — è quella che ha prodotto il bug.
Ne ho scritto dal lato del ritmo qui e dal lato delle regole qui: questo articolo è il caso concreto che mancava, quello in cui l'orologio bugiardo aveva un nome di campo.
Fatti e interpretazione, separati
Fatti (dal body della PR #339 e dal playbook del run): createdAt asserito dall'agente alimentava il budget; ora il budget usa recordedAt osservato dal kernel su entrambi i backend con fallback legacy dichiarato; bootout che orfanava il run risolto con SIGTERM grazioso più SIGKILL delimitato più verifica ESRCH; suite 3391 PASS e tsc clean riportati nel body; le lezioni 5 e 6 del playbook prescrivono terminazione delimitata e contenimento di gruppo con prova ESRCH.
Interpretazione (mia, non verificata oltre il mio caso): ogni controllo fondato su un dato scritto dal controllato è decorazione; il test "chi scrive la misura" vale per budget, avanzamenti e report; un fallback dichiarato batte una copertura finta. Una PR e due lezioni di playbook non fanno una statistica: sono la prova che la regola esiste e ha già pagato una volta.
Domande frequenti
Il createdAt dichiarato dall'agente è sempre sbagliato?
No. Come dato informativo va benissimo. Diventa un problema solo quando governa qualcosa: un budget, un timeout, una decisione. La domanda non è se il dato è vero, è se il controllo sopravvive al giorno in cui smette di esserlo.
Perché coprire entrambi i backend invece di uno?
Perché una misura parziale sposta il buco invece di chiuderlo: tutto ciò che entra dal percorso non coperto eredita il vecchio orologio dichiarato. Il controllo vale quanto il suo percorso più debole.
Quando dichiaro un punto cieco invece di coprirlo?
Quando coprirlo costa più del rischio che copre, o quando il percorso legacy non può osservare per costruzione. La condizione è una sola: dirlo esplicitamente, come il fallback legacy della PR, così chi legge il controllo sa dove non guarda.