# Modal Events Wiring Specification

**Status:** Started
**Created:** 2026-01-24
**Priority:** Medium
**Risk:** Medium - Modal system is actively used by many commands

## Problem Statement

Two modal lifecycle events are defined in `kollabor/events/models.py` but never emitted:
- `MODAL_SHOW` - should signal when modal becomes visible
- `MODAL_SAVE` - should signal when user triggers save action

The documentation describes these as part of the modal lifecycle, but the implementation skips them.

## Current State

### Events Defined (models.py lines 121-133)
```python
MODAL_TRIGGER = "modal_trigger"          # [USED] opens modal
STATUS_MODAL_TRIGGER = "status_modal_trigger"  # [USED]
STATUS_MODAL_RENDER = "status_modal_render"    # [USED]
LIVE_MODAL_TRIGGER = "live_modal_trigger"      # [USED]
MODAL_COMMAND_SELECTED = "modal_command_selected"  # [USED]
PAUSE_RENDERING = "pause_rendering"      # [USED]
RESUME_RENDERING = "resume_rendering"    # [USED]
MODAL_SHOW = "modal_show"                # [NOT EMITTED]
MODAL_HIDE = "modal_hide"                # [USED]
MODAL_SAVE = "modal_save"                # [NOT EMITTED]
```

### Documentation Gap
- `docs/reference/modal-system-guide.md` (lines 510-545) describes MODAL_SHOW and MODAL_SAVE as part of lifecycle
- `docs/reference/event-types-reference.md` (line 800) acknowledges: "MODAL_SHOW, MODAL_SAVE - not emitted"
- `docs/reference/hook-system-sdk.md` lists them as available events

## Modal System Users

### Core Commands (system_commands.py)
- `_show_profiles_modal()` - LLM profile selection
- `_show_create_profile_modal()` - Create new profile form
- `_show_cd_modal()` - Directory change modal
- `_show_create_agent_modal()` - Agent creation form
- Multiple other modals for config editing

### Plugins
- `resume_conversation_plugin.py` - Conversation resume/branch modals (10+ modal uses)
- `tmux_plugin.py` - Terminal session management

### Core Components
- `kollabor/commands/executor.py` - Routes modal commands
- `kollabor/io/input/modal_controller.py` - Modal input handling
- `kollabor/ui/modal_renderer.py` - Modal rendering
- `kollabor/ui/modal_actions.py` - Save/cancel handling
- `kollabor/io/status/help_system.py` - Help overlays
- `kollabor/io/status/navigation_manager.py` - Status area modals
- `kollabor/io/status/interaction_handler.py` - Widget interactions

## Proposed Implementation

### MODAL_SHOW Event

**When:** After `prepare_modal_display()` succeeds and modal is rendered

**Where:** `kollabor/ui/modal_renderer.py` in `show_modal()` method

**Data:**
```python
{
    "modal_title": str,
    "modal_type": str,  # "config", "form", "selection", etc.
    "ui_config": UIConfig,
    "timestamp": float
}
```

**Purpose:**
- Plugins can react when modals become visible
- Analytics/logging of modal usage
- Accessibility hooks (screen readers)

### MODAL_SAVE Event

**When:** When user triggers save (Ctrl+S or Enter on save action)

**Where:** Either:
- `kollabor/ui/modal_actions.py` in `_handle_save_action()` - needs event_bus injection
- OR `kollabor/ui/modal_renderer.py` before calling action handler

**Data:**
```python
{
    "modal_title": str,
    "changes": Dict[str, Any],
    "changes_count": int,
    "widgets": List[str],  # widget types involved
    "timestamp": float
}
```

**Purpose:**
- Plugins can intercept/validate saves
- Audit logging of configuration changes
- Undo/history tracking

## Implementation Steps

### Phase 1: Preparation
- [ ] Add event_bus to ModalRenderer if not present
- [ ] Add event_bus to ModalActionHandler
- [ ] Verify event_bus is available at modal creation time

### Phase 2: MODAL_SHOW
- [ ] Identify exact location after modal renders successfully
- [ ] Add emit_with_hooks call with modal metadata
- [ ] Test with existing modals (config, profile, agent)

### Phase 3: MODAL_SAVE
- [ ] Add emit before save action executes
- [ ] Include change data in event
- [ ] Test save flow still works
- [ ] Verify event fires before changes applied (allows interception)

### Phase 4: Testing
- [ ] Test all modal commands still work
- [ ] Test plugins using modals (resume_conversation, tmux)
- [ ] Test keyboard shortcuts (Ctrl+S, Escape)
- [ ] Test event data is correct

### Phase 5: Documentation
- [ ] Update event-types-reference.md (remove "not emitted" note)
- [ ] Update modal-system-guide.md if needed
- [ ] Add examples of hooking these events

## Files to Modify

```
kollabor/ui/modal_renderer.py      - Add MODAL_SHOW emission
kollabor/ui/modal_actions.py       - Add MODAL_SAVE emission (needs event_bus)
```

## Files to Test After Changes

```
kollabor/commands/system_commands.py     - Config, profile, agent modals
plugins/resume_conversation_plugin.py - Conversation modals
plugins/tmux_plugin.py               - Terminal modals
kollabor/io/status/help_system.py        - Help modal
kollabor/io/status/interaction_handler.py - Widget modals
```

## Risk Assessment

**Breaking Changes:**
- None expected - adding events is additive
- Existing code doesn't depend on these events

**Testing Priority:**
1. `/config` command - most complex modal with widgets
2. `/profile` command - selection modal
3. `/resume` command - conversation plugin modals
4. Help overlay (F1/?)

## Related Issues

- Part of larger event system cleanup
- See also: STATUS_TAKEOVER_* events (not wired)
- See also: WIDGET_COMMAND_EXECUTE (not wired)

## References

- `docs/reference/modal-system-guide.md` - Modal architecture
- `docs/reference/event-types-reference.md` - Event definitions
- `kollabor/events/models.py` - EventType enum
