---
title: "Inspect a project"
description: "Read-only SDK entry points behind doctor, check and diff, plus the integrity checks and the lock and provenance state, none of which writes a file."
type: "reference"
---
# Inspect a project

Read-only SDK entry points behind doctor, check and diff, plus the integrity checks and the lock and provenance state, none of which writes a file.

## Inspect state without writing [#inspect-state-without-writing]

None of these translate or mutate the lock. Only `extract` writes a file (the source catalog), and
only `doctor` with `live` makes a network request (the provider's language list).

### doctor [#doctor]

<AvailableFrom version="0.9.0" />

Validates the project setup and spends nothing: it constructs no provider and makes no network
request unless `live` asks for one, and reads the API key value only for that one language-list
request (LibreTranslate gets no key). Every check runs even when an earlier one failed, so one call
reports every independent problem; [`verbatra doctor`](https://verbatra.kreitz-webdev.de/docs/cli/doctor.md#what-it-checks) lists the
checks.

```ts title="Signature"
function doctor(
  input?: DoctorInput,
  deps?: DoctorDeps,
): Promise<DoctorResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `cwd` | `string` | no | Directory to search the config from. Defaults to the process working directory. Locale paths resolve against the project root resolveProjectRoot returns: the directory of a config found by the search, otherwise this directory. |
| `configPath` | `string` | no | An explicit config file to validate, bypassing the search. A missing file is an error rather than a failed check. |
| `literals` | `boolean` | no | Run the untranslated-literal scan instead of the setup checks: the config is loaded, then the source roots of its `extract` block are scanned for hardcoded user-facing string literals. No other setup check runs (`format-adapter`, `provider`, `api-key`, `network-policy`, `source-file`, `plural-rules`, `plural-completeness`, `locale-codes`, `locale-state`, `locales`), so no API key environment variable is looked at and a run with no key set can pass. |
| `dataFlow` | `boolean` | no | Describe where the project's data goes instead of running the setup checks: the config is loaded and DoctorResult.dataFlow carries the DataFlowManifest dataFlow builds. Only the `config` and `data-flow` checks run, no API key is read and no network request is made. Takes precedence over DoctorInput.live; ignored when DoctorInput.literals is set. |
| `live` | `boolean` | no | Fetch the configured machine-translation provider's current language list before the `locales` check, instead of judging against the table verbatra ships. It is the one doctor option that sends a network request: to the provider's language list endpoint only (DeepL's `/v3/languages`, Google Cloud Translation's `languages`, or the `languages` endpoint of the configured LibreTranslate server), which uses no translation quota. For DeepL and Google Cloud Translation the request is sent only when the provider's API key variable is set, while LibreTranslate needs no key variable; in every case it is sent only when the network policy permits the provider's host; otherwise, or when the request fails, the static table is used and LocaleCapabilityReport.live says why. It does nothing for an LLM provider or `none`. Ignored on a literal run. Defaults to false. |
| `onProgress` | `ScanProgressListener` | no | Called once after each application source file the `literals` scan reads, with the running count and the total, for progress reporting. |

**Returns:** `DoctorResult`

**Throws:** [`CONFIG_NOT_FOUND`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#config_not_found)

<AvailableFrom version="0.12.0" />

The `network-policy` check fails when the effective [network policy](https://verbatra.kreitz-webdev.de/docs/network-policy.md) refuses
the provider's host or proxy, or a network variable is invalid, and passes for the `none` provider.
The informational checks never fail and rename nothing; a `warn` leaves `ok` true, and the
[check table](https://verbatra.kreitz-webdev.de/docs/cli/doctor.md#what-it-checks) says what each names and when it is `skipped`.

<AvailableFrom version="0.12.0" />

The `locales` check judges every configured locale as `translate` does before it spends: it fails
on an unsupported locale, is `skipped` for `none`, and returns the verdicts in
`DoctorResult.locales` as a `LocaleCapabilityReport`. With `live: true` it first fetches the
provider's current language list, using no quota; `LocaleCapabilityReport.live` says how that went.
See [Language support](https://verbatra.kreitz-webdev.de/docs/language-support.md#checking-support-before-a-run).

With `literals` set, only the `config` and `untranslated-literals` checks run, as
[`verbatra doctor --literals`](https://verbatra.kreitz-webdev.de/docs/cli/doctor.md#untranslated-literals) does. `doctor` loads the
config itself, so a project with no config gets a report, not a thrown error: `ok` is true exactly
when no check failed, and `CONFIG_NOT_FOUND` is thrown only for an explicit `configPath` that does
not exist.

<AvailableFrom version="0.12.0" />

Only a failed check carries `fix`, one imperative next step; like `detail`, it names variables and
paths, never a key value.

### dataFlow [#dataflow]

<AvailableFrom version="0.12.0" />

Describes where a project's data goes, for the loaded config, as a versioned `DataFlowManifest`. [`verbatra doctor --data-flow`](https://verbatra.kreitz-webdev.de/docs/cli/doctor.md#data-flow) prints it and lists its fields; `doctor({ dataFlow: true })` returns it as `DoctorResult.dataFlow`. It reads no API key and makes no network request. An invalid network variable or an unreadable source file is reported in the manifest rather than thrown.

```ts title="Signature"
function dataFlow(
  input?: DataFlowInput,
  deps?: DataFlowDeps,
): Promise<DataFlowManifest>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `cwd` | `string` | no | Directory to search the config from. Defaults to the process working directory. Every path resolves against the project root resolveProjectRoot returns: the directory of a config found by the search, otherwise this directory. |
| `configPath` | `string` | no | An explicit config file to describe, bypassing the search. |

**Returns:** `DataFlowManifest`

**Throws:** [`CONFIG_NOT_FOUND`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#config_not_found), [`CONFIG_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#config_invalid)

### dataFlowManifestSchema [#dataflowmanifestschema]

<AvailableFrom version="0.12.0" />

The zod schema for a `DataFlowManifest`, so a CI step or a reviewer's tooling can validate one. Unknown fields are kept, since a newer verbatra may add fields within version 1; ignore the ones you do not know. `DATA_FLOW_MANIFEST_VERSION` is the `version` this build writes.

```ts title="Signature"
const dataFlowManifestSchema: z.ZodType<DataFlowManifest>;
```

### extract [#extract]

<AvailableFrom version="0.11.0" />

Scans your application source for translation call sites and merges what it finds into the source
locale catalog, even one that does not exist yet. It constructs no provider, reads no API key, and
makes no network request.

```ts title="Signature"
function extract(
  input: ExtractInput,
  deps?: ExtractDeps,
): Promise<ExtractResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | A resolved config whose `extract` block names the framework and the source roots. |
| `cwd` | `string` | no | Directory the roots and locale paths are resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `dryRun` | `boolean` | no | Report what would be added without writing anything. |
| `onProgress` | `ScanProgressListener` | no | Called once after each application source file the scan reads, with the running count and the total, for progress reporting. |

**Returns:** `ExtractResult`

**Throws:** [`EXTRACT_NOT_CONFIGURED`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#extract_not_configured), [`EXTRACT_FS_UNSUPPORTED`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#extract_fs_unsupported), [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid), [`SOURCE_UNWRITABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unwritable)

**Example:** [Extract keys from your source code](https://verbatra.kreitz-webdev.de/docs/programmatic-api.md#extract-keys-from-your-source-code)

Only genuinely new keys are added ([What it writes](https://verbatra.kreitz-webdev.de/docs/cli/extract.md#what-it-writes)). What the
scan cannot resolve comes back as data in `dynamic`, `conflicts`, and `diagnostics`, never thrown
([What it reports](https://verbatra.kreitz-webdev.de/docs/cli/extract.md#what-it-reports-instead-of-guessing)), and the result never
carries a source file's contents.

`config.extract` names the framework and the source roots. Discovery needs the optional
`readDirectory` member of `SdkFs`; without it, `EXTRACT_FS_UNSUPPORTED`.

### check [#check]

<AvailableFrom version="0.4.0" />

Reports per-locale drift as counts: `missing` (in source, absent from target), `stale` (source
changed since last translated), and `upToDate`. Use it as a CI gate.

```ts title="Signature"
function check(
  input: CheckInput,
  deps?: CheckDeps,
): Promise<CheckSummary>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` is resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `locales` | `readonly string[]` | no | Restrict the report to these target locales. Defaults to every configured target locale. |
| `consistency` | `boolean` | no | Also report, per locale, every source string translated more than one way under different keys (see LocaleCheckSummary.inconsistencies). Defaults to false. |
| `qa` | `boolean` | no | Also run the quality check over every committed value (see LocaleCheckSummary.qa): the write-time integrity gate, whose refusals are reported as errors, and the review reasons a translation run computes, reported as warnings. Keyless: no provider is called and nothing is written. Defaults to false. |
| `qaSeverity` | `"error" \| "warning"` | no | The lowest severity the quality check reports. `error` skips the review reasons entirely, so only integrity failures are reported. Ignored unless CheckInput.qa is true. Defaults to `warning`. |
| `requireReviewed` | `boolean` | no | Also run the review gate (see CheckSummary.review): every value written by a machine-class path (see MACHINE_CLASS_ORIGINS) must be approved in the provenance file. A value a person wrote, imported, or edited outside verbatra needs no approval, and neither does one with no provenance record. An approval given against a source text that has changed since does not count. Keyless: no provider is called and nothing is written. Defaults to false. |
| `sensitive` | `boolean` | no | Also scan the source file and the glossary of every reported locale for content that looks sensitive (see CheckSummary.sensitive), with the config's `sensitiveData` detectors, patterns and allow list, or the default detectors when the block is absent. It scans every field a language model would receive, whatever the configured provider and `sensitiveData.mode`. Keyless: no provider is called and nothing is written. Defaults to false. |

**Returns:** `CheckSummary`

**Throws:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid), [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#lock_file_invalid), [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_locale)

**Example:** [Check in CI without writing](https://verbatra.kreitz-webdev.de/docs/programmatic-api.md#check-in-ci-without-writing)

`inSync` is true exactly when every checked locale has nothing missing and nothing stale.

<AvailableFrom version="0.11.0" />

With `consistency: true`, each `LocaleCheckSummary` also carries `inconsistencies`: one
`InconsistencyGroup` per source string the locale translates more than one way under different
keys, in the shape the [consistency report](https://verbatra.kreitz-webdev.de/docs/cli/check.md#consistency-report) shows. It is a
report only: it never changes `inSync`, a count, or any file.

<AvailableFrom version="0.12.0" />

Each `LocaleCheckSummary` also carries `provenance`: counts `byOrigin` and `byReviewState` over the
keys the locale has a value for, read from `verbatra.provenance.json`
([origins](https://verbatra.kreitz-webdev.de/docs/the-lock-file.md#provenance-who-wrote-each-value)). This and every other provenance
field in a report is left out, never an error, when the file is corrupt or from a newer verbatra.

<AvailableFrom version="0.12.0" />

Each `LocaleCheckSummary` also carries `protected`, the share of `stale` a `translate` run would leave for a person under `humanEdits` and `pinnedKeys` ([Protected keys](https://verbatra.kreitz-webdev.de/docs/cli/check.md#protected-keys)). They still count as stale, so `inSync` stays false until a person resolves them; a missing pinned key counts only as missing.

<AvailableFrom version="0.12.0" />

With `qa: true`, `check` also runs the [quality check](https://verbatra.kreitz-webdev.de/docs/cli/check.md#quality-check) over every
committed value, keyless and without writing: each `LocaleCheckSummary` carries a `qa` report and
the summary `qa` totals, in that section's shapes. Error reasons come from `INTEGRITY_GATE_REASONS`,
warning reasons from `REVIEW_REASON_CODES`, severities from `QA_SEVERITIES`; `qaSeverity: "error"`
skips warnings. It never changes `inSync`: a CI gate reads `qa.errors`, plus `qa.warnings` when strict.

<AvailableFrom version="0.12.0" />

Each `LocaleCheckSummary` also carries `incompletePlurals`, ordered by key: one `IncompletePlural`
`{ code: "PLURAL_CATEGORIES_INCOMPLETE", key, argument?, ruleType, missing }` per plural lacking CLDR
categories the target language uses. A warning only;
[plural categories](https://verbatra.kreitz-webdev.de/docs/cli/check.md#plural-categories) lists the formats and rules.

With `requireReviewed: true`, `check` also runs the
[review gate](https://verbatra.kreitz-webdev.de/docs/cli/check.md#require-reviewed-translations), keyless and without writing: each
`LocaleCheckSummary` carries `review: { unreviewed }`, the machine-class keys not approved, and the
summary carries `review: { reviewed, unreviewed, code? }` with the codes that section names. The
report never changes `inSync`; a CI gate reads `review.reviewed`.

<AvailableFrom version="0.12.0" />

With `sensitive: true`, `check` also runs the [sensitive content](https://verbatra.kreitz-webdev.de/docs/cli/check.md#sensitive-content)
scan, keyless and without writing: the summary carries `sensitive: { findings, glossaryTerms }`, one
`{ key, fields, detectors }` per flagged key, never the matched text. A CI gate fails on either.

### checkFile [#checkfile]

<AvailableFrom version="0.12.0" />

Checks one locale file right after a person or an agent edited it. It reads only that file and,
for a target locale, the source file; it calls no provider, reads no API key, and writes nothing.

```ts title="Signature"
function checkFile(
  input: CheckFileInput,
  deps?: CheckFileDeps,
): Promise<CheckFileSummary>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` and CheckFileInput.file are resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `file` | `string` | yes | The locale file to check, absolute or relative to the working directory. |
| `qaSeverity` | `"error" \| "warning"` | no | The lowest severity to report. `error` skips the review reasons, so only syntax and integrity failures are reported. Defaults to `warning`. |

**Returns:** `CheckFileSummary`

**Throws:** [`NOT_A_LOCALE_FILE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#not_a_locale_file), [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid)

`file` is absolute or relative to `cwd`; [One file](https://verbatra.kreitz-webdev.de/docs/cli/check.md#one-file) shows the
`CheckFileSummary` shape. A target file is checked like `check` with `qa: true`, the source file for
syntax alone. A file that does not parse is not thrown: its locale carries one `QaSyntaxFinding`,
with the position `AdapterError.position` reports for JSON and YAML. A path that is no configured
locale's file, or a missing file, throws `NOT_A_LOCALE_FILE`.

### diff [#diff]

<AvailableFrom version="0.4.0" />

The detailed sibling of `check`: the same computation, but it returns the key lists per locale
(`missing`, `changed`, `orphaned`) instead of counts. Orphaned keys are report-only and never flip
`hasPendingChanges`, since a default run does not prune.

```ts title="Signature"
function diff(
  input: DiffInput,
  deps?: DiffDeps,
): Promise<DiffSummary>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` is resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `locales` | `readonly string[]` | no | Restrict the report to these target locales. Defaults to every configured target locale. |
| `unused` | `boolean` | no | Also scan the application source configured in the `extract` block and report the source-catalog keys nothing references, as DiffSummary.unused. Off by default. |
| `onProgress` | `ScanProgressListener` | no | Called once after each application source file the `unused` scan reads, with the running count and the total, for progress reporting. |

**Returns:** `DiffSummary`

**Throws:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid), [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#lock_file_invalid), [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_locale)

**Example:** [Check in CI without writing](https://verbatra.kreitz-webdev.de/docs/programmatic-api.md#check-in-ci-without-writing)

With `unused: true` it also scans the config's `extract` roots, read-only and keyless, and adds an
`unused` report of the source-locale keys no static reference names, separate from every `orphaned`
list and never flipping `hasPendingChanges`; [Unused source keys](https://verbatra.kreitz-webdev.de/docs/cli/diff.md#unused-source-keys)
explains its fields.

<AvailableFrom version="0.12.0" />

Each `LocaleDiff` also carries `changedOrigins`, the origin of each `changed` key's current value
(such as `machine`, `human`, or `external`): whose work a retranslation would replace.

<AvailableFrom version="0.12.0" />

Each `LocaleDiff` also carries `protected`, the missing and changed keys a `translate` run would leave alone, sorted; they still count as pending.

### keyIntegrity [#keyintegrity]

<AvailableFrom version="0.5.0" />

Reports, for each locale's changed keys, whether the current target value still matches the
source's placeholders and inline markup and is valid ICU: each entry carries `key`,
`hasPlaceholders`, `matches`, the `missing` and `extra` tokens on a mismatch, `icuValid`,
`markupMatches`, and `markupDetails`, never a string value. Values written before the write-time gate
existed or edited outside verbatra are judged the same. Studio surfaces this per-key report.

```ts title="Signature"
function keyIntegrity(
  input: KeyIntegrityInput,
  deps?: KeyIntegrityDeps,
): Promise<readonly LocaleKeyIntegrity[]>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` is resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `locales` | `readonly string[]` | no | Restrict the report to these target locales. Defaults to every configured target locale. |
| `keys` | `readonly string[]` | no | Restrict the report to these keys. Each must exist in the source resource. Only keys the diff reports as changed are ever judged, so a requested key whose translation is missing or up to date is left out rather than reported. Defaults to every changed key. |

**Returns:** `readonly LocaleKeyIntegrity[]`

**Throws:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid), [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#lock_file_invalid), [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_locale), [`UNKNOWN_KEY`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_key)

<AvailableFrom version="0.12.0" />

Each entry also carries `icuArmsMatch` and `icuArmDetails`: whether the value's ICU `plural`,
`selectordinal`, and `select` arms fit the target language, judged as the
[write-time gate](https://verbatra.kreitz-webdev.de/docs/translation-safety.md#plural-arms-per-target-language) judges them, with one
short problem per wrong arm. `icuArmsMatch` is always true for a format that does not check arms.

`keys` narrows the check; only keys that are "changed" for a locale are ever checked.

### localeIntegrity [#localeintegrity]

<AvailableFrom version="0.12.0" />

Finds every translation in the target locales that is broken right now: a lost or added
placeholder or inline markup, invalid ICU, or ICU arms that do not fit the target language. Unlike
`keyIntegrity`, it judges every key present in both the source and a target locale, whatever its
sync state, by the same rules, and returns only failing keys: an empty `entries` list means the
locale passes.

```ts title="Signature"
function localeIntegrity(
  input: LocaleIntegrityInput,
  deps?: LocaleIntegrityDeps,
): Promise<readonly LocaleKeyIntegrity[]>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` is resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `locales` | `readonly string[]` | no | Restrict the report to these target locales. Defaults to every configured target locale. |

**Returns:** `readonly LocaleKeyIntegrity[]`

**Throws:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid), [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_locale)

Each call reads and parses the source and each requested target file fresh, with no cache.

### lockState [#lockstate]

<AvailableFrom version="0.5.0" />

Reports the lock file's existence, version, and per-locale drift (baseline key count plus missing,
stale, and up-to-date counts). `exists` comes from an explicit probe, so an absent and an empty lock
file stay distinguishable; when absent, the result is `{ exists: false }` and nothing else is read.

```ts title="Signature"
function lockState(
  input: LockStateInput,
  deps?: LockStateDeps,
): Promise<LockStateResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` is resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `locales` | `readonly string[]` | no | Restrict the report to these target locales. Defaults to every configured target locale. |

**Returns:** `LockStateResult`

**Throws:** [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_locale), [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#lock_file_invalid), [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid)

Each locale also carries the same `provenance` counts `check` reports.

### loadLockFile [#loadlockfile]

<AvailableFrom version="0.5.0" />

Reads the lock file itself (`verbatra.lock.json`, also exported as `LOCK_FILE_NAME`) and returns
its parsed shape: `{ version, locales }`, where each locale maps keys to the source content hash
they were last translated from. A missing file degrades to an empty lock, the same first-run
behavior `translate` relies on; use `lockState` when you need to distinguish absence.

```ts title="Signature"
function loadLockFile(
  input?: LoadLockFileInput,
  deps?: LoadLockFileDeps,
): Promise<LockFile>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `cwd` | `string` | no | Directory holding the lock-file. Defaults to the process working directory, even when the config was found in a parent directory: pass the root resolveProjectRoot returns. |

**Returns:** `LockFile`

**Throws:** [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#lock_file_invalid)

No config needed.

### loadProvenance [#loadprovenance]

<AvailableFrom version="0.12.0" />

Reads the provenance file itself (`verbatra.provenance.json`, also exported as
`PROVENANCE_FILE_NAME`) and returns its stored shape: `{ version, locales }`, where each locale maps
keys to a record `{ origin, provider?, model?, valueHash, reviewState?, reviewer?, reviewedSourceHash? }`, with no
translated text. A missing file, or one from a newer verbatra, reads as empty; a corrupt one
throws `PROVENANCE_FILE_INVALID`. `keyValue`, `localeValues`, `check`, `diff`, and `lockState`
report the interpreted view (`KeyProvenance`), which also tells `unrecorded` from `external`.

```ts title="Signature"
function loadProvenance(
  input?: LoadProvenanceInput,
  deps?: LoadProvenanceDeps,
): Promise<ProvenanceFile>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `cwd` | `string` | no | Directory holding the provenance file. Defaults to the process working directory, even when the config was found in a parent directory: pass the root resolveProjectRoot returns. |

**Returns:** `ProvenanceFile`

**Throws:** [`PROVENANCE_FILE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#provenance_file_invalid)

No config needed.

### runStatus [#runstatus]

<AvailableFrom version="0.5.0" />

Reads the review-flag and token-usage snapshot the most recent non-dry-run `translate` or `watch`
run persisted to `.verbatra-local/run-status.json`. Never throws: an unusable file
degrades to `available: false`. The file is best-effort telemetry, not a correctness baseline.

```ts title="Signature"
function runStatus(
  input?: RunStatusInput,
  deps?: RunStatusDeps,
): Promise<RunStatusResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `cwd` | `string` | no | Directory holding the `.verbatra-local` status directory. Defaults to the process working directory, even when the config was found in a parent directory: pass the root resolveProjectRoot returns. |

**Returns:** `RunStatusResult`

No config needed. Returns `{ available: false, reason }` (see `RUN_STATUS_UNAVAILABLE_REASONS`)
or `{ available: true, version, generatedAt, usage?, budget?, locales }`.

A snapshot from before the token budget was enforced is still read, minus a `budget` with
`supported: false` (its `tokensUsed: 0` was not a count). New snapshots add only a marker field, so
an older reader may show an estimated budget as not tracked. An unknown review reason is ignored,
and an entry left with none is dropped.

### reviewQueue [#reviewqueue]

<AvailableFrom version="0.12.0" />

Reads the review queue from the committed files: every key whose current value has a machine-class
origin (`machine`, `memory`, `fuzzy`, or `agent`, the `MACHINE_CLASS_ORIGINS` tuple) and is not
approved, per target locale, in source order. It reads the locale files, `verbatra.lock.json`, and
`verbatra.provenance.json`, so everyone on the same commit sees the same queue. A key leaves it once
its value is approved or rejected, or a person writes or imports a new value; a value an agent
rewrote stays, and so does an approval given before the source changed. The last `runStatus`
snapshot only adds detail: each entry's `reasons` (empty when the run did not flag it with a known
reason), the locale's `fuzzyHits`, and `lastRunAt`.

```ts title="Signature"
function reviewQueue(
  input: ReviewQueueInput,
  deps?: ReviewQueueDeps,
): Promise<ReviewQueueResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` is resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `locales` | `readonly string[]` | no | Restrict the queue to these target locales. Defaults to every configured target locale. |
| `includeApproved` | `boolean` | no | Also list, per locale, the machine-class values already approved (see ReviewQueueLocale.approved), for a reviewer who wants to revisit them. Defaults to false. |

**Returns:** `ReviewQueueResult`

**Throws:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_locale), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid), [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#lock_file_invalid)

**Example:** [Work through the review queue](https://verbatra.kreitz-webdev.de/docs/programmatic-api.md#work-through-the-review-queue)

Returns `{ available: true, locales, lastRunAt? }`,
each locale `{ locale, needsReview, approved?, fuzzyHits? }` and each entry `{ key, reasons, provenance }`;
`approved` lists the approved machine-class values and is present only with `includeApproved: true`.
When the provenance file is corrupt or from a newer verbatra it returns
`{ available: false, reason: "provenance-unreadable" }`. A source, target, or lock file that cannot
be read fails the call as it fails `check`. Up to 0.11 the queue was the last run's flags only.

### provenanceReport [#provenancereport]

<AvailableFrom version="0.12.0" />

Builds the per-locale report `verbatra report provenance` prints: every key with a value in both
the source and a target locale, in source order, with its origin, review state, provider, model and
reviewer, counted in one `PROVENANCE_BUCKETS` bucket
([the provenance report](https://verbatra.kreitz-webdev.de/docs/provenance-evidence.md#the-provenance-report) defines them). It calls no
provider and writes nothing.

```ts title="Signature"
function provenanceReport(
  input: ProvenanceReportInput,
  deps?: ProvenanceReportDeps,
): Promise<ProvenanceReportResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` is resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `locales` | `readonly string[]` | no | Restrict the report to these target locales. Defaults to every configured target locale. |
| `toolVersion` | `string` | no | The verbatra version to stamp on the report, as ProvenanceReport.toolVersion. Defaults to `unknown`. |

**Returns:** `ProvenanceReportResult`

**Throws:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_locale), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid), [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#lock_file_invalid)

`deps` also takes `now`, the clock for `generatedAt`. The result's full shape is
[the JSON schema](https://verbatra.kreitz-webdev.de/docs/provenance-evidence.md#the-json-schema).
When the provenance file is corrupt or from a newer verbatra it returns
`{ available: false, reason: "provenance-unreadable" }`, since every value would read as
`unrecorded`. A source, target, or lock file that cannot be read fails the call as it fails
`check`. The report is supporting evidence, not legal advice.

### provenanceReportPage [#provenancereportpage]

<AvailableFrom version="0.12.0" />

Builds the same report as `provenanceReport` and returns its entries one page at a time, optionally only those in some `buckets`, with a cursor for the next page. Every page keeps each locale's full `total` and `counts`. The MCP server's `report.provenance` pages with it. Read-only.

```ts title="Signature"
function provenanceReportPage(
  input: ProvenanceReportPageInput,
  deps?: ProvenanceReportDeps,
): Promise<ProvenanceReportPageResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `buckets` | `array` | no | List only the entries in these buckets. The counts always cover every bucket. |
| `limit` | `number` | no | The most entries the page holds, a whole number from 1 to PAGE_LIMIT_CAP. Defaults to PAGE_LIMIT_DEFAULT. |
| `cursor` | `string` | no | The `nextCursor` of the previous page. Omit it to read the first page. |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` is resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `locales` | `readonly string[]` | no | Restrict the report to these target locales. Defaults to every configured target locale. |
| `toolVersion` | `string` | no | The verbatra version to stamp on the report, as ProvenanceReport.toolVersion. Defaults to `unknown`. |

**Returns:** `ProvenanceReportPageResult`

**Throws:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_format), [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#unknown_locale), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#source_invalid), [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#lock_file_invalid), [`PAGE_CURSOR_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#page_cursor_invalid), [`PAGE_LIMIT_INVALID`](https://verbatra.kreitz-webdev.de/docs/error-codes.md#page_limit_invalid)

Each locale carries `entries` only on the pages that hold one of them. A page holds at most `limit` entries, `PAGE_LIMIT_DEFAULT` by default; pass `nextCursor` back as `cursor`, with the same `locales` and `buckets`, until it is absent. It is unavailable, or fails, exactly when `provenanceReport` is.
