# Insight ledger

The executive summary, in the three states it can honestly be in: not run yet; partial (some sections couldn't be computed, named); or ready, with counts by severity and the few findings that matter most.

- Registry name: `insight-ledger` (`@candor/insight-ledger`)
- 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/insight-ledger

## Install

```bash
npx candor-ui add insight-ledger
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/insight-ledger`.
It brings in: data, finding, locale, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { InsightLedger } from "@/components/insight-ledger"
import type { Finding } from "@/lib/data"

const findings: Finding[] = [
  { id: "f1", severity: "critical", title: "Billing tests fail on the new discount rules", body: "Three tests fail when an invoice mixes annual and monthly discounts.", evidence: [{ label: "billing.test.ts", detail: "3 failures" }] },
  { id: "f2", severity: "serious", title: "No rollback for the plan_tier rename", body: "Migration 0136 rewrites rows and has no down migration.", evidence: [{ label: "6,031 rows", detail: "would change" }] },
  { id: "f3", severity: "warning", title: "Two dashboards still read legacy_score", body: "This release drops the column.", evidence: [{ label: "Weekly health" }, { label: "Churn review" }] },
  { id: "f4", severity: "info", title: "The dark-mode flag is at 100% everywhere", body: "Safe to remove.", evidence: [{ label: "dark-mode" }] },
]

export default function Example() {
  return (
    <InsightLedger
      className="max-w-2xl"
      state="partial"
      headline="Ready to ship except billing: three tests fail on mixed discounts, and one migration can’t be undone."
      findings={findings}
      notComputed={[{ section: "User impact", reason: "needs session analytics, which isn’t connected for Production" }]}
    />
  )
}
```

## <InsightLedger>

Props:

- `state: "not-run" | "partial" | "ready"`: not-run before the checks have run; partial when some sections couldn't be computed (listed in `notComputed`); ready otherwise.
- `headline?: string | undefined`: One or two sentences, from the report's own findings.
- `findings?: Finding[] | undefined` (default `[]`): The report's findings; counted by severity, and the three most severe are shown.
- `notComputed?: { section: string; reason: string }[] | undefined` (default `[]`): Sections that couldn't be computed, and why.
- `className?: string | undefined`

## Strings (`insightLedger`)

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

- `notRun`: No summary yet. It’s written once the report’s checks have run.
- `summaryOfFindings`: Summary of findings
- `summary`: Summary
- `countCritical`: critical
- `countSerious`: serious
- `countWarning`: warning
- `countInfo`: note
- `critical`: Critical
- `serious`: Serious
- `warning`: Warning
- `info`: Note
- `notComputed`: Not computed

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