cleanup: remove old reminder system and unused crontab files

Todo management now lives entirely in skills/calendar/ via VTODO + todoman.
This commit is contained in:
Yanxin Lu
2026-03-23 09:53:49 -07:00
parent 31efcffb19
commit 13986aa3ab
7 changed files with 4 additions and 395 deletions

View File

@@ -30,17 +30,7 @@ _这份文件记录持续性项目和重要状态跨会话保留。_
## 🎯 活跃项目
### 1. 每日待办提醒系统
**状态**: 迁移中 → VTODO`skills/calendar/MIGRATION.md`
**创建**: 2026-02-15
**旧系统**(待清理):
- 脚本: `~/.openclaw/workspace/scripts/reminder_check.py`
- 文件: `~/.openclaw/workspace/reminders/active.md`
**新系统**: 已合并到日历技能(`skills/calendar/`),使用 VTODO + todoman + CalDAV 同步
---
### 3. 邮件自动处理系统
### 1. 邮件自动处理系统
**状态**: 运行中
**创建**: 2026-02-27
**更新**: 2026-03-05基于学习机制优化
@@ -69,7 +59,7 @@ _这份文件记录持续性项目和重要状态跨会话保留。_
---
### 4. 工作区自动备份
### 2. 工作区自动备份
**状态**: 运行中
**创建**: 2026-03-06
**更新**: 2026-03-12移除脚本改用直接 git 命令)
@@ -86,7 +76,7 @@ _这份文件记录持续性项目和重要状态跨会话保留。_
---
### 5. 日历邀请 + CalDAV 同步
### 3. 日历邀请 + CalDAV 同步
**状态**: 运行中
**创建**: 2026-03-18
**配置**:
@@ -113,7 +103,6 @@ _这份文件记录持续性项目和重要状态跨会话保留。_
| 邮件处理器 | `~/.openclaw/workspace/scripts/email_processor/` |
| 日历/待办 | `~/.openclaw/workspace/skills/calendar/` |
| 日历数据 | `~/.openclaw/workspace/calendars/` (home=事件, tasks=待办) |
| ~~待办提醒~~ | ~~`scripts/reminder_check.py`~~ → 已迁移到 `skills/calendar/` |
---

View File

@@ -1,12 +0,0 @@
# OpenClaw 定时任务 - 小鹿
# 时区: America/Los_Angeles (PST)
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
# 每日新闻摘要 - 早上 5:00
0 5 * * * cd ~/.openclaw/workspace/scripts/news_digest && ./run.sh -v >> ~/.openclaw/workspace/logs/news_digest.log 2>&1 && python3 ~/.openclaw/workspace/scripts/news_digest/send_digest.py >> ~/.openclaw/workspace/logs/news_digest.log 2>&1
# 每日待办提醒 - 早上 8:00
0 8 * * * cd ~/.openclaw/workspace && python3 scripts/reminder_check.py 2>&1 | ~/.local/bin/himalaya message write --to mail@luyx.org --from youlu@luyanxin.com --subject "📋 今日待办清单"

View File

@@ -1,30 +0,0 @@
# 提醒事项表
## 待办事项Pending
| 事项 | 截止日期 | 优先级 | 状态 | 备注 |
|------|----------|--------|------|------|
| 给过敏医生打电话 | 2026-02-14 | 高 | done | 问集群过敏针吃的三个药物 |
| 给tilles打电话 | 2026-02-17 | 中 | done | 把horizon检测结果发给她并调整B超时间跟进治疗进度 |
| 跟进iui保险报销 | 2026-03-25 | 中 | pending | 确认iui人工授精费用保险报销进度避免过期 |
| 短杖贴上胶布 | 2026-02-28 | 低 | done | 周五提醒:用胶布包裹短杖把手,防滑/保护 |
| 打电话给progyny问iui报销 | 2026-04-04 | 中 | pending | 询问iui报销相关事宜 |
| 跟进CVS药物报销 | 2026-02-21 | 中 | done | 确认CVS买的药物报销是否到账核对金额 |
| 打电话给progyny问Pacific Bill | 2026-02-20 | 中 | done | 周五前询问Pacific Bill相关事宜 |
| 问tilles医生子宫情况 | 2026-02-17 | 高 | done | 问子宫是否已经fixed/修复好,确认是否可以开始备孕/下一步治疗 |
| 打电话给Erica wang约超声波 | 2026-02-18 | 中 | done | 预约超声波检查囊肿(确认囊肿情况,是否需要处理) |
| 跟accolade确认保险覆盖 | | 中 | done | 确认保险是否cover b超和erica wang的office visit |
| 给过敏医生打电话约过敏针 | 2026-02-18 | 中 | done | 约集群过敏针(免疫治疗),需要定期打针建立耐受 |
| 打电话给足科医生换时间 | 2026-02-20 | 中 | done | 周五前换预约时间 |
## 使用说明
1. **添加事项**:在表格中新增一行
2. **截止日期**:格式 YYYY-MM-DD空着默认为明天
3. **优先级**:高/中/低,空着默认为中
4. **状态**pending待办/ done已完成
5. **每天早上8:00自动检查**,到期事项会通知你
## 已完成归档
已完成的事项会自动移动到 archive/ 目录

View File

@@ -1,221 +0,0 @@
#!/usr/bin/env python3
"""
Daily Reminder Checker
Reads reminders from markdown table, filters due items, sends notification
"""
import re
import os
from datetime import datetime, timedelta
from pathlib import Path
# Paths
BASE_DIR = Path.home() / ".openclaw/workspace/reminders"
ACTIVE_FILE = BASE_DIR / "active.md"
ARCHIVE_DIR = BASE_DIR / "archive"
# Priority mapping (lower number = higher priority)
PRIORITY_MAP = {
'': 0, 'urgent': 0, 'high': 0,
'': 1, 'normal': 1, 'medium': 1,
'': 2, 'low': 2
}
def parse_table(content):
"""Parse markdown table into list of dicts"""
lines = content.strip().split('\n')
reminders = []
for line in lines:
# Skip header lines and separators
if line.startswith('|') and '---' not in line and '事项' not in line:
cells = [cell.strip() for cell in line.split('|')[1:-1]]
if len(cells) >= 4 and cells[0] and cells[0] != '事项':
reminder = {
'事项': cells[0],
'截止日期': cells[1] if len(cells) > 1 else '',
'优先级': cells[2] if len(cells) > 2 else '',
'状态': cells[3] if len(cells) > 3 else 'pending',
'备注': cells[4] if len(cells) > 4 else ''
}
reminders.append(reminder)
return reminders
def get_default_date():
"""Return tomorrow's date as string"""
tomorrow = datetime.now() + timedelta(days=1)
return tomorrow.strftime('%Y-%m-%d')
def normalize_reminder(reminder):
"""Apply defaults and normalize"""
# Default priority
if not reminder['优先级']:
reminder['优先级'] = ''
# Default date
if not reminder['截止日期']:
reminder['截止日期'] = get_default_date()
# Normalize status
reminder['状态'] = reminder['状态'].lower() if reminder['状态'] else 'pending'
return reminder
def get_days_until(due_date_str):
"""Calculate days until due date"""
try:
due_date = datetime.strptime(due_date_str, '%Y-%m-%d')
today = datetime.now()
delta = (due_date.date() - today.date()).days
return delta
except ValueError:
return None
def get_urgency_label(days):
"""Get urgency label based on days until due"""
if days is None:
return "❓ 日期未知"
elif days < 0:
return f"🔴 逾期 {-days}"
elif days == 0:
return "🔴 今天"
elif days == 1:
return "🟡 明天"
elif days <= 3:
return f"🟡 {days} 天后"
else:
return f"🟢 {days} 天后"
def sort_reminders(reminders):
"""Sort by priority (high first), then by date (earlier first)"""
def sort_key(r):
priority = PRIORITY_MAP.get(r['优先级'].lower(), 1)
try:
date = datetime.strptime(r['截止日期'], '%Y-%m-%d')
except ValueError:
date = datetime.max
return (priority, date)
return sorted(reminders, key=sort_key)
def format_notification(pending_reminders):
"""Format all pending reminders for notification"""
if not pending_reminders:
return None
today_str = datetime.now().strftime('%Y-%m-%d')
lines = [f"📋 今日待办清单 ({today_str})", "=" * 50]
# Group by priority
groups = {'': [], '': [], '': []}
for r in pending_reminders:
prio = r['优先级']
if prio in groups:
groups[prio].append(r)
# Output high priority
if groups['']:
lines.append("\n🔴 高优先级:")
for r in groups['']:
days = get_days_until(r['截止日期'])
urgency = get_urgency_label(days)
note = f" | {r['备注']}" if r['备注'] else ""
lines.append(f"{r['事项']} ({urgency}){note}")
# Output medium priority
if groups['']:
lines.append("\n🟡 中优先级:")
for r in groups['']:
days = get_days_until(r['截止日期'])
urgency = get_urgency_label(days)
note = f" | {r['备注']}" if r['备注'] else ""
lines.append(f"{r['事项']} ({urgency}){note}")
# Output low priority
if groups['']:
lines.append("\n🟢 低优先级:")
for r in groups['']:
days = get_days_until(r['截止日期'])
urgency = get_urgency_label(days)
note = f" | {r['备注']}" if r['备注'] else ""
lines.append(f"{r['事项']} ({urgency}){note}")
lines.append("\n" + "=" * 50)
lines.append("📝 完成事项后请修改状态为 done")
lines.append("📁 管理文件: ~/.openclaw/workspace/reminders/active.md")
return '\n'.join(lines)
def archive_done_reminders(reminders):
"""Move done reminders to archive"""
done = [r for r in reminders if r['状态'] == 'done']
if not done:
return
# Create archive filename with current quarter
now = datetime.now()
quarter = (now.month - 1) // 3 + 1
archive_file = ARCHIVE_DIR / f"{now.year}-Q{quarter}.md"
# Append to archive
with open(archive_file, 'a', encoding='utf-8') as f:
for r in done:
f.write(f"| {r['事项']} | {r['截止日期']} | {r['优先级']} | done | {r['备注']} |\n")
def update_active_file(reminders):
"""Rewrite active file without done items"""
pending = [r for r in reminders if r['状态'] != 'done']
with open(ACTIVE_FILE, 'w', encoding='utf-8') as f:
f.write("# 提醒事项表\n\n")
f.write("## 待办事项Pending\n\n")
f.write("| 事项 | 截止日期 | 优先级 | 状态 | 备注 |\n")
f.write("|------|----------|--------|------|------|\n")
for r in pending:
f.write(f"| {r['事项']} | {r['截止日期']} | {r['优先级']} | {r['状态']} | {r['备注']} |\n")
f.write("\n## 使用说明\n\n")
f.write("1. **添加事项**:在表格中新增一行\n")
f.write("2. **截止日期**:格式 YYYY-MM-DD空着默认为明天\n")
f.write("3. **优先级**:高/中/低,空着默认为中\n")
f.write("4. **状态**pending待办/ done已完成\n")
f.write("5. **每天早上8:00自动检查**,到期事项会通知你\n\n")
f.write("## 已完成归档\n\n")
f.write("已完成的事项会自动移动到 archive/ 目录\n")
def main():
"""Main function - show all pending reminders as todo list"""
# Check if file exists
if not ACTIVE_FILE.exists():
print("No reminders file found")
return
# Read and parse
with open(ACTIVE_FILE, 'r', encoding='utf-8') as f:
content = f.read()
reminders = parse_table(content)
# Normalize and filter for pending only
reminders = [normalize_reminder(r) for r in reminders]
pending_reminders = [r for r in reminders if r['状态'] == 'pending']
if not pending_reminders:
# No pending reminders - silent
return
# Sort and format
pending_reminders = sort_reminders(pending_reminders)
notification = format_notification(pending_reminders)
if notification:
print(notification)
# Archive done items (optional - uncomment if you want auto-archive)
# archive_done_reminders(reminders)
# update_active_file(reminders)
if __name__ == "__main__":
main()

View File

@@ -1,117 +0,0 @@
# Migration: reminder_check.py → calendar todo
## What's changing
| Before | After |
|--------|-------|
| `scripts/reminder_check.py` | `skills/calendar/scripts/calendar.sh todo` |
| `reminders/active.md` (markdown table) | `calendars/tasks/*.ics` (RFC 5545 VTODO) |
| Local only, no sync | CalDAV sync to all devices via vdirsyncer |
| No native reminders | VALARM triggers on phone/desktop |
| Cron reads markdown | Cron reads .ics via todoman |
| Custom Python parsing | todoman for robust RFC 5545 VTODO handling |
## Prerequisites
- [ ] Install todoman (see below)
- [ ] Configure todoman (see below)
- [ ] `calendar.sh todo add --dry-run` works
- [ ] `~/.openclaw/workspace/calendars/tasks/` directory exists (auto-created by `todo add`)
- [ ] vdirsyncer has a `cal/tasks` pair configured
- [ ] Live tests 8-12 from `TESTING.md` pass on the Linux machine
## Step 0: Install and configure todoman
### Install
```bash
# Debian/Ubuntu (the agent's Linux machine)
pip install todoman
# macOS (Homebrew)
brew install todoman
```
The CLI command is `todo`.
### Configure
Create `~/.config/todoman/config.py`:
```python
path = "~/.openclaw/workspace/calendars/tasks/"
date_format = "%Y-%m-%d"
time_format = "%H:%M"
default_due = 24
default_priority = 0
humanize = True
```
### Verify
```bash
# Should list todos (or show empty list without errors)
todo list
```
## Step 1: Migrate pending reminders
Two items are pending in `reminders/active.md`:
```bash
SKILL_DIR=~/.openclaw/workspace/skills/calendar
$SKILL_DIR/scripts/calendar.sh todo add \
--summary "跟进iui保险报销" \
--due "2026-03-25" \
--priority medium \
--description "确认iui人工授精费用保险报销进度避免过期"
$SKILL_DIR/scripts/calendar.sh todo add \
--summary "打电话给progyny问iui报销" \
--due "2026-04-04" \
--priority medium \
--description "询问iui报销相关事宜"
```
Note: `todo add` emails each item to `mail@luyx.org`. This is expected.
Verify:
```bash
$SKILL_DIR/scripts/calendar.sh todo list
```
## Step 2: Set up cron
Ask the agent to set up a daily cron job via `openclaw cron`:
> Set up a daily cron at 8:00 AM PST that runs:
> `~/.openclaw/workspace/skills/calendar/scripts/calendar.sh todo check`
> and emails the output to mail@luyx.org with subject "📋 今日待办清单"
The old `reminder_check.py` cron should be removed by the agent at the same time.
## Step 3: Verify
- [ ] `todo list` (todoman directly) shows both migrated items
- [ ] `calendar.sh todo list` shows both items with Chinese priority labels
- [ ] `vdirsyncer sync` completes without errors
- [ ] Todos appear on phone/CalDAV client
- [ ] Next morning's cron email arrives with the new format
## Step 4: Clean up
After a few days of successful operation:
```bash
# Remove old reminder system
rm scripts/reminder_check.py
rm -r reminders/
```
## Rollback
If something goes wrong, the old system is still intact until Step 4:
- `reminders/active.md` is unchanged
- `scripts/reminder_check.py` still works
- Re-add the old cron entry to restore the previous behavior

View File

@@ -436,7 +436,7 @@ def _days_until(due_val):
def _urgency_label(days):
"""Urgency label with emoji, matching reminder_check.py style."""
"""Urgency label with emoji."""
if days is None:
return "❓ 日期未知"
elif days < 0: