-
Notifications
You must be signed in to change notification settings - Fork 553
feat: implement ideation feature for brainstorming and idea management #354
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
Conversation
- Introduced a new IdeationService to manage brainstorming sessions, including idea creation, analysis, and conversion to features. - Added RESTful API routes for ideation, including session management, idea CRUD operations, and suggestion generation. - Created UI components for the ideation dashboard, prompt selection, and category grid to enhance user experience. - Integrated keyboard shortcuts and navigation for the ideation feature, improving accessibility and workflow. - Updated state management with Zustand to handle ideation-specific data and actions. - Added necessary types and paths for ideation functionality, ensuring type safety and clarity in the codebase.
…or autonomous mode - Removed MCP permission settings from the application, including related functions and UI components. - Updated SDK options to always bypass permissions and allow unrestricted tool access in autonomous mode. - Adjusted related components and services to reflect the removal of MCP permission configurations, ensuring a cleaner and more efficient codebase.
- Added a new script (dev.mjs) to start the application in development mode with hot reloading using Vite. - The script includes functionality for installing Playwright browsers, resolving port configurations, and launching either a web or desktop application. - Removed the old init.mjs script, which was previously responsible for launching the application. - Updated package.json to reference the new dev.mjs script for the development command. - Introduced a shared utilities module (launcher-utils.mjs) for common functionalities used in both development and production scripts.
- Revised instructions for starting Automaker, changing from `npm run dev` to `npm run start` for production mode. - Added a setup wizard for authentication on first run, with options for using Claude Code CLI or entering an API key. - Clarified development mode instructions, emphasizing the use of `npm run dev` for live reload and hot module replacement.
…ment - Changed permissionMode settings in enhance and generate title routes to improve edit acceptance and default behavior. - Refactored performance measurement cleanup in the App component to only execute in development mode, preventing unnecessary operations in production. - Simplified the startServerAndWait function signature for better readability.
…nd tests - Changed permissionMode from 'default' to 'bypassPermissions' in sdk-options and claude-provider unit tests. - Added allowDangerouslySkipPermissions flag in claude-provider test to enhance permission handling.
- Added .claude/hans/ to .gitignore to prevent tracking of specific directory. - Updated cleanup calls in dev.mjs and start.mjs to use await for proper asynchronous handling. - Enhanced error handling during cleanup in case of failures. - Improved server failure handling in startServerAndWait function to ensure proper termination of failed processes.
- Introduced a new option to launch the application in a Docker container (Isolated Mode) from the main menu. - Added checks for the ANTHROPIC_API_KEY environment variable to ensure proper API functionality. - Updated process management to include Docker, allowing for better cleanup and handling of spawned processes. - Enhanced user prompts and logging for improved clarity during the launch process.
Fix memory leak
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughAdds a full ideation feature: backend IdeationService and routes, frontend IdeationView and components, types, platform path utilities, store integration, Electron/HTTP API surface, tests, and removes legacy feature-suggestions UI and hooks. Also updates keyboard shortcuts and navigation. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as IdeationView (frontend)
participant Store as IdeationStore
participant API as HttpApiClient / ElectronAPI
participant Server as IdeationService
participant AI as AI Provider
participant Disk as Disk Storage
User->>UI: choose prompt & generate
UI->>Store: create generation job (generating)
UI->>API: generateSuggestions(projectPath, promptId, category)
API->>Server: POST /api/ideation/suggestions
activate Server
Server->>AI: build prompt + send request
AI-->>Server: suggestions response
Server->>Disk: persist ideas
Server-->>API: return suggestions[]
deactivate Server
API->>Store: update job (ready, suggestions)
Store-->>UI: render suggestions in dashboard
User->>UI: accept suggestion
UI->>API: convertToFeature(projectPath, ideaId)
API->>Server: POST /api/ideation/convert
Server->>Disk: create feature, optionally delete idea
Server-->>API: featureId
API->>Store: remove suggestion / update UI
Store-->>UI: show feature added
Estimated code review effort🎯 4 (Complex) | ⏱️ ~55 minutes Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @webdevcody, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request delivers a major new 'Ideation' capability, transforming how users can brainstorm and develop new features within the application. It provides a structured environment for generating, refining, and tracking ideas, leveraging AI for project analysis and suggestion generation. This integration aims to streamline the product development workflow from concept to implementation, replacing a more limited prior suggestion mechanism with a dedicated, interactive ideation space. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
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.
Code Review
This pull request introduces a comprehensive ideation feature, including a new IdeationService on the backend, corresponding API routes, and a full set of UI components for managing ideas. The overall structure is well-designed, with a clear separation of concerns. The new IdeationService is robust, handling sessions, CRUD operations, and AI-powered suggestion generation with good error handling and asynchronous processing. The UI is well-organized into a dashboard and a flow for generating new ideas.
However, there are a few areas for improvement. I've identified some instances of data duplication and inconsistent logic between the frontend and backend, particularly concerning the list of guided prompts and the conversion of suggestions into features. Addressing these will improve maintainability and reduce the risk of future bugs. I've also noted a couple of places where backend logic could be enhanced or made more consistent. My detailed comments provide specific suggestions to resolve these points.
| const validCategories: IdeaCategory[] = ['feature', 'ux-ui', 'dx', 'growth', 'technical']; | ||
| if (!validCategories.includes(category as IdeaCategory)) { | ||
| res.status(400).json({ success: false, error: 'Invalid category' }); | ||
| return; | ||
| } |
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.
The list of validCategories is hardcoded and incomplete. It's missing categories like 'security', 'performance', etc., which are present in IdeationService. This will cause valid categories to be rejected. Instead of hardcoding, you should get the list of valid categories directly from the ideationService to ensure it's always up-to-date.
| const validCategories: IdeaCategory[] = ['feature', 'ux-ui', 'dx', 'growth', 'technical']; | |
| if (!validCategories.includes(category as IdeaCategory)) { | |
| res.status(400).json({ success: false, error: 'Invalid category' }); | |
| return; | |
| } | |
| const validCategories = ideationService.getPromptCategories().map((c) => c.id); | |
| if (!validCategories.includes(category as IdeaCategory)) { | |
| res.status(400).json({ success: false, error: 'Invalid category' }); | |
| return; | |
| } |
|
|
||
| /** | ||
| * Get all guided prompts | ||
| * NOTE: Keep in sync with apps/ui/src/components/views/ideation-view/data/guided-prompts.ts |
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.
The comment "NOTE: Keep in sync with apps/ui/src/components/views/ideation-view/data/guided-prompts.ts" indicates that the list of guided prompts is duplicated in both the backend and frontend. This is a maintenance risk and can lead to inconsistencies. The backend should be the single source of truth for this data. The frontend should fetch the prompts using the /api/ideation/prompts endpoint, which is already implemented. Please remove the duplicated data from the frontend.
apps/ui/src/lib/http-api-client.ts
Outdated
| addSuggestionToBoard: async (projectPath: string, suggestion: AnalysisSuggestion) => { | ||
| // Create a feature directly from the suggestion | ||
| const result = await this.post<{ success: boolean; feature?: Feature; error?: string }>( | ||
| '/api/features/create', | ||
| { | ||
| projectPath, | ||
| feature: { | ||
| title: suggestion.title, | ||
| description: | ||
| suggestion.description + | ||
| (suggestion.rationale ? `\n\n**Rationale:** ${suggestion.rationale}` : ''), | ||
| category: | ||
| suggestion.category === 'ux-ui' | ||
| ? 'enhancement' | ||
| : suggestion.category === 'dx' | ||
| ? 'chore' | ||
| : suggestion.category === 'technical' | ||
| ? 'refactor' | ||
| : 'feature', | ||
| status: 'backlog', | ||
| }, | ||
| } | ||
| ); | ||
| return { | ||
| success: result.success, | ||
| featureId: result.feature?.id, | ||
| error: result.error, | ||
| }; | ||
| }, |
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.
The addSuggestionToBoard method implements logic to convert an AnalysisSuggestion into a Feature on the client-side. This logic is duplicated and inconsistent with the mapIdeaCategoryToFeatureCategory method in apps/server/src/services/ideation-service.ts. The category mapping here is incomplete. This logic should reside on the backend to ensure consistency and a single source of truth. I suggest creating a new endpoint, for example /api/ideation/add-suggestion, that accepts a suggestion and handles the conversion to a feature on the server.
| import { createLogger } from '@automaker/utils'; | ||
|
|
||
| const logger = createLogger('ideation:suggestions-generate'); |
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.
For consistency with other route files in this module, you should use the shared logError and getErrorMessage utilities from ../common.js instead of creating a local logger.
| import { createLogger } from '@automaker/utils'; | |
| const logger = createLogger('ideation:suggestions-generate'); | |
| import { getErrorMessage, logError } from '../common.js'; |
| logger.error('Failed to generate suggestions:', error); | ||
| res.status(500).json({ | ||
| success: false, | ||
| error: (error as Error).message, | ||
| }); | ||
| } |
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.
To maintain consistency in error handling across the ideation routes, please use the shared logError and getErrorMessage utilities here.
| logger.error('Failed to generate suggestions:', error); | |
| res.status(500).json({ | |
| success: false, | |
| error: (error as Error).message, | |
| }); | |
| } | |
| logError(error, 'Failed to generate suggestions'); | |
| res.status(500).json({ | |
| success: false, | |
| error: getErrorMessage(error), | |
| }); |
| private async generateAnalysisSuggestions( | ||
| _projectPath: string, | ||
| structure: Awaited<ReturnType<typeof this.gatherProjectStructure>> | ||
| ): Promise<AnalysisSuggestion[]> { | ||
| // Generate basic suggestions based on project structure analysis | ||
| const suggestions: AnalysisSuggestion[] = []; | ||
|
|
||
| if (structure.routes.length > 0 && structure.routes.length < 5) { | ||
| suggestions.push({ | ||
| id: this.generateId('sug'), | ||
| category: 'feature', | ||
| title: 'Expand Core Functionality', | ||
| description: 'The app has a small number of routes. Consider adding more features.', | ||
| rationale: `Only ${structure.routes.length} routes detected. Most apps benefit from additional navigation options.`, | ||
| priority: 'medium', | ||
| }); | ||
| } | ||
|
|
||
| if ( | ||
| !structure.dependencies?.includes('react-query') && | ||
| !structure.dependencies?.includes('@tanstack/react-query') | ||
| ) { | ||
| suggestions.push({ | ||
| id: this.generateId('sug'), | ||
| category: 'technical', | ||
| title: 'Add Data Fetching Library', | ||
| description: 'Consider adding React Query or similar for better data management.', | ||
| rationale: | ||
| 'Data fetching libraries provide caching, background updates, and better loading states.', | ||
| priority: 'low', | ||
| }); | ||
| } | ||
|
|
||
| return suggestions; | ||
| } |
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.
- Introduced `dev.mjs` for development mode with hot reloading using Vite. - Added `start.mjs` for production mode, serving pre-built static files without hot reloading. - Created a new utility module `launcher-utils.mjs` for shared functions across scripts. - Updated package.json scripts to reflect new launch commands. - Removed deprecated `init.mjs` and associated MCP permission settings from the codebase. - Added `.dockerignore` and updated `.gitignore` for better environment management. - Enhanced README with updated usage instructions for starting the application.
|
@claude increase coverage for test suite tests |
|
Claude finished @webdevcody's task in 4m 7s —— View job Increasing Test Coverage for Ideation Feature ✅I've successfully added comprehensive unit tests for the ideation feature introduced in this PR. AnalysisThe ideation feature adds:
Based on the vitest config, routes are excluded from coverage, so I focused on comprehensive unit tests for the What I've AddedCreated comprehensive unit tests in Session Management (5 tests)
Ideas CRUD (11 tests)
Idea to Feature Conversion (4 tests)
Project Analysis (3 tests)
Prompt Management (3 tests)
Suggestion Generation (2 tests)
Total: 28 comprehensive unit tests covering all major functionality of the IdeationService. TestingPlease run Changes Committed
--- | |
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.
Actionable comments posted: 5
♻️ Duplicate comments (7)
apps/server/src/routes/ideation/routes/prompts.ts (1)
29-33: Incomplete category validation - matches previous review.The hardcoded
validCategoriesarray is missing 4 valid categories from theIdeaCategorytype:'security','performance','accessibility', and'analytics'. This will cause valid requests to be rejected with a 400 error.As suggested in the previous review, fetch the valid categories dynamically from
ideationService.getPromptCategories()to ensure consistency with the type definition.🔎 Proposed fix
- const validCategories: IdeaCategory[] = ['feature', 'ux-ui', 'dx', 'growth', 'technical']; + const validCategories = ideationService.getPromptCategories().map((c) => c.id); if (!validCategories.includes(category as IdeaCategory)) { res.status(400).json({ success: false, error: 'Invalid category' }); return; }apps/server/src/routes/ideation/routes/suggestions-generate.ts (2)
7-9: Use shared error utilities for consistency.This file should use the shared
logErrorandgetErrorMessageutilities from../common.jsinstead of creating a separate logger instance, as noted in previous review comments and as implemented in other ideation route files.🔎 Recommended refactor to use shared utilities
-import { createLogger } from '@automaker/utils'; - -const logger = createLogger('ideation:suggestions-generate'); +import { getErrorMessage, logError } from '../common.js';
34-34: Replace local logging with shared utilities.Replace the local logger calls with the shared error handling utilities for consistency with other ideation routes.
🔎 Recommended refactor
- logger.info(`Generating ${suggestionCount} suggestions for prompt: ${promptId}`); + // Optional: If info logging is needed, use the shared logger from common.js- logger.error('Failed to generate suggestions:', error); + logError(error, 'Failed to generate suggestions'); res.status(500).json({ success: false, - error: (error as Error).message, + error: getErrorMessage(error), });Also applies to: 48-52
apps/ui/src/components/views/ideation-view/components/prompt-list.tsx (1)
8-29: Avoid duplicating guided prompts between frontend and backendThis component pulls prompts from
../data/guided-prompts, while the backendIdeationService.getAllPrompts()maintains an almost identical list (and even has a “Keep in sync” comment). That duplication is the same maintenance risk previously flagged in the server file.Consider making the backend the single source of truth for guided prompts (e.g., via
/api/ideation/promptsor the existing ideation API) and have the UI fetch by category instead of importing static data here. That will prevent future drift between server and UI prompt sets.Also applies to: 103-159
apps/server/src/services/ideation-service.ts (2)
861-910: Guided prompts are still duplicated between backend and frontend
getPromptCategories/getAllPromptsdefine a full catalog of guided prompts and carry the same “NOTE: Keep in sync with apps/ui/.../guided-prompts.ts” comment that was previously flagged. The new PromptList UI still imports prompts from the frontend data module, so you now have two copies of the same catalogue.This remains a maintenance and consistency risk:
- Adding/editing prompts requires touching two files.
- It’s easy for the backend prompts used by analysis/suggestions to diverge from what the UI displays.
Prefer the backend as the single source of truth for guided prompts:
- Keep the prompt definitions here in
IdeationService, and- Expose them via the existing ideation routes,
- Then update the UI to consume
/api/ideation/prompts(or the Electron ideation API) instead of staticguided-prompts.ts.Once that’s wired, you can delete the duplicated prompt data from the frontend module.
Also applies to: 989-1225
1575-1609:generateAnalysisSuggestionsis still a placeholder heuristicThis method still returns a couple of generic, structure-based suggestions (routes count and a missing data-fetching library), which matches the prior feedback that it’s a placeholder:
if (structure.routes.length > 0 && structure.routes.length < 5) { … } if (!deps.includes('react-query') && !deps.includes('@tanstack/react-query')) { … }For the analysis feature to be genuinely useful, this should eventually:
- Either call into the same provider/SDK stack with a dedicated analysis prompt, or
- At least generate a richer, more context-aware set of
AnalysisSuggestions based on the discovered structure and dependencies.Not a correctness bug, but worth tracking so this doesn’t ship as “final” behavior.
apps/ui/src/lib/http-api-client.ts (1)
1650-1730: MoveaddSuggestionToBoardconversion logic to the backend and align category mapping
ideation.addSuggestionToBoardis still convertingAnalysisSuggestion→Featureentirely on the client and reimplements its own category mapping:
'ux-ui' → 'enhancement''dx' → 'chore''technical' → 'refactor'- everything else →
'feature'This duplicates and partially contradicts
mapIdeaCategoryToFeatureCategoryinapps/server/src/services/ideation-service.ts, which also handlessecurity,performance,accessibility, andanalytics(mappingsecuritytobug, etc.). That’s exactly the duplication/inconsistency called out in the earlier review.To avoid drift and ensure a single source of truth:
- Move this conversion into the ideation backend (e.g., a dedicated
/api/ideation/add-suggestionor by extending the existing convert/feature routes), and- Change
addSuggestionToBoardhere to just POST{ projectPath, suggestion }to that endpoint and return its response.At minimum, if you keep a temporary client-side path, mirror the full mapping used in
mapIdeaCategoryToFeatureCategoryso security/performance/accessibility/analytics suggestions don’t silently get misclassified as plain'feature'.
🧹 Nitpick comments (11)
apps/ui/src/components/views/ideation-view/data/guided-prompts.ts (1)
65-391: Consider fetching prompts from the server API instead of hardcoding.The static
GUIDED_PROMPTSdata duplicates prompt data that also exists server-side (viaIdeationService) with corresponding API endpoints (GET /prompts,GET /prompts/:categoryfromapps/server/src/routes/ideation/routes/prompts.ts).This duplication creates a maintenance burden—prompts must be updated in both locations to stay synchronized. Since API routes exist specifically for fetching prompts, consider removing the hardcoded client-side data and fetching from the server instead.
If offline support or faster initial load is required, the hardcoded data could serve as a fallback, but this should be explicitly documented.
💡 Alternative approach
Remove the static
GUIDED_PROMPTSand fetch from the API:// Fetch prompts from server instead of hardcoding export async function fetchPrompts(): Promise<IdeationPrompt[]> { const response = await apiClient.get('/api/ideation/prompts'); return response.data.prompts; } export async function fetchPromptsByCategory(category: IdeaCategory): Promise<IdeationPrompt[]> { const response = await apiClient.get(`/api/ideation/prompts/${category}`); return response.data.prompts; }If you need offline fallback, keep the static data but document its purpose:
/** * Static fallback prompts for offline usage or initial load. * Production data should be fetched from the server API. */ export const GUIDED_PROMPTS_FALLBACK: IdeationPrompt[] = [ // ... existing prompts ];apps/server/src/routes/ideation/routes/ideas-delete.ts (1)
27-28: Consider returning 404 for non-existent ideas.The delete operation always returns
{ success: true }even if the idea doesn't exist (sincedeleteIdeasilently ignores missing ideas). This differs from the update handler which returns 404 for non-existent ideas.While idempotent deletes are valid, returning success without confirmation may mask bugs where clients delete the wrong
ideaId. Consider aligning with the update handler's behavior for consistency.🔎 Proposed change for explicit existence check
- await ideationService.deleteIdea(projectPath, ideaId); - res.json({ success: true }); + const deleted = await ideationService.deleteIdea(projectPath, ideaId); + if (!deleted) { + res.status(404).json({ success: false, error: 'Idea not found' }); + return; + } + res.json({ success: true });This would require modifying
deleteIdeato return a boolean indicating whether the idea existed.libs/types/src/event.ts (1)
36-36: Inconsistent event naming:analysis-completevsanalysis-completed.The existing event uses
project:analysis-completed(line 25), but the new ideation event usesideation:analysis-complete. Consider usingideation:analysis-completedfor consistency across the codebase.🔎 Suggested fix
- | 'ideation:analysis-complete' + | 'ideation:analysis-completed'apps/server/src/routes/ideation/routes/session-get.ts (1)
35-39: Duplicatemessagesfield in response.The
sessionobject (of typeIdeationSessionWithMessages) already containsmessages. Addingmessages: session.messagesat line 38 duplicates this field at the top level of the response, which increases payload size unnecessarily and may cause confusion for API consumers.🔎 Suggested fix
res.json({ success: true, session: { ...session, isRunning }, - messages: session.messages, });apps/ui/src/store/ideation-store.ts (2)
176-176:substris deprecated; usesubstringinstead.
String.prototype.substr()is deprecated. Replace withsubstring()for the same behavior.🔎 Suggested fix
- const jobId = `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; + const jobId = `job-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
192-205: Potential issue with falsyerrorvalues.Line 200 uses
error: error || null, which converts an empty string''tonull. If an empty string error is intentionally passed, it will be lost. Consider using nullish coalescing (??) if you want to preserve empty strings, or keep||if empty strings should be treated as "no error."🔎 Suggested fix (if empty strings should be preserved)
? { ...job, status, suggestions: suggestions || job.suggestions, - error: error || null, + error: error ?? null, completedAt: status !== 'generating' ? new Date().toISOString() : null, }apps/ui/src/components/views/ideation-view/components/ideation-dashboard.tsx (1)
238-240: Unsafe type assertion for error object.
(error as Error).messageassumeserroris anErrorinstance, but caught exceptions can be any type. This could throw if someone throws a non-Error value.🔎 Suggested fix
} catch (error) { console.error('Failed to add to board:', error); - toast.error((error as Error).message); + toast.error(error instanceof Error ? error.message : 'Failed to add to board'); } finally {libs/types/src/ideation.ts (1)
203-218: AlignIdeationStreamEventwith the actual event payload shapeThe current definition:
export interface IdeationStreamEvent { type: 'ideation:stream'; sessionId: string; content: string; done: boolean; }doesn’t match what
IdeationService.sendMessageactually emits on the'ideation:stream'channel, where the payload looks like:
{ sessionId, type: 'message', message: IdeationMessage }{ sessionId, type: 'stream', content, done: false }{ sessionId, type: 'message-complete', message, content, done: true }{ sessionId, type: 'aborted' }{ sessionId, type: 'error', error }To avoid misleading consumers, consider modeling this as a discriminated union over the inner
typefield, e.g.:Example refactor
-export interface IdeationStreamEvent { - type: 'ideation:stream'; - sessionId: string; - content: string; - done: boolean; -} +export type IdeationStreamEvent = + | { + type: 'message'; + sessionId: string; + message: IdeationMessage; + } + | { + type: 'stream' | 'message-complete'; + sessionId: string; + content: string; + done: boolean; + message?: IdeationMessage; + } + | { + type: 'aborted'; + sessionId: string; + } + | { + type: 'error'; + sessionId: string; + error: string; + };This keeps
EventTypeas'ideation:stream'at the transport level while giving callers an accurate payload type.apps/ui/src/lib/electron.ts (1)
16-26: Ideation API surface is consistent; consider tighteningconvertToFeaturetypingThe new
IdeationAPIinterface andideation?: IdeationAPIaddition onElectronAPIline up with the HTTP client implementation and the server routes; method shapes and payload types look coherent.One minor improvement:
convertToFeaturecurrently returnsfeature?: any. Since you already have aFeaturetype in this module (and in@automaker/types), you can make this safer and more self-documenting by returningfeature?: Featureinstead ofany, while still keepingfeatureId?: stringfor convenience.Also, ensure the actual Electron IPC bridge (main process) is updated to implement this
ideationinterface; otherwise, browser code relying on the real Electron API (not just the HTTP client) will seeideationasundefined.Also applies to: 43-55, 57-129, 748-749
apps/server/src/services/ideation-service.ts (2)
758-787: Harden suggestion parsing: normalize priority and reduce JSON brittleness
parseSuggestionsFromResponseand the text fallback do a good job of salvaging non-JSON responses, but there are a couple of robustness gaps:
- You trust
item.priorityas-is, even though the model may emit"High"/"MEDIUM"or other variants. That can silently break any downstream code that expects'high' | 'medium' | 'low'.- The JSON extraction regex grabs the first
[...]substring; if the model ever wraps JSON in prose with other bracketed content, you could parse the wrong segment.Suggested improvements:
Normalize priority to your union type and default safely:
const raw = typeof item.priority === 'string' ? item.priority.toLowerCase() : ''; const priority: 'high' | 'medium' | 'low' = raw === 'high' || raw === 'low' ? raw : 'medium';Optionally, tighten JSON extraction by preferring the last
[...]block or by instructing the model even more strongly (you already do some of this in the system prompt).Even just the priority normalization would prevent subtle filtering bugs later.
Also applies to: 793-854
446-450: Consider recordingarchivedAtwhen archiving ideas
archiveIdeacurrently only flips the status:return this.updateIdea(projectPath, ideaId, { status: 'archived' as IdeaStatus, });Given the
Ideatype includes anarchivedAt?: stringfield, it would be useful to also stamp the archive time here so clients can sort/filter by when an idea was archived.Example:
return this.updateIdea(projectPath, ideaId, { status: 'archived' as IdeaStatus, archivedAt: new Date().toISOString(), });
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (43)
.claude/.gitignoreapps/server/src/index.tsapps/server/src/routes/ideation/common.tsapps/server/src/routes/ideation/index.tsapps/server/src/routes/ideation/routes/analyze.tsapps/server/src/routes/ideation/routes/convert.tsapps/server/src/routes/ideation/routes/ideas-create.tsapps/server/src/routes/ideation/routes/ideas-delete.tsapps/server/src/routes/ideation/routes/ideas-get.tsapps/server/src/routes/ideation/routes/ideas-list.tsapps/server/src/routes/ideation/routes/ideas-update.tsapps/server/src/routes/ideation/routes/prompts.tsapps/server/src/routes/ideation/routes/session-get.tsapps/server/src/routes/ideation/routes/session-message.tsapps/server/src/routes/ideation/routes/session-start.tsapps/server/src/routes/ideation/routes/session-stop.tsapps/server/src/routes/ideation/routes/suggestions-generate.tsapps/server/src/services/ideation-service.tsapps/ui/src/components/layout/sidebar/hooks/use-navigation.tsapps/ui/src/components/ui/keyboard-map.tsxapps/ui/src/components/views/board-view.tsxapps/ui/src/components/views/board-view/dialogs/feature-suggestions-dialog.tsxapps/ui/src/components/views/board-view/dialogs/index.tsapps/ui/src/components/views/board-view/hooks/index.tsapps/ui/src/components/views/board-view/hooks/use-board-effects.tsapps/ui/src/components/views/board-view/hooks/use-suggestions-state.tsapps/ui/src/components/views/board-view/kanban-board.tsxapps/ui/src/components/views/ideation-view/components/ideation-dashboard.tsxapps/ui/src/components/views/ideation-view/components/prompt-category-grid.tsxapps/ui/src/components/views/ideation-view/components/prompt-list.tsxapps/ui/src/components/views/ideation-view/data/guided-prompts.tsapps/ui/src/components/views/ideation-view/index.tsxapps/ui/src/hooks/use-keyboard-shortcuts.tsapps/ui/src/lib/electron.tsapps/ui/src/lib/http-api-client.tsapps/ui/src/routes/ideation.tsxapps/ui/src/store/app-store.tsapps/ui/src/store/ideation-store.tslibs/platform/src/index.tslibs/platform/src/paths.tslibs/types/src/event.tslibs/types/src/ideation.tslibs/types/src/index.ts
💤 Files with no reviewable changes (6)
- apps/ui/src/components/views/board-view/hooks/index.ts
- apps/ui/src/components/views/board-view/hooks/use-suggestions-state.ts
- apps/ui/src/components/views/board-view.tsx
- apps/ui/src/components/views/board-view/dialogs/feature-suggestions-dialog.tsx
- apps/ui/src/components/views/board-view/hooks/use-board-effects.ts
- apps/ui/src/components/views/board-view/dialogs/index.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always import from shared packages (@automaker/*), never from old relative paths
Files:
apps/server/src/routes/ideation/routes/convert.tsapps/server/src/routes/ideation/routes/session-message.tsapps/server/src/routes/ideation/routes/ideas-list.tsapps/server/src/routes/ideation/common.tsapps/server/src/routes/ideation/routes/ideas-create.tsapps/server/src/routes/ideation/routes/session-start.tsapps/server/src/routes/ideation/routes/session-stop.tsapps/server/src/routes/ideation/routes/suggestions-generate.tsapps/ui/src/routes/ideation.tsxapps/ui/src/store/ideation-store.tslibs/types/src/event.tsapps/server/src/routes/ideation/index.tsapps/ui/src/components/ui/keyboard-map.tsxapps/ui/src/components/views/ideation-view/components/prompt-category-grid.tsxapps/ui/src/components/views/ideation-view/components/ideation-dashboard.tsxapps/ui/src/components/layout/sidebar/hooks/use-navigation.tslibs/platform/src/paths.tsapps/server/src/routes/ideation/routes/session-get.tsapps/server/src/routes/ideation/routes/ideas-delete.tsapps/server/src/routes/ideation/routes/ideas-update.tsapps/server/src/routes/ideation/routes/ideas-get.tsapps/server/src/index.tsapps/ui/src/components/views/ideation-view/components/prompt-list.tsxapps/ui/src/store/app-store.tslibs/types/src/index.tsapps/ui/src/lib/http-api-client.tsapps/ui/src/components/views/ideation-view/data/guided-prompts.tsapps/ui/src/hooks/use-keyboard-shortcuts.tsapps/server/src/routes/ideation/routes/analyze.tsapps/server/src/routes/ideation/routes/prompts.tsapps/ui/src/components/views/ideation-view/index.tsxapps/server/src/services/ideation-service.tslibs/platform/src/index.tslibs/types/src/ideation.tsapps/ui/src/components/views/board-view/kanban-board.tsxapps/ui/src/lib/electron.ts
apps/server/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
createEventEmitter()fromlib/events.tsfor all server operations to emit events that stream to frontend via WebSocket
Files:
apps/server/src/routes/ideation/routes/convert.tsapps/server/src/routes/ideation/routes/session-message.tsapps/server/src/routes/ideation/routes/ideas-list.tsapps/server/src/routes/ideation/common.tsapps/server/src/routes/ideation/routes/ideas-create.tsapps/server/src/routes/ideation/routes/session-start.tsapps/server/src/routes/ideation/routes/session-stop.tsapps/server/src/routes/ideation/routes/suggestions-generate.tsapps/server/src/routes/ideation/index.tsapps/server/src/routes/ideation/routes/session-get.tsapps/server/src/routes/ideation/routes/ideas-delete.tsapps/server/src/routes/ideation/routes/ideas-update.tsapps/server/src/routes/ideation/routes/ideas-get.tsapps/server/src/index.tsapps/server/src/routes/ideation/routes/analyze.tsapps/server/src/routes/ideation/routes/prompts.tsapps/server/src/services/ideation-service.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
resolveModelString()from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names
Files:
apps/server/src/routes/ideation/routes/convert.tsapps/server/src/routes/ideation/routes/session-message.tsapps/server/src/routes/ideation/routes/ideas-list.tsapps/server/src/routes/ideation/common.tsapps/server/src/routes/ideation/routes/ideas-create.tsapps/server/src/routes/ideation/routes/session-start.tsapps/server/src/routes/ideation/routes/session-stop.tsapps/server/src/routes/ideation/routes/suggestions-generate.tsapps/ui/src/routes/ideation.tsxapps/ui/src/store/ideation-store.tslibs/types/src/event.tsapps/server/src/routes/ideation/index.tsapps/ui/src/components/ui/keyboard-map.tsxapps/ui/src/components/views/ideation-view/components/prompt-category-grid.tsxapps/ui/src/components/views/ideation-view/components/ideation-dashboard.tsxapps/ui/src/components/layout/sidebar/hooks/use-navigation.tslibs/platform/src/paths.tsapps/server/src/routes/ideation/routes/session-get.tsapps/server/src/routes/ideation/routes/ideas-delete.tsapps/server/src/routes/ideation/routes/ideas-update.tsapps/server/src/routes/ideation/routes/ideas-get.tsapps/server/src/index.tsapps/ui/src/components/views/ideation-view/components/prompt-list.tsxapps/ui/src/store/app-store.tslibs/types/src/index.tsapps/ui/src/lib/http-api-client.tsapps/ui/src/components/views/ideation-view/data/guided-prompts.tsapps/ui/src/hooks/use-keyboard-shortcuts.tsapps/server/src/routes/ideation/routes/analyze.tsapps/server/src/routes/ideation/routes/prompts.tsapps/ui/src/components/views/ideation-view/index.tsxapps/server/src/services/ideation-service.tslibs/platform/src/index.tslibs/types/src/ideation.tsapps/ui/src/components/views/board-view/kanban-board.tsxapps/ui/src/lib/electron.ts
🧠 Learnings (3)
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Frontend UI must use TanStack Router for file-based routing, organize components in components/views/, implement stores with Zustand, and use custom hooks in hooks/ directory
Applied to files:
apps/ui/src/routes/ideation.tsx
📚 Learning: 2025-12-30T01:02:07.114Z
Learnt from: illia1f
Repo: AutoMaker-Org/automaker PR: 324
File: apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx:122-131
Timestamp: 2025-12-30T01:02:07.114Z
Learning: Tailwind CSS v4 uses postfix syntax for the important modifier: append ! at the end of the utility class (e.g., backdrop-blur-[0px]! or hover:bg-red-500!). The older v3 style used a prefix (!) at the start (e.g., !backdrop-blur-[0px]); prefer the postfix form for consistency across TSX files.
Applied to files:
apps/ui/src/routes/ideation.tsxapps/ui/src/components/ui/keyboard-map.tsxapps/ui/src/components/views/ideation-view/components/prompt-category-grid.tsxapps/ui/src/components/views/ideation-view/components/ideation-dashboard.tsxapps/ui/src/components/views/ideation-view/components/prompt-list.tsxapps/ui/src/components/views/ideation-view/index.tsxapps/ui/src/components/views/board-view/kanban-board.tsx
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Applies to apps/server/src/**/*.{ts,tsx} : Use `createEventEmitter()` from `lib/events.ts` for all server operations to emit events that stream to frontend via WebSocket
Applied to files:
libs/types/src/event.ts
🧬 Code graph analysis (19)
apps/server/src/routes/ideation/routes/session-message.ts (3)
apps/server/src/services/ideation-service.ts (1)
IdeationService(52-1679)libs/types/src/ideation.ts (1)
SendMessageOptions(163-166)apps/server/src/routes/ideation/common.ts (1)
logError(12-12)
apps/server/src/routes/ideation/routes/ideas-list.ts (1)
apps/server/src/routes/ideation/common.ts (1)
logError(12-12)
apps/server/src/routes/ideation/common.ts (1)
apps/server/src/routes/common.ts (1)
createLogError(34-38)
apps/server/src/routes/ideation/routes/session-start.ts (1)
libs/types/src/ideation.ts (1)
StartSessionOptions(157-161)
apps/ui/src/routes/ideation.tsx (1)
apps/ui/src/components/views/ideation-view/index.tsx (1)
IdeationView(129-208)
libs/platform/src/paths.ts (1)
apps/server/src/lib/secure-fs.ts (1)
secureFs(8-39)
apps/server/src/routes/ideation/routes/session-get.ts (2)
apps/server/src/services/dev-server-service.ts (1)
isRunning(415-417)apps/server/src/routes/ideation/common.ts (1)
logError(12-12)
apps/server/src/routes/ideation/routes/ideas-delete.ts (1)
apps/server/src/routes/ideation/common.ts (1)
logError(12-12)
apps/server/src/routes/ideation/routes/ideas-get.ts (1)
apps/server/src/routes/ideation/common.ts (1)
logError(12-12)
apps/ui/src/components/views/ideation-view/components/prompt-list.tsx (7)
apps/ui/src/lib/electron.ts (2)
IdeaCategory(46-46)getElectronAPI(827-836)libs/types/src/ideation.ts (2)
IdeaCategory(9-18)IdeationPrompt(102-109)libs/types/src/index.ts (2)
IdeaCategory(149-149)IdeationPrompt(160-160)apps/ui/src/store/ideation-store.ts (1)
useIdeationStore(143-324)apps/server/src/services/ideation-service.ts (1)
getPromptsByCategory(901-904)apps/ui/src/components/views/ideation-view/data/guided-prompts.ts (1)
getPromptsByCategory(381-383)apps/ui/src/components/ui/card.tsx (2)
Card(84-84)CardContent(84-84)
apps/ui/src/lib/http-api-client.ts (3)
apps/ui/src/lib/electron.ts (7)
IdeationAPI(58-129)StartSessionOptions(51-51)CreateIdeaInput(52-52)UpdateIdeaInput(53-53)IdeaCategory(46-46)ConvertToFeatureOptions(54-54)AnalysisSuggestion(50-50)libs/types/src/ideation.ts (6)
StartSessionOptions(157-161)CreateIdeaInput(168-179)UpdateIdeaInput(181-190)IdeaCategory(9-18)ConvertToFeatureOptions(192-197)AnalysisSuggestion(121-129)libs/types/src/event.ts (1)
EventCallback(40-40)
apps/ui/src/components/views/ideation-view/data/guided-prompts.ts (3)
libs/types/src/ideation.ts (3)
PromptCategory(95-100)IdeationPrompt(102-109)IdeaCategory(9-18)libs/types/src/index.ts (3)
PromptCategory(159-159)IdeationPrompt(160-160)IdeaCategory(149-149)apps/server/src/services/ideation-service.ts (1)
getPromptsByCategory(901-904)
apps/ui/src/hooks/use-keyboard-shortcuts.ts (2)
apps/ui/src/store/app-store.ts (1)
DEFAULT_KEYBOARD_SHORTCUTS(184-219)libs/types/src/index.ts (1)
DEFAULT_KEYBOARD_SHORTCUTS(88-88)
apps/server/src/routes/ideation/routes/analyze.ts (1)
apps/server/src/routes/ideation/common.ts (1)
logError(12-12)
apps/server/src/routes/ideation/routes/prompts.ts (3)
apps/server/src/routes/ideation/common.ts (1)
logError(12-12)libs/types/src/ideation.ts (1)
IdeaCategory(9-18)libs/types/src/index.ts (1)
IdeaCategory(149-149)
apps/ui/src/components/views/ideation-view/index.tsx (5)
apps/ui/src/store/ideation-store.ts (2)
IdeationMode(36-36)useIdeationStore(143-324)libs/types/src/ideation.ts (1)
IdeaCategory(9-18)apps/ui/src/components/views/ideation-view/data/guided-prompts.ts (1)
getCategoryById(389-391)apps/ui/src/components/views/ideation-view/components/prompt-category-grid.tsx (1)
PromptCategoryGrid(38-78)apps/ui/src/components/views/ideation-view/components/prompt-list.tsx (1)
PromptList(21-162)
apps/server/src/services/ideation-service.ts (4)
libs/types/src/ideation.ts (15)
IdeationSession(69-77)IdeationMessage(79-85)StartSessionOptions(157-161)IdeationSessionWithMessages(87-89)SendMessageOptions(163-166)CreateIdeaInput(168-179)Idea(36-61)UpdateIdeaInput(181-190)IdeaStatus(19-19)ProjectAnalysisResult(131-151)IdeaCategory(9-18)AnalysisSuggestion(121-129)PromptCategory(95-100)IdeationPrompt(102-109)AnalysisFileInfo(115-119)apps/server/src/lib/sdk-options.ts (2)
validateWorkingDirectory(37-49)createChatOptions(500-535)libs/platform/src/paths.ts (7)
ensureIdeationDir(316-323)getIdeaDir(228-230)getIdeaPath(241-243)getIdeasDir(215-217)getIdeationAnalysisPath(303-305)getIdeationSessionsDir(266-268)getIdeationSessionPath(279-281)apps/server/src/providers/provider-factory.ts (1)
ProviderFactory(13-108)
libs/types/src/ideation.ts (2)
apps/ui/src/lib/electron.ts (10)
IdeaCategory(46-46)Idea(45-45)IdeationSession(47-47)IdeationMessage(48-48)AnalysisSuggestion(50-50)ProjectAnalysisResult(49-49)StartSessionOptions(51-51)CreateIdeaInput(52-52)UpdateIdeaInput(53-53)ConvertToFeatureOptions(54-54)libs/types/src/index.ts (23)
IdeaCategory(149-149)IdeaStatus(150-150)ImpactLevel(151-151)EffortLevel(152-152)IdeaAttachment(153-153)Idea(154-154)IdeationSessionStatus(155-155)IdeationSession(156-156)IdeationMessage(157-157)IdeationSessionWithMessages(158-158)PromptCategory(159-159)IdeationPrompt(160-160)AnalysisFileInfo(161-161)AnalysisSuggestion(162-162)ProjectAnalysisResult(163-163)StartSessionOptions(164-164)SendMessageOptions(165-165)CreateIdeaInput(166-166)UpdateIdeaInput(167-167)ConvertToFeatureOptions(168-168)IdeationEventType(169-169)IdeationStreamEvent(170-170)IdeationAnalysisEvent(171-171)
apps/ui/src/components/views/board-view/kanban-board.tsx (1)
apps/ui/src/components/ui/hotkey-button.tsx (1)
HotkeyButton(169-288)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: e2e
🔇 Additional comments (33)
.claude/.gitignore (1)
1-1: Clarify the purpose of thehans/directory being ignored.The pattern is syntactically correct, but the PR description doesn't explain why this directory should be ignored. Please clarify:
- What does the
hans/directory contain?- Why is it being added to
.gitignorein this PR?- Should this have been ignored previously?
This helps ensure the change aligns with repository conventions and doesn't accidentally hide important artifacts or source files.
apps/ui/src/components/views/board-view/kanban-board.tsx (2)
8-8: LGTM: Import cleanup aligns with removed suggestions feature.The removal of the
Lightbulbicon import is consistent with eliminating the legacy feature suggestions UI.
129-142: No action needed - hotkey is correctly registered at parent level.The
hotkeyActive={false}is intentional. Theshortcuts.startNexthotkey is registered globally in the parentboard-view.tsxcomponent via theuseBoardKeyboardShortcutshook (lines 800-804), which callsuseKeyboardShortcuts()to listen for the key event. The HotkeyButton here is purely a UI indicator showing the available shortcut; settinghotkeyActive={false}prevents duplicate key handling. This is the correct pattern.apps/server/src/routes/ideation/common.ts (1)
1-12: LGTM!Clean utility module that follows the established pattern for scoped logging and error handling. The re-export approach keeps error handling consistent across ideation routes.
apps/server/src/routes/ideation/routes/prompts.ts (1)
11-22: LGTM!The prompts handler follows best practices with proper error handling and clean response format.
libs/platform/src/paths.ts (2)
191-305: LGTM!The ideation path utilities follow the established patterns in this module with clear documentation and proper path hierarchy. All functions are pure path builders with no I/O side effects.
316-323: LGTM!The directory creation follows the established pattern used by
ensureAutomakerDirand safely creates all necessary subdirectories with proper path validation viasecureFs.libs/platform/src/index.ts (1)
26-36: LGTM!The new ideation path exports follow the established pattern and properly expose the utilities added to
paths.ts.apps/ui/src/components/views/ideation-view/data/guided-prompts.ts (1)
8-63: LGTM!The
PROMPT_CATEGORIESarray correctly includes all 9 categories defined in theIdeaCategorytype with appropriate metadata (name, icon, description).apps/ui/src/components/ui/keyboard-map.tsx (2)
93-95: LGTM!The new shortcut labels for
ideation,githubIssues, andgithubPrsare consistent with the existing naming patterns and provide clear human-readable descriptions.
121-123: LGTM!Correctly categorized as 'navigation' shortcuts, consistent with similar navigation items like
board,agent, andterminal.apps/ui/src/routes/ideation.tsx (1)
1-6: LGTM!Clean route definition following TanStack Router's file-based routing pattern. The component import and route configuration are correct. Based on learnings, this properly uses TanStack Router as required for frontend routing.
apps/server/src/routes/ideation/routes/ideas-list.ts (1)
9-25: LGTM!The handler follows the established pattern for ideation routes with proper input validation and error handling. The read-only list operation correctly delegates to
ideationService.getIdeas()without needing event emission.apps/server/src/routes/ideation/routes/ideas-update.ts (1)
10-45: LGTM!The handler follows the consistent CRUD pattern with thorough input validation for all required fields (
projectPath,ideaId,updates). The 404 handling for non-existent ideas is appropriate.apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts (4)
13-13: LGTM!Lightbulb icon is an appropriate choice for the Ideation feature.
34-36: LGTM!Interface extension for the new shortcuts is consistent with the existing pattern.
99-104: LGTM!The Ideation nav item is correctly structured and positioned at the top of the Tools section. The integration with the shortcuts system is properly wired.
185-192: LGTM!GitHub navigation items now have keyboard shortcuts properly assigned, improving keyboard accessibility for the GitHub section.
apps/ui/src/components/views/ideation-view/components/prompt-category-grid.tsx (1)
1-78: LGTM!Well-structured component with:
- Correct use of
@automaker/typesfor shared types (per coding guidelines)- Responsive grid layout with appropriate breakpoints
- Graceful fallback to
Zapicon when category icon isn't in the map- Clean navigation with back button
apps/ui/src/store/app-store.ts (1)
32-33: LGTM!The addition of
'ideation'to theViewModeunion is correct and aligns with the new ideation feature being introduced.apps/server/src/routes/ideation/routes/ideas-get.ts (1)
9-39: LGTM!The handler implementation is correct:
- Properly validates required fields (
projectPathandideaId)- Handles the not-found case with appropriate 404 response
- Uses centralized error handling utilities
- Response structure aligns with API conventions
apps/server/src/index.ts (1)
167-167: LGTM!The
IdeationServiceinstantiation correctly includes theeventsparameter, enabling event emissions for ideation operations.apps/server/src/routes/ideation/routes/ideas-create.ts (1)
10-42: LGTM! Clean validation and error handling.The handler follows good practices:
- Thorough input validation with explicit error messages
- Consistent use of shared error utilities (
logError,getErrorMessage)- Proper separation of concerns (delegates business logic to the service layer)
Note: Per coding guidelines, event emission for streaming to the frontend should occur within
IdeationService.createIdearather than in the route handler itself.apps/server/src/routes/ideation/routes/session-message.ts (1)
29-34: Verify error handling for immediate failures insendMessage.The fire-and-forget pattern responds with
{ success: true }immediately, but ifideationService.sendMessagethrows synchronously (e.g., session validation failure), that error will only be logged asynchronously and won't reach the client in the HTTP response.Consider whether immediate validation errors (like invalid sessionId) should be caught and returned to the client before responding with success.
Based on coding guidelines, verify that
IdeationService.sendMessageemits appropriate error events via the WebSocket connection so clients can handle failures through that channel.apps/server/src/routes/ideation/routes/analyze.ts (2)
9-30: LGTM! Consistent async pattern for streaming operations.The fire-and-forget pattern for
analyzeProjectis appropriate for long-running operations that stream results via WebSocket. Error handling uses shared utilities consistently.Note: Similar to
session-message.ts, immediate synchronous validation errors inanalyzeProjectwon't reach the HTTP response, but this appears to be an intentional architectural pattern for streaming operations.
32-49: LGTM! Clean synchronous fetch handler.The
getCachedAnalysishandler properly awaits the result and uses consistent error handling with shared utilities.apps/ui/src/hooks/use-keyboard-shortcuts.ts (1)
240-253: Excellent improvement for forward compatibility!Merging with
DEFAULT_KEYBOARD_SHORTCUTSensures that newly added shortcuts (like theideation: 'I'shortcut) are available even for users with older persisted state. The use ofuseMemowith proper dependencies is correct and prevents unnecessary recalculations.The merge order
{ ...DEFAULT_KEYBOARD_SHORTCUTS, ...keyboardShortcuts }correctly allows user customizations to override defaults.apps/server/src/routes/ideation/routes/session-start.ts (1)
1-30: LGTM!The handler follows the established pattern correctly: validates required input, delegates to the service, and handles errors consistently. Import from
@automaker/typesaligns with coding guidelines.apps/ui/src/components/views/ideation-view/index.tsx (1)
129-208: LGTM!The
IdeationViewcomponent is well-structured with clean navigation logic, appropriate memoization of callbacks, and good handling of the no-project state. The breadcrumb and header components provide consistent navigation patterns.apps/server/src/routes/ideation/index.ts (1)
37-38: The handlers for/session/messageand/session/stopdo not expectprojectPath. These endpoints work withsessionIdonly, which is already validated within the handlers themselves. Unlike/session/startand/session/getwhich operate on projects, these session-level endpoints operate on existing sessions identified bysessionIdand do not require path parameter validation.Likely an incorrect or invalid review comment.
libs/types/src/index.ts (1)
147-172: Ideation type re-exports look consistentThe new export block cleanly surfaces all ideation types from
./ideation.jsand matches the definitions used across server/UI. No issues from a typing or module-resolution perspective.apps/ui/src/components/views/ideation-view/components/prompt-list.tsx (1)
21-89: Prompt selection, job lifecycle, and error handling are solidThe prompt-selection flow (project presence check, per-prompt loading guard, generation job creation, state updates, and toast UX) is well-structured and integrates cleanly with
useIdeationStoreand the Electron/HTTP ideation API. The optional chaining onapi.ideationplus the generic error branch keeps failures graceful.Also applies to: 103-155
libs/types/src/ideation.ts (1)
9-61: Core ideation domain types are cohesive and match usageThe Idea/Session/Prompt/Analysis/CRUD option types are well-factored and line up with how the server and UI are using them (categories, status enums, analysis structures, etc.). No structural issues stand out here.
Also applies to: 69-151
apps/server/src/index.ts
Outdated
| app.use('/api/backlog-plan', createBacklogPlanRoutes(events, settingsService)); | ||
| app.use('/api/mcp', createMCPRoutes(mcpTestService)); | ||
| app.use('/api/pipeline', createPipelineRoutes(pipelineService)); | ||
| app.use('/api/ideation', createIdeationRoutes(ideationService, featureLoader)); |
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.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check createIdeationRoutes signature and how it wires route handlers
echo "=== Checking createIdeationRoutes signature ==="
ast-grep --pattern 'export function createIdeationRoutes($$$) {
$$$
}'
echo ""
echo "=== Checking how convert handler is wired ==="
rg -n -A5 'createConvertHandler'
echo ""
echo "=== Checking how session-stop handler is wired ==="
rg -n -A5 'createSessionStopHandler'Repository: AutoMaker-Org/automaker
Length of output: 3553
🏁 Script executed:
#!/bin/bash
# Get full createIdeationRoutes signature
echo "=== Full createIdeationRoutes signature and start of implementation ==="
sed -n '25,35p' apps/server/src/routes/ideation/index.ts
echo ""
echo "=== Check if convert.ts uses events or createEventEmitter ==="
rg -n 'createEventEmitter|events|emit' apps/server/src/routes/ideation/routes/convert.ts
echo ""
echo "=== Check if session-stop.ts uses events or createEventEmitter ==="
rg -n 'createEventEmitter|events|emit' apps/server/src/routes/ideation/routes/session-stop.ts
echo ""
echo "=== Check entire createIdeationRoutes function parameters ==="
head -40 apps/server/src/routes/ideation/index.ts | tail -20Repository: AutoMaker-Org/automaker
Length of output: 1350
🏁 Script executed:
#!/bin/bash
# Check context around line 221 in index.ts
echo "=== Context around line 221 in apps/server/src/index.ts ==="
sed -n '210,230p' apps/server/src/index.ts
echo ""
echo "=== Check ideationService type definition ==="
rg -A10 'class IdeationService|interface IdeationService' apps/server/src/
echo ""
echo "=== Check if events is created and available in index.ts ==="
rg -n 'const events|createEventEmitter' apps/server/src/index.ts | head -20Repository: AutoMaker-Org/automaker
Length of output: 2278
Ensure ideation route handlers emit events to frontend via WebSocket.
The createIdeationRoutes factory should receive the events parameter and pass it to route handlers (convert, session-stop, session-start, session-message, etc.), enabling them to emit events as required by the coding guideline. While ideationService has events available, the handlers are not currently emitting any events. See how createBacklogPlanRoutes(events, settingsService) on line 219 and createGitHubRoutes(events, settingsService) on line 218 receive events explicitly.
| export function createConvertHandler( | ||
| ideationService: IdeationService, | ||
| featureLoader: FeatureLoader | ||
| ) { | ||
| return async (req: Request, res: Response): Promise<void> => { | ||
| try { | ||
| const { projectPath, ideaId, keepIdea, column, dependencies, tags } = req.body as { | ||
| projectPath: string; | ||
| ideaId: string; | ||
| } & ConvertToFeatureOptions; | ||
|
|
||
| if (!projectPath) { | ||
| res.status(400).json({ success: false, error: 'projectPath is required' }); | ||
| return; | ||
| } | ||
|
|
||
| if (!ideaId) { | ||
| res.status(400).json({ success: false, error: 'ideaId is required' }); | ||
| return; | ||
| } | ||
|
|
||
| // Convert idea to feature structure | ||
| const featureData = await ideationService.convertToFeature(projectPath, ideaId); | ||
|
|
||
| // Apply any options from the request | ||
| if (column) { | ||
| featureData.status = column; | ||
| } | ||
| if (dependencies && dependencies.length > 0) { | ||
| featureData.dependencies = dependencies; | ||
| } | ||
| if (tags && tags.length > 0) { | ||
| featureData.tags = tags; | ||
| } | ||
|
|
||
| // Create the feature using FeatureLoader | ||
| const feature = await featureLoader.create(projectPath, featureData); | ||
|
|
||
| // Delete the idea unless keepIdea is explicitly true | ||
| if (!keepIdea) { | ||
| await ideationService.deleteIdea(projectPath, ideaId); | ||
| } | ||
|
|
||
| // Return featureId as expected by the frontend API interface | ||
| res.json({ success: true, featureId: feature.id }); | ||
| } catch (error) { | ||
| logError(error, 'Convert to feature failed'); | ||
| res.status(500).json({ success: false, error: getErrorMessage(error) }); | ||
| } | ||
| }; | ||
| } |
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.
Missing event emissions for convert operation.
According to the coding guidelines, all server operations should use createEventEmitter() to emit events that stream to the frontend via WebSocket. This handler performs significant operations (converting idea to feature, creating the feature, and optionally deleting the idea) but doesn't emit any events to notify the frontend of these changes.
As per coding guidelines, "Use createEventEmitter() from lib/events.ts for all server operations to emit events that stream to frontend via WebSocket."
🔎 Proposed fix to add event emissions
export function createConvertHandler(
ideationService: IdeationService,
- featureLoader: FeatureLoader
+ featureLoader: FeatureLoader,
+ events: EventEmitter
) {
return async (req: Request, res: Response): Promise<void> => {
try {
const { projectPath, ideaId, keepIdea, column, dependencies, tags } = req.body as {
projectPath: string;
ideaId: string;
} & ConvertToFeatureOptions;
if (!projectPath) {
res.status(400).json({ success: false, error: 'projectPath is required' });
return;
}
if (!ideaId) {
res.status(400).json({ success: false, error: 'ideaId is required' });
return;
}
// Convert idea to feature structure
const featureData = await ideationService.convertToFeature(projectPath, ideaId);
// Apply any options from the request
if (column) {
featureData.status = column;
}
if (dependencies && dependencies.length > 0) {
featureData.dependencies = dependencies;
}
if (tags && tags.length > 0) {
featureData.tags = tags;
}
// Create the feature using FeatureLoader
const feature = await featureLoader.create(projectPath, featureData);
+
+ // Emit event for feature creation
+ events.emit('feature:created', { projectPath, feature });
// Delete the idea unless keepIdea is explicitly true
if (!keepIdea) {
await ideationService.deleteIdea(projectPath, ideaId);
+ // Emit event for idea deletion
+ events.emit('ideation:idea:deleted', { projectPath, ideaId });
}
// Return featureId as expected by the frontend API interface
res.json({ success: true, featureId: feature.id });
} catch (error) {
logError(error, 'Convert to feature failed');
res.status(500).json({ success: false, error: getErrorMessage(error) });
}
};
}Note: You'll also need to update the route wiring in apps/server/src/routes/ideation/index.ts to pass the events parameter.
Committable suggestion skipped: line range outside the PR's diff.
| export function createSessionStopHandler(ideationService: IdeationService) { | ||
| return async (req: Request, res: Response): Promise<void> => { | ||
| try { | ||
| const { sessionId } = req.body as { sessionId: string }; | ||
|
|
||
| if (!sessionId) { | ||
| res.status(400).json({ success: false, error: 'sessionId is required' }); | ||
| return; | ||
| } | ||
|
|
||
| await ideationService.stopSession(sessionId); | ||
| res.json({ success: true }); | ||
| } catch (error) { | ||
| logError(error, 'Stop session failed'); | ||
| res.status(500).json({ success: false, error: getErrorMessage(error) }); | ||
| } | ||
| }; | ||
| } |
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.
Missing event emissions for session stop operation.
According to the coding guidelines, all server operations should use createEventEmitter() to emit events that stream to the frontend via WebSocket. This handler stops an ideation session but doesn't emit any events to notify the frontend of this state change.
As per coding guidelines, "Use createEventEmitter() from lib/events.ts for all server operations to emit events that stream to frontend via WebSocket."
🔎 Proposed fix to add event emission
-export function createSessionStopHandler(ideationService: IdeationService) {
+export function createSessionStopHandler(ideationService: IdeationService, events: EventEmitter) {
return async (req: Request, res: Response): Promise<void> => {
try {
const { sessionId } = req.body as { sessionId: string };
if (!sessionId) {
res.status(400).json({ success: false, error: 'sessionId is required' });
return;
}
await ideationService.stopSession(sessionId);
+
+ // Emit event for session stop
+ events.emit('ideation:session:stopped', { sessionId });
+
res.json({ success: true });
} catch (error) {
logError(error, 'Stop session failed');
res.status(500).json({ success: false, error: getErrorMessage(error) });
}
};
}Note: You'll also need to update the route wiring in apps/server/src/routes/ideation/index.ts to pass the events parameter.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/server/src/routes/ideation/routes/session-stop.ts around lines 9 to 26,
the handler stops a session but does not emit any events; update the handler to
create an event emitter via createEventEmitter() (imported from lib/events.ts),
use it to emit a session-stopped event (including sessionId and relevant
metadata) after ideationService.stopSession(sessionId) succeeds, and ensure
errors still log and respond as before; also update
apps/server/src/routes/ideation/index.ts to accept and pass the events emitter
into this route when wiring handlers.
| async sendMessage( | ||
| sessionId: string, | ||
| message: string, | ||
| options?: SendMessageOptions | ||
| ): Promise<void> { | ||
| const activeSession = this.activeSessions.get(sessionId); | ||
| if (!activeSession) { | ||
| throw new Error(`Session ${sessionId} not found`); | ||
| } | ||
|
|
||
| if (activeSession.isRunning) { | ||
| throw new Error('Session is already processing a message'); | ||
| } | ||
|
|
||
| activeSession.isRunning = true; | ||
| activeSession.abortController = new AbortController(); | ||
|
|
||
| // Add user message | ||
| const userMessage: IdeationMessage = { | ||
| id: this.generateId('msg'), | ||
| role: 'user', | ||
| content: message, | ||
| timestamp: new Date().toISOString(), | ||
| }; | ||
| activeSession.messages.push(userMessage); | ||
|
|
||
| // Emit user message | ||
| this.events.emit('ideation:stream', { | ||
| sessionId, | ||
| type: 'message', | ||
| message: userMessage, | ||
| }); | ||
|
|
||
| try { | ||
| const projectPath = activeSession.session.projectPath; | ||
|
|
||
| // Build conversation history | ||
| const conversationHistory = activeSession.messages.slice(0, -1).map((msg) => ({ | ||
| role: msg.role, | ||
| content: msg.content, | ||
| })); | ||
|
|
||
| // Load context files | ||
| const contextResult = await loadContextFiles({ | ||
| projectPath, | ||
| fsModule: secureFs as Parameters<typeof loadContextFiles>[0]['fsModule'], | ||
| }); | ||
|
|
||
| // Gather existing features and ideas to prevent duplicate suggestions | ||
| const existingWorkContext = await this.gatherExistingWorkContext(projectPath); | ||
|
|
||
| // Build system prompt for ideation | ||
| const systemPrompt = this.buildIdeationSystemPrompt( | ||
| contextResult.formattedPrompt, | ||
| activeSession.session.promptCategory, | ||
| existingWorkContext | ||
| ); | ||
|
|
||
| // Create SDK options | ||
| const sdkOptions = createChatOptions({ | ||
| cwd: projectPath, | ||
| model: options?.model || 'sonnet', | ||
| systemPrompt, | ||
| abortController: activeSession.abortController!, | ||
| }); | ||
|
|
||
| const effectiveModel = sdkOptions.model!; | ||
| const provider = ProviderFactory.getProviderForModel(effectiveModel); | ||
|
|
||
| const executeOptions: ExecuteOptions = { | ||
| prompt: message, | ||
| model: effectiveModel, | ||
| cwd: projectPath, | ||
| systemPrompt: sdkOptions.systemPrompt, | ||
| maxTurns: 1, // Single turn for ideation | ||
| abortController: activeSession.abortController!, | ||
| conversationHistory: conversationHistory.length > 0 ? conversationHistory : undefined, | ||
| }; | ||
|
|
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.
🛠️ Refactor suggestion | 🟠 Major
Normalize model aliases with resolveModelString before creating chat options
Both sendMessage and generateSuggestions currently pass raw aliases like 'sonnet' into createChatOptions:
const sdkOptions = createChatOptions({
cwd: projectPath,
model: options?.model || 'sonnet', // sendMessage
...
});
// and
const sdkOptions = createChatOptions({
cwd: projectPath,
model: 'sonnet', // generateSuggestions
...
});Per the repo guidelines for *.ts files, you should resolve aliases (haiku, sonnet, opus, etc.) via resolveModelString() from @automaker/model-resolver before handing them to the SDK/provider. That also guarantees ProviderFactory.getProviderForModel(effectiveModel) always sees a canonical model ID.
Consider something along the lines of:
import { resolveModelString } from '@automaker/model-resolver';
// …
const modelId = resolveModelString(options?.model ?? 'sonnet');
const sdkOptions = createChatOptions({
cwd: projectPath,
model: modelId,
systemPrompt,
abortController: activeSession.abortController!,
});and similarly for generateSuggestions, using a resolved default model.
Also applies to: 598-669
🤖 Prompt for AI Agents
In apps/server/src/services/ideation-service.ts around lines 145 to 223 (and
also apply same fix at ~598-669), the code passes raw model aliases like
'sonnet' into createChatOptions and ProviderFactory; resolveModelString from
@automaker/model-resolver should be used first. Import resolveModelString,
compute const modelId = resolveModelString(options?.model ?? 'sonnet') (or
resolve default for generateSuggestions), pass modelId into createChatOptions,
and then use the resolved modelId when calling
ProviderFactory.getProviderForModel and setting executeOptions.model so the SDK
and provider always receive a canonical model identifier.
| ideation: string; | ||
| githubIssues: string; | ||
| githubPrs: string; |
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.
🧩 Analysis chain
🏁 Script executed:
# First, locate and examine the app-store.ts file
find . -name "app-store.ts" -type fRepository: AutoMaker-Org/automaker
Length of output: 99
🏁 Script executed:
cat -n ./apps/ui/src/store/app-store.ts | head -250Repository: AutoMaker-Org/automaker
Length of output: 8421
🏁 Script executed:
# Search for keyboard shortcut usage - where githubIssues and startNext are actually bound/handled
echo "=== Searching for keyboard shortcut binding/event handling ==="
rg -n --type=ts --type=tsx "githubIssues|startNext" --context=5 | head -100Repository: AutoMaker-Org/automaker
Length of output: 174
🏁 Script executed:
# Search for githubIssues and startNext usage without file type restrictions
echo "=== Searching for githubIssues usage ==="
rg -n "githubIssues" --context=3 | head -80
echo ""
echo "=== Searching for startNext usage ==="
rg -n "startNext" --context=3 | head -80Repository: AutoMaker-Org/automaker
Length of output: 8959
🏁 Script executed:
# Search for keyboard event handling hooks and where shortcuts are actually bound
echo "=== Searching for useKeyboardShortcuts hook ==="
fd -t f "use.*keyboard" --type f | xargs head -100
echo ""
echo "=== Searching for keyboard event listeners and context handling ==="
rg -n "addEventListener.*keydown|onKeyDown|useEffect.*keyboard" --context=2 | head -100Repository: AutoMaker-Org/automaker
Length of output: 13694
🏁 Script executed:
# Read the full use-keyboard-shortcuts.ts file to understand the global keyboard handler
cat -n apps/ui/src/hooks/use-keyboard-shortcuts.ts | tail -150Repository: AutoMaker-Org/automaker
Length of output: 5707
🏁 Script executed:
# Search for where navigation items and their shortcuts are used to handle keyboard events
echo "=== Searching for navigation shortcut handling ==="
rg -n "use-navigation" --type ts | head -20
echo ""
echo "=== Searching for handler of github navigation shortcuts ==="
rg -n "github|Issues.*navigate|viewMode.*github" --context=3 | head -100
echo ""
echo "=== Checking if there's a global keyboard shortcut handler for navigation ==="
rg -n "useKeyboardShortcuts.*navigation|navigation.*shortcut" --context=5 | head -80Repository: AutoMaker-Org/automaker
Length of output: 7778
🏁 Script executed:
# Find where navigationShortcuts is defined in use-navigation
cat -n apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts | head -250Repository: AutoMaker-Org/automaker
Length of output: 8156
🏁 Script executed:
# Continue reading use-navigation.ts to see where githubIssues shortcut is registered
cat -n apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts | sed -n '250,350p'Repository: AutoMaker-Org/automaker
Length of output: 1339
Add context restriction for githubIssues shortcut to prevent conflict with startNext.
Both githubIssues (line 194) and startNext (line 205) use the 'G' key. While startNext is explicitly documented as "Only active in board view" (line 205), githubIssues is registered globally whenever a project has a GitHub remote. When in the board view with a GitHub-enabled project, both shortcuts fire simultaneously, creating unpredictable behavior.
Either restrict githubIssues to activate only outside board view, change its key binding, or add a modifier. Update the default shortcut assignment (lines 193-195) and add a clarifying comment to document the context restriction.
- Add 28 unit tests covering all major IdeationService functionality - Test session management (start, get, stop, running state) - Test idea CRUD operations (create, read, update, delete, archive) - Test idea to feature conversion with user stories and notes - Test project analysis and caching - Test prompt management and filtering - Test AI-powered suggestion generation - Mock all external dependencies (fs, platform, utils, providers) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Web Dev Cody <webdevcody@users.noreply.github.com>
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.
Actionable comments posted: 1
🧹 Nitpick comments (3)
apps/server/tests/unit/services/ideation-service.test.ts (3)
23-29: Consider using a model constant for the mock.The hardcoded model string
'claude-sonnet-4-20250514'in the mock is acceptable for test context, but consider extracting it to a constant if this model string is used elsewhere in tests to ease future updates.
127-155: Avoid flakysetTimeoutfor async coordination.Using
setTimeout(resolve, 10)to wait for async processing is fragile and can cause intermittent test failures. Consider usingvi.waitFor()or returning/awaiting the actual promise from the service method.🔎 Suggested improvement using vi.waitFor
await service.startSession(testProjectPath, options); - // Give time for the async message to process - await new Promise((resolve) => setTimeout(resolve, 10)); + // Wait for the async message to be processed + await vi.waitFor(() => { + expect(mockProvider.executeQuery).toHaveBeenCalled(); + }); - expect(mockProvider.executeQuery).toHaveBeenCalled(); });
302-305: Type assertions for mock directory entries are acceptable.The
as anyassertions for mockDirentobjects are a pragmatic approach when only specific properties (name,isDirectory) are needed. For improved type safety, you could create a helper function that returns properly typed mock directory entries.🔎 Optional: Helper for typed mock directory entries
// Add at top of describe block or in a test utilities file const mockDirent = (name: string, isDir: boolean) => ({ name, isDirectory: () => isDir, isFile: () => !isDir, isBlockDevice: () => false, isCharacterDevice: () => false, isSymbolicLink: () => false, isFIFO: () => false, isSocket: () => false, } as import('fs').Dirent);Also applies to: 344-347
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/server/tests/unit/services/ideation-service.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always import from shared packages (@automaker/*), never from old relative paths
Files:
apps/server/tests/unit/services/ideation-service.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
resolveModelString()from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names
Files:
apps/server/tests/unit/services/ideation-service.test.ts
🪛 GitHub Actions: Format Check
apps/server/tests/unit/services/ideation-service.test.ts
[warning] 1-1: Prettier reported code style issues in this file. Run 'prettier --write' to fix.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: e2e
🔇 Additional comments (8)
apps/server/tests/unit/services/ideation-service.test.ts (8)
1-16: Imports follow appropriate patterns.The imports correctly use
@automaker/*packages for shared code (platform, utils, types) and path aliases (@/) for internal server modules. This aligns with the coding guidelines to avoid old relative paths.
38-86: Test setup is well-structured.The
beforeEachproperly clears mocks, creates mock dependencies, and configures platform/utils mocks. TheafterEachcorrectly restores mocks. Good separation of concerns.
92-230: Session management tests are comprehensive.Good coverage of session lifecycle including start, get, stop, and running state checks. Tests appropriately verify event emissions, persistence, and edge cases (non-existent sessions).
236-487: Ideas CRUD tests provide solid coverage.Tests cover creation with required/optional fields, retrieval (including sorting by
updatedAt), updates, deletion, and archiving. Edge cases for invalid files and non-existent ideas are handled well.
493-575: Conversion tests verify the idea-to-feature mapping thoroughly.Tests confirm category mapping, user stories inclusion, notes inclusion, and error handling for non-existent ideas. Good validation of the transformed feature structure.
581-654: Project analysis tests verify event lifecycle and caching.Tests confirm analysis-started/complete events are emitted, error events on failure, and cache retrieval behavior. Good coverage.
660-704: Prompt management tests are adequate.Tests verify category retrieval, all prompts retrieval, and filtering by category. The
as anyassertion on line 699 is appropriate for testing non-existent category behavior.
710-762: Suggestion generation tests cover the happy path and error case.Tests verify event emission on generation start and proper error handling for non-existent prompts.
| @@ -0,0 +1,763 @@ | |||
| import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; | |||
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.
Fix Prettier formatting issues.
The pipeline reports formatting violations. Run prettier --write on this file to resolve the code style issues before merging.
#!/bin/bash
# Check current Prettier violations in this file
npx prettier --check "apps/server/tests/unit/services/ideation-service.test.ts" 2>&1 || true🧰 Tools
🪛 GitHub Actions: Format Check
[warning] 1-1: Prettier reported code style issues in this file. Run 'prettier --write' to fix.
🤖 Prompt for AI Agents
In apps/server/tests/unit/services/ideation-service.test.ts around lines 1 to 1,
the file fails Prettier formatting checks; run Prettier to fix style violations
by executing a format command (e.g., npx prettier --write
apps/server/tests/unit/services/ideation-service.test.ts) or integrate your
editor/IDE formatter, then stage the formatted file and re-run the pipeline to
ensure the formatting errors are resolved.
…tionService - Changed the category mapping for 'feature' from 'feature' to 'ui'. - Updated ID generation format to use hyphens instead of underscores for better readability. - Enhanced unit tests to reflect the updated category and ensure proper functionality.
…feature - Updated the ideation routes to include an EventEmitter for better event management. - Added a new endpoint to handle adding suggestions to the board, ensuring consistent category mapping. - Modified existing routes to emit events for idea creation, update, and deletion, improving frontend notifications. - Refactored the convert and create idea handlers to utilize the new event system. - Removed static guided prompts data in favor of dynamic fetching from the backend API.
Summary by CodeRabbit
New Features
Removals
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.