Compare commits

...

2 Commits

Author SHA1 Message Date
Yanxin Lu
912bcf53bd calendar: fix _days_until to handle Unix timestamps from todoman --porcelain 2026-03-22 15:50:43 -07:00
Yanxin Lu
cf8158c7cc calendar: update TESTING.md with todoman verification steps 2026-03-22 15:43:18 -07:00
2 changed files with 33 additions and 13 deletions

View File

@@ -170,22 +170,26 @@ $SKILL_DIR/scripts/calendar.sh todo add \
**Verify:** **Verify:**
- [ ] Script exits without error - [ ] Script exits without error
- [ ] `.ics` file created in `~/.openclaw/workspace/calendars/tasks/` - [ ] `.ics` file created in `~/.openclaw/workspace/calendars/tasks/`
- [ ] `todo list` (todoman directly) shows "Test Todo"
- [ ] Email arrives at `mail@luyx.org` with .ics attachment - [ ] Email arrives at `mail@luyx.org` with .ics attachment
- [ ] `vdirsyncer sync` ran - [ ] `vdirsyncer sync` ran
## 9. List Todos ## 9. List Todos
```bash ```bash
# List pending todos # Via our wrapper (formatted Chinese output)
$SKILL_DIR/scripts/calendar.sh todo list $SKILL_DIR/scripts/calendar.sh todo list
# List all (including completed) # Via todoman directly (should show the same items)
todo list
# Include completed
$SKILL_DIR/scripts/calendar.sh todo list --all $SKILL_DIR/scripts/calendar.sh todo list --all
``` ```
**Verify:** **Verify:**
- [ ] "Test Todo" appears with correct urgency label - [ ] "Test Todo" appears in both outputs
- [ ] Priority grouping is correct - [ ] Priority grouping is correct in wrapper output
- [ ] `--all` flag works (same output when none are completed) - [ ] `--all` flag works (same output when none are completed)
## 10. Complete a Todo ## 10. Complete a Todo
@@ -195,9 +199,9 @@ $SKILL_DIR/scripts/calendar.sh todo complete --match "Test Todo"
``` ```
**Verify:** **Verify:**
- [ ] .ics file updated with `STATUS:COMPLETED` and `COMPLETED:` timestamp - [ ] `todo list` (todoman) — "Test Todo" no longer appears
- [ ] `todo list` — "Test Todo" no longer appears - [ ] `$SKILL_DIR/scripts/calendar.sh todo list` — also gone
- [ ] `todo list --all` "Test Todo" appears as completed (with checkmark) - [ ] `$SKILL_DIR/scripts/calendar.sh todo list --all` — appears as completed (with checkmark)
- [ ] `vdirsyncer sync` ran - [ ] `vdirsyncer sync` ran
## 11. Delete a Todo ## 11. Delete a Todo
@@ -211,13 +215,16 @@ $SKILL_DIR/scripts/calendar.sh todo add \
--due "$TEST_DATE" \ --due "$TEST_DATE" \
--priority low --priority low
# Confirm it appears
todo list
# Delete # Delete
$SKILL_DIR/scripts/calendar.sh todo delete --match "Delete Me" $SKILL_DIR/scripts/calendar.sh todo delete --match "Delete Me"
``` ```
**Verify:** **Verify:**
- [ ] .ics file removed from tasks dir - [ ] .ics file removed from tasks dir
- [ ] `todo list` does not show "Delete Me Todo" - [ ] `todo list` (todoman) does not show "Delete Me Todo"
- [ ] `vdirsyncer sync` ran - [ ] `vdirsyncer sync` ran
## 12. Todo Check (Cron Output) ## 12. Todo Check (Cron Output)
@@ -278,6 +285,9 @@ vdirsyncer sync
# khal can read local calendar # khal can read local calendar
khal list today 7d khal list today 7d
# todoman can list todos
todo list
``` ```
## Common Failures ## Common Failures
@@ -290,4 +300,6 @@ khal list today 7d
| `ModuleNotFoundError: icalendar` | Run `uv sync --project $SKILL_DIR` to install dependencies | | `ModuleNotFoundError: icalendar` | Run `uv sync --project $SKILL_DIR` to install dependencies |
| Invite shows as attachment (no Accept/Decline) | Check MIME `Content-Type` includes `method=REQUEST` | | Invite shows as attachment (no Accept/Decline) | Check MIME `Content-Type` includes `method=REQUEST` |
| Event not in `khal list` after sync | Check `.ics` file exists in `~/.openclaw/workspace/calendars/home/` | | Event not in `khal list` after sync | Check `.ics` file exists in `~/.openclaw/workspace/calendars/home/` |
| `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 | | Todo not syncing | Check `~/.openclaw/workspace/calendars/tasks/` exists, verify vdirsyncer `cal/tasks` pair |

View File

@@ -413,15 +413,23 @@ def _todoman_list_json(*extra_args):
return json.loads(result.stdout) return json.loads(result.stdout)
def _days_until(due_str): def _days_until(due_val):
"""Days from today until due date string. Negative means overdue.""" """Days from today until due date (string or Unix timestamp). Negative means overdue."""
if not due_str: if not due_val:
return None return None
# Unix timestamp (int/float) from todoman --porcelain
if isinstance(due_val, (int, float)):
try:
due_date = datetime.fromtimestamp(due_val, tz=timezone.utc).date()
except (ValueError, TypeError, OSError):
return None
return (due_date - date.today()).days
# String formats (ISO or YYYY-MM-DD)
try: try:
due_date = datetime.fromisoformat(due_str).date() due_date = datetime.fromisoformat(due_val).date()
except (ValueError, TypeError): except (ValueError, TypeError):
try: try:
due_date = _parse_date(due_str) due_date = _parse_date(due_val)
except ValueError: except ValueError:
return None return None
return (due_date - date.today()).days return (due_date - date.today()).days