# Build the "Autonomy level selector" pattern: `AutonomyLevelControl`

## Stack (edit this block to match your project)
- React 18+ with TypeScript: one function component, typed props, no `any`.
- Tailwind CSS, using your design system's tokens if you have them.
- Presentational only: data comes in through props, decisions go out through callbacks. No fetching or global state inside.
- If your codebase already has conventions (naming, shared components, tokens), follow them over this spec.

## What the pattern is for
An explicit spectrum from suggest-only to review-after, set by the user rather than assumed by the product.

Use it when: Agents that will run repeatedly, where trust should grow with demonstrated reliability.

## What to build
A control that lets a person choose how much an agent may do on its own, from suggest-only through ask-first to act-then-report. It shows what each level would mean for the work currently queued, which limits apply at every level, and the track record that unlocks higher levels. It renders in agent settings or a run panel.

### Props
- `levels`: Array<{ id: string; name: string; description: string; locked?: { reason: string } }>, ordered from least to most autonomous.
- `currentLevelId`: string and `onChangeLevel(id: string)`, controlled. The component only requests a change; the parent enforces the level as server-side policy.
- `status`: "idle" | "saving" | "error", for the pending change.
- `queuedItems?`: Array<{ id: string; label: string; outcomeByLevel: Record<string, { text: string; kind: "draft" | "ask" | "act" }> }>, what the agent would do with each queued item at each level.
- `policies?`: Array<{ text: string; setBy?: string }>, limits that override every level, e.g. "Refunds over $500 always need a person".
- `trackRecord?`: { periodLabel: string; total: number; approvedUnchanged: number; edited: number; undone: number }, the evidence for raising the level.
- `history?`: Array<{ from: string; to: string; by: string; at: Date }>, past changes, newest first.

### States it must render
- Default: levels as an ordered scale with the current one checked, a badge "Level 2: Ask first", and the queue preview showing each item's outcome, e.g. "Asks you".
- Previewing a level: hovering or focusing another level updates the queue preview and a count such as "You approve 1 of 4", without changing anything.
- Locked level: a disabled option with its unlock condition, e.g. "Unlocks after 30 days at level 3 with under 1% undone".
- Saving: the new level shows as pending; queued items keep their place.
- Changed: a log line "Lowered from Act, then report to Ask first by you at 10:42. All 4 queued items kept their place."
- Error: the previous level stays checked with an inline message and Retry.

### Interactions
- Selecting a level calls `onChangeLevel(id)`; lowering a level is always one action, never behind a confirmation or a lock.
- Raising to the most autonomous unlocked level asks for one confirmation that lists what will now happen without asking.
- Items whose outcome is governed by a policy show that policy next to the outcome, e.g. "Asks you, over $500 limit", at every level.
- Arrow keys move the selection along the scale.

### Edge cases
- No single "autonomous" switch: every level is a distinct option, and there is always a way back to a lower one.
- An item already in progress when the level changes: show it finishes under the level it started with, and say so.
- A level the person may not choose because an admin capped it: show it disabled with who set the cap.
- Empty queue: the preview says "Nothing queued" and the levels still describe behaviour in words.

## Must avoid
A single "autonomous" master switch that grants everything at once with no ratchet back down.

## Engineering constraint
Enforce levels server-side as policy, not in the client; changing level must not lose queued work.

## Accessibility
- The scale is a `radiogroup`; each option's name includes level number, name and description, and locked options use `aria-disabled` with the unlock reason as description.
- Announce the change log line after a level is saved.

## House rules
- Real `<button>`/`<input>` elements, full keyboard use, visible focus; announce status changes with `aria-live="polite"`; respect `prefers-reduced-motion`.
- All user-facing text comes from props (or a `labels` prop) so it can be translated.
- One consistent accent marks anything the AI made or is doing; amber means "needs a person", red means risky, green means done. Never rely on colour alone.
- Fits a 360 px wide container without horizontal scrolling.

## Acceptance checks
- [ ] Every state above can be rendered by passing props, with no internal fake data.
- [ ] Every interaction and edge case above behaves as described.
- [ ] Nothing in "Must avoid" can happen with this component.

## Deliver
1. The component file with its exported prop types.
2. A short usage example that renders each state.
