Eight of the 26 drafts sitting in skills/autonomous/ were mined from turns my own machine had written. Not user requests. Scheduler traffic. My system watched itself work, decided the work looked important because it kept happening, and wrote it down as something a person might want again.
The symptom went into my notes on 2026-06-29, in the exact words I would have pasted into a search box: Skill proposer auto-suggests system/scheduled tasks (heartbeat, CPU checks, daily briefings) as reusable skills. I did not find the cause until 2026-09-09.
auto-vodou-board-worker-6bd6db: six identical turns, one draft skill
The proposer clusters recurring multi-step traces and promotes the clusters into skill drafts. You run it with a floor on both dimensions: at least four steps, at least two recurrences. The drafts land as markdown on disk, which is the one merciful part of this story, because it means you can count them with a shell.
$ ls skills/autonomous/*.md | wc -l
26
$ grep -rl 'board-worker\|heartbeat' skills/autonomous/*.md | wc -l
8
The clearest offender was auto-vodou-board-worker-6bd6db, created 2026-06-06 out of six recurring board-worker system-prompt turns. Six occurrences of a prompt string that a background worker replays on a timer, clustered into a "skill" and offered to me as a reusable procedure. It reads like a skill. It has arguments, steps, an expected output. It is my own cron schedule with a slug.
I filed it as a threshold problem, and I was wrong for ten weeks
My first read was that --min-recurrence 2 was too permissive, and that the fix lived somewhere in the tuning. That framing kept the bug alive from late June to September, because it is exactly backwards. Machine turns are the most repetitive rows in the store, byte for byte, forever. Raising the recurrence floor deletes the ragged human clusters first and leaves the cron traffic standing. Every threshold I could have raised would have improved the precision of the wrong thing.
The ranking function was not broken. It was doing what recurrence mining is supposed to do. TraceCompiler states the premise plainly: a recurring intent is issued again and again, and the regularity is the value. True, and it is why the failure is structural rather than a bad heuristic. A scheduled job is a recurring intent with a perfect delivery record. If repetition is your signal, the machine is your best contributor.
The blast radius stayed small for an unrelated reason: proposed automations in my system are inert until a human clicks Enable. Nothing ran. It was a corpus poisoning incident with the trigger removed, which is the only kind you get to write up calmly.
The class: a learner whose best signal is repetition, and a log that never records who typed
Strip the nouns and this is any system that mines its own logs to learn, where the log does not record who caused each row. It shows up in conversation-memory stores that a background job writes into alongside real users, in RAG corpora indexed from a docs directory that includes app-generated pages, and in fine-tune sets scraped from production traces where retries and health checks look like traffic. The MCP server that logs its own tool calls back into the vector database it queries is the purest version.
The standard advice is source-class tagging at ingestion. Tianpan's provenance-debt post is right about the important half: stamp it at write time, because recovering it later is expensive and incomplete (I got to confirm that experimentally, since eight already-written drafts carry no field explaining where they came from). What that advice does not cover is my case: the bytes were written by a human. I wrote that board-worker system prompt myself. Any classifier looking at content, and any hand-maintained "do not capture" blocklist, files it as human_primary, correctly. The thing that made it poison was not authorship. It was that a timer initiated the turn.
Every row a learning loop reads must record which actor initiated the turn, stamped by the writer at insert time, and the loop's candidate query must filter on that column instead of inferring provenance from content. Either your schema has that column and your query has that WHERE clause, or it does not.
Rank your own message table by repetition, then look at the clock
Five minutes, your stack, no tools of mine. First ask whether the column exists at all:
-- If this errors, you already have your answer.
SELECT actor_kind, COUNT(*) FROM messages GROUP BY 1;
-- failing: Error: no such column: actor_kind
-- What your miner would rank first:
SELECT substr(replace(content, char(10), ' '), 1, 60) AS head,
COUNT(*) AS n, COUNT(DISTINCT session_id) AS sessions
FROM messages WHERE role = 'user'
GROUP BY 1 HAVING n > 2 ORDER BY n DESC LIMIT 20;
-- The cheap tell, if you have no provenance to filter on:
SELECT strftime('%M', created_at) AS minute, COUNT(*) AS n
FROM messages GROUP BY 1 ORDER BY n DESC LIMIT 5;
Passing looks like top rows in varied human phrasing, n in the low single digits, spread across many sessions, and a flat minute histogram. Failing looks like byte-identical heads whose n matches a cron period (24 for something hourly over a day), often with sessions at 1, and one minute of the hour holding a visible share of all traffic. Humans do not send 40% of their messages at :00.
If your top-20 by repetition is machine traffic, that is your few-shot pool, your memory candidates and your eval set, ranked in that order, today.
The rule I would give a stranger: provenance is a write-time column, not a read-time heuristic. If your learner cannot answer "who initiated this row" with a WHERE clause, it will eventually teach itself your cron schedule and present it to you as a skill.
Source: My skill miner learned from my cron jobs: 8 of 26 drafts by Chad Priest, from Building Vodou in Public.
Top comments (0)