# Manual Poll Start — Upstream Integration Guide

## Overview

The vote-app now supports a `poll.start` WebSocket message that explicitly triggers poll generation. This replaces the previous behavior where polls were always auto-generated on `game.ended`.

## Poll Modes

The vote-app has two poll modes:

| Mode | `game.ended` behavior | `poll.start` behavior |
|------|----------------------|----------------------|
| **manual** (default) | Logged but no poll generated | Generates a new poll |
| **auto** | Generates a new poll (legacy behavior) | Generates a new poll |

The mode is persisted in the vote-app database and survives restarts. It can be toggled from the debug panel (Game Control section).

## Message Format

Send this JSON message over the existing upstream WebSocket connection:

```json
{
  "type": "poll.start",
  "sessionId": 3
}
```

### Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `type` | string | yes | Must be `"poll.start"` |
| `sessionId` | number | no | Included for consistency; the vote-app uses its internally tracked session ID |

The `sessionId` field is optional in practice — the vote-app tracks the active session from `session.started` / subscription events and uses that to determine which games to exclude from the poll. Including it is recommended for protocol consistency.

## When to Send

- **After `game.ended`** — if the vote-app is in `manual` mode, `game.ended` alone will not create a poll. Send `poll.start` when you're ready for viewers to vote on the next game.
- **At any time** — you can send `poll.start` to force a new poll regardless of mode. Any existing active poll is deactivated and replaced.

## What Happens on Receipt

1. The vote-app fetches enabled games from the upstream API (`GET /api/games?enabled=true`)
2. It fetches the current session's games (`GET /api/sessions/{id}/games`) to exclude recently played titles
3. It picks 3 random games (weighted by favor bias) plus an "Other" option
4. The previous active poll (if any) is deactivated
5. The new poll is created and broadcast to all connected browser clients via WebSocket

## Example (Node.js)

```javascript
// Assuming `ws` is your existing WebSocket connection to the vote-app upstream
// and you've already authenticated and subscribed to the session

function startPoll(sessionId) {
  ws.send(JSON.stringify({
    type: 'poll.start',
    sessionId: sessionId
  }));
}

// Typical flow: game ends, wait for the right moment, then start the poll
ws.on('message', (raw) => {
  const msg = JSON.parse(raw);

  if (msg.type === 'game.ended') {
    // Game just ended — start poll when ready
    // (in manual mode, vote-app won't auto-generate one)
    startPoll(msg.data.sessionId);
  }
});
```

## Existing Messages (Unchanged)

These upstream messages continue to work as before:

- `game.ended` — in `auto` mode, still triggers poll generation; in `manual` mode, logged but no poll created
- `voting.ended` — deactivates the active poll and broadcasts the winner
- `game.started` — deactivates the active poll and hides the overlay
- `room.connected` — deactivates the active poll and broadcasts room info
- `poll.leading` — still sent by the vote-app to upstream when the leading vote changes
