# Build the "Recall attribution" pattern: `MemoryAttribution`

## 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
When the system uses memory, it says which memory — turning surprise into confirmation.

Use it when: Assistants whose personalisation is otherwise indistinguishable from guessing.

## What to build
Shows which memories an AI answer used: numbered markers in the text tie each personalised claim to a memory, and a list underneath names each memory's source with an excerpt. A person can confirm, mark a memory as not relevant, or forget it from the same place. It renders under or beside an AI message.

### Props
- `segments`: Array<{ text: string; memoryIds?: string[] }>, the answer split into spans; a span with `memoryIds` drew on those memories.
- `memories`: Array<{ id: string; title: string; source: { label: string; at: Date; savedBy?: string }; excerpt?: string; forgotten?: boolean }>, exactly the memories retrieved and logged with this response.
- `responseId`: string, shown with the logged memory ids so the record can be audited.
- `status`: "attributed" | "none" | "unavailable".
- `selectedId?`: string and `onSelect(id: string | null)`, controlled selection.
- `expanded?`: boolean and `onToggle(expanded: boolean)`, whether the memory list is open.
- `onMarkIrrelevant(memoryId)`, `onForget(memoryId)` and `onCorrect?(memoryId)`: callbacks. The component never edits memory itself.

### States it must render
- Collapsed: a chip in the message header, e.g. "Used 3 memories", and small numbered markers in the text.
- Expanded: the list of memories with title, source, date and who saved it, each with Not relevant and Forget.
- Memory selected: its spans are highlighted and its excerpt opens, showing where the fact came from.
- Marked not relevant: the row dims with "Won't be used for requests like this".
- None: "No memories used" stated explicitly, so personalisation is never implied. Unavailable: "Memory sources weren't logged for this answer"; nothing is reconstructed after the fact.

### Interactions
- Clicking a marker or a memory row selects it; clicking again clears the selection.
- The header chip toggles the list via `onToggle`.
- Not relevant, Forget and Correct call their callbacks; Forget asks for a one-step confirmation inline.

### Edge cases
- A memory that shaped the answer without a specific span (tone, sign-off style) is listed under "Also used".
- A memory forgotten after this answer: keep its title, drop the excerpt, and label it "Forgotten since".
- A memory saved by someone else in a shared workspace shows who saved it.
- Only memories present in `memories` can have markers; a `memoryIds` entry with no matching memory renders no marker and is ignored.

## Must avoid
Personalisation that feels like surveillance because the source is never named.

## Engineering constraint
Log the retrieved memory IDs with the response so the citation is real, not reconstructed.

## Accessibility
- Markers are buttons labelled like "Memory 2: prefers email over phone" with `aria-pressed`.
- The link between span and memory is shown with an underline or outline as well as colour.

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