# AI Content Classification

## Objective

Sort text or records into a fixed set of categories, with review for low confidence.

A background classification pass that assigns records to labels from a versioned taxonomy, recording confidence and routing uncertain cases to a person.

## Before You Begin

This feature is being added to an application that already exists and already
works. Do not scaffold a new project, and do not assume a blank slate.

Inspect the codebase first and establish:

- The existing application structure and where code of this kind already lives.
- The framework and version in use.
- The existing design system — colours, spacing, typography, and component conventions.
- Existing UI components you can reuse instead of writing new ones.
- The existing database structure, if this feature needs to persist anything.
- The existing authentication and authorization system, if this feature is user-scoped.
- Dependencies already installed, so you don't add a library that duplicates one.
- The existing test setup and conventions.

Only start writing code once you understand the above. If the application
already implements part of this feature, extend it rather than replacing it.

## Implementation Instructions

1. Define the taxonomy as data the app owns, not as prose inside a prompt. Every label needs a definition and examples, and the set of valid labels must be enforced on the result rather than trusted from it.
2. Store the taxonomy version alongside every classification, so a label applied last quarter can still be explained against the definitions in force at the time.
3. Record a confidence value with each result and set a threshold below which the record is marked needs review instead of being labelled. Route those to an existing queue or list rather than leaving them unclassified and invisible.
4. Classify in the app's existing background-job system, batched, with a token ceiling and backoff on provider errors. Do not classify inline when a record is saved, or a provider outage becomes a failure to save.
5. Build the input from an explicit allow-list of fields. Restricted or sensitive attributes must be excluded unless an operator has approved them for this purpose, and that approval must be recorded.

## UI and UX Requirements

Match the application's existing design system exactly. Reuse its components,
spacing, and typography. This feature should look like it was always there.

## Responsive Requirements

Works on mobile, tablet, and desktop. Touch targets are large enough to hit on a
phone, and nothing overflows horizontally at 320px.

## Accessibility Requirements

- Fully keyboard navigable.
- Correct semantic elements and ARIA roles.
- Visible focus states.
- Meets WCAG AA contrast.
- Dynamic changes are announced to screen readers.
- Respects prefers-reduced-motion.

## Edge Cases

- A model will return a label that sounds plausible and does not exist. Validate every returned label against the current taxonomy and treat an invented one as a failed classification, not as a new category.
- Confidence must be part of the contract. A result with no confidence, or one below the threshold, becomes a needs-review record rather than a quietly applied label.
- Some records genuinely belong to more than one category. Decide in advance whether the taxonomy is single or multi label, and for single-label taxonomies send genuinely ambiguous records to review instead of forcing a pick.
- Changing the taxonomy invalidates prior work. Version it, keep old versions readable, and make reclassification after a change an explicit operator action rather than an automatic sweep.
- Restricted fields must never enter the input by default. Where an operator has approved one, record who approved it and when, and exclude it again if the approval is withdrawn.
- Human corrections must outrank the model. Once a person has set a label, a later automatic run must not overwrite it, and the correction should be visible as such.
- Malformed structured output, a refusal, or a timeout must leave the record unclassified and retryable, never labelled with a default category that pollutes the counts.
- When the model is unavailable, records queue as pending classification and every downstream view that filters by category must handle unclassified records rather than dropping them.

## Testing

Exercise the feature end to end in the running application. Cover every edge case
above, then run the existing test suite and confirm nothing regressed.

## Acceptance Criteria

- [ ] Labels are validated against a stored taxonomy and invented labels are rejected.
- [ ] Every classification records its confidence and the taxonomy version in force.
- [ ] Results below the confidence threshold are marked needs review and appear in a queue.
- [ ] Classification runs in batched background jobs with token ceilings and backoff.
- [ ] Input fields come from a documented allow-list, with any restricted field approval recorded.
- [ ] A human-set label is never overwritten by a later automatic run.
- [ ] Provider failure leaves records pending rather than defaulted, and views handle unclassified records.
- [ ] The feature matches the existing design system.
- [ ] No existing functionality is broken.

## Adaptation Rules

- Match the existing design system. Do not introduce a new colour palette,
  spacing scale, or component library.
- Reuse existing components and utilities wherever they fit.
- Follow the naming, file layout, and code style already present.
- Do not upgrade, replace, or remove existing dependencies to make this
  feature fit. Adapt the feature to the app, not the app to the feature.
- Do not break existing functionality. If a change is genuinely required in
  existing code, make the smallest one that works and say so.
- If something in these instructions conflicts with how the application is
  built, follow the application and explain the deviation.

## Final Verification

Before you report the work as done:

1. Re-read the acceptance criteria above and check each one against what you
   actually built.
2. Run the application and exercise the feature end to end.
3. Run the existing test suite and confirm you have broken nothing.
4. Check the feature on mobile, tablet, and desktop widths.
5. Check keyboard navigation and focus handling.
6. Summarize what changed: files added, files modified, and anything you
   deliberately did differently because of how this application is built.

If any acceptance criterion is unmet, fix it before reporting completion.
