# `single_step_choice`

## Use when / do not use when

Use when exactly one standard option completes the step on selection. Do not use for emoji-led choices, multi-select, or a separate form submission.

## Exact metadata contract

<!-- funnelsgrove:generated:start contract-v3/step/single_step_choice -->
### Generated contract facts — do not edit

- Step contract version: `3`
- Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
- Type: `single_step_choice`
- Family: `choice`
- Description: Exactly one standard option is selected.
- Action owner: `step`
- Analytics role: _none_
- Terminal: `false`
- Required kind: _none_
- Allowed kinds: _None_
- Allowed semantic events: _None_
- Forbidden capabilities: `email-capture`, `checkout`, `subscription-management`, `subscription-handoff`, `hardcoded-navigation`, `provider-direct-analytics`, `browser-registration-completed`

#### Choice contract

- Cardinality: `one`
- Presentation: `standard`
- Completion: `selection`
- Allow empty config: `false`

#### Automatic lifecycle events

`first_step_clicked`, `first_step_viewed`, `funnel_started`, `step_completed`, `step_exited`, `step_started`

#### Approved capability owners

- `choice-write` must be owned by `useStepChoices`.

#### Reserved identities

_No reserved identity for this type._

#### Golden fixture source

```ts
import type { FunnelManifestStep, FunnelStepMeta } from '@funnelsgrove/runtime';

const choice = { answerKey: 'routine' } as const;

const manifestStep = {
  id: 'routine',
  name: 'routine',
  path: '/routine',
  filePath: 'src/steps/step-routine.tsx',
  componentKey: 'stepRoutine',
  type: 'single_step_choice',
  choice,
  title: 'Choose a routine',
} as const satisfies FunnelManifestStep;

const componentMeta = {
  id: 'routine',
  name: 'routine',
  type: 'single_step_choice',
  choice,
  figmaNodeId: 'golden:single-step-choice',
  title: 'Choose a routine',
  description: 'Select exactly one routine.',
} as const satisfies FunnelStepMeta;

export const goldenFixture = {
  stepType: 'single_step_choice',
  manifestStep,
  componentMeta,
  options: [
    { id: 'daily', label: 'Every day' },
    { id: 'weekdays', label: 'Weekdays' },
  ],
  persistedAnswer: 'daily',
  helper: 'useStepChoices',
} as const;
```
<!-- funnelsgrove:generated:end contract-v3/step/single_step_choice -->

## Interaction and persisted answer shape

Declare `choice.answerKey` in both metadata copies. Persist one stable option ID as a scalar string, never the label or an object.

## Automatic lifecycle events

`useStepChoices` coordinates the answer write with the controller-owned completion lifecycle. Preview keeps provider delivery suppressed.

## Required semantic conversions

None. Selecting an option is answer state plus automatic lifecycle completion.

## Approved shared helpers

Use `useStepChoices`; let it complete and route after the stable ID is persisted.

## MUST rules

- Give every option a stable ID that survives copy changes.
- Keep the manifest and component `choice.answerKey` identical.

## NEVER rules

- Never call answer SDK methods directly from the choice component.
- Never store a display label, index, or whole option object.

## Golden template or fixture

See the [embedded canonical fixture](#golden-fixture-source) generated from `single_step_choice.fixture.ts`.

## Validation command

Run `fgrove validate`.

## Manual QA and completion criteria

Select every option once; confirm exactly one stable ID is saved and each selection completes/routes only once.
