Files
full-focus/.claude/commands/evening-prep.md
aj.siegel 20d8c1aedc Add fetch_evening_tasks.py script and shared notion_helpers module
Refactors weekly-template's Notion client setup into a shared helper
(with .env/dotenv support and full pagination), and adds a dedicated
evening-prep script so both commands can fall back to script-based
fetching instead of the MCP search/fetch pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 23:05:57 -04:00

61 lines
6.3 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.
# Evening Prep
You are given the following context for my day:
$ARGUMENTS
Please create a new note in the "Daily Notes" folder.
* The title should be "Daily Note - YYYY-MM-DD" using today's date.
* Below the title, link to the Weekly Note for the current week using format: `[[Weekly Note - Month Day, Year]]` where the date is the Sunday of the current week
## Step 1: read tomorrow's calendar events
Use the Microsoft 365 connector's `outlook_calendar_search` tool to fetch tomorrow's events:
* `afterDateTime`: tomorrow at 00:00, `beforeDateTime`: tomorrow at 23:59
* `query: "*"`, `order: "oldest"`, `limit: 25`
🚨 TIMEZONE: The connector returns times in **UTC** (ISO strings ending in `Z`). Convert each to Eastern Time before displaying — EDT = UTC−4 (mid-Mar to early-Nov), EST = UTC−5 otherwise. Flag any `isAllDay` events (PTO/OOO) as out-of-office rather than meetings.
## Step 1b: Check tomorrow's Runna workout
Fetch the Runna ical feed (see CLAUDE.md "Data Sources") with `curl -sL <url>` and find the `VEVENT` whose `DTSTART` is tomorrow's date.
* If one exists: the workout block is 9:00 AM + `X-WORKOUT-ESTIMATED-DURATION` (fall back to the high end of the duration range in `SUMMARY`/`DESCRIPTION` if that field is missing) + a 20-minute shower buffer after.
* Check that block against tomorrow's calendar events from Step 1. If clear, note AJ is free for the workout and what time he's clear by. If a meeting falls inside the block, flag it by name and time so AJ can decide whether to move, shorten, or skip the workout.
* If no workout is scheduled tomorrow, skip this silently — do not add a Workout section.
## Step 2: Under the **Agenda** heading
Format my calendar events in a simple Markdown table with columns: Time (ET), Event Name, Owner, and Duration
* Time should be the FIRST column
* Put a star next to any events that overlap with other events
* Put two !! next to any events starting before 9 AM ET or after 5 PM ET
* Do not include personal appointments that don't affect my work day
* My work day goes from 9 AM ET to 5:30 PM ET. Use this to determine my availability.
Let me know how much unscheduled time I have.
* Directly beneath the Agenda table, if Step 1b found a workout scheduled tomorrow, add a one-line **Workout** note stating whether the 9 AM block is clear or naming the conflicting meeting.
## Step 3: Get task data
1. **Get this week's focus projects** — read the current Weekly Note (`Weekly Notes/Weekly Note - <Sunday's date>.md`) and use its listed focus projects + weekly goals. (Only if that note is missing: `notion-search` the Projects collection `collection://2c0abd6c-450a-807a-a3d7-000b8d8aaecc` with `page_size: 25`, fetch the results in parallel, and keep those with `Focus this week` = `__YES__` and `Status` = "Active".)
2. **Get candidate tasks** — run `python3 scripts/fetch_evening_tasks.py`. This already excludes `Status` = "Done" or "Blocked" and paginates through the full Tasks database, so no candidate is missed as the tracker grows.
3. **Rank locally**: by (1) `has_blocking` true, (2) `suggested_for_today` ≤ tomorrow, (3) soonest `due_date`.
**If the script errors or is unavailable** (e.g. missing `.env`/`NOTION_TOKEN` on this machine), fall back instead of failing the command: `notion-search` the Tasks collection `collection://2c0abd6c-450a-8085-80a0-000ba136a154` with `page_size: 25`, `max_highlight_length: 0`, seeded with the focus-project names plus "blocking due this week suggested today" (this Notion MCP has no filter/query tool and `view://` URLs aren't fetchable — see CLAUDE.md "HOW TO QUERY THESE DATABASES"). Fetch candidate pages in parallel to read `Status`, `Suggested for today`, `Due date`, `Blocking`, `Priority`, `Project`, then filter/rank as in step 3 above. Do NOT print any "falling back" message for `view://` fetches, but DO tell me the script failed and you're using the fallback.
Format the note with the following sections:
1. Under **Suggested Tasks** list up to 3 tasks from the ranked set above (Blocking-others tasks always come first). For each, show the task name, related project, and a Notion link.
2. Under **Key Projects** list this week's focus projects with their weekly goal.
- If a search legitimately returns no qualifying open tasks, say so plainly — never invent tasks to fill the list.
## Step 4: Mark Top Tasks in Notion
The Tasks Tracker has a `Top Task` checkbox property and a `Top Tasks` view (filtered to `Top Task = true` AND `Status != Done`) for surfacing the current day's Big 3 at a glance. At most 3 tasks may be checked at any time.
1. Present the Suggested Tasks from Step 3 to AJ and let him confirm or swap any of them before finalizing.
2. Use `marked_top_tasks` from the Step 3 script output (already every task with `Top Task = true`, any status — no extra search needed). If the Step 3 fallback was used instead, `notion-search` the Tasks collection (`collection://2c0abd6c-450a-8085-80a0-000ba136a154`) filtered/queried for `Top Task` = true.
3. Any currently-marked task whose `status` = "Done" gets `Top Task` set to false immediately — regardless of whether it's in today's agreed set. Don't wait for a replacement to unmark a completed task.
4. For each other currently-marked task that is NOT in today's agreed set, `notion-update-page` to set `Top Task` = false.
5. For each of the (up to 3) agreed tasks, `notion-update-page` to set `Top Task` = true.
6. Never have more than 3 tasks checked at once — unmark old ones before marking new ones.
Note: this only unchecks stale Done tasks when an evening-prep run touches them. It isn't real-time — if AJ marks a task Done in Notion outside of this flow, the checkbox stays checked until the next evening-prep pass (though the `Top Tasks` view already filters out `Status = Done`, so it won't show there regardless). True real-time un-checking would need a native Notion automation (Settings → Automations → when Status is set to Done → uncheck Top Task), which isn't something these tools can create.
## Formatting Rules
* Always provide a tl;dr summary at the top of the note
* Add a "## Table of Contents" section after the frontmatter using Obsidian internal link syntax `[[#Heading Name]]` for all H2 sections
* Include all major sections: tl;dr, Agenda, Suggested Tasks, Key Projects, Suggested Reading, etc.
* Format all date displays as Month, Day Year