Skip to content

DEPRECATION NOTICE

This implementation plan has been completed. The checkboxes below were not updated during implementation and do not reflect current status. Please refer to the actual codebase for the current implementation state. Key implemented features include:

  • Argument Parsing (packages/maid-engine/src/maid_engine/commands/arguments.py)
  • Command Decorators (packages/maid-engine/src/maid_engine/commands/decorators.py)
  • Help Generator (packages/maid-engine/src/maid_engine/commands/help.py)
  • Hook System (packages/maid-engine/src/maid_engine/commands/hooks.py)
  • Lock System (packages/maid-engine/src/maid_engine/commands/locks.py)
  • Layered Registry (packages/maid-engine/src/maid_engine/commands/registry.py)

Command System Enhancements - Implementation Plan

Summary

This plan implements four major enhancements to MAID's command system to achieve feature parity with Evennia:

  1. Advanced Argument Parsing - Declarative argument schemas with type coercion, entity resolution, and pattern matching
  2. Auto-Generated Help from Docstrings - Automatic help text extraction from handler docstrings and argument specs
  3. Pre/Post Command Hooks - Middleware pipeline for logging, cooldowns, combat checks, and cleanup
  4. Enhanced Lock System - Expression-based permissions with AND/OR/NOT operators and pluggable lock functions

All features are backward-compatible; existing commands continue to work without modification.


Tasks

Phase 1: Core Argument Parsing Infrastructure

Location: packages/maid-engine/src/maid_engine/commands/arguments.py

  • [x] Create ArgumentType enum with types: STRING, INTEGER, FLOAT, BOOLEAN, ENTITY, ENTITY_LIST, DIRECTION, PLAYER, REST
  • [x] Create SearchScope enum for entity search: ROOM, INVENTORY, EQUIPMENT, ROOM_AND_INVENTORY, ALL
  • [x] Create ArgumentError dataclass for parse errors
  • [x] Create ArgumentSpec generic dataclass with validation logic
  • Supports: name, type, required, default, description, choices, pattern, search_scope, min/max values
  • [x] Create ParsedArguments dataclass with dict-like access and error tracking
  • [x] Create EntityReference class for resolved entity results with entity, found, and iteration support
  • [x] Create ArgumentPattern dataclass for pattern-based parsing (e.g., <target> = <message>)
  • [x] Write unit tests for all dataclasses and enums

Phase 2: Argument Parser Implementation

Location: packages/maid-engine/src/maid_engine/commands/arguments.py

  • [x] Implement ArgumentParser class
  • [x] Implement parse() method dispatching to positional or pattern parsing
  • [x] Implement _parse_positional() for sequential argument parsing
  • [x] Implement _parse_pattern() for regex-based pattern extraction
  • [x] Implement _parse_value() for type coercion (STRING, INTEGER, FLOAT, BOOLEAN)
  • Depends on: Phase 1 dataclasses
  • [x] Implement entity resolution in _resolve_entity()
  • [x] Support index syntax (2.sword)
  • [x] Support all syntax (all.sword)
  • [x] Support special keywords (me, here)
  • [x] Implement _entity_matches_keyword() for keyword matching
  • Depends on: SearchScope, EntityReference
  • [x] Implement _resolve_player() for online player lookup
  • [x] Implement _normalize_direction() for direction aliases (n→north, etc.)
  • [x] Write unit tests for ArgumentParser with all argument types
  • [x] Write integration tests for entity resolution

Phase 3: Argument Decorators

Location: packages/maid-engine/src/maid_engine/commands/decorators.py

  • [x] Implement @arguments(*specs) decorator
  • Wraps handler to parse arguments before execution
  • Attaches __argument_parser__ and __argument_specs__ for introspection
  • Depends on: ArgumentParser
  • [x] Implement @pattern(pattern_string, *specs) decorator
  • Supports delimited patterns like <target> = <message>
  • Depends on: ArgumentPattern, ArgumentParser
  • [x] Write unit tests for decorators
  • [x] Add usage examples to docstrings

Phase 4: Help Generator

Location: packages/maid-engine/src/maid_engine/commands/help.py

  • [x] Create HelpEntry dataclass with all help fields
  • [x] Create ArgumentHelp dataclass for argument documentation
  • [x] Implement HelpGenerator class
  • [x] Implement generate() to create HelpEntry from CommandDefinition
  • [x] Implement _parse_docstring() to extract short/long description, see_also, examples
  • [x] Implement _generate_usage() from argument specs or pattern
  • [x] Implement _extract_argument_help() from handler decorators
  • Depends on: Phase 3 decorators (for __argument_specs__)
  • [x] Implement format_terminal() for terminal-friendly output with wrapping
  • [x] Write unit tests for docstring parsing
  • [x] Write unit tests for usage generation
  • [x] Write unit tests for terminal formatting

Phase 5: Hook System Infrastructure

Location: packages/maid-engine/src/maid_engine/commands/hooks.py

  • [x] Create HookPriority enum: FIRST, HIGH, NORMAL, LOW, LAST
  • [x] Create HookResult enum: CONTINUE, CANCEL, SKIP
  • [x] Create PreHookContext dataclass with cancel() method
  • [x] Create PostHookContext dataclass with result, exception, execution_time_ms
  • [x] Create RegisteredHook dataclass with matches() method for command/category filtering
  • [x] Implement HookRegistry class
  • [x] Implement register_pre_hook() with priority sorting
  • [x] Implement register_post_hook() with priority sorting
  • [x] Implement unregister() by name
  • [x] Implement get_pre_hooks() and get_post_hooks() with filtering
  • [x] Write unit tests for HookRegistry

Phase 6: Command Executor with Hooks

Location: packages/maid-engine/src/maid_engine/commands/hooks.py

  • [x] Implement CommandExecutor class
  • [x] Implement execute() with full pre/post hook pipeline
  • [x] Handle pre-hook cancellation with user message
  • [x] Handle SKIP result to bypass remaining pre-hooks
  • [x] Ensure post-hooks run even on handler exception
  • [x] Track execution time for post-hook context
  • [x] Implement _call_hook() supporting both sync and async handlers
  • Depends on: HookRegistry
  • [x] Write unit tests for hook execution order
  • [x] Write unit tests for cancellation flow
  • [x] Write unit tests for exception handling

Phase 7: Built-in Hooks

Location: packages/maid-engine/src/maid_engine/commands/hooks.py

  • [x] Implement logging_pre_hook() - log command attempts
  • [x] Implement logging_post_hook() - log command completion with timing
  • [x] Implement CooldownHook class
  • Tracks per-player, per-command cooldowns
  • Reads cooldown from command metadata
  • [x] Implement CombatStateHook class
  • Blocks configurable commands during combat
  • [x] Implement MetricsHook class
  • Collects execution counts, times, error counts
  • Provides get_stats() method
  • [x] Write unit tests for each built-in hook

Phase 8: Lock Expression Parser

Location: packages/maid-engine/src/maid_engine/commands/locks.py

  • [x] Create LockContext dataclass with player, world, target, command context
  • [x] Create LockFunctionRegistry class for registering/evaluating lock functions
  • [x] Create LockNode ABC and concrete node classes:
  • [x] LockFunctionNode - function call like perm(admin)
  • [x] LockAndNode, LockOrNode, LockNotNode - operators
  • [x] LockTrueNode, LockFalseNode - constants
  • [x] Implement LockExpressionParser class
  • [x] Implement tokenizer with TOKEN_PATTERNS
  • [x] Implement parse() with expression caching
  • [x] Implement recursive descent: _parse_or_expr, _parse_and_expr, _parse_not_expr, _parse_primary
  • [x] Handle parentheses for grouping
  • [x] Produce clear error messages for invalid expressions
  • [x] Write unit tests for parser with various expressions
  • [x] Write unit tests for operator precedence

Phase 9: Lock Evaluator and Built-in Functions

Location: packages/maid-engine/src/maid_engine/commands/locks.py

  • [x] Implement LockEvaluator class with check() method
  • Depends on: LockExpressionParser
  • [x] Implement built-in lock functions:
  • [x] lock_all(), lock_none() - always pass/fail
  • [x] lock_perm() - access level check
  • [x] lock_owns() - target ownership check
  • [x] lock_holds() - inventory check
  • [x] lock_in_room() - room tag check
  • [x] lock_has_flag() - player tag check
  • [x] lock_in_guild(), lock_guild_rank() - guild checks
  • [x] lock_level() - account access level check (and lock_char_level() - character level check)
  • [x] lock_in_combat() - combat state check
  • [x] lock_has_item() - inventory item check
  • [x] lock_has_skill() - skill level check
  • [x] Register all built-in functions with LockFunctionRegistry
  • [x] Write unit tests for each lock function

Phase 10: Registry Integration

Location: packages/maid-engine/src/maid_engine/commands/registry.py

  • [x] Add locks: str field to CommandDefinition dataclass
  • [x] Add metadata: dict[str, Any] field to CommandDefinition for hook data (e.g., cooldowns)
  • [x] Initialize HookRegistry and CommandExecutor in LayeredCommandRegistry.__init__()
  • [x] Initialize LockEvaluator in LayeredCommandRegistry.__init__()
  • [x] Update execute() method to:
  • [x] Evaluate lock expressions before execution
  • [x] Use CommandExecutor for hook pipeline
  • Depends on: Phases 6 and 9
  • [x] Add register_pre_hook() and register_post_hook() convenience methods
  • [x] Write integration tests for full command flow with hooks and locks
  • [x] Verify backward compatibility with existing commands

Phase 11: Update Command Decorator

Location: packages/maid-engine/src/maid_engine/commands/decorators.py

  • [x] Update @command() decorator to accept locks parameter
  • [x] Update @command() decorator to accept metadata parameter (for cooldowns etc.)
  • [x] Ensure HelpGenerator can access lock expressions
  • [x] Write integration tests for decorated commands with locks

Phase 12: Help Command Integration

  • [x] Update help command to use HelpGenerator
  • [x] Display lock requirements in help output (P1)
  • [x] Format argument help with required markers
  • [x] Test help output for commands with full decorators

Phase 13: Documentation and Examples

  • [x] Add docstrings to all public classes and methods
  • [x] Create usage examples in docs/examples/:
  • [x] Basic argument parsing example
  • [x] Pattern-based parsing example
  • [x] Hook registration example
  • [x] Custom lock function example
  • [x] Update CLAUDE.md with new command system features
  • [x] Document migration path for existing commands

Phase 14: Testing and Performance

  • [x] Achieve 90%+ test coverage for ArgumentParser, HookRegistry, CommandExecutor
  • [x] Achieve 95%+ test coverage for LockExpressionParser
  • [x] Add performance benchmarks:
  • [x] Argument parsing (5 args) < 1ms
  • [x] Lock expression parsing < 0.5ms
  • [x] Lock evaluation (complex) < 0.1ms
  • [x] Hook pipeline (5 hooks) < 2ms
  • [x] Run full regression test suite
  • [x] Test backward compatibility with existing commands

Dependencies Graph

Phase 1 (Dataclasses)
    └─► Phase 2 (ArgumentParser)
           └─► Phase 3 (Decorators)
                  └─► Phase 4 (HelpGenerator)
                  └─► Phase 11 (Command Decorator Updates)

Phase 5 (Hook Infrastructure)
    └─► Phase 6 (CommandExecutor)
           └─► Phase 7 (Built-in Hooks)
           └─► Phase 10 (Registry Integration)

Phase 8 (Lock Parser)
    └─► Phase 9 (Lock Functions)
           └─► Phase 10 (Registry Integration)

Phase 10 (Registry Integration)
    └─► Phase 11 (Command Decorator Updates)
           └─► Phase 12 (Help Command)
                  └─► Phase 13 (Documentation)
                         └─► Phase 14 (Testing)

Priority Ordering

P0 (Must Have): - Phases 1-3: Core argument parsing - Phases 5-6: Hook infrastructure and executor - Phases 8-10: Lock system and registry integration

P1 (Should Have): - Phase 4: Help generator - Phase 7: Built-in hooks - Phase 12: Help command integration

P2 (Nice to Have): - Phase 13: Documentation and examples - Phase 14: Performance benchmarks


Estimated Effort

Phase Effort Dependencies
Phase 1 0.5 day None
Phase 2 1 day Phase 1
Phase 3 0.5 day Phase 2
Phase 4 1 day Phase 3
Phase 5 0.5 day None
Phase 6 1 day Phase 5
Phase 7 0.5 day Phase 6
Phase 8 1 day None
Phase 9 1 day Phase 8
Phase 10 1 day Phases 6, 9
Phase 11 0.5 day Phase 10
Phase 12 0.5 day Phases 4, 11
Phase 13 1 day Phase 12
Phase 14 1 day All

Total: ~11 days