# Voice Control Simplification Plan

## Current State

**30 files** across 7 directories (~3300 lines):

```
dora_voice_control/
├── behaviors/          # 2 files
│   ├── __init__.py
│   └── base.py
├── node/               # 5 files
│   ├── __init__.py
│   ├── adapter.py
│   ├── context.py
│   ├── dispatcher.py
│   └── logging.py
├── robot/              # 6 files
│   ├── __init__.py
│   ├── adapter.py      # VacuumGripperAdapter, ParallelGripperAdapter
│   ├── command_queue.py
│   ├── image_handler.py
│   ├── pose_handler.py
│   └── status_handler.py
├── scene/              # 4 files
│   ├── __init__.py
│   ├── notifier.py
│   ├── objects_handler.py
│   └── state.py
├── utils/              # 3 files
│   ├── __init__.py
│   ├── config.py
│   └── state.py
├── voice/              # 4 files
│   ├── __init__.py
│   ├── handler.py
│   ├── intent.py
│   └── parser.py
├── web/                # 4 files
│   ├── __init__.py
│   ├── api.py
│   ├── models.py
│   └── templates.py
├── __init__.py
└── main.py
```

## Problems

1. **Too many small files** - Many files are <50 lines
2. **Robot-specific code scattered** - Adapter in robot/, behavior in behaviors/
3. **Hard to add new robots** - Need to touch multiple directories
4. **Deep import chains** - `from ..node import ...`

---

## Proposed Structure

**12 files** across 3 directories:

```
dora_voice_control/
├── __init__.py
├── main.py
├── node.py             # Dora infrastructure (adapter, context, dispatcher, logger)
├── handlers.py         # All event handlers (voice, robot, scene)
├── scene.py            # SceneState, SceneObject
├── state.py            # SharedState, RobotStep, config loading
├── web.py              # API server (api + models + templates)
└── behaviors/
    ├── __init__.py     # get_behavior() factory
    ├── base.py         # ActionContext, ActionInfo, RobotBehavior base
    └── littlehand/
        ├── __init__.py
        └── robot.py    # LittlehandBehavior + VacuumGripperAdapter
```

---

## File Consolidation Map

### `node.py` (merge 5 files)

| From | Content |
|------|---------|
| `node/logging.py` | VoiceControlLogger |
| `node/adapter.py` | NodePort, DoraNodeAdapter, MockNodeAdapter |
| `node/context.py` | OutputPort, NodeContext |
| `node/dispatcher.py` | EventHandler, EventDispatcher |

### `handlers.py` (merge 7 files)

| From | Content |
|------|---------|
| `voice/handler.py` | VoiceInputHandler |
| `voice/intent.py` | Intent, IntentQueue |
| `robot/pose_handler.py` | PoseHandler |
| `robot/status_handler.py` | StatusHandler |
| `robot/image_handler.py` | ImageHandler |
| `robot/command_queue.py` | CommandQueueService |
| `scene/objects_handler.py` | ObjectsHandler |
| `scene/notifier.py` | SceneNotifier |

### `scene.py` (merge 2 files)

| From | Content |
|------|---------|
| `scene/state.py` | SceneState, SceneObject |

Already consolidated - just move to root.

### `state.py` (merge 2 files)

| From | Content |
|------|---------|
| `utils/state.py` | SharedState, RobotStep, VoiceState, DebugState |
| `utils/config.py` | VoiceConfig, ApiConfig, LLMConfig, loaders |

### `web.py` (merge 3 files)

| From | Content |
|------|---------|
| `web/api.py` | create_api(), start_api_server() |
| `web/models.py` | CommandRequest, CommandResponse |
| `web/templates.py` | HTML_TEMPLATE |

### `behaviors/littlehand/robot.py` (new)

| From | Content |
|------|---------|
| `robot/adapter.py` | VacuumGripperAdapter (robot-specific) |
| `behaviors/base.py` | Action implementations (robot-specific) |

Robot adapter moves INTO the behavior folder.

---

## Per-Robot Folder Structure

Each robot gets its own folder with everything it needs:

```
behaviors/
├── __init__.py         # get_behavior(robot_type) factory
├── base.py             # Shared base classes
│   - ActionContext
│   - ActionInfo
│   - RobotBehavior (abstract)
│
└── littlehand/         # Vacuum gripper robot
    ├── __init__.py
    └── robot.py
        - VacuumGripperAdapter
        - LittlehandBehavior (actions, LLM signature)
        - ACTIONS dict
        - CommandSignature (DSPy)
```

### Adding a New Robot (e.g., "gripper_arm")

1. Create `behaviors/gripper_arm/`
2. Create `robot.py` with:
   - `ParallelGripperAdapter`
   - `GripperArmBehavior`
   - Custom actions
3. Register in `behaviors/__init__.py`

No need to touch other files.

---

## Implementation Steps

### Phase 1: Consolidate node/ → node.py

1. Create `node.py` merging adapter, context, dispatcher, logging
2. Update imports in all files
3. Delete `node/` directory

### Phase 2: Consolidate handlers

1. Create `handlers.py` merging all handlers
2. Update imports
3. Delete `voice/`, `robot/` directories (except adapter)

### Phase 3: Consolidate utils/ → state.py

1. Create `state.py` merging config and state
2. Update imports
3. Delete `utils/` directory

### Phase 4: Move scene/ → scene.py

1. Move `scene/state.py` to `scene.py`
2. Update imports
3. Delete `scene/` directory

### Phase 5: Consolidate web/ → web.py

1. Create `web.py` merging api, models, templates
2. Update imports
3. Delete `web/` directory

### Phase 6: Restructure behaviors per robot

1. Create `behaviors/littlehand/robot.py`
2. Move VacuumGripperAdapter from robot/adapter.py
3. Move action implementations from behaviors/base.py
4. Update `behaviors/__init__.py` factory
5. Delete old robot/adapter.py

### Phase 7: Update main.py

1. Update all imports to new structure
2. Simplify initialization

---

## Final Structure Comparison

| Before | After |
|--------|-------|
| 30 files | 12 files |
| 7 directories | 3 directories |
| Robot code scattered | Robot code in one folder |
| Deep imports | Flat imports |

---

## Benefits

1. **Easier navigation** - Fewer files to search
2. **Self-contained robots** - One folder per robot type
3. **Simpler imports** - `from .node import ...` instead of `from ..node import ...`
4. **Easier testing** - Mock one module instead of many
5. **Clear ownership** - Robot-specific code in robot folder
