Skip to content

feat(agents): add provider-neutral orchestration - #5632

Open
megascan wants to merge 13 commits into
pingdotgg:mainfrom
megascan:agent/native-agent-orchestration
Open

feat(agents): add provider-neutral orchestration#5632
megascan wants to merge 13 commits into
pingdotgg:mainfrom
megascan:agent/native-agent-orchestration

Conversation

@megascan

@megascan megascan commented Aug 7, 2026

Copy link
Copy Markdown

What Changed This PR adds a provider-neutral Agents system to T3 Code. It is one end-to-end feature, but it is intentionally not a small change: the implementation crosses contracts, persistence, server orchestration, MCP, all five provider adapters, web/desktop, mobile, tests, migrations, and documentation. The diff is 136 files, 17,408 additions, and 84 deletions. The implementation is ready for human review after automated review hardening. Suggested labels: enhancement, documentation, size:XXL, needs-triage, preview:web, and codex. The fork author does not have upstream triage permission, so GitHub rejected applying them directly. ### Agent profiles and Rules - Adds typed Agent profile and Rule contracts, including environment/project scope, content-addressed profile revisions, model selection, instructions, runtime/workspace/tool policy, hooks, delegation allowlists, provider requirements, and bounded budgets. - Stores environment profiles under T3-owned state and project profiles as explicit t3.json references. Project documents are contained to the canonical project root; the catalog does not recursively scan repositories. - Saves Markdown/YAML documents with compare-and-swap revision checks, atomic replacement, archive/restore, duplicate diagnostics, and backward-compatible decoding. - Adds deterministic Rules that can always apply, match workspace-relative file globs, or attach explicitly to profiles. - Adds chatSelectable (default true for existing documents). Turning it off makes a specialist “delegation only”: it disappears from new top-level chat choices but remains available to agent_list and orchestration. This is discovery policy, not authorization. ### Durable orchestration - Models child work as ordinary T3 threads with a pinned profile revision, not provider-native subagents. This preserves T3 history, remote access, and multi-device visibility. - Adds an event-sourced AgentRun domain with append-only events, transactional projection updates, immutable profile snapshots, parent-thread/lineage queries, revision-based waiting, deadlines, usage, results, follow-ups, cancellation, and integration state. - Adds migrations 39/40 for Agent run storage and the optional pinned profile on thread projections. These numbers were rebased onto current upstream migration 38. - Enforces hard lineage ceilings: depth 4, concurrency 8, 32 runs, and 120 minutes. Child budgets can reduce but cannot exceed the parent budget. - Adds a race-free wait path: subscribers attach before the durable revision read, so agents can wait for progress without sleep loops or polling. ### T3-owned Agent tools Adds a provider-portable MCP toolkit: - agent_list - agent_spawn - agent_status - agent_wait - agent_result - agent_send - agent_cancel - agent_integrate The toolkit is scoped from the invoking T3 thread/project. Launch is asynchronous and returns a durable run id; result reads are bounded and paginated. ### Provider-neutral boundary - Adds explicit Agent runtime capability declarations to Codex, Claude, Cursor, Grok, and OpenCode adapters. - Keeps provider-specific complexity at the adapter boundary. Catalog, orchestration, persistence, clients, and MCP handlers do not switch on provider kind. - Uses deny-by-default compatibility checks. A spawn is rejected when the selected adapter cannot honestly enforce a requested guarantee, such as exact native tool restriction, system-level instruction delivery, or requested usage accounting. - Future providers join the same path by declaring capabilities and supporting the existing T3 MCP injection boundary; they do not require a new Agent implementation. ### Shared and isolated workspaces - Shared runs use the invoking workspace and obey profile write-concurrency policy. - Isolated runs use a separate Git worktree and require explicit integration. - Integration verifies canonical paths and Git common-directory identity, refuses dirty targets and untracked child files, generates a bounded tracked binary patch, preflights it with git apply --check --3way, then applies it. Conflicts remain visible instead of being guessed through. ### Web, desktop, mobile, and remote behavior - Adds Settings → Agents with environment/project profile management, archive/restore, policy editing, Rules management, and the direct-chat visibility switch. - Adds a searchable Agent picker beside the web/desktop model picker. A currently pinned profile remains visible in its existing thread even if later marked delegation-only. - Adds native mobile settings plus Agent selection in new-task and existing-thread composer flows. Mobile uses the platform menu rather than a text-search popover. - Extends typed WebSocket RPCs and shared client runtime state, so local, LAN, relay, and tunnel clients talk to the host-owned catalog and durable runs rather than reading local files. - Adds user documentation, contributor architecture documentation, and glossary entries. ## Why ACP gives T3 a clean provider transport, but ACP providers do not inherently know they are running inside T3 and cannot reliably orchestrate one another. Provider-native subagent features also differ in naming, policy, lifetime, and availability. That makes a workflow such as “chat with an inexpensive coordinator, delegate architecture to one model, implementation to another, and review to a third” provider-specific and fragile. This design puts orchestration in the layer that actually has the necessary context: T3. It reuses T3 threads, WebSocket contracts, persistence, MCP injection, and provider adapters. The visible Agent is a reusable T3 policy profile; every child remains inspectable as normal T3 work. The result works with current providers without baking OpenGrok/GrokBuild behavior into the core, while giving future providers one explicit compatibility contract. ## UI Changes ### Before: no Agent settings surface Settings before Agents ### After: first-party profile and Rule management The selected specialist is marked delegation only; the host identifier is redacted from this public evidence image. Settings with Agent profiles and direct-chat visibility ### After: searchable picker beside the model picker Search filters the direct-chat profiles immediately. The delegation-only Terra specialist is intentionally absent while remaining available to orchestration through agent_list. Searchable Agent picker ### After: direct Agent selection is visible beside the model Selected Agent in the composer ### After: file-aware Rules use the same settings language File-aware Rule editor Short picker interaction recording Evidence is published on a separate fork branch so binary review artifacts do not enter this product diff. ## Verification - Original feature matrix over 28 focused files: 185/185 tests passed. - First post-review regression matrix over 21 focused files: 116/116 tests passed. - CodeRabbit response matrix over every modified test file: 105/105 tests passed. - Third review-hardening matrix over every newly modified test file: 94/94 tests passed. - Latest reviewer-response matrix across mobile, catalog, stores, Rules, prompt matching, orchestration, budgets, and terminal hooks: 45/45 tests passed. - Recovery-hardening runtime matrix across orchestration, deadlines, event retry, persistence compensation, Rules, and shared project-file coordination: 57/57 tests passed. - Latest web/mobile selection and compare-and-swap matrix: 29/29 tests passed. - Truthful provider-capability regressions for OpenCode, Cursor, and Grok: 3/3 tests passed. - Latest event-ordering, single-execution hook retry, async settings context, and active draft picker matrix: 43/43 tests passed. - Cross-surface readable settings validation matrix: 29/29 tests passed.

  • Collision-safe composer context regression: 2/2 tests passed. - Final paginated review-response matrix for mobile selection/settings, web mutation locking, and fail-closed result reads: 35/35 tests passed. Macroscope correctness and Effect conventions are green on 1062149af; Cursor Bugbot found no new issues; all 108/108 review threads are resolved. - Latest-main broad changed-test matrix: 318/320 tests passed. The two failures are unchanged upstream Windows-only limitations: a hard-coded /logs separator assertion and a symlink test blocked by local EPERM; all other 198 tests outside that server seam passed. - Contracts, shared runtime, server, web, and mobile typechecks: passed. - Whole-PR targeted lint and formatting: passed with zero diagnostics. - Web production build: passed. - Server bundle build: passed. - git diff --check: passed. - Rebased onto current upstream/main; the feature branch is thirteen commits ahead and zero commits behind. Integrated browser coverage used an isolated .t3 development environment and exercised: 1. creating multiple environment Agent profiles and a file-aware Rule; 2. preserving brace globs such as src/**/*.{ts,tsx} across save and reload; 3. searching and selecting a chat-selectable Agent directly beside the model picker; 4. confirming a delegation-only specialist is excluded from direct-chat search; 5. applying a profile's preferred model when available and falling back safely when unavailable; 6. archiving and restoring both a profile and a Rule without destructive deletion; 7. retaining an archived-but-pinned profile label on its existing durable thread; 8. opening a fresh draft with Choose agent instead of leaking the previous route's selection; 9. preserving the earlier real Grok 4.5 turn and selected profile across watcher restarts. Focused backend coverage additionally exercises prompt injection and pinned-profile continuity, child-run lifecycle and result retrieval, shared orchestration, isolated-worktree integration/refusal, compare-and-swap persistence, deadline handling, and provider capability rejection. ## Honest Scope and Known Limitations - During an early contributor-machine startup, migration 40 was applied to the developer's live T3 home before startup failed. The process was stopped, no feature records were intentionally written there, and every subsequent runtime/UI pass used an isolated .t3 home. This affected local contributor state only, not repository or production data. - This is a large architectural feature PR, despite being one product concern. It does not meet the repository preference for small contributions; that checklist item is intentionally left unchecked. - Agents are T3-managed child threads, not a wrapper around provider-native subagent APIs. This is deliberate, but it means provider-native team/agent UIs are not surfaced here. - chatSelectable is not an access-control boundary. Delegation policy and provider compatibility remain the execution gates. - Web/desktop has text search in the picker; mobile currently uses the native platform menu and does not provide text search. - Token and monetary budgets can only be enforced where the adapter reports the required usage. Profiles that require unsupported accounting are rejected rather than approximately enforced. - Isolated integration intentionally rejects untracked child files and dirty targets. It does not invent staging/merge decisions on the user's behalf. - Profile/Rule files are environment-local or repository-referenced. There is no cross-environment profile marketplace, cloud sync, or import/export workflow in this PR. - Catalog RPC responses intentionally cap profiles, Rules, and diagnostics at 100 each to bound WebSocket payloads. Oversized catalogs remain loadable and show an explicit truncation diagnostic, but entries after the first 100 are not selectable in this version. - The integrated UI pass covered web/desktop behavior in the real client. Mobile received focused unit coverage and a full TypeScript check, but was not exercised on a physical device or simulator in this pass. - I did not run a production-scale concurrency soak, relay/tunnel latency test, or accessibility screen-reader audit. The implementation bounds payloads and avoids broadcast profile bodies, but maintainers should treat performance and accessibility review as explicit draft-review work. - The server typecheck emits existing non-failing Effect style suggestions; there are no type errors. - On this Windows host, the full changed-test matrix retains two unrelated upstream test limitations: one assertion hard-codes a POSIX path separator, and one symlink-security test requires privileges not available to the current process. Both failing lines predate this branch and are unchanged by the PR. - The new provider capability assertions pass directly. Running the complete Cursor/Grok adapter files on this Windows host additionally hits their existing Unix .sh mock-wrapper EFTYPE limitation, and the complete OpenCode file hits the same privileged-symlink EPERM limitation noted above; Linux CI remains the authoritative full-adapter run. - Automated review raised terminal-hook cross-run concurrency as performance debt. Hooks intentionally remain inline in this PR because afterResult is part of the durable success/failure decision and provider events must remain ordered per thread. A safe improvement needs a keyed bounded scheduler with explicit drain/shutdown semantics; raw forking would make correctness worse. - Agent MCP toolkit groups are exposed to every provider session, but this is not the authorization boundary: spawn requires a selected profile and exact delegation allowlist, while lifecycle operations enforce project, thread, lineage, and run ownership. t3McpCapabilities remains a compatibility declaration rather than an ACL. ## Checklist - [ ] This PR is small and focused — it is one focused feature, but the end-to-end implementation is intentionally large. - [x] I explained what changed and why. - [x] I included before/after screenshots for the UI changes. - [x] I included a short video for the picker interaction. Implemented with GPT-5.6 Sol through the Codex harness in T3 Code.

Note

Add provider-neutral agent orchestration with profile/rule management UI and MCP toolkit

  • Introduces a full agent orchestration system: AgentRun event-sourced state machine, AgentRunRepository, deadline reactor, and AgentOrchestration service interface, persisted via migrations 39–40 (new projection_agent_runs, agent_run_events, and agent_profile_snapshots tables).
  • Adds AgentProfileStore and AgentRuleStore with compare-and-swap semantics, Markdown+YAML frontmatter serialization, per-workspace semaphore locking, and revision conflict errors.
  • Adds AgentCatalog to discover and lazily load profiles and rules from the filesystem, and AgentPromptResolver to compile prompts (with hook execution, rule matching, and context file extraction) before forwarding to the provider.
  • Adds resolveAgentRuntimeCompatibility to validate provider adapter capabilities against agent profile requirements; incompatible combinations fail early with a structured error in ProviderCommandReactor.
  • Exposes eight new WebSocket RPC endpoints (agentsCatalog, agentsGetProfile/SaveProfile/ArchiveProfile/RestoreProfile, agentsGetRule/SaveRule/ArchiveRule/RestoreRule) and an AgentToolkit MCP server with agent_list/spawn/status/wait/result/send/cancel/integrate tools.
  • Adds agent profile and rule settings UIs on web (/settings/agents) and mobile (SettingsAgents sheet screen), and integrates an AgentProfilePicker into the chat composer on both platforms.
  • Threads propagate a pinned agentProfile reference through orchestration events, projection, and queued outbox messages; the thread.turn-start-requested event can clear the pinned profile.
  • Risk: shell hooks execute subprocesses in the workspace root with platform-specific shells; output is truncated at 64 KiB but non-zero exits and timeouts produce blocking errors that fail the turn.

Macroscope summarized 1062149.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Added configurable Agents with reusable profiles, rules, hooks, delegation, budgets, and workspace options.
    • Added Agents settings on web and mobile for creating, editing, saving, archiving, and restoring profiles and rules.
    • Added agent selection to chat and mobile task composition, including profile-specific model defaults.
    • Added agent run monitoring, messaging, cancellation, results, and workspace integration.
    • Added MCP tools for managing and controlling agent runs.
  • Documentation
    • Added user and internal documentation covering Agents, profiles, rules, runs, compatibility, and safety.

Note

Medium Risk
Changes affect turn-start payloads, remote agent document persistence, and new server catalog/hook execution paths; mistakes could alter which instructions/models run or mishandle revision conflicts, though mobile is mostly UI/state over existing RPC contracts.

Overview
Mobile adds a first-party Settings → Agents flow and threads agent profile selection through new-task and existing-thread composers, drafts, and the outbox.

The new Settings Agents screen lets users pick environment/project context, browse profile and rule catalogs (with load/save/archive via remote commands), and edit compact drafts backed by agentProfile.logic / agentRule.logic (revision checks, schema validation, chat-selectable filtering). Navigation is registered as SettingsAgents with a Configuration row on the main settings screen.

Composer UX adds an Agent control pill next to model/options. It loads the catalog through useAgentProfileCatalog, lists only chat-selectable profiles (while keeping a pinned delegation-only profile visible), applies a profile’s default model when chosen, and passes agentProfile through resolveAgentProfileSelection into thread creation, thread.turn.start, queued messages, and persisted composer drafts (including explicit “No agent”).

Server (in this diff) introduces AgentCatalog (Markdown discovery, bounded RPC lists, project t3.json references), AgentHookRunner (workspace-contained context/shell hooks with timeouts), and AgentOrchestration service surface plus orchestration helpers/tests; the integration harness stubs AgentPromptResolver where profiles are unused.

Reviewed by Cursor Bugbot for commit 1062149. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Aug 7, 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
📝 Walkthrough

Walkthrough

Native agent orchestration is added across contracts, catalog and rule storage, prompt compilation, durable runs, MCP and WebSocket APIs, provider compatibility, web and mobile settings, chat selection, thread state, persistence, and documentation.

Changes

Native agent platform

Layer / File(s) Summary
Contracts and catalog
packages/contracts/..., packages/shared/..., apps/server/src/agents/AgentCatalog.ts, packages/client-runtime/src/state/agents.ts
Adds validated profile, rule, run, reference, RPC, project-file, catalog, and glob contracts.
Storage and prompt preparation
apps/server/src/agents/AgentProfileStore.ts, apps/server/src/agents/AgentRuleStore.ts, apps/server/src/agents/AgentHookRunner.ts, apps/server/src/agents/AgentPromptResolver.ts, apps/server/src/agents/prompt/*
Adds revision-aware Markdown persistence, secure hooks, rule matching, and deterministic prompt compilation.
Durable runs and orchestration
apps/server/src/agents/run/*, apps/server/src/agents/AgentOrchestration*.ts, apps/server/src/persistence/Migrations/*
Adds event-sourced run state, SQL persistence, deadlines, provider-event processing, child-thread lifecycle, worktree integration, and runtime wiring.
Transport and provider integration
apps/server/src/mcp/*, apps/server/src/ws.ts, apps/server/src/auth/RpcAuthorization.ts, apps/server/src/provider/*
Adds agent MCP tools, capability checks, WebSocket catalog and mutation handlers, authorization mappings, and provider compatibility metadata.
Thread profile propagation
packages/contracts/src/orchestration.ts, apps/web/src/components/ChatView.tsx, apps/mobile/src/features/threads/*, apps/mobile/src/state/*
Carries nullable, revision-pinned agent profile references through thread commands, projections, drafts, outbox messages, chat sends, and mobile composers.
Web and mobile settings
apps/web/src/components/settings/*, apps/web/src/routes/settings.agents.tsx, apps/mobile/src/features/settings/*, apps/mobile/src/Stack.tsx
Adds agent and rule settings panels, editors, navigation, validation, archive and restore actions, and revision-aware saves.
Documentation and validation
docs/..., apps/*/**/*.test.*, packages/*/**/*.test.*
Documents agent behavior and adds contract, catalog, storage, orchestration, prompt, provider, UI, and state coverage.

Estimated code review effort: 5 (Critical) | ~120 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.06% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly identifies the main change: adding provider-neutral agent orchestration.
Description check ✅ Passed The description includes What Changed, Why, UI Changes, verification details, limitations, screenshots, video, and the required checklist.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 7, 2026

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new Effect services under apps/server/src/agents/**, their MCP/WS call sites, and the layer wiring. Findings are limited to Effect service conventions in the new code: standalone *Shape interfaces instead of inline Context.Service interfaces, error classes whose only payload is a free-form detail (with the underlying failure discarded rather than kept as cause), and a duplicated agent-services layer in the WebSocket route.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/agents/AgentOrchestration.ts Outdated
Comment thread apps/server/src/ws.ts Outdated
Comment thread apps/server/src/agents/AgentPromptResolver.ts Outdated
Comment thread apps/server/src/agents/run/AgentRunRepository.ts Outdated
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts Outdated
Comment thread apps/server/src/agents/AgentRuleStore.ts Outdated
Comment thread apps/server/src/agents/AgentHookRunner.ts Outdated
Comment thread apps/server/src/agents/AgentHookRunner.ts Outdated
Comment thread apps/server/src/agents/AgentRuleStore.ts
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts
Comment thread apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts
Comment thread apps/server/src/agents/AgentCatalog.ts Outdated
Comment thread apps/server/src/agents/AgentPromptResolver.ts Outdated
Comment thread apps/server/src/agents/AgentProfileStore.ts Outdated
Comment thread apps/server/src/agents/AgentCatalog.ts
Comment thread apps/server/src/agents/AgentHookRunner.ts Outdated
@megascan
megascan force-pushed the agent/native-agent-orchestration branch from 86d41ba to 091b57d Compare August 7, 2026 18:53
@megascan

megascan commented Aug 7, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 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: 19

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (14)
apps/server/src/orchestration/Layers/ProjectionPipeline.ts-813-816 (1)

813-816: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the thread projection timestamp.

Line 815 changes agentProfile but leaves updatedAt unchanged. Clients can miss this state transition when they order or reconcile threads by updatedAt, especially if no later session event is emitted. Set updatedAt: event.occurredAt in this upsert.

🤖 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 `@apps/server/src/orchestration/Layers/ProjectionPipeline.ts` around lines 813
- 816, Update the projectionThreadRepository.upsert call in the projection event
handler to set updatedAt to event.occurredAt alongside agentProfile, preserving
the existing row fields and ensuring the thread timestamp reflects this state
transition.
docs/internals/glossary.md-95-97 (1)

95-97: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use standard adverb placement.

Change “applies always” to “always applies.”

🤖 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 `@docs/internals/glossary.md` around lines 95 - 97, Update the glossary’s Rule
definition to change the wording from “applies always” to “always applies,”
preserving the rest of the definition and its reference unchanged.

Source: Linters/SAST tools

apps/web/src/components/settings/AgentsSettings.logic.ts-128-132 (1)

128-132: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject empty and blank input in parseInteger.

Number("") and Number(" ") return 0, and Number.isInteger(0) is true. If the user clears "Maximum runs" or "Maximum concurrency", the document is built with 0. The schema then rejects the document with a decode error instead of the field-specific message.

🛡️ Proposed fix
 function parseInteger(value: string, label: string): number {
+  if (value.trim().length === 0) throw new Error(`${label} is required.`);
   const parsed = Number(value);
   if (!Number.isInteger(parsed)) throw new Error(`${label} must be a whole number.`);
   return parsed;
 }
🤖 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 `@apps/web/src/components/settings/AgentsSettings.logic.ts` around lines 128 -
132, Update parseInteger to explicitly reject empty or whitespace-only value
before converting it with Number, so cleared “Maximum runs” and “Maximum
concurrency” fields produce the existing label-specific whole-number error
instead of being interpreted as zero.
apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx-718-730 (1)

718-730: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reflect the off state in the "Always apply" toggle.

The toggle keeps bg-primary for both states, so the off state looks active. The profile toggle at lines 597-609 switches the background. Also add an accessibilityLabel, because the row label is a sibling element.

🎨 Proposed fix
         <Pressable
           accessibilityRole="switch"
+          accessibilityLabel="Always apply"
           accessibilityState={{ checked: props.draft.alwaysApply }}
           onPress={() => props.onChange("alwaysApply", !props.draft.alwaysApply)}
-          className="rounded-full bg-primary px-3 py-1"
+          className={`rounded-full px-3 py-1 ${props.draft.alwaysApply ? "bg-primary" : "bg-subtle-strong"}`}
         >
-          <Text className="text-sm font-t3-bold text-primary-foreground">
+          <Text
+            className={`text-sm font-t3-bold ${props.draft.alwaysApply ? "text-primary-foreground" : "text-foreground-muted"}`}
+          >
             {props.draft.alwaysApply ? "On" : "Off"}
           </Text>
         </Pressable>
🤖 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 `@apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx` around lines
718 - 730, Update the Always apply toggle in the surrounding settings component
to use the inactive background styling when props.draft.alwaysApply is false,
matching the profile toggle’s state-dependent styling. Add an accessibilityLabel
to the Pressable so the control is identified independently of its sibling text
label.
apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx-457-476 (1)

457-476: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add loading and error states to the rules list.

The profile list handles catalog.isPending and catalog.error. The rules list does not. During the first load the user sees "No rules yet." If the catalog request fails, the rules section shows the same empty message and hides the failure.

🩹 Proposed fix
           <View className="overflow-hidden rounded-2xl bg-subtle">
-            {rules.length === 0 ? (
+            {catalog.isPending && catalog.data === null ? (
+              <Text className="p-4 text-sm text-foreground-muted">Loading rules…</Text>
+            ) : null}
+            {catalog.error ? (
+              <Text accessibilityRole="alert" className="p-4 text-sm text-danger">
+                {catalog.error}
+              </Text>
+            ) : null}
+            {!catalog.isPending && !catalog.error && rules.length === 0 ? (
               <Text className="p-4 text-sm text-foreground-muted">
                 No rules yet. Create one to apply reusable instructions by path.
               </Text>
             ) : null}
🤖 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 `@apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx` around lines
457 - 476, Update the rules list rendering around rules.length and rules.map to
handle the catalog loading and error states consistently with the profile list:
show a loading state while catalog.isPending, show the catalog error when
catalog.error is present, and only show “No rules yet” after a successful load
with no rules. Preserve the existing RuleRow rendering for loaded rules.
packages/contracts/src/agents.ts-445-452 (1)

445-452: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Rule failures report profile error messages.

The rule error aliases point at AgentProfileError. A missing or conflicting rule therefore produces AgentProfileNotFoundError with the text "Agent profile '/' was not found." That text reaches the Rules settings UI and MCP clients and names the wrong entity. Add rule-specific AgentRuleNotFoundError and AgentRuleRevisionConflictError variants, or parameterize the message with the document kind.

🤖 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 `@packages/contracts/src/agents.ts` around lines 445 - 452, Update the rule
error definitions near AgentRuleGetError, AgentRuleSaveError,
AgentRuleArchiveError, and AgentRuleRestoreError so rule failures no longer
alias AgentProfileError. Add rule-specific not-found and revision-conflict
variants, or parameterize the shared error with the rule document kind, ensuring
exposed messages identify a rule rather than an agent profile.
packages/client-runtime/src/state/agents.ts-37-72 (1)

37-72: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Add command-level caching after agent mutations.

The web and mobile settings screens call catalog.refresh() inline, so this library does not prevent the same mutation from showing stale catalog/profile/rule data from another atomQuery. Add registry.refresh(...) to onSuccess in these commands so consumers do not have to duplicate the same invalidation.

🤖 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 `@packages/client-runtime/src/state/agents.ts` around lines 37 - 72, Update the
agent mutation commands in the command registry to invalidate related catalog,
profile, and rule queries through registry.refresh(...) in each command’s
onSuccess handler. Apply this to saveProfile, archiveProfile, restoreProfile,
saveRule, archiveRule, and restoreRule, using the existing query identifiers and
preserving their current scheduler and concurrency configuration.
apps/server/src/agents/prompt/RuleMatcher.ts-116-116 (1)

116-116: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

escapeRegex does not escape *, so wildcards inside {...} become regex quantifiers.

Line 153 escapes each alternation branch with escapeRegex. The escape set at line 116 omits *. A glob such as {*.ts,*.tsx} therefore compiles to (?:\*?\.ts|...)-style output where * acts as a quantifier on the preceding character instead of matching a path segment. The rule then matches the wrong files, silently and with no diagnostic.

The single-character path at line 156 is not affected, because * and ? are handled by earlier branches. Only alternation contents reach escapeRegex as multi-character strings.

Either reject * and ? inside alternations with a thrown Error, which surfaces as an invalid-glob diagnostic, or compile each alternative through the same character loop.

This also relates to the static analysis hint on line 158. Glob text reaches new RegExp after this incomplete escaping. Rule globs are author-supplied and the candidate list is bounded to the context files, so the practical backtracking risk is low, but the escaping gap should still be closed.

Also applies to: 146-154

🤖 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 `@apps/server/src/agents/prompt/RuleMatcher.ts` at line 116, The escapeRegex
function must escape `*` so wildcard characters inside alternation branches
cannot become regex quantifiers. Update its character class while preserving the
existing alternation compilation flow in the matcher around the branch handling
that calls `escapeRegex`.

Source: Linters/SAST tools

apps/server/src/agents/prompt/RuleMatcher.ts-238-259 (1)

238-259: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

contentBytes does not measure content.

The loop accumulates only rule.body bytes. The emitted content also contains a <!-- t3-agent-rule: scope/id -->\n header for each non-empty rule and a \n\n joiner between chunks. The returned contentBytes is therefore always lower than the byte length of content, and the 64 KiB cap does not bound what the prompt actually carries.

The loop also charges bytes for rules whose body is empty, which are then skipped at line 252 and contribute nothing to content.

Measure the chunk that is appended.

🐛 Proposed fix
   for (const rule of matched.rules) {
-    const bodyBytes = textEncoder.encode(rule.body).byteLength;
-    const nextBytes = contentBytes + bodyBytes;
+    if (rule.body.length === 0) continue;
+    const chunk = `<!-- t3-agent-rule: ${rule.scope}/${rule.id} -->\n${rule.body}`;
+    const separatorBytes = chunks.length === 0 ? 0 : 2;
+    const nextBytes = contentBytes + separatorBytes + textEncoder.encode(chunk).byteLength;
     if (nextBytes > maxBytes) {
       throw new AgentRuleContentOverflowError({
         limitBytes: maxBytes,
         actualBytes: nextBytes,
         ruleId: rule.id,
         scope: rule.scope,
       });
     }
     contentBytes = nextBytes;
-    if (rule.body.length > 0) {
-      chunks.push(`<!-- t3-agent-rule: ${rule.scope}/${rule.id} -->\n${rule.body}`);
-    }
+    chunks.push(chunk);
   }

Note that the test at apps/server/src/agents/prompt/prompt.test.ts line 94 uses maxBytes = 4 with a 5-byte body, so it still overflows after this change.

🤖 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 `@apps/server/src/agents/prompt/RuleMatcher.ts` around lines 238 - 259, Update
the content assembly loop around matched.rules so byte accounting measures each
emitted chunk, including its rule header and newline, and skips empty bodies
before charging bytes. Use the encoded byte length of the exact chunk appended
to chunks, accumulate that value for contentBytes, and retain the overflow check
against maxBytes so the existing 5-byte body test still throws.
apps/server/src/ws.ts-1111-1127 (1)

1111-1127: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Return catalog diagnostics in agentsCatalog.

agentCatalog.list() is a success-only effect that collects malformed profile and rule entries in AgentCatalogSnapshot.diagnostics. agentsCatalog currently returns only profiles and rules, so a user cannot see why a catalog entry is missing.

🤖 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 `@apps/server/src/ws.ts` around lines 1111 - 1127, Update the
WS_METHODS.agentsCatalog handler to include catalog.diagnostics in its returned
object alongside the filtered profiles and rules, preserving the existing
includeArchived filtering behavior.
apps/server/src/agents/run/AgentRunReactor.ts-47-53 (1)

47-53: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Log when the terminal hook is skipped.

If getProfileSnapshot returns None, or the workspace root cannot be resolved, Line 52 returns without any signal. The configured afterResult and onError hooks then never run, and the operator sees nothing. putProfileSnapshot should have persisted the snapshot at launch, so a missing snapshot indicates a real defect upstream. Emit a warning with run.id and run.profile.revision.

🤖 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 `@apps/server/src/agents/run/AgentRunReactor.ts` around lines 47 - 53, Update
the early-return guard in the hook execution flow to emit a warning when profile
is null or workspaceRoot is null, including run.id and run.profile.revision in
the log; preserve the existing return behavior and do not alter hook execution
for valid values.
apps/server/src/agents/run/AgentRunDeadlineReactor.ts-26-33 (1)

26-33: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard against an unparsable timestamp, and correct the comment.

Two problems exist in this segment.

Date.parse returns NaN for a malformed timestamp. AgentRun.requestedAt and AgentRun.startedAt are plain string fields, so a corrupt persisted value produces NaN. isDeadlineExpired then always returns false, and schedule computes Math.max(0, NaN - nowMillis), which is NaN, and passes it to Duration.millis. The run then never reaches its wall-time budget.

The comment states the budget starts when a run is requested. The code prefers run.startedAt, so a run that stays queued receives a later deadline. Align the comment with the code.

🐛 Proposed guard
-/** The wall-time budget starts when a run is requested until it finishes. */
-export const deadlineAtMillis = (run: AgentRun): number => {
-  const origin = Date.parse(run.startedAt ?? run.requestedAt);
-  return origin + run.budget.maxWallTimeMinutes * 60_000;
-};
+/**
+ * The wall-time budget starts when a run starts, and falls back to the
+ * request time while the run is still queued.
+ */
+export const deadlineAtMillis = (run: AgentRun): number => {
+  const parsed = Date.parse(run.startedAt ?? run.requestedAt);
+  const origin = Number.isNaN(parsed) ? Date.parse(run.requestedAt) : parsed;
+  return (Number.isNaN(origin) ? 0 : origin) + run.budget.maxWallTimeMinutes * 60_000;
+};
🤖 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 `@apps/server/src/agents/run/AgentRunDeadlineReactor.ts` around lines 26 - 33,
Update deadlineAtMillis to handle an unparsable run.startedAt or run.requestedAt
without returning NaN, preserving a valid deadline calculation for deadline
expiration and scheduling; use the existing AgentRun timestamp context and
choose an appropriate safe fallback for invalid persisted timestamps. Correct
the comment above deadlineAtMillis to state that the wall-time budget starts
from the timestamp selected by the implementation, including the startedAt
preference.
apps/server/src/persistence/Migrations/040_ProjectionThreadsAgentProfile.ts-4-16 (1)

4-16: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Add a migration test for agent_profile_json.

ProjectionThreadRepository reads and writes agent_profile_json through agentProfile in upsert, getById, and listByProjectId, but 040_ProjectionThreadsAgentProfile has no test cover. Add a migration test that runs up to migration 040 and asserts the column exists, following the existing migration test pattern.

🤖 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 `@apps/server/src/persistence/Migrations/040_ProjectionThreadsAgentProfile.ts`
around lines 4 - 16, Add a migration test following the existing migration test
pattern that runs migrations through 040_ProjectionThreadsAgentProfile and
verifies projection_threads contains the agent_profile_json column. Cover the
schema assertion only; do not alter ProjectionThreadRepository or migration
behavior.
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts-774-798 (1)

774-798: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Move getCapabilities into the profile branch.

resolvedPrompt.profile !== null is the only consumer of requestedCapabilities, so fetching it on every turn start adds an unneeded provider lookup. Calling it before ensureSessionForThread also runs capabilities lookup after unknown-instance failures, which can return provider capabilities errors instead of the descriptive unknown-instance errors from getInstanceInfo.

♻️ Proposed refactor
-    const requestedModelSelection =
-      input.modelSelection ?? threadModelSelections.get(input.threadId) ?? thread.modelSelection;
-    const requestedCapabilities = yield* providerService.getCapabilities(
-      requestedModelSelection.instanceId,
-    );
-    if (resolvedPrompt.profile !== null) {
-      const profile = resolvedPrompt.profile;
+    const requestedModelSelection =
+      input.modelSelection ?? threadModelSelections.get(input.threadId) ?? thread.modelSelection;
+    if (resolvedPrompt.profile !== null) {
+      const profile = resolvedPrompt.profile;
+      const requestedCapabilities = yield* providerService.getCapabilities(
+        requestedModelSelection.instanceId,
+      );
🤖 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 `@apps/server/src/orchestration/Layers/ProviderCommandReactor.ts` around lines
774 - 798, Move the providerService.getCapabilities call into the
resolvedPrompt.profile !== null branch, immediately before
resolveAgentRuntimeCompatibility, and keep requestedModelSelection available
there. Avoid fetching capabilities when no profile is present, while preserving
ensureSessionForThread/getInstanceInfo validation ordering so unknown instances
produce their existing descriptive errors first.
🤖 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 `@apps/mobile/src/features/settings/agentProfile.logic.ts`:
- Around line 51-56: Extract a shared numeric parsing helper that rejects blank
or whitespace-only input before conversion, then apply range validation at each
caller. In apps/mobile/src/features/settings/agentProfile.logic.ts lines 51-56,
update integer so maxRuns and maxWallTimeMinutes reject blank values; in
apps/mobile/src/features/settings/agentRule.logic.ts lines 44-50, make
parseInteger reuse the shared helper instead of duplicating conversion and
integer checks. In apps/mobile/src/features/settings/agentProfile.logic.test.ts
lines 11-29, add negative cases asserting blank budget input and blank priority
cause buildAgentProfileDocument and buildAgentRuleDocument to throw.
- Around line 40-43: Update the runtimeMode default in draftFromProfile so a new
profile uses the least-permissive intended default, “auto,” instead of
“full-access”; leave the other profile defaults unchanged and preserve explicit
existing runtimeMode values.

In `@apps/mobile/src/features/settings/agentRule.logic.ts`:
- Around line 59-65: Update the mapping logic around the scope and id extraction
to split each colon-delimited target only at its first colon, preserving all
remaining text in id. Keep the environment default for targets without a colon,
then validate the preserved remainder with the existing scope and id checks so
malformed multi-colon targets are rejected rather than truncated.

In `@apps/mobile/src/state/use-thread-composer-state.ts`:
- Around line 110-113: Update the draft persistence and empty-draft handling
around updateComposerDraftSettings and isEmptyDraft so an explicit agentProfile:
null is preserved rather than causing the draft to be deleted. Ensure clearing a
thread-locked profile remains effective for the next turn while retaining
existing removal behavior for genuinely empty drafts.

In `@apps/server/src/agents/AgentCatalog.ts`:
- Around line 702-715: Update validate to reuse the single discovered source
collection returned by list/discovery instead of calling find, getProfile, or
getRule for each entry. Extract the post-find loading logic into
loadProfile(source) and loadRule(source), have getProfile and getRule call these
helpers after find, and have validate resolve each entry’s source from the
already discovered collection before invoking the corresponding loader.

In `@apps/server/src/agents/AgentOrchestrationLive.ts`:
- Around line 979-982: Update the follow-up turn construction in send to load
the pinned profile snapshot via runs.getProfileSnapshot(run.profile.revision),
then derive runtimeMode and interactionMode from that profile using the same
logic as spawn rather than hardcoding "full-access" and "default". Preserve the
profile’s approval requirements for every subsequent turn.

In `@apps/server/src/agents/AgentPromptResolver.ts`:
- Around line 24-45: Reject URI schemes in both normalizeCandidate in
apps/server/src/agents/AgentPromptResolver.ts lines 24-45 and
normalizeWorkspaceRelativePath in apps/server/src/agents/prompt/RuleMatcher.ts
lines 74-98 by adding the same scheme-prefix validation after the drive-letter
check; preserve existing rejection behavior and ensure values such as
https://example.com/x are rejected rather than normalized as relative paths.
Consider sharing the validator to prevent the rules from diverging.

In `@apps/server/src/agents/prompt/PromptCompiler.ts`:
- Around line 180-188: Update compileAgentPrompt and the compileAgentRules
integration to handle AgentRuleContentOverflowError without letting it escape as
a defect. Use isAgentRuleContentOverflowError to convert the overflow into the
established AgentPromptDiagnostic/result path, preserving the declared
AgentPromptCompilation and AgentPromptResolutionError flow for user-facing
handling.

In `@apps/server/src/agents/run/AgentRunDeadlineReactor.ts`:
- Around line 56-67: In apps/server/src/agents/run/AgentRunDeadlineReactor.ts
lines 56-67, update the cancellation handling in the deadline reactor to
distinguish Result failure from an empty successful event list: log the failure
details before returning false, while preserving the existing no-op behavior for
empty events. In apps/server/src/agents/run/AgentRunReactor.ts lines 47-53, add
a warning before the early return that includes run.id, run.profile.revision,
and the specific missing value.

In `@apps/server/src/agents/run/AgentRunReactor.ts`:
- Around line 162-175: Update the event handling flow around handle and
runTerminalHook so terminal hooks execute on forked fibers or through a bounded
per-thread concurrent consumer instead of blocking Stream.runForEach’s single
consumer fiber. Preserve sequential event processing for each thread while
allowing hooks from different runs or threads to proceed independently, and
retain the existing error logging context.
- Around line 87-100: The budget-exhaustion branch in AgentRunReactor must stop
matching the human-readable detail text. Add a structured discriminator such as
reason to AgentRunCommandInvariantError, set it for budget-exhaustion failures,
and update the completion check to compare that discriminator while preserving
the existing dispatch behavior.

In `@apps/server/src/mcp/McpSessionRegistry.ts`:
- Line 131: Update McpSessionRegistry.issue() so the "agents" capability is
granted only when the thread’s attached target profile declares the
corresponding MCP tools, rather than unconditionally for every credential;
preserve "preview" access and ensure delegation uses the profile-specific
capability set.

In `@apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts`:
- Around line 303-308: Update the thread.turn.start test setup around
resolveAgentPrompt and the dispatch at line 577 to provide a valid agentProfile
with a known profileRef, then assert the resolveAgentPrompt mock receives that
matching profileRef alongside the message. Ensure the test specifically
exercises the pinned-profile path rather than allowing a null profile reference.
- Around line 2917-2926: Replace the local waitFor polling block in the test
with yield* Effect.promise(() => harness.drain()) after the relevant dispatches.
Use harness.drain to wait for both reactor workers before reading the model,
while preserving the subsequent failure-activity assertions.

In `@apps/server/src/persistence/Migrations/039_AgentRuns.ts`:
- Around line 69-72: Update the migration near the existing
idx_projection_agent_runs_lineage definition to add a dedicated index on
projection_agent_runs(root_run_id), using an IF NOT EXISTS guard and a clear
root-run index name. Leave the existing parent_run_id, status, and created_at
index unchanged.

In `@apps/server/src/ws.ts`:
- Around line 2384-2391: Update websocketRpcRouteLayer and the server
route-layer wiring to construct one shared AgentProfileServices.layer per server
instance and provide that same layer to both HTTP routes and WebSocket RPC,
rather than extracting and rebuilding AgentCatalog, AgentProfileStore, and
AgentRuleStore inside websocketRpcRouteLayer. Ensure AgentRuleStore and
AgentProfileStore retain shared mutex and revision state across both transports.

In `@apps/web/src/components/settings/AgentsSettings.tsx`:
- Around line 506-518: Update the scope select in the AgentsSettings profile
form to use the existing-profile rule from RulesSettings: disable it when the
profile is not new by applying the equivalent isNew-based disabled condition,
while preserving the current value and change handling.

In `@apps/web/src/components/settings/RulesSettings.tsx`:
- Around line 149-158: Update the catch block in the rule restore flow to handle
caught values with the same instanceof Error check used near line 132, passing
plain Error instances directly to setError and using failureMessage only for
Cause values. Remove the unsafe Cause.Cause cast while preserving the existing
error-state behavior.
- Around line 108-113: Update save in RulesSettings so buildAgentRuleDocument
receives no baseline when creating a new rule: use the selectedKey/new-rule
state to pass null for new rules, matching the isNew guard in AgentsSettings,
and retain ruleQuery.data?.rule only when editing an existing selected rule.

---

Minor comments:
In `@apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx`:
- Around line 718-730: Update the Always apply toggle in the surrounding
settings component to use the inactive background styling when
props.draft.alwaysApply is false, matching the profile toggle’s state-dependent
styling. Add an accessibilityLabel to the Pressable so the control is identified
independently of its sibling text label.
- Around line 457-476: Update the rules list rendering around rules.length and
rules.map to handle the catalog loading and error states consistently with the
profile list: show a loading state while catalog.isPending, show the catalog
error when catalog.error is present, and only show “No rules yet” after a
successful load with no rules. Preserve the existing RuleRow rendering for
loaded rules.

In `@apps/server/src/agents/prompt/RuleMatcher.ts`:
- Line 116: The escapeRegex function must escape `*` so wildcard characters
inside alternation branches cannot become regex quantifiers. Update its
character class while preserving the existing alternation compilation flow in
the matcher around the branch handling that calls `escapeRegex`.
- Around line 238-259: Update the content assembly loop around matched.rules so
byte accounting measures each emitted chunk, including its rule header and
newline, and skips empty bodies before charging bytes. Use the encoded byte
length of the exact chunk appended to chunks, accumulate that value for
contentBytes, and retain the overflow check against maxBytes so the existing
5-byte body test still throws.

In `@apps/server/src/agents/run/AgentRunDeadlineReactor.ts`:
- Around line 26-33: Update deadlineAtMillis to handle an unparsable
run.startedAt or run.requestedAt without returning NaN, preserving a valid
deadline calculation for deadline expiration and scheduling; use the existing
AgentRun timestamp context and choose an appropriate safe fallback for invalid
persisted timestamps. Correct the comment above deadlineAtMillis to state that
the wall-time budget starts from the timestamp selected by the implementation,
including the startedAt preference.

In `@apps/server/src/agents/run/AgentRunReactor.ts`:
- Around line 47-53: Update the early-return guard in the hook execution flow to
emit a warning when profile is null or workspaceRoot is null, including run.id
and run.profile.revision in the log; preserve the existing return behavior and
do not alter hook execution for valid values.

In `@apps/server/src/orchestration/Layers/ProjectionPipeline.ts`:
- Around line 813-816: Update the projectionThreadRepository.upsert call in the
projection event handler to set updatedAt to event.occurredAt alongside
agentProfile, preserving the existing row fields and ensuring the thread
timestamp reflects this state transition.

In `@apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
- Around line 774-798: Move the providerService.getCapabilities call into the
resolvedPrompt.profile !== null branch, immediately before
resolveAgentRuntimeCompatibility, and keep requestedModelSelection available
there. Avoid fetching capabilities when no profile is present, while preserving
ensureSessionForThread/getInstanceInfo validation ordering so unknown instances
produce their existing descriptive errors first.

In `@apps/server/src/persistence/Migrations/040_ProjectionThreadsAgentProfile.ts`:
- Around line 4-16: Add a migration test following the existing migration test
pattern that runs migrations through 040_ProjectionThreadsAgentProfile and
verifies projection_threads contains the agent_profile_json column. Cover the
schema assertion only; do not alter ProjectionThreadRepository or migration
behavior.

In `@apps/server/src/ws.ts`:
- Around line 1111-1127: Update the WS_METHODS.agentsCatalog handler to include
catalog.diagnostics in its returned object alongside the filtered profiles and
rules, preserving the existing includeArchived filtering behavior.

In `@apps/web/src/components/settings/AgentsSettings.logic.ts`:
- Around line 128-132: Update parseInteger to explicitly reject empty or
whitespace-only value before converting it with Number, so cleared “Maximum
runs” and “Maximum concurrency” fields produce the existing label-specific
whole-number error instead of being interpreted as zero.

In `@docs/internals/glossary.md`:
- Around line 95-97: Update the glossary’s Rule definition to change the wording
from “applies always” to “always applies,” preserving the rest of the definition
and its reference unchanged.

In `@packages/client-runtime/src/state/agents.ts`:
- Around line 37-72: Update the agent mutation commands in the command registry
to invalidate related catalog, profile, and rule queries through
registry.refresh(...) in each command’s onSuccess handler. Apply this to
saveProfile, archiveProfile, restoreProfile, saveRule, archiveRule, and
restoreRule, using the existing query identifiers and preserving their current
scheduler and concurrency configuration.

In `@packages/contracts/src/agents.ts`:
- Around line 445-452: Update the rule error definitions near AgentRuleGetError,
AgentRuleSaveError, AgentRuleArchiveError, and AgentRuleRestoreError so rule
failures no longer alias AgentProfileError. Add rule-specific not-found and
revision-conflict variants, or parameterize the shared error with the rule
document kind, ensuring exposed messages identify a rule rather than an agent
profile.

---

Nitpick comments:
In `@apps/mobile/src/state/thread-outbox.test.ts`:
- Around line 131-149: Extend the test around resolveQueuedThreadSettings to
cover both remaining agentProfile branches: assert that an explicit
agentProfile: null clears the thread profile, and assert that omitting the
agentProfile property preserves the existing thread profile. Keep the current
queued-profile round-trip assertion unchanged so all three hasOwnProperty-based
behaviors are verified.

In `@apps/mobile/src/state/use-thread-composer-state.test.ts`:
- Around line 1-4: Rename the test file from use-thread-composer-state.test.ts
to agentProfileSelection.test.ts so its filename matches the
resolveAgentProfileSelection module under test.

In `@apps/server/src/agents/AgentCatalog.test.ts`:
- Around line 33-298: Add a focused test in the AgentCatalog suite that calls
the public validate method with one valid profile and one Markdown document
lacking frontmatter, then assert validation aggregates the expected
missing-frontmatter diagnostic alongside the valid document results. Exercise
both discovery/list diagnostics and per-document loading through validate,
without using arbitrary timeouts.

In `@apps/server/src/agents/AgentCatalog.ts`:
- Around line 193-200: Introduce a scope-neutral AgentLocator (or
AgentRuleLocator) alias in packages/contracts and use it for rule references,
including getRule and RuleFrontmatter.profiles where applicable, while retaining
AgentProfileLocator for profile references. Rename decodeProfileLocator at the
rule-decoding call sites around lines 493 and 825 to reflect that it decodes
rule identifiers, and update all related imports and usages.

In `@apps/server/src/agents/AgentHookRunner.ts`:
- Around line 113-127: Update the POSIX invocation in the shell-hook runner to
use /bin/sh with only the -c argument, removing the login-shell behavior while
preserving the existing command, working directory, timeout, and output
handling.
- Around line 15-45: Extract the identical field definitions from
AgentHookBlockedError and AgentHookExecutionError into a shared schema field-set
constant, then reuse it when declaring both TaggedErrorClass schemas. Keep both
error tags and their existing message getters distinct and unchanged.

In `@apps/server/src/agents/AgentOrchestrationLive.ts`:
- Around line 699-709: In the isolated-worktree branch of the prepareThread
setup, capture the already-validated context.thread.branch in a local constant
immediately after its guard, then use that constant for refName and baseRefName
instead of non-null assertions. Preserve the existing branch validation and
worktree creation behavior.

In `@apps/server/src/agents/AgentProfileStore.test.ts`:
- Around line 172-173: Update the test around projectFile in AgentProfileStore
tests to parse t3.json as JSON and inspect its decoded agents array. Assert that
exactly one agent has id "project-reviewer", replacing the raw project-reviewer
substring count while preserving the existing file-read flow.
- Around line 93-104: The compare-and-swap failure paths are untested. In
apps/server/src/agents/AgentProfileStore.test.ts:93-104, add a second save using
the already-consumed saved.revision and assert
AgentProfileStoreRevisionConflictError; in
apps/server/src/agents/AgentRuleStore.test.ts:62-75, add the equivalent
stale-revision save and assert the rule store’s typed revision-conflict error.
Also add, in either test file, coverage for supplying expectedRevision when the
profile or rule does not exist, asserting the appropriate failure.

In `@apps/server/src/agents/AgentProfileStore.ts`:
- Around line 388-397: Resolve the `documentPath` behavior for new environment
profiles in the surrounding profile creation flow: either honor
`input.profile.sourcePath` consistently, or validate and reject conflicting
values while retaining `defaultPath`. If always using the environment default is
intentional, add a concise comment documenting that rule; preserve
existing-project behavior.

In `@apps/server/src/agents/AgentPromptResolver.test.ts`:
- Around line 87-89: Strengthen the test assertion in the resolver test so it
verifies the compiled prelude appears before the user-supplied marker, using the
ordering of “## T3 runtime” and malicious in resolved.message. Keep the existing
assertions unchanged; do not address duplicate markers here, as that belongs to
PromptCompiler.

In `@apps/server/src/agents/AgentPromptResolver.ts`:
- Around line 183-199: Update the Effect.forEach call that loads snapshot.rules
in resolve to use bounded concurrency greater than one, preserving the existing
resolutionError mapping and result ordering. Do not alter rule lookup behavior;
only configure concurrency to avoid sequential catalog.getRule calls.
- Around line 156-166: Extract the child-run turn command ID construction into a
shared helper, then reuse it in AgentOrchestrationLive when sending
thread.turn.start and in AgentPromptResolver.isCompiledAgentTurn when comparing
commandId. Ensure the helper consistently formats the agent-spawn prefix and run
ID.

In `@apps/server/src/agents/AgentRuleStore.test.ts`:
- Around line 137-138: Update the assertion in the t3.json test to decode
projectFile as JSON, inspect its rules array, and assert exactly one entry whose
id is "project-typescript"; remove the substring-count assertion so the test
validates structured data rather than JSON text layout.

In `@apps/server/src/agents/AgentRuleStore.ts`:
- Around line 365-372: Update the documentPath selection in the relevant
AgentRuleStore function to use Result.isSuccess(current), matching the existing
check earlier in the same function, while preserving the current success and
fallback sourcePath behavior.

In `@apps/server/src/agents/prompt/prompt.test.ts`:
- Around line 72-88: The matching tests around matchAgentRules need coverage for
advanced and malformed glob patterns. Add focused cases for alternation and
character-class patterns, including src/**/*.{ts,tsx} matching src/a.tsx and
{*.ts,*.tsx} matching the appropriate files, plus an unclosed src/[ts pattern
that yields an invalid-glob diagnostic and never matches.

In `@apps/server/src/agents/prompt/PromptCompiler.ts`:
- Around line 83-84: Remove the redundant compatibility aliases from
PromptCompiler and RuleMatcher: delete portablePromptEnvelope, compilePrompt,
matchRules, compileRules, and RuleContentOverflowError exports or properties,
retaining only the canonical names and updating index re-exports and internal
references accordingly.
- Around line 144-148: Document in renderPortablePrompt that envelope.task is
intentionally preserved verbatim and may contain duplicate prompt markers or
section headings, so future consumers must not treat them as trust signals;
update the existing AgentPromptResolver test expectation only if needed to
preserve this documented behavior.

In `@apps/server/src/agents/run/AgentRun.test.ts`:
- Around line 165-292: Update the test title for “enforces inherited depth,
run-count, concurrency, and token budgets” to also identify the estimated-cost
budget assertion, so all five covered budget dimensions are visible when the
test fails.
- Around line 294-405: Add tests in the AgentRun transition/decision coverage
for both missing branches: advance the command occurredAt beyond the configured
maxWallTimeMinutes and assert the relevant succeed or follow-up decision is
rejected, then request a child run with maxRuns or maxTotalTokens greater than
its parent and assert budgetDoesNotExpand rejects it. Reuse the existing
request, start, transition, decide, and fixture helpers and preserve current
assertions.

In `@apps/server/src/agents/run/AgentRun.ts`:
- Around line 365-475: Update the second event switch in evolve to add a default
branch that passes the event to a never assertion, making any newly added
AgentRunEvent variant a compile-time error while preserving all existing cases.

In `@apps/server/src/agents/run/AgentRunDeadlineReactor.test.ts`:
- Around line 90-165: Add focused coverage for the make scheduling flow: use a
fake change stream and TestClock to verify layer startup recovers an active run
from listActive and schedules expiration, then emits a completed-status change
and verifies cancelScheduled removes the timer. Exercise the behavior
deterministically without arbitrary timeouts, anchoring the test around make,
listActive recovery, change-event handling, and TestClock.
- Around line 67-85: Replace the trailing `as AgentRunRepository["Service"]`
cast in `repositoryFor` with a `satisfies AgentRunRepository["Service"]` check
on the object literal, preserving the existing inferred object type while
ensuring missing or incompatible service members fail typechecking.

In `@apps/server/src/agents/run/AgentRunReactor.ts`:
- Around line 22-26: Import the exported AgentRun type from ./AgentRun.ts and
use it directly for the run parameter in both hookWorkspace and the other helper
around lines 41–45. Remove the duplicated
NonNullable<Effect.Success<ReturnType<typeof repository.get>>…> type derivation
while preserving the existing helper behavior.

In `@apps/server/src/agents/run/AgentRunRepository.test.ts`:
- Around line 66-206: Extend the AgentRunRepository test suite with focused
coverage for putProfileSnapshot and getProfileSnapshot, including the persisted
profile data used by recovery or hook execution. Add assertions for
getByChildThread and listActive, including expected child-thread lookup and
active-run filtering. Keep the tests isolated within
testLayer("AgentRunRepository", ...) and use the existing migration, repository,
and fixture helpers.

In `@apps/server/src/agents/run/AgentRunRepository.ts`:
- Around line 159-163: The unfiltered SQL branch in the event retrieval method
should not remain available. Make the where/filter parameter required and remove
the fallback query that selects all events, updating the method signature and
callers as needed while preserving the existing filtered queries.
- Around line 218-236: Update the AgentRunRepository projection and migration
039 so result_json is populated from the run’s result data rather than a
constant null, and consumedEstimatedCostUsd is stored alongside consumedTokens.
Ensure the INSERT column/value lists and conflict-update clause consistently
include both fields, using the existing serialization pattern for result data
and the AgentRun property for cost.

In `@apps/server/src/mcp/McpHttpServer.ts`:
- Around line 217-227: Rename ToolkitRegistrations to a preview-specific name
that reflects its use by PreviewToolkitRegistrationLive. Wrap
AgentToolkitHandlersLive and AgentToolkit with
McpToolkit.makeMcpToolkitRegistration using the agents capability, then expose
AgentToolkitRegistrationLive from that registration so it follows the same
capability-aware path as the preview toolkits.

In `@apps/server/src/orchestration/agentProfile.test.ts`:
- Around line 17-30: Update the event helper so it is generic over a specific
OrchestrationEvent member, deriving the type and payload parameters from that
member instead of accepting an arbitrary type and unknown payload. Construct the
shared envelope with the generic event type and retain only any necessary cast
for fields whose union narrowing requires it, ensuring each event call validates
its payload against the selected event type.
- Around line 61-72: Add a second turn-start test case alongside the existing
null-agentProfile case, using a non-null agentProfile in
thread.turn-start-requested and asserting that the projected thread preserves
that exact value. Keep the existing null case unchanged so both clearing and
applying event values are verified.

In `@apps/server/src/orchestration/projector.ts`:
- Around line 547-563: Update the "thread.turn-start-requested" handler so that
when payload.agentProfile is undefined it returns nextBase unchanged, avoiding
the updateThread call; retain the existing agentProfile patch through
updateThread when the value is present.

In `@apps/server/src/persistence/Migrations/039_AgentRuns.test.ts`:
- Around line 48-59: Replace the name-based index assertions in the migration
test with behavioral checks: insert duplicate agent_run_events rows sharing the
same agent_run_id and revision, and duplicate projection_agent_runs rows sharing
child_thread_id, asserting both inserts fail. Preserve any setup required by the
schema and ensure the event constraint test covers the duplicate-revision
behavior used by AgentRunRepository.dispatch.

In `@apps/server/src/persistence/Migrations/039_AgentRuns.ts`:
- Around line 74-82: Remove the redundant CREATE INDEX statements for
idx_agent_run_events_run_revision and idx_projection_agent_runs_child_thread
from the migration, relying on the existing UNIQUE constraints. Update the
corresponding assertions in the migration test to no longer expect either index
name.

In `@apps/server/src/provider/AgentRuntimeCompatibility.test.ts`:
- Around line 29-46: Add coverage in AgentRuntimeCompatibility tests for the
delegation path in resolveAgentRuntimeCompatibility, ensuring the portable
fixture’s mcpServerInjection capability does not mask it. Add assertions for
both mcp-server-injection-unsupported and token-accounting-unsupported while
preserving the existing unsupported-issue expectations.

In `@apps/server/src/ws.ts`:
- Around line 470-482: Replace the derived ref type in mapAgentCatalogError with
AgentProfileLocator, and add AgentProfileLocator to the existing
`@t3tools/contracts` import. Preserve the current error mapping behavior and ref
values.

In `@apps/web/src/components/chat/ChatComposer.tsx`:
- Around line 680-682: Update the selectedAgentProfile useState declaration in
ChatComposer to remove the explicit AgentProfileRef | null generic parameter and
rely on the lazy initializer’s inferred type, preserving the existing initial
value and state behavior.

In `@apps/web/src/components/settings/AgentsSettings.logic.test.ts`:
- Around line 24-44: Update the revision assertion in the “preserves a revision
and parses structured policy fields” test to compare document.revision with the
exact baseline revision, "a".repeat(64), instead of only validating its
hexadecimal format. Keep the existing structured-field assertions unchanged.

In `@apps/web/src/components/settings/AgentsSettings.logic.ts`:
- Around line 177-204: In the configuration-building logic, compute each
optional numeric value once before constructing the result object, then reuse it
for both the undefined check and assigned property. Update the handling around
sharedWriteConcurrency, maxTotalTokens, and maxEstimatedCostUsd while preserving
omission of undefined fields and existing parse behavior.

In `@apps/web/src/components/settings/RulesSettings.logic.ts`:
- Around line 74-89: Extract the shared archived/scope/name/id comparator into
one generic catalog sort helper, then re-export that helper under both
sortAgentRules and sortAgentProfiles. Update the existing sortAgentRules
implementation and the corresponding sortAgentProfiles implementation to use the
shared symbol while preserving their current signatures and ordering.

In `@apps/web/src/components/settings/settingsSearch.ts`:
- Around line 171-175: Add a separate search entry titled “Rules” alongside the
existing “Agents” entry in the settings search configuration, using the same
/settings/agents route so RulesSettingsPanel is discoverable when users search
for “rules”.

In `@apps/web/src/routeTree.gen.ts`:
- Around line 100-104: Remove the `as any` cast from the
`SettingsAgentsRouteImport.update` call in the generated route definition by
regenerating it with typed output. If the generator cannot avoid the cast, add a
narrowly scoped lint exception for this generated route file and document the
generated-code justification.

In `@packages/contracts/src/agents.ts`:
- Around line 351-382: Introduce or reuse a dedicated AgentRuleId brand from
agentRefs.ts, then update AgentRuleSummary.id and all rule operation
identifiers, including AgentRuleGetInput.id, AgentRuleArchiveInput.id, and the
id carried by AgentRuleDocument used in AgentRuleSaveInput, to use AgentRuleId
consistently instead of AgentProfileId or AgentSlug.
- Around line 674-746: Remove the compatibility alias export blocks for
AgentMcpStart/Get/Submit, AgentMcpAgent*, and McpAgentRun* so each codec has one
canonical exported name. Update any call sites referencing those aliases to use
the corresponding canonical
AgentMcpList/Spawn/Status/Wait/Result/Send/Cancel/Integrate symbols.
🪄 Autofix

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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 121fbec2-7b16-4a78-9116-a9cc89a98d48

📥 Commits

Reviewing files that changed from the base of the PR and between 72d673a and 091b57d.

📒 Files selected for processing (121)
  • apps/mobile/src/Stack.tsx
  • apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
  • apps/mobile/src/features/settings/SettingsRouteScreen.tsx
  • apps/mobile/src/features/settings/agentProfile.logic.test.ts
  • apps/mobile/src/features/settings/agentProfile.logic.ts
  • apps/mobile/src/features/settings/agentRule.logic.test.ts
  • apps/mobile/src/features/settings/agentRule.logic.ts
  • apps/mobile/src/features/settings/components/settings-sheet-targets.ts
  • apps/mobile/src/features/threads/NewTaskDraftScreen.tsx
  • apps/mobile/src/features/threads/ThreadComposer.tsx
  • apps/mobile/src/features/threads/ThreadDetailScreen.tsx
  • apps/mobile/src/features/threads/ThreadRouteScreen.tsx
  • apps/mobile/src/features/threads/new-task-flow-provider.tsx
  • apps/mobile/src/features/threads/use-project-actions.ts
  • apps/mobile/src/lib/projectThreadStartTurn.ts
  • apps/mobile/src/state/agentProfileSelection.ts
  • apps/mobile/src/state/agents.ts
  • apps/mobile/src/state/thread-outbox-model.ts
  • apps/mobile/src/state/thread-outbox.test.ts
  • apps/mobile/src/state/use-composer-drafts.ts
  • apps/mobile/src/state/use-thread-composer-state.test.ts
  • apps/mobile/src/state/use-thread-composer-state.ts
  • apps/mobile/src/state/use-thread-outbox-drain.ts
  • apps/server/integration/OrchestrationEngineHarness.integration.ts
  • apps/server/src/agents/AgentCatalog.test.ts
  • apps/server/src/agents/AgentCatalog.ts
  • apps/server/src/agents/AgentHookRunner.test.ts
  • apps/server/src/agents/AgentHookRunner.ts
  • apps/server/src/agents/AgentOrchestration.ts
  • apps/server/src/agents/AgentOrchestrationLive.test.ts
  • apps/server/src/agents/AgentOrchestrationLive.ts
  • apps/server/src/agents/AgentProfileServices.ts
  • apps/server/src/agents/AgentProfileStore.test.ts
  • apps/server/src/agents/AgentProfileStore.ts
  • apps/server/src/agents/AgentPromptResolver.test.ts
  • apps/server/src/agents/AgentPromptResolver.ts
  • apps/server/src/agents/AgentRuleStore.test.ts
  • apps/server/src/agents/AgentRuleStore.ts
  • apps/server/src/agents/prompt/PromptCompiler.ts
  • apps/server/src/agents/prompt/RuleMatcher.ts
  • apps/server/src/agents/prompt/index.ts
  • apps/server/src/agents/prompt/prompt.test.ts
  • apps/server/src/agents/run/AgentRun.test.ts
  • apps/server/src/agents/run/AgentRun.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.test.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.ts
  • apps/server/src/agents/run/AgentRunReactor.ts
  • apps/server/src/agents/run/AgentRunRepository.test.ts
  • apps/server/src/agents/run/AgentRunRepository.ts
  • apps/server/src/auth/RpcAuthorization.ts
  • apps/server/src/mcp/McpHttpServer.test.ts
  • apps/server/src/mcp/McpHttpServer.ts
  • apps/server/src/mcp/McpInvocationContext.test.ts
  • apps/server/src/mcp/McpInvocationContext.ts
  • apps/server/src/mcp/McpSessionRegistry.test.ts
  • apps/server/src/mcp/McpSessionRegistry.ts
  • apps/server/src/mcp/McpToolkit.ts
  • apps/server/src/mcp/toolkits/agents/handlers.ts
  • apps/server/src/mcp/toolkits/agents/tools.ts
  • apps/server/src/orchestration/Layers/ProjectionPipeline.ts
  • apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
  • apps/server/src/orchestration/agentProfile.test.ts
  • apps/server/src/orchestration/decider.ts
  • apps/server/src/orchestration/projector.ts
  • apps/server/src/persistence/Layers/ProjectionThreads.ts
  • apps/server/src/persistence/Migrations.ts
  • apps/server/src/persistence/Migrations/039_AgentRuns.test.ts
  • apps/server/src/persistence/Migrations/039_AgentRuns.ts
  • apps/server/src/persistence/Migrations/040_ProjectionThreadsAgentProfile.ts
  • apps/server/src/persistence/Services/ProjectionThreads.ts
  • apps/server/src/provider/AgentRuntimeCompatibility.test.ts
  • apps/server/src/provider/AgentRuntimeCompatibility.ts
  • apps/server/src/provider/Layers/ClaudeAdapter.ts
  • apps/server/src/provider/Layers/CodexAdapter.ts
  • apps/server/src/provider/Layers/CursorAdapter.ts
  • apps/server/src/provider/Layers/GrokAdapter.ts
  • apps/server/src/provider/Layers/OpenCodeAdapter.ts
  • apps/server/src/provider/Services/ProviderAdapter.ts
  • apps/server/src/server.test.ts
  • apps/server/src/server.ts
  • apps/server/src/ws.ts
  • apps/web/src/components/ChatView.logic.test.ts
  • apps/web/src/components/ChatView.logic.ts
  • apps/web/src/components/ChatView.tsx
  • apps/web/src/components/chat/AgentProfilePicker.logic.ts
  • apps/web/src/components/chat/AgentProfilePicker.test.ts
  • apps/web/src/components/chat/AgentProfilePicker.tsx
  • apps/web/src/components/chat/ChatComposer.tsx
  • apps/web/src/components/settings/AgentsSettings.logic.test.ts
  • apps/web/src/components/settings/AgentsSettings.logic.ts
  • apps/web/src/components/settings/AgentsSettings.test.tsx
  • apps/web/src/components/settings/AgentsSettings.tsx
  • apps/web/src/components/settings/RulesSettings.logic.test.ts
  • apps/web/src/components/settings/RulesSettings.logic.ts
  • apps/web/src/components/settings/RulesSettings.test.tsx
  • apps/web/src/components/settings/RulesSettings.tsx
  • apps/web/src/components/settings/SettingsSidebarNav.tsx
  • apps/web/src/components/settings/settingsSearch.ts
  • apps/web/src/routeTree.gen.ts
  • apps/web/src/routes/settings.agents.tsx
  • apps/web/src/state/agents.ts
  • docs/internals/agents.md
  • docs/internals/glossary.md
  • docs/user/agents.md
  • packages/client-runtime/package.json
  • packages/client-runtime/src/state/agents.ts
  • packages/contracts/src/agentRefs.test.ts
  • packages/contracts/src/agentRefs.ts
  • packages/contracts/src/agents.test.ts
  • packages/contracts/src/agents.ts
  • packages/contracts/src/index.ts
  • packages/contracts/src/orchestration.ts
  • packages/contracts/src/providerRuntime.ts
  • packages/contracts/src/rpc.ts
  • packages/contracts/src/t3ProjectFile.test.ts
  • packages/contracts/src/t3ProjectFile.ts
  • packages/shared/package.json
  • packages/shared/src/agentRuleGlobs.test.ts
  • packages/shared/src/agentRuleGlobs.ts

Comment thread apps/mobile/src/features/settings/agentProfile.logic.ts Outdated
Comment thread apps/mobile/src/features/settings/agentProfile.logic.ts
Comment thread apps/mobile/src/features/settings/agentRule.logic.ts
Comment thread apps/mobile/src/state/use-thread-composer-state.ts
Comment thread apps/server/src/agents/AgentCatalog.ts
Comment thread apps/server/src/persistence/Migrations/039_AgentRuns.ts
Comment thread apps/server/src/ws.ts
Comment thread apps/web/src/components/settings/AgentsSettings.tsx
Comment thread apps/web/src/components/settings/RulesSettings.tsx Outdated
Comment thread apps/web/src/components/settings/RulesSettings.tsx
@megascan
megascan force-pushed the agent/native-agent-orchestration branch from 091b57d to 4195a0b Compare August 7, 2026 19:19
@megascan

megascan commented Aug 7, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 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.

@megascan
megascan force-pushed the agent/native-agent-orchestration branch from 4195a0b to 2ec33ac Compare August 7, 2026 19:42
@megascan

megascan commented Aug 7, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 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.

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up on the earlier findings: the standalone *Shape interfaces, the AgentRuleStore message getters, and the duplicated AgentProfileServices.layer in ws.ts are all resolved, and the hook/prompt/orchestration errors now carry structural attributes plus a real cause. One retained issue: several pure validation failures now manufacture an Error (or default one) purely to satisfy a cause field that is required, which the conventions call out explicitly. Three inline notes below.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/agents/AgentOrchestrationLive.ts Outdated
Comment thread apps/server/src/agents/AgentHookRunner.ts Outdated
Comment thread apps/server/src/agents/AgentPromptResolver.ts Outdated
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts Outdated
Comment thread apps/server/src/agents/AgentHookRunner.ts Outdated
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts Outdated
Comment thread apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts Outdated
Comment thread apps/server/src/agents/AgentPromptResolver.ts Outdated
Comment thread apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx Outdated
Comment thread apps/server/src/agents/run/AgentRunReactor.ts
Comment thread apps/server/src/agents/run/AgentRun.ts
Comment thread apps/server/src/agents/run/AgentRunDeadlineReactor.ts Outdated

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

🧹 Nitpick comments (2)
apps/server/src/agents/prompt/RuleMatcher.ts (1)

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

Remove redundant return type annotations.

TypeScript infers these return types from the implementations. Keep annotations where they define required parameter or public data shapes.

As per coding guidelines, “Prefer inferred types over explicit annotations and do not use any.”

Also applies to: 33-33, 74-74, 101-101, 117-117, 120-120, 163-166, 173-176, 184-184

🤖 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 `@apps/server/src/agents/prompt/RuleMatcher.ts` at line 21, Remove redundant
explicit return type annotations from the identified getters and methods in
RuleMatcher, including get message and the additional referenced locations,
while preserving annotations that define required parameter or public data
shapes. Keep the implementations and inferred return behavior unchanged, and do
not introduce any.

Source: Coding guidelines

apps/server/src/agents/AgentOrchestrationLive.ts (1)

822-831: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Replace Option.getOrThrow with a typed failure.

Line 830 converts a missing run into an unhandled defect. Every other failure in spawn maps into AgentProfileInvalidError. An MCP caller receives a typed error in all other paths and an untyped defect here.

♻️ Proposed refactor
       const run = yield* runs.get(runId).pipe(
         Effect.mapError((cause) =>
           invalid("Could not reload the Agent run.", {
             operation: "run-reload",
             cause,
             runId,
           }),
         ),
-        Effect.map(Option.getOrThrow),
+        Effect.flatMap(
+          Option.match({
+            onNone: () =>
+              Effect.fail(
+                invalid("The Agent run disappeared after it started.", {
+                  operation: "run-reload",
+                  runId,
+                }),
+              ),
+            onSome: Effect.succeed,
+          }),
+        ),
       );
🤖 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 `@apps/server/src/agents/AgentOrchestrationLive.ts` around lines 822 - 831,
Update the run reload flow in spawn around runs.get and Option.getOrThrow so a
missing run produces the same typed AgentProfileInvalidError path as other
failures instead of an unhandled defect. Map the empty Option to invalid with
the existing run-reload operation context and runId, while preserving the
current successful run value and runs.get error mapping.
🤖 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 `@apps/mobile/src/features/settings/agentSettings.logic.ts`:
- Around line 1-5: Update parseRequiredNumber to parse the trimmed input once,
reject results that are not finite—including NaN—alongside the existing
required-value validation, and remove its explicit number return type so
TypeScript infers it.

In `@apps/server/src/agents/AgentOrchestrationLive.ts`:
- Around line 693-718: Update failSpawn to clean up isolated Git worktrees
before deleting the child thread when target.workspace.mode is
"isolated-worktree". Track successful createWorktree completion in prepareThread
and only invoke the worktree-removal operation from failSpawn when that creation
succeeded, preserving existing failure dispatch behavior.
- Around line 584-607: Update the agent-run.request handling around the visible
compileAgentPrompt flow to apply the same lineage token and estimated-cost
budget checks already used for follow-up handling. Validate the requested child
run before it is spawned, reject over-budget requests through the existing error
path, and preserve the current depth, run-count, and concurrency checks.
- Around line 52-58: Update the AgentProfileInvalidError construction to omit
the cause property when context?.cause is undefined, using the same
conditional-spread pattern as profileId and runId; preserve the existing cause
value whenever one is provided.

In `@apps/server/src/agents/prompt/RuleMatcher.ts`:
- Around line 241-259: Update the rule-content accumulation in the loop over
matched.rules to measure the serialized output rather than only rule.body:
construct each non-empty rule’s header/body chunk, include its "\n\n" separator
as emitted by chunks.join("\n\n"), and check the resulting byte count against
maxBytes before appending. Preserve empty-rule behavior and report the
serialized size in AgentRuleContentOverflowError.
- Around line 120-160: Replace the backtracking RegExp construction in globRegex
with a linear-time glob-matching implementation, ensuring patterns containing
repeated or overlapping wildcards such as **a cannot cause exponential work when
tested against a non-matching path. Preserve the existing glob semantics for *,
**, ?, character classes, and alternations, and update callers to use the safe
matcher instead of expression.test.

---

Nitpick comments:
In `@apps/server/src/agents/AgentOrchestrationLive.ts`:
- Around line 822-831: Update the run reload flow in spawn around runs.get and
Option.getOrThrow so a missing run produces the same typed
AgentProfileInvalidError path as other failures instead of an unhandled defect.
Map the empty Option to invalid with the existing run-reload operation context
and runId, while preserving the current successful run value and runs.get error
mapping.

In `@apps/server/src/agents/prompt/RuleMatcher.ts`:
- Line 21: Remove redundant explicit return type annotations from the identified
getters and methods in RuleMatcher, including get message and the additional
referenced locations, while preserving annotations that define required
parameter or public data shapes. Keep the implementations and inferred return
behavior unchanged, and do not introduce any.
🪄 Autofix

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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5daa31b4-9fa3-4d8e-96b2-d0b2d7a434ce

📥 Commits

Reviewing files that changed from the base of the PR and between 4195a0b and 2ec33ac.

📒 Files selected for processing (31)
  • apps/mobile/src/features/settings/agentProfile.logic.test.ts
  • apps/mobile/src/features/settings/agentProfile.logic.ts
  • apps/mobile/src/features/settings/agentRule.logic.test.ts
  • apps/mobile/src/features/settings/agentRule.logic.ts
  • apps/mobile/src/features/settings/agentSettings.logic.ts
  • apps/mobile/src/state/use-composer-drafts.test.ts
  • apps/server/src/agents/AgentCatalog.test.ts
  • apps/server/src/agents/AgentCatalog.ts
  • apps/server/src/agents/AgentOrchestrationLive.test.ts
  • apps/server/src/agents/AgentOrchestrationLive.ts
  • apps/server/src/agents/AgentPromptResolver.test.ts
  • apps/server/src/agents/AgentPromptResolver.ts
  • apps/server/src/agents/prompt/RuleMatcher.ts
  • apps/server/src/agents/prompt/prompt.test.ts
  • apps/server/src/agents/run/AgentRun.test.ts
  • apps/server/src/agents/run/AgentRun.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.ts
  • apps/server/src/agents/run/AgentRunReactor.ts
  • apps/server/src/mcp/McpSessionRegistry.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts
  • apps/server/src/persistence/Migrations/039_AgentRuns.test.ts
  • apps/server/src/persistence/Migrations/039_AgentRuns.ts
  • apps/server/src/ws.ts
  • apps/web/src/components/settings/AgentsSettings.logic.test.ts
  • apps/web/src/components/settings/AgentsSettings.logic.ts
  • apps/web/src/components/settings/AgentsSettings.test.tsx
  • apps/web/src/components/settings/AgentsSettings.tsx
  • apps/web/src/components/settings/RulesSettings.logic.test.ts
  • apps/web/src/components/settings/RulesSettings.logic.ts
  • apps/web/src/components/settings/RulesSettings.tsx
  • docs/user/agents.md
🚧 Files skipped from review as they are similar to previous changes (24)
  • apps/mobile/src/features/settings/agentProfile.logic.test.ts
  • apps/web/src/components/settings/AgentsSettings.logic.test.ts
  • apps/server/src/persistence/Migrations/039_AgentRuns.test.ts
  • apps/web/src/components/settings/RulesSettings.logic.test.ts
  • apps/server/src/agents/AgentPromptResolver.test.ts
  • apps/server/src/agents/prompt/prompt.test.ts
  • apps/mobile/src/features/settings/agentRule.logic.test.ts
  • apps/web/src/components/settings/AgentsSettings.logic.ts
  • apps/server/src/mcp/McpSessionRegistry.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.ts
  • apps/server/src/ws.ts
  • docs/user/agents.md
  • apps/web/src/components/settings/RulesSettings.tsx
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts
  • apps/mobile/src/features/settings/agentProfile.logic.ts
  • apps/web/src/components/settings/AgentsSettings.tsx
  • apps/mobile/src/features/settings/agentRule.logic.ts
  • apps/server/src/agents/AgentCatalog.test.ts
  • apps/server/src/persistence/Migrations/039_AgentRuns.ts
  • apps/web/src/components/settings/RulesSettings.logic.ts
  • apps/server/src/agents/run/AgentRun.test.ts
  • apps/server/src/agents/run/AgentRun.ts
  • apps/server/src/agents/AgentPromptResolver.ts
  • apps/server/src/agents/run/AgentRunReactor.ts

Comment thread apps/mobile/src/features/settings/agentSettings.logic.ts Outdated
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts Outdated
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts
Comment thread apps/server/src/agents/prompt/RuleMatcher.ts Outdated
Comment thread apps/server/src/agents/prompt/RuleMatcher.ts

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on error attribute safety in the new Agent orchestration code. Earlier rounds' findings (standalone *Shape interfaces, missing message getters, invented cause values, duplicated AgentProfileServices layer) look addressed.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/agents/AgentOrchestrationLive.ts Outdated
@megascan

megascan commented Aug 7, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 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.

Comment thread apps/server/src/agents/AgentOrchestrationLive.ts
Comment thread apps/web/src/components/settings/RulesSettings.tsx
Comment thread apps/server/src/agents/run/AgentRunReactor.ts
Comment thread packages/contracts/src/agents.ts
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts Outdated
Comment thread apps/server/src/ws.ts Outdated

@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.

Caution

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

⚠️ Outside diff range comments (1)
apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx (1)

257-295: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Add failure handling to the archive and restore handlers.

saveRuleDocument and save wrap their awaited command in try/catch/finally and show an error message. archiveRestoreRule and archiveRestore use try/finally only. If command(...) rejects instead of returning a failure result, the rejection escapes through () => void archiveRestoreRule(), the user sees no message, and an unhandled promise rejection is produced.

Add a catch branch that sets the corresponding error state.

🛠️ Proposed fix for `archiveRestoreRule`
       setRuleNotice(selectedRuleSummary.archivedAt ? "Rule restored." : "Rule archived.");
       catalog.refresh();
+    } catch (caught) {
+      setRuleError(caught instanceof Error ? caught.message : "The rule could not be updated.");
     } finally {
       ruleCommandInFlight.current = false;
       setRuleCommandPending(false);
     }

Also applies to: 349-387

🤖 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 `@apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx` around lines
257 - 295, Update archiveRestoreRule and the corresponding archiveRestore
handler to add catch branches around their awaited command calls, setting the
appropriate rule error state when a rejection occurs. Preserve the existing
early returns, success handling, and finally blocks so command-in-flight state
is always cleared.
🧹 Nitpick comments (2)
apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx (1)

43-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Share diagnosticLabel instead of copying it.

The same helper exists in apps/web/src/components/settings/AgentsSettings.tsx and apps/web/src/components/settings/RulesSettings.tsx. Three copies of one formatting rule will drift. Move the helper into shared client code and import it in all three screens.

As per coding guidelines, "shared logic belongs in packages/client-runtime when appropriate."

🤖 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 `@apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx` around lines
43 - 44, Move the diagnosticLabel helper into shared client code under
packages/client-runtime, then import and reuse it in SettingsAgentsRouteScreen,
AgentsSettings, and RulesSettings. Remove each local duplicate while preserving
the existing diagnostic formatting behavior.

Source: Coding guidelines

apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts (1)

672-678: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the user-visible failure for the rejected profile.

The test verifies that no prompt resolution, session start, or turn send occurs. It does not verify what the user sees. Add a read-model assertion after harness.drain() that the thread records the incompatibility failure. That protects against a silent-drop regression where the turn is rejected without any activity.

As per coding guidelines, "Backend behavior changes must include focused tests for that behavior."

🤖 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 `@apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts` around
lines 672 - 678, Extend the test after harness.drain() to read the thread’s
activity/read model and assert it records the user-visible incompatibility
failure for the rejected profile. Keep the existing no-op assertions for
resolveAgentPrompt, startSession, and sendTurn, and use the test harness’s
established read-model accessors and failure representation.

Source: Coding guidelines

🤖 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.

Outside diff comments:
In `@apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx`:
- Around line 257-295: Update archiveRestoreRule and the corresponding
archiveRestore handler to add catch branches around their awaited command calls,
setting the appropriate rule error state when a rejection occurs. Preserve the
existing early returns, success handling, and finally blocks so
command-in-flight state is always cleared.

---

Nitpick comments:
In `@apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx`:
- Around line 43-44: Move the diagnosticLabel helper into shared client code
under packages/client-runtime, then import and reuse it in
SettingsAgentsRouteScreen, AgentsSettings, and RulesSettings. Remove each local
duplicate while preserving the existing diagnostic formatting behavior.

In `@apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts`:
- Around line 672-678: Extend the test after harness.drain() to read the
thread’s activity/read model and assert it records the user-visible
incompatibility failure for the rejected profile. Keep the existing no-op
assertions for resolveAgentPrompt, startSession, and sendTurn, and use the test
harness’s established read-model accessors and failure representation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7370eb5b-bfc2-4cbe-9684-93259c1edb44

📥 Commits

Reviewing files that changed from the base of the PR and between 2ec33ac and 372874b.

📒 Files selected for processing (24)
  • apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
  • apps/server/integration/OrchestrationEngineHarness.integration.ts
  • apps/server/src/agents/AgentCatalog.ts
  • apps/server/src/agents/AgentHookRunner.test.ts
  • apps/server/src/agents/AgentHookRunner.ts
  • apps/server/src/agents/AgentOrchestrationLive.test.ts
  • apps/server/src/agents/AgentOrchestrationLive.ts
  • apps/server/src/agents/AgentPromptResolver.test.ts
  • apps/server/src/agents/AgentPromptResolver.ts
  • apps/server/src/agents/prompt/RuleMatcher.ts
  • apps/server/src/agents/prompt/prompt.test.ts
  • apps/server/src/agents/run/AgentRun.test.ts
  • apps/server/src/agents/run/AgentRun.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.test.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.ts
  • apps/server/src/agents/run/AgentRunReactor.test.ts
  • apps/server/src/agents/run/AgentRunReactor.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
  • apps/server/src/ws.ts
  • apps/web/src/components/settings/AgentsSettings.tsx
  • apps/web/src/components/settings/RulesSettings.tsx
  • packages/contracts/src/agents.test.ts
  • packages/contracts/src/agents.ts
🚧 Files skipped from review as they are similar to previous changes (14)
  • apps/server/integration/OrchestrationEngineHarness.integration.ts
  • apps/server/src/agents/prompt/prompt.test.ts
  • apps/server/src/agents/AgentHookRunner.test.ts
  • apps/server/src/ws.ts
  • apps/server/src/agents/run/AgentRun.ts
  • apps/server/src/agents/AgentHookRunner.ts
  • apps/web/src/components/settings/AgentsSettings.tsx
  • apps/server/src/agents/run/AgentRunDeadlineReactor.ts
  • apps/server/src/agents/prompt/RuleMatcher.ts
  • apps/server/src/agents/run/AgentRun.test.ts
  • apps/server/src/agents/AgentPromptResolver.ts
  • apps/web/src/components/settings/RulesSettings.tsx
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
  • packages/contracts/src/agents.ts

Comment thread apps/server/src/agents/AgentOrchestrationLive.ts
Comment thread apps/server/src/agents/run/AgentRun.ts Outdated
Comment thread apps/server/src/agents/run/AgentRunReactor.ts Outdated
Comment thread apps/server/src/ws.ts
Comment thread apps/server/src/agents/prompt/RuleMatcher.ts
@megascan
megascan force-pushed the agent/native-agent-orchestration branch from 0dd2d15 to e8bc73b Compare August 7, 2026 21:06
Comment thread apps/server/src/agents/prompt/RuleMatcher.ts
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts Outdated
Comment thread apps/server/src/agents/AgentRuleStore.ts Outdated
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts
Comment thread apps/server/src/agents/AgentProfileStore.ts
Comment thread apps/server/src/agents/AgentRuleStore.ts Outdated
Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/server/src/provider/Layers/OpenCodeAdapter.ts Outdated
Comment thread apps/server/src/agents/run/AgentRunReactor.ts
Comment thread apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx Outdated
@megascan

megascan commented Aug 7, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 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.

Comment thread apps/web/src/components/settings/AgentsSettings.tsx
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts
Comment thread apps/web/src/components/chat/ChatComposer.tsx Outdated
Comment thread apps/server/src/agents/run/AgentRunReactor.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: 3

Caution

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

⚠️ Outside diff range comments (1)
apps/server/src/provider/Layers/OpenCodeAdapter.ts (1)

1714-1719: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Rebuild the OpenCode adapter when provider settings change.

OpenCodeDriver.create calls makeOpenCodeAdapter once, while makeManagedServerProvider only updates the snapshot/settings stream. If serverUrl changes, startSession can target the new URL while capabilities.agentRuntime still reports the URL captured at driver creation.

🤖 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 `@apps/server/src/provider/Layers/OpenCodeAdapter.ts` around lines 1714 - 1719,
Update the OpenCode adapter lifecycle around makeOpenCodeAdapter and
makeManagedServerProvider so the adapter is recreated whenever provider
settings, especially serverUrl, change rather than only updating the
snapshot/settings stream. Ensure startSession and capabilities.agentRuntime both
use the current settings and remain consistent after a URL change.
🧹 Nitpick comments (20)
apps/server/src/agents/prompt/RuleMatcher.ts (1)

69-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document that normalizeWorkspaceRelativePath throws.

The function is exported and throws AgentRulePathError on four separate branches. The doc comment describes the normalization but does not state the failure mode. An external caller that omits a try/catch will surface an uncaught error.

Add the throw contract to the comment.

🤖 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 `@apps/server/src/agents/prompt/RuleMatcher.ts` around lines 69 - 99, Update
the doc comment for normalizeWorkspaceRelativePath to explicitly state that it
throws AgentRulePathError when the supplied path is invalid, while preserving
the existing normalization description and implementation.
apps/server/src/agents/AgentProjectFileCoordinator.ts (2)

35-38: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Document that workspaceRoot must already be canonical.

The lock key is the raw string. Two spellings of the same directory, for example a symlink path and its realPath, map to two different semaphores and give no mutual exclusion. AgentProfileStore.writeProjectReference resolves realPath before it calls this function, but the precondition is not stated anywhere.

State the precondition on the service method, or normalize the key inside lockFor.

♻️ Proposed change
 export class AgentProjectFileCoordinator extends Context.Service<
   AgentProjectFileCoordinator,
   {
+    /**
+     * Serialize `effect` against other holders of the same workspace lock.
+     * Callers must pass a canonicalized root (for example the result of
+     * `FileSystem.realPath`); the lock key is compared as a plain string.
+     */
     readonly withWorkspaceLock: <A, E, R>(
🤖 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 `@apps/server/src/agents/AgentProjectFileCoordinator.ts` around lines 35 - 38,
Document on the withWorkspaceLock service method that workspaceRoot must already
be canonical (realPath-resolved) before use, preserving the existing lockFor
keying behavior; alternatively, normalize workspaceRoot inside lockFor so
equivalent directory spellings share the same semaphore.

17-33: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

locks grows without eviction.

lockFor inserts one Semaphore per distinct workspaceRoot string and never removes it. The server is long-lived, and the PR adds isolated worktrees that can produce many distinct roots over a session. Each entry is small, so this is not urgent, but the map has no upper bound.

Consider keying by a bounded LRU, or removing a lock when it has no waiters.

🤖 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 `@apps/server/src/agents/AgentProjectFileCoordinator.ts` around lines 17 - 33,
Update AgentProjectFileCoordinator.make and its lockFor helper so locks are
evicted instead of retained indefinitely for every distinct workspaceRoot. Use a
bounded LRU or remove entries once their Semaphore has no waiters, while
preserving serialization for concurrent operations sharing the same
workspaceRoot.
apps/server/src/agents/run/AgentRunReactor.ts (1)

213-258: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Log the discarded onError hook failures and the dropped usage decode.

Two failures are currently silent:

  • Lines 224, 239, and 250 use Effect.ignore on runTerminalHook(run, "onError"). Keeping the original failure as the run failure is correct, but an operator gets no signal when the onError hook itself fails or when its prerequisites are unavailable.
  • Line 213 uses decodeUsage, which returns an Option. A payload that does not satisfy RuntimeTaskUsage yields None, and the run is recorded with no usage. Token and cost budgets are then under-counted with no trace.

Replace Effect.ignore with a log-and-continue, and log a warning when the usage decode returns None.

♻️ Sketch
-        yield* runTerminalHook(run, "onError").pipe(Effect.ignore);
+        yield* runTerminalHook(run, "onError").pipe(
+          Effect.catchCause((cause) =>
+            Effect.logWarning("Agent onError hook failed", { runId: run.id, cause }),
+          ),
+        );
🤖 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 `@apps/server/src/agents/run/AgentRunReactor.ts` around lines 213 - 258, Update
the turn-completion, turn-aborted, and runtime-error paths in the
AgentRunReactor to log failures from runTerminalHook(run, "onError") while still
continuing and preserving the original run failure; replace Effect.ignore with
the repository’s established log-and-continue pattern. After decodeUsage, emit a
warning when the result is None, then retain the existing optional usage
dispatch behavior.
apps/server/src/agents/AgentCatalog.ts (1)

592-676: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the repeated AgentCatalogDocumentError mapper.

The same Effect.mapError block that builds an AgentCatalogDocumentError with code: "invalid-document" appears six times across profileSummary, ruleSummary, profileDocument, and ruleDocument. A single helper reduces the repetition and keeps the error shape consistent.

♻️ Sketch: one shared mapper
+  const invalidDocument = (kind: CatalogEntryKind, source: Source) => (cause: unknown) =>
+    new AgentCatalogDocumentError({
+      kind,
+      scope: source.ref.scope,
+      id: source.ref.id,
+      sourcePath: source.sourcePath,
+      code: "invalid-document",
+      cause,
+    });

Each loader then uses Effect.mapError(invalidDocument("profile", source)).

🤖 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 `@apps/server/src/agents/AgentCatalog.ts` around lines 592 - 676, Extract the
repeated AgentCatalogDocumentError construction into a shared invalidDocument
mapper helper that accepts the document kind and source, preserves the existing
scope, id, sourcePath, code, and cause fields, and returns the mapped error.
Replace the duplicated Effect.mapError blocks in profileSummary, ruleSummary,
profileDocument, and ruleDocument with this helper.
apps/server/src/agents/AgentOrchestrationLive.test.ts (2)

446-460: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Do not point the failure test at the repository working directory.

The test passes process.cwd() and path.join(process.cwd(), "apps") as worktree paths. The result then depends on the working directory that the test runner selects and on the presence of an apps directory below it. GitFailureLayer stubs ProcessRunner, so the paths only need to exist for any filesystem checks. Use makeTempDirectoryScoped, as the other integration tests in this file do. That removes the dependency on the runner working directory and keeps the test away from the real repository.

🤖 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 `@apps/server/src/agents/AgentOrchestrationLive.test.ts` around lines 446 -
460, The isolated-worktree failure test currently depends on the repository
working directory and its apps directory. Update the test around “does not
expose Git command output in isolated-worktree failure details” to create a
scoped temporary directory with makeTempDirectoryScoped, derive both worktree
paths from it, and retain the existing GitFailureLayer and assertions.

143-164: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Strengthen the minimumBudgets assertion.

Every field of effectiveParentBudget is smaller than the matching field of childProfileBudget. The expected result is the parent budget unchanged. A function that ignores the first argument and returns the second passes this test. Make one child field smaller than the parent field, so the assertion proves a per-field minimum.

♻️ Proposed change
   const childProfileBudget = {
     maxRuns: 8,
     maxConcurrency: 4,
     maxDepth: 4,
-    maxWallTimeMinutes: 30,
+    maxWallTimeMinutes: 2,
     maxTotalTokens: 100_000,
     maxEstimatedCostUsd: 10,
   };
@@
   NodeAssert.deepEqual(minimumBudgets(childProfileBudget, effectiveParentBudget), {
     ...effectiveParentBudget,
+    maxWallTimeMinutes: 2,
   });
🤖 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 `@apps/server/src/agents/AgentOrchestrationLive.test.ts` around lines 143 -
164, Strengthen the test for minimumBudgets by making one field in
childProfileBudget smaller than the corresponding effectiveParentBudget field,
while leaving the other fields larger. Update the expected result so that field
uses the child value and the remaining fields retain the parent values,
verifying per-field minimum behavior.
apps/server/src/agents/AgentRuleStore.test.ts (1)

139-140: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the reference count by parsing t3.json.

The test name states that one checked-in project rule reference is written. The assertion counts raw substring occurrences, which equals 2 only because the id and the path both contain project-typescript. Parse the file and assert the length of the rules array instead. The same pattern exists in apps/server/src/agents/AgentProfileStore.test.ts.

🤖 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 `@apps/server/src/agents/AgentRuleStore.test.ts` around lines 139 - 140, Update
the test assertion after reading t3.json to parse the JSON and assert the rules
array length is one, rather than counting raw “project-typescript” substring
occurrences. Apply the same approach in the corresponding AgentProfileStore test
pattern.
apps/server/src/agents/prompt/prompt.test.ts (2)

216-247: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace the manual try/catch capture with a throwing assertion.

Both tests declare a mutable error variable, wrap the call in try/catch, and then check the captured value. assert.throws accepts a predicate and expresses the same contract in one statement. It also fails clearly when the call does not throw, instead of testing undefined against the type guard.

♻️ Proposed change
-  let error: unknown;
-  try {
-    compileAgentRules({ rules: [rule] }, 4);
-  } catch (caught) {
-    error = caught;
-  }
-  assert.isTrue(isAgentRuleContentOverflowError(error));
-  assert.equal((error as { limitBytes?: number }).limitBytes, 4);
+  assert.throws(
+    () => compileAgentRules({ rules: [rule] }, 4),
+    (caught: unknown) =>
+      isAgentRuleContentOverflowError(caught) && caught.limitBytes === 4,
+  );
🤖 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 `@apps/server/src/agents/prompt/prompt.test.ts` around lines 216 - 247, Replace
the manual try/catch error capture in both tests with assert.throws calls around
compileAgentRules, using a predicate that validates
isAgentRuleContentOverflowError and the expected limitBytes value for the first
test. Keep the existing successful compilation assertions and byte-count
behavior unchanged.

202-214: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

State how this test detects a backtracking regression.

The pattern uses 48 overlapping deep-star groups against a 400-character path. If the matcher regressed to exponential backtracking, this test would not fail on an assertion. It would hang until the runner timeout expires. Add a comment that records this intent, so a later reader does not shrink the input and remove the protection.

🤖 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 `@apps/server/src/agents/prompt/prompt.test.ts` around lines 202 - 214, Add a
concise comment above the test case describing that its intentionally large
overlapping-wildcard input guards against exponential backtracking, which would
cause the test to hang or time out rather than fail an assertion. Keep the
existing pattern and path sizes unchanged.
apps/server/src/agents/AgentProfileStore.test.ts (1)

211-212: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the reference count by parsing t3.json.

The test name states that the t3.json reference stays singular. The assertion counts raw substring occurrences, which equals 2 only because the id and the path both contain project-reviewer. A format change, such as dropping the id or renaming the file, breaks this test without a behavior change. Parse the file and assert the length of the agents array.

♻️ Proposed change
-      const projectFile = yield* fileSystem.readFileString(path.join(workspace, "t3.json"));
-      assert.equal((projectFile.match(/project-reviewer/g) ?? []).length, 2);
+      const projectFile = JSON.parse(
+        yield* fileSystem.readFileString(path.join(workspace, "t3.json")),
+      ) as { readonly agents?: ReadonlyArray<{ readonly id: string }> };
+      assert.deepEqual(
+        (projectFile.agents ?? []).map((entry) => entry.id),
+        ["project-reviewer"],
+      );
🤖 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 `@apps/server/src/agents/AgentProfileStore.test.ts` around lines 211 - 212,
Update the t3.json assertion in the relevant test to parse projectFile as JSON
and assert the length of its agents array is 1, rather than counting raw
“project-reviewer” substring occurrences. Keep the test focused on the singular
agent reference behavior.
apps/server/src/agents/AgentCatalog.test.ts (2)

353-354: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Explain the expected project-load count.

assert.equal(yield* Ref.get(projectLoads), 2) states the contract that the test name describes, but the value 2 is unexplained. State why one validate call loads the project file twice, for example once for profiles and once for rules. Without that, a future change that makes the count 1 or 3 gives no signal about which behavior regressed.

🤖 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 `@apps/server/src/agents/AgentCatalog.test.ts` around lines 353 - 354, Clarify
the expected project-load count in the test around validation by documenting why
one validate call increments projectLoads twice, specifically identifying the
separate profile and rules loads. Keep the assertion at 2 and place the
explanation adjacent to the assertion so changes to either load path are
distinguishable.

358-438: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the shared 101-entry profile fixture.

Both tests build an identical 101-element profile array. The literal is 15 lines long and repeats every field. Extract one makeProfiles(count) helper and call it from both tests. This keeps the two bound assertions focused on the bound they verify.

🤖 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 `@apps/server/src/agents/AgentCatalog.test.ts` around lines 358 - 438, Extract
the duplicated 101-entry profile construction from the two tests into a shared
makeProfiles(count) helper near the test cases, preserving the existing
AgentProfileSummary fields and generated IDs. Replace each inline profiles
Array.from block with makeProfiles(101), leaving the assertions and
rule/diagnostic fixtures unchanged.
apps/web/src/components/settings/AgentsSettings.logic.ts (2)

233-248: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Share one sort helper with the rules editor.

sortAgentProfiles and sortAgentRules in apps/web/src/components/settings/RulesSettings.logic.ts implement the same ordering: active before archived, environment before project, then name, then id. The generic constraints are identical. Extract one helper and call it from both modules.

🤖 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 `@apps/web/src/components/settings/AgentsSettings.logic.ts` around lines 233 -
248, Extract the shared ordering logic from sortAgentProfiles into a reusable
sort helper with the same generic constraints, then update both
sortAgentProfiles and sortAgentRules to call it. Preserve the ordering of active
before archived, environment before project, followed by name and id, and remove
the duplicated implementation from the settings modules.

176-207: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Parse each optional field once.

parseOptionalInteger and parseOptionalNumber run twice for every optional field: once in the spread condition and once in the value. The label string is also repeated at each call site. A future edit can change one copy and not the other, which then produces a mismatched error message. Compute each value once and spread it conditionally.

♻️ Proposed change
+  const sharedWriteConcurrency = parseOptionalInteger(
+    draft.sharedWriteConcurrency,
+    "Shared write concurrency",
+  );
+  const maxTotalTokens = parseOptionalInteger(draft.maxTotalTokens, "Maximum total tokens");
+  const maxEstimatedCostUsd = parseOptionalNumber(
+    draft.maxEstimatedCostUsd,
+    "Maximum estimated cost",
+  );
   const document = {
@@
     workspace: {
       mode: draft.workspaceMode,
       access: draft.workspaceAccess,
-      ...(parseOptionalInteger(draft.sharedWriteConcurrency, "Shared write concurrency") ===
-      undefined
-        ? {}
-        : {
-            sharedWriteConcurrency: parseOptionalInteger(
-              draft.sharedWriteConcurrency,
-              "Shared write concurrency",
-            ),
-          }),
+      ...(sharedWriteConcurrency === undefined ? {} : { sharedWriteConcurrency }),
     },
@@
-      ...(parseOptionalInteger(draft.maxTotalTokens, "Maximum total tokens") === undefined
-        ? {}
-        : { maxTotalTokens: parseOptionalInteger(draft.maxTotalTokens, "Maximum total tokens") }),
-      ...(parseOptionalNumber(draft.maxEstimatedCostUsd, "Maximum estimated cost") === undefined
-        ? {}
-        : {
-            maxEstimatedCostUsd: parseOptionalNumber(
-              draft.maxEstimatedCostUsd,
-              "Maximum estimated cost",
-            ),
-          }),
+      ...(maxTotalTokens === undefined ? {} : { maxTotalTokens }),
+      ...(maxEstimatedCostUsd === undefined ? {} : { maxEstimatedCostUsd }),
🤖 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 `@apps/web/src/components/settings/AgentsSettings.logic.ts` around lines 176 -
207, Update the configuration-building logic around the workspace and budgets
fields to parse each optional value only once, including sharedWriteConcurrency,
maxTotalTokens, and maxEstimatedCostUsd. Store each parsed result using the
existing labels, then conditionally spread the corresponding property only when
its value is defined, ensuring validation and error messages cannot diverge.
apps/web/src/components/settings/RulesSettings.test.tsx (2)

1-26: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the archive control that the test name claims.

The test name mentions "reversible lifecycle controls". The rendered editor is created with isNew set, so RuleEditor does not render the Archive or Restore button. The assertions only check Save. Add a case with isNew={false} and archived both false and true, and assert the Archive and Restore labels. This matches the guideline that every way in has a corresponding way out and a way to see the state.

As per coding guidelines: "For stateful features, provide reverse transitions and visibility: every way in must have the corresponding way out and a way to see the state".

🤖 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 `@apps/web/src/components/settings/RulesSettings.test.tsx` around lines 1 - 26,
Expand the “renders file targeting and reversible lifecycle controls” test to
render RuleEditor with isNew={false} in both archived={false} and
archived={true} states, asserting the corresponding “Archive” and “Restore”
labels while preserving the existing field and Save assertions.

Source: Coding guidelines


44-46: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Do not depend on the rendered attribute order.

These regexes require disabled="" to appear before aria-label in the same tag. The order comes from the prop order inside the Input and Textarea wrappers in apps/web/src/components/settings/RulesSettings.tsx. If a wrapper spreads props differently, or a new prop is added, the assertions fail while the disabled behavior stays correct. Match the element by its aria-label first, then assert that the same tag contains disabled.

♻️ Proposed change
-    expect(markup).toMatch(/<input[^>]*disabled=""[^>]*aria-label="Rule name"/);
-    expect(markup).toMatch(/<textarea[^>]*disabled=""[^>]*aria-label="Rule file globs"/);
-    expect(markup).toMatch(/<textarea[^>]*disabled=""[^>]*aria-label="Rule instructions"/);
+    const disabledTag = (tag: string, label: string) =>
+      new RegExp(`<${tag}(?=[^>]*aria-label="${label}")(?=[^>]*disabled="")[^>]*>`);
+    expect(markup).toMatch(disabledTag("input", "Rule name"));
+    expect(markup).toMatch(disabledTag("textarea", "Rule file globs"));
+    expect(markup).toMatch(disabledTag("textarea", "Rule instructions"));
🤖 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 `@apps/web/src/components/settings/RulesSettings.test.tsx` around lines 44 -
46, Update the markup assertions in the RulesSettings tests to locate each input
or textarea by its aria-label first, then verify that the same element contains
disabled, without relying on attribute ordering.
apps/server/src/agents/run/AgentRunDeadlineReactor.test.ts (1)

76-97: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid the as casts on the repository and provider fakes.

repositoryFor builds a full object literal, then casts it with as AgentRunRepository["Service"]. The cast hides any drift between the fake and the real interface. If a method is added or a signature changes, the compiler stays silent and the test keeps passing against a stale contract. Type the literal directly with satisfies or an explicit return type, and remove the cast. providerFor uses as unknown as ProviderServiceShape, which is broader still; a partial helper with one Pick<ProviderServiceShape, "interruptTurn"> cast keeps the surface narrow.

As per coding guidelines: "Prefer inferred types over explicit annotations and do not use any."

🤖 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 `@apps/server/src/agents/run/AgentRunDeadlineReactor.test.ts` around lines 76 -
97, Update repositoryFor and providerFor to avoid broad as casts: make the
repository object satisfy AgentRunRepository["Service"] directly so interface
drift is checked, and narrow the provider fake to Pick<ProviderServiceShape,
"interruptTurn"> rather than casting through unknown. Preserve the existing
helper behavior while relying on inferred types where possible.

Source: Coding guidelines

apps/mobile/src/features/settings/agentRule.logic.test.ts (1)

48-66: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the parsed target instead of only a throw.

The test name states that the full target after the first colon is preserved. The second assertion only checks that buildAgentRuleDocument throws. It does not show which value was parsed, and it passes for any error, including an unrelated one. Assert the thrown message, or build a valid document and assert rule.profiles.

♻️ Proposed change
     expect(() =>
       buildAgentRuleDocument(
         {
           ...draftFromRule(),
           id: "target",
           name: "Target",
           profiles: "environment:reviewer:truncated",
         },
         null,
       ),
-    ).toThrow();
+    ).toThrow("reviewer:truncated");
🤖 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 `@apps/mobile/src/features/settings/agentRule.logic.test.ts` around lines 48 -
66, Update the second assertion in the buildAgentRuleDocument test to verify the
parsed target value after the first colon, rather than only asserting that an
error is thrown. Use a valid input or assert the specific result/error message
so the test confirms profiles preserves “reviewer:truncated” and cannot pass due
to an unrelated failure.
apps/web/src/components/settings/RulesSettings.logic.ts (1)

62-77: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Drop the invented revision value from new-document builders.

AgentRuleStore.save and AgentProfileStore.save compare only expectedRevision; baseline === null already prevents a conflict and causes a “new” error when an existing document is found. Returning revision: "a".repeat(64) makes new documents carry a valid revision that can collide later. Use a shared sentinel or omit the field in both buildAgentRuleDocument and buildAgentProfileDocument.

🤖 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 `@apps/web/src/components/settings/RulesSettings.logic.ts` around lines 62 -
77, Update buildAgentRuleDocument in
apps/web/src/components/settings/RulesSettings.logic.ts (lines 62-77) and
buildAgentProfileDocument in
apps/web/src/components/settings/AgentsSettings.logic.ts (lines 158-164) to stop
assigning "a".repeat(64) as the revision for new documents. Omit revision or use
the shared sentinel consistently in both builders, while preserving baseline
revisions for existing documents.
🤖 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 `@apps/server/src/agents/run/AgentRunReactor.ts`:
- Around line 104-131: Ensure the successful-run flow around
completeSuccessfulRun records a durable typed receipt when input.afterResult
completes, before dispatching command, and consults that receipt on retries to
skip re-executing the hook. Use the existing event-sourced receipt pattern and
preserve the current failure dispatch behavior for hook and budget-exhaustion
failures.
- Around line 23-27: Bound TERMINAL_EVENT_RETRY_SCHEDULE with a finite retry or
elapsed-time limit before it is consumed by Effect.catchCause, while preserving
its existing exponential backoff and 30-second maximum delay. Ensure permanently
failing provider events exhaust this budget and are skipped so the sequential
runForEach fiber can continue before the scheduled stop.

In `@apps/web/src/components/settings/RulesSettings.logic.ts`:
- Around line 53-61: Update the rule-save logic around decodeAgentRuleDocument
to catch decode failures and rethrow a readable error identifying the invalid
field, while preserving existing validation messages. Add an explicit priority
range check after the integer check so values outside -100 through 100 are
rejected before schema decoding. Apply the same readable decode-error handling
and priority-range validation to the profile builder in AgentsSettings.logic.ts.

---

Outside diff comments:
In `@apps/server/src/provider/Layers/OpenCodeAdapter.ts`:
- Around line 1714-1719: Update the OpenCode adapter lifecycle around
makeOpenCodeAdapter and makeManagedServerProvider so the adapter is recreated
whenever provider settings, especially serverUrl, change rather than only
updating the snapshot/settings stream. Ensure startSession and
capabilities.agentRuntime both use the current settings and remain consistent
after a URL change.

---

Nitpick comments:
In `@apps/mobile/src/features/settings/agentRule.logic.test.ts`:
- Around line 48-66: Update the second assertion in the buildAgentRuleDocument
test to verify the parsed target value after the first colon, rather than only
asserting that an error is thrown. Use a valid input or assert the specific
result/error message so the test confirms profiles preserves
“reviewer:truncated” and cannot pass due to an unrelated failure.

In `@apps/server/src/agents/AgentCatalog.test.ts`:
- Around line 353-354: Clarify the expected project-load count in the test
around validation by documenting why one validate call increments projectLoads
twice, specifically identifying the separate profile and rules loads. Keep the
assertion at 2 and place the explanation adjacent to the assertion so changes to
either load path are distinguishable.
- Around line 358-438: Extract the duplicated 101-entry profile construction
from the two tests into a shared makeProfiles(count) helper near the test cases,
preserving the existing AgentProfileSummary fields and generated IDs. Replace
each inline profiles Array.from block with makeProfiles(101), leaving the
assertions and rule/diagnostic fixtures unchanged.

In `@apps/server/src/agents/AgentCatalog.ts`:
- Around line 592-676: Extract the repeated AgentCatalogDocumentError
construction into a shared invalidDocument mapper helper that accepts the
document kind and source, preserves the existing scope, id, sourcePath, code,
and cause fields, and returns the mapped error. Replace the duplicated
Effect.mapError blocks in profileSummary, ruleSummary, profileDocument, and
ruleDocument with this helper.

In `@apps/server/src/agents/AgentOrchestrationLive.test.ts`:
- Around line 446-460: The isolated-worktree failure test currently depends on
the repository working directory and its apps directory. Update the test around
“does not expose Git command output in isolated-worktree failure details” to
create a scoped temporary directory with makeTempDirectoryScoped, derive both
worktree paths from it, and retain the existing GitFailureLayer and assertions.
- Around line 143-164: Strengthen the test for minimumBudgets by making one
field in childProfileBudget smaller than the corresponding effectiveParentBudget
field, while leaving the other fields larger. Update the expected result so that
field uses the child value and the remaining fields retain the parent values,
verifying per-field minimum behavior.

In `@apps/server/src/agents/AgentProfileStore.test.ts`:
- Around line 211-212: Update the t3.json assertion in the relevant test to
parse projectFile as JSON and assert the length of its agents array is 1, rather
than counting raw “project-reviewer” substring occurrences. Keep the test
focused on the singular agent reference behavior.

In `@apps/server/src/agents/AgentProjectFileCoordinator.ts`:
- Around line 35-38: Document on the withWorkspaceLock service method that
workspaceRoot must already be canonical (realPath-resolved) before use,
preserving the existing lockFor keying behavior; alternatively, normalize
workspaceRoot inside lockFor so equivalent directory spellings share the same
semaphore.
- Around line 17-33: Update AgentProjectFileCoordinator.make and its lockFor
helper so locks are evicted instead of retained indefinitely for every distinct
workspaceRoot. Use a bounded LRU or remove entries once their Semaphore has no
waiters, while preserving serialization for concurrent operations sharing the
same workspaceRoot.

In `@apps/server/src/agents/AgentRuleStore.test.ts`:
- Around line 139-140: Update the test assertion after reading t3.json to parse
the JSON and assert the rules array length is one, rather than counting raw
“project-typescript” substring occurrences. Apply the same approach in the
corresponding AgentProfileStore test pattern.

In `@apps/server/src/agents/prompt/prompt.test.ts`:
- Around line 216-247: Replace the manual try/catch error capture in both tests
with assert.throws calls around compileAgentRules, using a predicate that
validates isAgentRuleContentOverflowError and the expected limitBytes value for
the first test. Keep the existing successful compilation assertions and
byte-count behavior unchanged.
- Around line 202-214: Add a concise comment above the test case describing that
its intentionally large overlapping-wildcard input guards against exponential
backtracking, which would cause the test to hang or time out rather than fail an
assertion. Keep the existing pattern and path sizes unchanged.

In `@apps/server/src/agents/prompt/RuleMatcher.ts`:
- Around line 69-99: Update the doc comment for normalizeWorkspaceRelativePath
to explicitly state that it throws AgentRulePathError when the supplied path is
invalid, while preserving the existing normalization description and
implementation.

In `@apps/server/src/agents/run/AgentRunDeadlineReactor.test.ts`:
- Around line 76-97: Update repositoryFor and providerFor to avoid broad as
casts: make the repository object satisfy AgentRunRepository["Service"] directly
so interface drift is checked, and narrow the provider fake to
Pick<ProviderServiceShape, "interruptTurn"> rather than casting through unknown.
Preserve the existing helper behavior while relying on inferred types where
possible.

In `@apps/server/src/agents/run/AgentRunReactor.ts`:
- Around line 213-258: Update the turn-completion, turn-aborted, and
runtime-error paths in the AgentRunReactor to log failures from
runTerminalHook(run, "onError") while still continuing and preserving the
original run failure; replace Effect.ignore with the repository’s established
log-and-continue pattern. After decodeUsage, emit a warning when the result is
None, then retain the existing optional usage dispatch behavior.

In `@apps/web/src/components/settings/AgentsSettings.logic.ts`:
- Around line 233-248: Extract the shared ordering logic from sortAgentProfiles
into a reusable sort helper with the same generic constraints, then update both
sortAgentProfiles and sortAgentRules to call it. Preserve the ordering of active
before archived, environment before project, followed by name and id, and remove
the duplicated implementation from the settings modules.
- Around line 176-207: Update the configuration-building logic around the
workspace and budgets fields to parse each optional value only once, including
sharedWriteConcurrency, maxTotalTokens, and maxEstimatedCostUsd. Store each
parsed result using the existing labels, then conditionally spread the
corresponding property only when its value is defined, ensuring validation and
error messages cannot diverge.

In `@apps/web/src/components/settings/RulesSettings.logic.ts`:
- Around line 62-77: Update buildAgentRuleDocument in
apps/web/src/components/settings/RulesSettings.logic.ts (lines 62-77) and
buildAgentProfileDocument in
apps/web/src/components/settings/AgentsSettings.logic.ts (lines 158-164) to stop
assigning "a".repeat(64) as the revision for new documents. Omit revision or use
the shared sentinel consistently in both builders, while preserving baseline
revisions for existing documents.

In `@apps/web/src/components/settings/RulesSettings.test.tsx`:
- Around line 1-26: Expand the “renders file targeting and reversible lifecycle
controls” test to render RuleEditor with isNew={false} in both archived={false}
and archived={true} states, asserting the corresponding “Archive” and “Restore”
labels while preserving the existing field and Save assertions.
- Around line 44-46: Update the markup assertions in the RulesSettings tests to
locate each input or textarea by its aria-label first, then verify that the same
element contains disabled, without relying on attribute ordering.
🪄 Autofix

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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f8de1563-10e9-45fe-b5bc-748b6a40b4d9

📥 Commits

Reviewing files that changed from the base of the PR and between 372874b and 89c7064.

📒 Files selected for processing (52)
  • apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
  • apps/mobile/src/features/settings/agentProfile.logic.test.ts
  • apps/mobile/src/features/settings/agentProfile.logic.ts
  • apps/mobile/src/features/settings/agentRule.logic.test.ts
  • apps/mobile/src/features/settings/agentRule.logic.ts
  • apps/mobile/src/features/settings/agentSettings.logic.test.ts
  • apps/mobile/src/features/settings/agentSettings.logic.ts
  • apps/mobile/src/features/threads/NewTaskDraftScreen.tsx
  • apps/mobile/src/features/threads/ThreadComposer.tsx
  • apps/server/src/agents/AgentCatalog.test.ts
  • apps/server/src/agents/AgentCatalog.ts
  • apps/server/src/agents/AgentOrchestrationLive.test.ts
  • apps/server/src/agents/AgentOrchestrationLive.ts
  • apps/server/src/agents/AgentProfileServices.ts
  • apps/server/src/agents/AgentProfileStore.test.ts
  • apps/server/src/agents/AgentProfileStore.ts
  • apps/server/src/agents/AgentProjectFileCoordinator.ts
  • apps/server/src/agents/AgentRuleStore.test.ts
  • apps/server/src/agents/AgentRuleStore.ts
  • apps/server/src/agents/AgentStoreErrorMapping.test.ts
  • apps/server/src/agents/AgentStoreErrorMapping.ts
  • apps/server/src/agents/AgentWorkspaceRoot.test.ts
  • apps/server/src/agents/AgentWorkspaceRoot.ts
  • apps/server/src/agents/prompt/RuleMatcher.ts
  • apps/server/src/agents/prompt/prompt.test.ts
  • apps/server/src/agents/run/AgentRun.test.ts
  • apps/server/src/agents/run/AgentRun.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.test.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.ts
  • apps/server/src/agents/run/AgentRunReactor.test.ts
  • apps/server/src/agents/run/AgentRunReactor.ts
  • apps/server/src/provider/Layers/CursorAdapter.test.ts
  • apps/server/src/provider/Layers/CursorAdapter.ts
  • apps/server/src/provider/Layers/GrokAdapter.test.ts
  • apps/server/src/provider/Layers/GrokAdapter.ts
  • apps/server/src/provider/Layers/OpenCodeAdapter.test.ts
  • apps/server/src/provider/Layers/OpenCodeAdapter.ts
  • apps/server/src/ws.ts
  • apps/web/src/components/chat/AgentProfilePicker.logic.ts
  • apps/web/src/components/chat/AgentProfilePicker.test.ts
  • apps/web/src/components/chat/AgentProfilePicker.tsx
  • apps/web/src/components/chat/ChatComposer.logic.test.ts
  • apps/web/src/components/chat/ChatComposer.logic.ts
  • apps/web/src/components/chat/ChatComposer.tsx
  • apps/web/src/components/settings/AgentsSettings.logic.test.ts
  • apps/web/src/components/settings/AgentsSettings.logic.ts
  • apps/web/src/components/settings/AgentsSettings.tsx
  • apps/web/src/components/settings/RulesSettings.logic.test.ts
  • apps/web/src/components/settings/RulesSettings.logic.ts
  • apps/web/src/components/settings/RulesSettings.test.tsx
  • apps/web/src/components/settings/RulesSettings.tsx
  • packages/contracts/src/agents.ts
🚧 Files skipped from review as they are similar to previous changes (21)
  • apps/server/src/provider/Layers/CursorAdapter.ts
  • apps/mobile/src/features/threads/NewTaskDraftScreen.tsx
  • apps/server/src/agents/AgentProfileServices.ts
  • apps/server/src/provider/Layers/GrokAdapter.ts
  • apps/web/src/components/settings/RulesSettings.logic.test.ts
  • apps/mobile/src/features/settings/agentProfile.logic.ts
  • apps/mobile/src/features/settings/agentSettings.logic.ts
  • apps/mobile/src/features/settings/agentProfile.logic.test.ts
  • apps/server/src/agents/run/AgentRun.test.ts
  • apps/web/src/components/chat/AgentProfilePicker.test.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.ts
  • apps/web/src/components/settings/AgentsSettings.tsx
  • apps/mobile/src/features/threads/ThreadComposer.tsx
  • apps/server/src/agents/run/AgentRun.ts
  • packages/contracts/src/agents.ts
  • apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
  • apps/web/src/components/settings/RulesSettings.tsx
  • apps/server/src/ws.ts
  • apps/web/src/components/chat/ChatComposer.tsx
  • apps/server/src/agents/AgentRuleStore.ts
  • apps/server/src/agents/AgentOrchestrationLive.ts

Comment thread apps/server/src/agents/run/AgentRunReactor.ts
Comment thread apps/server/src/agents/run/AgentRunReactor.ts
Comment thread apps/web/src/components/settings/RulesSettings.logic.ts
@megascan

megascan commented Aug 7, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Head commit changed.

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.

Comment thread apps/web/src/components/chat/ChatComposer.logic.ts
Comment thread apps/server/src/agents/AgentOrchestrationLive.ts
Comment thread apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
@megascan

megascan commented Aug 7, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Head commit changed.

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.

@megascan

megascan commented Aug 7, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 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: 4

🤖 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 `@apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx`:
- Around line 569-574: Update the rules catalog rendering near the rules.length
check in SettingsAgentsRouteScreen to handle loading and error states before
showing the empty-catalog message. Mirror the existing profile catalog guards
around lines 509-521, using the rules catalog’s loading and error state symbols,
and preserve “No rules yet” only for a successfully loaded empty result.
- Around line 839-851: Update the Always apply Pressable to use an off-state
background when props.draft.alwaysApply is false, while preserving the primary
background when enabled. Add an accessibilityLabel identifying it as the “Always
apply” switch, matching the accessible labeling used by the nearby Show in chat
Agent picker switch.
- Around line 287-320: Add a catch handler to archiveRestoreRule, and likewise
to archiveRestore, so rejected command promises set an appropriate user-facing
rule error while preserving the existing context-key guard. Keep the finally
blocks responsible for clearing ruleCommandInFlight and ruleCommandPending,
ensuring void archiveRestoreRule() and the corresponding archiveRestore call do
not produce unhandled rejections.

In `@apps/web/src/components/settings/RulesSettings.tsx`:
- Around line 127-182: In the RulesSettings mutation flow, add shared isMutating
state used by both save and archiveRestore, set it before either command starts,
and clear it in a finally block so it resets on success or failure. Pass
isMutating to RuleEditor and disable both Save and Archive/Restore actions while
it is true, preventing concurrent submissions with stale expectedRevision
values.
🪄 Autofix

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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 778bef4d-4da2-4296-a024-f1fdc2fefd7c

📥 Commits

Reviewing files that changed from the base of the PR and between 372874b and c2bc3bf.

📒 Files selected for processing (52)
  • apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
  • apps/mobile/src/features/settings/agentProfile.logic.test.ts
  • apps/mobile/src/features/settings/agentProfile.logic.ts
  • apps/mobile/src/features/settings/agentRule.logic.test.ts
  • apps/mobile/src/features/settings/agentRule.logic.ts
  • apps/mobile/src/features/settings/agentSettings.logic.test.ts
  • apps/mobile/src/features/settings/agentSettings.logic.ts
  • apps/mobile/src/features/threads/NewTaskDraftScreen.tsx
  • apps/mobile/src/features/threads/ThreadComposer.tsx
  • apps/server/src/agents/AgentCatalog.test.ts
  • apps/server/src/agents/AgentCatalog.ts
  • apps/server/src/agents/AgentOrchestrationLive.test.ts
  • apps/server/src/agents/AgentOrchestrationLive.ts
  • apps/server/src/agents/AgentProfileServices.ts
  • apps/server/src/agents/AgentProfileStore.test.ts
  • apps/server/src/agents/AgentProfileStore.ts
  • apps/server/src/agents/AgentProjectFileCoordinator.ts
  • apps/server/src/agents/AgentRuleStore.test.ts
  • apps/server/src/agents/AgentRuleStore.ts
  • apps/server/src/agents/AgentStoreErrorMapping.test.ts
  • apps/server/src/agents/AgentStoreErrorMapping.ts
  • apps/server/src/agents/AgentWorkspaceRoot.test.ts
  • apps/server/src/agents/AgentWorkspaceRoot.ts
  • apps/server/src/agents/prompt/RuleMatcher.ts
  • apps/server/src/agents/prompt/prompt.test.ts
  • apps/server/src/agents/run/AgentRun.test.ts
  • apps/server/src/agents/run/AgentRun.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.test.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.ts
  • apps/server/src/agents/run/AgentRunReactor.test.ts
  • apps/server/src/agents/run/AgentRunReactor.ts
  • apps/server/src/provider/Layers/CursorAdapter.test.ts
  • apps/server/src/provider/Layers/CursorAdapter.ts
  • apps/server/src/provider/Layers/GrokAdapter.test.ts
  • apps/server/src/provider/Layers/GrokAdapter.ts
  • apps/server/src/provider/Layers/OpenCodeAdapter.test.ts
  • apps/server/src/provider/Layers/OpenCodeAdapter.ts
  • apps/server/src/ws.ts
  • apps/web/src/components/chat/AgentProfilePicker.logic.ts
  • apps/web/src/components/chat/AgentProfilePicker.test.ts
  • apps/web/src/components/chat/AgentProfilePicker.tsx
  • apps/web/src/components/chat/ChatComposer.logic.test.ts
  • apps/web/src/components/chat/ChatComposer.logic.ts
  • apps/web/src/components/chat/ChatComposer.tsx
  • apps/web/src/components/settings/AgentsSettings.logic.test.ts
  • apps/web/src/components/settings/AgentsSettings.logic.ts
  • apps/web/src/components/settings/AgentsSettings.tsx
  • apps/web/src/components/settings/RulesSettings.logic.test.ts
  • apps/web/src/components/settings/RulesSettings.logic.ts
  • apps/web/src/components/settings/RulesSettings.test.tsx
  • apps/web/src/components/settings/RulesSettings.tsx
  • packages/contracts/src/agents.ts
🚧 Files skipped from review as they are similar to previous changes (41)
  • apps/server/src/agents/AgentWorkspaceRoot.test.ts
  • apps/server/src/agents/AgentStoreErrorMapping.test.ts
  • apps/server/src/provider/Layers/CursorAdapter.test.ts
  • apps/server/src/provider/Layers/OpenCodeAdapter.test.ts
  • apps/server/src/provider/Layers/CursorAdapter.ts
  • apps/mobile/src/features/settings/agentRule.logic.test.ts
  • apps/web/src/components/chat/ChatComposer.logic.test.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.test.ts
  • apps/server/src/agents/AgentWorkspaceRoot.ts
  • apps/server/src/agents/AgentProfileStore.test.ts
  • apps/server/src/provider/Layers/GrokAdapter.test.ts
  • apps/server/src/agents/run/AgentRun.test.ts
  • apps/mobile/src/features/threads/NewTaskDraftScreen.tsx
  • apps/server/src/agents/AgentCatalog.test.ts
  • apps/mobile/src/features/settings/agentRule.logic.ts
  • apps/server/src/agents/AgentStoreErrorMapping.ts
  • apps/web/src/components/settings/RulesSettings.test.tsx
  • apps/server/src/provider/Layers/GrokAdapter.ts
  • apps/server/src/agents/AgentProjectFileCoordinator.ts
  • apps/server/src/agents/prompt/prompt.test.ts
  • apps/mobile/src/features/threads/ThreadComposer.tsx
  • apps/server/src/provider/Layers/OpenCodeAdapter.ts
  • apps/web/src/components/chat/AgentProfilePicker.logic.ts
  • apps/server/src/agents/AgentProfileStore.ts
  • apps/server/src/ws.ts
  • apps/web/src/components/settings/RulesSettings.logic.ts
  • apps/server/src/agents/prompt/RuleMatcher.ts
  • apps/server/src/agents/AgentRuleStore.ts
  • apps/server/src/agents/run/AgentRunDeadlineReactor.ts
  • apps/mobile/src/features/settings/agentProfile.logic.ts
  • apps/server/src/agents/AgentRuleStore.test.ts
  • apps/web/src/components/chat/AgentProfilePicker.test.ts
  • apps/web/src/components/chat/ChatComposer.tsx
  • apps/server/src/agents/run/AgentRun.ts
  • apps/web/src/components/settings/AgentsSettings.tsx
  • apps/server/src/agents/AgentProfileServices.ts
  • packages/contracts/src/agents.ts
  • apps/web/src/components/chat/AgentProfilePicker.tsx
  • apps/server/src/agents/AgentOrchestrationLive.test.ts
  • apps/server/src/agents/run/AgentRunReactor.ts
  • apps/server/src/agents/AgentOrchestrationLive.ts

Comment thread apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
Comment thread apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
Comment thread apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx
Comment thread apps/web/src/components/settings/RulesSettings.tsx
@megascan
megascan marked this pull request as ready for review August 7, 2026 22:15

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c2bc3bf. Configure here.

Comment thread apps/mobile/src/features/threads/NewTaskDraftScreen.tsx Outdated
Comment thread apps/mobile/src/features/settings/SettingsAgentsRouteScreen.tsx Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

Diff is too large for automated approval analysis. A human reviewer should evaluate this PR.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant