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>
61 lines
6.3 KiB
Markdown
61 lines
6.3 KiB
Markdown
# 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
|