Files
nanobot-runtime/results/remind-skill-top5-priorities-2026-06-02.md
2026-06-10 06:39:52 +02:00

87 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# /remind Skill — Top 5 Priorities (Merged from Two Audits)
**Datum:** 2026-06-02
**Model:** GLM-5.1:cloud
**Zdroje:** `results/2026-06-02_remind-skill-analysis-and-improvements.md` + `results/remind-skill-audit-2026-06-02.md`
---
## 1. Stabilní ID + dedup fix (nahradit SHA1[:8] + substring match)
**Problém:** Dva propojené bugy:
- `.reminder_state.json` používá `SHA1(text)[:8]` jako dedup klíč — 4 bajty hex, kolize při ~65k reminderů. Změna textu (i překlep) vytvoří nový klíč → duplikátní doručení.
- `remove` matchuje substring — `remove --keyword "boty"` smaže i "koupit boty pro dědu".
- `cmd_remove` používá `is not` identity check — funguje jen díky referenční shodě, po refaktoringu (deep copy, reload) se rozbije.
**Řešení:**
- Přidat `id` pole (UUID nebo short hash z text+timestamp) přiřazené při `add`.
- `remove` i `update` primárně přes `--id`, `--keyword` jako fallback.
- State file klíč → stabilní `id` místo SHA1[:8].
- `cmd_remove` filtrovat přes `id` nebo index, ne přes `is not`.
**Dopad:** Zabrání tichým datovým ztrátám a duplikátům. Bez toho je celý skill nespolehlivý.
---
## 2. Garbage collection `at` reminderů + deduplikace při doručení
**Problém:** Dva propojené bugy:
- Jednorázové `at` remindery zůstávají v `reminder.yaml` navždy. Po odeslání se jen přestanou spouštět, ale loadují se každý minutovým cronem. Po měsících tam budou stovky mrtvých záznamů.
- `should_fire()` má 60s okno — s minutovým cronem může `at` reminder doručit dvakrát (např. při dvojím spuštění cronu nebo časovém posunu). Log ukazuje, že to zatím proběhlo OK, ale není to garantováno.
**Řešení:**
- `remind_send.py` po úspěšném doručení `at` reminderu: buď ho smazat z YAML, nebo přidat `purge` subcommand pro ruční cleanup.
- Zužit existující state file pro dedup: zúžit okno na `0 <= delta < 30` a kontrolovat, zda už byl ve stejném minutovém okně doručen (state file už existuje, jen má špatný klíč — viz bod 1).
- Alternativně: SQLite state tabulka `fired(text, scheduled_at, fired_at)` s `PRIMARY KEY(text, scheduled_at)`.
**Dopad:** Zabrání spamu a nekonečnému růstu YAML souboru.
---
## 3. Atomic writes + odstranění ruční YAML konstrukce
**Problém:** Dva propojené problémy v `remind_edit.py`:
- Zápis do `reminder.yaml` je neatomický — `with open(REMINDER_FILE, "w")` může při crashu zanechat prázdný/s poškozený soubor = ztráta všech reminderů.
- `format_reminder()` ručně skládá YAML stringy (`f"- text: {text}"`) — neescapuje speciální znaky (uvozovky, dvojtečky, newlines), nedrží konzistentní odsazení, duplikuje logiku ruamel.yaml.
**Řešení:**
- Atomic write: `tmp = path.with_suffix(".tmp")``yaml.dump(data, f)``os.replace(tmp, path)`.
- Nahradit `format_reminder()` builděním dictu a `yaml.dump()` celého dokumentu. Použít `ruamel.yaml.scalarstring.LiteralScalarString` přímo z knihovny (smazat vlastní třídu).
- Přidat validaci před zápisem (schema check).
**Dopad:** Zabrání ztrátě dat a tichým YAML parse chybám. Největší robustness win s minimálním úsilím.
---
## 4. `update` příkaz + `list` příkaz
**Problém:**
- `remind_edit.py` má jen `add` a `remove`. Změna času = smazat a vytvořit znovu — rizikové (viz bod 1, substring match).
- `list` je dokumentovaný v SKILL.md, ale v kódu neexistuje. Uživatel (nebo LLM) nemá jak zkontrolovat aktuální stav.
**Řešení:**
- Přidat `update --id X [--cron ...] [--at ...] [--random-* ...]` — najde reminder a upraví jen zadaná pole.
- Přidat `list` — vypíše všechny remindery s ID, textem a typem schedule.
- Přidat `--dry-run` k `add` a `update` pro bezpečné testování.
**Dopad:** Zásadní UX zlepšení, snižuje riziko chyb při úpravách, doplňuje chybějící dokumentovanou funkci.
---
## 5. Testy pro `remind_edit.py` a `remind_send.py`
**Problém:** Testy pokrývají jen `random_times.py`. Dva hlavní skripty (CRUD operace, dedup, fire detection, YAML I/O) nemají žádné testy. Jakákoliv změna v bodech 14 bez testů = riziko regresí.
**Řešení:** Přidat unit testy pro:
- `cmd_add` s různými kombinacemi flagů (cron, at, random)
- `cmd_remove` s 0/1/N matches, substring kolize
- `should_fire` s různými typy reminderů a okraji časových oken
- Dedup state management (nový i starý formát)
- Atomic write (crash uprostřed zápisu)
- Validace `at` v budoucnosti
**Dopad:** Bez testů je jakýkoliv refaktoring hazard. S testy se body 14 dají implementovat bez strachu z regresí.
---
*Zbylé návrhy (SQLite backend, pause/resume, cron until, retry TTL, log enrichment, chat_id z configu, per-reminder TZ) jsou P2P3 — užitečné, ale nejsou blokátory.*