DEV Community

Cover image for I Wanted a Guardian. I Kept Building Things I Had to Babysit.

I Wanted a Guardian. I Kept Building Things I Had to Babysit.

Self-Correcting Systems on October 22, 2026

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady. What I Built I have been building agents f...
Collapse
 
saeediphone profile image
Saeed iPhone •

I like the focus on building an agent that takes responsibility for investigating problems rather than simply reporting changes. The emphasis on transparency, evidence, and knowing when not to claim success makes this a much more grounded approach to autonomous AI.

Collapse
 
kenielzep97 profile image
Self-Correcting Systems •

appreciate that. knowing when not to claim success is the part that keeps biting me, its easy to report a change and call it done. taking responsibility for the investigation is the harder half.

Collapse
 
saeediphone profile image
Saeed iPhone •

That’s the difficult part of building reliable autonomous agents: distinguishing between making a change and actually solving the problem. Evidence-based verification and being transparent about uncertainty are what turn an agent from a task runner into something you can genuinely trust.

Thread Thread
 
kenielzep97 profile image
Self-Correcting Systems •

yeah. reporting a change is the easy half. proving the problem is actually gone is the part i keep missing.

Thread Thread
 
saeediphone profile image
Saeed iPhone •

That’s an important distinction. A reliable agent shouldn’t stop at reporting that it made a change; it needs to verify the original issue is resolved and keep checking that it stays resolved. Without that feedback loop, autonomy is still just another thing to babysit.

Collapse
 
innokentyb profile image
Kent Bodrov •

A collector change needs its own migration receipt: old collector version and snapshot, new version and snapshot, and the differences attributable to the collector. Before accepting the new baseline, replay a fixture containing both the timestamp-only change and a real content edit. Otherwise a quiet run after repair may mean the repair absorbed the evidence you wanted to notice.

Collapse
 
kenielzep97 profile image
Self-Correcting Systems •

Neither exists yet. The Guardian edited its collector without saving the old script next to the new one, and nothing replayed a timestamp only change beside a real edit.

The next morning showed a different failure. The run saw my later commit to scs-guardian, then stayed silent because a rule said my own commits don't matter. That rule needs its own test: a change that actually matters, showing up under my name.

Collapse
 
innokentyb profile image
Kent Bodrov •

That makes the author filter a separate failure from the collector. I'd keep authorship as context, then decide whether the change matters. A useful paired fixture would apply the same meaningful edit once under your identity and once under another identity; the alert decision should stay the same. Recording why an item was suppressed would also distinguish a deliberate quiet run from a change the Guardian never observed.

Collapse
 
kenielzep97 profile image
Self-Correcting Systems •

yeah, authorship is context not the verdict. the paired fixture is the clean test, the same meaningful edit under my identity and under another, and the alert has to come out the same or the filter is keying on who instead of what. and recording why something was suppressed is the part i was missing, it separates a deliberate quiet run from a change the guardian never actually observed.

Collapse
 
hershys profile image
Hershys •

Same shape of bug here, different organ. My watcher's rule was "stay quiet unless something changed." The filter was never what bit me. The baseline underneath it was.

I stored snapshots in directories named by count (__998, __999) and sorted them as text, so __1000 came before __999. Past a thousand files a day, every diff was confidently wrong, and a wrong baseline makes a quiet morning look like a calm one. Which is your suppression-log problem one layer down: recording why you stayed quiet only helps if the reference point is trustworthy. Log reasons against a corrupted baseline and you get a tidy audit trail of a lie.

Two things that would have caught mine sooner, in case they help the migration receipts:

  1. Put a header inside the baseline itself (count, newest filename, written at) and refuse to diff when it disagrees with what is actually on disk. A version number tells you the code changed. It does not tell you the reference is intact.
  2. Save atomically. Mine wrote the snapshot in place, one iOS suspend left half a JSON, and every later run died on load. That is the failure shape I fear most now: the guard is broken and it looks exactly like silence.

The script and both postmortems are here if the ugly version is useful to anyone: hershys.mataroa.blog/blog/a-tiny-s...

Collapse
 
kenielzep97 profile image
Self-Correcting Systems •

that last line is the one. on oct 28 the 7am job died on a dns error and six minutes later a follow-up was filed no_change. a failed run and a quiet morning sat next to each other. a header inside the baseline that refuses to diff when it disagrees with disk, plus atomic save, both going on the list.

Collapse
 
hershys profile image
Hershys •

the dns case is the one a header alone misses.

a torn baseline is a file you can see is wrong. a run that never happened leaves a perfectly valid baseline, so the next diff honestly reports no change. failed run and quiet morning end up identical, which is how the tool teaches you to trust silence.

what i ended up with: run status written into the baseline before the diff, and if the last run didn't finish, UNKNOWN instead of no change. unknown is still a report. keep the failure reason next to the timestamp too, because dns and disk full want different reactions and you won't remember which one it was on tuesday.

if you want to compare notes, the version with the header is one file: hershys.mataroa.blog (stdlib only, prints nothing until something moves)