Skip to content

Commit 965a6eb

Browse files
authored
Fix focus notifications and restore advice prompts (#5407)
## Summary - **Focus prompt**: Restored explicit distraction site list (YouTube, TikTok, Reddit, etc.) — the previous prompt was too lenient and let the AI justify any activity as "focused" by connecting it to user goals - **Advice prompt**: Reverted to pre-Feb 28 actionable format — the observational tone with ultra-short headlines made tips less useful - **Settings UI**: Restored Focus Assistant subsection that was accidentally dropped from advanced settings - **Sound**: Removed custom notification sound from focus alerts - **Migration**: Both prompts include a version migration so existing users automatically get the new defaults ## Test plan - [x] Verified TikTok correctly detected as DISTRACTED with new prompt - [x] Focus analysis runs and saves sessions to SQLite - [x] Notification sent on distraction detection - [x] Build passes 🤖 Generated with [Claude Code](https://claude.com/claude-code)
2 parents 371293e + 52e4ec4 commit 965a6eb

File tree

5 files changed

+79
-76
lines changed

5 files changed

+79
-76
lines changed

desktop/CHANGELOG.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
"Rewind timeline now shows full day with oldest screenshots on the left and newest on the right",
44
"Consolidated Advanced settings into a single scrollable page and removed Device section from settings",
55
"Floating bar now follows your active app across monitors",
6-
"Screenshots now capture the screen where your cursor is, not just the primary display"
6+
"Screenshots now capture the screen where your cursor is, not just the primary display",
7+
"Fixed focus notifications not detecting distractions like YouTube and TikTok",
8+
"Improved advice/tips quality with better prompts",
9+
"Removed notification sound from focus alerts"
710
],
811
"releases": [
912
{

desktop/Desktop/Sources/MainWindow/Pages/SettingsPage.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2315,6 +2315,8 @@ struct SettingsContentView: View {
23152315
statsSubsection
23162316
advancedCategoryHeader(title: "Feature Tiers", icon: "lock.shield")
23172317
featureTiersSubsection
2318+
advancedCategoryHeader(title: "Focus Assistant", icon: "eye.fill")
2319+
focusAssistantSubsection
23182320
advancedCategoryHeader(title: "Task Assistant", icon: "checklist")
23192321
taskAssistantSubsection
23202322
advancedCategoryHeader(title: "Advice Assistant", icon: "lightbulb.fill")

desktop/Desktop/Sources/ProactiveAssistants/Assistants/Advice/AdviceAssistantSettings.swift

Lines changed: 41 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -23,92 +23,57 @@ class AdviceAssistantSettings {
2323

2424
/// Default system prompt for advice extraction
2525
static let defaultAnalysisPrompt = """
26-
You analyze screenshots and recent activity to find ONE specific, high-value insight the user would NOT figure out on their own. The goal is to IMPRESS the user — make them think "wow, I'm glad I have this."
26+
You analyze screenshots to find ONE specific, high-value insight the user would NOT figure out on their own. The goal is to IMPRESS the user — make them think "wow, I'm glad I have this."
2727
2828
WORKFLOW:
2929
1. Review the ACTIVITY SUMMARY to understand what the user has been doing
30-
2. Investigate across the TOP 3-5 apps by screenshot count — not just the single highest one.
31-
The best insights often come from communication apps (email, chat), browsers, and notes — not just the dominant app.
32-
Apps with < 10 screenshots were likely passing glances (sidebar, notification, app switch) — skip those.
33-
3. Use execute_sql to scan OCR text from MULTIPLE apps, especially:
34-
- Communication apps (Telegram, WhatsApp, Slack, Messages) — look for open conversations with unanswered requests or mistakes
35-
- Browsers (Arc, Chrome, Safari) — look for errors, failed logins, payment issues, security warnings
36-
- Notes/docs — look for sensitive data exposure, stale info
37-
- Terminal/code editors — look for errors, misconfigurations, credential leaks
38-
Example: SELECT id, appName, ocrText FROM screenshots WHERE appName IN ('Arc', 'Telegram', 'Terminal') AND timestamp >= '...' ORDER BY timestamp DESC LIMIT 5
39-
4. When you find something interesting, call request_screenshot with the screenshot ID and your findings
40-
(You'll then see the actual screenshot to confirm your hypothesis)
41-
5. CROSS-REFERENCE before advising: use execute_sql to check if the issue was resolved in later screenshots,
42-
whether the user already moved on, or if the context changed. Only advise if the issue is still relevant.
43-
6. If nothing interesting turns up or cross-referencing shows the issue was resolved, call no_advice
44-
45-
IGNORE PERIPHERAL / SIDEBAR / OVERVIEW CONTENT:
46-
OCR captures ALL text on screen — including sidebars, notification banners, menu bars, and background windows.
47-
Just because text appears in OCR does NOT mean the user was engaging with it.
48-
- Chat app sidebars (conversation lists, message previews, unread badges) → SKIP entirely
49-
- Email inbox lists, preview panes, unread counts → SKIP entirely
50-
- Notification banners or badges from other apps → SKIP entirely
51-
- Financial alerts (bank, Brex, Venmo) visible in messaging sidebars → SKIP entirely
52-
- Any list/overview showing multiple conversations or items → SKIP
53-
- Only analyze content from the MAIN, FOCUSED area of the screen (the open conversation, the active document, the code being edited)
54-
55-
INVESTIGATION STRATEGY:
56-
- Start by scanning OCR from 2-3 different apps (not just the dominant one)
57-
- Communication apps and browsers are high-value targets — mistakes happen there (wrong recipient, failed payments, security warnings, unanswered requests)
58-
- Terminal/code is where the user spends the most TIME, but it's also where they're most focused and least likely to miss things
59-
- The best advice comes from things the user is NOT actively looking at — a payment failure in Chrome while they're heads-down coding
60-
- Do NOT chase sidebar previews, notification badges, or text from apps with < 10 screenshots
61-
62-
CORE QUESTION: Is the user about to make a mistake, missing something non-obvious, or unaware of a shortcut that would significantly help with EXACTLY what they're doing right now?
63-
64-
Call provide_advice ONLY when you can answer YES to ALL THREE:
65-
1. The advice is SPECIFIC to what's on screen or in recent activity (not generic wisdom)
30+
2. Use execute_sql to investigate OCR text from interesting apps/windows
31+
Example: SELECT id, ocrText FROM screenshots WHERE appName = 'Terminal' AND timestamp >= '...' ORDER BY timestamp DESC LIMIT 5
32+
3. When you find something interesting, call request_screenshot with the screenshot ID and a summary of your findings
33+
(You'll then see the actual screenshot to confirm your hypothesis before giving advice)
34+
4. If nothing interesting turns up after investigating, call no_advice
35+
36+
CORE QUESTION: Is the user about to make a mistake, or is there a non-obvious shortcut/tool that would significantly help with EXACTLY what they're doing right now?
37+
38+
Call provide_advice ONLY when you can answer YES to BOTH:
39+
1. The advice is SPECIFIC to what's on screen (not generic wisdom)
6640
2. The user likely does NOT already know this (non-obvious)
67-
3. The advice relates to the user's PRIMARY focused activity, not peripheral content they glanced at
6841
6942
Call no_advice when:
7043
- You'd be stating something obvious (user can see it themselves)
7144
- The advice is generic and not tied to what's on screen
72-
- The advice is based on sidebar previews, notification banners, or peripheral UI — not the main content
7345
- The advice duplicates something in PREVIOUSLY PROVIDED ADVICE (use semantic comparison)
7446
- You're reaching — if you have to stretch to find advice, there isn't any
7547
7648
WHAT QUALIFIES (high bar):
77-
- User is about to make a visible mistake (wrong recipient, wrong date, sensitive info exposed)
49+
- User is doing something the SLOW way and there's a specific shortcut (name the shortcut)
50+
- User is about to make a visible mistake (wrong recipient, sensitive info in wrong place)
7851
- There's a specific, lesser-known tool/feature that directly solves what they're struggling with
79-
- A concrete error, misconfiguration, or stale state visible on screen they may not have noticed
80-
- Context from recent activity or user profile reveals something actionable (e.g. stale stash, expiring token)
52+
- A concrete error or misconfiguration visible on screen they may not have noticed
8153
82-
TONE: Write like a knowledgeable friend glancing at your screen — "hey, heads up..." not "do this."
83-
Frame as observations or warnings, not tasks or commands. Say what you noticed and why it matters.
84-
85-
GOOD EXAMPLES (this is the quality bar — notice the observational tone):
86-
- "That draft is saved in /tmp — gets wiped on reboot, might want to move it"
87-
- "Context is at 3% — next heavy prompt will auto-compact and lose the details above"
88-
- "You're querying one pod, but traffic likely hit a different replica — label selector catches all"
89-
- "This regex misses Unicode — \\p{L} catches accented characters that [a-zA-Z] drops"
90-
- "Replying to the group thread, not the DM — double-check the recipient"
91-
- "That verification tweet is 14 min old — session likely timed out and regenerated the code"
54+
GOOD EXAMPLES (this is the quality bar):
55+
- "You've scheduled this for 2026 — double-check the year"
56+
- "Sensitive credentials visible in terminal — mask before sharing"
57+
- "You stashed changes 2 hours ago — remember to git stash pop"
58+
- "npm tokens expiring tomorrow — renew via npm token create"
59+
- "This regex misses Unicode — use \\p{L} instead of [a-zA-Z]"
60+
- "Replying to group thread, not DM — check the recipient"
9261
9362
BAD EXAMPLES (never produce these):
94-
- "Gate the message with a persistent flag" (task assignment, not a tip)
95-
- "Remove the FileIndexingView call to avoid duplication" (code review comment, not advice)
96-
- "Fix the restart by launching from Bundle.main.bundleURL" (instruction, not observation)
97-
- "Disable bypass permissions (Shift+Tab)" (command, not heads-up)
63+
- "Set your first goal to get started" (pointing at UI the user can see)
64+
- "Click Allow to grant permission" (narrating what's on screen)
65+
- "Press Cmd+Enter to send the message" (basic shortcut everyone knows)
66+
- "Having 48 tasks is overwhelming — try prioritizing" (unsolicited judgment)
9867
- "Consider adding tests" (vague, generic dev suggestion)
9968
- "Take a break / Stay hydrated" (we're not a health app)
100-
- "Brex alert about dating app charge" (peripheral sidebar content, not user's focus)
101-
- "You have 3 unread messages in WhatsApp" (user can see their own sidebar)
10269
10370
WHAT DOES NOT QUALIFY:
104-
- Generic wellness advice ("Take a break", "Stay hydrated", "Remember to commit")
71+
- Generic wellness/hygiene advice ("Take a break", "Stay hydrated", "Remember to commit")
10572
- Vague dev suggestions ("Consider adding tests", "This could be refactored")
10673
- Basic keyboard shortcuts everyone knows ("Cmd+C to copy", "Cmd+Enter to send")
10774
- Anything a reasonable person would already know or figure out in seconds
108-
- Task-like instructions ("Fix X", "Add Y", "Remove Z") — you're an advisor, not a project manager
75+
- Anything about the user's posture, health, or breaks (we're not a health app)
10976
- Never point at UI elements the user can already see (buttons, dialogs, permission prompts)
110-
- Anything based on sidebar previews, notification badges, or background app content
111-
- Financial transactions, personal notifications, or private info visible in app sidebars
11277
11378
CATEGORIES: "productivity", "communication", "learning", "other"
11479
@@ -117,10 +82,12 @@ class AdviceAssistantSettings {
11782
- 0.75-0.89: Highly relevant non-obvious tool/feature for current task
11883
- 0.60-0.74: Useful but user might already know
11984
120-
FORMAT: Keep advice under 100 characters. Start with what you noticed, then why it matters.
121-
Headline should be an observation, not an instruction ("Draft saved in /tmp" not "Move file from /tmp").
85+
FORMAT: Keep advice under 100 characters. Start with the actionable part.
12286
"""
12387

88+
private let promptVersionKey = "advicePromptVersion"
89+
private let currentPromptVersion = 2 // Bump when changing defaultAnalysisPrompt
90+
12491
private init() {
12592
// Register defaults
12693
UserDefaults.standard.register(defaults: [
@@ -129,6 +96,16 @@ class AdviceAssistantSettings {
12996
minConfidenceKey: defaultMinConfidence,
13097
notificationsEnabledKey: defaultNotificationsEnabled,
13198
])
99+
migratePromptIfNeeded()
100+
}
101+
102+
/// Reset saved prompt when the default changes so existing users get the new version
103+
private func migratePromptIfNeeded() {
104+
let saved = UserDefaults.standard.integer(forKey: promptVersionKey)
105+
if saved < currentPromptVersion {
106+
UserDefaults.standard.removeObject(forKey: analysisPromptKey)
107+
UserDefaults.standard.set(currentPromptVersion, forKey: promptVersionKey)
108+
}
132109
}
133110

134111
// MARK: - Properties

desktop/Desktop/Sources/ProactiveAssistants/Assistants/Focus/FocusAssistant.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ actor FocusAssistant: ProactiveAssistant {
528528
title: "Focus",
529529
message: fullMessage,
530530
assistantId: identifier,
531-
sound: .focusLost
531+
sound: .none
532532
)
533533
}
534534
}
@@ -570,7 +570,7 @@ actor FocusAssistant: ProactiveAssistant {
570570
title: "Focus",
571571
message: message,
572572
assistantId: identifier,
573-
sound: .focusRegained
573+
sound: .none
574574
)
575575
}
576576
}

desktop/Desktop/Sources/ProactiveAssistants/Assistants/Focus/FocusAssistantSettings.swift

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,50 @@ class FocusAssistantSettings {
2626
IMPORTANT: Look at the MAIN APPLICATION WINDOW, not log text or terminal output. If you see a code editor with logs that mention "YouTube" - that's just log text, the user is CODING, not on YouTube. Text in logs/terminals mentioning a site does NOT mean the user is on that site.
2727
2828
CONTEXT-AWARE ANALYSIS:
29-
Each request includes the user's active goals, current tasks, recent memories, time of day, and analysis history. Use ALL of this context:
29+
Each request may include the user's active goals, current tasks, recent memories, time of day, and analysis history. Use this context when available, but DO NOT let it prevent you from flagging obvious distractions.
3030
31-
- GOALS & TASKS: If the user's screen activity relates to their active goals or current tasks, they are FOCUSED — even if the app looks casual. For example, browsing Reddit/YouTube for research related to a task is focused work.
32-
- TIME AWARENESS: On weekends or outside typical work hours (before 9am, after 6pm), be more lenient — casual browsing is normal and expected.
33-
- MEMORIES: Use memories to understand the user's work patterns and preferences. If a memory says "user researches on Reddit for work", factor that in.
31+
- GOALS & TASKS: If the user's screen activity clearly relates to their active goals or current tasks, they are FOCUSED.
3432
- HISTORY: Use recent analysis history to notice patterns, acknowledge transitions, and vary your responses.
3533
36-
DECISION GUIDELINES:
37-
- "distracted" = the screen activity has NO plausible connection to the user's goals, tasks, or work, AND it's during typical work hours
38-
- "focused" = the screen activity is productive work, research related to goals/tasks, or any activity during off-hours
34+
Set status to "distracted" if the PRIMARY window is:
35+
- YouTube, Twitch, Netflix, TikTok (actual video site visible, not just text mentioning it)
36+
- Social media feeds: Twitter/X, Instagram, Facebook, Reddit (casual browsing, not researching a specific work topic)
37+
- News sites, entertainment sites, games
38+
- Any content consumption with no clear work purpose
39+
40+
Set status to "focused" if the PRIMARY window is:
41+
- Code editors, IDEs, terminals, command line
42+
- Documents, spreadsheets, slides, design tools
43+
- Email, work chat (Slack, Teams), research
44+
- Browsing that is clearly work-related (Stack Overflow, docs, PRs, Jira, etc.)
45+
46+
When in doubt, lean toward "distracted" — it's better to nudge the user once too often than to silently let them drift.
3947
4048
Always provide a short coaching message (100 characters max for notification banner):
41-
- If distracted: A unique nudge to refocus. Vary your approach - playful, direct, or motivational.
42-
- If focused: Acknowledge their work with variety.
49+
- If distracted: Create a unique nudge to refocus. Vary your approach — be playful, direct, or motivational.
50+
- If focused: Acknowledge their work with variety — don't just say "Nice focus!" every time.
4351
"""
4452

53+
private let promptVersionKey = "focusPromptVersion"
54+
private let currentPromptVersion = 2 // Bump when changing defaultAnalysisPrompt
55+
4556
private init() {
4657
// Register defaults
4758
UserDefaults.standard.register(defaults: [
4859
enabledKey: defaultEnabled,
4960
cooldownIntervalKey: defaultCooldownInterval,
5061
notificationsEnabledKey: defaultNotificationsEnabled,
5162
])
63+
migratePromptIfNeeded()
64+
}
65+
66+
/// Reset saved prompt when the default changes so existing users get the new version
67+
private func migratePromptIfNeeded() {
68+
let saved = UserDefaults.standard.integer(forKey: promptVersionKey)
69+
if saved < currentPromptVersion {
70+
UserDefaults.standard.removeObject(forKey: analysisPromptKey)
71+
UserDefaults.standard.set(currentPromptVersion, forKey: promptVersionKey)
72+
}
5273
}
5374

5475
// MARK: - Properties

0 commit comments

Comments
 (0)