> ## Documentation Index
> Fetch the complete documentation index at: https://hedgeem-api.qeetoto.com/llms.txt
> Use this file to discover all available pages before exploring further.

# F008 — Hand Status

> Per-hand status labels emitted by the server at each betting stage, driving UI indicators and GDK win flow

# F008 — Hand Status

| Field  | Value                |
| ------ | -------------------- |
| ID     | F008                 |
| Phase  | 1 — Core Game Engine |
| Jira   | HEDGE-133            |
| Status | TS ✅ · JS ⬜ · UMA ✅  |

## Business Rule

At every betting stage the server assigns each hand a `handStatus` label. These labels drive:

* Which hands are highlighted as the **favourite** (most likely to win)
* Which hands are marked as **dead** at RIVER (losers)
* Which hand is the **winner** at RIVER
* UI display in the TS client (favourite badge, win/dead overlays)

## HandStatus Values

| Value                          | When set           | Meaning                                                          |
| ------------------------------ | ------------------ | ---------------------------------------------------------------- |
| `IN_PLAY_BETTING_STAGE_ACTIVE` | HOLE / FLOP / TURN | Normal active hand — player may bet                              |
| `IN_PLAY_FAVOURITE`            | HOLE / FLOP / TURN | The hand with the highest `winPercentage`; exactly one per stage |
| `IN_PLAY_WINNER`               | RIVER              | The hand that won the showdown                                   |
| `IN_PLAY_DEAD`                 | RIVER              | All non-winning hands at RIVER                                   |

Four further values exist in the `HandStatus` enum (`UNDEFINED`, `IN_NON_BETTING_STAGE`, `IN_PLAY_PREVIOUS_BETTING_STAGE_NOT_ACTIVE`, `IN_PLAY_DISABLED`, `IN_PLAY_WILL_WIN`) but are not emitted by the live advance endpoint.

## Favourite Logic

At pre-RIVER stages the hand with the highest `winPercentage` receives `IN_PLAY_FAVOURITE`. In the event of a tie the first hand (lowest `handIndex`) wins the tiebreak.

```typescript theme={null}
// api/tables/[tableId]/advance.ts — buildHandOdds()
const status = i === favouriteIdx
  ? HandStatus.IN_PLAY_FAVOURITE
  : HandStatus.IN_PLAY_BETTING_STAGE_ACTIVE;
```

## RIVER Logic

At RIVER the hand evaluator sets `winPercentage = 100` (or `drawPercentage = 100` for a split) for the winner. The API maps this to `IN_PLAY_WINNER`; all other hands receive `IN_PLAY_DEAD`.

## TypeScript Implementation

`ApiClient.ts` maps `handStatus` to a boolean flag used by the scene:

```typescript theme={null}
statusIsFavourite: o.handStatus === 'IN_PLAY_FAVOURITE',
```

## UMA State Bridge

`platform.js` exposes `handStatus` via `window._lastStages`:

```
window._lastStages[handIndex][lastEntry].handStatus
  → 'IN_PLAY_FAVOURITE' | 'IN_PLAY_BETTING_STAGE_ACTIVE' | 'IN_PLAY_WINNER' | 'IN_PLAY_DEAD' | null
```

`_lastStages` is populated:

* At HOLE init (alongside `_holeOdds`)
* After each advance (FLOP, TURN, RIVER) via `buildGameStatus`

At RIVER, `window._winnerInfo[i].isWinner` is an additional proxy: `true` ↔ `IN_PLAY_WINNER`.

## Acceptance Criteria

| #   | Criterion                                                                                         | JS | TS | UMA |
| --- | ------------------------------------------------------------------------------------------------- | -- | -- | --- |
| AC1 | At HOLE, exactly one hand has `IN_PLAY_FAVOURITE`; all others have `IN_PLAY_BETTING_STAGE_ACTIVE` | ⬜  | ✅  | ✅   |
| AC2 | At FLOP, exactly one hand has `IN_PLAY_FAVOURITE`; all others have `IN_PLAY_BETTING_STAGE_ACTIVE` | ⬜  | ✅  | ✅   |
| AC3 | At TURN, exactly one hand has `IN_PLAY_FAVOURITE`; all others have `IN_PLAY_BETTING_STAGE_ACTIVE` | ⬜  | ✅  | ✅   |
| AC4 | At RIVER, exactly one hand has `IN_PLAY_WINNER`; all others have `IN_PLAY_DEAD`                   | ⬜  | ✅  | ✅   |
| AC5 | `IN_PLAY_FAVOURITE` hand always has the lowest odds value (= highest `winPercentage`)             | ⬜  | ✅  | ✅   |

### UMA-testable ACs (via state bridge)

| #       | UMA Criterion                                                                                                                                    | Notes                                  |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------- |
| AC1-UMA | After HOLE, `_lastStages[i][0].handStatus`: exactly one `IN_PLAY_FAVOURITE`, rest `IN_PLAY_BETTING_STAGE_ACTIVE`                                 | Set at HOLE init alongside `_holeOdds` |
| AC2-UMA | After FLOP advance, same check on `_lastStages[i][last].handStatus`                                                                              |                                        |
| AC3-UMA | After TURN advance, same check                                                                                                                   |                                        |
| AC4-UMA | After RIVER advance, `_winnerInfo` has exactly one `isWinner === true`; `_lastStages[i][last].handStatus` ∈ { `IN_PLAY_WINNER`, `IN_PLAY_DEAD` } |                                        |
| AC5-UMA | The hand with `IN_PLAY_FAVOURITE` has the minimum odds value in `_lastStages` at that stage                                                      | Lowest odds = highest win%             |

## Version Parity

| Version        | Status        | Notes                                                                                    |
| -------------- | ------------- | ---------------------------------------------------------------------------------------- |
| JS (reference) | ⬜ Not audited |                                                                                          |
| TS             | ✅ Verified    | `statusIsFavourite` mapped in `ApiClient.ts`; favourite badge rendered in `GameScene.ts` |
| UMA            | ✅ Verified    | `tests/features/F008-hand-status.spec.ts` — AC1–AC5 (UMA) pass (2026-04-15)              |

## Test Coverage

Playwright spec: `tests/features/F008-hand-status.spec.ts` — AC1–AC5 (UMA).

Run with:

```bash theme={null}
VERSION=uma npx playwright test tests/features/F008-hand-status.spec.ts --project=features --workers=1
```

## Related Features

* F006 — Odds Calculation (`winPercentage` drives the favourite selection)
* F005 — Hand Evaluation (RIVER winner determined by pokersolver → `IN_PLAY_WINNER`)
* F025 — Dead Hand Display (uses `IN_PLAY_DEAD` status)
* F026 — Cant-Lose Display (uses `IN_PLAY_WILL_WIN` — not yet implemented in live endpoint)
