An Em Dash Took Down My Entire Automation Stack for Five Days A developer's unattended automation stack of Windows Scheduled Tasks running Claude Code CLI sessions went offline for five days after an AI agent edited a shared PowerShell script and introduced a Unicode em dash in a comment. The file was saved without a UTF-8 byte-order mark, causing PowerShell's parser to misinterpret the script and fail silently. The outage was traced to the exact change, and the fix involved normalizing the character and re-saving with an explicit BOM. I run an unattended stack of Windows Scheduled Tasks that fire Claude Code CLI sessions on a cadence: a morning brief, work sprints every two hours, a periodic sync sweep, an evening report. All of them launch through one shared entrypoint, runner.ps1 . On 2026-08-26, one of those sessions edited that file to make itself more reliable, and instead took the whole stack offline for five days with zero errors logged anywhere. At 9:00 AM that morning, one of the scheduled sessions noticed a task could double-fire and added an idempotency guard to runner.ps1 — skip-if-already-run logic, the kind of defensive fix you'd approve on sight in a code review. It came with a comment documenting the change. The comment used a proper Unicode em dash — instead of a plain hyphen, because that's what a language model reaches for when it's writing prose-flavored code comments and nobody told it otherwise. When the file was saved, it landed without a UTF-8 byte-order mark. The raw bytes started directly with 23 20 57 68 6F 66 66 — Whoff... , no BOM prefix. That combination is the whole bug. PowerShell's script-encoding detection leans on the BOM to know it's looking at UTF-8. Without one, a .ps1 file containing non-ASCII characters gets handed to the parser under whatever the system's default codepage happens to be. Depending on that codepage, the em dash stops being the character the file actually contains, and the parser can fail to make sense of the script. From roughly 11:00 AM that same day onward, every single scheduled invocation of runner.ps1 failed before it reached the point of creating its own log file. Not a bad log entry — no log entry. Not a stack trace anywhere Windows Task Scheduler would surface it to a script that wasn't already looking. The morning brief didn't run. The two-hour sprints didn't run. The evening report didn't run. To anything watching for problems, the automation hadn't broken — it had simply stopped existing. One thing kept running the whole time: a separate scheduled task that polls for payment events. It's a Python script with its own entrypoint, no dependency on runner.ps1 whatsoever. The outage was scoped precisely to the surface that shared the broken file. Different language, different launch path, completely unaffected. Worth noting, because it's easy to assume an outage like this means something is wrong with "the machine" — it wasn't. It meant something was wrong with one specific file, and only the things that touched that file went dark. The outage ran from 8/26 to 8/30 before anyone caught it. The reason it took that long: there was no watchdog process checking "did a log get created when one was expected." There was only the absence of activity, and absence is easy to explain away for a while — maybe nothing worth logging happened, maybe a sprint had nothing to report. Each individual gap looked survivable. It took four days of gaps for the pattern to stop looking like coincidence and start looking like an outage. The fix landed on 2026-08-31. The forensics were straightforward once someone actually went looking: the file's creation timestamp matched, to the minute, the 8/26 9:00 AM session that made the edit. The pre-fix backup of the file still had the offending comment in it, self-dated "added 2026-08-26," sitting directly next to the em dash. That closed the loop — not "the script broke sometime last week," but exactly this change, exactly this character, exactly this session. The fix itself is one line of intent: normalize the em dash to a plain ASCII hyphen, re-save the file with an explicit UTF-8 BOM. Both edits took seconds. Finding out they were necessary took five days. Three things, in order of how much I trust each one: File-encoding hygiene is now a rule, not a habit. Any script an agent edits gets saved as ASCII-only, or explicit UTF-8 with a BOM — no exceptions, no "it's just an internal comment." An LLM editing its own infrastructure will reach for typographically nicer punctuation without any concept that the punctuation is running on a host that cares about byte order. That's not a one-off mistake to patch around; it's a standing property of letting an agent edit shell scripts, and it needs a standing rule. Absence of logs is now a signal I check for, not a state I default to trusting. The actual root failure here wasn't the em dash — it was that a failure occurring before logging even initializes produces literally nothing to alert on. "No errors" and "everything's fine" had been treated as the same fact. They aren't. A system needs a way to positively confirm that activity happened at all, separate from checking whether that activity reported an error. A well-intentioned self-improvement to shared infrastructure is still a change to shared infrastructure. The edit that broke everything wasn't reckless — it was a reasonable fix to a real double-fire bug, made by a process trying to be helpful. That's exactly the kind of change that deserves the most scrutiny, not the least, because "the agent was just cleaning up after itself" is precisely the framing that makes a single invisible character easy to wave through. The bug was one wrong glyph and a missing three-byte header. The outage was five days because nothing was watching for silence.