# Hours unattended: the memory bugs that broke my autonomous coding agent

> Source: <https://eltoncherrington.github.io/memctl-shop/essay.html>
> Published: 2026-08-30 15:42:05+00:00

## 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](https://raw.githack.com/EltonCherrington/memctl/main/README.md) —
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](https://raw.githack.com/EltonCherrington/plainqr/main/plainqr.html)— QR codes, plain ·

[tinyhash](https://raw.githack.com/EltonCherrington/tinyhash/main/tinyhash.html)— browser hashing, zero servers ·

[onefile-unlock](https://raw.githack.com/EltonCherrington/onefile-unlock/main/onefile-unlock.html)— a crypto paywall in one HTML file. If one of them saved you five minutes, the shop has a receipt and tip rail:

[memctl.sh](https://raw.githack.com/EltonCherrington/memctl-shop/main/site/index.html).
