Skip to content

Move dashboard runtime repairs into core routes - #323

Merged
TraderSamwise merged 4 commits into
masterfrom
chore/core-sidecar-next-48
Jul 5, 2026
Merged

Move dashboard runtime repairs into core routes#323
TraderSamwise merged 4 commits into
masterfrom
chore/core-sidecar-next-48

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • route healthy dashboard-reload and restart-runtime through daemon-owned core text endpoints
  • add installed shim fast paths with stale-daemon Node fallback and caller tmux focus context
  • extract shared tmux runtime stop/statusline helpers and update command ownership docs/tests

Verification

  • yarn typecheck
  • yarn lint
  • yarn build
  • yarn vitest
  • yarn vitest src/installed-shim.test.ts src/daemon.test.ts src/core-command-ownership.test.ts

Summary by CodeRabbit

  • New Features

    • Added two advanced recovery commands for dashboards and runtime restarts, with support for opening the target in tmux when available.
    • Improved CLI handling for these commands, including optional flags and JSON output where applicable.
  • Bug Fixes

    • Dashboard and runtime recovery flows now refresh statusline artifacts and use safer project-root handling.
    • Requests without a project root are now rejected consistently.
  • Tests

    • Expanded coverage for new command routes, shell fast paths, and recovery behavior in healthy and stale-daemon scenarios.

@vercel

vercel Bot commented Jul 5, 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 5, 2026 7:35pm

@coderabbitai

coderabbitai Bot commented Jul 5, 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: 19 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: 30f37fc2-9611-4585-a3dd-0b58aa0b10ca

📥 Commits

Reviewing files that changed from the base of the PR and between ee50a69 and 68cae6e.

📒 Files selected for processing (8)
  • docs/command-ownership-inventory.md
  • scripts/installed-aimux-shim.sh
  • src/core-cli-routing.ts
  • src/core-command-ownership.test.ts
  • src/core-text.ts
  • src/daemon.test.ts
  • src/daemon.ts
  • src/installed-shim.test.ts
📝 Walkthrough

Walkthrough

This PR adds two new advanced recovery CLI commands, dashboard-reload and restart-runtime, backed by daemon routes. It introduces new API routes and text payload renderers, extracts tmux session-stop and statusline-artifact logic into reusable modules, refactors main.ts to use them, adds shim fast-path handlers, and updates CLI validation, tests, and documentation.

Changes

Dashboard reload and runtime restart feature

Layer / File(s) Summary
API contract and text rendering
src/core-command-contract.ts, src/core-text.ts
Adds dashboardReloadText/runtimeRestartText routes and payload interfaces/render helpers for the two new commands.
CLI command validation
src/core-cli-routing.ts
Adds flag-consumption helper and predicate validators for the new subcommands, wired into isCoreCliCommand.
Tmux utilities
src/tmux/runtime-stop.ts, src/tmux/statusline-artifacts.ts
New modules for stopping managed tmux sessions and rewriting dashboard/statusline artifact files.
Daemon route handlers
src/daemon.ts, src/daemon.test.ts
Adds route handlers resolving dashboard targets, rewriting statuslines, stopping runtime, and returning text/JSON responses; wires routes into dispatch and CLI-only allowlist; adds tests.
Installed shim fast paths
scripts/installed-aimux-shim.sh, src/installed-shim.test.ts
Adds POST/open helpers and dispatcher subcommands for the two commands with fast-path/fallback behavior; adds tests.
main.ts refactor
src/main.ts
Replaces local statusline/tmux-stop implementations with imports from new modules; removes an unused pre-stop snapshot call and stale imports.
Ownership tests and docs
src/core-command-ownership.test.ts, docs/command-ownership-inventory.md, docs/core-sidecar-north-star.md
Updates classification tests and documentation for the two commands, moving them to CUT status.

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

Sequence Diagram(s)

sequenceDiagram
  participant Shim as installed-aimux-shim.sh
  participant Daemon as daemon.ts
  participant Tmux as TmuxRuntimeManager
  participant Statusline as statusline-artifacts.ts

  Shim->>Daemon: POST /core/dashboard-reload-text
  Daemon->>Tmux: resolve dashboard target
  Daemon->>Statusline: rewriteDashboardStatuslineArtifacts
  Daemon->>Tmux: attach caller session (if --open)
  Daemon-->>Shim: rendered text/json payload

  Shim->>Daemon: POST /core/runtime-restart-text
  Daemon->>Tmux: stopProjectTmuxRuntime
  Daemon->>Statusline: rewriteDashboardStatuslineArtifacts
  Daemon-->>Shim: tmuxSessionsKilled + dashboard target
Loading

Possibly related PRs

  • TraderSamwise/aimux#116: Both PRs change the dashboard statusline artifact writing flow around rewriteLocalStatuslineArtifacts/rewriteDashboardStatuslineArtifacts.
  • TraderSamwise/aimux#239: Both PRs touch the aimux dashboard-reload open/client-session plumbing and dashboard target resolution semantics.
  • TraderSamwise/aimux#285: Both PRs modify src/core-cli-routing.ts's isCoreCliCommand validation logic.
🚥 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 clearly summarizes the main change: moving dashboard/runtime repair actions into core routes.
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-48

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

🧹 Nitpick comments (6)
src/core-text.ts (1)

322-328: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider surfacing tmuxSessionsKilled in the rendered text.

The payload carries tmuxSessionsKilled (per daemon.ts's runtimeRestartTextRoute), but the rendered lines never mention it, so CLI text output gives no confirmation of how many tmux sessions were actually stopped during a runtime restart.

♻️ Optional enhancement
 export function renderCoreRuntimeRestartLines(payload: CoreRuntimeRestartTextPayload): string[] {
   return [
     `Restarted project runtime for ${payload.projectRoot}`,
+    `Tmux sessions stopped: ${payload.tmuxSessionsKilled.length}`,
     `Dashboard: ${payload.dashboardSessionName}:${payload.dashboardTarget.windowIndex}`,
   ];
 }
🤖 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/core-text.ts` around lines 322 - 328, The rendered runtime restart text
in renderCoreRuntimeRestartLines should include the tmuxSessionsKilled value
from CoreRuntimeRestartTextPayload so CLI output confirms how many tmux sessions
were stopped. Update the string array returned by renderCoreRuntimeRestartLines
to add a line that surfaces tmuxSessionsKilled alongside the existing
projectRoot and dashboard details, using the payload field directly so the
output stays in sync with daemon.ts's runtimeRestartTextRoute.
src/core-cli-routing.ts (1)

98-110: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Equals-form flag values aren't checked for a leading -.

The --flag value branch rejects values starting with - (to avoid swallowing a following flag as the value), but the --flag=value branch only checks truthiness — --client-tty=-x would be accepted while --client-tty -x would not. Minor inconsistency; unlikely to matter in practice since = unambiguously delimits the value.

🤖 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/core-cli-routing.ts` around lines 98 - 110, The consumeOptionalTextFlag
helper handles flag values inconsistently between spaced and equals forms.
Update the equals-form branch in consumeOptionalTextFlag so it applies the same
leading-dash validation as the consumeRequiredValue path, and return null when
the parsed value is empty or starts with a hyphen. Keep the behavior aligned for
both forms of the same flag in src/core-cli-routing.ts.
src/core-command-ownership.test.ts (1)

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

Consider covering --client-tty / --current-client-session flag combos.

isCoreDashboardReloadCommand and isCoreRuntimeRestartCommand (src/core-cli-routing.ts) both accept --client-tty and --current-client-session in addition to --open/--json, but these disposition fixtures only cover the bare and --open/--json variants. Adding entries for the tty/session flag combos would keep this fixture in sync with the full CLI contract these commands accept.

🤖 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/core-command-ownership.test.ts` around lines 198 - 221, The disposition
fixture for core command ownership is missing coverage for the accepted
`--client-tty` and `--current-client-session` flag combinations. Update the test
cases in `src/core-command-ownership.test.ts` to add entries for
`dashboard-reload` and `restart-runtime` using these flags, alongside the
existing `isCoreDashboardReloadCommand` and `isCoreRuntimeRestartCommand`
scenarios. Make sure the new fixtures use the same `shim-fast-path` disposition
and the correct `shimNeedle` values so the test stays aligned with the CLI
routing contract in `src/core-cli-routing.ts`.
src/installed-shim.test.ts (1)

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

Good coverage of the main fast-path flows.

Consider adding a case where the route response has no dashboardTarget/sessionName (runtime-restart with nothing to attach to), to lock in the expected Error: command completed, but no dashboard target was available to open behavior and catch the empty dashboard_session_name formatting issue noted in scripts/installed-aimux-shim.sh.

🤖 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/installed-shim.test.ts` around lines 491 - 589, Add a regression test in
installed-shim.test.ts for the runtime-restart/dashboard-reload open path when
the route response lacks both dashboardTarget and sessionName. Use the existing
fixture helpers around fixture.run, dashboard-reload/restart-runtime, and the
textRouteFile/daemonInfoPath setup to assert the command fails with the expected
“no dashboard target was available to open” error and does not launch Node. This
will also lock in the empty dashboard_session_name handling in the shim.
scripts/installed-aimux-shim.sh (2)

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

Near-duplicate of aimux_post_project_restart_open.

This function repeats the mktemp/trap/curl-status/sed-parsing/attach-session boilerplate already implemented in aimux_post_project_restart_open (lines 255-308), differing only in the route path, success message, and error-message wording. Extracting a shared helper would reduce the surface area to maintain when this POST/parse/attach pattern needs to change.

♻️ Sketch of a shared helper
+aimux_post_and_open_dashboard_target() {
+  route_path="$1"
+  timeout="$2"
+  on_success="$3"  # callback name invoked with dashboard_session_name/project_root/window_index in scope
+  shift 3
+  port="$(aimux_matching_daemon_port)" || return 1
+  body_file="$(mktemp "${TMPDIR:-/tmp}/aimux-dashboard-open.XXXXXX")" || return 1
+  trap 'rm -f "$body_file"' EXIT
+  trap 'rm -f "$body_file"; exit 130' INT TERM
+  status="$(curl -sS --max-time "$timeout" -o "$body_file" -w '%{http_code}' -X POST "$@" \
+    "http://127.0.0.1:$port$route_path?json=1" 2>/dev/null || true)"
+  # ... shared status handling, sed extraction, attach-session logic ...
+}
🤖 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 `@scripts/installed-aimux-shim.sh` around lines 310 - 372, The logic in
aimux_post_dashboard_open_route is a near-duplicate of
aimux_post_project_restart_open, so factor the shared
mktemp/trap/curl-status/sed-parsing/attach-session flow into a common helper.
Keep only the route-specific pieces in aimux_post_dashboard_open_route: the
route path, success_kind-specific output, and final error wording. Update both
functions to call the shared helper so future changes to the POST/parse/attach
behavior happen in one place.

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

Duplicated open-detection/dispatch logic between the two new handlers.

The tmux client auto-detection and open-vs-direct-post branching (lines 805-820 and 872-890) is copy-pasted between aimux_try_dashboard_reload and aimux_try_runtime_restart, differing only by route path and success_kind. Since both were introduced in this PR, extracting a shared dispatch helper now avoids two places to keep in sync going forward.

♻️ Suggested shared dispatch helper
+aimux_dispatch_dashboard_action() {
+  route_path="$1"
+  success_kind="$2"
+  open="$3"
+  current_client_session="$4"
+  client_tty="$5"
+  shift 5
+  if [ "$open" -eq 1 ]; then
+    if [ -z "$current_client_session" ] && [ -z "$client_tty" ] && [ -n "${TMUX:-}" ] && command -v tmux >/dev/null 2>&1; then
+      current_client_session="$(tmux display-message -p "#{client_session}" 2>/dev/null || true)"
+      client_tty="$(tmux display-message -p "#{client_tty}" 2>/dev/null || true)"
+    fi
+    if [ -n "$current_client_session" ] || [ -n "$client_tty" ]; then
+      set -- "$@" --data-urlencode "open=1"
+      [ -n "$current_client_session" ] && set -- "$@" --data-urlencode "currentClientSession=$current_client_session"
+      [ -n "$client_tty" ] && set -- "$@" --data-urlencode "clientTty=$client_tty"
+      aimux_post_query_text_route "$route_path" 120 "$@"
+      return $?
+    fi
+    aimux_post_dashboard_open_route "$route_path" "$success_kind" 120 "$@"
+    return $?
+  fi
+  aimux_post_query_text_route "$route_path" 120 "$@"
+}

Then both handlers would just build their --data-urlencode args and call this helper.

🤖 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 `@scripts/installed-aimux-shim.sh` around lines 767 - 890, The tmux
auto-detection and open-vs-direct-post branching is duplicated in
aimux_try_dashboard_reload and aimux_try_runtime_restart, so extract that shared
logic into a helper and have both handlers call it. Keep the route-specific
pieces as arguments to the helper (such as the text route and success_kind/open
action), and let each handler only assemble its own query params like
projectRoot and json before dispatching.
🤖 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 `@docs/command-ownership-inventory.md`:
- Around line 42-43: The command ownership inventory entry for restart-runtime
is missing the stale-daemon fallback behavior that is documented for
dashboard-reload. Update the restart-runtime row to explicitly mention that it
also falls back to a Node bootstrap when the daemon is stale, while keeping the
healthy path daemon-owned; use the existing “restart-runtime” row and its
`/core/runtime-restart-text` description as the anchor for the edit.

In `@scripts/installed-aimux-shim.sh`:
- Around line 345-356: The runtime-restart success path in the success_kind case
is logging a dashboard target even when none exists, which leads to misleading
output before the missing-target error path. Update the runtime-restart branch
to only print the Dashboard line after confirming session_name is set, or guard
it so it only logs when a real dashboard target is available; keep the change
localized to the success_kind switch handling and the session_name check flow.

In `@src/daemon.ts`:
- Around line 635-639: In explicitProjectRootTextParam, the projectRoot lookup
uses nullish coalescing so an explicit empty string prevents falling back to
project. Update the parameter selection logic to treat blank projectRoot as
absent and then use project as the fallback before validating. Keep the fix
localized to explicitProjectRootTextParam in src/daemon.ts and preserve the
existing resolveProjectRoot and textError behavior.
- Around line 697-709: The dashboard reload flow in dashboardReloadTextRoute
invalidates statusline artifacts before confirming tmux is available, which can
leave the dashboard broken if tmux is missing. Move the tmux availability check
on TmuxRuntimeManager ahead of invalidateTmuxStatuslineArtifacts(projectRoot),
mirroring the ordering used in runtimeRestartTextRoute, so artifacts are only
deleted once you know regeneration can proceed.
- Around line 732-758: The runtime restart flow in runtimeRestartTextRoute
recreates tmux sessions but does not refresh the statusline artifacts, leaving
the dashboard footer stale. Add the same statusline invalidation/rewriting step
used by dashboardReloadTextRoute after stopping/restarting the project and
before returning the payload, so restart-runtime keeps the tmux UI current. Use
the runtimeRestartTextRoute flow, stopProjectTmuxRuntime, and
resolveDashboardTarget as the nearby anchors when wiring in the refresh logic.

---

Nitpick comments:
In `@scripts/installed-aimux-shim.sh`:
- Around line 310-372: The logic in aimux_post_dashboard_open_route is a
near-duplicate of aimux_post_project_restart_open, so factor the shared
mktemp/trap/curl-status/sed-parsing/attach-session flow into a common helper.
Keep only the route-specific pieces in aimux_post_dashboard_open_route: the
route path, success_kind-specific output, and final error wording. Update both
functions to call the shared helper so future changes to the POST/parse/attach
behavior happen in one place.
- Around line 767-890: The tmux auto-detection and open-vs-direct-post branching
is duplicated in aimux_try_dashboard_reload and aimux_try_runtime_restart, so
extract that shared logic into a helper and have both handlers call it. Keep the
route-specific pieces as arguments to the helper (such as the text route and
success_kind/open action), and let each handler only assemble its own query
params like projectRoot and json before dispatching.

In `@src/core-cli-routing.ts`:
- Around line 98-110: The consumeOptionalTextFlag helper handles flag values
inconsistently between spaced and equals forms. Update the equals-form branch in
consumeOptionalTextFlag so it applies the same leading-dash validation as the
consumeRequiredValue path, and return null when the parsed value is empty or
starts with a hyphen. Keep the behavior aligned for both forms of the same flag
in src/core-cli-routing.ts.

In `@src/core-command-ownership.test.ts`:
- Around line 198-221: The disposition fixture for core command ownership is
missing coverage for the accepted `--client-tty` and `--current-client-session`
flag combinations. Update the test cases in `src/core-command-ownership.test.ts`
to add entries for `dashboard-reload` and `restart-runtime` using these flags,
alongside the existing `isCoreDashboardReloadCommand` and
`isCoreRuntimeRestartCommand` scenarios. Make sure the new fixtures use the same
`shim-fast-path` disposition and the correct `shimNeedle` values so the test
stays aligned with the CLI routing contract in `src/core-cli-routing.ts`.

In `@src/core-text.ts`:
- Around line 322-328: The rendered runtime restart text in
renderCoreRuntimeRestartLines should include the tmuxSessionsKilled value from
CoreRuntimeRestartTextPayload so CLI output confirms how many tmux sessions were
stopped. Update the string array returned by renderCoreRuntimeRestartLines to
add a line that surfaces tmuxSessionsKilled alongside the existing projectRoot
and dashboard details, using the payload field directly so the output stays in
sync with daemon.ts's runtimeRestartTextRoute.

In `@src/installed-shim.test.ts`:
- Around line 491-589: Add a regression test in installed-shim.test.ts for the
runtime-restart/dashboard-reload open path when the route response lacks both
dashboardTarget and sessionName. Use the existing fixture helpers around
fixture.run, dashboard-reload/restart-runtime, and the
textRouteFile/daemonInfoPath setup to assert the command fails with the expected
“no dashboard target was available to open” error and does not launch Node. This
will also lock in the empty dashboard_session_name handling in the shim.
🪄 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: 5e7c3f26-932f-47c2-9117-b8e1809616ad

📥 Commits

Reviewing files that changed from the base of the PR and between d206169 and ee50a69.

📒 Files selected for processing (13)
  • docs/command-ownership-inventory.md
  • docs/core-sidecar-north-star.md
  • scripts/installed-aimux-shim.sh
  • src/core-cli-routing.ts
  • src/core-command-contract.ts
  • src/core-command-ownership.test.ts
  • src/core-text.ts
  • src/daemon.test.ts
  • src/daemon.ts
  • src/installed-shim.test.ts
  • src/main.ts
  • src/tmux/runtime-stop.ts
  • src/tmux/statusline-artifacts.ts

Comment thread docs/command-ownership-inventory.md Outdated
Comment thread scripts/installed-aimux-shim.sh
Comment thread src/daemon.ts
Comment thread src/daemon.ts
Comment thread src/daemon.ts
@TraderSamwise
TraderSamwise merged commit a391b34 into master Jul 5, 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