Skip to content

Fix dev server hang by reducing log spam and event frequency#828

Merged
gsxdsm merged 4 commits intoAutoMaker-Org:v1.0.0rcfrom
gsxdsm:fix/dev-server-hang
Mar 3, 2026
Merged

Fix dev server hang by reducing log spam and event frequency#828
gsxdsm merged 4 commits intoAutoMaker-Org:v1.0.0rcfrom
gsxdsm:fix/dev-server-hang

Conversation

@gsxdsm
Copy link
Collaborator

@gsxdsm gsxdsm commented Mar 3, 2026

Summary

  • Reduces WebSocket event logging to prevent progressive memory growth and browser slowdown
  • Increases output throttling from 4ms to 100ms (~250fps to 10fps) to keep WebSocket traffic manageable
  • Batches rapid dev server log updates using requestAnimationFrame to prevent excessive React re-renders
  • Extends state reconciliation interval from 5s to 30s as a fallback since WebSocket handles real-time updates
  • Improves Vite module resolution to prevent duplicate React instances across dep-optimization

Changes

Server-side logging optimization (apps/server/src/index.ts)

  • Changed high-frequency events (dev-server:output, test-runner:output, feature:progress) to use debug log level instead of info to prevent console spam
  • Removed verbose logging of payload keys and message length that contributed to accumulated memory growth
  • Changed WebSocket not-open warning from info to warn level
  • Added comment explaining the rationale: high-frequency events cause progressive memory growth and server slowdown

Dev server output throttling (apps/server/src/services/dev-server-service.ts)

  • Increased OUTPUT_THROTTLE_MS from 4ms (~250fps) to 100ms (~10fps) for more manageable WebSocket traffic
  • Increased OUTPUT_BATCH_SIZE from 4096 to 8192 bytes to compensate for lower update frequency
  • Added detailed comment explaining that the previous 4ms rate generated up to 250 events/sec, causing progressive browser slowdown from accumulated console logs, JSON serialization overhead, and React re-renders

Client-side event batching (apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts)

  • Refactored appendLogs to batch rapid output events using requestAnimationFrame, ensuring at most one React re-render per animation frame (~60fps max)
  • Extracted buffering logic into flushPendingOutput function that accumulates content and flushes it in RAF callbacks
  • Added cleanup effect to cancel pending RAF on unmount, preventing state updates after component unmount

Client-side polling optimization (apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-servers.ts)

  • Increased STATE_RECONCILE_INTERVAL_MS from 5s to 30s since WebSocket events handle real-time updates; reconciliation is only a fallback for missed events
  • Added global event recording on non-high-frequency WebSocket events (excludes dev-server:output) so smart polling recognizes WebSocket connectivity and doesn't trigger unnecessary query polling
  • Imported and used useEventRecencyStore to signal WebSocket health to the polling system

Client-side WebSocket message logging (apps/ui/src/lib/http-api-client.ts)

  • Reduced WebSocket message logging by skipping high-frequency event types (dev-server:output, test-runner:output, auto_mode_progress)
  • Removed callback dispatch count logging that added unnecessary overhead

Vite configuration improvements (apps/ui/vite.config.mts)

  • Added cacheDir configuration to keep dep-optimization cache local to apps/ui, preventing shared state across worktrees that can produce duplicate React instances
  • Added explicit subpath aliases for react/jsx-runtime and react/jsx-dev-runtime to prevent mixed module IDs between bare imports and optimized deps
  • Expanded dedupe list to include zustand, use-sync-external-store, and @xyflow/react, ensuring single instances are used across the application
  • Updated optimize include list to add React subpaths and use-sync-external-store variants for consistent pre-bundling

Test update (apps/server/tests/unit/services/dev-server-event-types.test.ts)

  • Updated test timeout from 100ms to 250ms to account for the new 100ms throttle rate, ensuring tests don't flake due to timing

Summary by CodeRabbit

  • Bug Fixes

    • Improved WebSocket health tracking to cut unnecessary polling.
    • Reduced log noise by changing log levels for very frequent events and removing redundant client-send messages.
  • Performance

    • Batched UI log updates to avoid excessive re-renders.
    • Slowed and batched dev-server output to improve stability and reduce browser load.
  • Chores

    • Localized build cache per workspace to prevent cross-workspace conflicts.
  • New Features

    • Dev server now exposes a stable allocated-port value for bookkeeping.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, 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 addresses performance and stability issues in the development server and UI by implementing a series of optimizations. The primary goal is to prevent the dev server from hanging and the browser from slowing down due to excessive logging, high event frequency, and duplicate React instances. Changes include reducing server-side log spam, throttling WebSocket output, batching client-side log updates, extending polling intervals, and refining Vite's configuration for dependency resolution.

Highlights

  • Reduced WebSocket event logging: WebSocket event logging was reduced to prevent progressive memory growth and browser slowdown.
  • Increased output throttling: Output throttling was increased from 4ms to 100ms (from ~250fps to 10fps) to manage WebSocket traffic more effectively.
  • Batched rapid dev server log updates: Rapid dev server log updates are now batched using requestAnimationFrame to prevent excessive React re-renders.
  • Extended state reconciliation interval: The state reconciliation interval was extended from 5s to 30s, as WebSocket handles real-time updates and reconciliation serves as a fallback.
  • Improved Vite module resolution: Vite module resolution was improved to prevent duplicate React instances across dependency optimization.

🧠 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.

Changelog
  • apps/server/src/index.ts
    • Changed high-frequency events (dev-server:output, test-runner:output, feature:progress) to use debug log level instead of info to prevent console spam
    • Removed verbose logging of payload keys and message length that contributed to accumulated memory growth
    • Changed WebSocket not-open warning from info to warn level
    • Added comment explaining the rationale: high-frequency events cause progressive memory growth and server slowdown
  • apps/server/src/services/dev-server-service.ts
    • Increased OUTPUT_THROTTLE_MS from 4ms (~250fps) to 100ms (~10fps) for more manageable WebSocket traffic
    • Increased OUTPUT_BATCH_SIZE from 4096 to 8192 bytes to compensate for lower update frequency
    • Added detailed comment explaining that the previous 4ms rate generated up to 250 events/sec, causing progressive browser slowdown from accumulated console logs, JSON serialization overhead, and React re-renders
  • apps/server/tests/unit/services/dev-server-event-types.test.ts
    • Updated test timeout from 100ms to 250ms to account for the new 100ms throttle rate, ensuring tests don't flake due to timing
  • apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts
    • Refactored appendLogs to batch rapid output events using requestAnimationFrame, ensuring at most one React re-render per animation frame (~60fps max)
    • Extracted buffering logic into flushPendingOutput function that accumulates content and flushes it in RAF callbacks
    • Added cleanup effect to cancel pending RAF on unmount, preventing state updates after component unmount
  • apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-servers.ts
    • Increased STATE_RECONCILE_INTERVAL_MS from 5s to 30s since WebSocket events handle real-time updates; reconciliation is only a fallback for missed events
    • Added global event recording on non-high-frequency WebSocket events (excludes dev-server:output) so smart polling recognizes WebSocket connectivity and doesn't trigger unnecessary query polling
    • Imported and used useEventRecencyStore to signal WebSocket health to the polling system
  • apps/ui/src/lib/http-api-client.ts
    • Reduced WebSocket message logging by skipping high-frequency event types (dev-server:output, test-runner:output, auto_mode_progress)
    • Removed callback dispatch count logging that added unnecessary overhead
  • apps/ui/vite.config.mts
    • Added cacheDir configuration to keep dep-optimization cache local to apps/ui, preventing shared state across worktrees that can produce duplicate React instances
    • Added explicit subpath aliases for react/jsx-runtime and react/jsx-dev-runtime to prevent mixed module IDs between bare imports and optimized deps
    • Expanded dedupe list to include zustand, use-sync-external-store, and @xyflow/react, ensuring single instances are used across the application
    • Updated optimize include list to add React subpaths and use-sync-external-store variants for consistent pre-bundling
Activity
  • No specific review comments or activity have been recorded for this pull request yet.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

Optimizes WebSocket logging and dev-server output frequency, adds an allocatedPort field to DevServerInfo, introduces RAF-based batching for UI dev-server logs, records WebSocket health to suppress polling, and tightens Vite React resolution and per-worktree caching.

Changes

Cohort / File(s) Summary
Server WebSocket Logging
apps/server/src/index.ts, apps/ui/src/lib/http-api-client.ts
High-frequency WS events (dev-server:output, test-runner:output, feature:progress, and auto-mode progress) are treated as high-frequency: filtered and logged at debug; other messages logged at info. Removed detailed payload/wsOpen logs and the separate "Sending event to client" message; non-open WS logged as warn.
Dev Server Service & Tests
apps/server/src/services/dev-server-service.ts, apps/server/tests/unit/services/dev-server-event-types.test.ts
Increased OUTPUT_THROTTLE_MS (4ms → 100ms) and OUTPUT_BATCH_SIZE (4096 → 8192). Added allocatedPort: number to DevServerInfo and populate it on start. Test wait extended to match throttle change.
UI Log Buffering
apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts
Replaced immediate state appends with buffered batching using RAF + fallback timer (pendingOutputRef). Added appendLogs, flushPendingOutput, resetPendingOutput, immediate flush at buffer limit, and cleanup to avoid updates after unmount or on server restart.
UI Features & WebSocket Health
apps/ui/src/components/views/board-view/hooks/use-board-features.ts, apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-servers.ts
Removed direct refetch; loadFeatures now invalidates features.all. Added useEventRecencyStore.recordGlobalEvent calls for non-output dev-server events to mark WS alive. Increased STATE_RECONCILE_INTERVAL_MS from 5,000ms to 30,000ms.
Vite Config / Dependency Resolution
apps/ui/vite.config.mts
Added cacheDir to localize dep-opt cache per worktree. Added explicit aliases for react/jsx-runtime and react/jsx-dev-runtime, extended dedupe to include zustand, use-sync-external-store, @xyflow/react, and included runtime/subpath entries in optimizeDeps.include.

Sequence Diagram(s)

sequenceDiagram
  participant Server as Server (DevServer Service)
  participant WS as WebSocket
  participant Client as UI (http-api-client)
  participant Buffer as UI Buffer (use-dev-server-logs)
  participant Store as UI State

  rect rgba(200,200,255,0.5)
  Server->>WS: emit dev-server:output (high-frequency)
  end

  rect rgba(200,255,200,0.5)
  WS->>Client: onmessage (raw event)
  Client->>Client: filter high-frequency events -> log at debug or info
  Client->>Buffer: deliver event (appendLogs)
  end

  rect rgba(255,200,200,0.5)
  Buffer->>Buffer: batch via requestAnimationFrame / fallback timer
  Buffer->>Store: flushPendingOutput -> commit logs to state
  end

  rect rgba(255,255,200,0.5)
  Note over Client,Store: For non-output events Client calls recordGlobalEvent() to mark WS healthy, suppressing reconciliation polling
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

Performance, Ready-To-Merge

Poem

🐇 I hop through packets, nibble noise to bits,
Batch the bursts with gentle fits,
Ports remembered, caches neat,
WebSocket beats in calmer feet,
A rabbit cheers—logs trimmed and sweet. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objectives: reducing log spam and event frequency to fix dev server hangs, which aligns with the core changes across server logging, throttling, batching, and reconciliation intervals.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts`:
- Around line 197-205: The current useEffect only cleans rafIdRef on unmount,
allowing stale pendingOutputRef to carry across worktree/session changes; modify
the effect in use-dev-server-logs.ts (the useEffect that currently returns the
raf cancellation) to run on relevant context changes (e.g., worktree id /
session id / dev-server started flag) instead of an empty dependency array and
inside its cleanup reset pendingOutputRef.current = "" (or null/[]) and
cancelAnimationFrame(rafIdRef.current) then set rafIdRef.current = null so any
buffered output is cleared whenever the worktree or dev-server session changes;
ensure you reference pendingOutputRef and rafIdRef in the dependency closure
correctly.

In `@apps/ui/src/lib/http-api-client.ts`:
- Around line 930-936: The high-frequency filter (variable isHighFrequency)
currently only checks data.type === 'auto_mode_progress' and misses wrapped
auto-mode messages like data.type === 'auto-mode:event'; update isHighFrequency
to also mark messages as high-frequency when data.type === 'auto-mode:event' and
the event payload indicates progress (e.g., data.payload?.subtype ===
'auto_mode_progress' or similar), while keeping the existing checks for
'dev-server:output' and 'test-runner:output' so logger.info('WebSocket
message:', data.type) is skipped for these high-frequency auto-mode progress
events.

In `@apps/ui/vite.config.mts`:
- Around line 256-268: The regex alias find: /^react(\/|$)/ is shadowing the
explicit aliases for 'react/jsx-runtime' and 'react/jsx-dev-runtime' so those
entries never match; fix by reordering the alias array in vite.config.mts to
place the explicit aliases for 'react/jsx-runtime' and 'react/jsx-dev-runtime'
(replacement paths pointing to ../../node_modules/react/...js) before the
broader /^react(\/|$)/ entry so Vite applies the specific matches first and
enables the deduplication fix.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2915f4 and fc6c69f.

📒 Files selected for processing (8)
  • apps/server/src/index.ts
  • apps/server/src/services/dev-server-service.ts
  • apps/server/tests/unit/services/dev-server-event-types.test.ts
  • apps/ui/src/components/views/board-view/hooks/use-board-features.ts
  • apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts
  • apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-servers.ts
  • apps/ui/src/lib/http-api-client.ts
  • apps/ui/vite.config.mts

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a 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 addresses a critical performance issue in the Automaker development server by reducing log spam, throttling output, batching events, and optimizing Vite configuration. The changes aim to prevent memory growth, browser slowdown, and duplicate React instances. The review focuses on the server-side logging optimization and dev server output throttling, ensuring the changes effectively mitigate the identified problems and maintain code clarity.

Note: Security Review did not run due to the size of the PR.

Comment on lines +96 to +97
const OUTPUT_THROTTLE_MS = 100; // ~10fps max update rate
const OUTPUT_BATCH_SIZE = 8192; // Larger batches to compensate for lower frequency
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The OUTPUT_THROTTLE_MS and OUTPUT_BATCH_SIZE constants are updated to 100ms and 8192 bytes, respectively. While these values are chosen to balance log streaming readability and WebSocket traffic, it's important to consider making these configurable via environment variables. This would allow administrators to fine-tune the throttling behavior without requiring code changes.

Making these values configurable would provide flexibility to adapt to different network conditions and browser capabilities.

Suggested change
const OUTPUT_THROTTLE_MS = 100; // ~10fps max update rate
const OUTPUT_BATCH_SIZE = 8192; // Larger batches to compensate for lower frequency
const OUTPUT_THROTTLE_MS = parseInt(process.env.OUTPUT_THROTTLE_MS || '100', 10); // ~10fps max update rate
const OUTPUT_BATCH_SIZE = parseInt(process.env.OUTPUT_BATCH_SIZE || '8192', 10); // Larger batches to compensate for lower frequency

} else {
logger.info('WARNING: Cannot send event, WebSocket not open. ReadyState:', ws.readyState);
logger.warn('Cannot send event, WebSocket not open. ReadyState:', ws.readyState);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The log level for the WebSocket not-open warning is changed from info to warn. While this change aligns with the severity of the message, it's important to ensure that such warnings are appropriately handled and monitored in a production environment. Consider adding metrics or alerts to track the frequency of these warnings to proactively address potential WebSocket connectivity issues.

If the WebSocket is not opened, it might be a critical issue that needs to be addressed soon.

Comment on lines +91 to +95
// Throttle output to prevent overwhelming WebSocket under heavy load.
// 100ms (~10fps) is sufficient for readable log streaming while keeping
// WebSocket traffic manageable. The previous 4ms rate (~250fps) generated
// up to 250 events/sec which caused progressive browser slowdown from
// accumulated console logs, JSON serialization overhead, and React re-renders.
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The comments added to explain the throttling mechanism are very helpful for understanding the rationale behind the changes. However, the comment could be improved by explicitly mentioning the specific metrics or monitoring tools that can be used to observe the impact of the throttling on browser performance and server load. This would provide additional guidance for future maintenance and optimization.

It's important to monitor the impact of this change on the user experience. If the throttling is too aggressive, it could lead to a noticeable degradation in the responsiveness of the dev server logs.

Comment on lines +93 to +94
// Throttled output needs a bit of time (OUTPUT_THROTTLE_MS is 100ms)
await new Promise((resolve) => setTimeout(resolve, 250));
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The timeout in the test is increased from 100ms to 250ms to accommodate the new throttle rate. While this addresses the immediate issue, it's important to ensure that the test remains reliable and doesn't become flaky due to timing variations. Consider adding additional assertions or retries to make the test more robust.

It's important to ensure that the test consistently passes and doesn't flake due to timing issues.

gsxdsm and others added 2 commits March 2, 2026 23:17
- Reset RAF buffer on context changes (worktree switch, dev-server restart)
  to prevent stale output from flushing into new sessions
- Fix high-frequency WebSocket filter to catch auto-mode:event wrapping
  (auto_mode_progress is wrapped in auto-mode:event) and add feature:progress
- Reorder Vite aliases so explicit jsx-runtime entries aren't shadowed by
  the broad /^react(\/|$)/ regex (Vite uses first-match-wins)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

♻️ Duplicate comments (1)
apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts (1)

206-211: ⚠️ Potential issue | 🟠 Major

Reset the pending RAF buffer on worktree/session context change, not only unmount.

At Line 206, cleanup only runs on unmount. If worktreePath changes while pendingOutputRef (Line 198) still has content or a RAF is queued, stale output can flush into the new context.

💡 Proposed fix
+  // Reset buffered output whenever the monitored context changes
+  useEffect(() => {
+    resetPendingOutput();
+  }, [worktreePath, resetPendingOutput]);
+
   // Clean up pending RAF on unmount to prevent state updates after unmount
   useEffect(() => {
     return () => {
       resetPendingOutput();
     };
   }, [resetPendingOutput]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts`
around lines 206 - 211, The cleanup currently only runs on unmount so
pendingOutputRef and any queued RAF can flush into a new context when the
worktree/session changes; update the hook so resetPendingOutput() runs whenever
the worktree/session context changes (e.g. include worktreePath and/or session
identifiers in the useEffect dependency array or add a separate effect that
calls resetPendingOutput on change) so any pending RAF buffer is cleared before
switching to the new worktree; reference resetPendingOutput, pendingOutputRef,
and the worktreePath/session context in your change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts`:
- Around line 196-201: The appendLogs path can let pendingOutputRef grow
unbounded when requestAnimationFrame callbacks are throttled; modify appendLogs
and the RAF scheduling so it also sets a fallback timer (e.g., setTimeout(...,
250)) when scheduling flushPendingOutput and stores its id (e.g., timerIdRef),
clear the timer when flushPendingOutput runs (and clear rafIdRef as already
done), and in appendLogs check pendingOutputRef.current.length (or byte/char
count) against MAX_LOG_BUFFER_SIZE and call flushPendingOutput immediately if it
reaches the limit; ensure both rafIdRef and timerIdRef are cleared/managed in
flushPendingOutput and when cancelling/rescheduling to avoid duplicate flushes.

---

Duplicate comments:
In
`@apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts`:
- Around line 206-211: The cleanup currently only runs on unmount so
pendingOutputRef and any queued RAF can flush into a new context when the
worktree/session changes; update the hook so resetPendingOutput() runs whenever
the worktree/session context changes (e.g. include worktreePath and/or session
identifiers in the useEffect dependency array or add a separate effect that
calls resetPendingOutput on change) so any pending RAF buffer is cleared before
switching to the new worktree; reference resetPendingOutput, pendingOutputRef,
and the worktreePath/session context in your change.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc6c69f and 736e12d.

📒 Files selected for processing (3)
  • apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts
  • apps/ui/src/lib/http-api-client.ts
  • apps/ui/vite.config.mts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/ui/src/lib/http-api-client.ts
  • apps/ui/vite.config.mts

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts (1)

236-241: ⚠️ Potential issue | 🟠 Major

Reset pending output on worktree context changes, not only unmount/restart.

pendingOutputRef can survive a switch from one non-null worktreePath to another and flush old output into the new session. This is because cleanup at Line 236 currently runs only on unmount, while Line 243-251 does not reset pending buffers before loading the next worktree.

Proposed fix
@@
-  useEffect(() => {
-    if (worktreePath && autoSubscribe) {
+  useEffect(() => {
+    // Prevent buffered output from a previous worktree/session
+    // from flushing into the newly selected context.
+    resetPendingOutput();
+    if (worktreePath && autoSubscribe) {
       hasFetchedInitialLogs.current = false;
       fetchLogs();
     } else {
       clearLogs();
     }
-  }, [worktreePath, autoSubscribe, fetchLogs, clearLogs]);
+  }, [worktreePath, autoSubscribe, fetchLogs, clearLogs, resetPendingOutput]);

Also applies to: 243-251

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts`
around lines 236 - 241, pendingOutputRef can leak output across sessions because
resetPendingOutput is only called in the unmount cleanup of the useEffect;
update the logic so pending buffers are cleared whenever the active worktree
changes, not just on unmount. Specifically, ensure resetPendingOutput is invoked
before switching/initializing a new worktree (e.g., call resetPendingOutput
right before invoking loadWorktree or add a useEffect that depends on
worktreePath and calls resetPendingOutput), referencing pendingOutputRef,
resetPendingOutput, loadWorktree and the existing useEffect cleanup to prevent
old output from flushing into a new session.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts`:
- Around line 236-241: pendingOutputRef can leak output across sessions because
resetPendingOutput is only called in the unmount cleanup of the useEffect;
update the logic so pending buffers are cleared whenever the active worktree
changes, not just on unmount. Specifically, ensure resetPendingOutput is invoked
before switching/initializing a new worktree (e.g., call resetPendingOutput
right before invoking loadWorktree or add a useEffect that depends on
worktreePath and calls resetPendingOutput), referencing pendingOutputRef,
resetPendingOutput, loadWorktree and the existing useEffect cleanup to prevent
old output from flushing into a new session.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 736e12d and 0a6e7a6.

📒 Files selected for processing (1)
  • apps/ui/src/components/views/board-view/worktree-panel/hooks/use-dev-server-logs.ts

@gsxdsm gsxdsm merged commit ae48065 into AutoMaker-Org:v1.0.0rc Mar 3, 2026
7 checks passed
gsxdsm added a commit to gsxdsm/automaker that referenced this pull request Mar 4, 2026
…er-Org#828)

* Changes from fix/dev-server-hang

* fix: Address PR AutoMaker-Org#828 review feedback

- Reset RAF buffer on context changes (worktree switch, dev-server restart)
  to prevent stale output from flushing into new sessions
- Fix high-frequency WebSocket filter to catch auto-mode:event wrapping
  (auto_mode_progress is wrapped in auto-mode:event) and add feature:progress
- Reorder Vite aliases so explicit jsx-runtime entries aren't shadowed by
  the broad /^react(\/|$)/ regex (Vite uses first-match-wins)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: Batch dev server logs and fix React module resolution order

* feat: Add fallback timer for flushing dev server logs in background tabs

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant