Skip to content

feat(runtime-host): add remote project registration - #3145

Merged
M4n5ter merged 11 commits into
mainfrom
feat/remote-project-registration
Aug 18, 2026
Merged

feat(runtime-host): add remote project registration#3145
M4n5ter merged 11 commits into
mainfrom
feat/remote-project-registration

Conversation

@M4n5ter

@M4n5ter M4n5ter commented Aug 17, 2026

Copy link
Copy Markdown
Member
English

Summary

Remote Desktop targets could select only Projects already registered on the Runtime Host. This PR adds a constrained Host-side directory picker so users can browse folders published by that Host and register one through the existing Project Catalog authority.

The service user's Home is published by default. Operators can replace it with up to eight named --project-root <label>=<absolute-path> entries. Remote browsing uses opaque root IDs and validated path segments; Local keeps the native OS picker.

Refs #2522

Verification

  • npm run lint — passed
  • npm run format:check — passed
  • npm run typecheck — passed across all workspaces
  • npm run astryx:surface-inventory — passed with 188 aligned surfaces and 0 blockers
  • affected Runtime Host, CLI, and Desktop tests — passed
  • npm test — 951/952 passed; the existing Candidate-arbitration timeout passed when rerun in isolation
  • exercised the Desktop flow against a real remote Runtime Host over SSH: switch between two published roots, toggle hidden folders, navigate, register a Project, and select it for a new task

AI use

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex contributed implementation, tests, analysis, and remote Desktop verification under maintainer direction

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No
简体中文

摘要

此前,Desktop 的远程目标只能选择已经在 Runtime Host 注册的 Project。本 PR 增加受限的 Host-side 目录选择器,让用户浏览该 Host 发布的文件夹,并通过现有 Project Catalog authority 注册所选目录。

默认发布运行服务用户的 Home。Operator 可以用最多八个命名的 --project-root <label>=<absolute-path> 替换默认范围。远程浏览只使用不透明 root ID 和经过校验的路径分段;Local 继续使用系统原生选择器。

关联 #2522

验证

  • npm run lint — 通过
  • npm run format:check — 通过
  • npm run typecheck — 所有 workspace 通过
  • npm run astryx:surface-inventory — 188 个 surface 全部 aligned,0 blocker
  • 受影响的 Runtime Host、CLI 与 Desktop 测试 — 通过
  • npm test — 951/952 通过;既有 Candidate 仲裁超时在隔离重跑时通过
  • 已通过 SSH 对真实远程 Runtime Host 验证 Desktop 流程:切换两个已发布 root、显示和隐藏隐藏目录、浏览并注册 Project,再将其选作新任务目标

AI 使用

  • 没有生成式工具作出实质性贡献
  • 生成式工具作出了实质性贡献

工具与范围:OpenAI Codex 在维护者指导下参与了实现、测试、分析和远程 Desktop 验证

检查清单

  • 测试覆盖本次变更,并会在缺少该变更时失败
  • lint、格式检查、类型检查和受影响测试均在本地通过

本 PR 是否会改变行为?

  • 是 — 已在上方摘要中说明

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 46d008ba-f9bf-4dfe-baa2-284ef4804a70

📥 Commits

Reviewing files that changed from the base of the PR and between 158a10f and 065dc74.

📒 Files selected for processing (2)
  • packages/runtime-host/src/__tests__/project-directory-authority.test.ts
  • packages/runtime-host/src/server/project-directory-authority.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/runtime-host/src/tests/project-directory-authority.test.ts
  • packages/runtime-host/src/server/project-directory-authority.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.


📝 Walkthrough

Summary

This PR adds remote project registration for Desktop targets. Users can browse Host-published folders through a constrained picker and register a selected folder through the existing Project Catalog authority. Local project selection still uses the native OS picker.

The implementation extends the existing Project Catalog, Runtime Host protocol, IPC bridge, and project-management service. It does not create a parallel registration path. Opaque root IDs, validated path segments, pagination limits, symlink checks, and canonical path boundaries restrict access to published roots.

The solution is the smallest coherent path for the feature. The remote picker, capability flags, bridge methods, protocol validation, directory authority, and Host-scoped actions support remote selection without changing local behavior. No clear deletion or simplification opportunity is visible without reducing behavior or regression coverage.

Reported validation includes lint, formatting, type checks, surface inventory checks, affected tests, and remote SSH verification. Full tests reportedly passed 951/952, with the existing timeout passing on isolated rerun. The current checkout returned no changed files, so the implementation and check results cannot be independently verified from the available diff.

Review-relevant risks

  • The reported changes affect Desktop bridge contracts and Runtime Host protocol types, including compatibility epoch 22 to 23. Material public-contract or release changes require independent human review under repository policy.
  • The reported changes affect user-visible project selection and add a remote directory picker. Material user-visible behavior changes require independent human review under repository policy.
  • The reported changes add Host directory access and project registration with path and symlink boundary checks. Material security changes require independent human review under repository policy.
  • The reported changes add CLI options and documentation for published project roots. Material configuration, release, or governance changes require independent human review under repository policy.
  • Required-check status remains unverified because the current checkout exposes no changed files or direct check evidence.
  • The person performing the merge must review the final diff. A maintainer makes the final determination.

Walkthrough

This change adds remote host-directory browsing and project registration. It extends runtime-host protocols, root configuration, Desktop IPC and preload APIs, storage boundaries, renderer project-selection flows, localization, styling, and validation tests.

Changes

Remote directory selection

Layer / File(s) Summary
Directory protocol contracts and validation
packages/runtime-host/src/protocol/*, packages/runtime-host/src/__tests__/project-catalog-protocol.test.ts
Adds directory query, listing, registration, pagination, size limits, path validation, decoders, mutation support, and compatibility epoch 23.
Host directory authority and catalog coordination
packages/runtime-host/src/server/project-directory-authority.ts, packages/runtime-host/src/server/project-catalog-coordinator.ts, packages/runtime-host/src/__tests__/*
Publishes roots, lists safe directory entries, rejects invalid or escaping paths, and resolves directory registrations through the project catalog.
Runtime host root configuration
packages/cli/src/*, packages/runtime-host/src/server/execution-*, docs/runtime-host-remote-access*
Adds repeatable --project-root <label>=<path> parsing, validation, service forwarding, composition wiring, help text, tests, and documentation.
Desktop directory transport and capability wiring
apps/desktop/src/main/*, apps/desktop/src/preload/*
Adds service, IPC, preload, runtime-client, and catalog methods for directory roots, listings, and registration. Remote hosts enable chooseHostDirectory; local hosts disable it.
Renderer directory picker integration
apps/desktop/src/renderer/*, packages/ui/src/workspace-picker.tsx
Adds the remote directory dialog, navigation and registration states, localized copy, project-selection wiring, styling, and group-scoped workspace actions.
Project registration boundary enforcement
packages/storage/src/project-catalog.ts, packages/storage/src/project-catalog-authority.ts, packages/storage/src/__tests__/project-catalog.test.ts
Adds withinRoot validation and rejects registration when the canonical project path is outside the selected root.

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

Merge Risk: 🟡 Moderate · up to 065dc

This PR adds remote folder browsing and project registration, but the current behavior leaves Relink enabled while doing nothing for some hosts and exposes root identifiers that may allow configured filesystem paths to be inferred. Merge should wait for these bounded correctness and security issues to be fixed or explicitly accepted.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant RemoteProjectDirectoryDialog
  participant MakaBridge
  participant ProjectManagementService
  participant HostProjectDirectoryAuthority
  participant ProjectCatalog

  User->>RemoteProjectDirectoryDialog: Open remote directory picker
  RemoteProjectDirectoryDialog->>MakaBridge: Request roots and directory entries
  MakaBridge->>ProjectManagementService: Forward directory request
  ProjectManagementService->>HostProjectDirectoryAuthority: Query validated path
  HostProjectDirectoryAuthority-->>ProjectManagementService: Return directory page
  ProjectManagementService-->>RemoteProjectDirectoryDialog: Return entries
  User->>RemoteProjectDirectoryDialog: Register selected directory
  RemoteProjectDirectoryDialog->>MakaBridge: Register directory
  MakaBridge->>ProjectManagementService: Forward registration
  ProjectManagementService->>HostProjectDirectoryAuthority: Resolve directory path
  HostProjectDirectoryAuthority->>ProjectCatalog: Register resolved path within root
  ProjectCatalog-->>RemoteProjectDirectoryDialog: Return registered project
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding remote project registration through the Runtime Host.
Description check ✅ Passed The description includes the required summary, issue reference, verification results, AI-use declaration, checklist, and behavior-change statement.
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.
Ai Use Disclosure ✅ Passed The PR selects substantive generative use, names OpenAI Codex and its scope, and all 11 introduced commits contain exactly one matching standalone Generated-by trailer.
✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch feat/remote-project-registration
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/remote-project-registration

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

@M4n5ter

M4n5ter commented Aug 17, 2026

Copy link
Copy Markdown
Member Author

@M4n5ter
M4n5ter marked this pull request as ready for review August 17, 2026 08:13
@hqhq1025
hqhq1025 requested a lite review from Copilot August 17, 2026 08:13

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

Caution

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

⚠️ Outside diff range comments (1)
apps/desktop/src/renderer/app-shell.tsx (1)

1908-1912: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not expose relink for host-directory-only Hosts.

onRelink is enabled when chooseHostDirectory is true. useNewTaskTarget.relinkProject exits unless chooseClientDirectory is true. A Host that supports only remote directory selection shows an enabled Relink action that does nothing. Keep onAdd enabled for either capability, but provide onRelink only when chooseClientDirectory is true.

Proposed fix
-        ...(host.capabilities.chooseClientDirectory || host.capabilities.chooseHostDirectory
-          ? {
-              onAdd: () => void newTask.addProject(host),
-              onRelink: (projectId: string) => void newTask.relinkProject(host, projectId),
-            }
-          : {}),
+        ...(host.capabilities.chooseClientDirectory || host.capabilities.chooseHostDirectory
+          ? { onAdd: () => void newTask.addProject(host) }
+          : {}),
+        ...(host.capabilities.chooseClientDirectory
+          ? { onRelink: (projectId: string) => void newTask.relinkProject(host, projectId) }
+          : {}),
🧹 Nitpick comments (2)
packages/runtime-host/src/__tests__/project-directory-authority.test.ts (1)

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

Consider covering cursor continuation.

The test covers roots, hidden directories, symlink exclusion, and registration. It does not cover directory_list_continue. The paging code in query computes start from the cursor and derives nextCursor from the last accepted entry, so a regression there stays invisible. A case with enough sibling folders to force a second page, asserting that concatenated pages equal the full sorted list with no duplicate or missing name, would protect that behavior.

apps/desktop/src/main/runtime-host-client.ts (1)

603-614: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Route this mutation through #mutateProject.

Every other project mutation on this class goes through #mutateProject. This one calls request directly. The input type ProjectCatalogMutateInput already includes the register_directory variant, so the helper accepts it. Using it keeps one call path for project mutations.

♻️ Proposed refactor
   async registerProjectDirectory(
     rootId: string,
     segments: readonly string[],
   ): Promise<ProjectCatalogProject> {
     return this.#projectForMutation(
-      await this.request("project.catalog.mutate", {
-        kind: "register_directory",
-        rootId,
-        segments,
-      }),
+      await this.#mutateProject({ kind: "register_directory", rootId, segments }),
     );
   }

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 574fd81b-26b2-4f5b-860d-5652b0402349

📥 Commits

Reviewing files that changed from the base of the PR and between 9607a86 and 3595150.

📒 Files selected for processing (25)
  • apps/desktop/src/main/__tests__/app-shell-project-actions.test.ts
  • apps/desktop/src/main/__tests__/project-management-service.test.ts
  • apps/desktop/src/main/app-ipc-main.ts
  • apps/desktop/src/main/project-management-service.ts
  • apps/desktop/src/main/runtime-host-boot.ts
  • apps/desktop/src/main/runtime-host-client.ts
  • apps/desktop/src/main/runtime-host-project-catalog.ts
  • apps/desktop/src/preload/bridge-contract.d.ts
  • apps/desktop/src/preload/preload.ts
  • apps/desktop/src/renderer/app-shell.tsx
  • apps/desktop/src/renderer/locales/shell-copy.ts
  • apps/desktop/src/renderer/remote-project-directory-dialog.tsx
  • apps/desktop/src/renderer/settings/projects-settings-page.tsx
  • apps/desktop/src/renderer/styles/composer.css
  • apps/desktop/src/renderer/use-new-task-target.ts
  • apps/desktop/src/renderer/use-project-context.ts
  • docs/astryx-surface-file-inventory.md
  • docs/astryx-surface-file-inventory.paths
  • packages/runtime-host/src/__tests__/project-catalog-protocol.test.ts
  • packages/runtime-host/src/__tests__/project-directory-authority.test.ts
  • packages/runtime-host/src/protocol/index.ts
  • packages/runtime-host/src/protocol/project-catalog.ts
  • packages/runtime-host/src/server/project-catalog-coordinator.ts
  • packages/runtime-host/src/server/project-directory-authority.ts
  • packages/ui/src/workspace-picker.tsx

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment thread apps/desktop/src/renderer/remote-project-directory-dialog.tsx
Comment thread docs/astryx-surface-file-inventory.md

Copilot AI 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.

Pull request overview

Adds remote Runtime Host-side project directory browsing + registration so Desktop can register a new Project on a remote Host without ever handling arbitrary Host paths (only opaque root IDs + validated path segments). This fits into the ongoing Runtime Host hardening work by keeping Host path resolution and project registration authority on the Host while exposing a constrained UX to remote clients.

Changes:

  • Introduces a HostProjectDirectoryAuthority and extends the project catalog protocol to support directory root + paged directory listing + “register selected directory” mutation.
  • Adds a new Desktop remote directory picker dialog and wires it into both the new-task workspace picker flow and Projects settings.
  • Updates Desktop/main IPC and runtime-host client/catalog plumbing to support directory queries + registration.

Reviewed changes

Copilot reviewed 24 out of 25 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/ui/src/workspace-picker.tsx Adjusts workspace picker actions to better support per-group add/no-project options and retry.
packages/runtime-host/src/server/project-directory-authority.ts Adds Host-side constrained directory browsing and registration path resolution under a published root.
packages/runtime-host/src/server/project-catalog-coordinator.ts Routes new directory query/mutation kinds through the project catalog coordinator and adds error mapping.
packages/runtime-host/src/protocol/project-catalog.ts Extends protocol types/limits and codecs for directory browsing + register_directory mutation.
packages/runtime-host/src/protocol/index.ts Bumps compatibility epoch to reflect protocol changes.
packages/runtime-host/src/tests/project-directory-authority.test.ts Adds Host authority tests for root containment and symlink escape prevention.
packages/runtime-host/src/tests/project-catalog-protocol.test.ts Adds protocol/grant tests to ensure remote directory selection stays path-free and traversal is rejected.
docs/astryx-surface-file-inventory.paths Adds the new remote directory dialog surface to Astryx inventory.
docs/astryx-surface-file-inventory.md Updates Astryx inventory totals and includes the new dialog entry.
apps/desktop/src/renderer/use-project-context.ts Extends DesktopProjectCapabilities with chooseHostDirectory default.
apps/desktop/src/renderer/use-new-task-target.ts Adds remote directory picker state + acceptance flow for registered projects in new-task target selection.
apps/desktop/src/renderer/styles/composer.css Adds styling for the remote project directory dialog layout.
apps/desktop/src/renderer/settings/projects-settings-page.tsx Adds “Add project” behavior that opens remote directory picker when supported.
apps/desktop/src/renderer/remote-project-directory-dialog.tsx New dialog UI for browsing host-published directories and registering a selected folder.
apps/desktop/src/renderer/locales/shell-copy.ts Adds localized copy strings for the remote directory dialog UI.
apps/desktop/src/renderer/app-shell.tsx Wires the remote directory dialog into the main shell overlay flow for new-task project actions.
apps/desktop/src/preload/preload.ts Exposes new directory roots/list/register APIs on the Maka bridge.
apps/desktop/src/preload/bridge-contract.d.ts Adds types + bridge method signatures for remote directory selection.
apps/desktop/src/main/runtime-host-project-catalog.ts Extends the runtime-host project catalog adapter with directory browsing + registration functions.
apps/desktop/src/main/runtime-host-client.ts Implements directory roots/listing/register operations against the Host project catalog protocol.
apps/desktop/src/main/runtime-host-boot.ts Wires directory catalog into project management service and toggles capability flags for local vs remote.
apps/desktop/src/main/project-management-service.ts Adds directory roots/list/register endpoints (Host-only) and IPC input validation for directory requests.
apps/desktop/src/main/app-ipc-main.ts Adds IPC handlers for directory roots/list/register project directory operations.
apps/desktop/src/main/tests/project-management-service.test.ts Adds coverage for remote Host directory actions and ensures client-local directory picker isn’t used remotely.
apps/desktop/src/main/tests/app-shell-project-actions.test.ts Updates capability expectations to include chooseHostDirectory.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/desktop/src/main/runtime-host-client.ts

@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


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 50b39d04-2d75-43c1-909d-59f76645f929

📥 Commits

Reviewing files that changed from the base of the PR and between 3595150 and 8798e89.

📒 Files selected for processing (19)
  • apps/desktop/src/main/__tests__/project-management-service.test.ts
  • apps/desktop/src/preload/bridge-contract.d.ts
  • apps/desktop/src/renderer/remote-project-directory-dialog.tsx
  • apps/desktop/src/renderer/styles/composer.css
  • docs/architecture/runtime-host-architecture.md
  • docs/architecture/runtime-host-architecture.zh-CN.md
  • docs/runtime-host-remote-access.md
  • docs/runtime-host-remote-access.zh-CN.md
  • packages/cli/src/__tests__/runtime-host-operator-command.test.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/runtime-host-cli.ts
  • packages/cli/src/runtime-host-service-command.ts
  • packages/runtime-host/src/__tests__/project-catalog-protocol.test.ts
  • packages/runtime-host/src/__tests__/project-directory-authority.test.ts
  • packages/runtime-host/src/protocol/project-catalog.ts
  • packages/runtime-host/src/server/execution-composition-factory.ts
  • packages/runtime-host/src/server/execution-composition.ts
  • packages/runtime-host/src/server/execution-service.ts
  • packages/runtime-host/src/server/project-directory-authority.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/desktop/src/renderer/styles/composer.css
  • packages/runtime-host/src/tests/project-catalog-protocol.test.ts
  • packages/runtime-host/src/tests/project-directory-authority.test.ts
  • apps/desktop/src/renderer/remote-project-directory-dialog.tsx
  • packages/runtime-host/src/protocol/project-catalog.ts
  • apps/desktop/src/main/tests/project-management-service.test.ts
  • apps/desktop/src/preload/bridge-contract.d.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment thread packages/runtime-host/src/server/project-directory-authority.ts

Copilot AI 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.

Pull request overview

Copilot reviewed 35 out of 36 changed files in this pull request and generated no new comments.

Suppressed comments (4)

apps/desktop/src/renderer/remote-project-directory-dialog.tsx:128

  • register() can still call onRegistered after the dialog has been closed or the Host has changed (the component stays mounted, and there is no request-sequence guard like navigate() / selectRoot()). This can register a project even if the user hit Cancel, and can update state for a stale Host.
  async function register(): Promise<void> {
    const host = props.host;
    if (!host || !root || registering) return;
    setRegistering(true);
    setError(undefined);
    try {
      props.onRegistered(await window.maka.projects.registerDirectory({
        rootId: root.id,
        segments,
      }, host));
    } catch (cause) {
      setError(localizedShellErrorMessage(cause, copy.projectUpdateFailedFallback, locale));
    } finally {
      setRegistering(false);
    }

apps/desktop/src/main/project-management-service.ts:221

  • requireDirectoryInput() only checks basic shapes. Because this is an IPC boundary (renderer -> main), it should defensively validate rootId/segments against the same constraints as the Runtime Host protocol (max segments, per-segment size, and forbidding '.', '..', and path separators). Without this, a compromised renderer can send arbitrarily large/invalid payloads and force expensive encoding / repeated protocol failures.
function requireDirectoryInput(value: unknown): {
  readonly rootId: string;
  readonly segments: readonly string[];
} {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    throw new TypeError('Invalid project directory');
  }
  const input = value as { rootId?: unknown; segments?: unknown };
  if (
    typeof input.rootId !== 'string' ||
    !Array.isArray(input.segments) ||
    !input.segments.every((segment) => typeof segment === 'string')
  ) {
    throw new TypeError('Invalid project directory');
  }
  return { rootId: input.rootId, segments: input.segments };

apps/desktop/src/renderer/locales/shell-copy.ts:743

  • The zh-CN label for hiding hidden folders is awkward/duplicated ("隐藏隐藏目录"). A clearer counterpart to "显示隐藏目录" is "不显示隐藏目录".
      remoteDirectoryShowHidden: '显示隐藏目录',
      remoteDirectoryHideHidden: '隐藏隐藏目录',

packages/cli/src/cli.ts:130

  • The help text for --project-root doesn't mention the absolute-path requirement, but parseProjectRoot() rejects non-absolute paths. Surfacing this constraint in --help makes the option self-explanatory.
    '  --project-root <label>=<path> Publish a project directory root (repeatable)',

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

Caution

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

⚠️ Outside diff range comments (1)
packages/runtime-host/src/server/project-directory-authority.ts (1)

168-171: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Use non-derivable IDs for named roots.

Lines 168-171 derive each ID from an unkeyed hash of the absolute root path. A root-list client can hash plausible paths offline and recover configured filesystem locations. This conflicts with opaque root IDs.

Generate a random ID when the authority is constructed. Keep it only in the authority root map.

As per path instructions, review the diff adversarially against the problem it claims to solve.

Source: Path instructions


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1db1e8a8-ea0b-40b5-9846-5e3bcd6d65b8

📥 Commits

Reviewing files that changed from the base of the PR and between 8798e89 and 9f8211c.

📒 Files selected for processing (14)
  • apps/desktop/src/main/runtime-host-client.ts
  • apps/desktop/src/renderer/app-shell.tsx
  • apps/desktop/src/renderer/locales/shell-copy.ts
  • apps/desktop/src/renderer/remote-project-directory-dialog.tsx
  • apps/desktop/src/renderer/use-new-task-target.ts
  • packages/cli/src/cli.ts
  • packages/runtime-host/src/__tests__/project-catalog-coordinator.test.ts
  • packages/runtime-host/src/__tests__/project-directory-authority.test.ts
  • packages/runtime-host/src/protocol/project-catalog.ts
  • packages/runtime-host/src/server/project-catalog-coordinator.ts
  • packages/runtime-host/src/server/project-directory-authority.ts
  • packages/storage/src/__tests__/project-catalog.test.ts
  • packages/storage/src/project-catalog-authority.ts
  • packages/storage/src/project-catalog.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/cli/src/cli.ts
  • apps/desktop/src/renderer/app-shell.tsx
  • apps/desktop/src/main/runtime-host-client.ts
  • apps/desktop/src/renderer/use-new-task-target.ts
  • apps/desktop/src/renderer/locales/shell-copy.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.

Comment thread apps/desktop/src/renderer/remote-project-directory-dialog.tsx
Comment thread packages/runtime-host/src/server/project-directory-authority.ts Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 39 out of 40 changed files in this pull request and generated no new comments.

Suppressed comments (1)

apps/desktop/src/renderer/remote-project-directory-dialog.tsx:174

  • aria-label for the breadcrumb <nav> is set to copy.currentProject (localized as “Current project”), but this UI represents the current directory path. This label will be incorrect for screen readers and should have a dedicated localized string (e.g. “Current folder” / “当前文件夹”).
          <LayoutContent padding={4}>
            <div className="remoteProjectDirectoryBody">
              <nav className="remoteProjectDirectoryBreadcrumbs" aria-label={copy.currentProject}>
                {roots.length > 1 ? (

@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 (1)
packages/runtime-host/src/__tests__/project-directory-authority.test.ts (1)

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

Do not hard-code opaque root ID values unless the protocol guarantees them.

root-1 and root-2 lock this test to the current allocation format. They do not verify path-independent stability. Assert that IDs are opaque, unique, and stable for equivalent published roots with different absolute paths. Keep the exact values only if the protocol explicitly guarantees these strings.

As per path instructions, tests must protect observable behavior and must not assert implementation details.

Source: Path instructions


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 42afad22-d272-461b-961b-9ed6b7a340f6

📥 Commits

Reviewing files that changed from the base of the PR and between 9f8211c and 158a10f.

📒 Files selected for processing (6)
  • apps/desktop/src/main/runtime-host-client.ts
  • apps/desktop/src/renderer/locales/shell-copy.ts
  • apps/desktop/src/renderer/remote-project-directory-dialog.tsx
  • packages/runtime-host/src/__tests__/project-directory-authority.test.ts
  • packages/runtime-host/src/server/project-catalog-coordinator.ts
  • packages/runtime-host/src/server/project-directory-authority.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/desktop/src/renderer/locales/shell-copy.ts
  • apps/desktop/src/main/runtime-host-client.ts
  • apps/desktop/src/renderer/remote-project-directory-dialog.tsx
  • packages/runtime-host/src/server/project-directory-authority.ts
  • packages/runtime-host/src/server/project-catalog-coordinator.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Copilot AI 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.

Pull request overview

Copilot reviewed 39 out of 40 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/runtime-host/src/server/project-directory-authority.ts:89

  • #resolveDirectory throws "Project directory is outside the published root" both when the resolved path escapes the root and when the path is inside the root but is not a directory. That makes invalid-request responses misleading (e.g., selecting a file under the root would report an out-of-root error). Split the checks so the error message matches the actual failure mode.

M4n5ter added 10 commits August 18, 2026 09:26
Allow remote Desktop targets to browse Host-published directory roots and register a selected directory without exposing arbitrary Host paths to the Client. Keep local project selection on the native OS picker and route remote registration through the existing Project Catalog authority.

Generated-by: OpenAI Codex
Render project actions inside their owning Host group so remote registration remains reachable even when another Host is selected. Keep the remote home view focused by omitting hidden directories from enumeration.

Generated-by: OpenAI Codex
Use Astryx controls for every directory and breadcrumb action, then register the new dialog in the generated surface inventory. This keeps the remote picker at zero surface blockers.

Generated-by: OpenAI Codex
Enumerate every contained directory published by the Host, including dot-prefixed names. Visibility is a presentation concern and must not silently narrow Project registration authority.

Generated-by: OpenAI Codex
Keep all Host directories reachable while hiding dot-prefixed entries by default in the Desktop picker. Users can reveal them explicitly without changing the Host authorization boundary.

Generated-by: OpenAI Codex
Replace the labeled switch with an accessible eye icon button while preserving the same explicit show and hide behavior.

Generated-by: OpenAI Codex
Keep the picker focused on navigation and selection. Remove explanatory implementation details that do not help users choose a project directory.

Generated-by: OpenAI Codex
Preserve the service user's home directory as the default while allowing operators to replace it with a bounded, named root allowlist. Remote Clients browse only opaque published roots, and Desktop can switch between them without learning unrestricted Host paths.

Generated-by: OpenAI Codex
Validate the final canonical Project path against its published root and keep pre-commit directory failures out of the Host drain path. Bound directory traversal and keep picker retries and late completions scoped to their exact Host.

Generated-by: OpenAI Codex
Keep optional directory browsing from blocking Host startup, make published root identifiers path-independent, and bound each enumeration before sorting. Align the Desktop picker’s navigation and retry behavior with the exact Host operation.

Generated-by: OpenAI Codex
Report non-directory selections separately from root escapes, and keep root identity tests focused on the protocol's uniqueness contract instead of its current allocation format.

Generated-by: OpenAI Codex
@M4n5ter
M4n5ter force-pushed the feat/remote-project-registration branch from 065dc74 to 0c47963 Compare August 18, 2026 01:29
@M4n5ter

M4n5ter commented Aug 18, 2026

Copy link
Copy Markdown
Member Author

I have manually reviewed the changes in this PR (the CI issue was not introduced by the changes in this PR, and has already been reported as #3177), take full responsibility for this, and decide to merge it.

@M4n5ter
M4n5ter merged commit be3fdd1 into main Aug 18, 2026
11 of 12 checks passed
@M4n5ter
M4n5ter deleted the feat/remote-project-registration branch August 18, 2026 01:43
Astro-Han added a commit to Astro-Han/maka-agent that referenced this pull request Aug 19, 2026
`goal.arm` is a new wire operation, so a client that has it and a Host that
does not are no longer safely interoperable. Without a new epoch the pair
completes the handshake, the client offers Set Goal, and the first arm reaches
an older decoder as an unknown operation — a protocol error that tears the
connection down instead of refusing the pair up front and routing the user to
the Host upgrade path.

The epoch is the boundary the repository already uses for this: apache#3145 advanced
it for a new operation and apache#3165 advanced it merely for removing catalog
filters. Handshake fixtures name deliberately stale epochs to exercise
rejection, so they stay as they are.

Generated-by: Claude Code
Astro-Han added a commit to Astro-Han/maka-agent that referenced this pull request Aug 19, 2026
`goal.arm` is a new wire operation, so a client that has it and a Host that
does not are no longer safely interoperable. Without a new epoch the pair
completes the handshake, the client offers Set Goal, and the first arm reaches
an older decoder as an unknown operation — a protocol error that tears the
connection down instead of refusing the pair up front and routing the user to
the Host upgrade path.

The epoch is the boundary the repository already uses for this: apache#3145 advanced
it for a new operation and apache#3165 advanced it merely for removing catalog
filters. Handshake fixtures name deliberately stale epochs to exercise
rejection, so they stay as they are.

Generated-by: Claude Code
Astro-Han added a commit to Astro-Han/maka-agent that referenced this pull request Aug 19, 2026
`goal.arm` is a new wire operation, so a client that has it and a Host that
does not are no longer safely interoperable. Without a new epoch the pair
completes the handshake, the client offers Set Goal, and the first arm reaches
an older decoder as an unknown operation — a protocol error that tears the
connection down instead of refusing the pair up front and routing the user to
the Host upgrade path.

The epoch is the boundary the repository already uses for this: apache#3145 advanced
it for a new operation and apache#3165 advanced it merely for removing catalog
filters. Handshake fixtures name deliberately stale epochs to exercise
rejection, so they stay as they are.

Generated-by: Claude Code
Astro-Han added a commit to Astro-Han/maka-agent that referenced this pull request Aug 20, 2026
`goal.arm` is a new wire operation, so a client that has it and a Host that
does not are no longer safely interoperable. Without a new epoch the pair
completes the handshake, the client offers Set Goal, and the first arm reaches
an older decoder as an unknown operation — a protocol error that tears the
connection down instead of refusing the pair up front and routing the user to
the Host upgrade path.

The epoch is the boundary the repository already uses for this: apache#3145 advanced
it for a new operation and apache#3165 advanced it merely for removing catalog
filters. Handshake fixtures name deliberately stale epochs to exercise
rejection, so they stay as they are.

Generated-by: Claude Code
Astro-Han added a commit to Astro-Han/maka-agent that referenced this pull request Aug 20, 2026
`goal.arm` is a new wire operation, so a client that has it and a Host that
does not are no longer safely interoperable. Without a new epoch the pair
completes the handshake, the client offers Set Goal, and the first arm reaches
an older decoder as an unknown operation — a protocol error that tears the
connection down instead of refusing the pair up front and routing the user to
the Host upgrade path.

The epoch is the boundary the repository already uses for this: apache#3145 advanced
it for a new operation and apache#3165 advanced it merely for removing catalog
filters. Handshake fixtures name deliberately stale epochs to exercise
rejection, so they stay as they are.

Generated-by: Claude Code
Astro-Han added a commit to Astro-Han/maka-agent that referenced this pull request Aug 20, 2026
`goal.arm` is a new wire operation, so a client that has it and a Host that
does not are no longer safely interoperable. Without a new epoch the pair
completes the handshake, the client offers Set Goal, and the first arm reaches
an older decoder as an unknown operation — a protocol error that tears the
connection down instead of refusing the pair up front and routing the user to
the Host upgrade path.

The epoch is the boundary the repository already uses for this: apache#3145 advanced
it for a new operation and apache#3165 advanced it merely for removing catalog
filters. Handshake fixtures name deliberately stale epochs to exercise
rejection, so they stay as they are.

Generated-by: Claude Code
Astro-Han added a commit to Astro-Han/maka-agent that referenced this pull request Aug 20, 2026
`goal.arm` is a new wire operation, so a client that has it and a Host that
does not are no longer safely interoperable. Without a new epoch the pair
completes the handshake, the client offers Set Goal, and the first arm reaches
an older decoder as an unknown operation — a protocol error that tears the
connection down instead of refusing the pair up front and routing the user to
the Host upgrade path.

The epoch is the boundary the repository already uses for this: apache#3145 advanced
it for a new operation and apache#3165 advanced it merely for removing catalog
filters. Handshake fixtures name deliberately stale epochs to exercise
rejection, so they stay as they are.

Generated-by: Claude Code
Astro-Han added a commit to Astro-Han/maka-agent that referenced this pull request Aug 20, 2026
`goal.arm` is a new wire operation, so a client that has it and a Host that
does not are no longer safely interoperable. Without a new epoch the pair
completes the handshake, the client offers Set Goal, and the first arm reaches
an older decoder as an unknown operation — a protocol error that tears the
connection down instead of refusing the pair up front and routing the user to
the Host upgrade path.

The epoch is the boundary the repository already uses for this: apache#3145 advanced
it for a new operation and apache#3165 advanced it merely for removing catalog
filters. Handshake fixtures name deliberately stale epochs to exercise
rejection, so they stay as they are.

Generated-by: Claude Code
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.

2 participants