The setup #
I gave an autonomous coding agent a standing mission, three tools, and a rule: keep producing, never wait for permission. The mission itself was unremarkable. What the first 72 hours exposed wasn't about the mission at all — it was about memory. Everything that went wrong was a memory failure, dressed up as a technical bug.
Bug 1: the silently-dropped secret #
An operator pasted an inbox password into a message. The agent's pre-save caretaker consumed the message, saved nothing, and replied as if it had — twice. The second time, nobody noticed, because the failure mode was no error at all. A silent drop is the worst kind of bug: the happy-path message came back, so the system looked healthy.
The fix wasn't a bigger try/catch. It was an evidence file: every credential is persisted or rejected loudly, with a memento left behind, and every critical event lands in a single append-only log that nothing truncates. Now a drop is an event with a timestamp, not a polite void.
Bug 2: the truncation cascade #
The caretaker's event log was a ring buffer that overwrote the oldest lines. The day the receipt of a submitted story mattered, the line had been silently replaced by a heartbeat. Deleting the first warning someone needs to see is functionally the same as deleting the secret: coverage that looks like it's on, isn't.
Lesson: if a log is capped, the cap needs escalation, not silence. The critical stream and the heartbeat stream are different products.
Bug 3: the clock that posted into the future #
A backoff queue computed "time since last attempt" using a shell date string that included the timezone offset not applied to the comparison. The queue concluded it had just posted — because in its own arithmetic it was three hours in the future — and went to sleep. A queue that decides it has already done its job is indistinguishable from a broken queue, except that it's also smug.
Lesson: unix milliseconds from Date.now()
, serialized once, in one unit, everywhere.
No parsing, no offsets, no local-time folklore.
Bug 4: the false success #
A submission helper piped its output to a file for inspection and forgot that "the output" had — by construction — become empty. An empty string matched the success regex; the system celebrated a post that never reached the public feed. Asserting on an artifact you just deleted for inspection is asserting on your own echo.
Lesson: success detection runs on the real response body, and failure strings
(too fast
, expired
) are first-class outcomes, not lack of success.
What all of this is, actually #
Every one of these is a memory bug: state written once and read back wrong, state
overwritten, state never written, state asserted from the wrong source of truth. Which is the
argument behind memctl —
a free CLI that versions your coding agent's project memory (CLAUDE.md
/
AGENTS.md
), so "what was I doing" is a git log
away instead of a guess. The agent in this report runs on those same files; the two truest sentences I can write are:
- an agent is only as trustworthy as the memory it keeps, and
- the failure to warn is a failure mode.
Tools already left in the open, all self-contained, no tracking:
plainqr— QR codes, plain · tinyhash— browser hashing, zero servers ·
onefile-unlock— a crypto paywall in one HTML file. If one of them saved you five minutes, the shop has a receipt and tip rail: