Skip to content

Route worktree and graveyard CLI through daemon#308

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

Route worktree and graveyard CLI through daemon#308
TraderSamwise merged 3 commits into
masterfrom
chore/core-sidecar-next-33

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

  • add daemon core text routes for worktree and graveyard CLI operations
  • route installed shim worktree/graveyard commands through daemon/project-service APIs in the healthy path
  • document command ownership cutover and cover stale-daemon fallback plus route guards

Verification

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

Summary by CodeRabbit

  • New Features

    • Added end-user command support for managing worktrees and graveyard workflows, with both text and JSON output.
    • Expanded daemon routing so these commands can be served directly when available.
  • Bug Fixes

    • Tightened access rules for core text routes to prevent unintended remote or browser-origin access.
    • Improved fallback behavior so commands switch cleanly to the launcher when daemon health is stale.
  • Documentation

    • Updated command ownership inventory to reflect the new supported command families.

@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 6:49pm

@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: 25 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: 36df3f27-9108-4596-bb48-076d6594ee89

📥 Commits

Reviewing files that changed from the base of the PR and between 1f88c50 and 1ea044e.

📒 Files selected for processing (5)
  • scripts/installed-aimux-shim.sh
  • src/core-text.ts
  • src/daemon.test.ts
  • src/daemon.ts
  • src/installed-shim.test.ts
📝 Walkthrough

Walkthrough

This PR adds worktree and graveyard command support end-to-end: new text-route contracts and renderers, daemon routing with loopback/CLI access control proxying to a project service, installed shim CLI dispatch, and corresponding tests/documentation updates reclassifying these commands from LEGACY to CUT.

Changes

Worktree/Graveyard Text Route Feature

Layer / File(s) Summary
Route contract and text rendering
src/core-command-contract.ts, src/core-text.ts
New CORE_API_ROUTES entries for worktree/graveyard text endpoints, plus payload interfaces and renderer functions producing human-readable list/status/cleanup output.
Daemon routing, access control, and project-service proxying
src/daemon.ts
Adds LOCAL_CLI_TEXT_ROUTES allowlist with loopback/cli-only 403 checks, a getProjectServiceJson() GET helper and array validator, new worktree/graveyard route handlers, and routeRequest wiring.
Daemon routing tests
src/daemon.test.ts
Verifies 403 rejection of core text routes for remote/browser origins and success paths for worktree/graveyard operations proxied through the project service.
Installed shim CLI dispatch
scripts/installed-aimux-shim.sh
Adds argument-parsing helper and aimux_try_worktree/aimux_try_graveyard functions calling the new daemon text routes via curl, wired into the command dispatch switch.
Shim ownership and fast-path tests, docs
src/core-command-ownership.test.ts, src/installed-shim.test.ts, docs/command-ownership-inventory.md
Adds fast-path ownership entries and shim needles, expands shim test mocks and adds fast-path/fallback tests, and updates ownership docs from LEGACY to CUT.

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

Sequence Diagram(s)

sequenceDiagram
  participant CLI as aimux CLI (shim)
  participant Daemon
  participant ProjectService

  CLI->>Daemon: curl GET/POST /core/worktree/*-text or /core/graveyard/*-text
  Daemon->>Daemon: check LOCAL_CLI_TEXT_ROUTES (loopback/cli-only 403)
  alt authorized
    Daemon->>ProjectService: getProjectServiceJson / postProjectServiceJson
    ProjectService-->>Daemon: JSON payload
    Daemon->>Daemon: validate required array/fields
    Daemon->>Daemon: renderCoreWorktree*/renderCoreGraveyard* lines
    Daemon-->>CLI: text or JSON response
  else unauthorized
    Daemon-->>CLI: 403 loopback-only / cli-only
  end
Loading

Possibly related PRs

  • TraderSamwise/aimux#35: Extends the same worktree/graveyard surface (resurrect/delete/list flows), overlapping with this PR's new worktree/graveyard route additions.
🚥 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 and concisely summarizes the main change: routing worktree and graveyard CLI commands through the daemon.
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-33

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.

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

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

Duplicate arg-parsing logic instead of reusing aimux_parse_project_json_args.

The cleanup branch reimplements the --project/--project=/--json parsing loop already extracted into aimux_parse_project_json_args (Lines 500-527), just adding --dry-run. This duplication risks silent drift (e.g., if the shared helper's validation changes, this copy won't get the fix).

♻️ Suggested consolidation
-    cleanup)
-      shift
-      project_root="$(pwd -P 2>/dev/null)" || return 1
-      json=0
-      dry_run=0
-      while [ "$#" -gt 0 ]; do
-        case "$1" in
-          --project)
-            shift
-            [ "$#" -gt 0 ] || return 1
-            case "$1" in -*) return 1 ;; esac
-            project_root="$1"
-            ;;
-          --project=*)
-            project_root="${1#--project=}"
-            [ -n "$project_root" ] || return 1
-            ;;
-          --json)
-            json=1
-            ;;
-          --dry-run)
-            dry_run=1
-            ;;
-          *)
-            return 1
-            ;;
-        esac
-        shift
-      done
-      project_root="$(aimux_resolve_project_arg "$project_root")" || return 1
-      path="/core/graveyard/cleanup-text"
-      [ "$json" -eq 1 ] && path="/core/graveyard/cleanup-text?json=1"
-      aimux_post_query_text_route "$path" 120 \
-        --data-urlencode "project=$project_root" --data-urlencode "dryRun=$dry_run"
-      ;;
+    cleanup)
+      shift
+      dry_run=0
+      remaining_args=""
+      while [ "$#" -gt 0 ]; do
+        case "$1" in
+          --dry-run) dry_run=1 ;;
+          *) remaining_args="$remaining_args $1" ;;
+        esac
+        shift
+      done
+      aimux_parse_project_json_args $remaining_args || return 1
+      path="/core/graveyard/cleanup-text"
+      [ "$AIMUX_PARSED_JSON" -eq 1 ] && path="/core/graveyard/cleanup-text?json=1"
+      aimux_post_query_text_route "$path" 120 \
+        --data-urlencode "project=$AIMUX_PARSED_PROJECT" --data-urlencode "dryRun=$dry_run"
+      ;;

Note: unquoted $remaining_args word-splitting is acceptable here since values are simple flags/paths, but verify no arguments containing spaces are expected.

🤖 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 609 - 643, The cleanup command
in the command-dispatch block is duplicating the
`--project`/`--project=`/`--json` parsing already handled by
`aimux_parse_project_json_args`, so update `cleanup` to reuse that helper and
only handle the extra `--dry-run` flag locally. Keep `project_root` resolution
via `aimux_resolve_project_arg`, and make sure the cleanup branch still passes
both the parsed project value and `dryRun` to `aimux_post_query_text_route`
without reimplementing the shared parsing loop.

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

Duplicate GET-request construction for worktree/graveyard list.

Both blocks reimplement the same GET pattern already factored into aimux_curl_project_text_route (Lines 229-235), differing only in that they need a caller-resolved project instead of pwd. Consider generalizing the existing helper to accept an explicit project argument and reuse it in both places to avoid triplicated curl invocation logic.

Also applies to: 588-591

🤖 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 538 - 542, Duplicate GET
request construction is repeated in the worktree/graveyard list paths instead of
reusing the existing request helper. Update aimux_curl_project_text_route to
accept an explicit project argument (rather than always deriving it from pwd),
then call that helper from the list-text and graveyard list blocks so both use
the same curl logic and only vary by caller-provided project and path.
src/daemon.ts (1)

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

getProjectServiceJson duplicates postProjectServiceJson.

Endpoint lookup, ensureProject gating, status/ok validation, and the catch-block error formatting are copied almost verbatim from postProjectServiceJson (lines 533-573), differing only in HTTP method/body. Consider factoring the shared logic into one private helper taking method/body as parameters to avoid the two copies diverging over time (e.g. the timeout-vs-generic-error status code distinction already present in the /proxy/ handler isn't applied to either of these).

🤖 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 487 - 531, getProjectServiceJson duplicates
postProjectServiceJson; extract the shared endpoint lookup, ensureProject
handling, requestJson status/ok validation, and catch-block error formatting
into a private helper used by both methods. Keep the helper parameterized by
method/body so getProjectServiceJson and postProjectServiceJson only supply
their HTTP-specific differences, and preserve the existing error/status behavior
in the shared path.
src/core-text.ts (1)

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

Duplicate worktree table formatting.

renderCoreWorktreeListLines and the worktrees block inside renderCoreGraveyardLines build the same Name/Branch/Path table (same padEnd widths, same separator length) with only the empty-field fallback ("" vs "?") differing. Consider extracting a shared row-formatting helper to avoid the two copies drifting apart.

♻️ Proposed shared helper
+function formatWorktreeRow(worktree: Record<string, unknown>, fallback = ""): string {
+  return (
+    String(worktree.name ?? fallback).padEnd(30) +
+    String(worktree.branch ?? "").padEnd(35) +
+    String(worktree.path ?? fallback)
+  );
+}
+
 export function renderCoreWorktreeListLines(payload: CoreWorktreeSummaryTextPayload): string[] {
   const worktrees = payload.worktrees.filter((entry) => entry && typeof entry === "object") as Array<
     Record<string, unknown>
   >;
   if (worktrees.length === 0) return ["No worktrees found."];
   const lines = ["Name".padEnd(30) + "Branch".padEnd(35) + "Path", "-".repeat(95)];
-  for (const worktree of worktrees) {
-    lines.push(
-      String(worktree.name ?? "").padEnd(30) + String(worktree.branch ?? "").padEnd(35) + String(worktree.path ?? ""),
-    );
-  }
+  for (const worktree of worktrees) lines.push(formatWorktreeRow(worktree));
   return lines;
 }

Also applies to: 277-309

🤖 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 240 - 252, Duplicate worktree table formatting
exists in renderCoreWorktreeListLines and the worktrees block inside
renderCoreGraveyardLines, so extract the shared Name/Branch/Path row and header
formatting into a common helper using the same padEnd widths and separator
length. Keep the only behavioral difference in the fallback values ("", "?") as
an input to the helper, and update both call sites to use the shared formatting
so the two tables cannot drift apart.
🤖 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.

Nitpick comments:
In `@scripts/installed-aimux-shim.sh`:
- Around line 609-643: The cleanup command in the command-dispatch block is
duplicating the `--project`/`--project=`/`--json` parsing already handled by
`aimux_parse_project_json_args`, so update `cleanup` to reuse that helper and
only handle the extra `--dry-run` flag locally. Keep `project_root` resolution
via `aimux_resolve_project_arg`, and make sure the cleanup branch still passes
both the parsed project value and `dryRun` to `aimux_post_query_text_route`
without reimplementing the shared parsing loop.
- Around line 538-542: Duplicate GET request construction is repeated in the
worktree/graveyard list paths instead of reusing the existing request helper.
Update aimux_curl_project_text_route to accept an explicit project argument
(rather than always deriving it from pwd), then call that helper from the
list-text and graveyard list blocks so both use the same curl logic and only
vary by caller-provided project and path.

In `@src/core-text.ts`:
- Around line 240-252: Duplicate worktree table formatting exists in
renderCoreWorktreeListLines and the worktrees block inside
renderCoreGraveyardLines, so extract the shared Name/Branch/Path row and header
formatting into a common helper using the same padEnd widths and separator
length. Keep the only behavioral difference in the fallback values ("", "?") as
an input to the helper, and update both call sites to use the shared formatting
so the two tables cannot drift apart.

In `@src/daemon.ts`:
- Around line 487-531: getProjectServiceJson duplicates postProjectServiceJson;
extract the shared endpoint lookup, ensureProject handling, requestJson
status/ok validation, and catch-block error formatting into a private helper
used by both methods. Keep the helper parameterized by method/body so
getProjectServiceJson and postProjectServiceJson only supply their HTTP-specific
differences, and preserve the existing error/status behavior in the shared path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 85cac626-508b-4a54-bd87-101b5df48471

📥 Commits

Reviewing files that changed from the base of the PR and between 6701f62 and 1f88c50.

📒 Files selected for processing (8)
  • docs/command-ownership-inventory.md
  • scripts/installed-aimux-shim.sh
  • 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

@TraderSamwise

Copy link
Copy Markdown
Owner Author

Independent review finding fixed: aimux graveyard send <sessionId> could print resurrected because the project service returns status: "graveyard" for the kill/graveyard route. Fixed in 1ea044e by mapping graveyard/graveyarded to graveyarded and adding daemon coverage for the send route.

@TraderSamwise
TraderSamwise merged commit 818c17d 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