Porting the Self-Fixing Bug Workflow to a Bot With No Sentry, No Railway, No CI Runner A developer ported TribeMarkets' self-fixing production bug workflow to python-discord-scheduler-bot, a Python Discord bot for scheduling Rainbow Six Siege gaming sessions that runs as a systemd service on a mini PC, replacing Bugsink, Sentry, Railway, and a GitHub Actions CI runner with a rotating app.log file and a single git clone. The port required re-deriving every guardrail from the original design, including fingerprinting log lines by stripping quoted values and numbers before hashing and scoping occurrence counts to the current release's short git SHA. The checkpoint mechanism tracks the log file's inode plus a byte offset and walks both rotated backups on an inode mismatch to avoid silently dropping records between scheduled runs. ← All technical posts https://patrickdesjardins.com/blog Porting the Self-Fixing Bug Workflow to a Bot With No Sentry, No Railway, No CI Runner Posted on: I previously wrote about TribeMarkets' self-fixing production loop https://patrickdesjardins.com/blog/building-tribemarkets-with-ai-architecture-and-self-fixing-production : a scheduled GitHub Actions workflow that reads grouped errors from Bugsink and, under a long list of guardrails, prepares a draft pull request for a repeatable production bug. I wanted the same closed loop for a much older, much less glamorous project: python-discord-scheduler-bot https://github.com/MrDesjardins/python-discord-scheduler-bot , a Python Discord bot that schedules gaming sessions for a Rainbow Six Siege community, running as a systemd service on a mini PC under my desk. The problem is that almost none of TribeMarkets' https://tribemarkets.com/ infrastructure exists here. There is no Bugsink or Sentry. Errors go to a rotating app.log file written by Python's own logging module. There is no Railway. The bot runs directly on a box I SSH into. There is no GitHub Actions runner with a clean, disposable checkout on every run. There is one git clone, and it's the same one the bot process reads its code from. Every guardrail from the original design had to be re-derived for a much more fragile execution environment, and two of the bugs I hit while building it were more interesting than the feature itself. Sourcing incidents from a log file instead of an error tracker Bugsink hands you pre-grouped issues with occurrence counts for free. A raw app.log doesn't group anything, it's just lines. The bot already logs in a consistent format see deps/log.py , so the first job is turning that into something fingerprintable: LOG LINE RE = re.compile r"^ ?P