Skip to content

feat: capability-based agent composition and architecture#520

Merged
yacosta738 merged 13 commits into
mainfrom
feature/capability-architecture
Apr 12, 2026
Merged

feat: capability-based agent composition and architecture#520
yacosta738 merged 13 commits into
mainfrom
feature/capability-architecture

Conversation

@yacosta738
Copy link
Copy Markdown
Contributor

Summary

  • Add capability-based agent composition with registry system for providers, channels, memory, tools, security, and observability
  • Implement agent composer with manifest parsing, plan generation, and dependency resolution
  • Add WCAG 2.1 AA accessibility improvements to dashboard
  • Add chat navigation item and improve accessibility features
  • Add beta release workflow configuration for testing release process

Changes

  • Agent Runtime: Capability-based architecture with registry snapshots and resolvers
  • Dashboard: Accessibility improvements and new chat navigation
  • Documentation: Update configuration and customization guides in English and Spanish
  • CI/CD: New beta release workflow (release-please-beta) for testing

Testing

  • 3488 Rust tests pass
  • Web lint and accessibility checks pass
  • Pre-push hook validation successful

Risks

  • New capability architecture may require user migration guide
  • Beta release workflow needs validation before production use

- Add skip link to main content
- Add auth field semantics (autocomplete, aria-describedby)
- Add focus trap to delete confirmation dialog
- Add focus restoration for session detail
- Add error summary with focus navigation in WebhookSettings
- Add target size improvements (24px min) to buttons
- Add vitest happy-dom environment config
Introduce registry-backed manifest composition so runtime capabilities can be selected declaratively while preserving the existing full-runtime bootstrap path.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 12, 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 registry/factory surfaces for capability families, implements a manifest-driven composer that validates and resolves AgentManifest into a ComposedRuntimePlan, materials composed bootstrap helpers to instantiate runtimes from plans, introduces beta-aware release automation, and adds broad documentation, spec archives, and dashboard accessibility/tests.

Changes

Cohort / File(s) Summary
Capability crates: registries & factories
clients/agent-runtime/crates/corvus-providers/src/{registry,factory}.rs, clients/agent-runtime/crates/corvus-channels/src/{registry,factory}.rs, clients/agent-runtime/crates/corvus-tools/src/{registry,factory}.rs, clients/agent-runtime/crates/corvus-memory/src/{registry,factory}.rs, clients/agent-runtime/crates/corvus-security/src/{registry,factory}.rs, clients/agent-runtime/crates/corvus-observability/src/lib.rs, clients/agent-runtime/crates/.../src/lib.rs
Introduce static descriptors, availability enums, resolve/list APIs, and factory selection helpers; rework crate public APIs to expose registry/factory modules and re-exports.
Composer: manifest, plan, resolver, snapshot
clients/agent-runtime/crates/corvus-composer/src/{manifest,plan,registry_snapshot,resolver}.rs, clients/agent-runtime/crates/corvus-composer/src/lib.rs
Add typed AgentManifest schema, ComposedRuntimePlan and CapabilityReport types, RegistrySnapshot collection, resolver with deterministic validation and ValidationError variants; expose parse/resolve/required_capabilities APIs.
Bootstrap & runtime wiring
clients/agent-runtime/src/bootstrap/composed.rs, clients/agent-runtime/src/bootstrap/mod.rs, clients/agent-runtime/src/composer.rs, clients/agent-runtime/src/{channels,providers,memory,observability,security}/*.rs, clients/agent-runtime/src/agent/agent.rs
New composed bootstrap entrypoints (bootstrap_from_plan, agent_from_plan), root shim changes to normalize capability keys via registries, CLI composer flow updated to load/resolve manifests and compose plans; added/updated unit tests.
Workspace / Cargo updates
clients/agent-runtime/Cargo.toml, clients/agent-runtime/crates/corvus-observability/Cargo.toml, .release-please-beta-manifest.json
Add corvus-observability crate and workspace wiring; add beta manifest entry.
CI / release workflows
.github/workflows/release-please-beta.yml, .github/workflows/_publish.yml, .github/workflows/{publish-release,publish-snapshot,release-please}.yml, release-please-beta-config.json, scripts/release-contract.test.mjs
Add beta release workflow; make _publish.yml channel-aware with prerelease input and outputs; update callers and tests to validate beta prerelease/tag/dist-tag behavior.
Docs, specs & archives
clients/web/apps/docs/src/content/docs/**, openspec/changes/archive/2026-04-12-capability-based-agent-composition/*, openspec/specs/*, .agents/journal/scribe-journal.md
Large documentation rewrites and translations: configuration/customization/features/release guides; new agent-composer and capability-architecture specs, design/tasks/verify archives; replace scribe-journal entry with Documentation Accuracy Audit.
Web dashboard: accessibility & tests
clients/web/apps/dashboard/src/{App.vue,App.spec.ts}, clients/web/apps/dashboard/src/components/**/**/*.vue, clients/web/apps/dashboard/e2e/accessibility-smoke.spec.ts, clients/web/apps/dashboard/src/test/runAxe.ts
Add focus management, ARIA/live regions, input attributes, help text, touch-target sizing; add Axe helper, accessibility unit and e2e tests, and expose some component focus methods.
Web test infra & deps
clients/web/apps/dashboard/package.json, clients/web/apps/dashboard/scripts/run-coverage.mjs, clients/web/apps/dashboard/vite.config.ts, clients/web/pnpm-workspace.yaml
Add coverage runner, Vitest happy-dom test config, Axe/Playwright devDeps, run scripts, and pnpm catalog entries.
Front-end locales & UI tweaks
clients/web/packages/locales/src/{en,es}.json, multiple *.vue style tweaks
Add nav.chat locale entries; multiple UI accessibility/touch-target style adjustments.
Misc / tests / lint / ignores
.gitignore, CHANGELOG.md, various test files across clients/agent-runtime and clients/web
Ignore additional test artifacts, changelog version range tweak, numerous unit/test updates reflecting API and accessibility changes.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as Composer CLI
    participant Loader as Manifest Loader
    participant Snapshot as RegistrySnapshot
    participant Resolver as Resolver
    participant Bootstrap as Composed Bootstrap
    participant Runtime as AgentBuilder/Runtime

    User->>CLI: load_composer(manifest_path)
    CLI->>Loader: parse_manifest(toml_string)
    Loader-->>CLI: AgentManifest
    CLI->>Snapshot: RegistrySnapshot::collect()
    Snapshot->>Snapshot: gather families (provider/channel/tool/memory/observer/security)
    Snapshot-->>CLI: snapshot
    CLI->>Resolver: resolve_manifest(&manifest, &snapshot)
    Resolver-->>CLI: ComposedRuntimePlan / ValidationError
    CLI->>Bootstrap: bootstrap_from_plan(&config, &plan)
    Bootstrap->>Bootstrap: materialize sandbox/observer/memory/tools/provider
    Bootstrap-->>Runtime: construct AgentBuilder inputs
    Runtime-->>CLI: ready Agent
    CLI-->>User: composed agent ready
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • yuniel-acosta
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/capability-architecture

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

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

Deploying corvus with  Cloudflare Pages  Cloudflare Pages

Latest commit: e8712ef
Status: ✅  Deploy successful!
Preview URL: https://fe15c03e.corvus-42x.pages.dev
Branch Preview URL: https://feature-capability-architect.corvus-42x.pages.dev

View logs

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 12, 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 3089 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 238 >= 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-12 to 2026-04-12

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

Caution

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

⚠️ Outside diff range comments (7)
clients/web/apps/docs/src/content/docs/es/guides/configuration.md (1)

11-228: ⚠️ Potential issue | 🟡 Minor

Confirm EN/ES parity (or add an explicit translation-gap note).

This is a substantial user-facing ES rewrite; please ensure the corresponding EN doc is updated in the same release window, or add a clear “pending EN sync” note to avoid drift.

As per coding guidelines **/*.{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.”

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

In `@clients/web/apps/docs/src/content/docs/es/guides/configuration.md` around
lines 11 - 228, This Spanish doc is a substantial user-facing rewrite and needs
EN/ES parity; either update the corresponding English doc within the same
release window or add an explicit “Pending EN sync” note at the top of this file
so readers and reviewers know the translation gap. Locate the Spanish page
(configuration.md) — specifically the top-level heading "Configuración del Agent
Runtime (`~/.corvus/config.toml`)" and the overall runtime/config sections — and
either mirror the changes into the English version or add a clear badge/notice
under the main title stating the EN translation is pending, referencing the
repository doc guideline for **/*.{md,mdx} parity.
clients/web/apps/dashboard/src/components/memory/MemoryList.spec.ts (1)

140-238: ⚠️ Potential issue | 🟡 Minor

Add teardown for mounted wrappers to prevent focus/DOM leakage between tests.

These new cases assert document.activeElement and dialog state, but the file still mounts into document.body without unmount cleanup, which can make runs order-dependent.

Suggested fix
-import { beforeEach, describe, expect, it, vi } from "vitest";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
@@
+const mountedWrappers = new Set<ReturnType<typeof mount>>();
+
 function mountMemoryList(props?: Record<string, unknown>) {
-  return mount(MemoryList, {
+  const wrapper = mount(MemoryList, {
     attachTo: document.body,
@@
-  });
+  });
+  mountedWrappers.add(wrapper);
+  return wrapper;
 }
+
+afterEach(() => {
+  for (const wrapper of mountedWrappers) wrapper.unmount();
+  mountedWrappers.clear();
+  document.body.replaceChildren();
+});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/web/apps/dashboard/src/components/memory/MemoryList.spec.ts` around
lines 140 - 238, Add an afterEach teardown that unmounts/destroys the mounted
wrapper and clears DOM focus to prevent leakage between tests: ensure any
Wrapper returned by mountMemoryList() (the local variable wrapper in tests) is
cleaned up by calling wrapper.unmount() or wrapper.destroy() (depending on your
Vue Test Utils version) and reset document.activeElement (e.g., blur) after each
test; place this in an afterEach hook in MemoryList.spec.ts so all tests that
use mountMemoryList(), mockMemoryResponse, and assert document.activeElement run
with a clean DOM.
clients/web/apps/docs/src/content/docs/guides/configuration.md (1)

13-209: ⚠️ Potential issue | 🟡 Minor

Update require_approval_for_medium_risk default value in documentation.

The documented autonomy config shows require_approval_for_medium_risk = false, but the actual default in the config schema is true. This mismatch could mislead users about the actual security posture. Additionally, the autonomy section is incomplete—the schema also defines allowed_commands, forbidden_paths, auto_approve, and always_ask fields that should be documented for completeness.

All other documented config keys (sandbox options, memory backends, gateway settings) correctly match the implementation.

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

In `@clients/web/apps/docs/src/content/docs/guides/configuration.md` around lines
13 - 209, Update the autonomy section in the docs: change the default for
require_approval_for_medium_risk to true (it currently shows false) and expand
the `[autonomy]` block to document the additional schema fields
allowed_commands, forbidden_paths, auto_approve, and always_ask (describe their
purpose and expected types/values). Locate the autonomy example under "Agent
Runtime Configuration (`~/.corvus/config.toml`)" and update the `[autonomy]`
snippet and surrounding explanatory text to reflect these keys and the correct
default for require_approval_for_medium_risk.
.github/workflows/README.md (1)

697-710: ⚠️ Potential issue | 🟡 Minor

Update the dependency diagram for the beta release path.

The prose above now documents release-please-beta.yml as another caller of _publish.yml, but the workflow dependency block still omits it. That leaves the canonical workflow README internally inconsistent.

As per coding guidelines, **/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes.

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

In @.github/workflows/README.md around lines 697 - 710, The workflow dependency
diagram and caller list are missing release-please-beta.yml; update the block
that currently shows "publish-release.yml" and "publish-snapshot.yml" ->
"_publish.yml" to include release-please-beta.yml as another caller of
_publish.yml, and add release-please-beta.yml to the prose list of Other
workflows that call dallay/common-actions so the README's dependency diagram and
description (references: publish-release.yml, publish-snapshot.yml,
_publish.yml, release-please-beta.yml) are consistent.
clients/web/apps/docs/src/content/docs/es/guides/release.md (1)

162-167: ⚠️ Potential issue | 🟠 Major

La recuperación beta todavía apunta al flujo estable.

Este procedimiento ahora dice cubrir baseline estable o beta, pero los pasos siguientes siguen hablando solo del tag vX.Y.Z, del GitHub Release estable y de reejecutar la publicación estable. Si alguien repara vX.Y.Z-beta.N, este runbook lo manda al canal equivocado. Divide esos pasos por canal o parametriza explícitamente tag/release/handoff beta.

As per coding guidelines, **/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes.

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

In `@clients/web/apps/docs/src/content/docs/es/guides/release.md` around lines 162
- 167, The runbook currently assumes the stable channel (references to tag
`vX.Y.Z`, GitHub Release and re-running `release.published`) but must support
beta flows (e.g., `vX.Y.Z-beta.N`); update the steps to either branch by channel
or accept a channel parameter and explicitly substitute tag/release names—ensure
items 1–6 mention both
`.release-please-manifest.json`/`.release-please-beta-manifest.json`,
`version.txt`, Gradle/Cargo/npm version files, the expected SHA, and conditional
logic for canonical tag (`vX.Y.Z`) vs beta tag (`vX.Y.Z-beta.N`), conditional
check for the corresponding GitHub Release, and for step 5 instruct to reset the
authority and re-run the matching publication (`release.published` for stable or
the beta publication job) depending on the channel; also add a short note in
step 6 to choose a new baseline rather than rewriting history for either
channel.
clients/web/apps/docs/src/content/docs/guides/release.md (1)

162-167: ⚠️ Potential issue | 🟠 Major

Beta recovery steps still send operators down the stable path.

This section now says it covers stable or beta baseline repair, but Steps 3-5 still only refer to vX.Y.Z, the canonical GitHub Release, and rerunning the stable release.published handoff. That is the wrong recovery path for vX.Y.Z-beta.N. Split the procedure by channel or parameterize the beta tag/release/handoff explicitly.

As per coding guidelines, **/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes.

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

In `@clients/web/apps/docs/src/content/docs/guides/release.md` around lines 162 -
167, The recovery checklist currently assumes stable releases (references to
vX.Y.Z, canonical GitHub Release, and rerunning the stable release.published
handoff) but is used for beta repair too; update the steps around 3–5 in the
document to branch by channel: explicitly handle stable vs beta (e.g., keep
vX.Y.Z, GitHub Release, and rerun stable release.published for stable), and add
the parallel beta flow that uses the beta tag format vX.Y.Z-beta.N, checks for a
beta GitHub Release/tag and reruns the beta publish workflow (or the appropriate
beta handoff) instead of release.published; ensure mentions of
.release-please-manifest.json, version.txt, and release.published are
parameterized or duplicated so operators clearly see which file/tag/workflow
applies to stable vs beta.
.github/workflows/_publish.yml (1)

501-507: ⚠️ Potential issue | 🔴 Critical

Add publish as a direct dependency of both npm jobs.

Lines 575 and 644 reference needs.publish.outputs.npm_dist_tag, but neither job declares publish in needs. In GitHub Actions, job outputs are only accessible from direct dependencies. For beta releases, this will either break the workflow or silently fall back to latest, promoting prerelease packages to the stable npm dist-tag.

Suggested fix
  publish-npm-platforms:
     if: ${{ inputs.release }}
-    needs: build-native-binaries
+    needs: [publish, build-native-binaries]
@@
  publish-npm-base:
     if: ${{ inputs.release }}
-    needs: publish-npm-platforms
+    needs: [publish, publish-npm-platforms]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/_publish.yml around lines 501 - 507, The npm jobs that
read needs.publish.outputs.npm_dist_tag must declare publish as a direct
dependency; update each npm job's needs (e.g., add "publish" to the needs array
for the publish-npm-platforms job and the other npm jobs that reference
needs.publish.outputs.npm_dist_tag) so they directly depend on the publish job
and can access its outputs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agents/journal/scribe-journal.md:
- Around line 7-90: Several Markdown headings in scribe-journal.md (e.g.,
"Structure Assessment", "CLI Reference (`guides/cli-reference.md`)", "Cerebro
CLI (`cerebro/cli-reference.md`)" and others) are missing required surrounding
blank lines and trigger MD022; insert a single blank line above and below each
top-level and subheading so every heading is separated from adjacent content
(ensure lists and preceding paragraphs end with a blank line before the heading
and add a blank line after the heading before the following paragraph or list).
Locate headings by their exact text (e.g., "Structure Assessment", "CLI
Reference (`guides/cli-reference.md`)", "Cerebro CLI
(`cerebro/cli-reference.md`)", etc.) in scribe-journal.md and normalize spacing
consistently across the file to satisfy MD022.

In @.github/workflows/README.md:
- Around line 311-317: The Inputs table block is not separated from surrounding
text and triggers MD058; edit the README.md where the Inputs table (the
pipe-style table listing `release`, `prerelease`, `release_tag`, `release_id`)
appears and add a blank line immediately before the table and a blank line
immediately after it so the table is isolated from adjacent paragraph text.

In @.github/workflows/release-please-beta.yml:
- Around line 4-8: The workflow allows manual dispatch from any branch; add a
branch-guard condition to every job so the workflow only runs using beta sources
by checking the ref for both push and dispatch events (e.g., set each job's if
to: github.ref == 'refs/heads/beta' || (github.event_name == 'workflow_dispatch'
&& github.event.ref == 'beta')). Update the job-level conditions (for jobs like
any publish or build jobs) to use that exact expression so manual
workflow_dispatches from other branches are ignored.

In @.gitignore:
- Line 223: Remove the redundant ignore entry '/.playwright-mcp/' from
.gitignore because the existing pattern '.playwright-mcp/' already ignores those
directories at all levels; locate the literal '/.playwright-mcp/' line in the
file and delete it so only the general '.playwright-mcp/' pattern remains.

In `@clients/agent-runtime/crates/corvus-channels/src/registry.rs`:
- Around line 116-122: The ChannelDescriptor entry for the "webhook" channel
currently sets compiled: false but platform_supported: true, which misrepresents
its availability; update the ChannelDescriptor for key "webhook" to either set
platform_supported: false to reflect that it cannot be constructed until
compiled, or add a concise inline comment next to the "webhook" descriptor
explaining it is a placeholder/deferred implementation so callers of
channel_availability() (which returns CapabilityAvailability::Uncompiled) are
not misled; ensure you reference the ChannelDescriptor for "webhook" and adjust
the compiled/platform_supported flags or add the explanatory comment
accordingly.

In `@clients/agent-runtime/crates/corvus-composer/src/lib.rs`:
- Around line 231-255: The test platform_unavailable_failure_is_distinct
currently skips on Linux due to #[cfg(not(target_os = "linux"))]; modify the
test to force the PlatformUnavailableCapability path even on Linux by injecting
a fake/override snapshot or capability during AgentComposer::from_toml
invocation (e.g., register or pass a mock provider/capability that reports
unavailable) so AgentComposer::from_toml returns the
PlatformUnavailableCapability error; assert the error string still contains
"unavailable on this platform" and keep the test logic but remove or
conditionally bypass the cfg so CI/Linux runs the failure path.

In `@clients/agent-runtime/crates/corvus-composer/src/manifest.rs`:
- Line 6: The manifest's version field (pub version: String in Manifest) is
unvalidated; add validation during parsing/resolution to reject unsupported
formats/ranges (e.g., accept only "1" or semver-compatible values). Update the
parser/resolver that constructs Manifest (or add a
Manifest::validate/ManifestVersion enum) to parse and validate the version
string, returning a clear error for unsupported versions so callers fail fast in
the resolver logic.

In `@clients/agent-runtime/crates/corvus-composer/src/resolver.rs`:
- Around line 115-167: Canonicalize selected capability names via the registry
before performing the prechecks and calls to validate_selected_config_keys:
replace direct comparisons of raw manifest strings (e.g.,
manifest.providers.default, manifest.providers.enabled,
manifest.channels.default, manifest.channels.enabled, manifest.tools.enabled,
manifest.memory.backend, manifest.observability.enabled,
manifest.security.backend and the config key iterators) with their canonical
names obtained from the registry (e.g., call registry.find_in_family or the
project's canonicalization helper for
CapabilityFamily::Provider/Channel/Tool/Memory/Observer/Security) and then use
those canonical names for the default checks and for the lists passed into
validate_selected_config_keys; apply the same canonicalization change to the
analogous block at lines 206-218 so defaults, config keys, and tool_restrictions
are validated against canonical keys rather than raw input.

In `@clients/agent-runtime/crates/corvus-memory/src/registry.rs`:
- Around line 1-6: The enum CapabilityAvailability defined in registry.rs is
duplicated across multiple crates; move this type into the corvus-traits crate
as the single source of truth, delete the local definitions in corvus-memory
(registry.rs) and the other crates, and update all uses to import the shared
type from corvus_traits (e.g. use corvus_traits::CapabilityAvailability). Update
each crate's Cargo.toml to depend on corvus-traits if not already, adjust any
module paths or re-exports as needed, and run a build to fix any breakages
(tests/type changes) caused by the moved type.

In `@clients/agent-runtime/crates/corvus-observability/src/lib.rs`:
- Line 102: The current None branch returning Err(anyhow!("unknown observer
'{name}'")) in the observer_availability handling is defensive but unreachable
because resolve_observer_key(...) already guaranteed a canonical key; replace
that Err branch with a panic for violated invariants (e.g., use unreachable!()
or panic!("invariant: observer_availability returned None for resolved key
{name}")) so the code fails loudly on internal errors; update the code path
around resolve_observer_key and observer_availability to use unreachable!() (or
expect/panic with a clear message) instead of returning an Err to reflect the
invariant.

In `@clients/agent-runtime/crates/corvus-providers/src/registry.rs`:
- Around line 318-327: Add unit tests that assert regional aliases map to their
canonical provider keys by extending the existing tests module; specifically, in
the #[cfg(test)] mod tests where resolve_provider_key is exercised, add
assertions for regional/alternate aliases such as
assert_eq!(resolve_provider_key("kimi"), Some("moonshot")) (and any other
regional aliases from the alias lists) to ensure resolve_provider_key covers
those mappings as well.

In `@clients/agent-runtime/crates/corvus-tools/src/registry.rs`:
- Around line 17-214: Add a unit test that enforces case-insensitive uniqueness
across the registry by iterating the TOOLS slice and collecting lowercased
values of every ToolDescriptor.key and each alias in ToolDescriptor.aliases; the
test should fail if any lowercased string is seen more than once (detecting
collisions where a new entry would shadow an existing one under first-match
semantics). Place the test alongside the registry module tests, referencing
TOOLS and ToolDescriptor, and include clear failure messages indicating the
colliding key/alias and the providers involved.
- Around line 17-214: The evaluate_tool_policy() and
evaluate_tool_policy_for_origin() helpers are dead and the selection path in
select_tool() doesn't enforce policy; remove those unused functions (policy.rs
evaluate_tool_policy*/) or move their logic into the selection flow, and add a
call from select_tool() to the centralized policy check (use the same policy
API/name or inline the logic) before returning a ToolFactorySelection so denied
tools fail selection; ensure select_tool() queries the tool's descriptor (e.g.,
key and compiled flag on ToolDescriptor) and rejects high-risk tools (shell,
file_write, cron_*, etc.) when the policy denies them, returning an error
instead of a successful ToolFactorySelection.

In `@clients/agent-runtime/src/agent/agent.rs`:
- Around line 3155-3165: The test compares agent.memory.name() to the raw config
string which may be an alias; compute the canonical backend key via
resolve_memory_backend_key(&config.memory.backend) (or otherwise normalize the
config.memory.backend) and use that canonical key in the assertion instead of
the raw config value so that full_runtime_starts_without_manifest asserts
against the same normalized name produced by create_memory/Agent::from_config.

In `@clients/agent-runtime/src/bootstrap/composed.rs`:
- Around line 49-65: The code currently uses plan.observers.first() and thus
ignores additional enabled observers; either reject multi-observer plans or
materialize all of them. Fix by changing the logic around plan.observers to
handle multiple entries: either validate and error if plan.observers.len() > 1
(returning a clear error when more than one observer is present) or iterate over
plan.observers and merge/apply each observer's key and config into
config.observability (e.g., collect keys or set multiple endpoints/names as the
design requires), referencing plan.observers, observer.key, observer.config, and
the otel keys ("otel_endpoint", "otel_service_name") so no observers beyond the
first are silently dropped.
- Around line 66-73: The match on plan.security.key that sets
config.security.sandbox.backend must not silently map unknown keys to
SandboxBackend::Auto; instead change the wildcard arm to return an explicit
error (or propagate a Result) so boot fails on unmapped backends, or look up
plan.security.key in the authoritative registry mapping and use that mapping
only if present; update the code around config.security.sandbox.backend
assignment (the match on plan.security.key and the SandboxBackend enum handling)
to either return Err with a clear message including the unknown key or use the
registry lookup function before assigning, so no validated-but-unrecognized
backend can be downgraded to SandboxBackend::Auto.
- Around line 117-140: The code currently builds the full set of tools via
all_tools_with_runtime(...) and then filters with selected_tool_keys, which
materializes unselected tools and can cause side effects; modify the
factory/registry so selection happens before instantiation (e.g., add a
parameter to all_tools_with_runtime or create a new factory method like
create_selected_tools_with_runtime(selected_keys: &[String], ...) that accepts
plan.tools or selected_tool_keys and only constructs tools whose keys are
requested), update the call site in composed.rs to pass the selected keys
(plan.tools) into that factory instead of building all_tools and filtering, and
remove the post-construction filter to avoid unnecessary allocations, clones,
and side effects from unselected tool construction.

In `@clients/agent-runtime/src/channels/mod.rs`:
- Around line 2755-2764: is_supported_channel currently uses
corvus_channels::resolve_channel_key while build_channel searches the local
CHANNEL_REGISTRY, causing supported names (e.g., "stdio", "webhook") to be
reported but not constructible; change both functions to use
corvus_channels::select_channel() so canonicalization and construction are
aligned: update is_supported_channel to return whether
select_channel(channel_name) yields Some, and update build_channel to call
corvus_channels::select_channel(channel_name).and_then(|selected|
(selected.build)(config)) (or map the selected entry into an Arc<dyn Channel>)
instead of using CHANNEL_REGISTRY/resolve_channel_key so both discovery and
construction use the same registry resolution.

In `@clients/agent-runtime/src/composer.rs`:
- Around line 86-98: handle_run_command_with_config currently composes an Agent
via agent_from_plan and then returns success without running it, breaking the
"agent run" CLI contract; update this function to either (A) hand the composed
agent to the real runtime invocation path (e.g., call the runtime runner or
dispatcher used elsewhere with the produced _agent from
crate::bootstrap::composed::agent_from_plan) so the agent actually runs, or (B)
if runtime wiring doesn't exist yet, replace the silent success with an explicit
error return (anyhow::anyhow) stating that running composed agents is
unsupported and referencing handle_run_command_with_config and agent_from_plan
so callers see the contract is intentionally unimplemented; ensure you remove
the println-only success path and return a proper Result reflecting one of these
two choices.

In `@clients/agent-runtime/src/security/detect.rs`:
- Around line 14-31: The code is needlessly round-tripping
config.sandbox.backend through corvus_security::resolve_sandbox_key and then
mapping unknown strings to SandboxBackend::Auto, which can silently weaken
security; remove the re-resolution and use the typed config value directly
(i.e., stop calling corvus_security::resolve_sandbox_key and the
resolved_backend -> backend match) or, if you must accept registry keys,
validate the resolved string and return an explicit error (not
SandboxBackend::Auto) on any unrecognized value. Update the logic around the
backend_name / resolved_backend variables and the match that produces backend
(refer to config.sandbox.backend, backend_name,
corvus_security::resolve_sandbox_key, and the backend match) so that unknown
registry entries cause a fail-fast error rather than defaulting to Auto.

In `@clients/web/apps/dashboard/scripts/run-coverage.mjs`:
- Around line 45-56: The spawned child process created by spawn(pnpmCommand,
vitestArgs) lacks an 'error' event handler, so add child.on("error", (err) => {
console.error("Failed to spawn pnpm:", err); process.exit(1); }) (or use your
logger) to surface spawn failures and exit with a non‑zero code; attach this
handler alongside the existing child.on("exit", ...) (and ensure it's registered
immediately after creating child) so CI doesn't hang or fail silently when pnpm
cannot be started.
- Around line 26-27: The mapping using URL.pathname and passing a URL as cwd
breaks on Windows; replace uses of fileUrl.pathname and rootDir.pathname with
fileURLToPath(fileUrl) and fileURLToPath(rootDir) respectively (update the .map
that calls relative(...) to convert each fileUrl via fileURLToPath before
calling relative). Also add proper spawn error handling for the spawned process
(the variable returned by spawn) by listening for its 'error' event and handling
non-zero exit codes so the script doesn't crash on unhandled spawn errors;
update the spawn call site to attach child.on('error', ...) and check
child.on('exit' or 'close') to reject/exit on failure.

In `@clients/web/apps/dashboard/src/App.spec.ts`:
- Around line 676-681: Add a short inline comment above the await new
Promise((resolve) => globalThis.requestAnimationFrame(resolve)); explaining that
requestAnimationFrame is required to wait for the browser's focus restoration
timing (so focus returns to openButton.element) after DOM updates and that a
plain nextTick() does not guarantee the focus timing; place this comment near
the calls to nextTick and requestAnimationFrame so maintainers reading the test
around wrapper.find('[data-testid="session-detail"]') and openButton.element
understand why both waits are necessary.

In `@clients/web/apps/dashboard/src/App.vue`:
- Around line 257-258: The hard-coded accessibility and helper strings need to
be localized: replace the literal "Skip to main content" text in the skip-link
anchor (and the two auth helper paragraphs referenced elsewhere) with vue-i18n
keys (e.g. use {{$t('dashboard.skipToMainContent')}} or v-t directive) and add
corresponding keys to the i18n messages; ensure the focusMainContent method and
mainContentRef remain unchanged but now use the localized label for
screen-readers and include matching entries in the translation files for all
supported locales so the skip link and auth helper paragraphs are routed through
the existing i18n system.

In `@clients/web/apps/dashboard/src/components/chat/ChatWorkspace.spec.ts`:
- Around line 134-145: The test triggers the start button without mocking the
session-list fetch, causing an unmocked network call; before calling
startButton?.trigger("click") in the tests that use mountReadyWorkspace() (the
one asserting aria-describedby and the later test at 231+), add the same
fetchMock.mockResolvedValue(...) setup used in the other test that comments
"Mock the session list fetch that happens when session becomes ready" so the
session-list request is intercepted; ensure you place the
fetchMock.mockResolvedValue(...) call immediately before invoking
startButton?.trigger("click") so mountReadyWorkspace()/start session code uses
the mocked response.

In `@clients/web/apps/dashboard/src/components/config/BrowserSettings.vue`:
- Around line 82-84: The helper text in BrowserSettings.vue (element id
"browser-computer-use-api-key-help") is hardcoded in English; replace the
literal string with a call to the i18n translator (e.g.
$t('browser.useApiKeyHelp') or a suitably named key) and add that key with the
English copy to the appropriate locale file so the label uses localization like
the adjacent labels.

In `@clients/web/apps/dashboard/src/components/config/ComposioSettings.vue`:
- Around line 101-103: The helper paragraph with id "composio-api-key-help" in
ComposioSettings.vue is hardcoded in English; replace the literal string with an
i18n lookup (e.g., use $t or the component's i18n/composables) and add a new
translation key (e.g., composio.apiKeyHelp) to the locale files for all
languages. Update the template to call the i18n function (referencing the
"composio-api-key-help" element) and ensure the new key is present in the
en.json and other locale files so the text is localized instead of hardcoded.

In `@clients/web/apps/dashboard/src/components/config/MemorySettings.vue`:
- Around line 114-116: The paragraph with id "memory-cerebro-auth-token-help" in
MemorySettings.vue is hardcoded in English; replace it with a localized string
using the project's i18n system (e.g., use $t('memory.cerebroAuthTokenHelp') or
the <i18n> block) and add the new key "memory.cerebroAuthTokenHelp" to the
appropriate locale files with the English copy and translations; update any unit
tests or story snapshots that reference the hardcoded text if necessary.

In `@clients/web/apps/dashboard/src/components/config/WebhookSettings.vue`:
- Around line 80-82: The paragraph with id "webhook-error-summary-title" in
WebhookSettings.vue currently contains a hardcoded English string; replace the
literal text with a localized lookup using this.$t(...) (or $t(...) in the
template) and a new i18n key (e.g. "webhook.errorSummaryTitle") to match the
project's pattern, then add that key and its English value ("Please fix the
following error before saving.") to the relevant locale file(s); update any
tests or snapshots if necessary to reflect the new localized output.
- Around line 136-138: Replace the hardcoded helper text in the WebhookSettings
template with a localized string using $t(): locate the <p
id="webhook-secret-help" class="helper"> element in WebhookSettings.vue and
change its content to call $t('...') (add an appropriate key like
'webhook.secretHelp') and ensure you add that key and translated value to the
component's i18n resource file (or global translations) so the helper message is
localized.

In `@clients/web/apps/dashboard/src/components/config/WebSearchSettings.vue`:
- Around line 150-152: Replace the hardcoded helper text in the
WebSearchSettings.vue component (the <p> with id
"web-search-brave-api-key-help") with a call to the i18n translation function
(e.g., $t('webSearch.braveApiKeyHelp')) and add the corresponding key
"webSearch.braveApiKeyHelp" to your locale files (for each supported language)
with the existing copy as the value; ensure the component imports/uses the i18n
instance if needed so the helper renders the localized string.

In `@clients/web/apps/dashboard/src/components/sessions/SessionList.vue`:
- Around line 259-263: There are duplicate .select-btn CSS rule blocks causing
the padding value to be silently overridden; locate both .select-btn rule sets
and merge them into a single declaration (keep min-height: 32px, min-width: 32px
and the intended padding value) so only one .select-btn rule exists and remove
the redundant block to prevent CSS drift.

In `@clients/web/apps/dashboard/src/test/runAxe.ts`:
- Around line 23-29: The current call to axe.run spreads ...options after
setting rules so an options.rules can overwrite the merged rules and re-enable
"color-contrast"; fix by building an explicit merged rules object and pass it
into axe.run after spreading options (or ensure rules is set last). Concretely,
create a mergedRules object that starts with { "color-contrast": { enabled:
false } } and then deep-merge in options.rules (merging per-rule config objects,
not replacing the whole rules map), e.g. via a small helper or lodash.merge, and
then call axe.run(context, { ...options, rules: mergedRules }); reference:
axe.run, options.rules, and the "color-contrast" rule.

In `@clients/web/apps/dashboard/vite.config.ts`:
- Around line 23-27: The Vite config's test block uses Vitest options but
defineConfig is imported from "vite", so TypeScript won't validate
Vitest-specific settings; update the import to pull defineConfig (or
defineConfig as typed) from "vitest/config" instead of "vite" so the `test`
block (the test object with environment/include/exclude) is type-checked by
Vitest types and your IDE/TS will surface incorrect options for the test config.

In `@clients/web/apps/docs/src/content/docs/es/guides/customization.md`:
- Line 40: Replace the ungrammatical phrase "plataforma agénticas" in the
sentence "Corvus es una plataforma agénticas con estos componentes principales:"
with a singular, correct term; e.g., change it to "Corvus es una plataforma
agnóstica con estos componentes principales:" so the ES guide reads naturally
and matches user-facing docs parity expectations.

In `@clients/web/apps/docs/src/content/docs/guides/configuration.md`:
- Around line 151-154: The three bullet points that all begin with "MCP" (the
lines "MCP tools are namespaced as `mcp.<server>.<tool>`.", "MCP calls are
deny-by-default in supervised flows.", and "If one MCP server fails, healthy
servers still register.") should be rephrased to avoid repetition and improve
readability; change them to varied constructions such as starting the first with
"Tools…" (e.g., "Tools are namespaced as `mcp.<server>.<tool>`."), the second
with "Calls…" (e.g., "Calls are deny-by-default in supervised flows."), and the
third with "If a server fails…" (e.g., "If a server fails, healthy servers still
register."), preserving the original meaning and code formatting for the
namespaced example.

In `@clients/web/apps/docs/src/content/docs/guides/customization.md`:
- Around line 38-50: Update the "Current Architecture" section to include the
new capability composition layer (composer/registry) that centralizes where
providers, tools, memory, security, and observability are composed and
customized; explicitly mention the composer/registry surfaces and how they
relate to Rust Agent Runtime (`clients/agent-runtime`), Kotlin Multiplatform
Clients (`clients/composeApp`, `modules/agent-core-kmp`), Web Applications
(`clients/web`), and Cerebro Memory Service (`modules/cerebro`), and then mirror
the same addition in the Spanish `es/` file to keep EN/ES parity (or note
translation pending) per the markdown guidelines.

In
`@openspec/changes/archive/2026-04-12-capability-based-agent-composition/design.md`:
- Line 752: Change the compound modifier "Per crate tests asserting compiled
descriptors match expected canonical names and aliases." to use a hyphen:
"Per-crate tests asserting compiled descriptors match expected canonical names
and aliases." Update the table cell text (the string containing "Per crate tests
asserting compiled descriptors...") so the modifier is hyphenated consistently.

In
`@openspec/changes/archive/2026-04-12-capability-based-agent-composition/exploration.md`:
- Around line 28-36: Update the "What is missing" section to mark it as a
pre-implementation snapshot by adding an explicit qualifier such as "Initial
baseline at exploration time" (or change each bullet to "now addressed" where
applicable), and mention the specific symbols referenced (corvus-composer,
AgentBuilder, composer CLI paths, hardcoded capability lists, manifest shape
mismatch with PRD v1, corvus-observability crate, and root runtime factories
owning provider/channel/tool/memory/observer/sandbox creation) so readers
understand these items reflect the exploration baseline rather than current
state.

In
`@openspec/changes/archive/2026-04-12-capability-based-agent-composition/verify-report.md`:
- Around line 1-115: The report violates markdownlint rules: change the leading
"## Verification Report" to a top-level heading ("# Verification Report") to
satisfy MD041, and add/ensure blank lines before and after every heading and
before tables and fenced code blocks to satisfy MD022/MD058; specifically update
the "Verification Report" heading, the subsequent section headings (e.g.,
"Completeness", "Build & Tests Execution", "Spec Compliance Matrix",
"Correctness (Static — Structural Evidence)", "Coherence (Design)"), the tables
(the metrics and compliance matrices), and the fenced code blocks so each
heading has a preceding and following blank line and each table/fenced block is
separated by blank lines from surrounding text.
- Around line 19-56: The verification report omits Clippy status under the
"Build & Tests Execution" section; update verify-report.md to either run and
record the clippy check result (run `cargo clippy --all-targets -- -D warnings`
and include the command and pass/fail output) or explicitly document why clippy
was skipped (e.g., long-running CI, platform constraints) with that rationale;
ensure the new entry is placed alongside the existing "Formatting" and "Tests"
lines and clearly labeled (e.g., "Clippy: ✅ Passed" or "Clippy: ➖ Skipped —
<rationale>") so readers can verify adherence to the
clients/agent-runtime/**/*.rs validation guidance.

In `@openspec/specs/capability-architecture/spec.md`:
- Around line 426-445: The spec contains a contradiction between the "Phased
Roadmap Constraints for Later Adoption" composition-MVP (multi-family, boot-time
composition) and the later "M2 Tool-Family Descriptive Registry" requirements
which label the registry as tool-only and non-executing; update the M2 section
to align with the composition-MVP by removing or revising the
tool-only/non-executing language in the "M2 Tool-Family Descriptive Registry"
requirements so the registry supports multi-family real registry and factory
surfaces (provider, channel, tool, memory, observer, security) or explicitly
mark M2 as deprecated/transitioning, ensuring references to manifest-driven
validation and boot-time composition remain consistent with the composition-MVP
text.

---

Outside diff comments:
In @.github/workflows/_publish.yml:
- Around line 501-507: The npm jobs that read needs.publish.outputs.npm_dist_tag
must declare publish as a direct dependency; update each npm job's needs (e.g.,
add "publish" to the needs array for the publish-npm-platforms job and the other
npm jobs that reference needs.publish.outputs.npm_dist_tag) so they directly
depend on the publish job and can access its outputs.

In @.github/workflows/README.md:
- Around line 697-710: The workflow dependency diagram and caller list are
missing release-please-beta.yml; update the block that currently shows
"publish-release.yml" and "publish-snapshot.yml" -> "_publish.yml" to include
release-please-beta.yml as another caller of _publish.yml, and add
release-please-beta.yml to the prose list of Other workflows that call
dallay/common-actions so the README's dependency diagram and description
(references: publish-release.yml, publish-snapshot.yml, _publish.yml,
release-please-beta.yml) are consistent.

In `@clients/web/apps/dashboard/src/components/memory/MemoryList.spec.ts`:
- Around line 140-238: Add an afterEach teardown that unmounts/destroys the
mounted wrapper and clears DOM focus to prevent leakage between tests: ensure
any Wrapper returned by mountMemoryList() (the local variable wrapper in tests)
is cleaned up by calling wrapper.unmount() or wrapper.destroy() (depending on
your Vue Test Utils version) and reset document.activeElement (e.g., blur) after
each test; place this in an afterEach hook in MemoryList.spec.ts so all tests
that use mountMemoryList(), mockMemoryResponse, and assert
document.activeElement run with a clean DOM.

In `@clients/web/apps/docs/src/content/docs/es/guides/configuration.md`:
- Around line 11-228: This Spanish doc is a substantial user-facing rewrite and
needs EN/ES parity; either update the corresponding English doc within the same
release window or add an explicit “Pending EN sync” note at the top of this file
so readers and reviewers know the translation gap. Locate the Spanish page
(configuration.md) — specifically the top-level heading "Configuración del Agent
Runtime (`~/.corvus/config.toml`)" and the overall runtime/config sections — and
either mirror the changes into the English version or add a clear badge/notice
under the main title stating the EN translation is pending, referencing the
repository doc guideline for **/*.{md,mdx} parity.

In `@clients/web/apps/docs/src/content/docs/es/guides/release.md`:
- Around line 162-167: The runbook currently assumes the stable channel
(references to tag `vX.Y.Z`, GitHub Release and re-running `release.published`)
but must support beta flows (e.g., `vX.Y.Z-beta.N`); update the steps to either
branch by channel or accept a channel parameter and explicitly substitute
tag/release names—ensure items 1–6 mention both
`.release-please-manifest.json`/`.release-please-beta-manifest.json`,
`version.txt`, Gradle/Cargo/npm version files, the expected SHA, and conditional
logic for canonical tag (`vX.Y.Z`) vs beta tag (`vX.Y.Z-beta.N`), conditional
check for the corresponding GitHub Release, and for step 5 instruct to reset the
authority and re-run the matching publication (`release.published` for stable or
the beta publication job) depending on the channel; also add a short note in
step 6 to choose a new baseline rather than rewriting history for either
channel.

In `@clients/web/apps/docs/src/content/docs/guides/configuration.md`:
- Around line 13-209: Update the autonomy section in the docs: change the
default for require_approval_for_medium_risk to true (it currently shows false)
and expand the `[autonomy]` block to document the additional schema fields
allowed_commands, forbidden_paths, auto_approve, and always_ask (describe their
purpose and expected types/values). Locate the autonomy example under "Agent
Runtime Configuration (`~/.corvus/config.toml`)" and update the `[autonomy]`
snippet and surrounding explanatory text to reflect these keys and the correct
default for require_approval_for_medium_risk.

In `@clients/web/apps/docs/src/content/docs/guides/release.md`:
- Around line 162-167: The recovery checklist currently assumes stable releases
(references to vX.Y.Z, canonical GitHub Release, and rerunning the stable
release.published handoff) but is used for beta repair too; update the steps
around 3–5 in the document to branch by channel: explicitly handle stable vs
beta (e.g., keep vX.Y.Z, GitHub Release, and rerun stable release.published for
stable), and add the parallel beta flow that uses the beta tag format
vX.Y.Z-beta.N, checks for a beta GitHub Release/tag and reruns the beta publish
workflow (or the appropriate beta handoff) instead of release.published; ensure
mentions of .release-please-manifest.json, version.txt, and release.published
are parameterized or duplicated so operators clearly see which file/tag/workflow
applies to stable vs beta.
🪄 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: 62d56ccc-4769-4bf3-96ec-f62120cc15e0

📥 Commits

Reviewing files that changed from the base of the PR and between cd34820 and c96a47a.

⛔ Files ignored due to path filters (2)
  • clients/agent-runtime/Cargo.lock is excluded by !**/*.lock
  • clients/web/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (99)
  • .agents/journal/scribe-journal.md
  • .github/workflows/README.md
  • .github/workflows/_publish.yml
  • .github/workflows/dashboard-accessibility.yml
  • .github/workflows/publish-release.yml
  • .github/workflows/publish-snapshot.yml
  • .github/workflows/release-please-beta.yml
  • .github/workflows/release-please.yml
  • .gitignore
  • .release-please-beta-manifest.json
  • clients/agent-runtime/Cargo.toml
  • clients/agent-runtime/crates/corvus-channels/src/factory.rs
  • clients/agent-runtime/crates/corvus-channels/src/lib.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/Cargo.toml
  • clients/agent-runtime/crates/corvus-composer/src/lib.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/lib.rs
  • clients/agent-runtime/crates/corvus-memory/src/registry.rs
  • clients/agent-runtime/crates/corvus-observability/Cargo.toml
  • clients/agent-runtime/crates/corvus-observability/src/lib.rs
  • clients/agent-runtime/crates/corvus-providers/src/factory.rs
  • clients/agent-runtime/crates/corvus-providers/src/lib.rs
  • clients/agent-runtime/crates/corvus-providers/src/registry.rs
  • clients/agent-runtime/crates/corvus-security/src/factory.rs
  • clients/agent-runtime/crates/corvus-security/src/lib.rs
  • clients/agent-runtime/crates/corvus-security/src/registry.rs
  • clients/agent-runtime/crates/corvus-tools/src/factory.rs
  • clients/agent-runtime/crates/corvus-tools/src/lib.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/agent/agent.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/composer.rs
  • clients/agent-runtime/src/memory/mod.rs
  • clients/agent-runtime/src/observability/mod.rs
  • clients/agent-runtime/src/providers/mod.rs
  • clients/agent-runtime/src/security/detect.rs
  • clients/agent-runtime/src/security/policy.rs
  • clients/web/apps/dashboard/e2e/accessibility-smoke.spec.ts
  • clients/web/apps/dashboard/package.json
  • clients/web/apps/dashboard/scripts/run-coverage.mjs
  • clients/web/apps/dashboard/src/App.spec.ts
  • clients/web/apps/dashboard/src/App.vue
  • clients/web/apps/dashboard/src/components/chat/ChatWorkspace.spec.ts
  • clients/web/apps/dashboard/src/components/chat/ChatWorkspace.vue
  • clients/web/apps/dashboard/src/components/chat/SessionSidebar.spec.ts
  • clients/web/apps/dashboard/src/components/chat/SessionSidebar.vue
  • clients/web/apps/dashboard/src/components/chat/ToolApprovalCard.spec.ts
  • clients/web/apps/dashboard/src/components/chat/ToolApprovalCard.vue
  • clients/web/apps/dashboard/src/components/config/BrowserSettings.spec.ts
  • clients/web/apps/dashboard/src/components/config/BrowserSettings.vue
  • clients/web/apps/dashboard/src/components/config/ComposioSettings.spec.ts
  • clients/web/apps/dashboard/src/components/config/ComposioSettings.vue
  • clients/web/apps/dashboard/src/components/config/MemorySettings.spec.ts
  • clients/web/apps/dashboard/src/components/config/MemorySettings.vue
  • clients/web/apps/dashboard/src/components/config/WebSearchSettings.spec.ts
  • clients/web/apps/dashboard/src/components/config/WebSearchSettings.vue
  • clients/web/apps/dashboard/src/components/config/WebhookSettings.spec.ts
  • clients/web/apps/dashboard/src/components/config/WebhookSettings.vue
  • clients/web/apps/dashboard/src/components/memory/MemoryList.spec.ts
  • clients/web/apps/dashboard/src/components/memory/MemoryList.vue
  • clients/web/apps/dashboard/src/components/sessions/SessionDetail.spec.ts
  • clients/web/apps/dashboard/src/components/sessions/SessionDetail.vue
  • clients/web/apps/dashboard/src/components/sessions/SessionList.spec.ts
  • clients/web/apps/dashboard/src/components/sessions/SessionList.vue
  • clients/web/apps/dashboard/src/test/runAxe.ts
  • clients/web/apps/dashboard/vite.config.ts
  • clients/web/apps/docs/src/content/docs/clients/agent-runtime/ci-map.md
  • clients/web/apps/docs/src/content/docs/es/clients/agent-runtime/ci-map.md
  • clients/web/apps/docs/src/content/docs/es/guides/configuration.md
  • clients/web/apps/docs/src/content/docs/es/guides/customization.md
  • clients/web/apps/docs/src/content/docs/es/guides/features.md
  • clients/web/apps/docs/src/content/docs/es/guides/release.md
  • clients/web/apps/docs/src/content/docs/guides/configuration.md
  • clients/web/apps/docs/src/content/docs/guides/customization.md
  • clients/web/apps/docs/src/content/docs/guides/features.md
  • clients/web/apps/docs/src/content/docs/guides/release.md
  • clients/web/packages/locales/src/en.json
  • clients/web/packages/locales/src/es.json
  • clients/web/pnpm-workspace.yaml
  • openspec/changes/archive/2026-04-12-capability-based-agent-composition/archive-report.md
  • openspec/changes/archive/2026-04-12-capability-based-agent-composition/design.md
  • openspec/changes/archive/2026-04-12-capability-based-agent-composition/exploration.md
  • openspec/changes/archive/2026-04-12-capability-based-agent-composition/proposal.md
  • openspec/changes/archive/2026-04-12-capability-based-agent-composition/specs/agent-composer/spec.md
  • openspec/changes/archive/2026-04-12-capability-based-agent-composition/specs/capability-architecture/spec.md
  • openspec/changes/archive/2026-04-12-capability-based-agent-composition/state.yaml
  • openspec/changes/archive/2026-04-12-capability-based-agent-composition/tasks.md
  • openspec/changes/archive/2026-04-12-capability-based-agent-composition/verify-report.md
  • openspec/specs/agent-composer/spec.md
  • openspec/specs/capability-architecture/spec.md
  • release-please-beta-config.json
  • scripts/release-contract.test.mjs

Comment on lines +7 to +90
### Structure Assessment
- **Bilingual Parity:** ✅ Perfect. 53 files in English (root-level default), 53 files in Spanish (`es/`). 1:1 file mapping with identical directory structures.
- **Note:** The documentation does NOT use an `en/` directory. English docs live at the root of `docs/`, with `es/` as the translation overlay. This is consistent with Starlight's default locale behavior.

### CLI Reference (`guides/cli-reference.md`)
- **Accuracy:** ✅ High. All documented commands, subcommands, and flags verified against `clients/agent-runtime/src/main.rs` and `composer.rs`.
- **Verified commands:** onboard, agent, code, daemon, gateway, service, doctor, status, cron, models, providers, auth, skills, integrations, channel, hardware, peripheral, migrate, update, cost.
- **Dashboard activation codes:** DASH-001 through DASH-004, DASH-999 — all documented and verified in the onboard/dashboard code.
- **`make dev-up`**: Verified exists at Makefile:308.

### Cerebro CLI (`cerebro/cli-reference.md`)
- **Accuracy:** ✅ Fully implemented. Verified at `modules/cerebro/src/bin/cerebro.rs`. Two binaries: `cerebro` (full CLI) and `cerebro-serve` (lightweight server). Commands `serve` and `migrate import/validate` match docs exactly.

### Cerebro Configuration (`cerebro/configuration.md`)
- **Accuracy:** ✅ All config fields, env vars, storage modes, and TUI settings verified against `modules/cerebro/` source. `remote_surreal` correctly marked as "not yet implemented" in both docs and code.

### Architecture (`clients/agent-runtime/architecture.md`)
- **Accuracy:** ✅ High. All components verified as implemented:
- 22+ providers ✅ (including all regional variants and custom endpoints)
- 14 channels ✅ (CLI, Telegram, Discord, Slack, WhatsApp, Signal, iMessage, Matrix, DingTalk, QQ, Lark, Email, IRC, Mattermost)
- 32+ tools ✅
- 4 memory backends ✅ (sqlite, lucid, markdown, none)
- 5 observability backends ✅ (noop, log, prometheus, otel, multi)
- Security: Landlock ✅, Bubblewrap ✅, Firejail ✅ (verified in `security/firejail.rs`), Noop ✅
- **Minor note:** Docs mention "Firejail" in sandboxing section — this IS implemented (77 matches in code). The mermaid diagram says "landlock/firejail/bubblewrap" which is accurate.
- **Capability profiles** (full, code, lite) — verified in bootstrap code.

### Tools Reference (`clients/agent-runtime/tools/`)
- **Accuracy:** ✅ All tool category pages verified against actual tool implementations in `src/tools/`.
- **Security tiers** (Read-Only vs Action-Bearing) — verified against `security/policy.rs` risk classification.
- **MCP tool runtime** — verified in `tools/mcp/`, correctly documented as gated by `mcp.enabled`.

### Providers (`clients/agent-runtime/providers/index.mdx`)
- **Accuracy:** ✅ All 22+ providers verified. LM Studio confirmed at `providers/mod.rs:527`. Gemini OAuth and env vars (`GEMINI_API_KEY`, `GOOGLE_API_KEY`) verified in `providers/gemini.rs`. Regional providers (Moonshot, GLM, MiniMax, Qwen, Qianfan, Z.AI) all confirmed.

### Model Routing (`guides/model-routing.md`)
- **Accuracy:** ✅ `[[model_routes]]` and `[query_classification]` config structures verified against `config/schema.rs`. `corvus doctor` validation warnings verified in doctor module code. `allow_image_input` gate verified.

### Sandbox Isolation (`guides/runtime-sandbox-isolation.md`)
- **Accuracy:** ✅ All sandbox backends verified: landlock, firejail, bubblewrap, docker, none. `require = true` fail-closed behavior verified. Computer-use sidecar health check (`GET /v1/health`) verified. Audit log fields match implementation.

### Getting Started (`guides/getting-started.md`)
- **Accuracy:** ✅ Prerequisites match AGENTS.md. `make setup`, `make build`, `make run`, `make test` all verified in Makefile. Dashboard activation flow verified.

### SurrealDB Guide (`guides/surrealdb.md`)
- **Assessment:** This is a general operational guide for running SurrealDB with Docker Compose. Not specific to Corvus implementation but technically accurate for SurrealDB v3. No discrepancies found.

### Configuration Options (`guides/configuration.md`)
- **Assessment:** ⚠️ **PARTIAL COVERAGE**. This document focuses heavily on Gradle properties, version catalogs, and MCP configuration. It does NOT cover the full `config.toml` schema for the agent runtime (which is extensive — 30+ sections). The MCP section is accurate. **Recommendation:** This doc should be expanded or split to cover the agent runtime's full configuration surface.

### Customization (`guides/customization.md`)
- **Assessment:** ⚠️ **OUTDATED**. References `com.profiletailors` as the package namespace and mentions "This repository was created from a Gradle template." This is legacy template language. The "Platform Direction" section mentions "Kotlin + Spring Boot (WebFlux + Coroutines)" and "Neo4j for graph memory" which do NOT appear to be implemented in the current codebase. The actual architecture is Rust-based agent-runtime with Kotlin Multiplatform clients. **This section needs review and likely significant updates.**

### Features Checklist (`guides/features.md`)
- **Assessment:** ⚠️ **PARTIALLY OUTDATED**. Lists modules as `apps/composeApp`, `apps/androidApp`, etc. but the actual directory structure uses `clients/` prefix (e.g., `clients/composeApp`). Mentions "apps/agent-runtime-rust" but actual path is `clients/agent-runtime`. Missing several implemented features: cost tracking, update system, skills system, cron/scheduler, hardware peripherals, model routing, computer-use sidecar, tunnel providers. **Needs comprehensive update.**

### Development Procedures (`guides/development.md`)
- **Accuracy:** ✅ Makefile commands verified. `make setup`, `make run`, `make build`, `make test`, `make check`, `make format`, `make clean` all present. Documentation commands (`make docs-web-build`, etc.) verified against Makefile.

### Structure (`guides/structure.md`)
- **Accuracy:** ✅ Directory structure matches reality. `clients/`, `modules/`, `gradle/` all correctly described.

### Issues Summary

| Severity | File | Issue |
|----------|------|-------|
| 🔴 HIGH | `guides/customization.md` | References Spring Boot/Neo4j architecture not in codebase; legacy template language |
| 🔴 HIGH | `guides/features.md` | Wrong module paths (`apps/` vs `clients/`); missing 10+ major features |
| 🟡 MEDIUM | `guides/configuration.md` | Only covers Gradle/MCP; missing full agent runtime config reference |
| 🟢 LOW | `cerebro/` docs | All accurate, but lastReviewed date (2026-04-02) is recent — no action needed |

### Remediation (2026-04-12)

All three identified issues have been fixed:

1. **`guides/customization.md`** — ✅ Fixed. Removed Spring Boot/Neo4j references. Updated with current architecture (Rust agent runtime, KMP clients, Cerebro, web apps). Corrected VERSION to 3.0.0. Added `includeProjects` module registration guide. Both en/es synced.
2. **`guides/features.md`** — ✅ Fixed. Corrected all paths from `apps/` to `clients/`. Expanded from basic checklist to comprehensive coverage: 22+ providers, 14 channels, 32+ tools, memory backends, infrastructure, security, hardware, tunnels. Both en/es synced.
3. **`guides/configuration.md`** — ✅ Improved. Added full agent runtime config reference covering autonomy, security/sandbox, runtime, gateway, memory, agent profiles, model routing, multimodal/audio, scheduler, MCP, observability, cost, updates, skills, and env var overrides. Both en/es synced.

### Validation Results
- `make docs-check` — ✅ PASSED (astro check + biome + metadata validation: 0 errors, 0 warnings, 8 files validated)
- `make docs-build` — ✅ PASSED (80 pages built, search index generated, no broken links)

### Notes
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

Fix markdown heading spacing to satisfy MD022.

Several headings (for example Line 7, Line 11, Line 17, and others) are missing required surrounding blank lines. This will keep markdownlint noisy and can break consistent rendering in some processors.

Suggested pattern
 ### Structure Assessment
+
 - **Bilingual Parity:** ✅ Perfect. 53 files in English (root-level default), 53 files in Spanish (`es/`). 1:1 file mapping with identical directory structures.
🧰 Tools
🪛 LanguageTool

[style] ~80-~80: Consider using a different verb for a more formal wording.
Context: ... All three identified issues have been fixed: 1. guides/customization.md — ✅ ...

(FIX_RESOLVE)

🪛 markdownlint-cli2 (0.22.0)

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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)


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

(MD022, blanks-around-headings)

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

In @.agents/journal/scribe-journal.md around lines 7 - 90, Several Markdown
headings in scribe-journal.md (e.g., "Structure Assessment", "CLI Reference
(`guides/cli-reference.md`)", "Cerebro CLI (`cerebro/cli-reference.md`)" and
others) are missing required surrounding blank lines and trigger MD022; insert a
single blank line above and below each top-level and subheading so every heading
is separated from adjacent content (ensure lists and preceding paragraphs end
with a blank line before the heading and add a blank line after the heading
before the following paragraph or list). Locate headings by their exact text
(e.g., "Structure Assessment", "CLI Reference (`guides/cli-reference.md`)",
"Cerebro CLI (`cerebro/cli-reference.md`)", etc.) in scribe-journal.md and
normalize spacing consistently across the file to satisfy MD022.

Comment thread .github/workflows/README.md Outdated
Comment thread .github/workflows/release-please-beta.yml
Comment thread .gitignore Outdated
Comment thread clients/agent-runtime/crates/corvus-channels/src/registry.rs
| Layer | What to Test | Approach |
|-------|-------------|----------|
| Unit | Manifest v1 parsing and alias canonicalization | `corvus-composer` tests for PRD-shaped TOML, nested sections, and bad references. |
| Unit | Registry snapshot correctness | Per crate tests asserting compiled descriptors match expected canonical names and aliases. |
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.

🧹 Nitpick | 🔵 Trivial

Minor grammar nit.

Per static analysis: "Per crate" should be hyphenated as "Per-crate" when used as a compound modifier.

🧰 Tools
🪛 LanguageTool

[grammar] ~752-~752: Use a hyphen to join words.
Context: ...it | Registry snapshot correctness | Per crate tests asserting compiled descripto...

(QB_NEW_EN_HYPHEN)

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

In
`@openspec/changes/archive/2026-04-12-capability-based-agent-composition/design.md`
at line 752, Change the compound modifier "Per crate tests asserting compiled
descriptors match expected canonical names and aliases." to use a hyphen:
"Per-crate tests asserting compiled descriptors match expected canonical names
and aliases." Update the table cell text (the string containing "Per crate tests
asserting compiled descriptors...") so the modifier is hyphenated consistently.

Comment on lines +28 to +36
### What is missing

- `corvus-composer` does not yet compose a runnable agent through the real `AgentBuilder`.
- Composer CLI paths are placeholders and not production composition.
- Hardcoded capability lists in the composer are stale relative to the live runtime registrations.
- The manifest shape in `corvus-composer` does not match the PRD v1 contract.
- There is no extracted `corvus-observability` crate even though observers are required by the PRD target topology.
- Root runtime factories still own actual provider, channel, tool, memory, observer, and sandbox creation.

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

Clarify this section as a pre-implementation snapshot to avoid stale guidance.

The “What is missing” list reads as current-state assertions. Add an explicit “initial baseline at exploration time” qualifier (or update items to “now addressed”) so archive readers are not misled.

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

In
`@openspec/changes/archive/2026-04-12-capability-based-agent-composition/exploration.md`
around lines 28 - 36, Update the "What is missing" section to mark it as a
pre-implementation snapshot by adding an explicit qualifier such as "Initial
baseline at exploration time" (or change each bullet to "now addressed" where
applicable), and mention the specific symbols referenced (corvus-composer,
AgentBuilder, composer CLI paths, hardcoded capability lists, manifest shape
mismatch with PRD v1, corvus-observability crate, and root runtime factories
owning provider/channel/tool/memory/observer/sandbox creation) so readers
understand these items reflect the exploration baseline rather than current
state.

Comment on lines +1 to +115
## Verification Report

**Change**: capability-based-agent-composition
**Version**: N/A

---

### Completeness
| Metric | Value |
|--------|-------|
| Tasks total | 10 |
| Tasks complete | 10 |
| Tasks incomplete | 0 |

All tracked tasks in `tasks.md` are marked complete.

---

### Build & Tests Execution

**Build**: ➖ Skipped by request (`do NOT build`)

**Formatting**: ✅ Passed

Command run:

```bash
cargo fmt --all -- --check
```

Result: formatting check passed for the Rust workspace.

**Tests**: ✅ 26 passed / ❌ 0 failed / ⚠️ 0 skipped

Commands run:

```bash
cargo test -p corvus-composer
cargo test run_command_composes_agent_with_existing_builder_seam
cargo test composed_bootstrap_materializes_selected_components_only
cargo test composed_plan_preserves_channel_selection_for_future_runtime_wiring
cargo test composed_bootstrap_matches_full_runtime_for_lite_profile_path
cargo test full_runtime_starts_without_manifest
cargo test centralized_channel_factory_reuses_registry_for_named_lookup
cargo test factory_none_returns_noop
cargo test factory_none_uses_noop_memory
cargo test require_none_backend_returns_error
```

Observed results:
- `corvus-composer`: 8 passed
- targeted runtime/composer seam tests: 18 passed
- no failing or skipped targeted tests observed

**Coverage**: ➖ Not configured

---

### Spec Compliance Matrix
| Requirement | Scenario | Test | Result |
|-------------|----------|------|--------|
| Manifest v1 Schema Contract | Valid manifest uses PRD-aligned family sections | `crates/corvus-composer/src/lib.rs > valid_manifest_resolves_prd_v1_plan` | ✅ COMPLIANT |
| Manifest v1 Schema Contract | Default provider must be enabled | `crates/corvus-composer/src/lib.rs > default_provider_must_be_enabled` | ✅ COMPLIANT |
| Manifest v1 Schema Contract | Required family selections are enforced | `crates/corvus-composer/src/lib.rs > missing_required_family_selection_fails_before_composition` | ✅ COMPLIANT |
| Registry-Backed Semantic Validation | Validation uses live registries for all capability families | `crates/corvus-composer/src/lib.rs > valid_manifest_resolves_prd_v1_plan` + `registry_snapshot.rs` | ⚠️ PARTIAL |
| Registry-Backed Semantic Validation | Capability family mismatch is rejected deterministically | `crates/corvus-composer/src/lib.rs > family_mismatch_is_rejected_deterministically` | ✅ COMPLIANT |
| Registry-Backed Semantic Validation | Per-capability configuration is bound to selected capability identity | `crates/corvus-composer/src/lib.rs > config_for_unselected_capability_is_rejected` | ⚠️ PARTIAL |
| Availability and Unsupported Capability Failures | Unknown capability fails before composition | `crates/corvus-composer/src/lib.rs > unknown_capability_failure_is_distinct` | ✅ COMPLIANT |
| Availability and Unsupported Capability Failures | Uncompiled capability fails distinctly from unknown capability | `crates/corvus-composer/src/lib.rs > uncompiled_capability_failure_is_distinct` | ✅ COMPLIANT |
| Availability and Unsupported Capability Failures | Platform-unavailable capability fails distinctly from uncompiled capability | `crates/corvus-composer/src/lib.rs > platform_unavailable_failure_is_distinct` | ✅ COMPLIANT |
| Availability and Unsupported Capability Failures | Invalid capability configuration fails deterministically | `crates/corvus-composer/src/lib.rs > config_for_unselected_capability_is_rejected` | ⚠️ PARTIAL |
| Compose-to-AgentBuilder Behavior | Valid manifest composes into runtime builder inputs | `src/composer.rs > run_command_composes_agent_with_existing_builder_seam`; `src/bootstrap/composed.rs > composed_bootstrap_materializes_selected_components_only` | ✅ COMPLIANT |
| Compose-to-AgentBuilder Behavior | Only manifest-selected capabilities are composed for the MVP path | `src/bootstrap/composed.rs > composed_bootstrap_materializes_selected_components_only`; `src/bootstrap/composed.rs > composed_plan_preserves_channel_selection_for_future_runtime_wiring` | ⚠️ PARTIAL |
| Compose-to-AgentBuilder Behavior | Composer preserves runtime behavior of selected capabilities | `src/bootstrap/composed.rs > composed_bootstrap_matches_full_runtime_for_lite_profile_path` | ✅ COMPLIANT |
| Full-Runtime Backward Compatibility | Existing full runtime starts without a manifest | `src/agent/agent.rs > full_runtime_starts_without_manifest` | ✅ COMPLIANT |
| Full-Runtime Backward Compatibility | Manifest-driven subset does not remove full-capability mode | `src/composer.rs > run_command_composes_agent_with_existing_builder_seam`; `src/agent/agent.rs > full_runtime_starts_without_manifest` | ✅ COMPLIANT |
| Deferred Work Boundaries for the Composer MVP | Dynamic plugin loading is not required for manifest composition | static evidence: registry snapshot only uses compiled registries/factories | ⚠️ PARTIAL |
| Deferred Work Boundaries for the Composer MVP | Full runtime inversion remains deferred for the composer | static evidence: `bootstrap/composed.rs` feeds existing bootstrap/agent seams | ⚠️ PARTIAL |
| Composition MVP Multi-Family Registries | Each MVP capability family exposes a registry-backed composition surface | registry/factory modules exist for provider/channel/tool/memory/observability/security | ⚠️ PARTIAL |
| Composition MVP Multi-Family Registries | Migration may retain compatibility shims behind the registry boundary | `centralized_channel_factory_reuses_registry_for_named_lookup`; `factory_none_returns_noop`; `factory_none_uses_noop_memory`; `require_none_backend_returns_error` | ✅ COMPLIANT |
| Composition MVP Multi-Family Registries | Family boundaries remain explicit during composition | static evidence: family-specific crates/types and resolver families | ⚠️ PARTIAL |
| Registry Availability and Identity Semantics | Registry reports constructible compiled capability deterministically | positive-path composer/boot tests above | ⚠️ PARTIAL |
| Registry Availability and Identity Semantics | Registry distinguishes unknown from unavailable capability | `unknown_capability_failure_is_distinct`; `uncompiled_capability_failure_is_distinct`; `platform_unavailable_failure_is_distinct` | ✅ COMPLIANT |
| Registry Availability and Identity Semantics | Registry identity remains audit-visible across families | static evidence: stable keys/aliases preserved in registry records and validation errors | ⚠️ PARTIAL |
| Deterministic Validation Boundaries for Composition | Structural validation fails before registry lookup | `missing_required_family_selection_fails_before_composition`; `run_command_reports_validation_failures` | ✅ COMPLIANT |
| Deterministic Validation Boundaries for Composition | Availability validation fails before composition begins | `unknown_capability_failure_is_distinct`; `uncompiled_capability_failure_is_distinct`; `platform_unavailable_failure_is_distinct` | ✅ COMPLIANT |
| Deterministic Validation Boundaries for Composition | Platform validation remains a separate deterministic boundary | `platform_unavailable_failure_is_distinct` | ✅ COMPLIANT |
| Boot-Time Composition MVP Compatibility Baseline | Composed boot path targets the existing runtime builder baseline | `run_command_composes_agent_with_existing_builder_seam` | ✅ COMPLIANT |
| Boot-Time Composition MVP Compatibility Baseline | Full-runtime bootstrap remains valid | `full_runtime_starts_without_manifest` | ✅ COMPLIANT |
| Boot-Time Composition MVP Compatibility Baseline | Dynamic plugins remain deferred beyond the MVP | static evidence only | ⚠️ PARTIAL |
| Phased Roadmap Constraints for Later Adoption | Composition MVP combines only the bounded implementation slices | static scope evidence only | ⚠️ PARTIAL |
| Phased Roadmap Constraints for Later Adoption | Full runtime inversion remains deferred after the MVP | static scope evidence only | ⚠️ PARTIAL |
| M2 Anti-Scope and Deferred Work Constraints | Non-MVP runtime inversion work remains out of scope | static evidence only | ⚠️ PARTIAL |
| M2 Anti-Scope and Deferred Work Constraints | Generalized dependency orchestration remains deferred | static resolver remains deterministic and non-orchestrating | ⚠️ PARTIAL |

**Compliance summary**: 18/33 scenarios compliant, 15 partial, 0 untested

---

### Correctness (Static — Structural Evidence)
| Requirement | Status | Notes |
|------------|--------|-------|
| Manifest v1 schema | ✅ Implemented | `crates/corvus-composer/src/manifest.rs` matches the v1 family sections and config maps. |
| Registry-backed validation | ✅ Implemented | `registry_snapshot.rs` collects live family registries; `resolver.rs` validates through snapshot lookup instead of stale composer tables. |
| Distinct unknown/uncompiled/platform failure classes | ✅ Implemented | `ValidationError` plus family registries/factories preserve separate failure classes. |
| Compose to existing builder seam | ✅ Implemented | `src/bootstrap/composed.rs` materializes provider/memory/observer/security/tools and calls `Agent::from_bootstrap_with_provider`. |
| Full-runtime compatibility baseline | ✅ Implemented | Existing `bootstrap/mod.rs` and `Agent::from_config` baseline remain intact and additive composed path lives beside them. |
| MVP scope boundaries | ✅ Implemented | No dynamic plugin loader or generalized dependency solver was added. |
| Channel/runtime parity | ⚠️ Partial | Channel selections are resolved and preserved in the plan, but `bootstrap_from_plan` still does not materialize/start selected channels. |
| Behavioral parity proof | ✅ Implemented (targeted) | Lite-profile parity between composed bootstrap and full bootstrap is now covered by test. |

---

### Coherence (Design)
| Decision | Followed? | Notes |
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

Fix markdownlint failures in the archived report.

This file currently violates reported MD041/MD022/MD058 rules (top-level heading + missing blank lines around headings/tables). Please normalize formatting so CI docs lint stays green.

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

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

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


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

(MD022, blanks-around-headings)


[warning] 9-9: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)


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

(MD022, blanks-around-headings)


[warning] 60-60: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)


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

(MD022, blanks-around-headings)


[warning] 101-101: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)


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

(MD022, blanks-around-headings)


[warning] 115-115: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)

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

In
`@openspec/changes/archive/2026-04-12-capability-based-agent-composition/verify-report.md`
around lines 1 - 115, The report violates markdownlint rules: change the leading
"## Verification Report" to a top-level heading ("# Verification Report") to
satisfy MD041, and add/ensure blank lines before and after every heading and
before tables and fenced code blocks to satisfy MD022/MD058; specifically update
the "Verification Report" heading, the subsequent section headings (e.g.,
"Completeness", "Build & Tests Execution", "Spec Compliance Matrix",
"Correctness (Static — Structural Evidence)", "Coherence (Design)"), the tables
(the metrics and compliance matrices), and the fenced code blocks so each
heading has a preceding and following blank line and each table/fenced block is
separated by blank lines from surrounding text.

Comment on lines +19 to +56
### Build & Tests Execution

**Build**: ➖ Skipped by request (`do NOT build`)

**Formatting**: ✅ Passed

Command run:

```bash
cargo fmt --all -- --check
```

Result: formatting check passed for the Rust workspace.

**Tests**: ✅ 26 passed / ❌ 0 failed / ⚠️ 0 skipped

Commands run:

```bash
cargo test -p corvus-composer
cargo test run_command_composes_agent_with_existing_builder_seam
cargo test composed_bootstrap_materializes_selected_components_only
cargo test composed_plan_preserves_channel_selection_for_future_runtime_wiring
cargo test composed_bootstrap_matches_full_runtime_for_lite_profile_path
cargo test full_runtime_starts_without_manifest
cargo test centralized_channel_factory_reuses_registry_for_named_lookup
cargo test factory_none_returns_noop
cargo test factory_none_uses_noop_memory
cargo test require_none_backend_returns_error
```

Observed results:
- `corvus-composer`: 8 passed
- targeted runtime/composer seam tests: 18 passed
- no failing or skipped targeted tests observed

**Coverage**: ➖ Not configured

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 | 🟠 Major

Include cargo clippy status (or explicit skip rationale) in this verification section.

The report lists fmt/tests but omits clippy execution status, which leaves Rust validation incomplete for this change record.

As per coding guidelines 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”.

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

In
`@openspec/changes/archive/2026-04-12-capability-based-agent-composition/verify-report.md`
around lines 19 - 56, The verification report omits Clippy status under the
"Build & Tests Execution" section; update verify-report.md to either run and
record the clippy check result (run `cargo clippy --all-targets -- -D warnings`
and include the command and pass/fail output) or explicitly document why clippy
was skipped (e.g., long-running CI, platform constraints) with that rationale;
ensure the new entry is placed alongside the existing "Formatting" and "Tests"
lines and clearly labeled (e.g., "Clippy: ✅ Passed" or "Clippy: ➖ Skipped —
<rationale>") so readers can verify adherence to the
clients/agent-runtime/**/*.rs validation guidance.

Comment on lines +426 to +445
### Requirement: Phased Roadmap Constraints for Later Adoption

Follow-up adoption of the capability architecture MUST remain phased, but this change MAY deliver a
single explicitly scoped composition MVP that combines extraction completion, multi-family
registries, manifest v1 validation, and boot-time composition.

The composition MVP MUST remain bounded to:

- extraction completion for provider, channel, tool, memory, observer, and security families,
- real registry and factory surfaces for those families,
- deterministic manifest-driven validation,
- boot-time composition into the existing runtime builder baseline.

The composition MVP MUST NOT be interpreted as completing:

- dynamic plugin loading,
- generalized dependency-resolution orchestration,
- full runtime inversion,
- full removal of compatibility shims.

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 | 🟠 Major

Remove the now-conflicting M2 tool-only requirements.

These composition-MVP sections redefine the architecture around multi-family, boot-time composition, but the later M2 Tool-Family Descriptive Registry requirements still say the registry is tool-only and non-executing. Keeping both makes the active spec internally contradictory for implementers. As per coding guidelines, "Verify technical accuracy and that docs stay aligned with code changes".

Also applies to: 672-698

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

In `@openspec/specs/capability-architecture/spec.md` around lines 426 - 445, The
spec contains a contradiction between the "Phased Roadmap Constraints for Later
Adoption" composition-MVP (multi-family, boot-time composition) and the later
"M2 Tool-Family Descriptive Registry" requirements which label the registry as
tool-only and non-executing; update the M2 section to align with the
composition-MVP by removing or revising the tool-only/non-executing language in
the "M2 Tool-Family Descriptive Registry" requirements so the registry supports
multi-family real registry and factory surfaces (provider, channel, tool,
memory, observer, security) or explicitly mark M2 as deprecated/transitioning,
ensuring references to manifest-driven validation and boot-time composition
remain consistent with the composition-MVP text.

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.

Review continued from previous batch...

Comment thread clients/agent-runtime/src/bootstrap/composed.rs
Comment on lines +117 to +140
let all_tools = crate::tools::all_tools_with_runtime(
Arc::new(config.clone()),
&security,
Arc::clone(&runtime),
sandbox,
Arc::clone(&memory),
composio_key,
composio_entity_id,
&config.browser,
&config.http_request,
&config.workspace_dir,
&config.agents,
config.api_key.as_deref(),
config,
);
let selected_tool_keys: Vec<String> = plan.tools.iter().map(|tool| tool.key.clone()).collect();
let tools: Vec<Box<dyn Tool>> = all_tools
.into_iter()
.filter(|tool| {
selected_tool_keys
.iter()
.any(|selected| selected == tool.name())
})
.collect();
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 | 🟠 Major

Construct only manifest-selected tools.

all_tools_with_runtime(...) builds the full tool set and only then filters it. That defeats the composition boundary, adds avoidable startup work, and can trigger side effects for tools the manifest did not select. Move selection into the factory/registry path so unselected tools are never materialized. As per coding guidelines, "Avoid unnecessary allocations, clones, and blocking operations to maintain performance and efficiency".

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

In `@clients/agent-runtime/src/bootstrap/composed.rs` around lines 117 - 140, The
code currently builds the full set of tools via all_tools_with_runtime(...) and
then filters with selected_tool_keys, which materializes unselected tools and
can cause side effects; modify the factory/registry so selection happens before
instantiation (e.g., add a parameter to all_tools_with_runtime or create a new
factory method like create_selected_tools_with_runtime(selected_keys: &[String],
...) that accepts plan.tools or selected_tool_keys and only constructs tools
whose keys are requested), update the call site in composed.rs to pass the
selected keys (plan.tools) into that factory instead of building all_tools and
filtering, and remove the post-construction filter to avoid unnecessary
allocations, clones, and side effects from unselected tool construction.

yacosta738 and others added 2 commits April 12, 2026 19:09
- workflows: add branch guard to release-please-beta.yml
- gitignore: remove redundant .playwright-mcp/ entry
- corvus-channels: add comment for webhook deferred descriptor
- corvus-composer: fix platform_unavailable test to run on Linux
- corvus-composer: add canonicalization for default providers/channels
- corvus-observability: use unreachable!() for violated invariants
- corvus-providers: add regional alias tests (kimi, moonshot variants)
- corvus-tools: add case-insensitive uniqueness test for registry
- agent.rs: fix test to canonicalize memory backend key
- composed.rs: validate multi-observer and unknown security backend
- channels: align is_supported_channel and build_channel to use select_channel
- composer: return explicit error for unsupported 'agent run' feature
- security/detect: use typed config value directly, remove redundant resolution
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: 9

♻️ Duplicate comments (3)
clients/agent-runtime/src/channels/mod.rs (1)

2758-2771: ⚠️ Potential issue | 🟠 Major

stdio is still reported as supported but cannot be built.

select_channel("stdio") succeeds because the external registry marks it constructible, but CHANNEL_REGISTRY still has no "stdio" entry, so build_channel() returns None while is_supported_channel() returns true. That leaves discovery and construction out of sync for the CLI/stdio channel and can break composed runtime resolution. Add a local CliChannel builder entry or stop advertising "stdio" as constructible here.

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

In `@clients/agent-runtime/src/channels/mod.rs` around lines 2758 - 2771,
is_supported_channel currently returns true for "stdio" because select_channel
reports it constructible, but build_channel (which checks CHANNEL_REGISTRY) has
no "stdio" entry so construction fails; fix by keeping discovery and
construction in sync: either add a local CHANNEL_REGISTRY builder entry for the
CLI/stdio channel (e.g., an entry with key "stdio" whose build closure
constructs the CliChannel via the CliChannel builder used elsewhere) or ensure
select_channel does not advertise "stdio" as constructible; update the registry
or select_channel logic so select_channel("stdio"),
CHANNEL_REGISTRY.iter().find(...), and is_supported_channel all agree.
clients/agent-runtime/crates/corvus-composer/src/resolver.rs (1)

116-185: ⚠️ Potential issue | 🟠 Major

Canonicalize names before these subset checks and plan fields.

The registry lookup is alias-aware and case-insensitive, but these guards still compare raw manifest strings: default-vs-enabled checks, config-key validation, config lookup, and tool_restrictions subset validation. A manifest that uses a valid alias or different casing can still be rejected here, and default_channel / tool_restrictions stay non-canonical in the resolved plan. Normalize the selected/configured names through RegistrySnapshot first, then run the prechecks against canonical keys.

Also applies to: 187-222, 224-257

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

In `@clients/agent-runtime/crates/corvus-composer/src/resolver.rs` around lines
116 - 185, The prechecks are comparing raw manifest strings instead of canonical
registry keys; use RegistrySnapshot to canonicalize names (via
snapshot.find_in_family -> .map(|r| r.key)) before doing subset checks and
building the resolved plan: canonicalize default_provider/default_channel and
replace comparisons against manifest.providers.enabled /
manifest.channels.enabled with their canonical equivalents, map
manifest.tools.enabled, manifest.observability.enabled, manifest.memory.backend,
manifest.security.backend and manifest.tools.config keys through
snapshot.find_in_family before calling validate_selected_config_keys, and
similarly normalize any tool_restrictions and config lookups so all validations
and the plan store canonical keys returned by snapshot.find_in_family (use
CapabilityFamily to drive lookups).
clients/agent-runtime/src/bootstrap/composed.rs (1)

124-159: ⚠️ Potential issue | 🔴 Critical

Enforce the manifest’s effective tool allowlist before construction.

This path still builds the full tool universe and only filters by plan.tools, so two bad things happen: unselected tools are materialized anyway, and plan.tool_restrictions is ignored entirely. A composed manifest can validate with a tighter tool policy and then boot with extra executable tools. Construct only the effective allowlisted set, and do that before any tool initialization. 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" and "Avoid unnecessary allocations, clones, and blocking operations to maintain performance and efficiency".

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

In `@clients/agent-runtime/src/bootstrap/composed.rs` around lines 124 - 159, The
code currently calls all_tools_with_runtime(...) and then filters the resulting
vector, which causes all tools to be instantiated and ignores
plan.tool_restrictions; change the flow to compute the effective allowlist from
plan.tools and plan.tool_restrictions first (e.g., a Vec<String> of allowed tool
keys), then pass that allowlist into the tool construction path instead of
calling all_tools_with_runtime for the full universe — update calls involving
all_tools_with_runtime (and/or create a new function like
all_tools_with_runtime_for_keys) so only allowed tools are constructed, and
remove unnecessary clones of config when creating the allowlisted set to avoid
extra allocations and any pre-initialization of high-risk surfaces (refer to
SecurityPolicy, plan.tools, plan.tool_restrictions, all_tools_with_runtime, and
runtime/memory/sandbox parameters to locate where to change).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/README.md:
- Around line 309-310: The docs' workflow dependency diagram is missing the
newly referenced release-please-beta.yml; update the dependency diagram in
README.md so that release-please-beta.yml appears alongside publish-release.yml
and publish-snapshot.yml in the “Called by”/workflow dependencies section
(ensure any arrows, labels, or legend entries include release-please-beta.yml
and keep diagram formatting consistent with existing entries).

In @.github/workflows/release-please-beta.yml:
- Around line 57-60: The gh api call that sets release_id can fail due to GitHub
replication lag; wrap the gh api lookup (the command that assigns
release_id="$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${RELEASE_TAG}"
--jq '.id')") in a bounded retry loop with exponential/backoff sleeps (e.g., 4-5
attempts, increasing sleep between attempts) and exit non-zero if still
unresolved; once release_id is non-empty, echo it to "$GITHUB_OUTPUT" as before;
apply the same retry wrapper to the equivalent lookup in release-please.yml.

In `@clients/agent-runtime/crates/corvus-composer/src/resolver.rs`:
- Around line 239-271: The resolver is dropping manifest.memory.auto_save when
building ComposedRuntimePlan; update the ComposedRuntimePlan construction (the
memory field) to include the auto_save value from manifest.memory.auto_save
(e.g., add auto_save: manifest.memory.auto_save.clone() or .copied() as
appropriate) so that MemorySection.auto_save is forwarded into the resolved plan
(ensure the ComposedRuntimePlan/MemorySettings struct has an auto_save field if
needed and that bootstrap/composed.rs will read plan.memory.config/auto_save).

In `@clients/agent-runtime/crates/corvus-observability/src/lib.rs`:
- Around line 94-95: select_observer currently calls observer_availability(key)
again (causing a redundant registry resolution); instead derive availability
from the already-resolved descriptor/key and use that value to decide the
Constructible branch. Update the select_observer implementation to use the
availability field or a local availability computed when the descriptor was
first resolved (remove the extra observer_availability(key) call), then return
Ok(ObserverFactorySelection { key }) when that derived availability equals
CapabilityAvailability::Constructible.
- Around line 114-118: Add tests to cover normalization and error-path behavior
for observer resolution: extend the existing resolves_observer_aliases test (or
create new tests) to assert that resolve_observer_key handles trimming and
case-insensitivity (e.g., inputs with surrounding whitespace and different
letter cases resolve to the same keys) and add tests for select_observer to
verify it returns an appropriate error or panics on unknown input (exercise the
error branch when select_observer receives an unrecognized key). Reference
resolve_observer_key for normalization cases and select_observer for
unknown-input error behavior.

In `@clients/agent-runtime/crates/corvus-tools/src/registry.rs`:
- Around line 255-287: Change the HashMap to own the lowercased keys by using
std::collections::HashMap<String, &str> for seen, and when inserting move the
String (e.g. key_lower and alias_lower) rather than inserting &key_lower or
&alias_lower; keep the values as the static descriptor.key (&str) so insert
calls look like seen.insert(key_lower, descriptor.key) and
seen.insert(alias_lower, descriptor.key), and adjust variable names accordingly
where you check the returned existing owner.

In `@clients/agent-runtime/src/bootstrap/composed.rs`:
- Around line 15-21: Change config_from_plan to return Result<Config, E> instead
of Config (e.g., Result<Config, anyhow::Error> or your crate's Error type),
update its internal Err(...) returns to use the Result error variant, and adjust
both call sites to propagate errors with ?; specifically, modify the signature
of config_from_plan and replace the direct call in bootstrap_from_plan (where
config is assigned) with a ?-propagated call, and similarly update the other
call site that previously returned Err(...) so it now returns Err via the Result
and is propagated by callers (including build_bootstrap_and_provider) using ?.

In `@clients/agent-runtime/src/composer.rs`:
- Around line 299-307: The test
run_command_composes_agent_with_existing_builder_seam currently asserts that
handle_run_command_with_config(...) returns Ok, but
handle_run_command_with_config now returns an explicit CLI error for the `agent
run` case; update the test to assert the expected error instead of is_ok().
Specifically, change the assertion to check that
handle_run_command_with_config(...) returns Err and validate the error is the
CLI error you expect (either by matching the error variant/type or by checking
the error message/contains text) so the test asserts the explicit failure from
handle_run_command_with_config rather than success.
- Around line 86-100: The function handle_run_command_with_config currently
constructs a composed agent (via load_composer, composer.validate(), and
crate::bootstrap::composed::agent_from_plan) before returning the “unsupported
via CLI” Err; move the explicit unsupported-path Err so it is returned
immediately after validation (or even before validation) and remove the call to
agent_from_plan to avoid heavy initialization. Specifically, keep
load_composer/validate if you want manifest checks but return Err(...)
immediately afterward, or if no checks are needed simply return the Err before
calling composer.resolve_plan/agent_from_plan; do not change other call
sites—only reorder/remove the agent_from_plan invocation in
handle_run_command_with_config.

---

Duplicate comments:
In `@clients/agent-runtime/crates/corvus-composer/src/resolver.rs`:
- Around line 116-185: The prechecks are comparing raw manifest strings instead
of canonical registry keys; use RegistrySnapshot to canonicalize names (via
snapshot.find_in_family -> .map(|r| r.key)) before doing subset checks and
building the resolved plan: canonicalize default_provider/default_channel and
replace comparisons against manifest.providers.enabled /
manifest.channels.enabled with their canonical equivalents, map
manifest.tools.enabled, manifest.observability.enabled, manifest.memory.backend,
manifest.security.backend and manifest.tools.config keys through
snapshot.find_in_family before calling validate_selected_config_keys, and
similarly normalize any tool_restrictions and config lookups so all validations
and the plan store canonical keys returned by snapshot.find_in_family (use
CapabilityFamily to drive lookups).

In `@clients/agent-runtime/src/bootstrap/composed.rs`:
- Around line 124-159: The code currently calls all_tools_with_runtime(...) and
then filters the resulting vector, which causes all tools to be instantiated and
ignores plan.tool_restrictions; change the flow to compute the effective
allowlist from plan.tools and plan.tool_restrictions first (e.g., a Vec<String>
of allowed tool keys), then pass that allowlist into the tool construction path
instead of calling all_tools_with_runtime for the full universe — update calls
involving all_tools_with_runtime (and/or create a new function like
all_tools_with_runtime_for_keys) so only allowed tools are constructed, and
remove unnecessary clones of config when creating the allowlisted set to avoid
extra allocations and any pre-initialization of high-risk surfaces (refer to
SecurityPolicy, plan.tools, plan.tool_restrictions, all_tools_with_runtime, and
runtime/memory/sandbox parameters to locate where to change).

In `@clients/agent-runtime/src/channels/mod.rs`:
- Around line 2758-2771: is_supported_channel currently returns true for "stdio"
because select_channel reports it constructible, but build_channel (which checks
CHANNEL_REGISTRY) has no "stdio" entry so construction fails; fix by keeping
discovery and construction in sync: either add a local CHANNEL_REGISTRY builder
entry for the CLI/stdio channel (e.g., an entry with key "stdio" whose build
closure constructs the CliChannel via the CliChannel builder used elsewhere) or
ensure select_channel does not advertise "stdio" as constructible; update the
registry or select_channel logic so select_channel("stdio"),
CHANNEL_REGISTRY.iter().find(...), and is_supported_channel all agree.
🪄 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: 869932b3-bfc5-4098-8ae8-348cff739e38

📥 Commits

Reviewing files that changed from the base of the PR and between c96a47a and 95719d0.

⛔ Files ignored due to path filters (2)
  • clients/agent-runtime/Cargo.lock is excluded by !**/*.lock
  • modules/cerebro/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • .github/workflows/README.md
  • .github/workflows/release-please-beta.yml
  • .gitignore
  • CHANGELOG.md
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/crates/corvus-observability/src/lib.rs
  • clients/agent-runtime/crates/corvus-providers/src/registry.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/src/composer.rs
  • clients/agent-runtime/src/security/detect.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). (3)
  • GitHub Check: pr-checks
  • GitHub Check: sonar
  • GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (8)
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/security/detect.rs
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/security/detect.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/composer.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/security/detect.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/crates/corvus-observability/src/lib.rs
  • clients/agent-runtime/crates/corvus-providers/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/src/composer.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/security/detect.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/security/detect.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/crates/corvus-observability/src/lib.rs
  • clients/agent-runtime/crates/corvus-providers/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/src/composer.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/security/detect.rs
  • clients/agent-runtime/src/agent/agent.rs
  • CHANGELOG.md
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/crates/corvus-observability/src/lib.rs
  • clients/agent-runtime/crates/corvus-providers/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/src/composer.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:

  • CHANGELOG.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
🧠 Learnings (13)
📓 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/providers/**/*.rs : Implement `Provider` trait in `src/providers/` and register in `src/providers/mod.rs` factory when adding a new provider
📚 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/security/detect.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/src/composer.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/security/detect.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.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/security/detect.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/crates/corvus-observability/src/lib.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/src/composer.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/security/detect.rs
  • clients/agent-runtime/src/agent/agent.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/composer.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/agent/agent.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/crates/corvus-providers/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/src/composer.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/agent/agent.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/crates/corvus-providers/src/registry.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.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/agent/agent.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/composer.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/agent/agent.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/src/composer.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/agent/agent.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • 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/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/agent/agent.rs
  • clients/agent-runtime/src/channels/mod.rs
  • clients/agent-runtime/crates/corvus-channels/src/registry.rs
  • clients/agent-runtime/src/composer.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/agent/agent.rs
  • clients/agent-runtime/crates/corvus-composer/src/lib.rs
  • clients/agent-runtime/crates/corvus-tools/src/registry.rs
  • clients/agent-runtime/src/bootstrap/composed.rs
  • clients/agent-runtime/crates/corvus-composer/src/resolver.rs
  • clients/agent-runtime/src/composer.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/.github/**/*.{yml,yaml} : For workflow/template-only changes, ensure YAML/template syntax validity

Applied to files:

  • .github/workflows/release-please-beta.yml
🔇 Additional comments (7)
.gitignore (1)

115-116: Looks good: generated artifacts are correctly ignored.

Both entries are appropriate and reduce noisy diffs from local/test tooling outputs.

clients/agent-runtime/crates/corvus-observability/src/lib.rs (1)

89-92: Explicit unknown-observer error handling is the right contract.

Line 91 returns a hard error instead of silently falling back, which keeps capability selection deterministic.

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

CHANGELOG.md (1)

3-3: Compare-link updates look correct.

The updated compare ranges are consistent with the version progression shown in this file.

Also applies to: 252-252

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

14-16: Typed backend selection removes the old fail-open path.

Using the validated SandboxBackend enum directly preserves the explicit backend choice and avoids the old string round-trip fallback to Auto. Based on learnings: "Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable"

clients/agent-runtime/crates/corvus-channels/src/registry.rs (2)

116-123: Webhook availability is much clearer now.

The inline note matches channel_availability() returning Uncompiled, so callers are less likely to treat this as a runnable channel.


131-159: Resolution and availability flow looks consistent.

Trimming plus case-insensitive canonicalization before capability gating keeps lookup behavior stable across user-entered casing and aliases.

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

3156-3169: Good hardening of the bootstrap test.

Canonicalizing the configured memory backend before the assertion removes the alias/casing fragility in full_runtime_starts_without_manifest.

Comment thread .github/workflows/README.md
Comment thread .github/workflows/release-please-beta.yml
Comment thread clients/agent-runtime/crates/corvus-composer/src/resolver.rs
Comment thread clients/agent-runtime/crates/corvus-observability/src/lib.rs Outdated
Comment thread clients/agent-runtime/crates/corvus-observability/src/lib.rs
Comment thread clients/agent-runtime/crates/corvus-tools/src/registry.rs
Comment thread clients/agent-runtime/src/bootstrap/composed.rs
Comment thread clients/agent-runtime/src/composer.rs Outdated
Comment thread clients/agent-runtime/src/composer.rs
Lychee was incorrectly trying to check CSS @import statements as local
file:// URLs. These imports are resolved by build tools (Vite/Astro) at
build time, not by the filesystem.

Added exclude patterns for file:// URLs containing @corvus/shared,
tailwindcss, and @fontsource to prevent false-positive errors.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lychee.toml`:
- Around line 45-51: The exclude patterns in lychee.toml are unanchored
substrings ("@corvus/shared", "tailwindcss", "@fontsource" and "file://.*..."
entries) and will incorrectly match legitimate external links; update them to
anchored patterns so they only match intended package specifiers and file URLs —
replace "@corvus/shared", "tailwindcss", "@fontsource" with exact anchors like
"^@corvus/shared$", "^tailwindcss$", "^@fontsource$" and ensure the file-URL
entries are anchored at the start like "^file://.*@corvus/shared",
"^file://.*tailwindcss", "^file://.*@fontsource" so README/docs links aren’t
masked.
🪄 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: ade11f8d-c209-47bf-96b1-162aca371336

📥 Commits

Reviewing files that changed from the base of the PR and between 95719d0 and ffebece.

📒 Files selected for processing (1)
  • lychee.toml
📜 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 (1)
**/*

⚙️ 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:

  • lychee.toml

Comment thread lychee.toml
Comment on lines +45 to +51
"@corvus/shared",
"tailwindcss",
"@fontsource",
# File URLs from CSS @import statements (resolved by build tools, not lychee)
"file://.*@corvus/shared",
"file://.*tailwindcss",
"file://.*@fontsource",
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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify potential over-exclusion impact: find real external URLs that include these tokens.
# If matches are found, current unanchored patterns would hide them from lychee checks.
rg -nP 'https?://[^"'"'"' )]*(tailwindcss|@fontsource|corvus/shared)[^"'"'"' )]*'

Repository: dallay/corvus

Length of output: 787


🏁 Script executed:

# Check lychee.toml file structure and any documentation about exclude patterns
cat -n lychee.toml | head -60

Repository: dallay/corvus

Length of output: 2908


🏁 Script executed:

# Search for any lychee documentation or comments about how exclude patterns work
rg -i "exclude" lychee.toml -B2 -A2

Repository: dallay/corvus

Length of output: 603


🏁 Script executed:

# Check if there are any test files or documentation about lychee configuration
find . -type f -name "*.md" | xargs rg -l "lychee" | head -5

Repository: dallay/corvus

Length of output: 104


🏁 Script executed:

# Search for lychee documentation links or comments about pattern matching
rg "lycheeverse/lychee" lychee.toml

Repository: dallay/corvus

Length of output: 114


🏁 Script executed:

# Check if there are any GitHub workflow files that might show how lychee is called
cat .github/workflows/README.md | head -50

Repository: dallay/corvus

Length of output: 4952


🏁 Script executed:

# Look for any actual lychee invocation to understand how patterns are used
find .github/workflows -name "*.yml" -o -name "*.yaml" | xargs rg "lychee" -A3 -B1 | head -30

Repository: dallay/corvus

Length of output: 1968


Anchor exclude patterns to prevent masking legitimate documentation links

Lines 45–47 use unanchored patterns that will regex-match any URL containing these substrings. The repo contains legitimate external links like https://tailwindcss.com/docs/installation/using-vite (found in README.md and docs), which would be incorrectly excluded from validation and hidden from CI checks.

Proposed fix
-    "@corvus/shared",
-    "tailwindcss",
-    "@fontsource",
+    '^@corvus/shared(?:/|$)',
+    '^tailwindcss(?:/|$)',
+    '^@fontsource(?:-variable)?(?:/|$)',
     # File URLs from CSS `@import` statements (resolved by build tools, not lychee)
-    "file://.*@corvus/shared",
-    "file://.*tailwindcss",
-    "file://.*@fontsource",
+    '^file://.*@corvus/shared(?:/|$)',
+    '^file://.*tailwindcss(?:/|$)',
+    '^file://.*@fontsource(?:-variable)?(?:/|$)',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"@corvus/shared",
"tailwindcss",
"@fontsource",
# File URLs from CSS @import statements (resolved by build tools, not lychee)
"file://.*@corvus/shared",
"file://.*tailwindcss",
"file://.*@fontsource",
'^@corvus/shared(?:/|$)',
'^tailwindcss(?:/|$)',
'^@fontsource(?:-variable)?(?:/|$)',
# File URLs from CSS `@import` statements (resolved by build tools, not lychee)
'^file://.*@corvus/shared(?:/|$)',
'^file://.*tailwindcss(?:/|$)',
'^file://.*@fontsource(?:-variable)?(?:/|$)',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lychee.toml` around lines 45 - 51, The exclude patterns in lychee.toml are
unanchored substrings ("@corvus/shared", "tailwindcss", "@fontsource" and
"file://.*..." entries) and will incorrectly match legitimate external links;
update them to anchored patterns so they only match intended package specifiers
and file URLs — replace "@corvus/shared", "tailwindcss", "@fontsource" with
exact anchors like "^@corvus/shared$", "^tailwindcss$", "^@fontsource$" and
ensure the file-URL entries are anchored at the start like
"^file://.*@corvus/shared", "^file://.*tailwindcss", "^file://.*@fontsource" so
README/docs links aren’t masked.

…ess test

- Change HashMap<&str, &str> to HashMap<String, &str> to own the lowercased
  keys instead of borrowing from temporary strings
- Fix formatting in select_observer and build_channel
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 12, 2026

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 12, 2026

✅ Unit tests committed locally. Commit: 48881c2c1d60915676da04269f2b6050586df5bb

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot
77.4% Coverage on New Code (required ≥ 80%)
7.8% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@yacosta738 yacosta738 merged commit 69353fc into main Apr 12, 2026
15 of 17 checks passed
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.

1 participant