feat(agent-runtime): add slash command registry core#545
Conversation
…vice.rs issues - gateway/mod.rs: replace MockMemory with SqliteMemory in slash-session tests - canonical_outcome_early_response_intercepts_slash_session_commands - legacy_webhook_preview_intercepts_slash_session_commands - web_chat_stream_returns_deterministic_slash_session_sse_without_provider_execution - update assertions to expect 422 + session_command_failed error - session_commands/service.rs: - FakeMemory::get_session now looks up by session_id - build_resume_context adds truncation limits (2k per entry, 16k global) - visibility check uses get_session instead of paginated list - openspec/specs/sessions/spec.md: add trailing newline
Deploying corvus with
|
| Latest commit: |
4329d45
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c386ad04.corvus-42x.pages.dev |
| Branch Preview URL: | https://feature-dallay-539-slash-com.corvus-42x.pages.dev |
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 11 minutes and 16 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThis PR implements the core slash command registry architecture for Corvus, replacing hard-coded command dispatching with a validated, metadata-driven registry system. It introduces descriptor-based command metadata, refactors the parser to lexical parsing, implements registry storage with name/alias lookup and duplicate validation, adds a trait-based handler dispatch model, and integrates this across CLI, gateway, webhook, and channel ingress points while preserving fallthrough behavior for unknown slash-like input. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Justification: Substantial multi-file refactor touching critical ingress-path logic across four entry points (CLI, gateway HTTP/SSE, webhook, channels). Introduces trait-based dispatch, complex registry validation with duplicate detection, lexical parsing, and behavioral changes around error handling and session targeting. Heterogeneous changes across distinct modules require separate reasoning for each integration point. High density of logic changes and control-flow alterations warrant careful verification of fallthrough semantics and error propagation. Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Contributor ReportUser: @yacosta738
Contributor Report evaluates based on public GitHub activity. Analysis period: 2025-04-15 to 2026-04-15 |
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
clients/agent-runtime/src/gateway/mod.rs (1)
2213-2246:⚠️ Potential issue | 🟠 MajorAlign streaming slash-command semantics with
/webhook.Because the unconditional
upsert_sessionon Line 2180 still runs before this branch, a fresh/tldrover/web/chat/streamsucceeds against an auto-created session while/webhooknow returns422 session_command_failedbefore any tracking. That makes transport choice observable in command behavior and looks like a contract regression for the same slash command. Consider short-circuiting recognized slash commands before session upsert here as well, or explicitly documenting the divergence.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/agent-runtime/src/gateway/mod.rs` around lines 2213 - 2246, The branch handling crate::pre_execution::IngressDecision::SessionCommand is executed after an unconditional call to state.mem.upsert_session, which causes /web/chat/stream to auto-create sessions while /webhook returns session_command_failed; to fix, detect and short-circuit recognized slash commands before calling state.mem.upsert_session (or add a conditional skip of upsert_session when ingress_decision matches SessionCommand) so that SessionCommand handling (the block using update_session_activity, session_id, and result) runs without an earlier upsert creating differing transport behavior; update references to upsert_session, ingress_decision, and SessionCommand accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@clients/agent-runtime/src/session_commands/mod.rs`:
- Around line 6-16: Remove the temporary #[allow(unused_imports)] attributes
from the re-exports once downstream consumers stabilize: delete the attributes
applied to SessionCommandParser, the registry exports (default_registry,
SlashCommandRegistry) and the bulk types export (CommandContext,
RawSlashInvocation, SessionCommandError, SessionCommandResult,
SlashCommandArgumentShape, SlashCommandDescriptor, SlashCommandHandler,
SlashCommandRegistration, SlashCommandRequirements, SlashInvocation,
SlashRegistryError); keep the explicit pub use service::SessionCommandService
line as-is and ensure the module still compiles after removing those attributes.
In `@clients/agent-runtime/src/session_commands/parser.rs`:
- Around line 24-34: split_primary_target currently returns the entire trimmed
input as the second value instead of the arguments after the primary target;
update split_primary_target so after computing target_end and primary_target it
returns the post-target substring trimmed of leading whitespace. Concretely, set
remaining_args = if target_end == 0 { trimmed.to_string() } else {
trimmed[target_end..].trim_start().to_string() } and return (primary_target,
remaining_args) in the split_primary_target function.
In `@clients/agent-runtime/src/session_commands/registry.rs`:
- Around line 274-289: The validator currently allows "/" because it only checks
index 0; update validate_name to require at least one character after the
leading slash and enforce that the second character is an ASCII lowercase letter
(i.e. require name.len() >= 2 or check that chars().nth(1) exists and
is_ascii_lowercase()), while keeping the existing per-character rules for
subsequent chars, and continue returning Err(SlashRegistryError::InvalidName {
name: name.to_string() }) when the check fails.
- Around line 44-79: Reject a registration whose canonical name conflicts with
any existing alias and detect duplicate aliases inside the same descriptor:
first, before the alias loop, check if
self.by_alias.contains_key(registration.descriptor.canonical_name) and return an
AliasCollidesWithCanonical error using alias =
registration.descriptor.canonical_name and canonical_name = the existing
canonical owner (lookup self.registrations[*index].descriptor.canonical_name) to
show who owns that alias; then in the for alias in
registration.descriptor.aliases loop, validate_name(alias) as now but also
maintain a local HashSet (e.g., seen_aliases) to detect duplicate aliases inside
the same descriptor and return DuplicateAlias (with existing_canonical_name =
registration.descriptor.canonical_name.to_string()) when an alias repeats; keep
the existing checks against self.by_alias and self.by_canonical_name but ensure
the error payloads use the looked-up existing canonical name from
self.registrations when available.
In `@clients/agent-runtime/src/session_commands/service.rs`:
- Around line 455-466: The current logic trims `context` from the start when
`context.chars().count() > MAX_CONTEXT_LENGTH`, which discards the header
("Session {session_id} summary: {summary}"); change it to trim from the end
instead so the header is preserved: when `context` is too long, take the first
MAX_CONTEXT_LENGTH chars of `context` (e.g., via
`context.chars().take(MAX_CONTEXT_LENGTH)`), then ensure you don't cut mid-entry
by finding the last occurrence of "\n- " within that prefix and trimming the
prefix to that boundary (so only complete, older transcript entries are
dropped); keep using the `context` variable and `MAX_CONTEXT_LENGTH` and remove
the existing skip-from-start logic and the `find("\n- ")` adjustment that
realigns after cutting from the front.
- Around line 207-219: The second storage lookup is redundant—reuse the
already-fetched session variable (from the earlier get_session call stored in
session) to determine target_exists instead of calling self.memory.get_session
again; replace the await/map_err chain with a simple is_some() check on session
(or session.as_ref().is_some() depending on ownership) and keep returning
SessionCommandError::InvalidResumeTarget with session_id:
target_session_id.to_string() when false, preserving the existing error mapping
logic elsewhere.
In `@openspec/changes/archive/2026-04-15-slash-command-registry-core/proposal.md`:
- Line 77: Change the phrase "prompt side" to the hyphenated compound adjective
"prompt side-effects" in the proposal document: locate the text fragment "prompt
side" (appearing on the line containing "webhook, and channel-backed flows
continue to intercept slash commands before normal prompt side") and replace it
with "prompt side-effects"; also scan the same file for other occurrences of
"prompt side" to ensure consistent hyphenation across the doc.
In
`@openspec/changes/archive/2026-04-15-slash-command-registry-core/verify-report.md`:
- Line 1: The first heading "Verification Report" uses "##" but must be a
top-level H1; replace the existing "## Verification Report" with "# Verification
Report" so the document begins with an H1 per markdownlint MD041 rules.
---
Outside diff comments:
In `@clients/agent-runtime/src/gateway/mod.rs`:
- Around line 2213-2246: The branch handling
crate::pre_execution::IngressDecision::SessionCommand is executed after an
unconditional call to state.mem.upsert_session, which causes /web/chat/stream to
auto-create sessions while /webhook returns session_command_failed; to fix,
detect and short-circuit recognized slash commands before calling
state.mem.upsert_session (or add a conditional skip of upsert_session when
ingress_decision matches SessionCommand) so that SessionCommand handling (the
block using update_session_activity, session_id, and result) runs without an
earlier upsert creating differing transport behavior; update references to
upsert_session, ingress_decision, and SessionCommand accordingly.
🪄 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: def502fd-37c6-473b-b3ff-e39a974c8207
📒 Files selected for processing (20)
clients/agent-runtime/src/channels/mod.rsclients/agent-runtime/src/gateway/mod.rsclients/agent-runtime/src/gateway/webhook_dispatch.rsclients/agent-runtime/src/main.rsclients/agent-runtime/src/memory/sqlite.rsclients/agent-runtime/src/pre_execution/mod.rsclients/agent-runtime/src/session_commands/mod.rsclients/agent-runtime/src/session_commands/parser.rsclients/agent-runtime/src/session_commands/registry.rsclients/agent-runtime/src/session_commands/service.rsclients/agent-runtime/src/session_commands/types.rsopenspec/changes/archive/2026-04-15-slash-command-registry-core/design.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/exploration.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/proposal.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/specs/slash-command-registry/spec.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/state.yamlopenspec/changes/archive/2026-04-15-slash-command-registry-core/tasks.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/verify-report.mdopenspec/specs/sessions/spec.mdopenspec/specs/slash-command-registry/spec.md
📜 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). (1)
- GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (9)
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/memory/sqlite.rsclients/agent-runtime/src/gateway/webhook_dispatch.rsclients/agent-runtime/src/channels/mod.rsclients/agent-runtime/src/pre_execution/mod.rsclients/agent-runtime/src/main.rsclients/agent-runtime/src/session_commands/service.rsclients/agent-runtime/src/session_commands/parser.rsclients/agent-runtime/src/session_commands/mod.rsclients/agent-runtime/src/gateway/mod.rsclients/agent-runtime/src/session_commands/registry.rsclients/agent-runtime/src/session_commands/types.rs
clients/agent-runtime/**/*.rs
📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)
Run
cargo fmt --all -- --check,cargo clippy --all-targets -- -D warnings, andcargo testfor code validation, or document which checks were skipped and why
Files:
clients/agent-runtime/src/memory/sqlite.rsclients/agent-runtime/src/gateway/webhook_dispatch.rsclients/agent-runtime/src/channels/mod.rsclients/agent-runtime/src/pre_execution/mod.rsclients/agent-runtime/src/main.rsclients/agent-runtime/src/session_commands/service.rsclients/agent-runtime/src/session_commands/parser.rsclients/agent-runtime/src/session_commands/mod.rsclients/agent-runtime/src/gateway/mod.rsclients/agent-runtime/src/session_commands/registry.rsclients/agent-runtime/src/session_commands/types.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/memory/sqlite.rsclients/agent-runtime/src/gateway/webhook_dispatch.rsclients/agent-runtime/src/channels/mod.rsclients/agent-runtime/src/pre_execution/mod.rsclients/agent-runtime/src/main.rsclients/agent-runtime/src/session_commands/service.rsclients/agent-runtime/src/session_commands/parser.rsclients/agent-runtime/src/session_commands/mod.rsclients/agent-runtime/src/gateway/mod.rsclients/agent-runtime/src/session_commands/registry.rsclients/agent-runtime/src/session_commands/types.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/memory/sqlite.rsclients/agent-runtime/src/gateway/webhook_dispatch.rsopenspec/specs/sessions/spec.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/state.yamlclients/agent-runtime/src/channels/mod.rsclients/agent-runtime/src/pre_execution/mod.rsclients/agent-runtime/src/main.rsopenspec/changes/archive/2026-04-15-slash-command-registry-core/exploration.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/verify-report.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/tasks.mdclients/agent-runtime/src/session_commands/service.rsopenspec/changes/archive/2026-04-15-slash-command-registry-core/design.mdclients/agent-runtime/src/session_commands/parser.rsclients/agent-runtime/src/session_commands/mod.rsopenspec/changes/archive/2026-04-15-slash-command-registry-core/specs/slash-command-registry/spec.mdopenspec/specs/slash-command-registry/spec.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/proposal.mdclients/agent-runtime/src/gateway/mod.rsclients/agent-runtime/src/session_commands/registry.rsclients/agent-runtime/src/session_commands/types.rs
clients/agent-runtime/src/{security,gateway,tools}/**/*.rs
📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)
Treat
src/security/,src/gateway/,src/tools/as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks
Files:
clients/agent-runtime/src/gateway/webhook_dispatch.rsclients/agent-runtime/src/gateway/mod.rs
clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs
📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)
Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable
Files:
clients/agent-runtime/src/gateway/webhook_dispatch.rsclients/agent-runtime/src/gateway/mod.rs
**/*.{md,mdx}
⚙️ CodeRabbit configuration file
**/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes.
For user-facing docs, check EN/ES parity or explicitly note pending translation gaps.
Files:
openspec/specs/sessions/spec.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/exploration.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/verify-report.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/tasks.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/design.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/specs/slash-command-registry/spec.mdopenspec/specs/slash-command-registry/spec.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/proposal.md
clients/agent-runtime/src/channels/**/*.rs
📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)
Implement
Channeltrait insrc/channels/with consistentsend,listen, andhealth_checksemantics and cover auth/allowlist/health behavior with tests
Files:
clients/agent-runtime/src/channels/mod.rs
clients/agent-runtime/src/main.rs
📄 CodeRabbit inference engine (clients/agent-runtime/AGENTS.md)
clients/agent-runtime/src/main.rs: Preserve CLI contract unless change is intentional and documented; prefer explicit errors over silent fallback for unsupported critical paths
Keep startup path lean and avoid heavy initialization in command parsing flow
Files:
clients/agent-runtime/src/main.rs
🧠 Learnings (8)
📚 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/memory/sqlite.rsclients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/main.rs : 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/memory/sqlite.rsclients/agent-runtime/src/gateway/webhook_dispatch.rsclients/agent-runtime/src/channels/mod.rsclients/agent-runtime/src/pre_execution/mod.rsclients/agent-runtime/src/main.rsopenspec/changes/archive/2026-04-15-slash-command-registry-core/exploration.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/tasks.mdclients/agent-runtime/src/session_commands/service.rsopenspec/changes/archive/2026-04-15-slash-command-registry-core/design.mdclients/agent-runtime/src/session_commands/parser.rsclients/agent-runtime/src/session_commands/mod.rsclients/agent-runtime/src/gateway/mod.rsclients/agent-runtime/src/session_commands/registry.rsclients/agent-runtime/src/session_commands/types.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/channels/**/*.rs : Implement `Channel` trait in `src/channels/` with consistent `send`, `listen`, and `health_check` semantics and cover auth/allowlist/health behavior with tests
Applied to files:
clients/agent-runtime/src/channels/mod.rsclients/agent-runtime/src/main.rsclients/agent-runtime/src/gateway/mod.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/main.rs : Keep startup path lean and avoid heavy initialization in command parsing flow
Applied to files:
clients/agent-runtime/src/channels/mod.rsclients/agent-runtime/src/pre_execution/mod.rsclients/agent-runtime/src/main.rsopenspec/changes/archive/2026-04-15-slash-command-registry-core/tasks.mdclients/agent-runtime/src/session_commands/service.rsclients/agent-runtime/src/session_commands/parser.rsclients/agent-runtime/src/session_commands/mod.rsclients/agent-runtime/src/gateway/mod.rsclients/agent-runtime/src/session_commands/registry.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools,config}/**/*.rs : Do not silently weaken security policy or access constraints; keep default behavior secure-by-default with deny-by-default where applicable
Applied to files:
clients/agent-runtime/src/main.rsclients/agent-runtime/src/gateway/mod.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/**/*.rs : Run `cargo fmt --all -- --check`, `cargo clippy --all-targets -- -D warnings`, and `cargo test` for code validation, or document which checks were skipped and why
Applied to files:
clients/agent-runtime/src/main.rsopenspec/changes/archive/2026-04-15-slash-command-registry-core/verify-report.md
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/tools/**/*.rs : Implement `Tool` trait in `src/tools/` with strict parameter schema, validate and sanitize all inputs, and return structured `ToolResult` without panics in runtime path
Applied to files:
clients/agent-runtime/src/main.rs
📚 Learning: 2026-02-17T12:31:17.076Z
Learnt from: CR
Repo: dallay/corvus PR: 0
File: clients/agent-runtime/AGENTS.md:0-0
Timestamp: 2026-02-17T12:31:17.076Z
Learning: Applies to clients/agent-runtime/src/{security,gateway,tools}/**/*.rs : Treat `src/security/`, `src/gateway/`, `src/tools/` as high-risk surfaces and never broaden filesystem/network execution scope without explicit policy checks
Applied to files:
clients/agent-runtime/src/gateway/mod.rs
🪛 LanguageTool
openspec/changes/archive/2026-04-15-slash-command-registry-core/proposal.md
[grammar] ~77-~77: Use a hyphen to join words.
Context: ...cept slash commands before normal prompt side effects. Existing session commands ...
(QB_NEW_EN_HYPHEN)
🪛 markdownlint-cli2 (0.22.0)
openspec/changes/archive/2026-04-15-slash-command-registry-core/verify-report.md
[warning] 1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🔇 Additional comments (18)
clients/agent-runtime/src/memory/sqlite.rs (2)
4-5: LGTM: Import formatting improvement.Grouping related session state types on single lines improves readability. No semantic change.
1599-1599: LGTM: Test import addition is correct.Explicitly importing
SessionFieldPatchmakes test dependencies clear and supports the session state patching tests added for the slash-command registry feature.openspec/specs/sessions/spec.md (1)
595-595: No issues in this change segment.Line 595 is a non-behavioral docs touch and remains consistent with the current session spec contract.
As per coding guidelines: "
**/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes."openspec/changes/archive/2026-04-15-slash-command-registry-core/state.yaml (1)
1-12: State metadata looks consistent.Phase progression and archive handoff fields are internally coherent for the archived change record.
openspec/changes/archive/2026-04-15-slash-command-registry-core/specs/slash-command-registry/spec.md (1)
1-167: Spec contract is clear and aligned with implementation intent.The requirements are internally consistent and preserve critical boundaries (registry dispatch vs handler auth/backend enforcement).
As per coding guidelines: "
**/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes."openspec/specs/slash-command-registry/spec.md (1)
1-167: Looks good—requirements are precise and testable.The spec cleanly defines deterministic registry behavior while preserving existing slash-session semantics and fallthrough for unknown slash-like input.
As per coding guidelines: "
**/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes."clients/agent-runtime/src/gateway/webhook_dispatch.rs (1)
1087-1116: Good regression test for slash-like fallthrough.This test correctly protects the gateway path against over-eager slash interception by asserting normal provider execution for unknown slash-like input.
clients/agent-runtime/src/channels/mod.rs (1)
3263-3281: Good regression coverage for unknown slash-like fallthrough.Line 3263 adds the right guardrail: unknown slash-like input returns
Noneand sends no channel response.clients/agent-runtime/src/pre_execution/mod.rs (2)
50-77: Registry-first ingress dispatch is correctly wired.Line 50 through Line 77 correctly short-circuits recognized slash commands through the registry while preserving fallthrough for non-dispatched input.
259-292: Test coverage now pins critical slash-command error semantics.Line 259 through Line 292 adds strong regression checks for unsupported-backend
/tldrand invalid-argument/tldrusage.clients/agent-runtime/src/main.rs (3)
1529-1531: Behavioral change correctly aligns with registry semantics.The switch from
SessionCommandParser::parse(message).is_none()to!default_registry().recognizes(message)is intentional:parse()returnsSome(...)for any slash-prefixed input (e.g.,/resume-later), whilerecognizes()only returnstruefor registered commands. This ensures unknown slash-like input falls through to the agent loop rather than being incorrectly intercepted.The test at lines 3418–3428 validates this fallthrough behavior.
3411-3428: Test coverage validates registry fallthrough semantics.The
/tldrtest correctly expects an error when memory backend is"none"(SQLite required). The new/resume-latertest validates that unregistered slash-like input returnsNone(fallthrough) rather than being intercepted.
718-719: Pattern match updates are sound.Using
(..)and{ tool, .. }to ignore additional fields inApprovalRequiredis idiomatic and forward-compatible with future struct extensions.Also applies to: 782-782, 1422-1422
clients/agent-runtime/src/session_commands/service.rs (1)
564-571: Test helper now correctly filters by session ID.The
FakeMemory::get_sessionchange ensures the mock matches real behavior—only returning the session when the requested ID matches. This prevents false-positive test results.openspec/changes/archive/2026-04-15-slash-command-registry-core/exploration.md (1)
1-27: Documentation accurately captures the registry architecture.The exploration doc correctly describes the transition from hard-coded dispatch to registry-driven lookup, the
pre_execution::evaluate_ingressseam, and identifies relevant risks (transport parity,/resumeauthorization semantics, backend capability rules).clients/agent-runtime/src/session_commands/parser.rs (1)
6-22: Lexical parser implementation is sound.The parser correctly extracts the slash command token and raw args without hardcoding specific commands. Edge cases (bare
/, non-slash input, whitespace handling) are properly handled.openspec/changes/archive/2026-04-15-slash-command-registry-core/tasks.md (1)
1-26: Task documentation is complete and accurate.The implementation checklist correctly reflects the PR scope—registry core only, excluding help/introspection APIs and new command families. All four phases are marked complete with appropriate verification steps.
clients/agent-runtime/src/gateway/mod.rs (1)
1977-2040: Good move short-circuiting recognized slash commands before legacy session tracking.This keeps registry-backed session commands off the legacy upsert/autosave path while still preserving the shared ingress seam for non-slash prompts.
| #[allow(unused_imports)] | ||
| pub use parser::SessionCommandParser; | ||
| pub use registry::dispatch; | ||
| #[allow(unused_imports)] | ||
| pub use registry::{default_registry, SlashCommandRegistry}; | ||
| pub use service::SessionCommandService; | ||
| pub use types::{CommandContext, SessionCommandResult}; | ||
| #[allow(unused_imports)] | ||
| pub use types::{ | ||
| CommandContext, RawSlashInvocation, SessionCommandError, SessionCommandResult, | ||
| SlashCommandArgumentShape, SlashCommandDescriptor, SlashCommandHandler, | ||
| SlashCommandRegistration, SlashCommandRequirements, SlashInvocation, SlashRegistryError, | ||
| }; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Re-exports align with registry API; consider removing #[allow(unused_imports)] later.
The exported types match the new registry-driven architecture. The #[allow(unused_imports)] attributes are acceptable during transition, but consider removing them once downstream consumers stabilize.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@clients/agent-runtime/src/session_commands/mod.rs` around lines 6 - 16,
Remove the temporary #[allow(unused_imports)] attributes from the re-exports
once downstream consumers stabilize: delete the attributes applied to
SessionCommandParser, the registry exports (default_registry,
SlashCommandRegistry) and the bulk types export (CommandContext,
RawSlashInvocation, SessionCommandError, SessionCommandResult,
SlashCommandArgumentShape, SlashCommandDescriptor, SlashCommandHandler,
SlashCommandRegistration, SlashCommandRequirements, SlashInvocation,
SlashRegistryError); keep the explicit pub use service::SessionCommandService
line as-is and ensure the module still compiles after removing those attributes.
- parser: fix split_primary_target to return args after target - registry: strengthen validate_name to require len >= 2 and lowercase second char - registry: detect canonical vs alias conflicts and duplicate aliases in same descriptor - service: fix context truncation to trim from end preserving header - service: remove redundant get_session call in handle_resume - gateway: handle SessionCommand after session upsert for session-dependent commands - docs: fix 'prompt side' -> 'prompt side-effects' in proposal - docs: fix verify-report.md to use H1 instead of H2
Related Issues
Closes #539
Refs #527
Summary
This PR introduces the slash command registry core for
clients/agent-runtime.It replaces the previous hard-coded slash-session dispatch path with a validated central registry that owns command descriptors, canonical/alias lookup, and dispatch through the shared
pre_execution::evaluate_ingress(...)seam.It also keeps the existing session commands (
/resume,/suspend,/tldr,/compact) working through thin registry-backed handlers, preserves backend/authz enforcement inSessionCommandService, and syncs the completed OpenSpec artifacts for the change.Tested Information
Validated with the Rust runtime checks relevant to this change:
cargo fmt --manifest-path clients/agent-runtime/Cargo.toml --all -- --checkcargo clippy --manifest-path clients/agent-runtime/Cargo.toml --all-targets -- -D warningscargo test --manifest-path clients/agent-runtime/Cargo.tomlI also verified the gateway/webhook slash-command regression cases during the SDD verification loop.
Documentation Impact
openspec/specs/slash-command-registry/spec.mdopenspec/specs/sessions/spec.mdopenspec/changes/archive/2026-04-15-slash-command-registry-core/Breaking Changes
None.
Checklist