# Review queue

Grade real agent answers one at a time, from the keyboard: P pass, F fail, J/K next and previous. The judge's verdict is shown beside the item but never pre-fills the grade, so people grade the answer, not the judge.

- Registry name: `review-queue` (`@candor/review-queue`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/review-queue

## Install

```bash
npx candor-ui add review-queue
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/review-queue`.
It brings in: agent-avatar, button, locale, ops, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import * as React from "react"
import { ReviewQueue } from "@/components/review-queue"
import type { ReviewItem } from "@/lib/ops"

export default function Example() {
  const [items, setItems] = React.useState<ReviewItem[]>([
    { id: "r1", agent: { id: "arch", name: "Architect agent", role: "planner" }, ask: "Can we drop legacy_tier from customers now?", answer: "Yes, it has had no writes in the last 90 days, so it’s safe to drop.", judge: { verdict: "pass", reason: "Answers the question directly." } },
    { id: "r2", agent: { id: "dev", name: "Dev agent", role: "coder" }, ask: "Why did the backfill stop?", answer: "Batch 12 hit a row lock four times, so the run stopped itself. The rows updated before it keep their region.", judge: { verdict: "pass", reason: "Explains the stop and its effect." } },
    { id: "r3", agent: { id: "qa", name: "QA agent", role: "tester" }, ask: "Is the new_checkout flag on in Staging?", answer: "It’s on for 50% of Staging traffic, per flags/new_checkout.yaml." },
  ])
  return <ReviewQueue className="max-w-xl" items={items} onGrade={(id, grade, note) => setItems((xs) => xs.map((x) => (x.id === id ? { ...x, grade, note } : x)))} />
}
```

## <ReviewQueue>

Props:

- `items: ReviewItem[]`: Answers to grade; it opens on the first one without a grade.
- `onGrade: (id: string, grade: "pass" | "fail", note?: string) => void`: Called with the item's id, the grade, and the reviewer's note if they wrote one.
- `className?: string | undefined`

## Strings (`reviewQueue`)

The fixed words, English by default. Override any of them under `reviewQueue` in `<LocaleProvider strings={{ reviewQueue: { … } }}>`; the table is exported as `reviewQueueStrings`.

- `reviewQueue`: Review queue
- `review`: Review
- `progress`: {position} of {total} · {done} graded
- `youPass`: You: pass
- `youFail`: You: fail
- `asked`: Asked
- `answered`: Answered
- `judgeSaid`: Judge said {verdict}: {reason}
- `verdictPass`: pass
- `verdictFail`: fail
- `notePlaceholder`: Note (optional): why
- `note`: Note
- `hintPass`: pass
- `hintFail`: fail
- `hintNav`: next/previous
- `fail`: Fail
- `pass`: Pass

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
