Skip to content

feat: redesign the web ui and fix preview/run/stop#2

Open
efenocchi wants to merge 22 commits into
mainfrom
feat/frontend-redesign
Open

feat: redesign the web ui and fix preview/run/stop#2
efenocchi wants to merge 22 commits into
mainfrom
feat/frontend-redesign

Conversation

@efenocchi

@efenocchi efenocchi commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Redesigns the OpenREPL web UI into a modern AI-IDE look (Replit-inspired) and fixes several functional issues surfaced while testing the preview/run/stop flow end-to-end.

UI redesign

  • New elevation-layered dark theme, Replit coral accent (#ff3c00), Inter font, larger display type, rounded panels.
  • SVG icon set (lucide-style, no emojis); icons on tabs, sidebar and buttons.
  • Chat: role avatars, empty-state suggestion chips, rounded composer with a circular send button.
  • Projects sidebar with folder icons and an accent bar on the active project.

Functional fixes (found via real testing)

  • Preview proxy ownership follows the running app, not the newest socket (pickPreview), so a second tab/reconnect can't steal it.
  • Conversation history is replayed in the chat on project open (was persisted and fed to the LLM but never shown).
  • Usage is pushed on project open, so it isn't empty until a full refresh.
  • Workflow selection resets when switching projects (fixes "No runnable app found" on a valid project).
  • Stop now stops the app however it started — including shell/agent-started servers — and the app lifecycle is owned at the server level (AppHub), so any tab sees the same status/Stop button and Stop always reaches the process.
  • Preview "inception" fixed: the proxy rewrites root-absolute URLs (and redirects) to stay under /__preview, so a server-rendered app's links/forms/assets don't escape to OpenREPL's SPA fallback.
  • Reloader gap: the proxy retries the upstream for idempotent requests, so a dev server's boot-time restart no longer shows "Preview target unreachable".

Testing

  • 136 server tests pass, typecheck clean. New tests: app-hub.test.ts, pickPreview + rewritePreviewHtml in preview.test.ts, stopRuns in runner.test.ts.
  • Verified end-to-end with a real browser (Agent Browser): redesign renders, Run shows the styled app in the preview (no inception), Stop frees the port from any tab.

Session Context

Session transcript

Summary by CodeRabbit

  • New Features
    • Shared workspace app/preview lifecycle persists across tabs and reconnects; apps stop automatically when the last tab closes.
    • Added chat history sync and improved empty-state starter suggestions with a redesigned composer.
  • Bug Fixes
    • Preview proxying is more reliable: keeps redirects/HTML asset links inside the preview frame, selects the correct running preview across sessions, and retries idempotent requests.
    • Stopping apps/commands now cleans up more reliably and terminates long-running processes promptly.
  • UI Improvements
    • Refreshed dark theme and updated header/projects/preview/chat visuals with consistent iconography.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@efenocchi, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 39 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ff96e41e-d8af-46b9-bc9d-6ee4faa87a52

📥 Commits

Reviewing files that changed from the base of the PR and between 6433300 and 4de79de.

📒 Files selected for processing (1)
  • packages/server/src/app-hub.ts
📝 Walkthrough

Walkthrough

Introduces shared workspace app state on the server, updates preview routing and proxying, adds history event plumbing, and refreshes the web UI icons, chat, projects, and styling.

Changes

Server: AppHub, Session, Preview, Runner

Layer / File(s) Summary
AppHub state model and lifecycle
packages/server/src/app-hub.ts
Adds per-workspace app state, subscriptions, preview-port tracking, session attachment tracking, and serialized run/stop handling.
AppHub test coverage
packages/server/test/app-hub.test.ts
Adds tests for shared running/stopped status, preview cleanup, error states, preview_ready emission, multi-workspace selection, and detach-driven stop behavior.
Session delegates to AppHub
packages/server/src/session.ts
Moves preview and workflow control onto the hub, replays history and hub state on open, and unsubscribes from hub forwarding on close.
Multi-session preview routing
packages/server/src/index.ts
Adds shared hub/session tracking and routes /__preview through the running app preview with a session fallback.
Preview proxy retries and HTML rewriting
packages/server/src/preview.ts, packages/server/test/preview.test.ts
Adds retrying proxy attempts, HTML/redirect rewriting, preview source selection helpers, and tests for those behaviors.
CommandRunner process group kill and stopRuns
packages/server/src/runner.ts, packages/server/test/runner.test.ts
Tracks active one-shot processes, adds process-group stop handling, and tests stopRuns().
History UiEvent protocol addition
packages/shared/src/protocol.ts
Adds a history UI event carrying message history.

Web UI: icons, chat, theme, store

Layer / File(s) Summary
Icon set and App header/tabs
packages/web/src/icons.tsx, packages/web/src/App.tsx
Adds reusable SVG icons and updates the app header and tabs to render them.
Chat empty-state and composer redesign
packages/web/src/panes/Chat.tsx, packages/web/src/store.ts
Adds chat suggestions, a send-button composer, revised message labels, and history-event message loading.
Projects sidebar and preview workflow selection
packages/web/src/panes/Projects.tsx, packages/web/src/panes/Preview.tsx, packages/web/src/panes/FilesEditor.tsx
Replaces inline glyphs with icons, keeps preview workflow selection valid, and adjusts tree disclosure markup.
Dark theme overhaul and font loading
packages/web/index.html, packages/web/src/styles.css
Adds font loading and restyles the app theme, layout, panes, controls, and utility sections.

CI Coverage Formatting

Layer / File(s) Summary
Coverage summary emoji formatting
.github/workflows/ci.yaml
Formats each coverage category with an emoji derived from its percentage before the percentage and counts.

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main UI redesign and preview/run/stop fixes in the change set.
Description check ✅ Passed The description covers the required summary and testing details, though it does not follow the template's checkbox format exactly.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/frontend-redesign

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.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 84.61% (🎯 90%) 1584 / 1872
🔵 Statements 84.61% (🎯 90%) 1584 / 1872
🔵 Functions 92.96% (🎯 90%) 185 / 199
🔵 Branches 80.83% (🎯 80%) 506 / 626
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/server/src/app-hub.ts 83.82% 87.5% 100% 83.82% 119-121, 129-137, 151-157, 166-168
packages/server/src/index.ts 95.14% 85.29% 100% 95.14% 85-87, 115-116
packages/server/src/preview.ts 85.55% 66.66% 100% 85.55% 34-37, 61-62, 86-91, 96
packages/server/src/runner.ts 89.01% 77.77% 100% 89.01% 40, 82-83, 103, 112, 114-119
packages/server/src/session.ts 58.52% 76.92% 84.21% 58.52% 55-56, 70, 90, 95, 97, 108, 128, 146, 148, 266-381, 384-399
packages/shared/src/protocol.ts 0% 100% 100% 0% 48
Generated in workflow #20 for commit 4de79de by the Vitest Coverage Report Action

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (3)
packages/web/src/styles.css (1)

62-75: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor token inconsistency: a few hardcoded hex colors bypass the new CSS variable system.

Scrollbar thumb colors, .terminal background, and .preview-bar button.stop:hover use raw hex values instead of the new --bg-*/--bad tokens, unlike the rest of the theme.

♻️ Example alignment with tokens
 ::-webkit-scrollbar-thumb {
-  background: `#2c2c31`;
+  background: var(--bg-3);
   border: 2px solid transparent;
   background-clip: padding-box;
   border-radius: 8px;
 }
 ::-webkit-scrollbar-thumb:hover {
-  background: `#3a3a41`;
+  background: var(--border-strong);
   background-clip: padding-box;
 }
...
 .terminal {
   display: flex;
   flex-direction: column;
   height: 100%;
-  background: `#0d1117`;
+  background: var(--bg-0);
 }
...
 .preview-bar button.stop:hover {
-  background: `#ff7373`;
+  background: var(--bad);
 }

Also applies to: 665-670, 722-724

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/styles.css` around lines 62 - 75, The theme styling in
styles.css still uses hardcoded hex colors in the scrollbar thumb rules and
related UI states, which bypasses the new CSS token system. Update the scrollbar
thumb/hover styles, the .terminal background, and the .preview-bar
button.stop:hover state to use the existing --bg-* and --bad variables instead
of raw hex values, keeping the token usage consistent with the rest of the
stylesheet.
packages/server/src/session.ts (1)

210-220: 🩺 Stability & Availability | 🔵 Trivial

Orphaned dev servers when all sessions disconnect.

unmount() intentionally leaves the workspace app running in the hub so a reconnecting tab still sees it. However, nothing stops the hub's app once every session for that workspace is gone. On a long-lived server, repeatedly opening/running different projects (or closing all tabs) can accumulate orphaned dev-server processes holding ports. Consider a hub-level cleanup for workspaces with no attached sessions after an idle window, or stopping the app when the last session for a dir closes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/server/src/session.ts` around lines 210 - 220, The unmount flow in
session.ts only closes the tab mount and workspace handle, but it never stops
the hub-level app when the last session for a workspace disappears, which can
leave orphaned dev servers running. Update Session.unmount() and related
session/workspace tracking so that when the final session for a given
dir/workspace closes, the hub app is cleaned up after an idle window or stopped
immediately if no sessions remain. Use the existing activeRun, mount, and
workspace/session lifecycle logic to locate the cleanup point and ensure the
workspace-level process is terminated only when it is no longer attached to any
session.
packages/server/test/app-hub.test.ts (1)

1-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assertions are appropriately specific; consider extending coverage for stop/restart edge cases.

Test assertions correctly target specific values (toBe('running'), toBe(5173), toBe(true)) rather than generic substrings, consistent with path instructions for *.test.ts files. As a follow-up, consider adding coverage for the scenarios flagged in app-hub.ts: (a) runningPreview() when one workspace is stopped and a second, different workspace is running, and (b) restarting the same app on the same port to confirm preview_ready still re-broadcasts.

As per path instructions, packages/**/*.test.ts: "Prefer asserting on specific values (paths, tool names, model tiers) over generic substrings."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/server/test/app-hub.test.ts` around lines 1 - 59, Extend the AppHub
test coverage to include the edge cases called out in app-hub.ts: add a case
that verifies runningPreview() returns the active preview for a different
workspace after one workspace has been stopped, and another case that exercises
restarting the same app on the same port to confirm notePort() still emits a
preview_ready event again. Use the existing AppHub, stop, run, preview, and
notePort helpers so the new assertions stay specific and aligned with the
current test style.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/server/src/app-hub.ts`:
- Around line 92-114: Wrap both `CommandRunner.run()` in the install branch and
`WorkflowManager.start()` in `app-hub.ts` with error handling so rejected
promises do not leave the app stuck in `installing` or `starting`. In the
`app.installer` flow and the `app.mgr` flow, catch thrown errors, clear the
active runner/manager state, and call `setStatus` with `type: 'app_status'`,
`state: 'error'`, and a message that includes the failure context. Use the
existing `app.installer`, `app.mgr`, `setStatus`, and `broadcast` paths to keep
the state consistent and allow retry after failure.
- Around line 78-116: Serialize the AppHub run/stop lifecycle per directory so
overlapping calls cannot interleave the await this.stop(dir) → detectWorkflows()
→ app.mgr.start(wf) sequence. Add a per-dir lock or queue inside AppHub.run and
make stop(dir) participate in the same guard, using the existing appFor,
app.mgr, and app.activeWorkflow flow to ensure one workflow launch/teardown
completes before the next begins and status stays consistent.
- Around line 103-113: The workflow exit handling in app-hub currently marks the
whole app as stopped on every child process exit, which causes premature
teardown while sibling steps are still running. Update the
WorkflowManager.start() wiring in app.mgr initialization to track active child
processes per workflow, and only clear app.mgr and app.activeWorkflow after the
final child exits. Use the existing callbacks and symbols in AppHub,
WorkflowManager.start, notePort, and setStatus to keep status updates accurate
for each step without resetting the workflow too early.
- Around line 58-70: Update the preview lifecycle in app-hub so a stopped
workspace does not keep advertising a live preview. The issue is that stop() is
leaving PreviewManager’s port set, which lets runningPreview() keep returning a
dead app and can prevent a fresh preview refresh on restart. Fix this by
clearing the stored port when stopping a preview, or by making runningPreview()
skip apps whose mgr is null, using the existing runningPreview(), notePort(),
and PreviewManager state to keep /__preview in sync.

In `@packages/server/src/preview.ts`:
- Around line 45-71: The HTML rewrite path in preview handling can corrupt
compressed responses because `proxyReq` forwards `accept-encoding` and
`proxyRes` is later decoded with `toString('utf8')` in the `rewritePreviewHtml`
flow. Update the proxy request in `packages/server/src/preview.ts` so HTML is
either requested uncompressed by forcing `accept-encoding: identity` or
explicitly decompressed before rewriting, then continue stripping
`content-encoding` and adjusting `content-length` before sending the response.

---

Nitpick comments:
In `@packages/server/src/session.ts`:
- Around line 210-220: The unmount flow in session.ts only closes the tab mount
and workspace handle, but it never stops the hub-level app when the last session
for a workspace disappears, which can leave orphaned dev servers running. Update
Session.unmount() and related session/workspace tracking so that when the final
session for a given dir/workspace closes, the hub app is cleaned up after an
idle window or stopped immediately if no sessions remain. Use the existing
activeRun, mount, and workspace/session lifecycle logic to locate the cleanup
point and ensure the workspace-level process is terminated only when it is no
longer attached to any session.

In `@packages/server/test/app-hub.test.ts`:
- Around line 1-59: Extend the AppHub test coverage to include the edge cases
called out in app-hub.ts: add a case that verifies runningPreview() returns the
active preview for a different workspace after one workspace has been stopped,
and another case that exercises restarting the same app on the same port to
confirm notePort() still emits a preview_ready event again. Use the existing
AppHub, stop, run, preview, and notePort helpers so the new assertions stay
specific and aligned with the current test style.

In `@packages/web/src/styles.css`:
- Around line 62-75: The theme styling in styles.css still uses hardcoded hex
colors in the scrollbar thumb rules and related UI states, which bypasses the
new CSS token system. Update the scrollbar thumb/hover styles, the .terminal
background, and the .preview-bar button.stop:hover state to use the existing
--bg-* and --bad variables instead of raw hex values, keeping the token usage
consistent with the rest of the stylesheet.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bb8a08de-3dad-4caf-907f-8fc1eed1d613

📥 Commits

Reviewing files that changed from the base of the PR and between 9b156d8 and 434208f.

📒 Files selected for processing (18)
  • packages/server/src/app-hub.ts
  • packages/server/src/index.ts
  • packages/server/src/preview.ts
  • packages/server/src/runner.ts
  • packages/server/src/session.ts
  • packages/server/test/app-hub.test.ts
  • packages/server/test/preview.test.ts
  • packages/server/test/runner.test.ts
  • packages/shared/src/protocol.ts
  • packages/web/index.html
  • packages/web/src/App.tsx
  • packages/web/src/icons.tsx
  • packages/web/src/panes/Chat.tsx
  • packages/web/src/panes/FilesEditor.tsx
  • packages/web/src/panes/Preview.tsx
  • packages/web/src/panes/Projects.tsx
  • packages/web/src/store.ts
  • packages/web/src/styles.css

Comment thread packages/server/src/app-hub.ts
Comment thread packages/server/src/app-hub.ts Outdated
Comment thread packages/server/src/app-hub.ts Outdated
Comment thread packages/server/src/app-hub.ts Outdated
Comment thread packages/server/src/preview.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/server/src/app-hub.ts (2)

177-192: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

stopLocked leaves state inconsistent if mgr.stop() rejects.

There's no try/catch around await app.mgr.stop(). If it throws, app.mgr stays set, activeWorkflow and the preview port are never cleared, and setStatus never fires — so the UI shows a running app pointing at a dead server. Since detach calls void this.stop(dir), the rejection also becomes unhandled and can crash the process.

🔧 Proposed fix
   private async stopLocked(dir: string): Promise<void> {
     const app = this.apps.get(dir);
     if (app) {
       app.installer?.stopRuns();
       app.installer = null;
       if (app.mgr) {
-        await app.mgr.stop();
+        try { await app.mgr.stop(); }
+        catch { /* best-effort — still clean up state below */ }
         app.mgr = null;
       }
       app.activeWorkflow = null;
       app.preview.clearPort();
     }
     this.setStatus(dir, { type: 'app_status', state: 'stopped' });
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/server/src/app-hub.ts` around lines 177 - 192, The stopLocked flow
can leave AppHub state half-updated if app.mgr.stop() rejects, so update
stopLocked to handle failures from app.mgr.stop() while still cleaning up
app.installer, app.mgr, activeWorkflow, and app.preview consistently. Wrap the
stop sequence in a try/finally (or equivalent) so cleanup and setStatus in
AppHub always run even when mgr.stop() fails, and make sure the rejection is
observed/logged so detach calling stop(dir) does not produce an unhandled
rejection.

162-168: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Tear down the app before clearing references

WorkflowManager.start() can leave already-spawned detached children behind if a later step throws. Run the existing cleanup before nulling app.mgr/app.installer, so the failure path doesn’t orphan processes or keep ports busy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/server/src/app-hub.ts` around lines 162 - 168, The failure path in
app-hub’s app startup catch block clears app.installer and app.mgr before
cleanup, which can leave detached children running and ports occupied. In the
catch around WorkflowManager.start(), call the existing teardown/cleanup logic
first on the current app state, then null out app.mgr and app.installer, and
finally set the error status so the process tree is reliably stopped before
references are dropped.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/server/src/app-hub.ts`:
- Around line 177-192: The stopLocked flow can leave AppHub state half-updated
if app.mgr.stop() rejects, so update stopLocked to handle failures from
app.mgr.stop() while still cleaning up app.installer, app.mgr, activeWorkflow,
and app.preview consistently. Wrap the stop sequence in a try/finally (or
equivalent) so cleanup and setStatus in AppHub always run even when mgr.stop()
fails, and make sure the rejection is observed/logged so detach calling
stop(dir) does not produce an unhandled rejection.
- Around line 162-168: The failure path in app-hub’s app startup catch block
clears app.installer and app.mgr before cleanup, which can leave detached
children running and ports occupied. In the catch around
WorkflowManager.start(), call the existing teardown/cleanup logic first on the
current app state, then null out app.mgr and app.installer, and finally set the
error status so the process tree is reliably stopped before references are
dropped.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 45d8d88d-4fff-49f7-96b8-be1695ff6219

📥 Commits

Reviewing files that changed from the base of the PR and between a823a9f and 6433300.

📒 Files selected for processing (4)
  • packages/server/src/app-hub.ts
  • packages/server/src/session.ts
  • packages/server/test/app-hub.test.ts
  • packages/web/src/styles.css
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/server/src/session.ts
  • packages/web/src/styles.css

@efenocchi

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

Addressed all 8 comments from the previous review (5 actionable + 3 nitpicks):

  • Clear preview port on stop (fixes intermittent 502) + reset on last step exit
  • Serialize run()/stop() per dir with a mutex
  • try/catch around install/start → broadcast app_status:error
  • Track live steps so only the last exit marks the app stopped
  • Force accept-encoding: identity so gzipped HTML isn't corrupted
  • Stop a workspace app when its last session detaches (no orphaned dev servers)
  • Use theme tokens for scrollbar/terminal/stop-hover colors
  • Added hub edge-case tests (runningPreview with a stopped workspace, restart re-broadcast, detach-stop)

Please confirm the threads are resolved.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

@efenocchi Thanks for the detailed summary of the fixes. I'll re-review the PR now to verify that the preview port clearing, mutex serialization, error broadcasting, live-step tracking, gzip handling, session-detach stop behavior, theme token usage, and new hub edge-case tests all address the previous feedback correctly.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@efenocchi

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

Fixed the two follow-up comments on app-hub.ts:

  • stopLocked/teardown now clears refs before awaiting mgr.stop() and swallows its rejection, so stop() never rejects (safe for detach()'s fire-and-forget) and state is always consistent.
  • The run() catch path now tears the partial app down before clearing refs, so a mid-start failure can't orphan spawned children/ports.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd app-hub.ts
echo "---"
cat -n packages/server/src/app-hub.ts

Length of output: 9876


@efenocchi Verified both fixes in packages/server/src/app-hub.ts:

  1. teardown() (Lines 188-198): refs (app.mgr, app.activeWorkflow) and app.preview.clearPort() are now cleared before await mgr.stop().catch(() => {}), so a rejecting mgr.stop() can no longer leave state inconsistent, and stop()/detach() never reject.
  2. runLocked() catch path (Lines 162-168): now calls await this.teardown(app) before broadcasting the error status, so a mid-start failure tears down any already-spawned children/ports instead of orphaning them.

Also nice touch: the exit callback's if (mgr !== app.mgr) return; guard means a late exit from the torn-down mgr won't clobber state after teardown() has already nulled the ref. Both threads look resolved to me.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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