Skip to content

feat(agent): implement Plan Mode execution mode#530

Merged
yacosta738 merged 8 commits into
mainfrom
feature/plan-mode-execution
Apr 13, 2026
Merged

feat(agent): implement Plan Mode execution mode#530
yacosta738 merged 8 commits into
mainfrom
feature/plan-mode-execution

Conversation

@yacosta738
Copy link
Copy Markdown
Contributor

Summary

Implement Plan Mode - an explicit execution mode that restricts the agent to read-only analysis capabilities while blocking write/execute/delegation-risk actions.

Changes

  • Add ExecutionMode enum (Standard, Plan) to runtime config
  • Add --plan CLI flag for corvus agent and corvus code commands
  • Implement Plan Mode tool allowlist in security policy
  • Add distinct plan_mode_blocked outcome for fail-closed semantics
  • Propagate execution_mode through gateway webhook requests
  • Add TDD tests for Plan Mode behavior

Files Changed

  • clients/agent-runtime/src/config/schema.rs - ExecutionMode enum
  • clients/agent-runtime/src/main.rs - CLI --plan flag
  • clients/agent-runtime/src/security/policy.rs - Plan Mode allowlist
  • clients/agent-runtime/src/agent/dispatcher.rs - Blocked semantics
  • clients/agent-runtime/src/gateway/mod.rs - HTTP transport
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs - Tests

Testing

Run the Plan Mode tests:

cargo test --manifest-path clients/agent-runtime/Cargo.toml plan_mode

Roadmap

This implements Phase 2 of the Claúdio roadmap.
See: tmp/CLAUDIO_ROADMAP.md

Closes #529

- Add ExecutionMode enum (Standard, Plan) to runtime config
- Add --plan CLI flag for corvus agent and corvus code commands
- Implement Plan Mode tool allowlist in security policy
- Add distinct plan_mode_blocked outcome for fail-closed semantics
- Propagate execution_mode through gateway webhook requests
- Add TDD tests for Plan Mode behavior

Implements Claude Code-inspired Plan Mode for read-only analysis.

Closes #529
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 2026

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

Adds an explicit ExecutionMode (Standard | Plan), threads it through config/CLI/webhook/bootstrap/agent/security/dispatcher, implements a Plan-mode allowlist and policy-driven blocked outcomes (plan_mode_blocked), propagates structured policy denials via AgentTurnResult.policy_blocked and gateway responses, and filters tools at bootstrap and dispatch.

Changes

Cohort / File(s) Summary
Config & CLI
clients/agent-runtime/src/config/schema.rs, clients/agent-runtime/src/config/mod.rs, clients/agent-runtime/src/main.rs
Introduce ExecutionMode (default Standard), add agent.execution_mode to config, expose CLI --plan, and set effective execution mode for agent/code commands.
Security Policy
clients/agent-runtime/src/security/policy.rs, clients/agent-runtime/src/security/mod.rs
Add ToolPolicyOutcome, PLAN_MODE_BLOCKED_CODE, plan_mode_allows_tool() allowlist; add execution_mode to SecurityPolicy; new policy outcome APIs and from_config(..., execution_mode).
Dispatcher & Evaluation
clients/agent-runtime/src/agent/dispatcher.rs, clients/agent-runtime/tests/*
Add DispatchAction::Blocked { code, reason }; add evaluate_tool_risk_with_policy... that consults SecurityPolicy; map policy Deny→Blocked (Plan-mode semantics) and update tests.
Agent runtime & Results
clients/agent-runtime/src/agent/agent.rs
Wire security_policy: Arc<SecurityPolicy> into Agent/AgentBuilder; add execution_mode to TurnContext (defaulted in with_session) and to AgentTurnResult; add policy_blocked: Option<serde_json::Value> per-step and propagate to turn result.
Approval/Denial Payloads
clients/agent-runtime/src/approval/mod.rs
Add structured_policy_denial_payload(...) and structured_policy_denial_text(...); refactor existing denial helpers to delegate and support policy-driven code field.
Bootstrap & Tool Filtering
clients/agent-runtime/src/bootstrap/mod.rs, clients/agent-runtime/src/bootstrap/composed.rs
Pass execution_mode into SecurityPolicy::from_config(...); during bootstrap, when ExecutionMode::Plan filter registered tools to a plan-safe allowlist; tests added for filtered toolset.
Gateway / Webhook
clients/agent-runtime/src/gateway/mod.rs, clients/agent-runtime/src/gateway/webhook_dispatch.rs
Allow optional execution_mode in webhook body; resolve effective execution mode; add WebhookTerminalOutcome::PlanModeBlocked and mapping to machine-readable JSON/SSE (plan_mode_blocked) including execution_mode; replace approval-only parsing with policy-aware parser that prefers policy_blocked.
Channel Execution Helpers
clients/agent-runtime/src/channels/mod.rs
Handle DispatchAction::Blocked and return structured policy denial text via new approval helper.
Cron / Tools Tests
clients/agent-runtime/src/cron/scheduler.rs, clients/agent-runtime/src/tools/*, clients/agent-runtime/tests/mcp_policy_approval_parity.rs
Update test call sites to pass execution_mode into SecurityPolicy::from_config(...); treat Blocked as denied alongside ApprovalRequired; add plan-mode tests.
Docs / Specs / Tasks / Verify
openspec/changes/archive/2026-04-13-claude-capability-integration/*, openspec/specs/*
Add design/proposal/spec/tasks/verify docs describing Plan Mode contract, blocked outcome semantics, gateway mapping, and verification evidence.
Misc (scripts & test formatting)
scripts/mobile-smoke-test.sh, multiple crate test files`
Add mobile smoke-test script; minor test formatting and trailing-newline cleanups across several crates.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Gateway
    participant Agent
    participant Dispatcher
    participant SecurityPolicy
    participant ToolExec

    Client->>Gateway: webhook (execution_mode=plan)
    Gateway->>Agent: create WebhookTurnRequest (execution_mode=Plan)
    Agent->>Dispatcher: request tool dispatch
    Dispatcher->>SecurityPolicy: evaluate_tool_policy_outcome_for_origin(tool, origin)
    SecurityPolicy-->>Dispatcher: ToolPolicyOutcome(Deny, code="plan_mode_blocked", reason)
    Dispatcher-->>Agent: DispatchAction::Blocked { code, reason }
    Agent-->>Gateway: AgentTurnResult { policy_blocked: {code,tool,reason}, execution_mode: Plan }
    Gateway->>Client: HTTP 403 JSON / SSE event with code="plan_mode_blocked" and execution_mode
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • yuniel-acosta
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.93% 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
Title check ✅ Passed Title follows Conventional Commit style with 'feat(agent):' prefix and clearly describes the main change (Plan Mode execution mode). At 47 characters, it's well under the 72-character limit.
Description check ✅ Passed PR description covers all template sections: Summary (purpose of Plan Mode), detailed Changes list, Files Changed with specific modules, Testing instructions with cargo test command, and Roadmap reference linking to CLAUDIO_ROADMAP. Checklist items are completed.
Linked Issues check ✅ Passed All objectives from issue #529 are met: ExecutionMode enum added [config/schema.rs], --plan CLI flag implemented [main.rs], plan-safe tool allowlist in SecurityPolicy [security/policy.rs], distinct plan_mode_blocked outcome [dispatcher.rs], gateway/webhook propagation [gateway/], and TDD tests added [mcp_policy_approval_parity.rs].
Out of Scope Changes check ✅ Passed All code changes directly support Plan Mode implementation: config threading, CLI entry, security policy gating, dispatcher semantics, gateway transport, and test coverage. Minor formatting changes in corvus-channels/composer/memory files are low-risk housekeeping unrelated to scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/plan-mode-execution

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 and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 13, 2026

Deploying corvus with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8eb2270
Status: ✅  Deploy successful!
Preview URL: https://7d956187.corvus-42x.pages.dev
Branch Preview URL: https://feature-plan-mode-execution.corvus-42x.pages.dev

View logs

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 13, 2026

✅ Contributor Report

User: @yacosta738
Status: Passed (12/13 metrics passed)

Metric Description Value Threshold Status
PR Merge Rate PRs merged vs closed 89% >= 30%
Repo Quality Repos with ≥100 stars 0 >= 0
Positive Reactions Positive reactions received 10 >= 1
Negative Reactions Negative reactions received 0 <= 5
Account Age GitHub account age 3090 days >= 30 days
Activity Consistency Regular activity over time 108% >= 0%
Issue Engagement Issues with community engagement 0 >= 0
Code Reviews Code reviews given to others 546 >= 0
Merger Diversity Unique maintainers who merged PRs 2 >= 0
Repo History Merge Rate Merge rate in this repo 92% >= 0%
Repo History Min PRs Previous PRs in this repo 240 >= 0
Profile Completeness Profile richness (bio, followers) 90 >= 0
Suspicious Patterns Spam-like activity detection 1 N/A

Contributor Report evaluates based on public GitHub activity. Analysis period: 2025-04-13 to 2026-04-13

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 12

Caution

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

⚠️ Outside diff range comments (5)
clients/agent-runtime/src/main.rs (1)

874-900: ⚠️ Potential issue | 🟠 Major

Reject --plan when an agent composition subcommand is selected.

This branch parses plan, but if agent_subcommand is present it is silently ignored and build/run/new continue normally. Unsupported critical flags should fail fast instead of being dropped.

Suggested fix
         } => {
             // Handle agent composition subcommands (Phase 4)
             if let Some(subcommand) = agent_subcommand {
+                if plan {
+                    anyhow::bail!(
+                        "--plan is only supported for interactive or single-message `corvus agent` sessions"
+                    );
+                }
                 handle_agent_composition_command(subcommand).await
             } else {
                 // Legacy behavior: interactive agent loop
                 dispatch_agent_command(

Based on learnings: Preserve CLI contract unless change is intentional and documented; prefer explicit errors over silent fallback for unsupported critical paths.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/main.rs` around lines 874 - 900, The code currently
ignores the --plan flag when an agent_subcommand is present; update the
Commands::Agent branch to reject unsupported combinations by checking if
agent_subcommand.is_some() and plan.is_some() and returning an explicit
error/exit instead of continuing. Specifically, before calling
handle_agent_composition_command(subcommand).await, detect if plan.is_some()
(and any other mutually exclusive flags if needed) and return an Err or call a
clear error/usage message so handle_agent_composition_command and
dispatch_agent_command are not silently given conflicting inputs.
clients/agent-runtime/src/bootstrap/mod.rs (1)

247-269: ⚠️ Potential issue | 🟠 Major

Filter Plan Mode tools before constructing them.

tools::all_tools_with_runtime(...) still instantiates the full tool set, and only then the Plan Mode filter drops unsafe entries. That means blocked capabilities can still run constructor-time setup or fail Plan Mode startup because of config/dependency checks for tools the session is never allowed to use.

Move the allowlist check into tool selection/factory assembly so Plan Mode never constructs plan-unsafe tools in the first place.

Based on learnings: Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/bootstrap/mod.rs` around lines 247 - 269, Current
code calls tools::all_tools_with_runtime(...) which constructs every tool then
filters with profile.allows_tool(...) and
SecurityPolicy::plan_mode_allows_tool(...), allowing disallowed tools to run
constructor-time logic; update the factory so plan-mode/allowlist checks run
before construction. Specifically, modify tools::all_tools_with_runtime (or add
a new factory like tools::selective_tools_with_runtime) to accept a predicate
(or list of allowed names) and perform the profile.allows_tool and (if
config.agent.execution_mode == ExecutionMode::Plan)
SecurityPolicy::plan_mode_allows_tool checks while enumerating tool descriptors,
then only instantiate Box<dyn Tool> for names that pass; replace the current
call site to use the new factory or pass the predicate so unsafe tools are never
constructed.
clients/agent-runtime/src/gateway/mod.rs (1)

1950-1966: ⚠️ Potential issue | 🔴 Critical

Fail closed when Plan Mode reaches the legacy webhook path.

execution_mode is only forwarded inside the dispatcher branch. If gateway.webhook_dispatcher_enabled is false, Line 1988 and Line 2181 silently drop execution_mode: "plan" and continue through the legacy handlers, so an explicit read-only request can still run the non-Plan path. Reject any non-Standard mode before the legacy fallback in both /webhook and /web/chat/stream, and add a regression test for dispatcher-disabled JSON and SSE requests. Based on learnings: Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable.

Suggested fail-closed pattern
+let requested_execution_mode = webhook_body.execution_mode.unwrap_or_default();
 let config = state.config.lock().clone();
 let dispatcher_enabled = webhook_dispatcher_enabled(&config);
+if requested_execution_mode != ExecutionMode::Standard && !dispatcher_enabled {
+    let response = (
+        StatusCode::SERVICE_UNAVAILABLE,
+        Json(serde_json::json!({
+            "error": {
+                "code": "execution_mode_requires_dispatcher",
+                "execution_mode": requested_execution_mode,
+                "message": "Non-standard execution modes require the webhook dispatcher path",
+            },
+            "session_id": session_id,
+        })),
+    );
+    release_idempotency_key(&state, reserved_idempotency_key, false);
+    return response;
+}
 if dispatcher_enabled {
     let dispatch_result = webhook_dispatch::execute(
         &config,
         Arc::clone(&state.provider),
         Arc::clone(&state.mem),
@@
             webhook_dispatch::WebhookTurnRequest {
                 session_id: session_id.clone(),
                 session_source,
                 message: message.clone(),
-                execution_mode: webhook_body.execution_mode.unwrap_or_default(),
+                execution_mode: requested_execution_mode,
                 include_sse_frames: is_preview,
             },
         )

Mirror the same guard in handle_chat_stream.

Also applies to: 1988-2042, 2094-2117, 2181-2216

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/gateway/mod.rs` around lines 1950 - 1966, When
webhook_dispatcher_enabled(&config) is false we must fail-closed for
non-Standard execution modes instead of silently falling back to legacy
handlers: add an explicit guard before the legacy fallback that reads
webhook_body.execution_mode (same enum/string used when constructing
webhook_dispatch::WebhookTurnRequest) and returns a rejection/error for any mode
!= Standard; apply the same check in the streaming handler (handle_chat_stream)
so both /webhook and /web/chat/stream reject Plan/other modes when
webhook_dispatcher_enabled is false, mirroring the dispatcher branch behavior
around webhook_dispatch::execute and preventing legacy paths from handling
non-Standard requests.
clients/agent-runtime/src/agent/agent.rs (2)

2241-2250: ⚠️ Potential issue | 🟠 Major

Use the policy-aware gate in the mission precheck.

This branch still asks tool_dispatcher.check_tool_risk_for_origin(...), but Plan Mode denials are now computed through evaluate_tool_risk_with_policy_for_origin(...) in execute_gated_tool_calls(). In mission context, a Plan-mode-denied native tool can miss the mission_policy_denied fast-fail and continue past a blocked action.

Suggested change
         if self.mission_execution_context
             && calls.iter().any(|call| {
                 matches!(
-                    self.tool_dispatcher.check_tool_risk_for_origin(
-                        &call.name,
-                        &call.arguments,
-                        ExecutionOrigin::Mission,
-                    ),
+                    evaluate_tool_risk_with_policy_for_origin(
+                        &call.name,
+                        &self.security_policy,
+                        ExecutionOrigin::Mission,
+                    ),
                     DispatchAction::ApprovalRequired(_) | DispatchAction::Blocked { .. }
                 )
             })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/agent/agent.rs` around lines 2241 - 2250, The
mission precheck is calling self.tool_dispatcher.check_tool_risk_for_origin(...)
which is not policy-aware; replace that call with
self.tool_dispatcher.evaluate_tool_risk_with_policy_for_origin(&call.name,
&call.arguments, ExecutionOrigin::Mission) inside the same calls.iter().any(...)
branch so precheck uses the same policy-evaluated result as
execute_gated_tool_calls(), and treat any returned
policy-denied/Plan-mode-denied result the same way (i.e., trigger the
mission_policy_denied/fast-fail path used elsewhere). Ensure you reference the
same call fields (call.name, call.arguments) and ExecutionOrigin::Mission and
mirror the handling logic used in execute_gated_tool_calls() for the
DispatchAction/PolicyDecision enum.

1596-1621: ⚠️ Potential issue | 🟠 Major

Don't return Completed after a policy block.

Once policy_blocked is set, this loop can still return AgentTurnOutcome::Completed with final_text on a later iteration. That makes the block a side channel only; call paths in this file that still use turn() drop it and treat the turn as successful. Make the blocked state terminal here, or have turn() propagate it instead of returning text.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/agent/agent.rs` around lines 1596 - 1621, The loop
currently allows a later final_text to be returned even after policy_blocked was
set, which leaks the blocked state; update the loop in step_with_context
handling inside turn() so that after calling step_with_context (and after you
set policy_blocked = outcome.policy_blocked.clone() when None) you immediately
treat a non-None policy_blocked as terminal: do not accept or return
outcome.final_text if policy_blocked.is_some(); instead return an
AgentTurnResult that reflects the blocked terminal state (set terminal_outcome
to the blocked variant, include policy_blocked and event_log) or otherwise
propagate the blocked outcome up from turn() so callers cannot receive
final_text once policy_blocked was set. Ensure references to approval_required,
policy_blocked, event_log, AgentTurnEvent::Completed, AgentTurnResult,
AgentTurnOutcome::Completed, step_with_context and turn() are updated
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/agent-runtime/src/agent/agent.rs`:
- Around line 357-359: The builder's build() now unconditionally requires
security_policy which breaks callers like build_validation_agent,
turn_without_tools_returns_text, build_classification_test_agent and the
cost-test helpers that call .build().unwrap(); either thread a policy into each
of those call sites or restore a secure default in build(): replace the
ok_or_else(...) requirement with something like .unwrap_or_default() (using
SecurityPolicy::default()) or similar so security_policy =
self.security_policy.unwrap_or_default(), or alternatively update the listed
helper functions to set security_policy before calling build(); reference the
build() method and the security_policy field as the exact locations to change.

In `@clients/agent-runtime/src/agent/dispatcher.rs`:
- Around line 70-91: The current evaluate_tool_risk_with_policy_for_origin only
consults SecurityPolicy when execution_mode == ExecutionMode::Plan, which lets
hard denies from SecurityPolicy.evaluate_tool_policy_outcome_for_origin be
ignored in non-Plan modes; change the logic in
evaluate_tool_risk_with_policy_for_origin to always call
evaluate_tool_policy_outcome_for_origin(tool_name, origin) first, return
DispatchAction::Blocked immediately if outcome.decision ==
ToolPolicyDecision::Deny (preserving code/reason from outcome), and otherwise
for Plan map Allow/ApprovalRequired as currently done but for non-Plan continue
to call evaluate_tool_risk_for_origin(tool_name, origin) only when the policy
decision is not Deny (i.e., Allow or ApprovalRequired) so legacy risk checks run
without overriding explicit policy denies; reference functions:
evaluate_tool_risk_with_policy_for_origin,
evaluate_tool_policy_outcome_for_origin, evaluate_tool_risk_for_origin and types
SecurityPolicy, ExecutionMode::Plan, ToolPolicyDecision.

In `@clients/agent-runtime/src/main.rs`:
- Around line 1478-1490: The code currently returns early when
cli_blocking_error_from_turn_result(turn_result) yields an error in
handle_agent_command, which skips running the session epilogue
(record_agent_end_event and session cost summary); change the control flow so
you do not return immediately from inside the message-handling block: after
calling agent.turn_with_context(...) and computing
cli_blocking_error_from_turn_result(turn_result), capture that error into a
local variable (e.g., let blocking_err =
cli_blocking_error_from_turn_result(turn_result)) instead of returning, continue
to execute the rest of the block (printing final_text and setting run_result),
then after the whole message branch (before returning from handle_agent_command)
check if blocking_err.is_some() and return Err(blocking_err.unwrap()) so
record_agent_end_event and the session summary always run; reference
functions/vars: agent.turn_with_context, cli_blocking_error_from_turn_result,
run_result, record_agent_end_event, handle_agent_command.

In `@openspec/changes/archive/2026-04-13-claude-capability-integration/design.md`:
- Around line 398-404: Update the archived design's "Open Questions" section by
resolving or removing the stale checklist item that claims "the original delta
specs... are currently missing"; either (A) confirm and mark the checkbox as
resolved with a brief note stating where the delta specs were restored, or (B)
delete that bullet entirely and add a short archival note that all active
restoration tasks are complete or irrelevant for this archived file; edit the
"Open Questions" block (the checklist bullets under the header) so the archived
document no longer presents an unchecked, actionable item.

In
`@openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md`:
- Around line 18-30: The markdown needs small lint fixes: add a blank line after
each subsection heading ("In Scope" and "Out of Scope") so headings are followed
by an empty line, and hyphenate the phrase "read/search style" to
"read/search-style" where it appears in the "In Scope" list; update the
paragraph under "In Scope" accordingly to preserve punctuation and ensure the
hyphenation is applied to the list item referencing explicit tools.

In
`@openspec/changes/archive/2026-04-13-claude-capability-integration/specs/agent-loop/spec.md`:
- Around line 10-12: The phrase "web search style capabilities" in the Plan Mode
requirement is ambiguous; update the spec text in the agent-loop requirement
(the sentence starting "When Plan Mode is active...") to hyphenate
"web-search-style" so it reads "web-search-style capabilities", ensuring
consistency with other hyphenated items like "read-only file inspection" and
"read-only memory recall".

In
`@openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md`:
- Around line 25-31: Update the "Build & Tests Execution" section to explicitly
list the status of the cargo formatting and lints: add separate lines for "cargo
fmt --all -- --check" and "cargo clippy --all-targets -- -D warnings" under that
header showing whether each was Run ✅ or Skipped ➖ (and if skipped, include the
user-provided reason "Do NOT build"); keep the existing Tests line intact and
ensure the exact command texts are used so reviewers can see that formatting and
clippy checks were either executed or intentionally omitted.

In `@openspec/specs/client-surfaces/spec.md`:
- Line 889: The document adds a 1.5.0 change-history entry but the front-matter
still reports version: 1.4.0, causing a mismatch; update the front-matter
version field (the top-level "version" in the spec markdown) from 1.4.0 to 1.5.0
so it matches the new change-history entry (1.5.0) and keeps the spec
self-consistent.

In `@scripts/mobile-smoke-test.sh`:
- Around line 22-42: The check_prerequisites() function currently enforces
Android artifacts (ANDROID_APK and adb) unconditionally, blocking ios-only runs;
change it to accept a target/platform parameter (or split into
check_android_prerequisites() and check_common_prerequisites()) and only
validate ANDROID_APK and command -v adb when the target includes Android; always
validate CORVUS_BINARY in the common checks used by both ios and android; update
the ios mode invocation to call the common checks (or pass "ios") so missing
Android APK/adb no longer fail ios-only smoke tests.
- Around line 58-64: The script currently always calls log_success "Corvus
binary deployed" after attempting adb push, which emits success even when push
failed; change the flow in scripts/mobile-smoke-test.sh so the log_success call
only runs when adb push succeeds (i.e., after the successful adb push
command/its success branch), and do not emit log_success in the error branch
that calls log_warn/log_info; locate the adb push block and the log_success
invocation to move or gate the success message accordingly (referencing the adb
push command and the log_warn, log_info, and log_success calls).
- Line 7: The hardcoded
CORVUS_BINARY="clients/agent-runtime/target/release/corvus" can miss per-target
release folders; update the script so CORVUS_BINARY is resolved dynamically:
check for an environment/CI-provided target triple (e.g., TARGET or a GITHUB_*
var) and use target/$TARGET/release/corvus if present, otherwise search for a
matching binary under clients/agent-runtime/target/*/release/corvus (or use
find/glob to pick the existing file) and fail with a clear message if none
found; apply the same dynamic-resolution logic to the other occurrences
referenced around the 25-30 region so all binary lookups handle both
target/release and target/<target>/release layouts.
- Line 5: The script currently uses only "set -e" which doesn't propagate
failures from piped commands; update the top-level shell options by replacing
the existing set -e invocation with set -euo pipefail (i.e., change the "set -e"
line) so that pipeline failures (like xcodebuild | tail) and unset variable
references properly cause the script to exit non‑zero.

---

Outside diff comments:
In `@clients/agent-runtime/src/agent/agent.rs`:
- Around line 2241-2250: The mission precheck is calling
self.tool_dispatcher.check_tool_risk_for_origin(...) which is not policy-aware;
replace that call with
self.tool_dispatcher.evaluate_tool_risk_with_policy_for_origin(&call.name,
&call.arguments, ExecutionOrigin::Mission) inside the same calls.iter().any(...)
branch so precheck uses the same policy-evaluated result as
execute_gated_tool_calls(), and treat any returned
policy-denied/Plan-mode-denied result the same way (i.e., trigger the
mission_policy_denied/fast-fail path used elsewhere). Ensure you reference the
same call fields (call.name, call.arguments) and ExecutionOrigin::Mission and
mirror the handling logic used in execute_gated_tool_calls() for the
DispatchAction/PolicyDecision enum.
- Around line 1596-1621: The loop currently allows a later final_text to be
returned even after policy_blocked was set, which leaks the blocked state;
update the loop in step_with_context handling inside turn() so that after
calling step_with_context (and after you set policy_blocked =
outcome.policy_blocked.clone() when None) you immediately treat a non-None
policy_blocked as terminal: do not accept or return outcome.final_text if
policy_blocked.is_some(); instead return an AgentTurnResult that reflects the
blocked terminal state (set terminal_outcome to the blocked variant, include
policy_blocked and event_log) or otherwise propagate the blocked outcome up from
turn() so callers cannot receive final_text once policy_blocked was set. Ensure
references to approval_required, policy_blocked, event_log,
AgentTurnEvent::Completed, AgentTurnResult, AgentTurnOutcome::Completed,
step_with_context and turn() are updated accordingly.

In `@clients/agent-runtime/src/bootstrap/mod.rs`:
- Around line 247-269: Current code calls tools::all_tools_with_runtime(...)
which constructs every tool then filters with profile.allows_tool(...) and
SecurityPolicy::plan_mode_allows_tool(...), allowing disallowed tools to run
constructor-time logic; update the factory so plan-mode/allowlist checks run
before construction. Specifically, modify tools::all_tools_with_runtime (or add
a new factory like tools::selective_tools_with_runtime) to accept a predicate
(or list of allowed names) and perform the profile.allows_tool and (if
config.agent.execution_mode == ExecutionMode::Plan)
SecurityPolicy::plan_mode_allows_tool checks while enumerating tool descriptors,
then only instantiate Box<dyn Tool> for names that pass; replace the current
call site to use the new factory or pass the predicate so unsafe tools are never
constructed.

In `@clients/agent-runtime/src/gateway/mod.rs`:
- Around line 1950-1966: When webhook_dispatcher_enabled(&config) is false we
must fail-closed for non-Standard execution modes instead of silently falling
back to legacy handlers: add an explicit guard before the legacy fallback that
reads webhook_body.execution_mode (same enum/string used when constructing
webhook_dispatch::WebhookTurnRequest) and returns a rejection/error for any mode
!= Standard; apply the same check in the streaming handler (handle_chat_stream)
so both /webhook and /web/chat/stream reject Plan/other modes when
webhook_dispatcher_enabled is false, mirroring the dispatcher branch behavior
around webhook_dispatch::execute and preventing legacy paths from handling
non-Standard requests.

In `@clients/agent-runtime/src/main.rs`:
- Around line 874-900: The code currently ignores the --plan flag when an
agent_subcommand is present; update the Commands::Agent branch to reject
unsupported combinations by checking if agent_subcommand.is_some() and
plan.is_some() and returning an explicit error/exit instead of continuing.
Specifically, before calling handle_agent_composition_command(subcommand).await,
detect if plan.is_some() (and any other mutually exclusive flags if needed) and
return an Err or call a clear error/usage message so
handle_agent_composition_command and dispatch_agent_command are not silently
given conflicting inputs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 16be9604-09bd-4a16-b4e0-a8ffe4b62d0d

📥 Commits

Reviewing files that changed from the base of the PR and between b8fb377 and 27bb091.

📒 Files selected for processing (28)
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/src/config/mod.rs
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/cron/scheduler.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/security/mod.rs
  • clients/agent-runtime/src/security/policy.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/agent-loop/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/client-surfaces/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/state.yaml
  • openspec/changes/archive/2026-04-13-claude-capability-integration/tasks.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/specs/agent-loop/spec.md
  • openspec/specs/client-surfaces/spec.md
  • scripts/mobile-smoke-test.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: sonar
  • GitHub Check: pr-checks
  • GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (10)
clients/agent-runtime/src/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

clients/agent-runtime/src/**/*.rs: Never log secrets, tokens, raw credentials, or sensitive payloads in any logging statements
Avoid unnecessary allocations, clones, and blocking operations to maintain performance and efficiency

Files:

  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/cron/scheduler.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/mod.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/security/policy.rs
clients/agent-runtime/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Run cargo fmt --all -- --check, cargo clippy --all-targets -- -D warnings, and cargo test for code validation, or document which checks were skipped and why

Files:

  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/cron/scheduler.rs
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/mod.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/security/policy.rs
**/*.rs

⚙️ CodeRabbit configuration file

**/*.rs: Focus on Rust idioms, memory safety, and ownership/borrowing correctness.
Flag unnecessary clones, unchecked panics in production paths, and weak error context.
Prioritize unsafe blocks, FFI boundaries, concurrency races, and secret handling.

Files:

  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/cron/scheduler.rs
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/mod.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/security/policy.rs
**/*

⚙️ CodeRabbit configuration file

**/*: Security first, performance second.
Validate input boundaries, auth/authz implications, and secret management.
Look for behavioral regressions, missing tests, and contract breaks across modules.

Files:

  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/cron/scheduler.rs
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/mod.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/state.yaml
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/client-surfaces/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • clients/agent-runtime/src/channels/mod.rs
  • openspec/specs/agent-loop/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/tasks.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • openspec/specs/client-surfaces/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/agent-loop/spec.md
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • scripts/mobile-smoke-test.sh
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/security/policy.rs
clients/agent-runtime/src/tools/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Implement Tool trait in src/tools/ with strict parameter schema, validate and sanitize all inputs, and return structured ToolResult without panics in runtime path

Files:

  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/tools/schedule.rs
clients/agent-runtime/src/{security,gateway,tools}/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Treat src/security/, src/gateway/, src/tools/ as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks

Files:

  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/security/policy.rs
clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable

Files:

  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/mod.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/security/policy.rs
**/*.{md,mdx}

⚙️ CodeRabbit configuration file

**/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes.
For user-facing docs, check EN/ES parity or explicitly note pending translation gaps.

Files:

  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/client-surfaces/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • openspec/specs/agent-loop/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/tasks.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • openspec/specs/client-surfaces/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/agent-loop/spec.md
clients/agent-runtime/src/channels/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Implement Channel trait in src/channels/ with consistent send, listen, and health_check semantics and cover auth/allowlist/health behavior with tests

Files:

  • clients/agent-runtime/src/channels/mod.rs
clients/agent-runtime/src/main.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

clients/agent-runtime/src/main.rs: Preserve CLI contract unless change is intentional and documented; prefer explicit errors over silent fallback for unsupported critical paths
Keep startup path lean and avoid heavy initialization in command parsing flow

Files:

  • clients/agent-runtime/src/main.rs
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs : Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools}/**/*.rs : Treat `src/security/`, `src/gateway/`, `src/tools/` as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs : Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable

Applied to files:

  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/cron/scheduler.rs
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/mod.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • clients/agent-runtime/src/channels/mod.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/tasks.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/security/policy.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools}/**/*.rs : Treat `src/security/`, `src/gateway/`, `src/tools/` as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks

Applied to files:

  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/cron/scheduler.rs
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/mod.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/tasks.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/security/policy.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/main.rs : Preserve CLI contract unless change is intentional and documented; prefer explicit errors over silent fallback for unsupported critical paths

Applied to files:

  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/cron/scheduler.rs
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/mod.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • clients/agent-runtime/src/channels/mod.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/tasks.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/security/policy.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/main.rs : Keep startup path lean and avoid heavy initialization in command parsing flow

Applied to files:

  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/providers/**/*.rs : Implement `Provider` trait in `src/providers/` and register in `src/providers/mod.rs` factory when adding a new provider

Applied to files:

  • clients/agent-runtime/src/bootstrap/composed.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/tools/**/*.rs : Implement `Tool` trait in `src/tools/` with strict parameter schema, validate and sanitize all inputs, and return structured `ToolResult` without panics in runtime path

Applied to files:

  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/security/policy.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/**/*.rs : Run `cargo fmt --all -- --check`, `cargo clippy --all-targets -- -D warnings`, and `cargo test` for code validation, or document which checks were skipped and why

Applied to files:

  • clients/agent-runtime/src/tools/cron_update.rs
  • clients/agent-runtime/tests/mcp_policy_approval_parity.rs
  • clients/agent-runtime/src/tools/cron_add.rs
  • clients/agent-runtime/src/config/mod.rs
  • clients/agent-runtime/src/tools/schedule.rs
  • clients/agent-runtime/src/security/mod.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/tasks.md
  • clients/agent-runtime/src/config/schema.rs
  • clients/agent-runtime/src/bootstrap/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/security/policy.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/**/Cargo.toml : Do not add heavy dependencies for minor convenience; justify new crate additions

Applied to files:

  • clients/agent-runtime/src/security/mod.rs
  • clients/agent-runtime/src/approval/mod.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/security/policy.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/channels/**/*.rs : Implement `Channel` trait in `src/channels/` with consistent `send`, `listen`, and `health_check` semantics and cover auth/allowlist/health behavior with tests

Applied to files:

  • clients/agent-runtime/src/channels/mod.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Include threat/risk notes and rollback strategy for security, runtime, and gateway changes; add or update tests for boundary checks and failure modes

Applied to files:

  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/tasks.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
📚 Learning: 2026-02-17T07:28:38.934Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-17T07:28:38.934Z
Learning: Applies to .agents/AGENTS.md : Document agent configurations and capabilities in AGENTS.md

Applied to files:

  • clients/agent-runtime/src/config/schema.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/agent-loop/spec.md
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/**/*.rs : Avoid unnecessary allocations, clones, and blocking operations to maintain performance and efficiency

Applied to files:

  • clients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/**/Cargo.toml : Preserve release-size profile assumptions in `Cargo.toml` and avoid adding heavy dependencies unless clearly justified

Applied to files:

  • clients/agent-runtime/src/security/policy.rs
🪛 LanguageTool
openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md

[grammar] ~20-~20: Use a hyphen to join words.
Context: ...re plan mode allows explicit read/search style tools and blocks mutating or execu...

(QB_NEW_EN_HYPHEN)

openspec/specs/agent-loop/spec.md

[grammar] ~377-~377: Use a hyphen to join words.
Context: ...search, image inspection, and web search style capabilities. When Plan Mode is a...

(QB_NEW_EN_HYPHEN)

openspec/changes/archive/2026-04-13-claude-capability-integration/design.md

[style] ~92-~92: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...er tools only in bootstrap - Deny tools only at dispatch time - Rely on provider ins...

(ADVERB_REPETITION_PREMIUM)


[grammar] ~128-~128: Ensure spelling is correct
Context: ...ts transport callers, tests, and future surfaces distinguish policy class from transport...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

openspec/changes/archive/2026-04-13-claude-capability-integration/specs/agent-loop/spec.md

[grammar] ~12-~12: Use a hyphen to join words.
Context: ...search, image inspection, and web search style capabilities. When Plan Mode is a...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.22.0)
openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md

[warning] 18-18: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 29-29: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🪛 Shellcheck (0.11.0)
scripts/mobile-smoke-test.sh

[info] 30-30: Use find instead of ls to better handle non-alphanumeric filenames.

(SC2012)

🔇 Additional comments (15)
openspec/changes/archive/2026-04-13-claude-capability-integration/state.yaml (2)

1-1: Verify change name aligns with Plan Mode scope.

The change identifier "claude-capability-integration" is generic and doesn't clearly indicate this implements Plan Mode execution. Confirm this naming is intentional or if it should reference Plan Mode explicitly for clarity in change history.


13-13: Timestamp at exactly midnight appears placeholder.

The updated timestamp of 2026-04-13T00:00:00Z is suspiciously precise (exactly midnight UTC). Confirm this is intentional or replace with the actual archive timestamp for accurate change tracking.

clients/agent-runtime/src/bootstrap/composed.rs (1)

130-130: Execution mode propagation into security policy looks correct.

This keeps composed bootstrap policy evaluation consistent with Plan Mode semantics.

clients/agent-runtime/src/tools/cron_update.rs (1)

135-135: Test policy setup now correctly includes execution mode.

Good alignment with the runtime SecurityPolicy::from_config contract.

clients/agent-runtime/tests/mcp_policy_approval_parity.rs (1)

13-15: Parity tests are stricter in the right direction.

Treating both Execute and Blocked as failure here keeps the approval-required contract explicit for MCP paths.

Also applies to: 54-56, 66-68

clients/agent-runtime/src/tools/schedule.rs (1)

418-418: SecurityPolicy test setup is now mode-aware and consistent.

Passing execution_mode in both fixtures keeps schedule-tool tests aligned with Plan Mode enforcement.

Also applies to: 533-533

clients/agent-runtime/src/tools/cron_add.rs (1)

239-239: Good update to keep cron_add tests aligned with execution-mode policy.

This avoids test/runtime drift for Plan Mode behavior.

clients/agent-runtime/src/channels/mod.rs (1)

531-534: Good fail-closed handling for blocked tool actions.

Using a structured denial payload with explicit code/reason here correctly preserves policy semantics for channel responses.

clients/agent-runtime/src/cron/scheduler.rs (2)

23-27: Execution mode propagation in scheduler policy construction is correct.

This keeps cron security decisions aligned with Plan/Standard mode semantics in both normal scheduling and execute_job_now.
Based on learnings: "Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable."

Also applies to: 49-53


519-523: Test updates correctly track the new SecurityPolicy::from_config contract.

Nice parity coverage for the constructor signature change across scheduler command-policy tests.

Also applies to: 536-540, 554-558, 573-576, 591-594, 610-613, 628-631, 647-650, 671-674

clients/agent-runtime/src/security/mod.rs (1)

27-27: Re-export additions are appropriate and improve policy API consistency.

Exporting ToolPolicyOutcome and PLAN_MODE_BLOCKED_CODE from the security facade helps downstream modules consume Plan Mode denial semantics uniformly.
Based on learnings: "Treat src/security/, src/gateway/, src/tools/ as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks."

clients/agent-runtime/src/config/mod.rs (1)

8-16: ExecutionMode re-export is a good config-surface update.

This keeps execution-mode typing accessible from crate::config and supports consistent propagation across modules.

clients/agent-runtime/src/config/schema.rs (2)

483-504: Execution mode config wiring looks correct and backward-compatible.

agent.execution_mode is defaulted safely, and enum deserialization is explicit (snake_case) with Standard as the default.

Also applies to: 529-535


4274-4297: Good coverage for the new ExecutionMode contract.

Tests now verify default behavior, valid TOML values (plan/standard), and fail-closed rejection of unknown variants.

Also applies to: 6506-6526

openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md (1)

37-129: Proposal scope, risk boundaries, and rollout intent are clear.

The document keeps the change narrowly scoped to analysis-only Plan Mode and explicitly avoids broad capability-architecture claims.

As per coding guidelines, this keeps docs technically aligned with the implemented scope.

Comment thread clients/agent-runtime/src/agent/agent.rs Outdated
Comment thread clients/agent-runtime/src/agent/dispatcher.rs
Comment thread clients/agent-runtime/src/main.rs
Comment thread openspec/specs/client-surfaces/spec.md
Comment thread scripts/mobile-smoke-test.sh Outdated
Comment thread scripts/mobile-smoke-test.sh Outdated
Comment thread scripts/mobile-smoke-test.sh Outdated
Comment thread scripts/mobile-smoke-test.sh Outdated
yacosta738 and others added 5 commits April 13, 2026 17:02
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (3)
clients/agent-runtime/src/gateway/mod.rs (1)

1961-1966: ⚠️ Potential issue | 🔴 Critical

Do not let the request body downgrade the runtime’s execution mode.

unwrap_or_default() makes the gateway fall back to Standard, so a runtime started/configured in Plan Mode can be silently downgraded whenever the client omits execution_mode or explicitly sends "standard". On this gateway surface, the request should inherit the server-configured mode and only be allowed to stay the same or become more restrictive. Please add a regression test for “runtime in Plan Mode + missing/standard request mode” on both /webhook and /web/chat/stream.

Based on learnings: Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable.

Also applies to: 2112-2117

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/gateway/mod.rs` around lines 1961 - 1966, The
gateway currently uses webhook_body.execution_mode.unwrap_or_default() when
constructing webhook_dispatch::WebhookTurnRequest which lets a missing or
"standard" client request downgrade a runtime configured in Plan Mode; change
this to inherit the server/runtime-configured execution mode by default and only
accept a client-supplied execution_mode if it is the same or more restrictive
than the server mode (i.e., never weaken the server-configured mode). Replace
the unwrap_or_default usage in the WebhookTurnRequest construction (and the
analogous spot around lines 2112-2117) with logic that clamps/validates
webhook_body.execution_mode against the runtime/server execution mode; add
regression tests covering "runtime in Plan Mode + missing request mode" and
"runtime in Plan Mode + standard request mode" for both /webhook and
/web/chat/stream endpoints to ensure the request cannot downgrade the runtime.
clients/agent-runtime/src/main.rs (1)

1546-1554: ⚠️ Potential issue | 🟠 Major

Update handle_code_command to check for blocked outcomes like handle_agent_command does.

handle_code_command calls agent.run_single(&msg) which returns only Result<String>, discarding the policy_blocked metadata. This means cli_blocking_error_from_turn_result is never invoked for code sessions. In contrast, handle_agent_command calls turn_with_context directly and checks the result with cli_blocking_error_from_turn_result.

Result: corvus code --plan silently reports success even if a tool was blocked by plan-mode policy, while corvus agent --plan correctly rejects it.

Fix: Either refactor handle_code_command to call turn_with_context directly (like handle_agent_command), or change run_single to return the full AgentTurnResult instead of just the text, so the blocking check can be applied consistently.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/main.rs` around lines 1546 - 1554,
handle_code_command currently calls run_single(&msg) which returns only
Result<String>, discarding policy_blocked metadata so
cli_blocking_error_from_turn_result is never invoked; update handle_code_command
to either call turn_with_context (same as handle_agent_command) and then pass
the returned AgentTurnResult through cli_blocking_error_from_turn_result before
printing/returning, or modify run_single to return the full AgentTurnResult (not
just String) and apply cli_blocking_error_from_turn_result to that result;
ensure references to run_single, turn_with_context, handle_agent_command,
handle_code_command, cli_blocking_error_from_turn_result, and AgentTurnResult
are used so the blocking check is applied consistently for code sessions.
clients/agent-runtime/src/gateway/webhook_dispatch.rs (1)

384-406: ⚠️ Potential issue | 🟡 Minor

Remove dead code: approval_denial_from_history is unused in production.

This function is only called within its own unit test (approval_denial_is_detected_from_tool_results_history) and never used in any production code paths. Remove the function definition and its associated test, or retain both only if this functionality is planned for future use.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/gateway/webhook_dispatch.rs` around lines 384 -
406, Remove the dead helper function approval_denial_from_history and its
associated unit test approval_denial_is_detected_from_tool_results_history since
they are only used in tests and not referenced by production code; delete the
function definition from webhook_dispatch.rs and remove or comment out the
matching test, and run cargo test to ensure no remaining references or
compilation errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/agent-runtime/src/agent/dispatcher.rs`:
- Around line 446-468: The test bypasses the policy-aware path by calling
evaluate_tool_risk("shell"); replace that call with the policy-aware helper
(e.g., evaluate_tool_risk_with_policy_for_origin or
evaluate_tool_risk_with_policy) using the same SecurityPolicy instance
(`policy`) so the final assertion exercises the standard-mode branch under the
policy and still asserts DispatchAction::ApprovalRequired("shell".into());
update the assertion to use the returned value from the policy-aware helper.

In `@clients/agent-runtime/src/main.rs`:
- Around line 1611-1650: The function cli_blocking_error_from_turn_result
currently only treats PLAN_MODE_BLOCKED_CODE specially and otherwise ignores
other policy_blocked entries, which lets other policy blocks slip through as
success; update cli_blocking_error_from_turn_result so any presence of
turn_result.policy_blocked returns an anyhow::Error (i.e., treat every
policy_blocked as a CLI failure), constructing a clear message that includes
available fields (code, tool, reason) and preserving the current Plan Mode
phrasing when code == crate::security::PLAN_MODE_BLOCKED_CODE; keep the existing
approval_required branch as-is but ensure policy_blocked is checked first so any
policy_blocked always results in an error.

---

Outside diff comments:
In `@clients/agent-runtime/src/gateway/mod.rs`:
- Around line 1961-1966: The gateway currently uses
webhook_body.execution_mode.unwrap_or_default() when constructing
webhook_dispatch::WebhookTurnRequest which lets a missing or "standard" client
request downgrade a runtime configured in Plan Mode; change this to inherit the
server/runtime-configured execution mode by default and only accept a
client-supplied execution_mode if it is the same or more restrictive than the
server mode (i.e., never weaken the server-configured mode). Replace the
unwrap_or_default usage in the WebhookTurnRequest construction (and the
analogous spot around lines 2112-2117) with logic that clamps/validates
webhook_body.execution_mode against the runtime/server execution mode; add
regression tests covering "runtime in Plan Mode + missing request mode" and
"runtime in Plan Mode + standard request mode" for both /webhook and
/web/chat/stream endpoints to ensure the request cannot downgrade the runtime.

In `@clients/agent-runtime/src/gateway/webhook_dispatch.rs`:
- Around line 384-406: Remove the dead helper function
approval_denial_from_history and its associated unit test
approval_denial_is_detected_from_tool_results_history since they are only used
in tests and not referenced by production code; delete the function definition
from webhook_dispatch.rs and remove or comment out the matching test, and run
cargo test to ensure no remaining references or compilation errors.

In `@clients/agent-runtime/src/main.rs`:
- Around line 1546-1554: handle_code_command currently calls run_single(&msg)
which returns only Result<String>, discarding policy_blocked metadata so
cli_blocking_error_from_turn_result is never invoked; update handle_code_command
to either call turn_with_context (same as handle_agent_command) and then pass
the returned AgentTurnResult through cli_blocking_error_from_turn_result before
printing/returning, or modify run_single to return the full AgentTurnResult (not
just String) and apply cli_blocking_error_from_turn_result to that result;
ensure references to run_single, turn_with_context, handle_agent_command,
handle_code_command, cli_blocking_error_from_turn_result, and AgentTurnResult
are used so the blocking check is applied consistently for code sessions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b0eed5b0-f573-4847-a683-d5205eff2e84

📥 Commits

Reviewing files that changed from the base of the PR and between 27bb091 and 30635bd.

📒 Files selected for processing (19)
  • clients/agent-runtime/crates/corvus-channels/src/factory.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • clients/agent-runtime/crates/corvus-composer/src/plan.rs
  • clients/agent-runtime/crates/corvus-composer/src/registry_snapshot.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-memory/src/factory.rs
  • clients/agent-runtime/crates/corvus-memory/src/registry.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/main.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/agent-loop/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/specs/client-surfaces/spec.md
  • scripts/mobile-smoke-test.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: report / Contributor Quality Report
  • GitHub Check: sonar
  • GitHub Check: pr-checks
  • GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (8)
clients/agent-runtime/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Run cargo fmt --all -- --check, cargo clippy --all-targets -- -D warnings, and cargo test for code validation, or document which checks were skipped and why

Files:

  • clients/agent-runtime/crates/corvus-memory/src/registry.rs
  • clients/agent-runtime/crates/corvus-memory/src/factory.rs
  • clients/agent-runtime/crates/corvus-composer/src/plan.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-channels/src/factory.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/registry_snapshot.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
**/*.rs

⚙️ CodeRabbit configuration file

**/*.rs: Focus on Rust idioms, memory safety, and ownership/borrowing correctness.
Flag unnecessary clones, unchecked panics in production paths, and weak error context.
Prioritize unsafe blocks, FFI boundaries, concurrency races, and secret handling.

Files:

  • clients/agent-runtime/crates/corvus-memory/src/registry.rs
  • clients/agent-runtime/crates/corvus-memory/src/factory.rs
  • clients/agent-runtime/crates/corvus-composer/src/plan.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-channels/src/factory.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/registry_snapshot.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
**/*

⚙️ CodeRabbit configuration file

**/*: Security first, performance second.
Validate input boundaries, auth/authz implications, and secret management.
Look for behavioral regressions, missing tests, and contract breaks across modules.

Files:

  • clients/agent-runtime/crates/corvus-memory/src/registry.rs
  • clients/agent-runtime/crates/corvus-memory/src/factory.rs
  • clients/agent-runtime/crates/corvus-composer/src/plan.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-channels/src/factory.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/registry_snapshot.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • openspec/specs/client-surfaces/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/agent-loop/spec.md
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • scripts/mobile-smoke-test.sh
  • clients/agent-runtime/src/gateway/mod.rs
**/*.{md,mdx}

⚙️ CodeRabbit configuration file

**/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes.
For user-facing docs, check EN/ES parity or explicitly note pending translation gaps.

Files:

  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • openspec/specs/client-surfaces/spec.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/specs/agent-loop/spec.md
clients/agent-runtime/src/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

clients/agent-runtime/src/**/*.rs: Never log secrets, tokens, raw credentials, or sensitive payloads in any logging statements
Avoid unnecessary allocations, clones, and blocking operations to maintain performance and efficiency

Files:

  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
clients/agent-runtime/src/main.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

clients/agent-runtime/src/main.rs: Preserve CLI contract unless change is intentional and documented; prefer explicit errors over silent fallback for unsupported critical paths
Keep startup path lean and avoid heavy initialization in command parsing flow

Files:

  • clients/agent-runtime/src/main.rs
clients/agent-runtime/src/{security,gateway,tools}/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Treat src/security/, src/gateway/, src/tools/ as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks

Files:

  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable

Files:

  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/gateway/mod.rs
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs : Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools}/**/*.rs : Treat `src/security/`, `src/gateway/`, `src/tools/` as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/main.rs : Preserve CLI contract unless change is intentional and documented; prefer explicit errors over silent fallback for unsupported critical paths

Applied to files:

  • clients/agent-runtime/crates/corvus-memory/src/registry.rs
  • clients/agent-runtime/crates/corvus-memory/src/factory.rs
  • clients/agent-runtime/crates/corvus-composer/src/plan.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-channels/src/factory.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/registry_snapshot.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • scripts/mobile-smoke-test.sh
  • clients/agent-runtime/src/gateway/mod.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/providers/**/*.rs : Implement `Provider` trait in `src/providers/` and register in `src/providers/mod.rs` factory when adding a new provider

Applied to files:

  • clients/agent-runtime/crates/corvus-memory/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/plan.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-composer/src/registry_snapshot.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/**/Cargo.toml : Do not add heavy dependencies for minor convenience; justify new crate additions

Applied to files:

  • clients/agent-runtime/crates/corvus-memory/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-composer/src/registry_snapshot.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • clients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/**/*.rs : Run `cargo fmt --all -- --check`, `cargo clippy --all-targets -- -D warnings`, and `cargo test` for code validation, or document which checks were skipped and why

Applied to files:

  • clients/agent-runtime/crates/corvus-memory/src/registry.rs
  • clients/agent-runtime/crates/corvus-memory/src/factory.rs
  • clients/agent-runtime/crates/corvus-composer/src/plan.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-channels/src/factory.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/registry_snapshot.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/agent/agent.rs
  • scripts/mobile-smoke-test.sh
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/**/Cargo.toml : Preserve release-size profile assumptions in `Cargo.toml` and avoid adding heavy dependencies unless clearly justified

Applied to files:

  • clients/agent-runtime/crates/corvus-memory/src/factory.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-channels/src/factory.rs
  • clients/agent-runtime/crates/corvus-composer/src/registry_snapshot.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/**/*.rs : Avoid unnecessary allocations, clones, and blocking operations to maintain performance and efficiency

Applied to files:

  • clients/agent-runtime/crates/corvus-memory/src/factory.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • clients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/main.rs : Keep startup path lean and avoid heavy initialization in command parsing flow

Applied to files:

  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/channels/**/*.rs : Implement `Channel` trait in `src/channels/` with consistent `send`, `listen`, and `health_check` semantics and cover auth/allowlist/health behavior with tests

Applied to files:

  • clients/agent-runtime/crates/corvus-channels/src/factory.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • clients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs : Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable

Applied to files:

  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • scripts/mobile-smoke-test.sh
  • clients/agent-runtime/src/gateway/mod.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/tools/**/*.rs : Implement `Tool` trait in `src/tools/` with strict parameter schema, validate and sanitize all inputs, and return structured `ToolResult` without panics in runtime path

Applied to files:

  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools}/**/*.rs : Treat `src/security/`, `src/gateway/`, `src/tools/` as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks

Applied to files:

  • clients/agent-runtime/crates/corvus-composer/src/manifest.rs
  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/design.md
  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
  • scripts/mobile-smoke-test.sh
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Include threat/risk notes and rollback strategy for security, runtime, and gateway changes; add or update tests for boundary checks and failure modes

Applied to files:

  • openspec/changes/archive/2026-04-13-claude-capability-integration/verify-report.md
  • clients/agent-runtime/src/agent/dispatcher.rs
  • clients/agent-runtime/src/agent/agent.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Inspect existing module and adjacent tests before editing; define scope boundary with one concern per PR and avoid mixed feature+refactor+infra patches

Applied to files:

  • openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/.github/**/*.{yml,yaml} : For workflow/template-only changes, ensure YAML/template syntax validity

Applied to files:

  • scripts/mobile-smoke-test.sh
🪛 LanguageTool
openspec/changes/archive/2026-04-13-claude-capability-integration/design.md

[style] ~92-~92: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...er tools only in bootstrap - Deny tools only at dispatch time - Rely on provider ins...

(ADVERB_REPETITION_PREMIUM)


[grammar] ~128-~128: Ensure spelling is correct
Context: ...ts transport callers, tests, and future surfaces distinguish policy class from transport...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.22.0)
openspec/changes/archive/2026-04-13-claude-capability-integration/design.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

openspec/changes/archive/2026-04-13-claude-capability-integration/proposal.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🪛 Shellcheck (0.11.0)
scripts/mobile-smoke-test.sh

[info] 50-50: Use find instead of ls to better handle non-alphanumeric filenames.

(SC2012)

🔇 Additional comments (14)
clients/agent-runtime/src/gateway/mod.rs (1)

1846-1861: Structured plan_mode_blocked propagation looks good.

The JSON response, SSE error event, and regression tests all preserve the same machine-readable denial fields, which is the right contract for fail-closed clients.

Also applies to: 2169-2179, 5579-5724

clients/agent-runtime/src/agent/agent.rs (7)

357-359: LGTM: Default security policy now applied correctly.

The builder now falls back to SecurityPolicy::default() when unset, addressing the previous review concern about breaking callers. This maintains secure-by-default behavior while preserving backward compatibility.


1549-1560: LGTM: Clean denial result construction.

The blocked_result function correctly constructs a structured denial with the policy code and reason, enabling downstream consumers (CLI, gateway) to distinguish Plan Mode blocks from approval-required denials.


2260-2269: LGTM: Correct routing of Plan Mode blocks.

The code correctly distinguishes plan_mode_blocked from approval_required by checking the denial code, ensuring Plan Mode enforces fail-closed semantics rather than falling into the approval flow.


1473-1488: LGTM: Blocked tools correctly excluded from execution.

The Blocked variant is handled identically to ApprovalRequired in terms of preventing execution—blocked calls never reach execute_tools. This maintains the fail-closed contract for Plan Mode.


2242-2255: LGTM: Mission pre-check includes Blocked variant.

The mission context correctly bails on both ApprovalRequired and Blocked actions, preventing partial execution when Plan Mode (or other policy) would deny a delegated tool call.


57-64: LGTM: Sensible default for execution mode.

Defaulting to ExecutionMode::Standard in with_session is correct—Plan Mode is opt-in and adds restrictions rather than being the baseline that could be accidentally bypassed.


1517-1537: LGTM: Consistent denial payload structure.

The Blocked variant produces the same JSON shape ({code, tool, reason}) as ApprovalRequired, enabling uniform parsing in gateway/CLI consumers.

clients/agent-runtime/src/gateway/webhook_dispatch.rs (6)

438-456: LGTM: Clean config isolation per request.

The effective_config clone ensures each webhook request's execution_mode is isolated—no risk of Plan Mode leaking between concurrent requests.


516-528: LGTM: Robust denial parsing.

The function correctly extracts the (code, tool, reason) tuple with a sensible fallback for missing reason. Returning None on malformed payloads lets callers fail safely to Error.


219-238: LGTM: PlanModeBlocked canonical mapping.

The mapping correctly propagates execution_mode to the outcome and emits SSE frames with the plan_mode_blocked event code. No response text ensures the block is surfaced to the caller without partial results.


310-318: LGTM: Fallback reason handling includes Blocked.

The Blocked variant correctly falls through to the default reason format, as the actual denial reason is extracted from the policy evaluation, not this fallback path.


986-1030: LGTM: Good integration test coverage.

The test verifies the full webhook dispatch path for Plan Mode: request with execution_mode: Planfile_write tool call → PlanModeBlocked outcome. This validates the end-to-end contract.


463-479: Fail-closed policy handling is correct; extensibility can be addressed when new policy codes are introduced.

When policy_blocked contains a code other than PLAN_MODE_BLOCKED_CODE, it maps to CanonicalWebhookResult::Error. This is secure-by-default behavior (deny-by-default). Currently, only PLAN_MODE_BLOCKED_CODE is defined; future codes (e.g., rate limiting) should be added explicitly as new enum variants in CanonicalWebhookResult rather than relying on pattern matching, which will maintain type safety and prevent accidental silent failures.

Comment on lines +446 to +468
#[test]
fn plan_mode_denials_become_blocked_actions_without_changing_standard_semantics() {
let mut policy = SecurityPolicy::default();
policy.execution_mode = crate::config::ExecutionMode::Plan;

assert_eq!(
evaluate_tool_risk_with_policy("file_read", &policy),
DispatchAction::Execute
);

match evaluate_tool_risk_with_policy("file_write", &policy) {
DispatchAction::Blocked { code, reason } => {
assert_eq!(code, crate::security::PLAN_MODE_BLOCKED_CODE);
assert!(reason.contains("Plan Mode allows analysis-only capabilities"));
}
other => panic!("expected blocked plan-mode action, got {other:?}"),
}

assert_eq!(
evaluate_tool_risk("shell"),
DispatchAction::ApprovalRequired("shell".into())
);
}
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.

⚠️ Potential issue | 🟡 Minor

Exercise the policy-aware standard path in this regression test.

The last assertion calls evaluate_tool_risk("shell"), which bypasses evaluate_tool_risk_with_policy_for_origin(...). This test can still pass if the standard-mode branch in the new helper regresses again.

Suggested fix
     match evaluate_tool_risk_with_policy("file_write", &policy) {
         DispatchAction::Blocked { code, reason } => {
             assert_eq!(code, crate::security::PLAN_MODE_BLOCKED_CODE);
             assert!(reason.contains("Plan Mode allows analysis-only capabilities"));
         }
         other => panic!("expected blocked plan-mode action, got {other:?}"),
     }

+    let standard_policy = SecurityPolicy::default();
     assert_eq!(
-        evaluate_tool_risk("shell"),
+        evaluate_tool_risk_with_policy("shell", &standard_policy),
         DispatchAction::ApprovalRequired("shell".into())
     );

Based on learnings: Include threat/risk notes and rollback strategy for security, runtime, and gateway changes; add or update tests for boundary checks and failure modes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/agent/dispatcher.rs` around lines 446 - 468, The
test bypasses the policy-aware path by calling evaluate_tool_risk("shell");
replace that call with the policy-aware helper (e.g.,
evaluate_tool_risk_with_policy_for_origin or evaluate_tool_risk_with_policy)
using the same SecurityPolicy instance (`policy`) so the final assertion
exercises the standard-mode branch under the policy and still asserts
DispatchAction::ApprovalRequired("shell".into()); update the assertion to use
the returned value from the policy-aware helper.

Comment thread clients/agent-runtime/src/main.rs
- cli_blocking_error_from_turn_result: treat all policy_blocked as errors, not just PLAN_MODE_BLOCKED_CODE
- gateway: prevent client from downgrading server execution mode with resolve_webhook_execution_mode helper
- gateway: add regression tests for execution mode clamping
- webhook_dispatch: remove dead approval_denial_from_history function and test
- main: fix handle_code_command to use turn_with_context and apply cli_blocking_error_from_turn_result
- remove unused imports (ConversationMessage, ToolResultMessage)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (2)
clients/agent-runtime/src/gateway/webhook_dispatch.rs (1)

492-503: ⚠️ Potential issue | 🟠 Major

Don't require code for approval-required payloads.

The approval path at Lines 456-463 ignores code, but this helper makes it mandatory. That means any producer that emits { "tool": ..., "reason": ... } without code now degrades to WebhookTerminalOutcome::Error instead of preserving the approval-required contract. Split the approval and policy-blocked parsers, or make code optional here, and add a regression test for a code-less approval payload.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/gateway/webhook_dispatch.rs` around lines 492 -
503, The helper policy_denial_from_value currently requires a "code" field which
causes code-less approval-required payloads to be treated as errors; change
policy_denial_from_value to make the "code" extraction optional (return
Option<(Option<String>, String, String)> or split into two helpers: one for
approval-only parsing and one for policy-blocked parsing), update any callers
that expect a non-optional code (e.g., the approval path that uses
approval_reason_for_tool and the WebhookTerminalOutcome construction) to accept
the optional code path, and add a regression test asserting that a payload like
{ "tool": "...", "reason": "..." } is parsed as an approval-required outcome
rather than an error. Ensure the policy-blocked branch still enforces code
presence if needed.
clients/agent-runtime/src/gateway/mod.rs (1)

1966-1985: ⚠️ Potential issue | 🟠 Major

Fail closed when Plan Mode reaches the legacy webhook path.

execution_mode is only resolved and passed inside the dispatcher branch. If webhook_dispatcher_enabled is false, a request with "execution_mode":"plan" still falls through to the legacy path, which can auto_save conversation state and run simple_chat() without any Plan-mode enforcement. That silently drops the read-only guarantee on one transport path. Compute the effective mode before branching and reject Plan unless the dispatcher path is available, or enforce equivalent read-only behavior in the legacy path.

As per coding guidelines: clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs: Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable.

Also applies to: 2114-2140

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/agent-runtime/src/gateway/mod.rs` around lines 1966 - 1985, Compute
the effective execution mode before the dispatcher branch by calling
resolve_webhook_execution_mode(server_execution_mode,
webhook_body.execution_mode) and store it in a variable; then use
webhook_dispatcher_enabled(&config) to decide path: if the resolved mode is Plan
and dispatcher is not enabled, return an error/deny the request (fail-closed),
or alternatively enforce read-only behavior in the legacy path by disabling
auto_save and preventing simple_chat execution when the resolved mode is Plan;
update references around server_execution_mode, webhook_dispatcher_enabled,
resolve_webhook_execution_mode, webhook_dispatch::execute, simple_chat, and any
auto_save logic so Plan mode is never allowed to silently fall back to the
legacy path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/agent-runtime/src/gateway/webhook_dispatch.rs`:
- Around line 414-415: The code currently assigns request.execution_mode
directly into effective_config.agent.execution_mode after cloning config;
instead, clamp or validate request.execution_mode against the server-enforced
config before assigning so callers cannot downgrade a server-mandated
execution_mode. Update the assignment near effective_config = config.clone() to
compute a safe_mode = clamp_execution_mode(request.execution_mode,
config.agent.execution_mode) or similar policy check, and then set
effective_config.agent.execution_mode = safe_mode (fail closed to the
more-restrictive mode if mismatch). Locate and change the usage of
effective_config.agent.execution_mode and request.execution_mode in
webhook_dispatch.rs to apply this validation before any bootstrap logic runs.

---

Outside diff comments:
In `@clients/agent-runtime/src/gateway/mod.rs`:
- Around line 1966-1985: Compute the effective execution mode before the
dispatcher branch by calling
resolve_webhook_execution_mode(server_execution_mode,
webhook_body.execution_mode) and store it in a variable; then use
webhook_dispatcher_enabled(&config) to decide path: if the resolved mode is Plan
and dispatcher is not enabled, return an error/deny the request (fail-closed),
or alternatively enforce read-only behavior in the legacy path by disabling
auto_save and preventing simple_chat execution when the resolved mode is Plan;
update references around server_execution_mode, webhook_dispatcher_enabled,
resolve_webhook_execution_mode, webhook_dispatch::execute, simple_chat, and any
auto_save logic so Plan mode is never allowed to silently fall back to the
legacy path.

In `@clients/agent-runtime/src/gateway/webhook_dispatch.rs`:
- Around line 492-503: The helper policy_denial_from_value currently requires a
"code" field which causes code-less approval-required payloads to be treated as
errors; change policy_denial_from_value to make the "code" extraction optional
(return Option<(Option<String>, String, String)> or split into two helpers: one
for approval-only parsing and one for policy-blocked parsing), update any
callers that expect a non-optional code (e.g., the approval path that uses
approval_reason_for_tool and the WebhookTerminalOutcome construction) to accept
the optional code path, and add a regression test asserting that a payload like
{ "tool": "...", "reason": "..." } is parsed as an approval-required outcome
rather than an error. Ensure the policy-blocked branch still enforces code
presence if needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b58e9a02-6050-4f01-a19e-79b6c5863772

📥 Commits

Reviewing files that changed from the base of the PR and between 30635bd and 67b5942.

📒 Files selected for processing (3)
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
  • clients/agent-runtime/src/main.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: report / Contributor Quality Report
  • GitHub Check: pr-checks
  • GitHub Check: sonar
  • GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (7)
clients/agent-runtime/src/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

clients/agent-runtime/src/**/*.rs: Never log secrets, tokens, raw credentials, or sensitive payloads in any logging statements
Avoid unnecessary allocations, clones, and blocking operations to maintain performance and efficiency

Files:

  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
clients/agent-runtime/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Run cargo fmt --all -- --check, cargo clippy --all-targets -- -D warnings, and cargo test for code validation, or document which checks were skipped and why

Files:

  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
clients/agent-runtime/src/main.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

clients/agent-runtime/src/main.rs: Preserve CLI contract unless change is intentional and documented; prefer explicit errors over silent fallback for unsupported critical paths
Keep startup path lean and avoid heavy initialization in command parsing flow

Files:

  • clients/agent-runtime/src/main.rs
**/*.rs

⚙️ CodeRabbit configuration file

**/*.rs: Focus on Rust idioms, memory safety, and ownership/borrowing correctness.
Flag unnecessary clones, unchecked panics in production paths, and weak error context.
Prioritize unsafe blocks, FFI boundaries, concurrency races, and secret handling.

Files:

  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
**/*

⚙️ CodeRabbit configuration file

**/*: Security first, performance second.
Validate input boundaries, auth/authz implications, and secret management.
Look for behavioral regressions, missing tests, and contract breaks across modules.

Files:

  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
clients/agent-runtime/src/{security,gateway,tools}/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Treat src/security/, src/gateway/, src/tools/ as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks

Files:

  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs

📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)

Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable

Files:

  • clients/agent-runtime/src/gateway/mod.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs : Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools}/**/*.rs : Treat `src/security/`, `src/gateway/`, `src/tools/` as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/main.rs : Preserve CLI contract unless change is intentional and documented; prefer explicit errors over silent fallback for unsupported critical paths

Applied to files:

  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/mod.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/**/*.rs : Run `cargo fmt --all -- --check`, `cargo clippy --all-targets -- -D warnings`, and `cargo test` for code validation, or document which checks were skipped and why

Applied to files:

  • clients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/main.rs : Keep startup path lean and avoid heavy initialization in command parsing flow

Applied to files:

  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/webhook_dispatch.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs : Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable

Applied to files:

  • clients/agent-runtime/src/main.rs
  • clients/agent-runtime/src/gateway/mod.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/**/*.rs : Avoid unnecessary allocations, clones, and blocking operations to maintain performance and efficiency

Applied to files:

  • clients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/tools/**/*.rs : Implement `Tool` trait in `src/tools/` with strict parameter schema, validate and sanitize all inputs, and return structured `ToolResult` without panics in runtime path

Applied to files:

  • clients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools}/**/*.rs : Treat `src/security/`, `src/gateway/`, `src/tools/` as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks

Applied to files:

  • clients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/channels/**/*.rs : Implement `Channel` trait in `src/channels/` with consistent `send`, `listen`, and `health_check` semantics and cover auth/allowlist/health behavior with tests

Applied to files:

  • clients/agent-runtime/src/main.rs
🔇 Additional comments (1)
clients/agent-runtime/src/gateway/webhook_dispatch.rs (1)

219-238: Good fail-closed mapping for Plan Mode denials.

This keeps webhook transport aligned with the new plan_mode_blocked policy outcome and preserves a machine-readable denial path instead of collapsing it into a generic error.

Comment thread clients/agent-runtime/src/gateway/webhook_dispatch.rs Outdated
…parsing

- Clamp request execution mode against server config in webhook_dispatch
- Make resolve_webhook_execution_mode public for use in webhook_dispatch.rs
- Add explicit 403 error when Plan mode requested but dispatcher disabled
- Split policy_denial_from_value into two functions:
  - approval_denial_from_value: code is optional (approval-only payloads)
  - policy_denial_from_value: code is required (policy_blocked payloads)

Fixes PR #530 inline comments.
@sonarqubecloud
Copy link
Copy Markdown

@yacosta738 yacosta738 merged commit 43c8b45 into main Apr 13, 2026
13 checks passed
@yacosta738 yacosta738 deleted the feature/plan-mode-execution branch April 13, 2026 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plan Mode: Explicit Read-Only Execution Mode Run Android and iOS mobile parity smoke validation

1 participant