- Introduced `DocumentReference` objects with name, path, and external flag 🧩
- Smarter issue parsing extracts markdown `.md` links into downloadable docs 🔍
- Dedupes documents by filename, preferring external attachments when present 🧠
- Added 1MB issue-body parsing cap to prevent performance blowups 🚧
- Path traversal checks now apply only to repo-relative document references 🛡️
- Auto Run Docs setup can download external files directly via `fetch` 🌐
- Switched runner file ops to Node `fs`, replacing shell `cp/rm` usage 🧰
- Runner now configures git user.name/email to ensure commits always work 🪪
- Failure paths now clean up local repos automatically to reduce clutter 🧹
- History virtualization now measures elements directly for more accurate sizing 📏
- Marketplace and Symphony modals widened for a roomier workflow view 🖥️
Add Symphony registry documentation and contribution runner service:
- docs/SYMPHONY_REGISTRY.md: Registry documentation explaining how maintainers register repos
- docs/SYMPHONY_ISSUES.md: Guide for creating Symphony issues with Auto Run documents
- src/main/services/symphony-runner.ts: Service orchestrating contributions with draft PR claiming
- symphony-registry.json: Sample registry with Maestro as the first registered project
The runner service handles the full contribution flow: clone, branch, push, draft PR creation, Auto Run setup, finalization, and cancellation.
Implements all Symphony modal entry points and app integration:
- Add keyboard shortcut ⌘⇧Y to open Symphony modal (shortcuts.ts)
- Add handler in useMainKeyboardHandler.ts using ModalContext pattern
- Integrate SymphonyModal into App.tsx with contribution started handler
- Add Symphony to Cmd+K command palette (QuickActionsModal.tsx)
- Add Symphony to hamburger menu (SessionList.tsx)
- Add symphonyMetadata to Session type for contribution tracking
- Add IPC handlers: symphony:cloneRepo and symphony:startContribution
- Add preload bindings and TypeScript types for Symphony session API
- Wire up contribution event listener to update session state with PR info
The optional Symphony session group feature was skipped - sessions work
without a dedicated group and can be organized manually if needed.
- useSymphony: Primary hook for registry, issues, and contribution management
- useContribution: Single contribution state and action management
- useContributorStats: Stats and achievements tracking with formatted display
- index.ts: Central exports for all Symphony hooks
Hooks follow established patterns from useMarketplace and Usage Dashboard,
including debounced real-time updates, proper undefined handling for IPC
responses, and type-safe integration with the symphony IPC handlers.
* docs: add git hash display and configurable dev server port
## CHANGES
- Add `VITE_PORT` env variable to configure dev server port
- Display git commit hash in About modal next to version
- Add `__GIT_HASH__` build-time constant to both Vite configs
- Document running multiple Maestro instances with git worktrees
- Update CONTRIBUTING.md with parallel development instructions
* feat: add configurable ports for dev servers
- Allow VITE_PORT to configure main dev server port
- Update main window to load from configurable port
- Enable VITE_WEB_PORT for web interface dev server
- Add note in CONTRIBUTING.md about port configuration
- Log port usage in development mode
* docs: update CONTRIBUTING.md section and fix React DevTools script initialization
## CHANGES
- Rename "Linting" section to "Linting & Pre-commit Hooks" in table of contents
- Move script variable declaration outside conditional block
- Fix React DevTools script initialization order in index.html
* chore: update `.vscode/settings.json` with new markdownlint config
* fix: disable biome linting. Project uses ESLint
* chore: Update baseline-browser-mapping (>2 months old, warning message on "npm run build:web")
* chore: add .vscode/ to gitignore
* chore: fix gitignore to ignore .cscode/* files properly
* fix
* chore: stop tracking .vscode/ files, respect gitignore
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Add merged manifest lookup for local playbook imports
- Read local manifest and merge with official during import
- Display "Local" badge for custom playbooks in marketplace UI
- Add source badge in playbook detail view sidebar
- Support filesystem paths (absolute and tilde) for local playbooks
- Add comprehensive tests for local playbook import scenarios
- Add tests for merged manifest lookup and source tagging
- Fix mock file reads to handle local manifest ENOENT cases
- Agent Usage chart now tracks Maestro sessions, not providers 🎯
- Map session IDs to friendly names in charts and legends 🏷️
- Limit Agent Usage chart to top 10 sessions by queries 🔟
- Toggle Agent Usage chart between query counts and time metrics ⏱️
- Auto Run queries now record stats with accurate `source: auto` 🤖
- Interactive queries detect Auto Run state to tag stats correctly 🧠
- Smarter cumulative token normalization avoids inflated first-event context % 🛡️
- About modal shows dev commit hash alongside app version 🔍
- Group chat history summaries now strip markdown for cleaner reading 🧹
- Replace any[] with proper types in settings.ts (StoredSession, Group).
- Replace console.log with logger service in process.ts.
- Add consistent debug logging across remote IPC handlers.
- Remove all console.log/console.error statements in favor of logger
- Fix potential race condition in TTS queue by setting isTtsProcessing
flag before checking queue length
- Add comprehensive JSDoc comment explaining TTS_MIN_DELAY_MS (15s) rationale
- Fix type guard for stdin error handling with proper type checks
Add JSDoc comment explaining that web handlers require access to
module-level webServer state with getter/setter functions for proper
lifecycle management, which is why they are registered separately
in main/index.ts rather than through registerAllHandlers().
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add path traversal protection in attachments handlers using path.basename()
- Extract IMAGE_EXTENSIONS constant in filesystem.ts to avoid duplication
- Extract SERVER_STARTUP_TIMEOUT_MS and SERVER_STARTUP_POLL_INTERVAL_MS constants in web.ts
- Add proper AITabData type for aiTabs parameter in web:broadcastTabsChange handler
Add debug logging to help diagnose web broadcast issues. Logs webServer
existence and client count when broadcastUserInput is called.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Addresses PR review feedback on path traversal detection:
1. Fixed false positive issue - now checks for literal ".." path segments BEFORE normalization, allowing valid paths like "/Users/test/my..project" while still blocking traversal attacks like "/Users/../../../etc"
2. Added null byte check - prevents Unix security vulnerability
3. Added Windows reserved names check (CON, PRN, AUX, NUL, COM1-9, LPT1-9)
4. Improved Windows sensitive path detection - now checks across all drive letters (not just C:) and added more system directories
5. Added tests for:
- Valid paths with ".." in directory names
- Null byte rejection
- More specific traversal error assertion
All 102 stores module tests pass. Lint passes.
1. Type Safety: Added StoredSession interface with required fields (id, name, toolType, cwd, projectRoot) and index signature. Changed SessionsData.sessions from any[] to StoredSession[]. Changed GroupsData.groups from any[] to Group[].
2. Test Mock Cleanup: Refactored instances.test.ts to use vi.hoisted() for proper mock scoping, avoiding potential test interference.
3. Path Validation Security: Added isValidSyncPath() to getCustomSyncPath() that rejects relative paths, traversal sequences, paths that are too short, and paths in sensitive system directories.
Added 7 new path validation tests. All 15,311 tests pass.
- Pre-compile regex patterns at module level to avoid repeated compilation in data handlers that fire hundreds of times per second
- Add conditional debugLog() function to skip logging overhead in production (can be enabled via DEBUG_GROUP_CHAT=1 env var)
- Optimize group chat buffer from O(n²) string concatenation to O(n) array-based buffering with single join on read
- Consolidate MaestroSettings interface to single source of truth in persistence.ts to fix type incompatibility errors
- Add troubleshooting section for pre-commit hooks in CONTRIBUTING.md
- Make prepare script resilient for CI/Docker: husky || true
- Update .prettierignore to exclude coverage/ and *.min.js
- Split Git status into file, branch, and detail hooks for cleaner UI wiring 🧩
- Supercharged panel resizing by updating state only on mouseup ⚡
- Added explicit tests ensuring resize drags avoid excessive rerenders 🧪
- Refreshed dashboard wording: “Agent Comparison” is now “Provider Comparison” 🔁
- Renamed “Source Distribution” chart to clearer “Session Type” labeling 🏷️
- Updated chart accessibility labels and headings to match new terminology ♿
- Improved mobile timestamps: time-only for today, date+time for older 🕰️
- Added robust MessageHistory tests covering today vs older date formatting 📅
- Eliminated mobile session ref initialization race with immediate saved defaults 🚀
- Made active tab ref mirror URL/saved tab instantly for reliable callbacks 🧭
- Simplified hook test by removing unnecessary async waiting on refs 🧪
- Import useMainPanelProps, useSessionListProps, useRightPanelProps hooks
- Create memoized wizard handlers (handleWizardComplete, handleWizardLetsGo, handleToggleWizardShowThinking)
- Integrate all three props hooks with comprehensive dependency objects
- Update MainPanel, SessionList, and RightPanel JSX to use spread props pattern
- Fix type mismatches:
- BatchRunState null vs undefined
- AITab type for activeTab
- DocumentGenerationCallbacks function signature
- mergeSourceName/mergeTargetName string | undefined
- lastGraphFocusFilePath string | undefined
This optimization prevents React from re-evaluating 50-100+ props on every state change in MaestroConsoleInner by memoizing props objects that only change when their dependencies change.
Add React's useDeferredValue to prioritize input field responsiveness
while allowing expensive components to defer their updates. InputArea
uses the immediate inputValue for responsive typing, while the prompt
composer uses deferredInputValue to avoid blocking keystrokes.