-
Notifications
You must be signed in to change notification settings - Fork 246
feat: project-centric navigation with inbox system #549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
wistfulvariable
wants to merge
20
commits into
RunMaestro:main
Choose a base branch
from
wistfulvariable:documentation-2026-03-10
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
6ca2655
Add three-tier AI documentation system
2d0bbff
Add design doc for project-centric navigation with inbox
3ace449
Add implementation plan for project-centric navigation
8c045f8
feat: add Project and InboxItem type definitions
0360e76
feat: add projectStore with CRUD, selectors, and tests
5b19b61
feat: add inboxStore with dedup, dismissal, selectors, and tests
ab1362d
feat: add selectSessionsByProject selector to sessionStore
6b3043e
feat: add projects electron-store and IPC persistence handlers
5d2d86b
feat: expose window.maestro.projects IPC bridge
3418fac
feat: add useProjectRestoration with group-to-project migration
209f17e
feat: add useProjectRestoration with group→project migration
b4d8ca5
feat: add ProjectSidebar components (InboxItem, InboxSection, Project…
0cbcd9a
fix: use theme colors for inbox dots, optimize selectInboxItems
4593046
feat: add useInboxWatcher hook for session state → inbox triggers
f549fa9
feat: wire ProjectSidebar, useProjectRestoration, and useInboxWatcher…
cb26704
feat: add keyboard shortcuts for project cycling and new project
1972888
refactor: remove group and bookmark code from sessionStore
a56e321
fix: update persistence test for new projects IPC handlers
f874089
docs: update CLAUDE.md for project-centric navigation
8873b3e
fix: add projectsStore to HandlerDependencies in IPC handler index
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # Agent System | ||
|
|
||
| ## Active Agents | ||
|
|
||
| | ID | Binary | JSON Flag | Resume Flag | Read-Only Flag | Session Storage | | ||
| |----|--------|-----------|-------------|----------------|-----------------| | ||
| | `claude-code` | `claude` | `--output-format stream-json` | `--resume <id>` | `--permission-mode plan` | `~/.claude/projects/` | | ||
| | `codex` | `codex` | `--json` | `exec resume <thread_id>` | `--sandbox read-only` | `~/.codex/sessions/` | | ||
| | `opencode` | `opencode` | `--format json` | `--session <id>` | `--agent plan` | `~/.config/opencode/storage/` | | ||
| | `factory-droid` | `factory` | `-o stream-json` | `-s <id>` | default mode | `~/.factory/` | | ||
| | `terminal` | (system shell) | N/A | N/A | N/A | N/A | | ||
|
|
||
| ## Capabilities (23 flags per agent, `src/main/agents/capabilities.ts`) | ||
|
|
||
| Key flags: `supportsResume`, `supportsReadOnlyMode`, `supportsJsonOutput`, `supportsSessionId`, `supportsImageInput`, `supportsSlashCommands`, `supportsSessionStorage`, `supportsCostTracking`, `supportsUsageStats`, `supportsBatchMode`, `supportsStreaming`, `supportsModelSelection`, `supportsThinkingDisplay`, `supportsContextMerge` | ||
|
|
||
| UI features auto-enable/disable based on capability flags. | ||
|
|
||
| ## Adding a New Agent (6 steps) | ||
|
|
||
| 1. Add definition → `src/main/agents/definitions.ts` | ||
| 2. Define capabilities → `src/main/agents/capabilities.ts` | ||
| 3. Create output parser → `src/main/parsers/{agent}-output-parser.ts` | ||
| 4. Register parser → `src/main/parsers/index.ts` | ||
| 5. (Optional) Session storage → `src/main/storage/{agent}-session-storage.ts` | ||
| 6. (Optional) Error patterns → `src/main/parsers/error-patterns.ts` | ||
|
|
||
| ## Output Parser Interface | ||
|
|
||
| ```typescript | ||
| // Common parsed event structure | ||
| type: 'init' | 'text' | 'tool_use' | 'result' | 'error' | 'usage' | 'system' | ||
| sessionId?: string | ||
| text?: string | ||
| ``` | ||
|
|
||
| Registry: `registerOutputParser(agentId, parser)` / `getOutputParser(agentId)` | ||
|
|
||
| ## Gotcha: Agent-Specific Session ID Terminology | ||
|
|
||
| - Claude Code: `session_id` | ||
| - Codex: `thread_id` | ||
| - Different field names, same concept. Parsers normalize this. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| # Build System & CI/CD | ||
|
|
||
| ## Tech Stack | ||
|
|
||
| | Technology | Version | Purpose | | ||
| |------------|---------|---------| | ||
| | Electron | 28.x | Desktop app shell | | ||
| | React | 18.x | UI framework | | ||
| | TypeScript | 5.x | Type safety | | ||
| | Vite | 5.x | Bundler (renderer + web) | | ||
| | Vitest | 4.x | Test framework | | ||
| | Tailwind CSS | 3.x | Utility-first styling | | ||
| | Zustand | 5.x | State management | | ||
| | node-pty | 1.x | Terminal emulation | | ||
| | better-sqlite3 | 12.x | Stats database | | ||
| | Fastify | 4.x | Web server (mobile remote) | | ||
| | Commander | 14.x | CLI framework | | ||
| | React Flow | 11.x | Document graph visualization | | ||
| | Recharts | 3.x | Usage dashboard charts | | ||
|
|
||
| ## Build Sequence | ||
|
|
||
| ```bash | ||
| npm run build | ||
| → build:prompts # .md → generated TypeScript | ||
| → build:main # tsc → dist/main (CommonJS) | ||
| → build:preload # esbuild → dist/main/preload.js | ||
| → build:renderer # vite → dist/renderer (ESM) | ||
| → build:web # vite → dist/web | ||
| → build:cli # esbuild → dist/cli | ||
| ``` | ||
|
|
||
| ## TypeScript Configs (3 separate) | ||
|
|
||
| | Config | Module | Scope | | ||
| |--------|--------|-------| | ||
| | `tsconfig.main.json` | CommonJS | Main process + shared | | ||
| | `tsconfig.json` (root) | ESNext | Renderer + web + shared | | ||
| | `tsconfig.cli.json` | CommonJS | CLI + shared + prompts | | ||
|
|
||
| ## CI Pipeline (`.github/workflows/ci.yml`) | ||
|
|
||
| **Job 1: Lint** — prettier check, eslint, tsc (all 3 configs) | ||
| **Job 2: Test** — vitest run (unit tests only) | ||
|
|
||
| Integration/E2E/performance tests NOT in CI (manual). | ||
|
|
||
| ## Pre-commit Hooks | ||
|
|
||
| Husky + lint-staged: | ||
| - `*` → `prettier --write` | ||
| - `*.{js,ts,tsx,...}` → `eslint --fix` | ||
|
|
||
| Lightweight by design — heavy checks in CI. | ||
|
|
||
| ## Packaging | ||
|
|
||
| ```bash | ||
| npm run package # All platforms | ||
| npm run package:mac # macOS (.dmg, .zip) — x64 + arm64 | ||
| npm run package:win # Windows (.exe NSIS + portable) | ||
| npm run package:linux # Linux (.AppImage, .deb, .rpm) | ||
| ``` | ||
|
|
||
| Output: `release/` directory. Auto-publish via GitHub Actions on tag push. | ||
|
|
||
| ## Key Build Scripts (`scripts/`) | ||
|
|
||
| | Script | Purpose | | ||
| |--------|---------| | ||
| | `generate-prompts.mjs` | Compile .md prompts to TypeScript | | ||
| | `build-preload.mjs` | Bundle preload script with esbuild | | ||
| | `build-cli.mjs` | Bundle CLI with sourcemaps | | ||
| | `refresh-speckit.mjs` | Sync Spec-Kit prompts from GitHub | | ||
| | `refresh-openspec.mjs` | Sync OpenSpec prompts from Fission-AI | | ||
| | `set-version.mjs` | Update version across configs | | ||
| | `notarize.js` | macOS code signing post-build | | ||
|
|
||
| ## Environment Flags | ||
|
|
||
| - `NODE_ENV=development` — dev mode | ||
| - `USE_PROD_DATA=1` — use production data dir in dev | ||
| - `MAESTRO_DEMO_DIR=<path>` — demo mode with fresh data | ||
| - `VITE_PORT=<port>` — custom dev server port (default 5173) | ||
| - `DISABLE_HMR=1` — disable hot module replacement | ||
| - `DEBUG_GROUP_CHAT=1` — enable group chat debug logging |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # Data Model & State Management | ||
|
|
||
| ## Zustand Stores (11 total, `src/renderer/stores/`) | ||
|
|
||
| | Store | Purpose | Key state | | ||
| |-------|---------|-----------| | ||
| | `sessionStore` | Sessions, groups, active session | `sessions[]`, `groups[]`, `activeSessionId` | | ||
| | `settingsStore` | User preferences | themes, fonts, agent config, SSH remotes | | ||
| | `modalStore` | 50+ modal visibility + data | Registry pattern, not 50 fields | | ||
| | `tabStore` | Tab management | unified tab order, closed tab history | | ||
| | `agentStore` | Agent detection/capabilities | detected agents, capabilities map | | ||
| | `uiStore` | UI toggles | right panel tab, focus area | | ||
| | `batchStore` | Batch runner state | progress, docs, tasks | | ||
| | `groupChatStore` | Group chat | messages, participants | | ||
| | `notificationStore` | Toast queue | notifications[] | | ||
| | `operationStore` | Long-running ops | merge/transfer progress | | ||
| | `fileExplorerStore` | File tree | expansion state, scroll | | ||
|
|
||
| ## Session Interface (key fields) | ||
|
|
||
| ```typescript | ||
| interface Session { | ||
| id: string; | ||
| name: string; | ||
| toolType: ToolType; // 'claude-code' | 'codex' | 'opencode' | 'factory-droid' | ||
| state: SessionState; // 'idle' | 'busy' | 'connecting' | 'error' | ||
| inputMode: 'ai' | 'terminal'; | ||
| cwd: string; // Changes via cd | ||
| projectRoot: string; // Never changes (used for session storage) | ||
| aiTabs: AITab[]; | ||
| activeTabId: string; | ||
| filePreviewTabs: FilePreviewTab[]; | ||
| activeFileTabId: string | null; | ||
| unifiedTabOrder: UnifiedTabRef[]; // TabBar source of truth | ||
| executionQueue: QueuedItem[]; | ||
| } | ||
| ``` | ||
|
|
||
| ## Critical Invariant: unifiedTabOrder | ||
|
|
||
| **Every tab MUST have an entry in `unifiedTabOrder`.** Tabs missing from this array are invisible in TabBar even if content renders. | ||
|
|
||
| - When adding tabs: update both tab array AND `unifiedTabOrder` | ||
| - When activating: use `ensureInUnifiedTabOrder()` from `tabHelpers.ts` | ||
| - `buildUnifiedTabs(session)` is the canonical tab list builder | ||
|
|
||
| ## Settings Persistence | ||
|
|
||
| Settings stored via `electron-store` at platform-specific paths: | ||
| - macOS: `~/Library/Application Support/maestro/` | ||
| - Windows: `%APPDATA%/maestro/` | ||
| - Linux: `~/.config/maestro/` | ||
|
|
||
| Files: `maestro-settings.json`, `maestro-sessions.json`, `maestro-groups.json`, `maestro-agent-configs.json` | ||
|
|
||
| ## State Management Pattern | ||
|
|
||
| - **Zustand** for persistent/large state (selector-based subscriptions) | ||
| - **React Context** for transient UI state (LayerStack, Input, GitStatus, InlineWizard) | ||
| - Minimal prop drilling — components read directly from stores | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # Feature-Specific Notes | ||
|
|
||
| ## Usage Dashboard (`src/renderer/components/UsageDashboard/`) | ||
|
|
||
| - Backend: SQLite (`better-sqlite3`) with WAL mode → `src/main/stats-db.ts` | ||
| - Tables: `query_events`, `auto_run_sessions`, `auto_run_tasks`, `_migrations` | ||
| - Real-time: backend broadcasts `stats:updated` event, frontend debounces refresh | ||
| - Colorblind palettes: Wong-based, 3 variants → `src/renderer/constants/colorblindPalettes.ts` | ||
| - Charts wrapped in `ChartErrorBoundary` with retry | ||
|
|
||
| ## Document Graph (`src/renderer/components/DocumentGraph/`) | ||
|
|
||
| - Scans markdown for `[[wiki-links]]` and `[markdown](links)` | ||
| - React Flow for visualization | ||
| - Force-directed + hierarchical layout (`layoutAlgorithms.ts`) | ||
| - File watching via chokidar (NOT available for SSH remotes) | ||
| - Large files truncated: >1MB → parse first 100KB only | ||
| - Default 50 nodes, "Load more" adds 25 | ||
|
|
||
| ## Group Chat System (`src/main/group-chat/`) | ||
|
|
||
| - Moderator AI orchestrates multi-agent conversations | ||
| - @mentions route messages to specific agents | ||
| - No @mentions in moderator response = conversation complete | ||
| - Output buffer: 10MB limit (larger than process-manager's 100KB) | ||
| - Storage: `~/Library/Application Support/maestro/group-chats/{chatId}/` | ||
|
|
||
| ## Auto Run | ||
|
|
||
| - File-based document runner: markdown docs with checkbox tasks | ||
| - Playbooks: saved configurations for repeated batch runs | ||
| - Playbook assets: `assets/` subfolder (config files, YAML, Dockerfiles) | ||
| - Worktree support: operates in isolated git directory for true parallelization | ||
| - Achievement system: 15 conductor levels (1 min → 200 hours) | ||
|
|
||
| ## Director's Notes (Encore Feature) | ||
|
|
||
| - First Encore Feature — canonical gating example | ||
| - Flag: `encoreFeatures.directorNotes` | ||
| - Generates AI synopsis of work across sessions |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| # IPC API Surface | ||
|
|
||
| ## Adding an IPC Handler | ||
|
|
||
| 1. Create handler in `src/main/ipc/handlers/{domain}.ts`: | ||
| ```typescript | ||
| export function registerMyHandlers(deps: { getStore: () => Store }) { | ||
| ipcMain.handle('myDomain:myAction', async (_, arg) => { | ||
| return result; | ||
| }); | ||
| } | ||
| ``` | ||
| 2. Register in `src/main/index.ts` → `setupIpcHandlers()` | ||
| 3. Add preload API in `src/main/preload/` (module per namespace) | ||
| 4. Type the API in preload types | ||
|
|
||
| ## Handler Pattern | ||
|
|
||
| All handlers use dependency injection: | ||
| ```typescript | ||
| registerProcessHandlers({ | ||
| getProcessManager: () => processManager, | ||
| getAgentDetector: () => agentDetector, | ||
| agentConfigsStore, | ||
| settingsStore, | ||
| getMainWindow: () => mainWindow, | ||
| }); | ||
| ``` | ||
|
|
||
| Error handling wrapper: `withIpcErrorLogging()` for standardized logging. | ||
|
|
||
| ## Key Namespaces (40+) | ||
|
|
||
| | Namespace | Purpose | | ||
| |-----------|---------| | ||
| | `settings` | Get/set/getAll app settings | | ||
| | `sessions` / `groups` | Agent and group persistence | | ||
| | `process` | spawn, write, interrupt, kill, resize | | ||
| | `agents` | detect, getCapabilities, discoverModels | | ||
| | `agentSessions` | List/read/search provider sessions | | ||
| | `git` | status, diff, log, worktrees, createPR | | ||
| | `fs` | readDir, readFile, stat | | ||
| | `autorun` | Document + image management | | ||
| | `playbooks` | Batch run configuration CRUD | | ||
| | `stats` | Usage analytics (SQLite + WAL) | | ||
| | `groupChat` | Multi-agent coordination | | ||
| | `context` | Merge/groom/summarize sessions | | ||
| | `documentGraph` | File watching (chokidar) | | ||
| | `history` | Per-agent history (5000 entries/agent) | | ||
| | `tunnel` | Cloudflare tunnel management | | ||
| | `sshRemote` | SSH config management | | ||
| | `notification` | Desktop notifications, TTS | | ||
| | `web` / `live` / `webserver` | Web interface management | | ||
| | `symphony` | Open-source contribution system | | ||
|
|
||
| ## IPC Handler Count | ||
|
|
||
| 31 handler files in `src/main/ipc/handlers/` (~18,900 LOC total) | ||
|
|
||
| ## Service Layer (Renderer) | ||
|
|
||
| Services in `src/renderer/services/` wrap IPC with error handling: | ||
| ```typescript | ||
| // Pattern: never throw, return safe defaults | ||
| const gitService = { | ||
| async isRepo(cwd: string): Promise<boolean> { | ||
| try { return await window.maestro.git.isRepo(cwd); } | ||
| catch { return false; } | ||
| } | ||
| }; | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| # Implementation Patterns | ||
|
|
||
| ## Settings Persistence | ||
|
|
||
| ```typescript | ||
| // 1. State with default | ||
| const [mySetting, setMySettingState] = useState(defaultValue); | ||
|
|
||
| // 2. Wrapper that persists | ||
| const setMySetting = (value) => { | ||
| setMySettingState(value); | ||
| window.maestro.settings.set('mySetting', value); | ||
| }; | ||
|
|
||
| // 3. Load from batch in useEffect | ||
| const allSettings = await window.maestro.settings.getAll(); | ||
| if (allSettings['mySetting'] !== undefined) setMySettingState(allSettings['mySetting']); | ||
| ``` | ||
|
|
||
| ## Adding a Modal | ||
|
|
||
| 1. Create component in `src/renderer/components/` | ||
| 2. Add priority in `src/renderer/constants/modalPriorities.ts` | ||
| 3. Register with layer stack (use `onCloseRef` pattern to avoid re-registration): | ||
| ```typescript | ||
| const onCloseRef = useRef(onClose); | ||
| onCloseRef.current = onClose; | ||
| useEffect(() => { | ||
| if (isOpen) { | ||
| const id = registerLayer({ | ||
| type: 'modal', | ||
| priority: MODAL_PRIORITIES.YOUR_MODAL, | ||
| onEscape: () => onCloseRef.current(), | ||
| }); | ||
| return () => unregisterLayer(id); | ||
| } | ||
| }, [isOpen, registerLayer, unregisterLayer]); // onClose NOT in deps | ||
| ``` | ||
|
|
||
| ## Theme Colors | ||
|
|
||
| 13 required colors per theme. Use inline styles for theme colors: | ||
| ```typescript | ||
| style={{ color: theme.colors.textMain }} // Correct | ||
| className="text-gray-500" // Wrong for themed text | ||
| ``` | ||
| Use Tailwind for layout only. | ||
|
|
||
| ## Encore Features (Feature Gating) | ||
|
|
||
| Gate ALL access points when adding new Encore Features: | ||
| 1. Type flag → `EncoreFeatureFlags` in `src/renderer/types/index.ts` | ||
| 2. Default `false` → `useSettings.ts` | ||
| 3. Toggle UI → SettingsModal Encore tab | ||
| 4. App.tsx → conditional rendering + callbacks | ||
| 5. Keyboard shortcuts → guard with `ctx.encoreFeatures?.yourFeature` | ||
| 6. Hamburger menu → make setter optional, conditional render | ||
| 7. Command palette → pass `undefined` handler when disabled | ||
|
|
||
| ## Execution Queue | ||
|
|
||
| Messages queue when AI is busy. Write ops queue sequentially; read-only can parallelize. | ||
|
|
||
| ## Lazy Component Loading | ||
|
|
||
| Heavy modals loaded on-demand in App.tsx: | ||
| ```typescript | ||
| const SettingsModal = lazy(() => import('./components/Settings/SettingsModal')); | ||
| ``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update this data-model doc to match the new project/inbox architecture.
It still documents the pre-PR shape: “11” stores, no
projectStore/inboxStore, noSession.projectId, and no projects persistence file. That makes this memory doc misleading for anyone implementing follow-up changes on top of the new navigation model.Also applies to: 19-36, 47-55
🤖 Prompt for AI Agents