feat: Encore Feature system with gating infrastructure#473
feat: Encore Feature system with gating infrastructure#473felipeggv wants to merge 5 commits intoRunMaestro:mainfrom
Conversation
Extends the Encore Feature system with two new feature flags for upcoming Unified Inbox and Tab Description features. tabDescription defaults to true (enabled by default), unifiedInbox defaults to false. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…gs Encore tab - Import Inbox and FileText icons from lucide-react - Change Encore tab icon from FlaskConical to Sparkles per spec - Add Unified Inbox feature card with toggle, Beta badge, left-border accent - Add Tab Descriptions feature card with toggle, left-border accent - Both cards follow existing toggle pattern (spread-copy + flip flag) - All 113 SettingsModal tests pass, lint clean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…es encore features Add agentInbox shortcut (Alt+I) with encoreFeatures.unifiedInbox guard. Director's Notes shortcut already had its guard. Register agentInbox modal in the modal store and wire through App.tsx keyboard handler context. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nd unifiedInbox encore feature - Add onOpenAgentInbox gated prop (App.tsx → AppModals → QuickActionsModal) - Add AgentInbox rendering placeholder in App.tsx (commented, component TBD) - Add Unified Inbox entry to QuickActionsModal command palette - DirectorNotesModal gating was already in place from prior work Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…on consistency The tabDescription encore feature was defaulting to true, inconsistent with the encore pattern (all features disabled by default). No handler or UI exists yet for tab descriptions, so this is purely a default fix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review infoConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughThis PR introduces a new Agent Inbox feature with modal state management, keyboard shortcut (Alt+i), feature flags, and UI integration. Changes include modal state store updates, keyboard handler wiring, quick action menu entry, settings panel controls, and app-level callback exposure. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Keyboard as Keyboard Handler
participant UI as QuickActionsModal/<br/>SettingsModal
participant App as App.tsx
participant Store as Modal Store
participant Modal as Agent Inbox<br/>Modal
rect rgba(100, 150, 255, 0.5)
Note over User,Modal: Keyboard Shortcut Path (Alt+i)
User->>Keyboard: Press Alt+i
Keyboard->>Keyboard: Check unifiedInbox<br/>feature flag
Keyboard->>App: Call setAgentInboxOpen(true)
App->>Store: updateModal('agentInbox', true)
Store->>Modal: Re-render with open state
Modal->>User: Display Agent Inbox
end
rect rgba(150, 200, 100, 0.5)
Note over User,Modal: UI Click Path (Quick Actions)
User->>UI: Click "Unified Inbox"
UI->>App: Call onOpenAgentInbox()
App->>Store: updateModal('agentInbox', true)
Store->>Modal: Re-render with open state
Modal->>User: Display Agent Inbox
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Greptile SummaryAdds Encore Feature infrastructure for Unified Inbox and Tab Descriptions with proper feature gating
The implementation follows the established Director's Notes pattern from CLAUDE-PATTERNS.md with proper gating across keyboard shortcuts, command palette, and modal rendering. Confidence Score: 5/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
Start([User Action]) --> CheckFeature{Feature Enabled?}
CheckFeature -->|Yes| AllowAccess[Allow Access]
CheckFeature -->|No| BlockAccess[Block Access]
AllowAccess --> KB[Keyboard Shortcut Alt+I]
AllowAccess --> CP[Command Palette Entry]
AllowAccess --> Modal[Modal Rendering]
BlockAccess --> NoKB[No Keyboard Handler]
BlockAccess --> NoCP[No Command Palette Entry]
BlockAccess --> NoModal[No Modal]
subgraph Settings["Settings Store (settingsStore.ts)"]
SF[encoreFeatures.unifiedInbox: false]
SF2[encoreFeatures.tabDescription: false]
end
subgraph UI["Settings Modal UI"]
Toggle[Toggle Switch]
Toggle --> Update[Update encoreFeatures]
Update --> Persist[window.maestro.settings.set]
end
subgraph Gating["Feature Gates"]
KB --> Gate1{encoreFeatures?.unifiedInbox}
CP --> Gate2{onOpenAgentInbox !== undefined}
Modal --> Gate3{encoreFeatures.unifiedInbox && agentInboxOpen}
end
Settings --> CheckFeature
UI --> Settings
Last reviewed commit: 060ba44 |
📝 WalkthroughWalkthroughThis change adds support for two new encore features: Unified Inbox and Tab Descriptions. A new Agent Inbox modal is introduced with state management through the modal store, wired through the component hierarchy, accessible via keyboard shortcut (Alt+I) and Quick Actions menu, with UI toggles in Settings. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/renderer/components/SettingsModal.tsx (1)
3644-3772: Consider extracting a shared Encore toggle-card component.
Unified InboxandTab Descriptionsduplicate the same card/switch structure. A shared component will reduce drift and keep future feature toggles consistent.♻️ Proposed refactor sketch
+type EncoreToggleCardProps = { + enabled: boolean; + onToggle: () => void; + icon: React.ReactNode; + title: string; + description: string; + theme: Theme; + beta?: boolean; +}; + +const EncoreToggleCard = ({ + enabled, + onToggle, + icon, + title, + description, + theme, + beta, +}: EncoreToggleCardProps) => ( + <div + className="rounded-lg p-4" + style={{ + borderLeft: `3px solid ${enabled ? theme.colors.accent : theme.colors.border}`, + backgroundColor: enabled ? `${theme.colors.accent}08` : 'transparent', + }} + > + <button + className="w-full flex items-center justify-between text-left" + onClick={onToggle} + role="switch" + aria-checked={enabled} + > + {/* shared icon/title/description/switch UI */} + </button> + </div> +); ... - {/* Unified Inbox Feature Card */} - <div>...</div> - - {/* Tab Descriptions Feature Card */} - <div>...</div> + <EncoreToggleCard + enabled={encoreFeatures.unifiedInbox} + onToggle={() => + setEncoreFeatures({ ...encoreFeatures, unifiedInbox: !encoreFeatures.unifiedInbox }) + } + icon={<Inbox className="w-5 h-5" />} + title="Unified Inbox" + description="Aggregated view of pending actions across all agents" + theme={theme} + beta + /> + <EncoreToggleCard + enabled={encoreFeatures.tabDescription} + onToggle={() => + setEncoreFeatures({ + ...encoreFeatures, + tabDescription: !encoreFeatures.tabDescription, + }) + } + icon={<FileText className="w-5 h-5" />} + title="Tab Descriptions" + description="Show AI-generated descriptions below tab names for quick context" + theme={theme} + />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/renderer/components/SettingsModal.tsx` around lines 3644 - 3772, The two feature cards (Unified Inbox and Tab Descriptions) duplicate the same card + switch UI; extract a reusable component (e.g., EncoreFeatureToggle) that accepts props: id/key or value (boolean), onToggle (function), label (string), description (string), Icon (component), optional badge (e.g., "Beta"), and theme for styling, and preserves role="switch" and aria-checked behavior; replace the duplicated blocks in SettingsModal (the JSX using encoreFeatures.unifiedInbox/tabDescription and setEncoreFeatures) with calls to <EncoreFeatureToggle value={encoreFeatures.unifiedInbox} onToggle={() => setEncoreFeatures({...encoreFeatures, unifiedInbox: !encoreFeatures.unifiedInbox})} label="Unified Inbox" description="..." Icon={Inbox} badge="Beta" /> and similarly for tabDescription, ensuring the switch background/handle transform logic uses the passed value prop so visual state remains identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/renderer/App.tsx`:
- Line 3715: The onOpenAgentInbox prop is wired (onOpenAgentInbox,
setAgentInboxOpen, encoreFeatures.unifiedInbox) but the modal render
(AgentInboxModal) is commented out and the component is missing; restore or
implement the AgentInboxModal component and its render path: either re-enable
the existing render block for AgentInboxModal and ensure a concrete
AgentInboxModal component is created/ exported, or replace the commented block
with a call to a newly implemented AgentInboxModal that accepts isOpen and
onClose (tied to setAgentInboxOpen), and guard its rendering behind
encoreFeatures.unifiedInbox so the callback actually opens a real modal.
---
Nitpick comments:
In `@src/renderer/components/SettingsModal.tsx`:
- Around line 3644-3772: The two feature cards (Unified Inbox and Tab
Descriptions) duplicate the same card + switch UI; extract a reusable component
(e.g., EncoreFeatureToggle) that accepts props: id/key or value (boolean),
onToggle (function), label (string), description (string), Icon (component),
optional badge (e.g., "Beta"), and theme for styling, and preserves
role="switch" and aria-checked behavior; replace the duplicated blocks in
SettingsModal (the JSX using encoreFeatures.unifiedInbox/tabDescription and
setEncoreFeatures) with calls to <EncoreFeatureToggle
value={encoreFeatures.unifiedInbox} onToggle={() =>
setEncoreFeatures({...encoreFeatures, unifiedInbox:
!encoreFeatures.unifiedInbox})} label="Unified Inbox" description="..."
Icon={Inbox} badge="Beta" /> and similarly for tabDescription, ensuring the
switch background/handle transform logic uses the passed value prop so visual
state remains identical.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
src/renderer/App.tsxsrc/renderer/components/AppModals.tsxsrc/renderer/components/QuickActionsModal.tsxsrc/renderer/components/SettingsModal.tsxsrc/renderer/constants/shortcuts.tssrc/renderer/hooks/keyboard/useMainKeyboardHandler.tssrc/renderer/stores/modalStore.tssrc/renderer/stores/settingsStore.tssrc/renderer/types/index.ts
| onOpenDirectorNotes={ | ||
| encoreFeatures.directorNotes ? () => setDirectorNotesOpen(true) : undefined | ||
| } | ||
| onOpenAgentInbox={encoreFeatures.unifiedInbox ? () => setAgentInboxOpen(true) : undefined} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Agent Inbox state/callback references =="
rg -n --type=ts --type=tsx -C2 '\bagentInboxOpen\b|\bsetAgentInboxOpen\b|\bonOpenAgentInbox\b'
echo
echo "== Active AgentInboxModal JSX mounts (non-comment lines) =="
rg -nP --type=tsx '^\s*<AgentInboxModal\b' || true
echo
echo "== Any AgentInboxModal mentions (including comments) =="
rg -n --type=tsx 'AgentInboxModal'Repository: RunMaestro/Maestro
Length of output: 150
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check if the file exists and get its line count
if [ -f "src/renderer/App.tsx" ]; then
echo "== File found: src/renderer/App.tsx =="
wc -l src/renderer/App.tsx
echo
echo "== Lines around 3715 (callback setup) =="
sed -n '3710,3720p' src/renderer/App.tsx
echo
echo "== Lines 4111-4120 (alleged commented modal) =="
sed -n '4111,4120p' src/renderer/App.tsx
echo
echo "== Search for agentInboxOpen references =="
grep -n 'agentInboxOpen\|setAgentInboxOpen\|onOpenAgentInbox' src/renderer/App.tsx || echo "No matches found"
echo
echo "== Search for AgentInboxModal mentions =="
grep -n 'AgentInboxModal' src/renderer/App.tsx || echo "No matches found"
else
echo "File not found at src/renderer/App.tsx"
# List the directory structure
ls -la src/renderer/ 2>/dev/null || echo "src/renderer directory not found"
fiRepository: RunMaestro/Maestro
Length of output: 1523
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Search entire codebase for AgentInboxModal (excluding App.tsx) =="
find . -type f \( -name "*.tsx" -o -name "*.ts" -o -name "*.jsx" -o -name "*.js" \) -not -path "./node_modules/*" -not -path "./.git/*" | xargs grep -l 'AgentInboxModal' 2>/dev/null | grep -v 'App.tsx' || echo "No other files reference AgentInboxModal"
echo
echo "== Verify AgentInboxModal definition/export =="
find . -type f \( -name "*.tsx" -o -name "*.ts" \) -not -path "./node_modules/*" -not -path "./.git/*" | xargs grep -l 'export.*AgentInboxModal\|AgentInboxModal.*=' 2>/dev/null || echo "No definition found"Repository: RunMaestro/Maestro
Length of output: 239
Unified Inbox callback is wired but modal render is disabled and component doesn't exist.
Line 3715 enables opening the inbox via onOpenAgentInbox callback, but the only AgentInboxModal render block (Lines 4111-4120) is fully commented out with a note that the component is TBD. The component is not defined anywhere in the codebase, making the feature non-functional.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/renderer/App.tsx` at line 3715, The onOpenAgentInbox prop is wired
(onOpenAgentInbox, setAgentInboxOpen, encoreFeatures.unifiedInbox) but the modal
render (AgentInboxModal) is commented out and the component is missing; restore
or implement the AgentInboxModal component and its render path: either re-enable
the existing render block for AgentInboxModal and ensure a concrete
AgentInboxModal component is created/ exported, or replace the commented block
with a call to a newly implemented AgentInboxModal that accepts isOpen and
onClose (tied to setAgentInboxOpen), and guard its rendering behind
encoreFeatures.unifiedInbox so the callback actually opens a real modal.
Summary
EncoreFeatureFlagstype system withunifiedInboxandtabDescriptionflagssettingsStoreintegration with persistence viawindow.maestro.settingsAlt+Ifor Agent Inbox,Meta+Shift+Ofor Director Notes) behind feature flagsunifiedInboxencore featurefalseby default (convention: opt-in only)Commits
feat: add unifiedInbox and tabDescription to EncoreFeatureFlagsfeat: add Unified Inbox and Tab Descriptions cards to Settings Encore tabfeat: gate keyboard shortcuts for agentInbox and directorNotes encore featuresfeat: gate AgentInbox modal rendering and handler props behind unifiedInbox encore featurefix: set tabDescription encore default to false for convention consistencyTest plan
npm run lintpassesnpm run testpassesunifiedInboxis enabledfalseon fresh installSummary by CodeRabbit
Release Notes