# Phase 1 PR #2 Checklist: Fast-Path Command Registry

Created: 2026-02-12
Owner: Flynn core
Status: ready to implement

## Goal

Add a deterministic `CommandRegistry` that handles simple slash commands before `AgentOrchestrator`, reducing latency/token usage and keeping fallback behavior fully intact.

Initial fast-path commands for this PR:
- `/help`
- `/status`
- `/usage`
- `/model`
- `/compact`
- `/reset`

## PR Boundary

In scope:
- New `CommandRegistry` abstraction with typed handlers
- Built-in deterministic command handlers
- Fast-path integration in channel routing and gateway agent handler
- Graceful fallback to existing orchestrator flow when unmatched
- Unit + integration tests

Out of scope:
- Runtime plugin command loading
- Command auth/ACL system beyond current session/channel constraints
- Command chaining/pipelines
- Per-command rate limiting

## File-by-File Diff Plan

1) `src/commands/types.ts` (new)

- Define command contracts.

```ts
export interface CommandContext {
  channel: string;
  senderId: string;
  sessionId: string;
  rawInput: string;
}

export interface CommandResult {
  handled: boolean;
  text: string;
}

export interface CommandDefinition {
  name: string;
  aliases?: string[];
  description: string;
  execute: (args: string[], ctx: CommandContext) => Promise<CommandResult>;
}
```

2) `src/commands/registry.ts` (new)

- Implement registration + parse + execute.
- Use `Map` for O(1) lookup.

Required methods:
- `register(def: CommandDefinition): void`
- `get(nameOrAlias: string): CommandDefinition | undefined`
- `list(): CommandDefinition[]`
- `isCommand(input: string): boolean`
- `parse(input: string): { name: string; args: string[] } | null`
- `execute(input: string, ctx: CommandContext): Promise<CommandResult>`

3) `src/commands/builtin/index.ts` (new)

- Export command factories to avoid circular deps and enable daemon wiring with dependencies.

Factories:
- `createHelpCommand(registry: CommandRegistry)`
- `createStatusCommand()`
- `createUsageCommand()`
- `createModelCommand(...)`
- `createCompactCommand(...)`
- `createResetCommand(...)`

4) `src/commands/index.ts` (new)

- Barrel exports.

5) `src/daemon/index.ts` (modify)

- Construct a `CommandRegistry` at daemon startup.
- Register built-in commands with required deps.
- Pass registry into both message routing and gateway handler dependency paths.
- Add to `DaemonContext` if needed for future introspection.

6) `src/daemon/routing.ts` (modify)

- In `handler`, before invoking `agent.process(...)`:
  - detect slash command with registry
  - execute command
  - if `handled`, reply immediately and return
  - if not handled, continue existing orchestrator path

Important:
- Preserve existing `msg.metadata?.isCommand` behavior.
- Do not break current `/model`, `/usage`, `/compact`, `/reset` logic while migrating; either reuse existing code in handlers or keep compatibility shim.

7) `src/gateway/handlers/agent.ts` (modify)

- Add equivalent fast-path before agent processing.
- Return command output through existing gateway response events.
- Maintain cancellation/queue behavior unchanged.

8) `src/gateway/handlers/index.ts` and related handler deps (modify as needed)

- Thread `commandRegistry` through constructor/dependency interfaces.

9) Tests

- `src/commands/registry.test.ts` (new)
- `src/daemon/routing.test.ts` (modify/add cases)
- `src/gateway/handlers/agent.test.ts` (modify/add cases)

## Implementation Steps

1. Create typed command contracts and registry.
2. Add core parse/lookup/execute behavior with strict handling for unknown commands.
3. Implement built-in command handlers as factories.
4. Wire registry in daemon bootstrap.
5. Add channel router fast-path.
6. Add gateway fast-path.
7. Add tests for success/fallback/error cases.
8. Run full validation suite.

## Validation Commands

```bash
pnpm typecheck
pnpm test:run src/commands/registry.test.ts
pnpm test:run src/daemon/routing.test.ts
pnpm test:run src/gateway/handlers/agent.test.ts
pnpm test:run
pnpm lint
pnpm build
```

## Acceptance Criteria

- `CommandRegistry` supports register/get/list/parse/execute.
- Known commands are handled without entering `AgentOrchestrator.process()`.
- Unknown commands cleanly fall through to existing orchestration flow.
- Existing slash command UX remains unchanged for users.
- `/model`, `/usage`, `/compact`, `/reset` still function correctly via fast-path.
- Gateway and channel routes both support fast-path execution.
- All tests pass; no regressions in existing command behavior.

## Quality Gates

- Backward compatibility:
  - Existing command parsing and metadata behavior still works.
  - Existing TUI/web command flows are not broken.
- Security:
  - No shell execution from command names/args in registry core.
  - Input length and basic parse validation enforced.
  - Handler errors are caught and returned safely.
- Performance:
  - Lookup uses O(1) maps.
  - No measurable slowdown for non-command messages.
- Reliability:
  - Registry failures do not crash daemon startup unexpectedly.
  - Unknown command behavior deterministic and tested.

## Risks and Mitigations

- Risk: duplicate command logic between old path and new path.
  - Mitigation: move existing command branches into reusable built-in handlers, keep thin compatibility shim.
- Risk: divergence between gateway and channel behavior.
  - Mitigation: reuse same registry + handler functions; add parity tests for both entrypoints.
- Risk: hidden regressions in slash command edge-cases.
  - Mitigation: preserve existing parse semantics and add regression tests.

## Suggested Commit Message

`feat(commands): add fast-path command registry before orchestrator`

## Follow-up PRs

1. Add command discovery/docs endpoint for UI autocomplete.
2. Add optional command-level permission profiles.
3. Add skill-registered commands (`//skill`) on top of registry.
