# Build the "Edit attribution history" pattern: `EditHistory`

## 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
A per-change record of which edits came from a human and which from a model.

Use it when: Collaborative documents, code and designs where authorship affects review.

## What to build
A per-change history for a document, file or design that attributes each edit to the person or agent who made it, shows exactly what each change touched, and lets a single change be reverted without undoing the others. It renders as a side panel next to the content.

### Props
- `changes`: Array<{ id: string; actor: { kind: "person" | "agent"; name: string; onBehalfOf?: string }; at: Date; summary: string; ranges: Array<{ before: string; after: string; location?: string }>; revertible: boolean; revertedBy?: { name: string; at: Date } }>, one entry per edit, never batched across actors.
- `selectedId?`: string and `onSelect(id | null)`: which change is highlighted in the content.
- `filter`: "all" | "people" | "agents" | string (an actor id), with `onFilterChange`.
- `onRevert(id)`: revert only this change. The component never edits the document itself.
- `groupBy?`: "none" | "session", collapse an actor's consecutive edits into an expandable group that still lists each one.
- `conflicts?`: Record<string, string>, reasons a change cannot be reverted cleanly, keyed by change id.

### States it must render
- List: newest first, each entry with the actor chip (agents visibly distinct), time and a specific summary like "Changed refund window from 5 to 10 days".
- Selected: the change's before and after text inline, with the affected words highlighted in the content.
- Grouped: "Agent made 50 edits" expands to all 50, each still selectable and revertible.
- Reverted: the entry stays, struck through, with "Reverted by <name>".
- Conflict: Revert disabled with the reason, e.g. "Later edits changed this text".

### Interactions
- Clicking an entry calls `onSelect`; arrow keys move between entries.
- Revert asks for inline confirmation showing the before text, then calls `onRevert`.
- Filter chips by people, agents or a specific actor call `onFilterChange` and show counts.

### Edge cases
- An agent edit made with a person's credentials: show the agent as actor and the person as "on behalf of"; if unknown, label it "Actor unclear" rather than crediting the person.
- A change that touched many places: show the first three ranges and "+ n more".
- Reverting a change that a later change depends on: surface the conflict, never silently revert both.
- Pure formatting or whitespace edits: label them as such so they don't look like content changes.

## Must avoid
Collapsing an agent's fifty edits into one anonymous "updated" entry.

## Engineering constraint
Attribute at commit or block level with the agent identity, not the human's credentials.

## Accessibility
- The history is a list; each entry's name includes actor type, actor, time and summary.
- After revert, announce "Reverted: <summary>" and keep focus on that entry.

## 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.
