Implement Parameter DSL with 12 parameter types #292

Closed
opened 2026-03-16 01:59:21 +00:00 by freemo · 1 comment
Owner

Metadata

Key Value
Branch feature/m1-param-dsl
Commit Message feat: implement Parameter DSL with 12 parameter types
Parent Epic #291 — Input Validation Framework

Background and Context

Command handlers currently parse raw input strings manually, with each handler implementing its own ad-hoc parsing. This leads to inconsistent behavior and duplicated code. A declarative Parameter DSL will allow handlers to specify their expected parameters in a clean, readable format, enabling the validation pipeline to handle parsing and type-checking automatically.

The DSL must support 12 parameter types covering all common input patterns in a MUD: :string, :integer, :float, :direction, :object, :player, :mobile, :room, :area, :item, :boolean, :enum.

Expected Behavior

Command handlers declare parameters using a class-level DSL. Example usage:

class LookCommand < BaseCommand
  param :target, type: :object, required: false, in: :room
  param :direction, type: :direction, required: false
end

class GiveCommand < BaseCommand
  param :item, type: :item, required: true, in: :inventory
  param :target, type: :player, required: true, in: :room
  param :amount, type: :integer, required: false, default: 1
end

Each parameter declaration supports options: type, required (default false), default, in (scope for resolution), values (for :enum type), and description.

Acceptance Criteria

  • param class method is available on all command handler classes.
  • All 12 parameter types are defined and recognized: :string, :integer, :float, :direction, :object, :player, :mobile, :room, :area, :item, :boolean, :enum.
  • Parameters support options: type, required, default, in, values, description.
  • Parameter declarations are inherited by subclasses.
  • Each command class exposes its parameter list via .declared_params.
  • Invalid DSL usage (e.g., unknown type) raises a clear error at load time.

Subtasks

Code

  • Create ParameterDSL module with param class method.
  • Define ParamDefinition value object storing name, type, options.
  • Implement type registry mapping the 12 type symbols to type metadata.
  • Add .declared_params class method returning ordered list of ParamDefinition.
  • Ensure subclass inheritance of parameter declarations.
  • Add load-time validation of DSL usage (unknown types, duplicate names).

Quality

  • Docs: Update YARD comments on affected classes and methods. Update relevant Docusaurus documentation pages if applicable.
  • Tests (Cucumber): Add tests/unit/parameter_dsl.feature covering declaring parameters with all 12 types, inheritance, invalid DSL usage, default values, required vs optional.
  • Tests (Cucumber Integration): Add integration feature in tests/integration/ for parameter DSL declarations on command handlers.
  • Tests (Profiling): Run bundle exec rake unit_profile and verify no performance regressions.
  • Quality: Verify coverage >=97% via bundle exec rake unit. If coverage is <97% then review the current unit test coverage report at build/tests/unit/coverage/ and use it to write new Cucumber based unit tests to improve coverage. Specifically, write Cucumber/Gherkin style unit tests that are descriptively named and specifically improve coverage on whichever file has the most uncovered lines by writing tests that will target the uncovered lines in the report. Once that is done rerun bundle exec rake unit to verify all tests pass and coverage is above >=97%. Only mark this as complete once coverage is >=97%, if not repeat this task as many times as is needed until coverage reaches >=97%.
  • Quality: Run bundle exec rake (default task: unit tests with coverage) and bundle exec rake integration, fix any errors if needed ensuring both pass across entire code base, do not ignore any failure even if it seems unrelated to this commit, fix it.

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
## Metadata | Key | Value | |-----|-------| | **Branch** | `feature/m1-param-dsl` | | **Commit Message** | `feat: implement Parameter DSL with 12 parameter types` | | **Parent Epic** | #291 — Input Validation Framework | ## Background and Context Command handlers currently parse raw input strings manually, with each handler implementing its own ad-hoc parsing. This leads to inconsistent behavior and duplicated code. A declarative Parameter DSL will allow handlers to specify their expected parameters in a clean, readable format, enabling the validation pipeline to handle parsing and type-checking automatically. The DSL must support 12 parameter types covering all common input patterns in a MUD: `:string`, `:integer`, `:float`, `:direction`, `:object`, `:player`, `:mobile`, `:room`, `:area`, `:item`, `:boolean`, `:enum`. ## Expected Behavior Command handlers declare parameters using a class-level DSL. Example usage: ```ruby class LookCommand < BaseCommand param :target, type: :object, required: false, in: :room param :direction, type: :direction, required: false end class GiveCommand < BaseCommand param :item, type: :item, required: true, in: :inventory param :target, type: :player, required: true, in: :room param :amount, type: :integer, required: false, default: 1 end ``` Each parameter declaration supports options: `type`, `required` (default false), `default`, `in` (scope for resolution), `values` (for `:enum` type), and `description`. ## Acceptance Criteria - [ ] `param` class method is available on all command handler classes. - [ ] All 12 parameter types are defined and recognized: `:string`, `:integer`, `:float`, `:direction`, `:object`, `:player`, `:mobile`, `:room`, `:area`, `:item`, `:boolean`, `:enum`. - [ ] Parameters support options: `type`, `required`, `default`, `in`, `values`, `description`. - [ ] Parameter declarations are inherited by subclasses. - [ ] Each command class exposes its parameter list via `.declared_params`. - [ ] Invalid DSL usage (e.g., unknown type) raises a clear error at load time. ## Subtasks ### Code - [ ] Create `ParameterDSL` module with `param` class method. - [ ] Define `ParamDefinition` value object storing name, type, options. - [ ] Implement type registry mapping the 12 type symbols to type metadata. - [ ] Add `.declared_params` class method returning ordered list of `ParamDefinition`. - [ ] Ensure subclass inheritance of parameter declarations. - [ ] Add load-time validation of DSL usage (unknown types, duplicate names). ### Quality - [ ] Docs: Update YARD comments on affected classes and methods. Update relevant Docusaurus documentation pages if applicable. - [ ] Tests (Cucumber): Add `tests/unit/parameter_dsl.feature` covering declaring parameters with all 12 types, inheritance, invalid DSL usage, default values, required vs optional. - [ ] Tests (Cucumber Integration): Add integration feature in `tests/integration/` for parameter DSL declarations on command handlers. - [ ] Tests (Profiling): Run `bundle exec rake unit_profile` and verify no performance regressions. - [ ] Quality: Verify coverage >=97% via `bundle exec rake unit`. If coverage is <97% then review the current unit test coverage report at `build/tests/unit/coverage/` and use it to write new Cucumber based unit tests to improve coverage. Specifically, write Cucumber/Gherkin style unit tests that are descriptively named and specifically improve coverage on whichever file has the most uncovered lines by writing tests that will target the uncovered lines in the report. Once that is done rerun `bundle exec rake unit` to verify all tests pass and coverage is above >=97%. Only mark this as complete once coverage is >=97%, if not repeat this task as many times as is needed until coverage reaches >=97%. - [ ] Quality: Run `bundle exec rake` (default task: unit tests with coverage) and `bundle exec rake integration`, fix any errors if needed ensuring both pass across **entire** code base, do not ignore any failure even if it seems unrelated to this commit, fix it. ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done.
freemo added this to the v1.0.0 milestone 2026-03-16 01:59:21 +00:00
freemo self-assigned this 2026-03-16 01:59:21 +00:00
Author
Owner

Implementation Notes

Files Created

  1. lib/aethyr/core/input_handlers/validation/type_registry.rb - TypeRegistry module containing all 12 parameter types with metadata (name, description, category)

  2. lib/aethyr/core/input_handlers/validation/param_definition.rb - ParamDefinition value object storing parameter name, type, required flag, default value, scope, enum values, and description

  3. lib/aethyr/core/input_handlers/validation/parameter_dsl.rb - ParameterDSL module providing the param class method and declared_params accessor with inheritance support

Key Design Decisions

  • Immutable ParamDefinition: The value object is frozen after creation for thread safety
  • Type validation at declaration time: Unknown types raise UnknownTypeError immediately when param is called
  • Duplicate detection: DuplicateParameterError is raised if the same parameter name is declared twice (including inherited names)
  • Inheritance support: declared_params returns parent parameters first, then own parameters, maintaining declaration order
  • **options pattern: Used to reduce parameter count and satisfy rubocop while maintaining the same public API

Test Coverage

  • 32 unit test scenarios covering all 12 types, inheritance, validation errors, default values, scopes, and real-world examples
  • 6 integration test scenarios verifying DSL integration with command handlers
## Implementation Notes ### Files Created 1. **`lib/aethyr/core/input_handlers/validation/type_registry.rb`** - TypeRegistry module containing all 12 parameter types with metadata (name, description, category) 2. **`lib/aethyr/core/input_handlers/validation/param_definition.rb`** - ParamDefinition value object storing parameter name, type, required flag, default value, scope, enum values, and description 3. **`lib/aethyr/core/input_handlers/validation/parameter_dsl.rb`** - ParameterDSL module providing the `param` class method and `declared_params` accessor with inheritance support ### Key Design Decisions - **Immutable ParamDefinition**: The value object is frozen after creation for thread safety - **Type validation at declaration time**: Unknown types raise `UnknownTypeError` immediately when `param` is called - **Duplicate detection**: `DuplicateParameterError` is raised if the same parameter name is declared twice (including inherited names) - **Inheritance support**: `declared_params` returns parent parameters first, then own parameters, maintaining declaration order - **`**options` pattern**: Used to reduce parameter count and satisfy rubocop while maintaining the same public API ### Test Coverage - **32 unit test scenarios** covering all 12 types, inheritance, validation errors, default values, scopes, and real-world examples - **6 integration test scenarios** verifying DSL integration with command handlers
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference: aethyr/Aethyr#292
No description provided.