Skip to content

Move restart through core daemon#299

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

Move restart through core daemon#299
TraderSamwise merged 6 commits into
masterfrom
chore/core-sidecar-next-23

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

  • add a daemon-owned core restart command that reuses in-process project actors
  • route CLI restart requests through the daemon command bus, with stale-build bootstrap fallback
  • add an installed shell fast path for exact aimux restart when the matching daemon is already alive

Verification

  • yarn vitest run src/installed-shim.test.ts src/daemon.test.ts src/core-command-contract.test.ts src/control-plane-restart-client.test.ts
  • yarn vitest run src/one-shot-node-inventory.test.ts src/core-sidecar-boundary.test.ts
  • yarn typecheck
  • yarn lint
  • yarn vitest run
  • yarn build
  • AIMUX_RELEASE_VERSION=local-core-sidecar-next-23 yarn release:asset

Summary by CodeRabbit

  • New Features

    • Added a faster, more reliable control-plane restart flow for the CLI and daemon.
    • Introduced a plain-text restart response endpoint and support for JSON output when requested.
    • Improved restart handling to work with a project path when provided.
  • Bug Fixes

    • Restart now verifies the active daemon before responding, reducing stale or mismatched restart results.
    • Added fallback behavior when the daemon and local build do not match.
  • Tests

    • Expanded coverage for daemon restart behavior, response formats, and fallback cases.

@vercel

vercel Bot commented Jul 4, 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 4, 2026 11:06am

@coderabbitai

coderabbitai Bot commented Jul 4, 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: 26 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: b45743bd-c6d7-46cb-8310-00607c2f2f4b

📥 Commits

Reviewing files that changed from the base of the PR and between 9f5397a and 9c1ab91.

📒 Files selected for processing (9)
  • scripts/installed-aimux-shim.sh
  • src/control-plane-restart-client.test.ts
  • src/control-plane-restart-client.ts
  • src/core-sidecar-boundary.test.ts
  • src/daemon-supervisor.ts
  • src/daemon.test.ts
  • src/daemon.ts
  • src/runtime-restart.test.ts
  • src/runtime-restart.ts
📝 Walkthrough

Walkthrough

This PR adds a control-plane restart command and HTTP text endpoint to the daemon, a CLI restart client that falls back to local bootstrap restart on build mismatch, shell shim restart fast-path support, and refactors runtime-restart to use lazy default hooks instead of eager imports.

Changes

Control-plane restart flow

Layer / File(s) Summary
Core command contract
src/core-command-contract.ts
Adds restartText route, restart command name, and CoreRestartPayload/CoreRestartResult types wired into payload/result mappings.
Runtime restart lazy hooks
src/runtime-restart.ts
Replaces eager daemon-supervisor imports with dynamic-import default wrappers and new Fn type aliases for restart option hooks.
Daemon restart endpoint
src/daemon.ts, src/daemon.test.ts
Adds a restart core-command case, a POST /core/restart-text handler returning plain text with 500 on failures, DaemonRouteResponse contentType support, and corresponding tests.
CLI restart client
src/control-plane-restart-client.ts, src/control-plane-restart-client.test.ts
Adds restartControlPlaneFromCli, which tries the daemon core command first and falls back to restartAimuxControlPlane on a local-build mismatch error; tests cover success, projectRoot passthrough, fallback, and error rethrow.
CLI wiring
src/main.ts
Updates restartStaleControlPlane, aimux restart, and aimux daemon restart to use restartControlPlaneFromCli and its {restart, text} shape.
Shim restart fast-path
scripts/installed-aimux-shim.sh, src/installed-shim.test.ts
Adds aimux_matching_daemon_port()/aimux_try_restart(), a restart CLI dispatch case, and test fixture/coverage for the restart-text endpoint and fallback to Node launcher.

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

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant restartControlPlaneFromCli
  participant Daemon
  participant restartAimuxControlPlane
  CLI->>restartControlPlaneFromCli: restartControlPlaneFromCli(projectRoot)
  restartControlPlaneFromCli->>Daemon: core.restart command
  alt daemon healthy
    Daemon->>restartAimuxControlPlane: perform restart
    restartAimuxControlPlane-->>Daemon: restart result
    Daemon-->>restartControlPlaneFromCli: {restart, text} source daemon
  else build mismatch error
    restartControlPlaneFromCli->>restartAimuxControlPlane: local bootstrap restart
    restartAimuxControlPlane-->>restartControlPlaneFromCli: local result, source local-bootstrap
  end
  restartControlPlaneFromCli-->>CLI: CliControlPlaneRestartResult
Loading

Possibly related PRs

  • TraderSamwise/aimux#199: Continues the coherent restart work by integrating the restart flow into CLI/core/daemon restart routes touching the same src/main.ts and src/runtime-restart.ts files.
  • TraderSamwise/aimux#276: Modifies RestartAimuxControlPlaneOptions and the same restart flow in src/runtime-restart.ts used by control-plane repair.
  • TraderSamwise/aimux#280: Prior work routing daemon-control hooks through daemon-supervisor.js that this PR further refactors into default wrapper functions.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change: routing restart handling through the core daemon.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/core-sidecar-next-23

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

@TraderSamwise

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
✅ 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.

@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

🧹 Nitpick comments (4)
scripts/installed-aimux-shim.sh (2)

70-89: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Temp file not cleaned up if interrupted mid-request.

If the shell process is killed/interrupted during the up-to-300s curl call, body_file created by mktemp is left behind since there's no trap for cleanup. Low impact (single leaked temp file in /tmp) but easy to harden.

🧹 Optional cleanup via trap
 aimux_try_restart() {
   port="$(aimux_matching_daemon_port)" || return 1
   body_file="$(mktemp "${TMPDIR:-/tmp}/aimux-restart.XXXXXX")" || return 1
+  trap 'rm -f "$body_file"' EXIT INT TERM
   status="$(
🤖 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 70 - 89, The aimux_try_restart
helper leaves the mktemp-created body_file behind if the shell is interrupted
during the long curl request. Harden this by adding cleanup around
aimux_try_restart so body_file is always removed on exit or interruption, using
a trap scoped to the function and ensuring it is cleared after normal
completion; keep the change localized to aimux_try_restart and its existing
mktemp/curl/cat flow.

64-68: 🚀 Performance & Scalability | 🔵 Trivial

Duplicate /health fetch introduced by the refactor.

aimux_try_daemon_ensure() calls aimux_matching_daemon_port(), which already performs an internal aimux_health_json call via command substitution (a subshell), then makes a second, separate aimux_health_json call here to get JSON for aimux_print_daemon_ensure. Since the first call runs in a subshell, its json variable can't be reused, so this doubles the localhost network round-trip and introduces a small window where the daemon's health could change between the two checks.

Consider having aimux_matching_daemon_port() emit both the port and enough info (e.g., print port and pid on separate lines, or reuse the already-fetched JSON) so callers avoid the redundant fetch.
[recommended_refactor_effort_low_reward_medium]

🤖 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 64 - 68,
aimux_try_daemon_ensure() currently triggers two /health fetches because
aimux_matching_daemon_port() already calls aimux_health_json internally and then
aimux_try_daemon_ensure() calls aimux_health_json again for
aimux_print_daemon_ensure. Update the flow so the first lookup reuses or returns
the fetched JSON (or returns both port and needed metadata) and have
aimux_try_daemon_ensure() pass that through, removing the redundant localhost
round-trip while keeping aimux_print_daemon_ensure fed with the same data.
src/daemon.ts (1)

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

Add an explicit return type to restartControlPlane.

This is the sole assembly point for CoreRestartResult ({ restart, text }), consumed by both the command route and the text route. An explicit annotation would catch future drift against the core-command-contract.ts contract at compile time.

🛠️ Proposed fix
-  private async restartControlPlane(issuedAt: string, projectRoot?: string) {
+  private async restartControlPlane(issuedAt: string, projectRoot?: string): Promise<CoreRestartResult> {

(Import CoreRestartResult from ./core-command-contract.js alongside the existing imports.)

🤖 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/daemon.ts` around lines 426 - 439, Add an explicit return type to
restartControlPlane so it is locked to CoreRestartResult. This method is the
single place that builds the { restart, text } object used by both routes, so
update restartControlPlane in src/daemon.ts to import CoreRestartResult from
core-command-contract and annotate the method return type to match that
contract, keeping the existing restartAimuxControlPlane and
renderRuntimeRestartResult flow unchanged.
src/control-plane-restart-client.test.ts (1)

51-95: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Good coverage of daemon success and fallback paths.

Both the direct daemon-forwarding tests and the local-bootstrap fallback test correctly assert the returned { restart, text, source } shape and the underlying mock call arguments.

One minor gap: there's no test exercising the fallback path with no projectRoot (i.e., restartControlPlaneFromCli() triggering needsLocalBootstrap and calling restartAimuxControlPlane({ projectRoot: undefined })). Not blocking, but would round out coverage of the undefined branch already exercised for the daemon-success case at Line 64.

🤖 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/control-plane-restart-client.test.ts` around lines 51 - 95, The
restartControlPlaneFromCli test suite is missing coverage for the
no-project-root fallback branch. Add a test that calls
restartControlPlaneFromCli() with no argument, forces the daemon-core request to
reject with the local-build mismatch so needsLocalBootstrap is exercised, and
asserts restartAimuxControlPlane is called with { projectRoot: undefined } and
the returned result still includes the local-bootstrap source. Use the existing
restartControlPlaneFromCli, needsLocalBootstrap, and restartAimuxControlPlane
symbols to keep the new test aligned with the current flow.
🤖 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/daemon.ts`:
- Around line 600-609: The `/restartText` handler in `src/daemon.ts` should
preserve its text/plain contract even when `restartControlPlane` fails. Update
the POST branch that uses `restartControlPlane(issuedAt)` so that errors like
the lock-contention case are caught locally and returned as a text/plain
response, rather than bubbling to `start()`’s generic JSON `catch`; keep the
response shape consistent with the existing `restartText` route and use the
route’s existing symbols (`restartControlPlane`, `CORE_API_ROUTES.restartText`,
and the `start()` error path) to locate the fix.

---

Nitpick comments:
In `@scripts/installed-aimux-shim.sh`:
- Around line 70-89: The aimux_try_restart helper leaves the mktemp-created
body_file behind if the shell is interrupted during the long curl request.
Harden this by adding cleanup around aimux_try_restart so body_file is always
removed on exit or interruption, using a trap scoped to the function and
ensuring it is cleared after normal completion; keep the change localized to
aimux_try_restart and its existing mktemp/curl/cat flow.
- Around line 64-68: aimux_try_daemon_ensure() currently triggers two /health
fetches because aimux_matching_daemon_port() already calls aimux_health_json
internally and then aimux_try_daemon_ensure() calls aimux_health_json again for
aimux_print_daemon_ensure. Update the flow so the first lookup reuses or returns
the fetched JSON (or returns both port and needed metadata) and have
aimux_try_daemon_ensure() pass that through, removing the redundant localhost
round-trip while keeping aimux_print_daemon_ensure fed with the same data.

In `@src/control-plane-restart-client.test.ts`:
- Around line 51-95: The restartControlPlaneFromCli test suite is missing
coverage for the no-project-root fallback branch. Add a test that calls
restartControlPlaneFromCli() with no argument, forces the daemon-core request to
reject with the local-build mismatch so needsLocalBootstrap is exercised, and
asserts restartAimuxControlPlane is called with { projectRoot: undefined } and
the returned result still includes the local-bootstrap source. Use the existing
restartControlPlaneFromCli, needsLocalBootstrap, and restartAimuxControlPlane
symbols to keep the new test aligned with the current flow.

In `@src/daemon.ts`:
- Around line 426-439: Add an explicit return type to restartControlPlane so it
is locked to CoreRestartResult. This method is the single place that builds the
{ restart, text } object used by both routes, so update restartControlPlane in
src/daemon.ts to import CoreRestartResult from core-command-contract and
annotate the method return type to match that contract, keeping the existing
restartAimuxControlPlane and renderRuntimeRestartResult flow unchanged.
🪄 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: ace2d275-3213-4b43-836e-038d56dd4d44

📥 Commits

Reviewing files that changed from the base of the PR and between 36092b6 and 9f5397a.

📒 Files selected for processing (9)
  • scripts/installed-aimux-shim.sh
  • src/control-plane-restart-client.test.ts
  • src/control-plane-restart-client.ts
  • src/core-command-contract.ts
  • src/daemon.test.ts
  • src/daemon.ts
  • src/installed-shim.test.ts
  • src/main.ts
  • src/runtime-restart.ts

Comment thread src/daemon.ts
@TraderSamwise

Copy link
Copy Markdown
Owner Author

Sub-agent review follow-up: fixed the stale-daemon bootstrap fallback by preserving daemon info/state before command-bus probing, and restored verified legacy project-service cleanup for daemon-owned restarts. Covered by src/control-plane-restart-client.test.ts and src/daemon.test.ts in 6a2e42d.

@TraderSamwise

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
✅ 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.

@TraderSamwise

Copy link
Copy Markdown
Owner Author

Final sub-agent review follow-up: fixed retained-daemon restart reporting in 9c1ab91. Daemon-owned restarts now set retainDaemon: true, render daemon: retained pid=..., and repair diagnostics use daemon retained instead of reporting a fresh daemon start.

@TraderSamwise

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
✅ 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.

@TraderSamwise
TraderSamwise merged commit 559771e into master Jul 4, 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