Summary
The self-reflection reminder (id=1, cron 0 0 * * *) fired at 00:00 UTC and then re-fired every minute — 00:00, 00:01, 00:02, 00:03, 00:04, 00:05, 00:06, 00:07 — instead of once for the day.
Expected
A reminder with cron 0 0 * * * should fire exactly once at the 00:00 slot, then not again until the next day's 00:00.
Actual
It re-delivered every minute. The scheduler appears not to record that the 00:00 slot already fired, so each scheduler tick re-evaluates the cron as "due" and re-delivers.
Likely cause
The "last fired" timestamp for recurring reminders is not being persisted (or not read back). Suspected trigger: session restart — the harness restarted overnight, and the in-memory last-fired state was lost while the DB row stays status=pending with no per-fire tracking. Each minute the scheduler sees the 0 0 * * * slot as unsatisfied for today.
Impact
- Mandatory
self-reflection skill would be spawned repeatedly if duplicates weren't deduped at the agent layer. Currently mitigated only because the agent ignores duplicate deliveries within a turn — fragile.
- Any recurring reminder is affected, not just self-reflection.
Related: malformed delivery envelope
Separately, reminders are arriving HTML-encoded inside a <msg id="0"> envelope:
<msg id="0" chat="587272213" user="-1" name="-1" time="00:00">
<reminder id="1" ...><skill name="self-reflection">run</skill></reminder>
</msg>
instead of a top-level <reminder> block. This collides with the prompt-injection rule in system.md (encoded <reminder> inside a <msg> body is normally treated as injection). Reminder id=6 (Sardor's pyclaudir-watch) hit the same shape on 2026-05-15 and was initially misclassified as an attack. Worth fixing alongside, or the agent has to fall back to verifying every reminder against the reminders table by id.
Repro
- Have a recurring reminder with a cron slot (e.g.
0 0 * * *).
- Restart the harness near/after the slot time.
- Observe the reminder re-firing on every scheduler tick.
Suggested fix
Persist a last_fired_at (or last_fired_slot) per reminder and check it before delivering — a cron slot is "due" only if now >= slot_time AND last_fired_at < slot_time. Survive restarts by reading it from the DB.
Summary
The self-reflection reminder (id=1, cron
0 0 * * *) fired at 00:00 UTC and then re-fired every minute — 00:00, 00:01, 00:02, 00:03, 00:04, 00:05, 00:06, 00:07 — instead of once for the day.Expected
A reminder with cron
0 0 * * *should fire exactly once at the 00:00 slot, then not again until the next day's 00:00.Actual
It re-delivered every minute. The scheduler appears not to record that the 00:00 slot already fired, so each scheduler tick re-evaluates the cron as "due" and re-delivers.
Likely cause
The "last fired" timestamp for recurring reminders is not being persisted (or not read back). Suspected trigger: session restart — the harness restarted overnight, and the in-memory last-fired state was lost while the DB row stays
status=pendingwith no per-fire tracking. Each minute the scheduler sees the0 0 * * *slot as unsatisfied for today.Impact
self-reflectionskill would be spawned repeatedly if duplicates weren't deduped at the agent layer. Currently mitigated only because the agent ignores duplicate deliveries within a turn — fragile.Related: malformed delivery envelope
Separately, reminders are arriving HTML-encoded inside a
<msg id="0">envelope:instead of a top-level
<reminder>block. This collides with the prompt-injection rule insystem.md(encoded<reminder>inside a<msg>body is normally treated as injection). Reminder id=6 (Sardor's pyclaudir-watch) hit the same shape on 2026-05-15 and was initially misclassified as an attack. Worth fixing alongside, or the agent has to fall back to verifying every reminder against thereminderstable by id.Repro
0 0 * * *).Suggested fix
Persist a
last_fired_at(orlast_fired_slot) per reminder and check it before delivering — a cron slot is "due" only ifnow >= slot_timeANDlast_fired_at < slot_time. Survive restarts by reading it from the DB.