Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ RUN chmod +x /usr/local/bin/docker-entrypoint.sh

# Environment variables
ENV PORT=3008
ENV HOST=0.0.0.0
ENV DATA_DIR=/data
ENV HOME=/home/automaker
# Add user's local bin to PATH for cursor-agent
Expand Down
14 changes: 9 additions & 5 deletions apps/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -538,21 +538,25 @@ terminalWss.on('connection', (ws: WebSocket, req: import('http').IncomingMessage

// Start server with error handling for port conflicts
const startServer = (port: number) => {
server.listen(port, () => {
// Default to localhost for security, use HOST=0.0.0.0 for Docker (fixes #428)
const host = process.env.HOST || 'localhost';
server.listen(port, host, () => {
const terminalStatus = isTerminalEnabled()
? isTerminalPasswordRequired()
? 'enabled (password protected)'
: 'enabled'
: 'disabled';
const portStr = port.toString().padEnd(4);
// Display localhost for 0.0.0.0 binding (accessible via localhost)
const displayHost = host === '0.0.0.0' ? 'localhost' : host;
logger.info(`
╔═══════════════════════════════════════════════════════╗
║ Automaker Backend Server ║
╠═══════════════════════════════════════════════════════╣
║ HTTP API: http://localhost:${portStr} ║
║ WebSocket: ws://localhost:${portStr}/api/events ║
║ Terminal: ws://localhost:${portStr}/api/terminal/ws ║
║ Health: http://localhost:${portStr}/api/health ║
║ HTTP API: http://${displayHost}:${portStr} ║
║ WebSocket: ws://${displayHost}:${portStr}/api/events ║
║ Terminal: ws://${displayHost}:${portStr}/api/terminal/ws ║
║ Health: http://${displayHost}:${portStr}/api/health ║
║ Terminal: ${terminalStatus.padEnd(37)}║
╚═══════════════════════════════════════════════════════╝
`);
Expand Down
39 changes: 28 additions & 11 deletions apps/server/src/routes/setup/routes/deauth-claude.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,29 @@
*/

import type { Request, Response } from 'express';
import { getErrorMessage, logError } from '../common.js';
import * as fs from 'fs';
import { logError } from '../common.js';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Search for logError exports in shared packages and the codebase
rg "export.*logError" --type ts --type tsx --type js --type jsx -A 2

Repository: AutoMaker-Org/automaker

Length of output: 94


🏁 Script executed:

# Check where common.js is located relative to the file
fd "common.js" apps/server/src/

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Look for logError in @automaker packages
fd "@automaker" --type d | head -20

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Search for logError exports without incorrect type flag
rg "export.*logError" --type ts -A 2

Repository: AutoMaker-Org/automaker

Length of output: 3211


🏁 Script executed:

# Find common.js anywhere
fd "common\.js"

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Check the actual import path - look at the file structure
cat -n apps/server/src/routes/setup/routes/deauth-claude.ts | head -20

Repository: AutoMaker-Org/automaker

Length of output: 879


🏁 Script executed:

# Look for shared packages structure
git ls-files | grep -E "@automaker|packages|shared" | head -30

Repository: AutoMaker-Org/automaker

Length of output: 1661


🏁 Script executed:

# Check if this relative import pattern is used consistently across all routes
rg "from ['\"]\.\.\/common\.(?:js|ts)['\"]" --type ts | head -20

Repository: AutoMaker-Org/automaker

Length of output: 182


🏁 Script executed:

# Check if there's a shared packages directory or monorepo configuration
fd "package.json" | grep -E "(packages|shared)" | head -10

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Look at the common.ts in setup to understand the pattern
cat -n apps/server/src/routes/setup/common.ts | head -30

Repository: AutoMaker-Org/automaker

Length of output: 1001


🏁 Script executed:

# Check what's in the shared routes/common.js
cat -n apps/server/src/routes/common.js

Repository: AutoMaker-Org/automaker

Length of output: 131


🏁 Script executed:

# Look for @automaker packages that exist
fd "package.json" | xargs grep -l '"@automaker' | head -10

Repository: AutoMaker-Org/automaker

Length of output: 312


🏁 Script executed:

# Find the common.ts file at routes level
fd "common\.ts" apps/server/src/routes/ | grep -v node_modules

Repository: AutoMaker-Org/automaker

Length of output: 1076


🏁 Script executed:

# Check the structure of lib packages to see what's exported
cat -n libs/utils/package.json

Repository: AutoMaker-Org/automaker

Length of output: 1249


🏁 Script executed:

# Look at what's exported from @automaker/utils
fd "index\.(ts|js)" libs/utils/src/ -x cat -n {} \; | head -50

Repository: AutoMaker-Org/automaker

Length of output: 1343


🏁 Script executed:

# Check the main routes/common.ts file
cat -n apps/server/src/routes/common.ts

Repository: AutoMaker-Org/automaker

Length of output: 1271


🏁 Script executed:

# Check what's exported from @automaker/utils logger
cat -n libs/utils/src/logger.ts

Repository: AutoMaker-Org/automaker

Length of output: 8647


Move logError to a shared package to comply with coding guidelines.

Per coding guidelines, imports must use shared packages (@automaker/*) rather than relative paths. Currently, logError is imported from the relative path ../common.js. The createLogError function exists in apps/server/src/routes/common.ts but is not exported from any shared package. Extract and export createLogError (or a pre-configured logError function) from @automaker/utils or a dedicated shared logger package, then import from there instead of using a relative path.

🤖 Prompt for AI Agents
In @apps/server/src/routes/setup/routes/deauth-claude.ts at line 6, The import
of logError in deauth-claude.ts must be changed to come from a shared package:
extract or re-export the createLogError implementation (or a pre-configured
logError function) currently in apps/server/src/routes/common.ts into the shared
package (e.g., @automaker/utils or a dedicated @automaker/logger), export it
there, then update deauth-claude.ts to import logError from the shared package
instead of ../common.js; ensure the exported symbol name matches (createLogError
or logError) and update any callers to use that exported symbol.

import * as fs from 'fs/promises';
import * as path from 'path';

// Marker file location must be consistent with:
// - get-claude-status.ts (reads from .automaker/)
// - auth-claude.ts (deletes from .automaker/)
// - provider-factory.ts (checks in .automaker/)
const AUTOMAKER_DIR = '.automaker';
const DISCONNECTED_MARKER = '.claude-disconnected';

export function createDeauthClaudeHandler() {
return async (_req: Request, res: Response): Promise<void> => {
try {
// Create a marker file to indicate the CLI is disconnected from the app
const automakerDir = path.join(process.cwd(), '.automaker');
const markerPath = path.join(automakerDir, '.claude-disconnected');
const projectRoot = process.cwd();
const automakerDir = path.join(projectRoot, AUTOMAKER_DIR);
const markerPath = path.join(automakerDir, DISCONNECTED_MARKER);

// Ensure .automaker directory exists
if (!fs.existsSync(automakerDir)) {
fs.mkdirSync(automakerDir, { recursive: true });
}
await fs.mkdir(automakerDir, { recursive: true });

// Create the marker file with timestamp
fs.writeFileSync(
await fs.writeFile(
markerPath,
JSON.stringify({
disconnectedAt: new Date().toISOString(),
Expand All @@ -34,10 +39,22 @@ export function createDeauthClaudeHandler() {
});
} catch (error) {
logError(error, 'Deauth Claude failed');

// Return generic error to client (security: don't expose paths)
// Detailed diagnostics are in server logs
const nodeError = error as NodeJS.ErrnoException;
let userMessage = 'Failed to disconnect Claude CLI';
if (nodeError.code === 'EACCES') {
userMessage = 'Permission denied. Check directory permissions.';
} else if (nodeError.code === 'ENOSPC') {
userMessage = 'No space left on device.';
} else if (nodeError.code === 'EROFS') {
userMessage = 'Read-only filesystem. Check volume mounts.';
}

res.status(500).json({
success: false,
error: getErrorMessage(error),
message: 'Failed to disconnect Claude CLI from the app',
error: userMessage,
});
}
};
Expand Down
21 changes: 11 additions & 10 deletions apps/server/src/services/ideation-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1682,18 +1682,19 @@ Focus on practical, implementable suggestions that would genuinely improve the p
* Used by both idea-to-feature conversion and suggestion-to-feature conversion.
*/
mapSuggestionCategoryToFeatureCategory(category: IdeaCategory): string {
// Use capitalized categories to match existing conventions (fixes #396)
const mapping: Record<IdeaCategory, string> = {
feature: 'ui',
'ux-ui': 'enhancement',
dx: 'chore',
growth: 'feature',
technical: 'refactor',
security: 'bug',
performance: 'enhancement',
accessibility: 'enhancement',
analytics: 'feature',
feature: 'Feature',
'ux-ui': 'UI',
dx: 'DX',
growth: 'Growth',
technical: 'Technical',
security: 'Security',
performance: 'Performance',
accessibility: 'Accessibility',
analytics: 'Analytics',
};
return mapping[category] || 'feature';
return mapping[category] || 'Feature';
}
Comment on lines 1684 to 1698
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
cd /root

# Check the imports and structure of ideation-service.ts
echo "=== Checking ideation-service.ts imports ==="
head -50 apps/server/src/services/ideation-service.ts

echo ""
echo "=== Search for category usage patterns in codebase ==="
# Look for where categories are defined or used with capitalized names
rg -n --type=ts --type=tsx "Feature|DX|Growth|Technical|Security|Performance|Accessibility|Analytics" -g '!*.test.*' -g '!node_modules' --max-count=20 | head -40

echo ""
echo "=== Search for lowercase category patterns ==="
rg -n --type=ts --type=tsx "feature|growth|technical|security|performance|accessibility|analytics" -C1 -g '!*.test.*' -g '!node_modules' --max-count=25 | head -50

Repository: AutoMaker-Org/automaker

Length of output: 1857


🏁 Script executed:

#!/bin/bash
# Check for Feature category field definitions
echo "=== Searching for Feature category usage ==="
rg -n "category" -t ts --max-count=30 | grep -i feature | head -20

echo ""
echo "=== Check for Feature type definition ==="
rg -n "type Feature" -t ts

echo ""
echo "=== Search for where Feature objects are created ==="
rg -n "category.*Feature\|Feature.*category" -t ts | head -20

echo ""
echo "=== Look at feature-related files in services ==="
git ls-files apps/server/src/services/ | grep -i feature

echo ""
echo "=== Check database schemas or migrations for category values ==="
git ls-files | grep -E "(schema|migration|seed|fixture)" | head -10

Repository: AutoMaker-Org/automaker

Length of output: 3454


🏁 Script executed:

#!/bin/bash
# Get Feature type definition
echo "=== Feature type definition ==="
cat -n libs/types/src/feature.ts | head -80

echo ""
echo "=== Search for both mapping methods in ideation-service ==="
rg -n "mapIdeaCategoryToFeatureCategory|mapSuggestionCategoryToFeatureCategory" -A 15 apps/server/src/services/ideation-service.ts

echo ""
echo "=== Check test fixtures for feature data ==="
cat -n apps/server/tests/fixtures/configs.ts | head -150

Repository: AutoMaker-Org/automaker

Length of output: 4841


🏁 Script executed:

#!/bin/bash
# Find IdeaCategory type definition
echo "=== IdeaCategory type definition ==="
rg -n "type IdeaCategory|enum IdeaCategory" -A 10 libs/types/

echo ""
echo "=== Search for actual feature category values in code ==="
rg -n "category.*:" apps/server/src/ -t ts --max-count=40 | grep -E "(Feature|UI|DX|Growth|Technical|Security|Performance|Accessibility|Analytics|feature|ui|growth)" | head -30

echo ""
echo "=== Check for CategoryAutocomplete component (used in edit dialog) ==="
rg -n "CategoryAutocomplete" -A 30 apps/ui/src/components/ui/ 2>/dev/null | head -50

Repository: AutoMaker-Org/automaker

Length of output: 5974


🏁 Script executed:

#!/bin/bash
# Search for actual feature category examples in project files/data
echo "=== Search for category values in feature data files ==="
find . -name "features.json" -o -name "*.feature.json" 2>/dev/null | head -5

echo ""
echo "=== Search for category patterns across the codebase ==="
rg -n '"category"' -A 1 apps/server/src/ -t ts --max-count=50 | head -80

echo ""
echo "=== Check where ideas/suggestions are created with categories ==="
rg -n "AnalysisSuggestion|suggestion.*category" -B 2 -A 2 apps/server/src/ -t ts | head -60

Repository: AutoMaker-Org/automaker

Length of output: 4845


🏁 Script executed:

#!/bin/bash
# Find AnalysisSuggestion type definition
echo "=== AnalysisSuggestion type definition ==="
rg -n "interface AnalysisSuggestion|type AnalysisSuggestion" -A 15 libs/types/

echo ""
echo "=== Search for where suggestions are converted to features ==="
rg -n "suggestionToFeature|suggestion.*Feature" apps/server/src/ -t ts | head -20

echo ""
echo "=== Check add-suggestion route that uses mapSuggestionCategoryToFeatureCategory ==="
cat -n apps/server/src/routes/ideation/routes/add-suggestion.ts | head -80

Repository: AutoMaker-Org/automaker

Length of output: 3959


🏁 Script executed:

#!/bin/bash
# Search for issue #396 references
echo "=== Search for issue #396 context ==="
rg -n "#396|396" apps/server/src -t ts -B 3 -A 3

echo ""
echo "=== Look for existing category patterns in board/feature displays ==="
rg -n "category" apps/ui/src/components/views/board-view.tsx -B 2 -A 2 | head -40

echo ""
echo "=== Check if there are any test files that show expected categories ==="
git ls-files | grep -i "test\|spec" | grep -i "ideation\|suggestion" | head -5

Repository: AutoMaker-Org/automaker

Length of output: 2238


🏁 Script executed:

#!/bin/bash
# Check the ideation service test file
echo "=== Ideation service tests ==="
cat -n apps/server/tests/unit/services/ideation-service.test.ts | head -300

Repository: AutoMaker-Org/automaker

Length of output: 12614


🏁 Script executed:

#!/bin/bash
# Search for mapping function tests
echo "=== Search for category mapping tests ==="
rg -n "mapSuggestionCategoryToFeatureCategory|mapIdeaCategoryToFeatureCategory" -B 2 -A 10 apps/server/tests/ -t ts

echo ""
echo "=== Check board view to see what categories are actually displayed ==="
cat -n apps/ui/src/components/views/board-view.tsx | sed -n '255,290p'

echo ""
echo "=== Search for example features with categories ==="
rg -n "'Feature'|'UI'|'DX'|'Growth'" apps/ -t ts -t tsx | grep -v node_modules | grep -v test | head -20

Repository: AutoMaker-Org/automaker

Length of output: 1928


🏁 Script executed:

#!/bin/bash
# Search for where capitalized categories might be used
echo "=== Search for Capitalized category patterns ==="
rg -n "Feature|Growth|Technical|Security|Performance|Accessibility|Analytics|DX|UI" apps/server/src/services/ideation-service.ts -C 1 | grep -A 2 -B 2 "mapping\|1687\|1688\|1689\|1690"

echo ""
echo "=== Look at feature-loader to see how categories are persisted ==="
rg -n "category" apps/server/src/services/feature-loader.ts -B 2 -A 2 | head -50

echo ""
echo "=== Search for where idea-to-feature conversion is tested ==="
cat -n apps/server/tests/unit/services/ideation-service.test.ts | tail -200

Repository: AutoMaker-Org/automaker

Length of output: 9071


Category mapping standardizes format for consistency.

The mapping converts lowercase IdeaCategory values to capitalized feature categories, preventing duplicate lowercase and capitalized variants that could result from inconsistent casing. The mapping is correctly applied in the add-suggestion route (line 52) and serves as the single source of truth for idea/suggestion-to-feature conversion.

🤖 Prompt for AI Agents
In @apps/server/src/services/ideation-service.ts around lines 1684 - 1698, The
mapSuggestionCategoryToFeatureCategory function currently converts IdeaCategory
values to capitalized strings but may miss future categories; ensure the mapping
object in mapSuggestionCategoryToFeatureCategory exactly covers every variant of
the IdeaCategory union, keep its type as Record<IdeaCategory, string>, add any
missing category keys (using their exact IdeaCategory symbol names like feature,
'ux-ui', dx, growth, technical, security, performance, accessibility,
analytics), and keep the fallback to 'Feature'; then confirm the add-suggestion
route uses mapSuggestionCategoryToFeatureCategory for all idea->feature
conversions so the mapping remains the single source of truth.


private async saveSessionToDisk(
Expand Down
2 changes: 1 addition & 1 deletion apps/server/tests/unit/services/ideation-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ describe('IdeationService', () => {
expect(feature.id).toMatch(/^feature-/);
expect(feature.title).toBe('Add Dark Mode');
expect(feature.description).toBe('Implement dark mode theme');
expect(feature.category).toBe('ui'); // features -> ui mapping
expect(feature.category).toBe('Feature'); // features -> Feature mapping (capitalized, fixes #396)
expect(feature.status).toBe('backlog');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,15 +401,15 @@ export function AgentOutputModal({
)}
</div>
) : effectiveViewMode === 'summary' && summary ? (
<div className="flex-1 overflow-y-auto bg-zinc-950 rounded-lg p-4 min-h-[400px] max-h-[60vh] scrollbar-visible">
<div className="flex-1 overflow-y-auto bg-muted/50 dark:bg-zinc-950 rounded-lg p-4 min-h-[400px] max-h-[60vh] scrollbar-visible">
<Markdown>{summary}</Markdown>
</div>
) : (
<>
<div
ref={scrollRef}
onScroll={handleScroll}
className="flex-1 overflow-y-auto bg-zinc-950 rounded-lg p-4 font-mono text-xs min-h-[400px] max-h-[60vh] scrollbar-visible"
className="flex-1 overflow-y-auto bg-muted/50 dark:bg-zinc-950 rounded-lg p-4 font-mono text-xs min-h-[400px] max-h-[60vh] scrollbar-visible"
>
{isLoading && !output ? (
<div className="flex items-center justify-center h-full text-muted-foreground">
Expand All @@ -423,7 +423,7 @@ export function AgentOutputModal({
) : effectiveViewMode === 'parsed' ? (
<LogViewer output={output} />
) : (
<div className="whitespace-pre-wrap break-words text-zinc-300">{output}</div>
<div className="whitespace-pre-wrap break-words text-foreground/80">{output}</div>
)}
</div>

Expand Down