7.3 KiB
Deep Research Audit: /remind Skill
Datum: 2026-06-02
Model: GLM-5.1:cloud
Scope: SKILL.md, remind_edit.py, remind_send.py, random_times.py, testy, reminder.yaml, .reminder_state.json, log, crontab
🔴 Kritické problémy
1. Žádný update příkaz
remind_edit.py má jen list, add, remove. Když chceš změnit čas existujícího reminderu, musíš ho smazat a vytvořit znovu. To je nebezpečné — remove matchuje substring, takže při recreate můžeš trefit špatný záznam nebo vytvořit duplikát.
Návrh: Přidat update --keyword "..." --cron/--at/--random-* příkaz, který najde reminder a upraví jen zadaná pole.
2. at remindery se nikdy nesmažou (no garbage collection)
Jednorázové at remindery zůstávají v reminder.yaml navždy. Po odeslání se jen přestanou spouštět, ale leží v YAML a loadují se každý minutovým cronem. Po čase tam bude stovky mrtvých záznamů.
Návrh: remind_send.py by měl po úspěšném doručení at reminderu zapsat flag nebo rovnou zavolat remind_edit.py remove. Nebo lépe — přidat purge subcommand, který smaže všechny at remindery s at_time < now.
3. Žádné stabilní ID — remove matchuje substring
remove --keyword "boty" by smazal "objednat boty xshoes", ale taky "koupit boty pro dědu". Substring match na textu je křehký.
Návrh: Přidat id pole (hash nebo UUID) přiřazené při add. remove i update by primárně pracovaly s --id. --keyword by zůstal jako fallback.
4. Deduplikace přes SHA1(text)[:8] — kolize a křehkost
.reminder_state.json klíč je hashlib.sha1(text.encode())[:8] — 4 bajty hex. Při ~65k reminderů je kolize pravděpodobná. Horší: když se text změní (i jen překlep), dedup key se změní a reminder se odešle znovu.
Návrh: Použít stabilní id z bodu 3 jako klíč do state. SHA1[:8] zahodit.
🟡 Střední problémy
5. Hardcoded CHAT_ID v remind_send.py
CHAT_ID = "8826147089" je natvrdo v kódu. Když se změní uživatel nebo přidá druhý, musí se upravovat zdroják.
Návrh: Číst chat_id z config.json (tam už je token), nebo z reminder.yaml jako globální default_chat_id.
6. Žádná validace at časů v budoucnosti
remind_edit.py přijme --at "2020-01-01T00:00:00" bez chyby. Zápis v minulosti nedává smysl a nikdy se nespustí.
Návrh: Validovat at > now() v cmd_add. Případně alespoň varování na stderr.
7. Žádný max-retry / TTL pro neodeslané remindery
Když Telegram API vrátí chybu, remind_send.py zkusí znovu příští minutu — ale jen pokud last state nebyl nastaven. Když selže 100x po sobě, zkusí to 100x. Žádný TTL ani exponential backoff.
Návrh: Přidat retry count do state. Po 3 selháních označit jako failed a přestat zkoušet. Nebo jednoduše: po 5 minutách od first fire time přestat retryovat.
8. Identity check bug v cmd_remove
data["reminders"] = [r for r in data["reminders"] if r is not removed]
is not je identity check. Funguje, protože matches[0] je reference na stejný dict v seznamu, ale je to křehké — jakýkoliv refaktoring (deep copy, reload) to rozbije.
Návrh: Použít index nebo id-based filter.
9. Chybí dokumentace k at_times (multi-at)
SKILL.md dokumentuje --at jako "repeatable", ale remind_send.py zpracovává at_times pole, zatímco SKILL.md ho nezmíní jako samostatný koncept. Uživatel (nebo LLM) může být zmatený.
Návrh: Doplnit SKILL.md o příklad multi-at.
🔵 Zlepšení kódu
10. Přechod z YAML na SQLite
YAML je lidsky čitelný, ale:
- Atomic write přes
.tmp+os.replaceje správný, ale zbytečně složitý - YAML nemá schema, snadno se rozbije ruční editací
- Dotazy (list, search) vyžadují full load
Návrh: Přesunout data do db/reminders.sqlite (konvence db/*.sqlite). YAML nechat jako read-only export nebo zahodit. remind_edit.py by pracoval s SQLite, remind_send.py taky. Výhody: ID autoincrement, atomicity zdarma, snadný search, žádný parse overhead.
11. Cachování Telegram tokenu
_telegram_token() čte a parsuje config.json každou minutu. Soubor se nemění.
Návrh: Načíst jednou při startu, cachovat v modulu. Nebo ještě lépe — environment variable TELEGRAM_BOT_TOKEN.
12. Log enrichment
reminder.log má jen timestamp text. Chybí: delivery status, fire time vs actual send time, reminder ID.
Návrh: Formát: {ts} {id} {fire_time} {status} {text}
13. --dry-run flag pro add
Užitečné pro LLM skill workflow — ukáže, co by se přidalo, bez zápisu.
14. Test coverage — chybí testy pro remind_edit.py a remind_send.py
Testy pokrývají jen random_times.py. remind_edit.py (CRUD) a remind_send.py (dedup, fire detection) nemají žádné testy.
Návrh: Přidat unit testy pro:
cmd_adds různými kombinacemi flagůcmd_removes 0/1/N matches_due_fires různými typy reminderů- Dedup state management
🟢 Chybějící funkce
15. Pause / disable reminder
Nemáš způsob jak reminder dočasně vypnout bez smazání. Běžný use case: "nech mě týden na pokoji".
Návrh: Přidat enabled: true/false pole. remind_send.py by skipoval enabled: false. Příkaz remind_edit.py pause --id X / resume --id X.
16. Cron s end date
Cron remindery běží navždy. Chybí until datum pro cron (podobně jako random má from/until).
Návrh: Přidat until pole na úroveň reminderu. remind_send.py by po until datumu reminder přeskočil.
17. Snooze
Když reminder přijde a uživatel není připraven, nemá jak ho odložit. To by vyžadovalo interakci s Telegram botem (callback button), což je mimo současný scope, ale je to přirozené rozšíření.
18. list --due nebo list --next
Užitečné zobrazit jen remindery, které se spustí v následujících N hodin. SKILL.md to neumožňuje.
Návrh: Přidat list --due-within 2h nebo list --next 5.
19. Per-reminder timezone
SKILL.md říká "Timezone is always Europe/Prague". To je OK pro jednoho uživatele, ale kód je tight-coupled — TZ je konstanta v remind_send.py. Pro multi-user by to muselo být konfigurovatelné.
📋 Prioritizovaný implementační plán
| Priorita | Co | Proč |
|---|---|---|
| P0 | Stabilní ID + dedup fix (body 3, 4) | Bez toho hrozí kolize a duplikátní doručení |
| P0 | Garbage collection at reminderů (bod 2) |
YAML poroste donekonečna |
| P0 | Identity check fix v remove (bod 8) | Tichý bug, dnes funguje náhodou |
| P1 | update příkaz (bod 1) |
Zásadní UX zlepšení, snižuje riziko chyb |
| P1 | Validace at v budoucnosti (bod 6) |
Prevence nesmyslných vstupů |
| P1 | Retry TTL (bod 7) | Prevence nekonečných retry |
| P2 | SQLite backend (bod 10) | Architektonické zlepšení, ale není urgentní |
| P2 | Testy pro edit/send (bod 14) | Spolehlivost |
| P2 | pause/resume (bod 15) |
Užitečná funkce |
| P2 | until pro cron (bod 16) |
Užitečná funkce |
| P3 | Chat ID z configu (bod 5) | Multi-user příprava |
| P3 | Log enrichment (bod 12) | Debugovatelnost |
| P3 | --dry-run (bod 13) |
Vývojářská ergonomie |
| P3 | list --due (bod 18) |
Nice-to-have |