# Event System v2

This document is the source of truth for the Tier 3 event runtime.

## Coverage Checklist

- [x] Protocol contract (server -> client and client -> server)
- [x] Runtime architecture and lifecycle
- [x] Backend migration notes
- [x] iOS migration notes
- [x] Android migration notes
- [x] Verification command matrix
- [x] Legacy-path constraints

## Protocol Contract

### Outbound envelopes

Server emits one of the following top-level message types:

1. `event_prompt`
2. `event_resolved`
3. `event_error`

#### `event_prompt`

```json
{
  "type": "event_prompt",
  "eventId": "school_first_day",
  "instanceId": "evtinst_123",
  "prompt": "It is your first day of school. How do you introduce yourself?",
  "choices": [
    { "choiceId": "confident_intro", "text": "Confidently introduce yourself" },
    { "choiceId": "quiet_intro", "text": "Keep it short and quiet" }
  ],
  "metadata": {
    "category": "education"
  }
}
```

#### `event_resolved`

```json
{
  "type": "event_resolved",
  "eventId": "school_first_day",
  "instanceId": "evtinst_123",
  "resolutionText": "Your confidence made a strong first impression.",
  "effects": {
    "stats": { "happiness": 3 }
  },
  "metadata": {
    "category": "education",
    "status": "resolved"
  }
}
```

#### `event_error`

```json
{
  "type": "event_error",
  "code": "INVALID_EVENT_RESPONSE",
  "message": "Invalid event response payload",
  "eventId": "school_first_day"
}
```

### Inbound command (client -> server)

Interactive choices must be sent with command type `eventResponse`.

```json
{
  "type": "eventResponse",
  "message": {
    "eventId": "school_first_day",
    "choiceId": "confident_intro"
  }
}
```

## Runtime Architecture

The active runtime is `server/src/events/v2` and follows this flow:

1. Registry/collisions are validated at startup.
2. `promptNext(player)` selects at most one event prompt per tick.
3. A persisted event instance is created (`pending`).
4. Client responds with `eventResponse` (`eventId` + `choiceId`).
5. `respond(player, message)` validates choice and resolves deterministically.
6. Instance transitions to `resolved`; server emits `event_resolved`.

Legacy random dilemma polling (`activeDilemmas`, `checkDilemmas`) is inactive in the active runtime path.

## Backend Migration Notes

- `eventResponse` is the canonical response command.
- `questionEvent` response handling is deprecated for event choices.
- Generic fallback dispatch no longer routes to `allEvents` answer handlers.
- Legacy pollers in `stats_manager` are inert compatibility shims (`return null`).

Key guard tests:

- `server/tests/events-v2/no-legacy-runtime.test.ts`
- `server/tests/events-v2/legacy-removal.guard.test.ts`
- `server/tests/handlers/events.v2.dispatch.test.ts`

## iOS Migration Notes

iOS now decodes and renders v2 envelopes:

- `event_prompt`
- `event_resolved`
- `event_error`

iOS sends responses in the strict v2 contract:

```json
{ "type": "eventResponse", "message": { "eventId": "...", "choiceId": "..." } }
```

Relevant tests:

- `ios/lichunWebsocketTests/EventV2DecodingTests.swift`
- `ios/lichunWebsocketTests/EventV2ResponseTests.swift`
- `ios/lichunWebsocketTests/EventV2RenderingTests.swift`

## Android Migration Notes

Android now parses v2 envelopes and sends strict v2 responses with `eventId` + `choiceId`.

Relevant tests:

- `android/app/src/test/java/com/craigvg/lichun_android/network/EventV2ParsingTest.kt`
- `android/app/src/test/java/com/craigvg/lichun_android/network/EventV2ResponsePayloadTest.kt`
- `android/app/src/test/java/com/craigvg/lichun_android/ui/EventV2RenderTest.kt`

## Verification Matrix

### Backend

```bash
cd server
npm run build
npm test
npm run test:coverage
```

### iOS

```bash
cd ios
xcodebuild -project lichunWebsocket.xcodeproj -scheme BaoLife -configuration Debug build
xcodebuild test -project lichunWebsocket.xcodeproj -scheme BaoLife -destination 'platform=iOS Simulator,name=iPhone 15'
```

### Android

```bash
cd android
./gradlew assembleDebug
./gradlew test
./gradlew lint
```

## Legacy Constraints

These are intentionally unsupported in active runtime:

1. `allEvents` answer dispatch for interactive event responses.
2. `classBasedEvents` fallback response matching for event choices.
3. Random `checkDilemmas` polling for dilemma resolution.
4. Text-heuristic answer mapping for event choice resolution.
