From 9af6a603c0bfc0e6187d8d15d3542b82a1e949fd Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Thu, 5 Feb 2026 02:16:17 -0600 Subject: [PATCH 1/5] Remove outdated LLM feedback synopsis notification trigger The LLM analysis feedback synopsis feature was previously removed, but the documentation about it remained in both the UI and docs. --- docs/configuration.md | 1 - src/renderer/components/NotificationsPanel.tsx | 4 ---- 2 files changed, 5 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 78f6a6f4..2a92f2ee 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -112,7 +112,6 @@ In-app toast notifications appear in the corner when events occur. Configure how Notifications are sent when: - An AI task completes (OS notification + optional custom notification) - A long-running command finishes (OS notification) -- The LLM analysis generates a feedback synopsis (custom notification only, if configured) ## Sleep Prevention diff --git a/src/renderer/components/NotificationsPanel.tsx b/src/renderer/components/NotificationsPanel.tsx index 7731d4ed..ae85beff 100644 --- a/src/renderer/components/NotificationsPanel.tsx +++ b/src/renderer/components/NotificationsPanel.tsx @@ -306,10 +306,6 @@ export function NotificationsPanel({
Date: Thu, 5 Feb 2026 02:56:55 -0600 Subject: [PATCH 2/5] Improve custom notification logging to reflect actual trigger state - Update ToastContext to compute willTriggerCustomNotification before logging - audioNotification.enabled now only true when notification WILL be sent - Add reason field to explain why notification was skipped (disabled, no-command, opted-out, no-content) - Bump notification skip log from debug to info level in IPC handler - Update test to match new audioNotification format with reason field --- .../renderer/contexts/ToastContext.test.tsx | 2 +- src/main/ipc/handlers/notifications.ts | 5 ++- src/renderer/contexts/ToastContext.tsx | 41 +++++++++++++------ 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/__tests__/renderer/contexts/ToastContext.test.tsx b/src/__tests__/renderer/contexts/ToastContext.test.tsx index 1439da50..78c3a7e9 100644 --- a/src/__tests__/renderer/contexts/ToastContext.test.tsx +++ b/src/__tests__/renderer/contexts/ToastContext.test.tsx @@ -271,7 +271,7 @@ describe('ToastContext', () => { taskDuration: 5000, agentSessionId: 'test-session-id', tabName: 'TestTab', - audioNotification: { enabled: false }, + audioNotification: { enabled: false, reason: 'disabled' }, }); }); diff --git a/src/main/ipc/handlers/notifications.ts b/src/main/ipc/handlers/notifications.ts index 5df413cb..afcdedee 100644 --- a/src/main/ipc/handlers/notifications.ts +++ b/src/main/ipc/handlers/notifications.ts @@ -364,7 +364,10 @@ export function registerNotificationsHandlers(): void { async (_event, text: string, command?: string): Promise => { // Skip if there's no content to send if (!text || text.trim().length === 0) { - logger.debug('Notification skipped - no content to send', 'Notification'); + logger.info('Notification skipped - empty or whitespace-only content', 'Notification', { + textLength: text?.length ?? 0, + hasText: !!text, + }); return { success: true }; // Return success since there's nothing to do } diff --git a/src/renderer/contexts/ToastContext.tsx b/src/renderer/contexts/ToastContext.tsx index 8f7ca541..124bcfa2 100644 --- a/src/renderer/contexts/ToastContext.tsx +++ b/src/renderer/contexts/ToastContext.tsx @@ -98,7 +98,16 @@ export function ToastProvider({ // Capture audio feedback state for logging const { enabled: audioEnabled, command: audioCommand } = audioFeedbackRef.current; + // Determine if we have content to send for custom notification + // Also skip if there's no content to send + const hasContent = toast.message && toast.message.trim().length > 0; + + // Determine if custom notification will actually be triggered + const willTriggerCustomNotification = + audioEnabled && audioCommand && !toast.skipCustomNotification && hasContent; + // Log toast to system logs (include audio notification info) + // Only log enabled: true when we will actually trigger the notification window.maestro.logger.toast(toast.title, { type: toast.type, message: toast.message, @@ -107,23 +116,29 @@ export function ToastProvider({ taskDuration: toast.taskDuration, agentSessionId: toast.agentSessionId, tabName: toast.tabName, - // Audio/TTS notification info - audioNotification: - audioEnabled && audioCommand - ? { - enabled: true, - command: audioCommand, - } - : { - enabled: false, - }, + // Audio/TTS notification info - reflects whether notification WILL be triggered + audioNotification: willTriggerCustomNotification + ? { + enabled: true, + command: audioCommand, + } + : { + enabled: false, + reason: !audioEnabled + ? 'disabled' + : !audioCommand + ? 'no-command' + : toast.skipCustomNotification + ? 'opted-out' + : !hasContent + ? 'no-content' + : 'unknown', + }, }); // Run custom notification command if enabled and configured // Skip for toasts that explicitly opt out (e.g., synopsis messages) - // Also skip if there's no content to send - const hasContent = toast.message && toast.message.trim().length > 0; - if (audioEnabled && audioCommand && !toast.skipCustomNotification && hasContent) { + if (willTriggerCustomNotification) { console.log( '[ToastContext] Running custom notification with message:', toast.message, From d7e1b45bc16e1a0c68355a676f94187e0697a1ca Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Thu, 5 Feb 2026 14:05:46 -0600 Subject: [PATCH 3/5] Fix keyboard shortcuts to show platform-appropriate text (fixes #294) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Display "Ctrl+Enter" on Windows/Linux instead of macOS-specific "Command+Enter" and "⌘ + Enter" symbols. Uses isMacOS() helper from shortcutFormatter.ts to detect platform and render appropriate text. --- .../integration/AutoRunRightPanel.test.tsx | 1 + .../integration/AutoRunSessionList.test.tsx | 1 + .../components/AutoRunExpandedModal.test.tsx | 1 + .../components/AutoRunnerHelpModal.test.tsx | 1 + .../renderer/components/FilePreview.test.tsx | 1 + .../InlineWizard/WizardInputPanel.test.tsx | 5 +++-- .../renderer/components/InputArea.test.tsx | 9 +++++---- .../renderer/components/MainPanel.test.tsx | 1 + .../components/PromptComposerModal.test.tsx | 5 +++-- .../renderer/components/QuickActionsModal.test.tsx | 1 + .../renderer/components/RightPanel.test.tsx | 1 + .../renderer/components/SettingsModal.test.tsx | 6 ++++-- .../renderer/components/ShortcutEditor.test.tsx | 1 + src/renderer/components/GroupChatInput.tsx | 6 +++--- .../components/InlineWizard/WizardInputPanel.tsx | 5 +++-- src/renderer/components/InputArea.tsx | 6 +++--- src/renderer/components/PromptComposerModal.tsx | 5 +++-- src/renderer/components/SettingsModal.tsx | 14 +++++++------- .../Wizard/screens/ConversationScreen.tsx | 3 ++- 19 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/__tests__/integration/AutoRunRightPanel.test.tsx b/src/__tests__/integration/AutoRunRightPanel.test.tsx index 9be7fd5f..dc3688c0 100644 --- a/src/__tests__/integration/AutoRunRightPanel.test.tsx +++ b/src/__tests__/integration/AutoRunRightPanel.test.tsx @@ -119,6 +119,7 @@ vi.mock('../../renderer/components/TemplateAutocompleteDropdown', () => ({ vi.mock('../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: vi.fn((keys) => keys?.join('+') || ''), + isMacOS: vi.fn(() => false), })); // Create a mock theme for testing diff --git a/src/__tests__/integration/AutoRunSessionList.test.tsx b/src/__tests__/integration/AutoRunSessionList.test.tsx index e5472c8a..8a4fc375 100644 --- a/src/__tests__/integration/AutoRunSessionList.test.tsx +++ b/src/__tests__/integration/AutoRunSessionList.test.tsx @@ -126,6 +126,7 @@ vi.mock('../../renderer/components/TemplateAutocompleteDropdown', () => ({ vi.mock('../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: vi.fn((keys) => keys?.join('+') || ''), + isMacOS: vi.fn(() => false), })); vi.mock('../../renderer/hooks/useGitStatusPolling', () => ({ diff --git a/src/__tests__/renderer/components/AutoRunExpandedModal.test.tsx b/src/__tests__/renderer/components/AutoRunExpandedModal.test.tsx index c43e0583..03e67c0a 100644 --- a/src/__tests__/renderer/components/AutoRunExpandedModal.test.tsx +++ b/src/__tests__/renderer/components/AutoRunExpandedModal.test.tsx @@ -96,6 +96,7 @@ vi.mock('../../../renderer/components/AutoRun', () => ({ // Mock shortcut formatter vi.mock('../../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: vi.fn((keys: string[]) => keys.join('+')), + isMacOS: vi.fn(() => false), })); // Create a mock theme for testing diff --git a/src/__tests__/renderer/components/AutoRunnerHelpModal.test.tsx b/src/__tests__/renderer/components/AutoRunnerHelpModal.test.tsx index f79b4d25..46aae932 100644 --- a/src/__tests__/renderer/components/AutoRunnerHelpModal.test.tsx +++ b/src/__tests__/renderer/components/AutoRunnerHelpModal.test.tsx @@ -38,6 +38,7 @@ vi.mock('../../../renderer/contexts/LayerStackContext', async () => { // Mock formatShortcutKeys to return predictable output vi.mock('../../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: (keys: string[]) => keys.join('+'), + isMacOS: () => false, })); // Sample theme for testing diff --git a/src/__tests__/renderer/components/FilePreview.test.tsx b/src/__tests__/renderer/components/FilePreview.test.tsx index a0e3a67c..8f5e398a 100644 --- a/src/__tests__/renderer/components/FilePreview.test.tsx +++ b/src/__tests__/renderer/components/FilePreview.test.tsx @@ -109,6 +109,7 @@ vi.mock('../../../renderer/utils/tokenCounter', () => ({ // Mock shortcut formatter vi.mock('../../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: vi.fn((keys: string) => keys), + isMacOS: vi.fn(() => false), })); // Mock remarkFileLinks diff --git a/src/__tests__/renderer/components/InlineWizard/WizardInputPanel.test.tsx b/src/__tests__/renderer/components/InlineWizard/WizardInputPanel.test.tsx index 148df502..fd87e756 100644 --- a/src/__tests__/renderer/components/InlineWizard/WizardInputPanel.test.tsx +++ b/src/__tests__/renderer/components/InlineWizard/WizardInputPanel.test.tsx @@ -333,9 +333,10 @@ describe('WizardInputPanel', () => { expect(screen.getByText('Enter')).toBeInTheDocument(); }); - it('shows "⌘ + Enter" when enterToSend is false', () => { + it('shows "⌘ + Enter" (or "Ctrl + Enter" on non-Mac) when enterToSend is false', () => { render(); - expect(screen.getByText('⌘ + Enter')).toBeInTheDocument(); + // Test environment doesn't have Mac user agent, so it shows Ctrl + Enter + expect(screen.getByText(/⌘ \+ Enter|Ctrl \+ Enter/)).toBeInTheDocument(); }); it('calls setEnterToSend when clicked', () => { diff --git a/src/__tests__/renderer/components/InputArea.test.tsx b/src/__tests__/renderer/components/InputArea.test.tsx index 6c3db3c8..72b03688 100644 --- a/src/__tests__/renderer/components/InputArea.test.tsx +++ b/src/__tests__/renderer/components/InputArea.test.tsx @@ -235,17 +235,18 @@ describe('InputArea', () => { const props = createDefaultProps(); render(); - const button = screen.getByTitle('Switch to Meta+Enter to send'); + const button = screen.getByTitle(/Switch to (Cmd|Ctrl)\+Enter to send/); expect(button).toBeInTheDocument(); expect(button).toHaveTextContent('Enter'); }); - it('renders Cmd+Enter when enterToSend is false', () => { + it('renders Cmd+Enter (or Ctrl+Enter on non-Mac) when enterToSend is false', () => { const props = createDefaultProps({ enterToSend: false }); render(); const button = screen.getByTitle('Switch to Enter to send'); - expect(button).toHaveTextContent('⌘ + Enter'); + // Test environment doesn't have Mac user agent, so it shows Ctrl + Enter + expect(button).toHaveTextContent(/⌘ \+ Enter|Ctrl \+ Enter/); }); }); @@ -1505,7 +1506,7 @@ describe('InputArea', () => { const props = createDefaultProps({ enterToSend: true, setEnterToSend }); render(); - fireEvent.click(screen.getByTitle('Switch to Meta+Enter to send')); + fireEvent.click(screen.getByTitle(/Switch to (Cmd|Ctrl)\+Enter to send/)); expect(setEnterToSend).toHaveBeenCalledWith(false); }); diff --git a/src/__tests__/renderer/components/MainPanel.test.tsx b/src/__tests__/renderer/components/MainPanel.test.tsx index 3f46d353..9adfa6bf 100644 --- a/src/__tests__/renderer/components/MainPanel.test.tsx +++ b/src/__tests__/renderer/components/MainPanel.test.tsx @@ -148,6 +148,7 @@ vi.mock('../../../renderer/utils/tabHelpers', () => ({ // Mock shortcut formatter vi.mock('../../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: vi.fn((keys: string[]) => keys?.join('+') || ''), + isMacOS: vi.fn(() => false), })); // Configurable git status data for tests - can be modified in individual tests diff --git a/src/__tests__/renderer/components/PromptComposerModal.test.tsx b/src/__tests__/renderer/components/PromptComposerModal.test.tsx index ed125fdd..eb59407e 100644 --- a/src/__tests__/renderer/components/PromptComposerModal.test.tsx +++ b/src/__tests__/renderer/components/PromptComposerModal.test.tsx @@ -185,8 +185,9 @@ describe('PromptComposerModal', () => { /> ); - // When enterToSend is false, it shows "⌘ + Enter" - expect(screen.getByText('⌘ + Enter')).toBeInTheDocument(); + // When enterToSend is false, it shows "⌘ + Enter" on Mac or "Ctrl + Enter" on other platforms + // Test environment doesn't have Mac user agent, so it shows Ctrl + Enter + expect(screen.getByText(/⌘ \+ Enter|Ctrl \+ Enter/)).toBeInTheDocument(); }); it('should render close button with X icon', () => { diff --git a/src/__tests__/renderer/components/QuickActionsModal.test.tsx b/src/__tests__/renderer/components/QuickActionsModal.test.tsx index 24396d71..fd9cb348 100644 --- a/src/__tests__/renderer/components/QuickActionsModal.test.tsx +++ b/src/__tests__/renderer/components/QuickActionsModal.test.tsx @@ -59,6 +59,7 @@ vi.mock('../../../renderer/services/git', () => ({ vi.mock('../../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: vi.fn((keys: string[]) => keys.join('+')), + isMacOS: vi.fn(() => false), })); // Mock lucide-react diff --git a/src/__tests__/renderer/components/RightPanel.test.tsx b/src/__tests__/renderer/components/RightPanel.test.tsx index 782266e1..a5c327d0 100644 --- a/src/__tests__/renderer/components/RightPanel.test.tsx +++ b/src/__tests__/renderer/components/RightPanel.test.tsx @@ -21,6 +21,7 @@ vi.mock('../../../renderer/components/AutoRun', () => ({ vi.mock('../../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: vi.fn((keys) => keys.join('+')), + isMacOS: vi.fn(() => false), })); // Mock lucide-react diff --git a/src/__tests__/renderer/components/SettingsModal.test.tsx b/src/__tests__/renderer/components/SettingsModal.test.tsx index d858f297..00029027 100644 --- a/src/__tests__/renderer/components/SettingsModal.test.tsx +++ b/src/__tests__/renderer/components/SettingsModal.test.tsx @@ -38,6 +38,7 @@ vi.mock('../../../renderer/contexts/LayerStackContext', () => ({ // Mock formatShortcutKeys vi.mock('../../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: vi.fn((keys: string[]) => keys.join('+')), + isMacOS: vi.fn(() => false), // Test environment is not Mac })); // Mock AICommandsPanel @@ -808,14 +809,15 @@ describe('SettingsModal', () => { expect(setEnterToSendTerminal).toHaveBeenCalledWith(false); }); - it('should display Cmd+Enter when enter-to-send is false', async () => { + it('should display Cmd+Enter (or Ctrl+Enter on non-Mac) when enter-to-send is false', async () => { render(); await act(async () => { await vi.advanceTimersByTimeAsync(100); }); - expect(screen.getByText('⌘ + Enter')).toBeInTheDocument(); + // Test environment doesn't have Mac user agent, so it shows Ctrl + Enter + expect(screen.getByText(/⌘ \+ Enter|Ctrl \+ Enter/)).toBeInTheDocument(); }); }); diff --git a/src/__tests__/renderer/components/ShortcutEditor.test.tsx b/src/__tests__/renderer/components/ShortcutEditor.test.tsx index 9309f27c..f18ee4c9 100644 --- a/src/__tests__/renderer/components/ShortcutEditor.test.tsx +++ b/src/__tests__/renderer/components/ShortcutEditor.test.tsx @@ -14,6 +14,7 @@ import type { Theme, Shortcut } from '../../../renderer/types'; // Mock the shortcutFormatter module vi.mock('../../../renderer/utils/shortcutFormatter', () => ({ formatShortcutKeys: vi.fn((keys: string[]) => keys.join('+')), + isMacOS: vi.fn(() => false), })); // Import after mock to get the mocked version diff --git a/src/renderer/components/GroupChatInput.tsx b/src/renderer/components/GroupChatInput.tsx index 0eaea199..8a4b5cc8 100644 --- a/src/renderer/components/GroupChatInput.tsx +++ b/src/renderer/components/GroupChatInput.tsx @@ -22,7 +22,7 @@ import type { QueuedItem, Shortcut, } from '../types'; -import { formatShortcutKeys } from '../utils/shortcutFormatter'; +import { formatShortcutKeys, isMacOS } from '../utils/shortcutFormatter'; import { QueuedItemsList } from './QueuedItemsList'; import { normalizeMentionName } from '../utils/participantColors'; @@ -549,10 +549,10 @@ export const GroupChatInput = React.memo(function GroupChatInput({
diff --git a/src/renderer/components/InlineWizard/WizardInputPanel.tsx b/src/renderer/components/InlineWizard/WizardInputPanel.tsx index 87d62a55..474d47c0 100644 --- a/src/renderer/components/InlineWizard/WizardInputPanel.tsx +++ b/src/renderer/components/InlineWizard/WizardInputPanel.tsx @@ -26,6 +26,7 @@ import type { Session, Theme } from '../../types'; import { WizardPill } from './WizardPill'; import { WizardConfidenceGauge } from './WizardConfidenceGauge'; import { WizardExitConfirmDialog } from './WizardExitConfirmDialog'; +import { isMacOS } from '../../utils/shortcutFormatter'; interface WizardInputPanelProps { /** Current session with wizard state */ @@ -322,10 +323,10 @@ export const WizardInputPanel = React.memo(function WizardInputPanel({ diff --git a/src/renderer/components/InputArea.tsx b/src/renderer/components/InputArea.tsx index a2265dd7..985e72dc 100644 --- a/src/renderer/components/InputArea.tsx +++ b/src/renderer/components/InputArea.tsx @@ -18,7 +18,7 @@ import { Pin, } from 'lucide-react'; import type { Session, Theme, BatchRunState, Shortcut, ThinkingMode } from '../types'; -import { formatShortcutKeys } from '../utils/shortcutFormatter'; +import { formatShortcutKeys, isMacOS } from '../utils/shortcutFormatter'; import type { TabCompletionSuggestion, TabCompletionFilter } from '../hooks'; import type { SummarizeProgress, @@ -1087,10 +1087,10 @@ export const InputArea = React.memo(function InputArea(props: InputAreaProps) { diff --git a/src/renderer/components/PromptComposerModal.tsx b/src/renderer/components/PromptComposerModal.tsx index bab1c271..cb8f3973 100644 --- a/src/renderer/components/PromptComposerModal.tsx +++ b/src/renderer/components/PromptComposerModal.tsx @@ -4,6 +4,7 @@ import type { Theme, ThinkingMode } from '../types'; import { useLayerStack } from '../contexts/LayerStackContext'; import { MODAL_PRIORITIES } from '../constants/modalPriorities'; import { estimateTokenCount } from '../../shared/formatters'; +import { isMacOS } from '../utils/shortcutFormatter'; interface PromptComposerModalProps { isOpen: boolean; @@ -450,11 +451,11 @@ export function PromptComposerModal({ )} diff --git a/src/renderer/components/SettingsModal.tsx b/src/renderer/components/SettingsModal.tsx index 89d79f8d..74a96277 100644 --- a/src/renderer/components/SettingsModal.tsx +++ b/src/renderer/components/SettingsModal.tsx @@ -49,7 +49,7 @@ import { MODAL_PRIORITIES } from '../constants/modalPriorities'; import { AICommandsPanel } from './AICommandsPanel'; import { SpecKitCommandsPanel } from './SpecKitCommandsPanel'; import { OpenSpecCommandsPanel } from './OpenSpecCommandsPanel'; -import { formatShortcutKeys } from '../utils/shortcutFormatter'; +import { formatShortcutKeys, isMacOS } from '../utils/shortcutFormatter'; import { ToggleButtonGroup } from './ToggleButtonGroup'; import { SettingCheckbox } from './SettingCheckbox'; import { FontConfigurationPanel } from './FontConfigurationPanel'; @@ -1302,8 +1302,8 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro Input Send Behavior

- Configure how to send messages in each mode. Choose between Enter or Command+Enter - for each input type. + Configure how to send messages in each mode. Choose between Enter or{' '} + {isMacOS() ? 'Command' : 'Ctrl'}+Enter for each input type.

{/* AI Mode Setting */} @@ -1324,13 +1324,13 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro border: `1px solid ${theme.colors.border}`, }} > - {props.enterToSendAI ? 'Enter' : '⌘ + Enter'} + {props.enterToSendAI ? 'Enter' : isMacOS() ? '⌘ + Enter' : 'Ctrl + Enter'}

{props.enterToSendAI ? 'Press Enter to send. Use Shift+Enter for new line.' - : 'Press Command+Enter to send. Enter creates new line.'} + : `Press ${isMacOS() ? 'Command' : 'Ctrl'}+Enter to send. Enter creates new line.`}

@@ -1352,13 +1352,13 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro border: `1px solid ${theme.colors.border}`, }} > - {props.enterToSendTerminal ? 'Enter' : '⌘ + Enter'} + {props.enterToSendTerminal ? 'Enter' : isMacOS() ? '⌘ + Enter' : 'Ctrl + Enter'}

{props.enterToSendTerminal ? 'Press Enter to send. Use Shift+Enter for new line.' - : 'Press Command+Enter to send. Enter creates new line.'} + : `Press ${isMacOS() ? 'Command' : 'Ctrl'}+Enter to send. Enter creates new line.`}

diff --git a/src/renderer/components/Wizard/screens/ConversationScreen.tsx b/src/renderer/components/Wizard/screens/ConversationScreen.tsx index 071e812a..d8cb4a37 100644 --- a/src/renderer/components/Wizard/screens/ConversationScreen.tsx +++ b/src/renderer/components/Wizard/screens/ConversationScreen.tsx @@ -34,6 +34,7 @@ import type { WizardError } from '../services/wizardErrorDetection'; import { AUTO_RUN_FOLDER_NAME, wizardDebugLogger } from '../services/phaseGenerator'; import { getNextFillerPhrase } from '../services/fillerPhrases'; import { ScreenReaderAnnouncement } from '../ScreenReaderAnnouncement'; +import { isMacOS } from '../../../utils/shortcutFormatter'; interface ConversationScreenProps { theme: Theme; @@ -1613,7 +1614,7 @@ export function ConversationScreen({ className="px-1.5 py-0.5 rounded text-xs" style={{ backgroundColor: theme.colors.border }} > - ⌘+Enter + {isMacOS() ? '⌘' : 'Ctrl'}+Enter Send From b908ed5d6eacea39baf9104947595287859cf690 Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Thu, 5 Feb 2026 14:42:59 -0600 Subject: [PATCH 4/5] docs: add Conductor Profile section to configuration docs Explains what the Conductor Profile is, how to configure it, what to include, and how agents use it. Previously only had brief parenthetical mentions without dedicated documentation. --- docs/configuration.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index 2a92f2ee..9f88c72f 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -20,6 +20,44 @@ Settings are organized into tabs: | **AI Commands** | View and edit slash commands, [Spec-Kit](./speckit-commands), and [OpenSpec](./openspec-commands) prompts | | **SSH Hosts** | Configure remote hosts for [SSH agent execution](./ssh-remote-execution) | +## Conductor Profile + +The **Conductor Profile** (Settings → General → **About Me**) is a short description of yourself that gets injected into every AI agent's system prompt. This helps agents understand your background, preferences, and communication style so they can tailor responses accordingly. + +**To configure:** +1. Open **Settings** (`Cmd+,` / `Ctrl+,`) → **General** tab +2. Find the **About Me** text area at the top +3. Write a brief profile describing yourself + +### What to Include + +A good conductor profile is concise (a few sentences to a short paragraph) and covers: + +- **Your role/background**: Developer, researcher, team lead, etc. +- **Technical context**: Languages you work with, tools you prefer, platforms you use +- **Communication preferences**: Direct vs. detailed, level of explanation needed +- **Work style**: Preferences for how agents should approach tasks + +### Example Profile + +``` +Security researcher. macOS desktop. TypeScript and Python for tools. +Direct communication, no fluff. Action over process. Push back on bad ideas. +Generate markdown for Obsidian. CST timezone. +``` + +### How Agents Use It + +When you start a session, Maestro includes your conductor profile in the system prompt sent to the AI agent. This means: + +- Agents adapt their response style to match your preferences +- Technical context helps agents make appropriate assumptions +- Communication preferences reduce back-and-forth clarification + +### Using in Custom Commands + +You can reference your conductor profile in [slash commands](./slash-commands) using the `{{CONDUCTOR_PROFILE}}` template variable. This is useful for commands that need to remind agents of your preferences mid-conversation. + ## Checking for Updates Maestro checks for updates automatically on startup (configurable in Settings → General → **Check for updates on startup**). From 1f080785d2ee9c3434b06d5a494cfd40901fe910 Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Thu, 5 Feb 2026 14:46:35 -0600 Subject: [PATCH 5/5] ## CHANGES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tab naming now preserves referenced PR, issue, and ticket IDs 🔖 - Added clear examples for PR numbers, issue numbers, and JIRA IDs 📌 --- src/prompts/tab-naming.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/prompts/tab-naming.md b/src/prompts/tab-naming.md index 5f5f4d92..4ac412b8 100644 --- a/src/prompts/tab-naming.md +++ b/src/prompts/tab-naming.md @@ -4,6 +4,7 @@ Rules: - 2-4 words max, shorter is better - Title Case, no punctuation - Be specific (mention tech/file names if relevant) +- Include ID numbers (PR #, issue #, ticket ID) when mentioned - Use hyphens for compound concepts - If too vague, use format: YYYY-MM-DD Topic @@ -13,4 +14,7 @@ Examples: "refactor DB queries for pooling" = DB Connection Pooling "write tests for checkout" = Checkout Tests "fix TS errors in parser.ts" = Parser TS Errors +"review PR #256" = PR 256 Review +"fix issue #42 memory leak" = Issue 42 Memory Leak +"implement JIRA-1234 feature" = JIRA-1234 Feature "help with my code" = 2024-01-15 Code Help