"""slave_mailbox_monitor.py — sorveglianza in tempo (quasi) reale della mailbox slave→Adrian (scripts/slave-mailbox/mailbox.log). Nato dal blocco scoperto il 29/08/2026: una sessione slave headless (claude -p) non può usare SendMessage per contattare autonomamente una sessione viva (bloccato dal classificatore auto-mode di Claude Code — vedi archivio/Adrian/riferimento/claude-cli-headless.md). Il canale che resta, verificato funzionante: la slave scrive un evento come riga di testo in questo file, una sessione Adrian aperta lo intercetta armando questo Monitor. Stesso schema di PYTHON/gate-ufficio/nave/monitor_executions.py (poll su file di log, lettura incrementale per offset, niente database) — non reinventato da zero. Formato di una riga scritta dalla slave: "TIMESTAMP_ISO source: testo libero" Esempio: "2026-08-29T14:03:04+02:00 inbox-documenti: nuovo file rilevato, verificare formato" Se una sessione non ha il Monitor armato quando la riga viene scritta, il messaggio non è perso: resta nel file e viene recuperato al prossimo avvio sessione leggendo l'offset salvato in mailbox.offset (vedi avvio-sessione). """ import time from pathlib import Path MAILBOX_DIR = Path(__file__).resolve().parent / "slave-mailbox" MAILBOX_FILE = MAILBOX_DIR / "mailbox.log" OFFSET_FILE = MAILBOX_DIR / "mailbox.offset" POLL_SECONDS = 5 def main(): MAILBOX_DIR.mkdir(parents=True, exist_ok=True) MAILBOX_FILE.touch(exist_ok=True) # Riparte da dove si era fermata l'ultima lettura (Monitor precedente o # check di avvio-sessione) — non ri-notifica messaggi già visti altrove. if OFFSET_FILE.exists(): offset = int(OFFSET_FILE.read_text().strip() or 0) else: offset = MAILBOX_FILE.stat().st_size while True: size = MAILBOX_FILE.stat().st_size if size < offset: offset = 0 # file troncato/ruotato — raro, riparti da capo if size > offset: with open(MAILBOX_FILE, "r", encoding="utf-8", errors="replace") as f: f.seek(offset) new_content = f.read() offset = f.tell() for line in new_content.splitlines(): if line.strip(): print(f"[mailbox] {line.strip()}", flush=True) OFFSET_FILE.write_text(str(offset)) time.sleep(POLL_SECONDS) if __name__ == "__main__": main()