| name | wind-down |
| description | Interactive daily wrap-up: 1. Input candidates (Slack/email); 2. Discovered contacts; 3. Work log draft/write; 4. Next day's calendar preview. |
| version | 2.0.0 |
| author | Apollo |
| license | MIT |
| platforms | ["linux","macos"] |
| metadata | {"hermes":{"tags":["productivity","wind-down","daily-routine","work-log","inbox-triage","sources","calendar"],"related_skills":["work-log","morning-briefing","obsidian"]}} |
🌅 Daily Wind-Down & Wrap-Up
Overview
This skill governs the interactive daily wind-down and wrap-up session for Justin.
It runs in the late afternoon/evening when Justin is ready to close his workday, clear his head, and organize his vault for tomorrow.
Triggers
- "Let's start my wind down"
- "let's wrap up for today"
- "wind down"
- "wrap up"
Sequence of Phases
The wind-down session runs interactively in a strict, step-by-step sequence. Wait for Justin's confirmation or feedback at the end of each phase before proceeding.
Phase 1 — Input Candidates
Present potential input candidates (active Slack conversations and noteworthy primary-category emails from the last 36-48 hours) that Justin hasn't tagged with 🧠 or forwarded to Apollo, but that are highly worthy of being turned into inputs in his vault.
Run the unified script live to fetch candidates:
python3 /home/justin.guest/.hermes/scripts/fetch_source_candidates.py
If candidates (Slack or Email) are found:
- Show them with sequential numbers across both Slack and Email candidates.
- Format:
📋 N potential input candidates:
**Slack Conversations**
1. [\#channel-name] Topic or Preview — participants: Alice, Bob, Justin
2. [\#channel-name] Topic or Preview — participants: Endre, Justin
**Emails**
3. [Email/<account>] Subject line — from: Sender Name (Date)
...
Would you like to turn any of these conversations into inputs in your vault? (e.g. "yes, 1", "save 1 and 3", or "skip")
If Justin selects any:
- For each selected item:
- For Slack conversations:
- For Emails:
- Report the input(s) successfully saved.
If no candidates are found, skip this phase entirely and proceed to Phase 2.
Phase 2 — Discovered Contacts & Organizations
Present any discovered contacts or organizations (unresolved wikilinks found by the check_vault_signals.py script) from the signals cache file at ~/.hermes/morning-briefing/vault_signals_last_run.json (under the discovered_entities.people and discovered_entities.organizations fields).
Crucial Filtering & Duplication Check: The raw cache contains many false-positive people/organization names (such as "Use Anya Volosskaya", "ASL Bloom", "Daily Wind", "Scraps", or action item phrases).
- Filter Candidates: Filter out non-entity phrases, daily note headers, action items, or generic software tools before presenting the list. Only present genuine, unresolved human and organizational entities.
- Duplicate Check: Always perform a wildcard search (e.g.,
*Name*) using search_files under /home/justin.guest/Developer/obsidian-vault/ to check if a contact note already exists in Notebook/Contacts/ or Inbox/. Omit any entities that already have an existing contact card from the candidate list entirely.
If no new, unresolved, and verified human or organization candidates are found in the signals cache after filtering, skip this phase entirely and proceed to Phase 3.
Format:
👤 N discovered contact / organization candidates:
**People**
1. [Name] — first mentioned in [[context_file]]
**Organizations**
2. [Name] — first mentioned in [[context_file]]
...
Would you like me to create contact notes for any of these? (e.g. "yes, 1 as organization", "create 2", or "skip")
If Justin selects any:
- Check if the contact card already exists under
/home/justin.guest/Developer/obsidian-vault/Notebook/Contacts/ OR in /home/justin.guest/Developer/obsidian-vault/Inbox/ by performing a wildcard search on the name (e.g. searching for files matching *Name* using the search_files tool with target='files'). This is critical because contacts are saved with their unique timestamp appended (e.g., Notebook/Contacts/Tor Barstad 20260610075543.md).
- If a matching file exists in either location, do NOT overwrite or truncate it (as it contains precious history). Instead, patch the file in its current location to insert the standard frontmatter, executive summary, and state sections at the very top, preserving any existing content underneath.
- If the file does not exist in either location, create a new file in the inbox directory
/home/justin.guest/Developer/obsidian-vault/Inbox/<Name>.md and format the contact note following these strict standards:
- Report success and confirm creation in the inbox directory.
If no discovered contacts are found, proceed to Phase 3.
Phase 3 — Work Log Draft & Alignment
Draft today's work log, align with Justin, and write it to today's daily note. This step runs towards the end of the wind-down so that any activities, contact creations, log files, or inbox triage completed during previous steps are fully incorporated, ensuring the work log captures the final state of play for the day.
-
Calculate Dates:
- Determine
TARGET_DATE as today (e.g., 2026-06-07 in local time).
- Pre-compute timezone offsets dynamically to prevent UTC boundary leakage on calendar searches.
-
Gather Today's Raw Activities (Fast-track):
- Gather live activity from multiple direct sources:
- Calendar: Run Google Workspace calendar search with local timezone offset (e.g.,
python3 ~/.hermes/skills/productivity/google-workspace/scripts/gws_multi.py --account all calendar list --start <YYYY-MM-DD>T00:00:00<OFFSET> --end <YYYY-MM-DD>T23:59:59<OFFSET>).
- Slack: Run two searches for messages from/to Justin (e.g.,
python3 ~/.hermes/skills/social-media/slack/scripts/slack.py search 'from:@justin after:<YESTERDAY_DATE> before:<TOMORROW_DATE>' --limit 50).
- Linear: Query the Linear GraphQL API via Python's
urllib.request using LINEAR_API_KEY from ~/.hermes/.env (no "Bearer" prefix) to retrieve issues updated today where Justin is assignee, creator, or subscriber.
- TaskNotes & Task Management: Task management is fully handled via the TaskNotes Obsidian plugin. Scan the Vault Git history for file additions/deletions/renames under
TaskNotes/Tasks/ and TaskNotes/Archive/ to identify newly added, completed, or archived tasks.
- Vault Git: Check git history of the vault to capture manual notes, budget checks, and task status edits Justin made today (e.g.,
git -C ~/Developer/obsidian-vault log --since="<YYYY-MM-DD> 00:00:00" --until="<YYYY-MM-DD> 23:59:59" --name-status --pretty=format:"COMMIT:%h|%an|%s"). Filter out commits from Apollo (apollo-vm) or containing apollo to isolate Justin's manual edits, paying close attention to modified tasks or newly created budget check files.
- Read today's existing Obsidian daily note with
read_file to see manual scratchpad entries.
- Search the vault for any meeting/Granola notes generated today (look in
vault/Meetings/ or files containing today's date in their name).
- Read the daily briefing cache
/home/justin.guest/.hermes/morning-briefing/<YYYY-MM-DD>.json to check the vault_activity field, and run a quick terminal find command over the vault to gather any high-level vault restructuring, bulk updates, or manual categorization sweeps that took place during the day.
-
Synthesize the Work Log Draft:
- Synthesize the gathered material into a set of clean, structured blocks matching the standard work log format:
- Preview Summary: A highly concise, 1-2 sentence active-voice overview of the day's main focus.
- 🗓 Schedule & Events: Chronological bullet list of today's and tomorrow's meetings and events (shared with the Morning Briefing).
- ✅ Work Log: Synthesized highlights, bolded decisions (with accurate attribution), and open questions/blockers (omitting redundant accomplishments/completed tasks).
-
Present the Draft to Justin:
- Deliver the formatted draft in chat.
- Ask a short, focused question to capture offline context:
"Here is the draft of today's work log. Anything else from today that isn't captured here (e.g., side-quests, offline discussions, IRL decisions)?"
- Wait for Justin's response.
-
Write the Finalized Work Log:
- Combine Justin's feedback with the draft.
- Find or create today's daily note in
/home/justin.guest/Developer/obsidian-vault/Daily Notes/YYYY-MM-DD Weekday.md (create from template /home/justin.guest/Developer/obsidian-vault/Utilities/Templates/daily_note.md if missing, stripping Templater tags).
- Overwrite/replace the corresponding headings (
> [!summary], ## 🗓 Schedule & Events for Today's and Tomorrow's events, and ## ✅ Work Log with the subheading ### 🚀 Highlights & Decisions) with your new synthesized content.
- Crucial: Preserve the entire content of the
## 🌄 Morning Briefing section. Never modify or delete it.
- Append the sources attribution footer at the very bottom.
Phase 4 — Tomorrow's Calendar Preview & Close-out
Preview tomorrow's schedule to establish mental readiness, coordinate upcoming tasks, and close out the day.
-
Fetch Tomorrow's Schedule:
-
Present Tomorrow's Preview:
- Output a clean, chronological bullet list:
- **HH:MM - HH:MM** Event Title [Account/Context]
- Call out noteworthy patterns:
- Back-to-back blocks or intense scheduling.
- High-prep meetings or external attendees.
- First event of the day (so he knows when his morning starts).
-
Close out:
- Ask for Justin's acknowledgment.
- Once acknowledged, end with a quiet, minimal sign-off (e.g., "Have a good evening, Justin. See you tomorrow.").
Tone and Pacing
- Keep explanations minimal. Do not use filler or hedging theater.
- One phase per message. Do not dump the entire session at once.
- Wait for Justin's explicit go-ahead or text response between phases.
Pitfalls & Defensive Rules
- No Project Discovery in Wind-Down: Never attempt to run live project discovery or suggest project note creations during the wind-down session. Project suggestions are too noisy for this workflow; instead, project entity matching and timeline appends are handled exclusively via the automated ingest pipelines (
integrate-entities).
- Scratchpad Redirection: Quick notes or captured items during wind-down or on-the-go should go to the single global
/Inbox/Scratchpad.md note (categorized under # ✅ Tasks or # 🗒 Notes headings) rather than the daily note, which has retired its Scratchpad heading.
- Inputs Terminology: Always refer to Slack threads, emails, and other primary-category sources as "inputs" rather than "logs" in both conversations and note frontmatter, as per the updated vault schema.
- Accurate Attribution: When drafting highlights and decisions from emails or meeting notes, ensure decisions are attributed to the correct person (e.g., Anya, Nana, teachers, etc.) rather than assuming Justin made them.
- Accurate Assumption/Feasibility Status: Be extremely precise about what has actually been validated versus what remains an open question when drafting research findings. Always bound claims strictly to the scope of what was directly tested.
- Escape Slack Channels: Always write
#channel-name as \#channel-name inside the daily note so Obsidian doesn't parse it as a tag.
- Dynamic Timezone Offset: When fetching calendar events, always calculate and append the local timezone offset (e.g.
-04:00 or -05:00) to --start and --end to prevent boundary events from leaking from yesterday or tomorrow.
- Vault Sync Policy: The vault is synchronized via Obsidian Sync. Do not run automatic git commits or pushes. Git is only used manually for safety commits before major changes.
- TaskNotes Rule: Since task management is fully handled via the TaskNotes Obsidian plugin (
TaskNotes/Tasks/ and TaskNotes/Archive/), prioritize capturing task status changes (completed, archived, or added) directly from vault git history of the TaskNotes/ directory.
- Frontmatter Safety & Infinite Loops: Avoid extracting body content in a way that includes leading newlines, preventing infinite overwrite loops during hygiene tasks. Always
.lstrip() body content immediately upon extraction.
- Dangling Closing Dividers: Ensure any automated or manual procedure that adds or updates properties writes back the closing divider (
---) on a fresh line. Writing it without an intervening newline will append it directly to the end of the last property string (e.g., daily_note: '...'---), which corrupts properties.
- Non-Unique Aliases Guard: Always skip auto-linking any alias that is non-unique (shared by more than one distinct contact path) to avoid incorrect connections in the vault.
- Timelines Deactivation: Contact timelines are completely retired. Do not create
## Timeline sections or append timeline entries to contact cards during wind-down or ingestion; rely on Obsidian's native Backlinks panel instead. Project timelines are similarly disabled in favor of state/decision updates.
Verification Checklist