···11[[ TODO Workflow ]]
22Use this workflow only when you need to remember something for future work, or mark an existing todo item as completed.
33Maintain `TODO.md` and `TODO.DONE.md` under `file_state_dir`.
44+Recurring tasks live in `TODO.RECUR.md` under `file_state_dir`.
4556`TODO.md` entry format examples:
67```text
···1415- [x] [Created](2026-02-11 09:30), [Done](2026-02-11 10:00), [ChatID](tg:-1001981343441) | 2026-02-11 10:00 Had lunch with [John](tg:@johnwick), Miss Louis and [Sarah](tg:29930) at the Italian restaurant.
1516```
16171818+`TODO.RECUR.md` entry format examples:
1919+```text
2020+- [ ] [Next](2026-02-12 09:00), [Repeat](daily), [TZ](Asia/Tokyo), [ChatID](tg:-1001981343441) | Remind [John](tg:@johnwick) to submit the report.
2121+- [ ] [Next](2026-02-16 10:00), [Repeat](weekly) | Review open invoices.
2222+- [ ] [Next](2026-02-14 18:00), [Repeat](every 3 days) | Back up notes.
2323+```
2424+1725- If a new task is identified, use `todo_update` to add it to `TODO.md`.
2626+- If a new recurring task is identified, use `todo_update` with action `add_recurring`. Pass `content`, `next` (`YYYY-MM-DD HH:mm`), `repeat`, optional `tz`, and optional `chat_id`; supported repeat values are `daily`, `weekly`, and `every N days`.
2727+- If the user states a timezone, write it as an IANA timezone in `TZ` (for example `Asia/Tokyo`). If no timezone is stated, omit `TZ`; the runtime local timezone is used.
1828- If a task is expired, notify mentioned contacts via `contacts_send` with a concise reminder. Do not mention TODO files, pending counts, or delivery status. Then use `todo_update` to complete the task.
1929- If a task is not due, do nothing.
···122122 "If `input_raw` mentions a time (explicit or relative), resolve it with current time context in `runtime` (now_local/now_utc) and rewrite it as exact `YYYY-MM-DD hh:mm`.",
123123 "Must consider first-person references with speaker context: ",
124124 "- if the speaker mention themselves (like 'I', 'me', '$SPEAKER'), resolve to their own contact if available; similarly, resolve mentions of the speaker's direct interlocutors to those contacts if available;",
125125+ "- if runtime.speaker_username is already a valid `protocol:id`, use it as the speaker reference id;",
125126 "Attach IDs as `[Name](protocol:id)`, where id may be from reachable_ids, example input:",
126127 "Notice $SPEAKER to tell Alice invites Bob to the meeting of Lucy.",
127128 "and rewritten content (assume the $SPEAKER is 'Lyric'): ",
···205206 UserInputRaw: strings.TrimSpace(in.UserInputRaw),
206207 SpeakerUsername: func() string {
207208 v := strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(in.SpeakerUsername), "@"))
208208- if v == "" {
209209- return ""
210210- }
211211- return strings.ToLower(v)
209209+ return v
212210 }(),
213211 }
214212 if len(in.MentionUsernames) > 0 {
···113113Maintains `TODO.md` / `TODO.DONE.md` under `file_state_dir`, including add and complete operations.
114114115115- Key limits: `add` requires `people`; `complete` uses semantic matching and will error on no-match or ambiguous match.
116116+- Recurring todos are added with `action=add_recurring` and stored in `TODO.RECUR.md` under `file_state_dir`:
117117+ ```text
118118+ - [ ] [Next](2026-05-02 09:00), [Repeat](daily), [TZ](Asia/Tokyo), [ChatID](tg:-100123) | Remind [John](tg:@john) to submit report.
119119+ ```
120120+ Supported repeat values are `daily`, `weekly`, and `every N days`. `TZ` is optional; when omitted, the runtime local timezone is used. Heartbeat expands due recurring records into ordinary `TODO.md` items, advances `Next`, then includes the current open `TODO.md` items in the heartbeat task.
116121117122## Dedicated Tools
118123