Skip to content

Route team config through project service - #314

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

Route team config through project service#314
TraderSamwise merged 4 commits into
masterfrom
chore/core-sidecar-next-39

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • add project-service team config routes and shared app API wrappers
  • route daemon/core text and installed shim team commands through the service
  • update ownership docs and tests for the no-Node installed path

Verification

  • yarn vitest run src/metadata-server.test.ts src/daemon.test.ts src/installed-shim.test.ts src/core-command-ownership.test.ts
  • yarn tsc --noEmit
  • yarn lint
  • yarn build

Summary by CodeRabbit

  • New Features

    • Added project-based team configuration commands for viewing, initializing, and managing roles.
    • Introduced support for setting a default team role and updating role details from the CLI.
  • Bug Fixes

    • Team commands now use centralized project API endpoints, improving consistency across local and daemon-backed flows.
    • Role changes and default-role updates are reflected immediately in team config responses.
  • Tests

    • Expanded coverage for team command routing, API behavior, and daemon/project-service integration.

@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 4:48am

@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: 31 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: 8d909fac-4742-4e46-8da2-3f92c03d2b72

📥 Commits

Reviewing files that changed from the base of the PR and between fd970c6 and d666b91.

📒 Files selected for processing (6)
  • src/core-text.ts
  • src/daemon.test.ts
  • src/daemon.ts
  • src/installed-shim.test.ts
  • src/metadata-server.test.ts
  • src/metadata-server.ts
📝 Walkthrough

Walkthrough

Introduces a project-service-backed team role configuration feature: new API contract types and routes, MetadataServer storage/HTTP handlers, daemon core-text routing, CLI rewrite from local config to project API calls, an installed shim team command, client API wrappers, and supporting tests/docs.

Changes

Team role configuration feature

Layer / File(s) Summary
Team API contract and route coverage
src/project-api-contract.ts, app/lib/project-api-route-coverage.ts
Adds TeamRoleConfig, TeamConfig, TeamConfigResponse types and team route group to PROJECT_API_ROUTES/PROJECT_API_VIEWS; registers matching client-api coverage entries.
MetadataServer team config storage and HTTP handlers
src/metadata-server.ts, src/metadata-server.test.ts
Implements read/init/add/remove/set-default role operations persisted to .aimux/team.json, wires GET/POST routes in handleRoute, and adds an end-to-end HTTP test.
Core command contract and text rendering
src/core-command-contract.ts, src/core-text.ts, src/core-command-ownership.test.ts
Adds teamAddText/teamDefaultText/teamInitText/teamRemoveText/teamShowText contract routes, CoreTeamTextPayload type, rendering helpers for human-readable output, and ownership test mappings.
Daemon routing of team text endpoints
src/daemon.ts, src/daemon.test.ts
Wires LOCAL_CLI_TEXT_ROUTES and routeRequest handlers that fetch/mutate team config via the project service and render text output, with teamPayloadFromResult and per-action route helpers, validated by a new daemon test.
Client API wrappers
app/lib/api.ts
Adds getTeamConfig, initTeamConfig, addTeamRole, removeTeamRole, setDefaultTeamRole functions delegating to callProjectJson.
CLI team command rewrite
src/main.ts
Replaces local team config file handling with project-scoped API calls for team show/add/remove/default/init, adding TeamCommandOptions, buildTeamCliPayload, printTeamShow, printTeamInit.
Installed shim team command dispatch
scripts/installed-aimux-shim.sh, src/installed-shim.test.ts
Adds aimux_try_team() subdispatcher and top-level team case, plus tests for daemon routing and fallback behavior.
Documentation updates
docs/command-ownership-inventory.md, docs/core-sidecar-north-star.md
Updates ownership rows for aimux team ... and adds a north-star bullet for team role config commands.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Shim as installed-aimux-shim.sh
  participant Daemon
  participant ProjectService as MetadataServer

  User->>Shim: aimux team add role ...
  Shim->>Daemon: GET /core/team/add-text
  Daemon->>ProjectService: POST team.addRole { role, description, reviewedBy, canEdit }
  ProjectService->>ProjectService: mutate roles/defaultRole, saveTeamConfig
  ProjectService-->>Daemon: TeamConfigResponse
  Daemon->>Daemon: teamPayloadFromResult + renderCoreTeamAddLines
  Daemon-->>Shim: plain text response
  Shim-->>User: print output
Loading

Possibly related PRs

  • TraderSamwise/aimux#8: The new getTeamConfig/initTeamConfig/addTeamRole/removeTeamRole/setDefaultTeamRole wrappers in app/lib/api.ts depend on the callProjectJson helper introduced in this PR.
  • TraderSamwise/aimux#184: Both PRs extend the shared PROJECT_API_ROUTES contract, with this PR adding the /team/* route group and types.
  • TraderSamwise/aimux#308: Both PRs modify daemon LOCAL_CLI_TEXT_ROUTES/routeRequest to add new CLI-through-daemon text endpoints.
🚥 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: routing team config through the project service.
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-39

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

🧹 Nitpick comments (5)
src/metadata-server.ts (1)

1282-1296: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Fallback default role is a hardcoded magic string that can end up dangling.

If the removed role is the last remaining role (and is also the current defaultRole), config.defaultRole falls back to "coder" even though "coder" no longer exists in config.roles. Deriving the fallback from getDefaultTeamConfig().defaultRole (or leaving defaultRole unset when roles is empty) would avoid both the magic-string duplication and the dangling reference.

🤖 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/metadata-server.ts` around lines 1282 - 1296, The fallback handling in
removeTeamRole is using a hardcoded "coder" default that can point to a deleted
role. Update the defaultRole reassignment in removeTeamRole to derive the
fallback from getDefaultTeamConfig().defaultRole or otherwise leave it unset
when config.roles becomes empty, and keep the logic aligned with
loadTeamConfig/saveTeamConfig so defaultRole always references an existing role.
src/core-text.ts (2)

86-92: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Optional role weakens type safety for action-specific renderers.

role is optional here, but renderCoreTeamAddLines/renderCoreTeamRemoveLines/renderCoreTeamDefaultLines (Lines 359-369) assume it's always set. Nothing in the type system enforces that callers of teamPayloadFromResult pass role for those actions, so a future omission would silently render Role "undefined" saved. instead of failing at compile time.

Consider a discriminated payload (e.g. a variant requiring role: string for add/remove/default) to make the contract explicit.

🤖 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 86 - 92, The team payload contract in
teamPayloadFromResult is too loose because role is optional even though
renderCoreTeamAddLines, renderCoreTeamRemoveLines, and
renderCoreTeamDefaultLines require it for action-specific rendering. Update the
payload typing to use a discriminated union or equivalent variant that requires
role for the add/remove/default cases, and keep teamPayloadFromResult aligned
with those required fields so missing role becomes a compile-time error instead
of rendering undefined.

359-369: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Guard against missing role before rendering.

These functions interpolate payload.role (optional) directly into user-facing output. If a caller forgets to supply role, the message silently becomes Role "undefined" saved. with no error.

🛡️ Proposed defensive check
 export function renderCoreTeamAddLines(payload: CoreTeamTextPayload): string[] {
+  if (!payload.role) return ["Error: role is required for this operation."];
   return [`Role "${payload.role}" saved.`];
 }

Apply similarly to renderCoreTeamRemoveLines and renderCoreTeamDefaultLines, or better, enforce role: string via a discriminated payload type as noted above.

🤖 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 359 - 369, The rendering helpers are using
payload.role without guarding against it being missing, which can produce
user-facing text like undefined; update renderCoreTeamAddLines and apply the
same fix in renderCoreTeamRemoveLines and renderCoreTeamDefaultLines by either
validating role before interpolation or tightening the payload type so role is
required, and ensure the functions fail fast or handle the absence explicitly
rather than rendering an undefined value.
src/daemon.ts (1)

1583-1653: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Team mutation routes skip the standard mutation timeout.

teamInitTextRoute and teamRoleTextRoute call postProjectServiceJson without { timeoutMs: CLI_PROJECT_MUTATION_TIMEOUT_MS }, unlike other project-service mutation routes in this file (threadOpenTextRoute, handoffMutationTextRoute, taskMutationTextRoute, worktreePathTextRoute, graveyardAgentTextRoute, reviewRequestChangesTextRoute). This falls back to the shorter default PROXY_TIMEOUT_MS, which could cause spurious timeout errors on slower team.json writes.

🔧 Proposed fix
   private async teamInitTextRoute(routeUrl: URL, body: unknown): Promise<DaemonRouteResponse> {
     const project = this.requiredParam(routeUrl, body, "project");
     if (typeof project !== "string") return project;
-    const result = await this.postProjectServiceJson(project, PROJECT_API_ROUTES.team.init, {});
+    const result = await this.postProjectServiceJson(project, PROJECT_API_ROUTES.team.init, {}, {
+      timeoutMs: CLI_PROJECT_MUTATION_TIMEOUT_MS,
+    });
     const payload = this.teamPayloadFromResult(result, "team init");
     const result = await this.postProjectServiceJson(project, input.routePath, {
       role,
       ...(input.extraBody ? input.extraBody(role) : {}),
-    });
+    }, { timeoutMs: CLI_PROJECT_MUTATION_TIMEOUT_MS });

Separately, verifying this new daemon routing end-to-end requires building and running against an installed daemon rather than source inspection alone.

[reliability_and_availability]

Based on path instructions: "For aimux runtime or CLI behavior, source-level validation is not enough: build, install the local release asset, and run aimux restart so the daemon, services, and dashboards pick up the updated bundle."

🤖 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 1583 - 1653, The team mutation routes are missing
the standard mutation timeout, so update `teamInitTextRoute` and
`teamRoleTextRoute` to pass the same `{ timeoutMs:
CLI_PROJECT_MUTATION_TIMEOUT_MS }` option used by other mutation helpers in this
file. Apply the change on the `postProjectServiceJson` calls in those methods so
`team.json` writes use the longer mutation timeout instead of the default proxy
timeout.

Source: Path instructions

src/installed-shim.test.ts (1)

745-774: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Fallback test doesn't confirm the staleness check actually ran.

The assertions here only verify the Node launcher was invoked with expected args/exit codes; they don't check curlLog for a daemon-status/health probe. If the shim's staleness-detection logic regressed to unconditionally launching Node for team commands, this test would still pass.

Consider adding a curlLog assertion (similar to the matching-daemon test) to confirm a health check actually occurred before the Node fallback.

🤖 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 745 - 774, The fallback test in the
team daemon staleness case only checks Node launcher invocation, so it can pass
even if the health probe never runs. Update this test to assert the
health/status check occurred by inspecting curlLog, similar to the
matching-daemon test, alongside the existing run() and nodeLog assertions in the
makeFixture-based scenario.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/metadata-server.ts`:
- Around line 1257-1280: The addTeamRole method in metadata-server should
preserve existing RoleConfig fields when updating an already-defined role
instead of overwriting them with only the provided inputs. Update the nextRole
निर्माण in addTeamRole so it falls back to config.roles[role]?.reviewedBy and
config.roles[role]?.canEdit when those inputs are omitted, similar to how
description already preserves the prior value, and keep the existing
saveTeamConfig and notifyProjectChanged flow unchanged.

---

Nitpick comments:
In `@src/core-text.ts`:
- Around line 86-92: The team payload contract in teamPayloadFromResult is too
loose because role is optional even though renderCoreTeamAddLines,
renderCoreTeamRemoveLines, and renderCoreTeamDefaultLines require it for
action-specific rendering. Update the payload typing to use a discriminated
union or equivalent variant that requires role for the add/remove/default cases,
and keep teamPayloadFromResult aligned with those required fields so missing
role becomes a compile-time error instead of rendering undefined.
- Around line 359-369: The rendering helpers are using payload.role without
guarding against it being missing, which can produce user-facing text like
undefined; update renderCoreTeamAddLines and apply the same fix in
renderCoreTeamRemoveLines and renderCoreTeamDefaultLines by either validating
role before interpolation or tightening the payload type so role is required,
and ensure the functions fail fast or handle the absence explicitly rather than
rendering an undefined value.

In `@src/daemon.ts`:
- Around line 1583-1653: The team mutation routes are missing the standard
mutation timeout, so update `teamInitTextRoute` and `teamRoleTextRoute` to pass
the same `{ timeoutMs: CLI_PROJECT_MUTATION_TIMEOUT_MS }` option used by other
mutation helpers in this file. Apply the change on the `postProjectServiceJson`
calls in those methods so `team.json` writes use the longer mutation timeout
instead of the default proxy timeout.

In `@src/installed-shim.test.ts`:
- Around line 745-774: The fallback test in the team daemon staleness case only
checks Node launcher invocation, so it can pass even if the health probe never
runs. Update this test to assert the health/status check occurred by inspecting
curlLog, similar to the matching-daemon test, alongside the existing run() and
nodeLog assertions in the makeFixture-based scenario.

In `@src/metadata-server.ts`:
- Around line 1282-1296: The fallback handling in removeTeamRole is using a
hardcoded "coder" default that can point to a deleted role. Update the
defaultRole reassignment in removeTeamRole to derive the fallback from
getDefaultTeamConfig().defaultRole or otherwise leave it unset when config.roles
becomes empty, and keep the logic aligned with loadTeamConfig/saveTeamConfig so
defaultRole always references an existing role.
🪄 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: 63eb197b-7366-494d-beed-ab54d70fdb81

📥 Commits

Reviewing files that changed from the base of the PR and between cc180bf and fd970c6.

📒 Files selected for processing (15)
  • app/lib/api.ts
  • app/lib/project-api-route-coverage.ts
  • docs/command-ownership-inventory.md
  • docs/core-sidecar-north-star.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
  • src/main.ts
  • src/metadata-server.test.ts
  • src/metadata-server.ts
  • src/project-api-contract.ts

Comment thread src/metadata-server.ts
@TraderSamwise
TraderSamwise merged commit 273b77d 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