# code.py - PM_G-1 A/B firmware loader (stable; rarely changes).
#
# The real application is the PRECOMPILED app.mpy (CircuitPython compiles a big .py at boot, which
# fragments the heap and OOMs; a .mpy loads without compiling). app.bak holds the previous known-good
# build. The web editor pushes a new app.mpy to a "trial" slot over USB-MIDI; this loader runs it, and
# if it fails to boot it AUTOMATICALLY ROLLS BACK to app.bak. (Unbrickable: BOOTSEL -> drag a .uf2.)
# app.mpy clears the /trial marker once it has run healthily for ~5s.
import supervisor, os
supervisor.runtime.autoreload = False     # updates reboot explicitly; never auto-restart on our own writes

def _trial():
    try: os.stat("/trial"); return True
    except OSError: return False

try:
    import app                            # runs the application (app.mpy; ends with App().run())
except Exception:
    if _trial():                          # a freshly-pushed build crashed on startup -> roll back
        try:
            os.remove("/app.mpy"); os.rename("/app.bak", "/app.mpy"); os.remove("/trial")
        except Exception: pass
        supervisor.reload()               # reboot into the restored known-good build
    else:
        raise                             # the active build failed unexpectedly (rare) -> on-screen traceback
