calendar: add recurring events, event management, and safety rules
Add --rrule flag to send with DTSTART/BYDAY validation (RFC 5545). Add event list (via khal) and event delete (safe single-event removal). Document safety rules from 2026-03-25 incident: always dry-run recurring events, never rm .ics files, space out SMTP sends.
This commit is contained in:
@@ -293,9 +293,98 @@ $SKILL_DIR/scripts/calendar.sh todo check
|
||||
# Should produce no output
|
||||
```
|
||||
|
||||
## 14. Regression: Existing Invite Commands
|
||||
## 14. Dry Run: Recurring Event (--rrule)
|
||||
|
||||
Verify the rename didn't break VEVENT flow.
|
||||
Test recurring event generation. Use a date that falls on a Tuesday.
|
||||
|
||||
```bash
|
||||
# Find next Tuesday
|
||||
NEXT_TUE=$(python3 -c "from datetime import date,timedelta; d=date.today(); d+=timedelta((1-d.weekday())%7 or 7); print(d)")
|
||||
|
||||
$SKILL_DIR/scripts/calendar.sh send \
|
||||
--to "mail@luyx.org" \
|
||||
--subject "Recurring Test (Tue)" \
|
||||
--summary "Recurring Test (Tue)" \
|
||||
--start "${NEXT_TUE}T14:30:00" \
|
||||
--end "${NEXT_TUE}T15:00:00" \
|
||||
--rrule "FREQ=WEEKLY;COUNT=4;BYDAY=TU" \
|
||||
--dry-run
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- [ ] ICS has `RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=4`
|
||||
- [ ] DTSTART falls on a Tuesday
|
||||
- [ ] No validation errors
|
||||
|
||||
## 15. Validation: DTSTART/BYDAY Mismatch
|
||||
|
||||
Verify the tool rejects mismatched DTSTART and BYDAY.
|
||||
|
||||
```bash
|
||||
# This should FAIL — start is on a Tuesday but BYDAY=TH
|
||||
$SKILL_DIR/scripts/calendar.sh send \
|
||||
--to "mail@luyx.org" \
|
||||
--subject "Mismatch Test" \
|
||||
--summary "Mismatch Test" \
|
||||
--start "${NEXT_TUE}T09:00:00" \
|
||||
--end "${NEXT_TUE}T09:30:00" \
|
||||
--rrule "FREQ=WEEKLY;COUNT=4;BYDAY=TH" \
|
||||
--dry-run
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- [ ] Script exits with error
|
||||
- [ ] Error message says DTSTART falls on TU but RRULE says BYDAY=TH
|
||||
- [ ] Suggests changing --start to a date that falls on TH
|
||||
|
||||
## 16. Event List
|
||||
|
||||
```bash
|
||||
# List upcoming events
|
||||
$SKILL_DIR/scripts/calendar.sh event list
|
||||
|
||||
# Search by text
|
||||
$SKILL_DIR/scripts/calendar.sh event list --search "Calendar Skill Test"
|
||||
|
||||
# List with UIDs
|
||||
$SKILL_DIR/scripts/calendar.sh event list --format "{uid} {title}"
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- [ ] Events from earlier tests appear
|
||||
- [ ] Search narrows results correctly
|
||||
- [ ] UIDs are displayed with --format
|
||||
|
||||
## 17. Event Delete
|
||||
|
||||
```bash
|
||||
# Send a throwaway event first
|
||||
$SKILL_DIR/scripts/calendar.sh send \
|
||||
--to "mail@luyx.org" \
|
||||
--subject "Delete Me Event" \
|
||||
--summary "Delete Me Event" \
|
||||
--start "${TEST_DATE}T20:00:00" \
|
||||
--end "${TEST_DATE}T21:00:00"
|
||||
|
||||
# Verify it exists
|
||||
$SKILL_DIR/scripts/calendar.sh event list --search "Delete Me"
|
||||
|
||||
# Delete it
|
||||
$SKILL_DIR/scripts/calendar.sh event delete --match "Delete Me Event"
|
||||
|
||||
# Verify it's gone
|
||||
$SKILL_DIR/scripts/calendar.sh event list --search "Delete Me"
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- [ ] Event is created and visible
|
||||
- [ ] Delete removes exactly one event
|
||||
- [ ] Other events are untouched
|
||||
- [ ] `vdirsyncer sync` ran after delete
|
||||
|
||||
## 18. Regression: Existing Invite Commands
|
||||
|
||||
Verify new features didn't break VEVENT flow.
|
||||
|
||||
```bash
|
||||
$SKILL_DIR/scripts/calendar.sh send \
|
||||
@@ -309,7 +398,8 @@ $SKILL_DIR/scripts/calendar.sh send \
|
||||
|
||||
**Verify:**
|
||||
- [ ] ICS has `BEGIN:VEVENT`, `METHOD:REQUEST`
|
||||
- [ ] No errors from the renamed script
|
||||
- [ ] No RRULE present (single event)
|
||||
- [ ] No errors
|
||||
|
||||
---
|
||||
|
||||
@@ -347,3 +437,7 @@ todo list
|
||||
| `todo` command not found | Install with `uv tool install todoman` |
|
||||
| `todo list` errors | Check `~/.config/todoman/config.py` exists and `path` points to tasks dir |
|
||||
| Todo not syncing | Check `~/.openclaw/workspace/calendars/tasks/` exists, verify vdirsyncer `cal/tasks` pair |
|
||||
| DTSTART/BYDAY mismatch error | `--start` date doesn't fall on the BYDAY day. Change the start date to match |
|
||||
| Recurring events on wrong day | DTSTART was not aligned with BYDAY. Delete the event and resend with correct `--start` |
|
||||
| SMTP rate limit / EOF error | Too many sends too fast. Wait 10+ seconds between sends (Migadu limit) |
|
||||
| Events disappeared after cleanup | **Never use `rm *.ics`** on calendar dirs. Use `event delete --match` instead |
|
||||
|
||||
Reference in New Issue
Block a user