Description
PR #2922 introduced the zeph-commands crate scaffold with generic types and the ChannelSink trait, but all concrete slash command handlers remain in zeph-core because they access 20+ internal agent state types via Agent<C>.
This issue tracks completing the extraction so that zeph-commands contains the actual handlers, not just scaffolding.
Current state (after #2922)
zeph-commands contains:
ChannelSink trait
CommandOutput, SlashCategory, CommandInfo, CommandError
CommandHandler<Ctx> and CommandRegistry<Ctx> generic types
Still in zeph-core:
- All
*_commands.rs handler files
CommandContext<C> (generic over C: Channel)
- The concrete
CommandRegistry<CommandContext<C>> instantiation
Blockers
Handlers access internal agent state directly: MemoryState, SkillState, ToolOrchestrator, LearningEngine, FocusState, SidequestState, and ~15 more types. Two approaches to unblock:
Option A — Trait-based decoupling (preferred)
Introduce a CommandState trait in zeph-commands:
pub trait CommandState: Send + Sync {
fn memory(&self) -> &dyn MemoryAccess;
fn skills(&self) -> &dyn SkillAccess;
fn tools(&self) -> &dyn ToolAccess;
// ...
}
zeph-core::Agent<C> implements CommandState. Handlers in zeph-commands receive &dyn CommandState instead of direct field access.
Option B — Move subsystem types to leaf crates
Extract MemoryState, SkillState, etc. to zeph-memory, zeph-skills, zeph-tools respectively (some may already be there). Handlers import from those crates without needing zeph-core.
Option A is lower-risk; Option B aligns better with the long-term decomposition plan (#2909).
Acceptance Criteria
Related
Description
PR #2922 introduced the
zeph-commandscrate scaffold with generic types and theChannelSinktrait, but all concrete slash command handlers remain inzeph-corebecause they access 20+ internal agent state types viaAgent<C>.This issue tracks completing the extraction so that
zeph-commandscontains the actual handlers, not just scaffolding.Current state (after #2922)
zeph-commandscontains:ChannelSinktraitCommandOutput,SlashCategory,CommandInfo,CommandErrorCommandHandler<Ctx>andCommandRegistry<Ctx>generic typesStill in
zeph-core:*_commands.rshandler filesCommandContext<C>(generic overC: Channel)CommandRegistry<CommandContext<C>>instantiationBlockers
Handlers access internal agent state directly:
MemoryState,SkillState,ToolOrchestrator,LearningEngine,FocusState,SidequestState, and ~15 more types. Two approaches to unblock:Option A — Trait-based decoupling (preferred)
Introduce a
CommandStatetrait inzeph-commands:zeph-core::Agent<C>implementsCommandState. Handlers inzeph-commandsreceive&dyn CommandStateinstead of direct field access.Option B — Move subsystem types to leaf crates
Extract
MemoryState,SkillState, etc. tozeph-memory,zeph-skills,zeph-toolsrespectively (some may already be there). Handlers import from those crates without needingzeph-core.Option A is lower-risk; Option B aligns better with the long-term decomposition plan (#2909).
Acceptance Criteria
*_commands.rsfiles moved tocrates/zeph-commands/src/handlers/CommandContextis non-generic (noC: Channel) inzeph-commandszeph-coredoes not define any command handlerscargo build --workspacepasseszeph-coreinternals does not recompilezeph-commandsunless theCommandStateinterface changesRelated