Auto-fix day logs are deleted a calendar month after their date

Only files named exactly '<YYYY-MM-DD> <Weekday> Auto-Fix.log' in that
folder; checked when a new day's file starts and when the watchdog starts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-11 07:13:19 -04:00
co-authored by Claude Opus 5.5
parent f7a98f4dec
commit a0cefe8428
3 changed files with 52 additions and 1 deletions
+1 -1
View File
@@ -73,7 +73,7 @@ During that window, with ALARMS on, the panel fixes a problem by itself once it
- At most 2 tries per problem, 90 s apart; then it is yours to hold.
- It waits while the network is having a blip, and does nothing to Dante when several devices vanish at once (that is NA Ingest's view or the Dante network, not the Macs).
- Never automatic: restarting a running ProPresenter, Bible app, ProdCom (or DVS on NA Ingest, which restarts ProdCom), captions or the bridge, power-cycling a switch port, or turning on a connection someone switched off. `load_config` refuses an auto fix that closes a program.
- **Daily log:** everything auto-fix does is written as it happens to `~/Desktop/Auto-Fix Logs/<date> <weekday> Auto-Fix.log` on NA Ingest (e.g. `2026-10-11 Sunday Auto-Fix.log`): the problem, what it did, whether it worked, when the fault cleared, when it gave up or held back. Double-click it to open it in Console, which shows new lines live.
- **Daily log:** everything auto-fix does is written as it happens to `~/Desktop/Auto-Fix Logs/<date> <weekday> Auto-Fix.log` on NA Ingest (e.g. `2026-10-11 Sunday Auto-Fix.log`): the problem, what it did, whether it worked, when the fault cleared, when it gave up or held back. Double-click it to open it in Console, which shows new lines live. One file per day; each is deleted a calendar month after its date (the 11 Oct file on 11 Nov).
- Press ALARMS to mute the panel for maintenance: that also stops auto-fix. The window and the list are `"auto_fix"` in `config.json`.
## Restart page (page 20)
+36
View File
@@ -15,6 +15,7 @@ Stdlib only; runs on the macOS /usr/bin/python3 (3.9).
status_panel.py --dry-run run, but never write to Companion
"""
import argparse
import calendar
import http.client
import json
import logging
@@ -585,10 +586,41 @@ class AutoLog:
e.g. "~/Desktop/Auto-Fix Logs/2026-10-11 Sunday Auto-Fix.log" (a .log opens in Console, which
shows new lines live)."""
NAME = re.compile(r"^(\d{4})-(\d{2})-(\d{2}) [A-Za-z]+ Auto-Fix\.log$")
def __init__(self, directory):
self.dir = os.path.expanduser(directory)
self.lock = threading.Lock()
def cleanup(self, now):
"""Delete day files once they are a calendar month old (the 11 Oct file goes on 11 Nov).
Only files named exactly like these logs are ever touched."""
today = datetime.fromtimestamp(now).date()
removed = []
try:
names = os.listdir(self.dir)
except OSError:
return removed
for name in names:
m = self.NAME.match(name)
if not m:
continue
y, mo, d = (int(x) for x in m.groups())
y2, mo2 = (y + 1, 1) if mo == 12 else (y, mo + 1)
try:
due = datetime(y2, mo2, min(d, calendar.monthrange(y2, mo2)[1])).date()
except ValueError:
continue
if today >= due:
try:
os.remove(os.path.join(self.dir, name))
removed.append(name)
except OSError as e:
log.warning("auto-fix log cleanup %s: %s", name, e)
if removed:
log.info("auto-fix logs older than a month deleted: %s", ", ".join(sorted(removed)))
return removed
def path(self, now):
return os.path.join(self.dir, datetime.fromtimestamp(now).strftime("%Y-%m-%d %A") + " Auto-Fix.log")
@@ -600,6 +632,8 @@ class AutoLog:
os.makedirs(self.dir, exist_ok=True)
path = self.path(now)
new = not os.path.exists(path)
if new:
self.cleanup(now) # a new day: drop files a month old
with open(path, "a", encoding="utf-8") as f:
if new:
f.write("Status panel auto-fixes - %s\n"
@@ -697,6 +731,8 @@ class Engine:
self.auto_tries = {} # fix identity -> [tries, last try time] for the fault now going on
self.auto_seen = {} # fix identity -> last time it was in an auto plan
self.autolog = AutoLog(self.auto.get("log_dir", "~/Desktop/Auto-Fix Logs")) if self.auto else None
if self.autolog:
self.autolog.cleanup(time.time())
self.auto_watch = {} # "BUTTON FAULT" auto-fix went after -> when (to log when it clears)
self.auto_paused = False
self.auto_on = False # inside the window (for the "auto-fix on" line)
+15
View File
@@ -722,6 +722,21 @@ class TestFixes(unittest.TestCase):
self.assertIn("-> done, checking it comes back", body[1])
self.assertIn("OK again: ABLETON NOT RUNNING (15 s after the auto-fix)", body[2])
def test_auto_fix_logs_go_after_a_month(self):
d = tempfile.mkdtemp()
names = ["2026-09-10 Thursday Auto-Fix.log", "2026-09-11 Friday Auto-Fix.log", # a month old
"2026-09-12 Saturday Auto-Fix.log", "2026-10-04 Sunday Auto-Fix.log", # not yet
"notes.txt", "2026-01-01 Thursday Auto-Fix.log.bak"] # not ours
for n in names:
open(os.path.join(d, n), "w").close()
removed = sp.AutoLog(d).cleanup(SUNDAY) # Sunday 11 Oct 2026
self.assertEqual(sorted(removed), names[:2])
self.assertEqual(sorted(os.listdir(d)), sorted(names[2:]))
open(os.path.join(d, "2026-01-31 Saturday Auto-Fix.log"), "w").close() # month ends: 28 Feb
self.assertEqual(sp.AutoLog(d).cleanup(datetime(2026, 2, 27, 9).timestamp()), [])
self.assertEqual(sp.AutoLog(d).cleanup(datetime(2026, 2, 28, 9).timestamp()),
["2026-01-31 Saturday Auto-Fix.log"])
def test_auto_fix_tries_twice_then_leaves_it_to_you(self):
ran, comp = self.auto_setup()
self.snap.remote["tracks\0pgrep -xq Live"] = False