<!-- Generated by scripts/ax-docs.mts from the JSDoc in registry/ouro/ax/. Do not edit; run `pnpm run docs`. -->

# ax-precise-copy

A failure says what happened and precisely why (the system and its answer: "The mail service says this file was deleted"), who or what caused it where that is known, and the next step as a working action. "Couldn't show this picture" leaves the agent guessing at the cause and at what to tell the person. When the cause is unknown, the message says what was tried and what came back.

Vague: "couldn't", "could not", "something went wrong", "unable to", "failed to load", "an error occurred", and a text that is only a bare "Error" or "Upload failed", unless the cause follows the phrase in the same sentence ("Couldn't send: you're offline. Try again when you're back online.", "… because …"; not "Couldn't send: try again"). A negation or an action before the word ("No errors", "Retry failed") passes. The source rules kit (ouro-source-rules) keeps the identical list for an app's UI copy; change both together. A text that is precise and still holds a phrase ("The card service says your card could not be charged. Use another card.") goes on an allow-list, each entry with its reason.

```sh
npx shadcn@latest add ourostack/ouro-ui/ax-precise-copy#v1.3.10
```

It installs `lib/ouro/ax/precise-copy.ts`. Its tests are `ax-precise-copy-tests`. Every item runs on Node 22.18 or later as it is copied: the files import each other as `./<file>.ts`. The [Ouro AX guide](ax.md) shows how they fit together.

## Exports

### `BARE_FAILURE`

A bare failure: the whole text is "error" or "failed" (or "failure"), at most two words before it, or "Error:" with nothing after.

```ts
const BARE_FAILURE: RegExp
```

### `CAUSE_MARKER`

What marks a failure's cause after the phrase, in the same sentence: a colon, a dash or "because".

```ts
const CAUSE_MARKER: RegExp
```

### `checkFailureCopyAllow`

An allow-list read from JSON, checked: a list of `{ match, reason }`, each with a non-empty `match` and a `reason`. Throws naming each entry that is not one, with the fix.

```ts
function checkFailureCopyAllow(value: unknown): FailureCopyAllow[]
```

Example:

```ts
checkFailureCopyAllow([{ match: "could not be charged", reason: "names the card service and its answer" }]);
```

### `FAILURE_KEYS`

The fields of an answer that speak to the agent or the person: a refusal's or an outcome's `error`, `human` (its `reason` and `resume`), next steps and fixes, and in an Ouro AX answer (one with an `ax` field: an outcome, a checks report) its `summary` and each finding's `detail`.

```ts
const FAILURE_KEYS: ReadonlySet<string>
```

### `FailureCopyAllow`

A failure says what happened and precisely why (the system and its answer: "The mail service says this file was deleted"), who or what caused it where that is known, and the next step as a working action. "Couldn't show this picture" leaves the agent guessing at the cause and at what to tell the person. When the cause is unknown, the message says what was tried and what came back.

Vague: "couldn't", "could not", "something went wrong", "unable to", "failed to load", "an error occurred", and a text that is only a bare "Error" or "Upload failed", unless the cause follows the phrase in the same sentence ("Couldn't send: you're offline. Try again when you're back online.", "… because …"; not "Couldn't send: try again"). A negation or an action before the word ("No errors", "Retry failed") passes. The source rules kit (ouro-source-rules) keeps the identical list for an app's UI copy; change both together. A text that is precise and still holds a phrase ("The card service says your card could not be charged. Use another card.") goes on an allow-list, each entry with its reason.

```ts
interface FailureCopyAllow {
  match: string;
  reason: string;
}
```

### `LEAD_FAILURE`

A failure that leads the text ("Error: …", "Upload failed - …"), held to the same test as a phrase; the group is the marker.

```ts
const LEAD_FAILURE: RegExp
```

### `NOT_A_CAUSE`

First words that make the words after a marker a next step ("try again") or a vague word ("error") in place of a cause.

```ts
const NOT_A_CAUSE: readonly string[]
```

### `NOT_BARE_LEADS`

Words before "error" or "failed" that make the text other than a failure: a negation ("No errors") or an action ("Retry failed").

```ts
const NOT_BARE_LEADS: readonly string[]
```

### `statesCause`

Whether the text after a failure phrase states the cause in the same sentence: after a colon, a dash or "because", a substitution (`${…}`) or at least two words whose first is not in `NOT_A_CAUSE`, with no vague phrase in it.

```ts
function statesCause(rest: string): boolean
```

Example:

```ts
statesCause(" send: you're offline. Try again later."); // true
statesCause(" send: try again."); // false
```

### `VAGUE_FAILURE_PHRASES`

A phrase's name, then its pattern.

```ts
const VAGUE_FAILURE_PHRASES: readonly (readonly [string, RegExp])[]
```

### `VagueFailureFinding`

```ts
interface VagueFailureFinding {
  phrase: string;
  where: string;
  text: string;
  allowed: FailureCopyAllow | null;
}
```

### `vagueFailureIn`

The vague failure phrase in a message, by its name, or null when there is none or an allow-list entry lets it through. A text that is only "Error" or "Upload failed" is "bare error" or "bare failed".

```ts
function vagueFailureIn(text: string, allow?: readonly FailureCopyAllow[]): string | null
```

Example:

```ts
vagueFailureIn("Couldn't show this picture"); // "couldn't"
vagueFailureIn("The photo service says this picture was deleted. Ask its owner to share it again."); // null
```

### `vagueFailuresIn`

Every vague failure message in a value: a message, a `help --json`, an outcome, a refusal or a checks report. A finding an allow-list entry lets through carries the entry. With `messagesOnly`, only what is under `FAILURE_KEYS`, and an Ouro AX answer's `summary` and `detail`; a `code` is never read.

```ts
function vagueFailuresIn(value: unknown, options?: VagueFailuresOptions): VagueFailureFinding[]
```

Example:

```ts
vagueFailuresIn({ ax: "outcome/1", state: "failed", summary: "Not sent", error: { code: "send_failed", message: "Something went wrong" } }, { messagesOnly: true });
// [{ phrase: "something went wrong", where: "error.message", text: "Something went wrong", allowed: null }]
```

### `VagueFailuresOptions`

```ts
interface VagueFailuresOptions {
  messagesOnly?: boolean;
  allow?: readonly FailureCopyAllow[];
}
```
