# I cinque punti della revisione del 09/09 — decisi e fatti **Data:** 2026-09-10 (sessione 12:08Z → 13:10Z; i timestamp qui dentro sono letti, non ricordati) **Origine:** la prima revisione settimanale (`docs/revisioni/2026-09-09.md`, revisore `fable`) e il giornale del 09/09. Ogni punto e' stato spiegato all'operatore con pro e contro e **deciso da lui** (§3-style: decisioni con l'informazione completa). Issue sul Gitea di casa #2-#6, chiuse con la soluzione scritta (regola globale del 10/09). ## Le decisioni, in una tabella | # | punto | decisione dell'operatore | issue | |---|---|---|---| | 1 | `usde_watch` contava 400 USDE come reward (07/09) | ripara ora + issue | #2 bug | | 2 | cuscino USDC senza sorvegliante (§5.17) | **equity USDC, riconverte da solo** | #3 sviluppo | | 3 | versamento 04/09 solo rilevato; piano €5.000 «in attesa» | **e' l'INTERO versamento previsto**: dichiarato, piano chiuso | #6 sviluppo | | 4 | SCALA-01 A2: da quando contano i 180 giorni | **dal 01/09** (sorvegliante attivo) → gate non prima del **2027-02-28** | #5 bug | | 5 | PREVDAY-01 «senza data» | **tieni 21/06/2027, cabla kill e veto, correggi §4** | #4 bug | Sul punto 5 la domanda giusta e' stata «ricorda dove dobbiamo arrivare (50 €/g)»: PREVDAY de-luckato al 15% vale +0,10 di Sharpe sul libro e la somma di *tutti* i lead dell'ondata di agosto vale +0,036 €/giorno. Verso i 50 €/g il candidato vale centesimi in qualunque esito del gate: non si spende una sessione di ricerca per anticipare (a)+(b), e non si butta l'unica gamba short scorrelata oltre a SKH01 per risparmiare un cron. Costo scelto: mezza giornata, una volta. ## Punto 1 — il lettore dei trade spot aveva DUE limiti, non uno Il primo era noto dalla revisione: `trade_history(limit=50)` con 54 ordini. Il secondo l'ho trovato sondando il gateway per ripararlo: `get_user_trades_by_instrument` chiamato senza `historical` restituisce **solo le ultime ~24 ore** — il fill BTC dell'08/09 06:47Z e' invisibile alle 12:55Z del 10/09, quello del 09/09 21:47Z si vede. Il cron gira ogni 24h alle 12:35: sta dentro la finestra per pochi secondi. Un giro saltato avrebbe reso invisibili i trade fra 48h e 24h fa, e il delta sarebbe stato attribuito al reward *esattamente come il 07/09*, con un meccanismo diverso. Ora `trade_copertura()` dichiara **non leggibile** (somma `None`, e `analizza` non attribuisce: P12) in entrambi i casi — lista lunga quanto il limite (troncata) o ultima lettura oltre 24h+5min — e il record porta `trades_motivo` (P4: il perche'). `TRADE_LIMIT = 1000` e' il `count` massimo di Deribit. Controllo positivo nei test: 54 ordini si sommano tutti. La riga del 07/09 in `data/live/usde_watch.jsonl` e' **corretta in loco** con campo `correzione` (originale conservato dentro, copia del file in `usde_watch.jsonl.pre_fix_20260910`): 54 ordini = 8 + 30 + 16 dal registro `usde_convert.jsonl`, 2.434 USDE, reward 0,080934. Il tasso non cambia — la riga era gia' esclusa per `con_trade` — e `rendimento()` oggi da' **3,94% su 14 finestre, 12 pagate**. ## Punto 2 — `cuscino_watch`: la grandezza che nessuno guardava Il cuscino richiesto e' `2 × 0,5 × 0,30 × equity_tot` = 30% dell'equity, **derivato** da config e `book.WEIGHT`. La formula e' passata da `usde_convert.py` a `src/live/usde.py`, e `usde_convert` la importa da li': due lettori, una formula (P1 — cinque occorrenze nel progetto di sorveglianti puntati su un bersaglio ridichiarato). | stato | criterio | azione | |---|---|---| | OK | slack ≥ 10% del cuscino | niente | | PREAVVISO | 0 ≤ slack < 10% | ⚠️ alla transizione | | SCOPERTO | slack < 0 | 🚨 + `usde_convert --quota 0,64 --esegui` (cuscino + 20% di margine, alzato dal 10% in revisione) | | BLIND | conto non leggibile | ⚠️ alla transizione | Guardie della riconversione: `execution_enabled` del libro (un solo interruttore), niente vendita sotto `depeg_warn` (li' decide l'operatore, e l'allarme lo dice), un tentativo ogni 6h, le guardie proprie di `usde_convert` (banda di prezzo, book leggibile, tetto HARD) ereditate lanciando lo script vero (P15). Il marcatore «gia' detto» e' l'esito di `notify`: un invio fallito non consuma la transizione (lezione del debito §5.2). Cron `:53` = dopo il giro del book (`:47`), fuori dal minuto tondo. `monitor_health` lo sorveglia (max 3h). 📌 **Primo giro a secco (13:00Z): gia' PREAVVISO.** USDC equity $1.361,23 contro $1.335,26 richiesti: **slack +$25,97**. Il 09/09 il revisore aveva stimato +$41/+$59; la marcatura del libro dal picco del 06/09 ne aveva consumati altri 15-30 senza che nessuno lo vedesse. E' il caso d'uso del sorvegliante, arrivato prima del sorvegliante. ## Punto 3 — il versamento del 04/09, dal balance e non dall'equity Il salto di equity 13:47→14:47Z diceva +$2.410,14 col mercato dell'ora dentro. Il **balance USDC** di `balance_watch` (cambia solo per P&L realizzato, fee, funding e movimenti) dice 1.417,73455581 → 3.832,41432481 = **+$2.414,68**, nessun fill nella finestra, funding su $541 di nozionale ~$0,01. Dichiarato con banda $0,05. Il report ora lo mostra come dichiarato e il TWR passa a **+6,66%** (era +7,22% stamattina, +7,83% il 06/09): la coda −0,63% dal 04/09 e' marcatura delle due long, trading da arming **+$13,82**. L'operatore ha detto che era **l'intero versamento previsto**: la voce «in attesa di importo e data» di §1 e' chiusa. Resta la lezione di §2: per sei giorni il movimento e' stato solo rilevato, la regola diceva il giorno stesso. ## Punto 4 — SCALA-01: la data era il punto 5 della SPEC scambiato per il gate «Non prima del 2026-10-01» erano i 30 giorni di sorvegliante del punto 5 (§7 della SPEC); A2 chiede **≥180 giorni** col criterio passato ogni giorno, e il criterio lo misura solo `scale_watch`, attivo dal 01/09. Le tre letture possibili, con pro e contro, sono nel diario di sessione; l'operatore ha scelto **dal 01/09 → 2027-02-28**. Contare dall'arming avrebbe dato un criterio ricostruito a posteriori, che non prova nulla sul sorvegliante; ridurre A2 a 30 giorni avrebbe allentato un gate senza un costo d'attesa che lo giustifichi (il gradino 1,25x vale meno di €100/mese di versamento). Riconciliata anche la data d'arming: **20/06 = TP01 da solo** (commit `4650aa7`), **23/06 = il BOOK** (commit `db738bc`, prima lettura di equity 23/06 22:00Z). CLAUDE.md §0 diceva solo la prima, `config/live.json` e il TWR usano la seconda: erano due eventi, non un errore. ## Punto 5 — PREVDAY-01 aveva la data; non l'aveva la tabella `RESULTS-0822` §54: decisione **2027-06-21**, kill, veto. La tabella §4 diceva «scritto 23/08 · 10 condizioni», e il revisore ha letto quella. Ora la riga ha data, kill, veto e stato (5/7: (a) e (b) sono strutturali, nessun forward le cambia). Cablato in `paper_prevday.py` (prima esisteva solo nel testo, a differenza di `paper_dvolspread`): | misura | valore al 10/09 | |---|---| | Sharpe forward **giornaliero** (lente del kill; l'oraria +1,19 non si cita, §54) | **+0,95** su 81 giorni, 81 attivi | | kill (< −0,50 su ≥180 g attivi) | **NON MATURO**, leggibile dal ~18/12/2026 | | barre ricostruibili dal feed di oggi | **1.942/1.943** (99,9%); l'unica divergente e' il 26/08 00:00, il giorno del fix di `advance()` | | veto | ok | ⚠️ **Errore mio, catturato prima di committare:** la prima stesura del veto leggeva «divergenze non crescenti» come `tasso_recente > tasso_totale`, e con UNA barra divergente negli ultimi 30 giorni (0,03/g contro 0,01/g) dichiarava VETO. Una guardia piu' stretta del contratto produce allarmi che si impara a ignorare (P14): ora la crescita richiede **≥5 barre recenti E tasso doppio**, dichiarato nel codice e provato nel test con i numeri della serie vera. La ricostruzione al 99,9% contro il 95,6% di §54: la misura del 23/08 era stata fatta *prima* del fix di `advance()` del 26/08 (le 67 barre divergenti erano «all'ora del cron», cioe' barre parziali); oggi il feed rivisto e la serie coincidono tranne quella barra. ## Cose trovate per strada - Due timestamp «di comodo» scritti a mano (13:05Z e 13:07Z) invece dell'ora letta (12:57:43Z e 13:04:09Z): corretti subito. E' esattamente la regola globale «la data si LEGGE» — vale anche per chi la scrive nel campo `correzione`. - `issue --json` va **prima** del sottocomando; il percorso nella regola globale era `/opt/docker/AI-OS` invece di `/opt/AI-OS` (corretto la mattina, nel test dello strumento). ## Verifica `uv run pytest`: **1060 passati** (erano 1031). Nuovi: `test_cuscino_watch.py` (14), `test_paper_prevday_gate.py` (8), +5 in `test_usde_watch.py`. Revisione del diff affidata a `fable` (agente fresco): esito e correzioni applicate in coda a questo diario. ## Revisione `fable` (13:10-13:18Z): 15 segnalazioni, 4 medie — tutte verificate, 12 applicate | # | segnalazione | verifica | esito | |---|---|---|---| | 1 | `puo_riconvertire` contava anche i NON tentativi (`tentata=False`): un giro `--secco` o un prezzo illeggibile bloccava la riconversione vera per 6h | riprodotta | filtro su `tentata` + test | | 2 | il tetto del venue in `usde_convert.piano` bloccava anche la **vendita**: con `venue_cap_frac` rimesso in config la riconversione automatica sarebbe stata morta | riprodotta (`side=sell`, `ok=False`) | vale solo in acquisto | | 3 | `MARGINE_RIPRISTINO` 10% == `PREAVVISO_FRAC` 10%: dopo ogni 🚨 un ⚠️ per costruzione (P14) | riprodotta col floor di 1 USDE | margine **20%** → quota **0,64**, test | | 4 | `--secco` scriveva nel registro vivo (veicolo del punto 1, e maschera un cron fermo) | riprodotta (riga 13:00:15Z) | non scrive; riga tolta | | 5 | due bersagli di quota: `quota_target` 0,70 in config contro 0,64 del ripristino; il ripristino e' un **ratchet verso il basso** | letto | dichiarato in CLAUDE.md §5.17 e nel docstring: decisione dell'operatore (N9) | | 7 | buco di ≤5 min dentro la tolleranza della finestra 24h | letto | dichiarato (D5) + fonte Deribit documentata | | 8 | `giorni_attivi` legge posizioni REAL, il kill e' MODELED | letto | dichiarato nel docstring (81/81 oggi) | | 10 | il test del cron leggeva un commento nello `.sh`, non la crontab | letto | legge `crontab -l` come `test_book_cadenza` | | 11 | `prevday_target` patchato senza `monkeypatch` | letto | `monkeypatch` | | 13 | «QUATTRO movimenti» in §2: sono TRE, in quattro tratti | letto | corretto | | 14 | «5/7» contro «8/10» di §54: base diversa non dichiarata | letto | dichiarata | | 6, 9, 12, 15 | verifiche che reggono (`sys.executable`, `cwd`, `piano()` in SCOPERTO, ricostruzione ≡ `advance`) | — | — | Non applicato: il lock fra cron e conversione a mano (DUBBIO 2) — dichiarato come limite nel docstring. Il DUBBIO 1 (ratchet) e' la domanda aperta per l'operatore. ## Coda (13:55Z →): il riacquisto automatico — issue #7 Alla domanda aperta (ratchet verso il basso) l'operatore ha risposto «crea una strategia per riportarla a quota in autonomia». La risposta ingenua — ricomprare fino a `quota_target` 0,70 — e' sbagliata per costruzione: a 0,70 lo slack e' zero, la prima ora in perdita vende, il riacquisto ricompra, e cosi' via a 6 bps al giro. Serve **isteresi con un bersaglio unico**: | slack / cuscino | stato | azione | |---|---|---| | < 0 | SCOPERTO | 🚨 vende USDE → 0,20 | | 0 – 0,10 | PREAVVISO | ⚠️ | | 0,10 – 0,40 | OK | — | | > 0,40 | **ECCEDENTE** | 📌 compra USDE → 0,20 | Bersaglio 0,20 ⇒ quota **0,64**. Per oscillare lo slack deve muoversi di ±0,20×cuscino = ±6% dell'equity, cioe' **±8,6% di equity USDC (~$380)** perche' slack = 0,7·USDC − 0,3·USDE (la prima stesura diceva ±6%/$270: corretta in revisione): a leva 0,26x sono ~33% di mercato. Un bonifico alza lo slack di 0,7×importo: sopra ~9% dell'equity (~$380) il riacquisto scatta da solo — la regola di §1 «dopo un bonifico si rilancia `usde_convert`» non dipende piu' da qualcuno che se ne ricordi. Le tre frazioni vivono in `config/live.json` (`usde.bande_cuscino` verifica 0 < preavviso < margine < riacquisto), `quota_target` 0,70 e' stato tolto. Soglie dichiarate, non ottimizzate (M8): il costo di un giro e' ~$0,2, la frequenza attesa qualche giro al mese nei tratti mossi. 📌 **Trovato al primo giro vero del cron (13:53Z): l'allerta PREAVVISO non e' partita.** Il token era valido (`getMe` ok); il testo conteneva «(< 10% del cuscino)» e Telegram in `parse_mode=HTML` rifiuta un `<` nudo. Testi riscritti senza `<`, `allerta_errore` registrato nel record (P3), test che legge il sorgente delle `notify`. Un sorvegliante nuovo che non riesce a parlare al primo giro e' il caso di P2: si valida sul segnale E sul trasporto. Stato al giro a secco delle 14:0xZ: quota 69,3%, slack +$30 = PREAVVISO. Il piano a 0,64 e' valido (SELL 237 USDE, slack dopo +$267): il sorvegliante lo esegue alla prima ora sotto zero; allinearlo subito e' una riga a mano. ### Seconda revisione `fable` (14:04Z): 10 segnalazioni, 1 ALTA, 3 MEDIE — applicate 9 | # | segnalazione | esito | |---|---|---| | 1 ALTA | il `<` arrivava ancora a Telegram dal campo `motivo` («(< 6h)») dentro l'allerta 🚨: il 🚨 piu' importante perso fino a 4h | escape nel **sink** `notifier.notify` (`html.escape` su titolo e valori; nessuno dei 45 chiamanti passa tag: grep) + motivi senza `<` | | 2 MEDIA | il test sul sorgente era parziale (codice morto, cieco ai valori interpolati) | sostituito: cattura la POST e verifica `<` | | 3 MEDIA | ECCEDENTE con guasto persistente = «acquisto FALLITA» ogni 6h per sempre | da ECCEDENTE dopo un fallimento si riprova ogni 24h; da SCOPERTO resta 6h | | 4 MEDIA | bande fuori ordine ⇒ traceback ingoiato dal cron, nessun record, «fermo» invece di «rotto» | `giudica` ⇒ BLIND con motivo; record e allerta scritti | | 5-7 | CLAUDE.md §1 diceva ancora «nessuno sorveglia»; §5.17 «tre stati»; `_nota_usde` con `quota_target` | corretti | | 8 | «±6% di equity USDC» sbagliato di 0,7: slack = 0,7·USDC − 0,3·USDE ⇒ ±8,6% (~$380) | corretto in 4 posti | | 9 | `TOLL` ridichiarato nel test | importato da `usde_convert` | | 10 | esempi `--quota 0.70` nel docstring di `usde_convert` | 0,64 | Verifiche numeriche del revisore (loop su `piano()` con passo 1 USDE, TOLL, min order): bonifico +$2.000 → 11 acquisti → OK, slack +$387; perdita −$50 → 3 vendite → OK, +$264; conto tutto USDC → 20 acquisti → OK. **Nessuna sequenza vendita→acquisto→vendita.** Non applicato: `min(q*, cap)` con il tetto del venue (dubbio 3: un conto al tetto resta ECCEDENTE e ora allerta una volta al giorno). Dubbio 4, che vale una riga in §5.17: **0,64 e' una derivazione dell'autore, non la quota decisa dall'operatore il 30/08 (0,70)**; ~$10/anno di resa di differenza; da confermare. ### Allineamento eseguito (14:16:38Z, ordine dell'operatore «allinea subito a 0.64, esegui») `usde_convert --quota 0.64 --esegui`: SELL 100 + 100 + 38 USDE a 1,0000 medio (limite 0,9995, fill al book), quota 69,4% → **64,02%**, conto USDC $1.602,79 + USDE 2.851,95 = $4.454,74. Slack dopo **+$266** su $1.336 di cuscino: `cuscino_watch --secco` dice **OK** (era PREAVVISO a +$29). Costo: ~$0,1 di spread, fee zero. Registro in `data/live/usde_convert.jsonl`.