MISURATO oggi durante la revisione: `trades_db.py --help` non stampava l'uso, cadeva in sync() e riscriveva meta.ultimo_sync. Nessuno dei 18 script di scripts/live/ usava argparse: un flag sbagliato era il ramo else. Su journal.py avrebbe scritto pagina e riga di DB, su analista.py avrebbe speso una chiamata al modello e mandato un Telegram. - src/live/cli.valida: prima istruzione di ogni __main__, prima di connect()/sync/rete. --help -> 0 con l'uso; flag ignoto, valore mancante o posizionale -> 2 con l'elenco dei previsti (P4). NIENTE argparse: cambierebbe messaggi, codici d'uscita e --help di script che il cron gia' chiama. - 18 script cablati (i 3 che scrivono + 14 + cc01), flag invariati. - tests/test_cli_flag.py (30): elenco DERIVATO dalla cartella (P1), valida come prima istruzione, uso che documenta i flag, e i flag che il CRON usa davvero restano accettati (P15/P16); end-to-end su --help e flag ignoto con trades.db non toccato (M15). Verificato a mano: monitor_health --quiet, trades_db --sync --quiet, book_execute dry-run. Debito §5.15, primo passo: balance_watch (orario) registra `usde_usdc` a ogni campione — None con la ragione se illeggibile, mai 1,0. Il cablaggio nel bound quando la serie ha storia. Pulizia dalla revisione: tests/helpers.carica_script al posto della 15a copia del loader importlib (5 file del libro live); il fill di prova via upsert_fills invece di un INSERT che lasciava verified NULL; asserzioni non ancorate al padding; movimenti_capitale accetta le righe gia' lette (una SELECT invece di due ai due lati di una scrittura del cron). Test 910 verdi (+52). Diario 2026-09-02c. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XDJsH3iDSaBns3ccpPBwiu
4.1 KiB
2026-09-02 — Un flag sconosciuto non è l'azione di default
Scritto fra le 15:45Z e le 16:05Z. Il difetto è stato misurato, non ipotizzato: la revisione del
codice di questa sessione ha eseguito trades_db.py --help come sonda di tempi e lo ha visto
sincronizzare il DB.
1. Il difetto
Nessuno dei 18 script di scripts/live/ usava argparse. Leggevano gli argomenti così:
if "--reconcile" in args: ...
elif "--report" in args: ...
else: sync() # <- qui finiva QUALUNQUE cosa non riconosciuta
Un flag sbagliato non era un errore: era il ramo finale. Costo osservato e costi possibili:
| script | --help faceva |
gravità |
|---|---|---|
trades_db.py |
sync(): riscriveva meta.ultimo_sync |
osservato oggi, danno nullo |
journal.py |
scriveva la pagina di oggi e una riga nel DB | non osservato, ma scrive |
analista.py |
spendeva una chiamata al modello e mandava un Telegram | non osservato, ma spende |
2. La riparazione, e perché non è argparse
src/live/cli.valida(nome, uso, flag=..., con_valore=...), chiamata come prima istruzione di
ogni blocco __main__ — prima di connect(), prima del sync, prima della rete.
--help/-h→ stampa l'uso, esce 0;- flag non dichiarato, o valore mancante, o posizionale → stderr con cosa e cosa si poteva (P4), esce 2 (errore d'uso, distinto dall'1 con cui gli script segnalano un esito negativo);
- tutto il resto invariato.
Argparse no. Cambierebbe messaggi d'errore, codici d'uscita e il comportamento di --help su
18 script che il cron già invoca: romperebbe ciò che gira per riparare ciò che non gira mai. Qui
serviva l'opposto — lasciare intatti i flag esistenti e rifiutare solo l'ignoto.
3. Il test guarda entrambe le metà del contratto
tests/test_cli_flag.py, 30 test:
- l'elenco degli script si deriva dalla cartella (P1): uno script nuovo che legge
sys.argva mano e non chiamavalidafa fallire il test, non passa inosservato perché nessuno ha aggiornato una lista; validadev'essere la prima istruzione di__main__(uscire dopo l'effetto non è uscire);- l'uso deve nominare i flag che lo script accetta;
- i flag che il cron usa davvero devono restare accettati (P15/P16, letti dai
cron_*.sh): una guardia che ferma il libro di bordo la notte stessa sarebbe peggio del difetto; - end-to-end sui tre script che scrivono:
--helpesce 0 e non toccatrades.db; un flag ignoto esce 2 e non lo tocca (M15: il caso che ha causato il difetto, non un caso vicino).
Verificato a mano anche il contrario: monitor_health.py --quiet, trades_db.py --sync --quiet
e book_execute.py in dry-run escono 0 come prima.
4. Il resto della sessione
Indice USDE orario (debito §5.15, primo passo). Il classificatore dei movimenti di capitale
confronta due letture di equity a un'ora di distanza e il suo bound guarda solo BTC/ETH, mentre il
31% dell'equity è USDE: un depeg sarebbe scorporato come un prelievo. usde_watch registra
l'indice una volta al giorno — troppo rado. Ora balance_watch (orario, sola lettura) lo registra
a ogni campione, None con la ragione se non leggibile, mai 1,0. Il cablaggio nel bound viene
quando la serie ha storia: prima serve il dato, poi la regola.
Pulizia lasciata dalla revisione. tests/helpers.carica_script sostituisce la dodicesima copia
del caricatore importlib (15 in giro, con nomi di modulo diversi per lo stesso file e differenze
silenziose su sys.modules); il fill di prova si scrive con upsert_fills invece che con un
INSERT a mano che lasciava verified NULL, una forma che la produzione non produce; le
asserzioni sul testo del report non sono più ancorate al padding; movimenti_capitale accetta le
righe già lette, così il report non fa due SELECT sulla stessa tabella a un'ora del cron — due
letture ai due lati di una scrittura descriverebbero due istanti diversi.
5. Cosa NON ho fatto
- I loader
importlibdei test sulla ricerca (moduli inscripts/research/) restano come sono: sono a livello di modulo, con radici diverse, e toccarli non ripara niente. - Il bound USDE nel classificatore: manca la storia, non il codice.