@@ -261,7 +261,10 @@ morgan.token('status-colored', (_req, res) => {
261261app . use (
262262 morgan ( ':method :url :status-colored' , {
263263 // Skip when request logging is disabled or for health check endpoints
264- skip : ( req ) => ! requestLoggingEnabled || req . url === '/api/health' ,
264+ skip : ( req ) =>
265+ ! requestLoggingEnabled ||
266+ req . url === '/api/health' ||
267+ req . url === '/api/auto-mode/context-exists' ,
265268 } )
266269) ;
267270// CORS configuration
@@ -349,7 +352,9 @@ const ideationService = new IdeationService(events, settingsService, featureLoad
349352
350353// Initialize DevServerService with event emitter for real-time log streaming
351354const devServerService = getDevServerService ( ) ;
352- devServerService . setEventEmitter ( events ) ;
355+ devServerService . initialize ( DATA_DIR , events ) . catch ( ( err ) => {
356+ logger . error ( 'Failed to initialize DevServerService:' , err ) ;
357+ } ) ;
353358
354359// Initialize Notification Service with event emitter for real-time updates
355360const notificationService = getNotificationService ( ) ;
@@ -434,21 +439,18 @@ eventHookService.initialize(events, settingsService, eventHistoryService, featur
434439 logger . info ( '[STARTUP] Feature state reconciliation complete - no stale states found' ) ;
435440 }
436441
437- // Resume interrupted features in the background after reconciliation.
438- // This uses the saved execution state to identify features that were running
439- // before the restart (their statuses have been reset to ready/backlog by
440- // reconciliation above). Running in background so it doesn't block startup.
441- if ( totalReconciled > 0 ) {
442- for ( const project of globalSettings . projects ) {
443- autoModeService . resumeInterruptedFeatures ( project . path ) . catch ( ( err ) => {
444- logger . warn (
445- `[STARTUP] Failed to resume interrupted features for ${ project . path } :` ,
446- err
447- ) ;
448- } ) ;
449- }
450- logger . info ( '[STARTUP] Initiated background resume of interrupted features' ) ;
442+ // Resume interrupted features in the background for all projects.
443+ // This handles features stuck in transient states (in_progress, pipeline_*)
444+ // or explicitly marked as interrupted. Running in background so it doesn't block startup.
445+ for ( const project of globalSettings . projects ) {
446+ autoModeService . resumeInterruptedFeatures ( project . path ) . catch ( ( err ) => {
447+ logger . warn (
448+ `[STARTUP] Failed to resume interrupted features for ${ project . path } :` ,
449+ err
450+ ) ;
451+ } ) ;
451452 }
453+ logger . info ( '[STARTUP] Initiated background resume of interrupted features' ) ;
452454 }
453455 } catch ( err ) {
454456 logger . warn ( '[STARTUP] Failed to reconcile feature states:' , err ) ;
@@ -494,7 +496,7 @@ app.use(
494496) ;
495497app . use ( '/api/auto-mode' , createAutoModeRoutes ( autoModeService ) ) ;
496498app . use ( '/api/enhance-prompt' , createEnhancePromptRoutes ( settingsService ) ) ;
497- app . use ( '/api/worktree' , createWorktreeRoutes ( events , settingsService ) ) ;
499+ app . use ( '/api/worktree' , createWorktreeRoutes ( events , settingsService , featureLoader ) ) ;
498500app . use ( '/api/git' , createGitRoutes ( ) ) ;
499501app . use ( '/api/models' , createModelsRoutes ( ) ) ;
500502app . use ( '/api/spec-regeneration' , createSpecRegenerationRoutes ( events , settingsService ) ) ;
@@ -596,24 +598,23 @@ wss.on('connection', (ws: WebSocket) => {
596598
597599 // Subscribe to all events and forward to this client
598600 const unsubscribe = events . subscribe ( ( type , payload ) => {
599- logger . info ( 'Event received:' , {
601+ // Use debug level for high-frequency events to avoid log spam
602+ // that causes progressive memory growth and server slowdown
603+ const isHighFrequency =
604+ type === 'dev-server:output' || type === 'test-runner:output' || type === 'feature:progress' ;
605+ const log = isHighFrequency ? logger . debug . bind ( logger ) : logger . info . bind ( logger ) ;
606+
607+ log ( 'Event received:' , {
600608 type,
601609 hasPayload : ! ! payload ,
602- payloadKeys : payload ? Object . keys ( payload ) : [ ] ,
603610 wsReadyState : ws . readyState ,
604- wsOpen : ws . readyState === WebSocket . OPEN ,
605611 } ) ;
606612
607613 if ( ws . readyState === WebSocket . OPEN ) {
608614 const message = JSON . stringify ( { type, payload } ) ;
609- logger . info ( 'Sending event to client:' , {
610- type,
611- messageLength : message . length ,
612- sessionId : ( payload as Record < string , unknown > ) ?. sessionId ,
613- } ) ;
614615 ws . send ( message ) ;
615616 } else {
616- logger . info ( 'WARNING: Cannot send event, WebSocket not open. ReadyState:', ws . readyState ) ;
617+ logger . warn ( ' Cannot send event, WebSocket not open. ReadyState:', ws . readyState ) ;
617618 }
618619 } ) ;
619620
0 commit comments