Skip to content

Fix TUI dashboard readiness races#261

Merged
TraderSamwise merged 8 commits into
masterfrom
chore/tui-smoke-next-5
Jun 28, 2026
Merged

Fix TUI dashboard readiness races#261
TraderSamwise merged 8 commits into
masterfrom
chore/tui-smoke-next-5

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • require dashboard windows to stamp readiness before tmux navigation reuses them
  • keep same-machine dashboard navigation responsive while service repair/reconnect overlays are active
  • debounce transient runtime guard probes and ignore health timeouts that do not indicate service loss
  • stamp runtime contract earlier for new tmux sessions and strip focus-in reports from dashboard input

Verification

  • yarn typecheck
  • yarn lint
  • yarn vitest
  • AIMUX_RELEASE_VERSION=0.1.21-local-smoke76 yarn release:asset
  • scripts/install.sh release/aimux-darwin-arm64.tar.gz
  • manual real tmux smoke: 120 dashboard enter/back rounds

Summary by CodeRabbit

  • New Features

    • Dashboard window reuse now requires a matching “ready” stamp; the metadata open flow polls until ready (otherwise returns HTTP 503).
    • Local navigation during busy/guarded dashboard states is temporarily queued and replayed after the dashboard becomes responsive.
    • Dashboard footer/help key hints updated (including Enter/→ and library access via l).
  • Bug Fixes

    • More reliable dashboard respawn/reload decisions when build/readiness stamps are stale.
    • Improved runtime-guard readiness and focus/key handling during reconnect/busy/overlay transitions.
  • Tests

    • Added/updated readiness-based reuse/reload/503, queued-navigation, and revised dashboard key-binding coverage.

@vercel

vercel Bot commented Jun 28, 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 Jun 28, 2026 10:13am

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4f3cbed-2f39-45e9-815f-50521b8a4720

📥 Commits

Reviewing files that changed from the base of the PR and between 123617d and a853eae.

📒 Files selected for processing (5)
  • src/metadata-server.test.ts
  • src/multiplexer/runtime-guard.ts
  • src/tui/screens/dashboard-renderers.test.ts
  • src/tui/screens/dashboard-renderers.ts
  • src/tui/screens/overlay-renderers.ts
✅ Files skipped from review due to trivial changes (1)
  • src/tui/screens/overlay-renderers.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/tui/screens/dashboard-renderers.ts
  • src/multiplexer/runtime-guard.ts
  • src/metadata-server.test.ts

📝 Walkthrough

Walkthrough

Adds a dashboard ready stamp for reuse and respawn checks, defers selected local navigation during guarded states, updates runtime-guard probing and key handling, and stamps tmux runtime contracts earlier during new session creation.

Changes

Dashboard Readiness Stamp, Navigation Queuing & Runtime-Guard Improvements

Layer / File(s) Summary
Readiness stamp and dashboard open flow
src/runtime-owner.ts, scripts/tmux-control.sh, src/multiplexer/session-launch.ts, src/multiplexer/session-launch.test.ts, src/dashboard/targets.ts, src/dashboard/targets.test.ts, src/tmux/control-script.test.ts
Defines the dashboard ready option, marks the dashboard ready during session launch, waits for the ready stamp in shell validation, and updates dashboard target selection and shell tests to treat the ready stamp as part of reuse and reload decisions.
Metadata-server dashboard readiness polling
src/metadata-server.ts, src/metadata-server.test.ts
controls.openDashboard reads the ready stamp, clears it before respawning, waits for it to match the dashboard build stamp, and returns 503 when readiness does not appear within the polling window; the tests stub and assert the ready option across reopen scenarios.
Runtime-guard path matching and probe classification
src/multiplexer/runtime-guard.ts, src/multiplexer/runtime-guard.test.ts
Adds filesystem-path normalization for runtime rebuild correlation, keeps rebuild decisions driven by tmux session options, and expands probe tests for timeouts, disconnection, and client-session filtering.
Guarded navigation queuing and focus replay
src/multiplexer/dashboard-control.ts, src/multiplexer/dashboard-control.test.ts, src/multiplexer/runtime-guard.test.ts
Adds deferred local-navigation classification and flushing in the dashboard control path, stabilizes repair probe handling, and updates tests for reconnect, busy-overlay, and guarded key handling behavior.
Dashboard navigation and help text
src/multiplexer/dashboard-interaction.ts, src/multiplexer/dashboard-interaction.test.ts, src/tui/screens/dashboard-renderers.ts, src/tui/screens/dashboard-renderers.test.ts, src/tui/screens/overlay-renderers.ts
Removes l from plain dashboard navigation, routes l to the library view, updates dashboard interaction tests for the new key mapping, and adjusts footer and help text to match the revised shortcuts.

Runtime Contract Stamped Before Session Configuration

Layer / File(s) Summary
Early runtime contract stamping in session creation
src/tmux/runtime-manager.ts, src/tmux/runtime-manager.test.ts
ensureClientSession and ensureProjectSession now stamp the runtime contract before later session configuration, with tests checking the recorded set-option order.

Possibly Related PRs

  • TraderSamwise/aimux#206: Also changes scripts/tmux-control.sh dashboard validation flow around validate_dashboard_target, which is the same shell path updated here to wait for readiness.
  • TraderSamwise/aimux#237: Touches dashboard target usability checks in src/dashboard/targets.ts, the same area extended here with TMUX_DASHBOARD_READY_OPTION.
  • TraderSamwise/aimux#240: Modifies the dashboard runtime-guard repair/refresh workflow in src/multiplexer/dashboard-control.ts, overlapping with the guard probe stabilization and flush paths changed here.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I stamped the pane with ready light,
and queued my hops for guardrail night.
When busy winds began to blow,
I waited, then let navigation flow.
Thump! The dashboard woke just right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing dashboard readiness race conditions in the TUI dashboard flow.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/tui-smoke-next-5

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: 3

🤖 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 `@src/multiplexer/dashboard-control.ts`:
- Around line 228-233: The queued navigation payload currently stores the full
buffer in queuePendingDashboardLocalNavigation, which can replay extra coalesced
input later; update this helper to queue only the first parsed event’s raw bytes
(events[0].raw) instead of Buffer.from(data). Make the same change in the other
affected queueing path referenced by the review, and keep the pending.key logic
unchanged so it still validates only the first parsed event.

In `@src/multiplexer/runtime-guard.ts`:
- Around line 34-44: Update isProjectServiceConnectionError in runtime-guard.ts
to treat connect timeouts as connection failures. Add ETIMEDOUT handling
alongside the existing ECONNREFUSED/ECONNRESET/EPIPE checks, including matching
it in both the error.code and message-based branches. This should prevent
getProjectServiceManifest from falling through to the local-manifest path when a
socket connect timeout occurs.

In `@src/tmux/control-script.test.ts`:
- Around line 114-118: The fake tmux ready-option logic in the control script
test is diverging from scripts/tmux-control.sh because the
`@aimux-dashboard-ready` fallback currently substitutes the build stamp when the
value is missing. Update the option lookup path in control-script.test.ts so
`@aimux-dashboard-ready` stays unset/false when absent instead of inheriting
`@aimux-dashboard-build`, and keep the behavior aligned with the control script’s
readiness check in the same helper that reads state.windowOptions.
🪄 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: fc7ce326-eeef-499f-a376-9cd6139d3cab

📥 Commits

Reviewing files that changed from the base of the PR and between 7204c5f and b45806f.

📒 Files selected for processing (14)
  • scripts/tmux-control.sh
  • src/dashboard/targets.test.ts
  • src/dashboard/targets.ts
  • src/metadata-server.test.ts
  • src/multiplexer/dashboard-control.test.ts
  • src/multiplexer/dashboard-control.ts
  • src/multiplexer/runtime-guard.test.ts
  • src/multiplexer/runtime-guard.ts
  • src/multiplexer/session-launch.test.ts
  • src/multiplexer/session-launch.ts
  • src/runtime-owner.ts
  • src/tmux/control-script.test.ts
  • src/tmux/runtime-manager.test.ts
  • src/tmux/runtime-manager.ts

Comment thread src/multiplexer/dashboard-control.ts
Comment thread src/multiplexer/runtime-guard.ts Outdated
Comment thread src/tmux/control-script.test.ts Outdated

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

🤖 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 `@src/metadata-server.test.ts`:
- Around line 2885-2894: The stale-ready test in metadata-server.test.ts is
currently satisfied by earlier calls, so it doesn’t prove this request path
still resets state correctly. Before the stale-ready scenario, clear the
relevant mocks used in the open-dashboard flow, especially setWindowOptionMock
and respawnWindowMock, or switch the expectation in this block to assert only
the new call(s) made by this request. Use the existing open-dashboard test setup
and the TMUX_DASHBOARD_READY_OPTION assertion to keep the check scoped to the
stale-ready case.
🪄 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: 4e36be46-431d-44f2-9d50-f5984a0c20eb

📥 Commits

Reviewing files that changed from the base of the PR and between b45806f and 4401f87.

📒 Files selected for processing (2)
  • src/metadata-server.test.ts
  • src/metadata-server.ts

Comment thread src/metadata-server.test.ts Outdated
@TraderSamwise

Copy link
Copy Markdown
Owner Author

Independent review follow-up fixed in 123617d:

  • /control/open-dashboard now waits for the dashboard readiness stamp before focusing a respawned dashboard, returning 503 instead of switching to an unready pane.
  • Runtime guard health read timeouts now classify the project service as unreachable; the existing disconnected-probe stabilizer handles transient misses.

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

Caution

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

⚠️ Outside diff range comments (2)
src/tui/screens/dashboard-renderers.ts (1)

389-428: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the footer hint aligned with the actual activation key.

handleDashboardNavigationKey() still accepts "right" alongside "enter" in every dashboard navigation state, so these hints now hide a supported shortcut. Please either render Enter/→ here too, or drop "right" from the handler if the alias is intentionally gone.

🤖 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/tui/screens/dashboard-renderers.ts` around lines 389 - 428, The footer
hints in the dashboard renderer are out of sync with the supported activation
keys in handleDashboardNavigationKey(), since the handler still accepts both
Enter and right-arrow in these states. Update the hint labels in the dashboard
footer rendering to show the actual activation shortcut (for example Enter/→)
wherever that alias is still supported, or remove the right-arrow alias from
handleDashboardNavigationKey() if it is no longer intended.
src/multiplexer/runtime-guard.ts (1)

172-193: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Don't swallow local processing failures as unreachable.

This catch now covers both the HTTP probe and the local response-processing branch. If getProjectServiceManifest() or getProjectStateDirFor(projectRoot) throws, we silently downgrade that bug/config failure into a disconnected state, and downstream dashboard control will treat it like a recoverable guard miss. Please narrow the try to requestJson(...) or rethrow non-transport errors.

🤖 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-guard.ts` around lines 172 - 193, The runtime guard
in runtime-guard.ts is swallowing local processing errors and turning them into
"unreachable," which hides real bugs; narrow the inner try/catch around
requestJson in the health probe path or rethrow any non-transport failures. Keep
getProjectServiceManifest and getProjectStateDirFor(projectRoot) outside the
catch that maps network failures to serviceManifest = "unreachable", and
preserve the existing endpointPresent/serviceIdentityMismatch flow in the same
block.
🤖 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 `@src/metadata-server.test.ts`:
- Around line 2906-2911: The test in the metadata-server suite currently
verifies that `setWindowOptionMock` and `respawnWindowMock` are both called, but
it does not assert their order. Update this assertion block to pin the contract
that `TMUX_DASHBOARD_READY_OPTION` is cleared before `respawnWindowMock` runs,
using the same mocked calls (`setWindowOptionMock`, `respawnWindowMock`, and
`expect.objectContaining({ windowId: "`@99`" })`) so the sequence is enforced even
if implementation details change.

---

Outside diff comments:
In `@src/multiplexer/runtime-guard.ts`:
- Around line 172-193: The runtime guard in runtime-guard.ts is swallowing local
processing errors and turning them into "unreachable," which hides real bugs;
narrow the inner try/catch around requestJson in the health probe path or
rethrow any non-transport failures. Keep getProjectServiceManifest and
getProjectStateDirFor(projectRoot) outside the catch that maps network failures
to serviceManifest = "unreachable", and preserve the existing
endpointPresent/serviceIdentityMismatch flow in the same block.

In `@src/tui/screens/dashboard-renderers.ts`:
- Around line 389-428: The footer hints in the dashboard renderer are out of
sync with the supported activation keys in handleDashboardNavigationKey(), since
the handler still accepts both Enter and right-arrow in these states. Update the
hint labels in the dashboard footer rendering to show the actual activation
shortcut (for example Enter/→) wherever that alias is still supported, or remove
the right-arrow alias from handleDashboardNavigationKey() if it is no longer
intended.
🪄 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: b610548a-ff7e-4d51-8574-d087301c0bd0

📥 Commits

Reviewing files that changed from the base of the PR and between 4401f87 and 123617d.

📒 Files selected for processing (12)
  • src/metadata-server.test.ts
  • src/metadata-server.ts
  • src/multiplexer/dashboard-control.test.ts
  • src/multiplexer/dashboard-control.ts
  • src/multiplexer/dashboard-interaction.test.ts
  • src/multiplexer/dashboard-interaction.ts
  • src/multiplexer/runtime-guard.test.ts
  • src/multiplexer/runtime-guard.ts
  • src/tmux/control-script.test.ts
  • src/tui/screens/dashboard-renderers.test.ts
  • src/tui/screens/dashboard-renderers.ts
  • src/tui/screens/overlay-renderers.ts
✅ Files skipped from review due to trivial changes (1)
  • src/tui/screens/dashboard-renderers.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/metadata-server.ts
  • src/multiplexer/dashboard-control.ts
  • src/multiplexer/runtime-guard.test.ts
  • src/multiplexer/dashboard-control.test.ts

Comment thread src/metadata-server.test.ts
@TraderSamwise
TraderSamwise merged commit 26e628e into master Jun 28, 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