Skip to content

Fix TUI transition smoke regressions#359

Merged
TraderSamwise merged 3 commits into
masterfrom
chore/core-sidecar-next-84
Jul 8, 2026
Merged

Fix TUI transition smoke regressions#359
TraderSamwise merged 3 commits into
masterfrom
chore/core-sidecar-next-84

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • reconcile stale dashboard pending actions from raw API snapshots
  • demote orphaned starting sessions and avoid false restore failure modals
  • route local expose through the project sidecar socket with sanitized runtime errors

Verification

  • yarn vitest run src/dashboard/pending-actions.test.ts src/multiplexer/dashboard-model.test.ts src/multiplexer/persistence-methods.test.ts src/multiplexer/dashboard-ops.test.ts src/multiplexer/runtime-state.test.ts src/tmux/control-script.test.ts src/tmux/expose-model.test.ts src/tmux/expose-layout.test.ts src/tmux/expose-tile.test.ts src/popup-expose.test.ts src/error-display.test.ts src/managed-launch-env.test.ts src/tmux/runtime-manager.test.ts
  • yarn typecheck
  • yarn lint
  • yarn build
  • local release install + tealstreet-next smoke test

Summary by CodeRabbit

  • New Features

    • Added improved dashboard handling for pending session and service actions, including clearer state updates during refreshes.
    • Enhanced expose/popup workflows to use a local socket-based connection and better terminal behavior.
  • Bug Fixes

    • Better clears stale “pending” session/service states once the underlying service or session settles.
    • Improved session restore behavior so offline restarts recover more reliably and show clearer status messages.
    • User-facing errors are now shorter and more carefully redacted, reducing exposure of sensitive details.
  • Security

    • Tightened environment handling to preserve only allowed values during managed launches.

@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app Ready Ready Preview, Comment Jul 8, 2026 3:02pm

@TraderSamwise

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 35 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: bbc675ed-85f0-420a-bb7b-3c0995089755

📥 Commits

Reviewing files that changed from the base of the PR and between 660a089 and d0908ac.

📒 Files selected for processing (5)
  • scripts/tmux-control.sh
  • src/metadata-server.ts
  • src/multiplexer/dashboard-model.test.ts
  • src/multiplexer/dashboard-model.ts
  • src/tmux/control-script.test.ts
📝 Walkthrough

Walkthrough

This PR replaces the tmux exposé CLI invocation with a UNIX-socket daemon protocol (script, metadata-server, expose runtime), adds dashboard pending-action reconciliation against raw session/service state including resume-settle inactive handling, introduces sanitized user-facing error formatting used in several modules, and switches managed launch environment filtering to an allowlist.

Changes

Expose UNIX-socket daemon protocol

Layer / File(s) Summary
Local popup control
scripts/tmux-control.sh
show_local_expose resolves the expose daemon socket, builds a context payload, and streams it via nc -U inside a display-popup, with retry on status 75, replacing the old aimux expose CLI invocation.
Expose socket server
src/metadata-server.ts
Adds a net server bound to a socket path, header parsing/validation, piping to runTmuxExpose, and startup/shutdown lifecycle management.
Exposé TUI runtime and terminal control
src/tmux/expose.ts
Adds daemonEndpoint, configurable I/O streams, manageTerminal toggle, a reload/loading flow, and terminalSize()-based rendering/resize handling.
Fake tmux/test coverage
src/tmux/control-script.test.ts
Updates the fake tmux script and tests to verify socket-based popup interaction and failure reporting.

Dashboard pending-action reconciliation and resume settlement

Layer / File(s) Summary
Pending-action listing
src/dashboard/pending-actions.ts
Adds PendingSessionActionEntry/PendingServiceActionEntry and listSessionActions/listServiceActions methods.
Model reconciliation
src/multiplexer/dashboard-model.ts, src/multiplexer/dashboard-model.test.ts
Adds reconcileDashboardPendingActionsFromRawModel, invoked from applyDashboardModel, clearing settled pending actions.
Persistence wiring
src/multiplexer/persistence-methods.ts
Calls the reconciler inside reapplyDashboardPendingActions before cache rebuilds.
Resume-settle inactive handling
src/multiplexer/dashboard-ops.ts, src/multiplexer/dashboard-ops.test.ts
Adds allowInactiveSettle/isDashboardSessionRestoreInactive, tracks resumeRequestSettled, and sets flash messages based on restore outcome.
Orphaned starting sessions
src/multiplexer/runtime-state.ts, src/multiplexer/runtime-state.test.ts
Reconciles stale starting topology sessions to offline with a grace window and restoreBlockedReason.

Sanitized user-facing error formatting

Layer / File(s) Summary
Export helper
src/debug.ts
sanitizeLogString is now exported.
Error-display module
src/error-display.ts, src/error-display.test.ts
Adds userFacingErrorLines/userFacingErrorMessage for sanitized, truncated error text.
Usage in metadata-server and dashboard-ops
src/metadata-server.ts, src/multiplexer/dashboard-ops.ts
Replaces raw error message derivation with the new helpers across several failure paths.
runtime-manager window creation
src/tmux/runtime-manager.ts, src/tmux/runtime-manager.test.ts
Wraps createWindow's tmux call in try/catch, logging and rethrowing a generic error instead of leaking raw argv.

Managed launch environment allowlist

Layer / File(s) Summary
Allowlist-based filtering
src/managed-launch-env.ts, src/managed-launch-env.test.ts
Replaces EXCLUDED_ENV_KEYS with ALLOWED_ENV_KEYS; shouldExcludeEnvKey allows LC_-prefixed and allowlisted keys only, with updated test expectations.

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

Sequence Diagram(s)

sequenceDiagram
  participant TmuxControlScript
  participant ExposeSocket as "Expose Unix Socket"
  participant MetadataServer
  participant RunTmuxExpose

  TmuxControlScript->>ExposeSocket: nc -U context payload (project/session/pane/size)
  ExposeSocket->>MetadataServer: handleExposeSocket(header, stream)
  MetadataServer->>MetadataServer: parse/validate launch header
  MetadataServer->>RunTmuxExpose: runTmuxExpose(header params, input/output)
  RunTmuxExpose-->>MetadataServer: exit code
  MetadataServer-->>ExposeSocket: write code, end socket
  ExposeSocket-->>TmuxControlScript: popup status (retry on 75)
Loading
sequenceDiagram
  participant DashboardOps
  participant ResumeAPI
  participant DashboardModel
  participant RuntimeState

  DashboardOps->>ResumeAPI: resume offline session
  ResumeAPI-->>DashboardOps: resumeRequestSettled=true (finally)
  DashboardOps->>DashboardModel: waitForDashboardSessionResumeSettle(allowInactiveSettle)
  DashboardModel->>RuntimeState: reconcileDashboardPendingActionsFromRawModel(raw sessions/services)
  RuntimeState-->>DashboardModel: pending action cleared if settled
  DashboardModel-->>DashboardOps: restored or stayed-offline result
  DashboardOps->>DashboardOps: applyRestoreSettlementFlash(footerFlash)
Loading

Possibly related PRs

  • TraderSamwise/aimux#169: Both PRs modify scripts/tmux-control.sh's show_local_expose code path for opening the exposé popup.
  • TraderSamwise/aimux#214: Both PRs change scripts/tmux-control.sh's show_local_expose retry/relaunch behavior around the popup resize sentinel.
  • TraderSamwise/aimux#342: Both PRs directly modify dashboard pending-action reconciliation and resume/activation control flow in dashboard-ops.ts.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and clearly describes the PR’s main goal of fixing TUI transition smoke regressions.
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 chore/core-sidecar-next-84

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

@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: 4

🧹 Nitpick comments (3)
src/multiplexer/runtime-state.test.ts (1)

2059-2090: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Missing coverage for the fresh-starting-without-pending-flag case.

This test only covers a stale "starting" session with a matching "starting" pending flag. Add a companion test for a fresh "starting" session with no "starting" pending action set (or a different pending kind, e.g. "creating") to confirm it is not demoted within the grace window — this would catch the condition issue raised on src/multiplexer/runtime-state.ts (lines 288-293).

🤖 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 `@src/multiplexer/runtime-state.test.ts` around lines 2059 - 2090, Add a
companion test around reconcileOrphanedTopologySessions and
listTopologySessionStates for a fresh "starting" session that has no matching
"starting" DashboardPendingActions entry (or only a different pending kind like
"creating"); assert it stays in "starting" during the grace window and is not
demoted to "offline". Reuse the existing helpers upsertTopologySession,
noWindowsHost, and DashboardPendingActions so the new case specifically
exercises the pending-action check in runtime-state handling.
src/dashboard/pending-actions.ts (1)

164-185: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Correct implementation; minor duplication.

Both methods share identical shape (filter by target, slice key prefix, map fields). Could be consolidated into a private generic helper, e.g. private listActionsByTarget<T>(target, prefix): T[], to avoid maintaining two near-identical blocks.

🤖 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 `@src/dashboard/pending-actions.ts` around lines 164 - 185, The
`listSessionActions` and `listServiceActions` methods in `PendingActions` are
duplicated with only the target/prefix/type differing. Refactor them to use a
single private helper such as `listActionsByTarget` that filters by
`entry.target`, slices the appropriate key prefix, and maps the shared fields,
while keeping the existing public method names and return types intact.
src/multiplexer/dashboard-model.ts (1)

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

Grace-period constant duplicated across files without a shared source of truth.

PENDING_START_OFFLINE_SETTLE_MS (5000ms here) conceptually overlaps with STARTING_ORPHAN_RECONCILE_GRACE_MS in src/multiplexer/runtime-state.ts and the inline >= 5_000 threshold used in allowInactiveSettle in src/multiplexer/dashboard-ops.ts. All three independently encode "how long to wait before treating a starting session as settled/orphaned." Consider extracting a single shared constant to avoid future drift between these coordinated timing windows.

🤖 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 `@src/multiplexer/dashboard-model.ts` at line 58, The grace-period timing is
duplicated in dashboard-model, runtime-state, and dashboard-ops, so extract a
single shared constant for the “starting session settle/orphan” window and use
it everywhere. Update PENDING_START_OFFLINE_SETTLE_MS,
STARTING_ORPHAN_RECONCILE_GRACE_MS, and the allowInactiveSettle threshold to
reference the same source of truth so the coordinated timing stays aligned. Keep
the new constant in a shared module that both dashboard-model and runtime-state
can import without introducing local magic numbers.
🤖 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 `@scripts/tmux-control.sh`:
- Around line 528-530: Empty expose.sock.path can overwrite expose_socket with
an empty string and suppress the popup. In scripts/tmux-control.sh, update the
expose socket loading logic near the show_local_expose flow so head -n 1 from
expose_socket_file only replaces expose_socket when it returns a non-empty
value, otherwise keep the existing default socket path. Use the
expose_socket_file and expose_socket variables to locate the guard, and ensure
the later [ -e "$expose_socket" ] check still sees the default when the config
file is empty.

In `@src/metadata-server.ts`:
- Line 1342: The auxiliary expose socket startup in startExposeSocket is
currently awaited directly from start(), so any bind/listen failure can abort
the whole metadata server even though it is a secondary feature. Update the
start flow around startExposeSocket and the exposeServer error handling to
mirror the graceful fallback used by the main HTTP listen path: catch and log
expose-socket startup errors, allow start() to continue, and only fail the
server when the primary listener cannot start.
- Around line 1392-1396: The expose socket path is missing a local error
handler, so disconnects during handleExposeSocket can bubble to the
process-level uncaughtException flow and kill the daemon. Update the
createNetServer callback in exposeServer to register a socket.on("error", ...)
listener before invoking runInProjectContext/handleExposeSocket, and make it
safely destroy the socket there while keeping the existing catch-based cleanup
intact.

In `@src/multiplexer/dashboard-model.ts`:
- Around line 125-136: Add a time-based settle fallback to
servicePendingSettled, mirroring sessionPendingSettled, so "creating"/"starting"
service actions can clear even when the service never reaches "running". Update
servicePendingSettled to use the action.startedAt timestamp and a pending-start
timeout constant (similar to PENDING_START_OFFLINE_SETTLE_MS), and keep the
existing status-based checks for normal cases. Make sure the new logic is
applied in the dashboard-model service reconciliation path so persisted/reloaded
snapshots from persistence-methods.ts can also settle stuck pending service
actions.

---

Nitpick comments:
In `@src/dashboard/pending-actions.ts`:
- Around line 164-185: The `listSessionActions` and `listServiceActions` methods
in `PendingActions` are duplicated with only the target/prefix/type differing.
Refactor them to use a single private helper such as `listActionsByTarget` that
filters by `entry.target`, slices the appropriate key prefix, and maps the
shared fields, while keeping the existing public method names and return types
intact.

In `@src/multiplexer/dashboard-model.ts`:
- Line 58: The grace-period timing is duplicated in dashboard-model,
runtime-state, and dashboard-ops, so extract a single shared constant for the
“starting session settle/orphan” window and use it everywhere. Update
PENDING_START_OFFLINE_SETTLE_MS, STARTING_ORPHAN_RECONCILE_GRACE_MS, and the
allowInactiveSettle threshold to reference the same source of truth so the
coordinated timing stays aligned. Keep the new constant in a shared module that
both dashboard-model and runtime-state can import without introducing local
magic numbers.

In `@src/multiplexer/runtime-state.test.ts`:
- Around line 2059-2090: Add a companion test around
reconcileOrphanedTopologySessions and listTopologySessionStates for a fresh
"starting" session that has no matching "starting" DashboardPendingActions entry
(or only a different pending kind like "creating"); assert it stays in
"starting" during the grace window and is not demoted to "offline". Reuse the
existing helpers upsertTopologySession, noWindowsHost, and
DashboardPendingActions so the new case specifically exercises the
pending-action check in runtime-state handling.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: e325b495-844d-4bb9-8868-e990ca1f447a

📥 Commits

Reviewing files that changed from the base of the PR and between 4d2fcfd and 660a089.

📒 Files selected for processing (19)
  • scripts/tmux-control.sh
  • src/dashboard/pending-actions.ts
  • src/debug.ts
  • src/error-display.test.ts
  • src/error-display.ts
  • src/managed-launch-env.test.ts
  • src/managed-launch-env.ts
  • src/metadata-server.ts
  • src/multiplexer/dashboard-model.test.ts
  • src/multiplexer/dashboard-model.ts
  • src/multiplexer/dashboard-ops.test.ts
  • src/multiplexer/dashboard-ops.ts
  • src/multiplexer/persistence-methods.ts
  • src/multiplexer/runtime-state.test.ts
  • src/multiplexer/runtime-state.ts
  • src/tmux/control-script.test.ts
  • src/tmux/expose.ts
  • src/tmux/runtime-manager.test.ts
  • src/tmux/runtime-manager.ts

Comment thread scripts/tmux-control.sh
Comment thread src/metadata-server.ts Outdated
Comment thread src/metadata-server.ts
Comment thread src/multiplexer/dashboard-model.ts
@TraderSamwise
TraderSamwise merged commit a23d6d0 into master Jul 8, 2026
3 checks passed
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