> ## Documentation Index
> Fetch the complete documentation index at: https://hibi.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Hibi Resolvers: Extend Drift Detection in Any Language

> External resolvers grade anchor kinds, run verifiers, or attach advisories over JSONL-RPC on stdio. They are off until listed in .claims/resolvers.json.

A **resolver** is a program that grades an anchor, runs a verifier, or attaches advisory notes to a verdict. The built-in drift resolver runs **in-process** and does not speak the wire protocol. External resolvers run out-of-process and talk to the engine over JSONL-RPC on stdin and stdout.

## Roles

| Role                         | Method    | Effect                                                                                               |
| ---------------------------- | --------- | ---------------------------------------------------------------------------------------------------- |
| Anchor grader (non-advisory) | `resolve` | Produces the verdict for the anchor kinds it declares. May gate.                                     |
| Verifier runner              | `verify`  | Runs a verifier and returns `supported` or `refuted`. Dispatched only under `check --run-verifiers`. |
| Advisor (`advisory: true`)   | `resolve` | Attaches `advisories` to a verdict. Never changes a state, never gates.                              |

There is no built-in supersession resolver and no semantic advisor; supersession is an engine operation (`hibi supersede`).

## The protocol

Newline-delimited JSON-RPC, one object per line. Three methods:

<ParamField path="describe" type="method">
  Returns `{ name, version, kinds, tier, advisory, verifierKinds? }`. The engine calls it first and routes work only to a resolver that claimed it.
</ParamField>

<ParamField path="resolve" type="method">
  Params: `{ assertion, files: { doc, code: { path: content } }, proposition? }`. Returns `{ verdict?, advisories? }`. The engine reads the files; the resolver never touches the filesystem.
</ParamField>

<ParamField path="verify" type="method">
  Params: `{ assertion, verifier, changedEvidence }`. No file contents are sent. Returns `{ behavior: "supported" | "refuted", advisories?, notes? }`; `advisories` and `notes` default to empty. An error response, a timeout, or a spawn failure counts as no result.
</ParamField>

Print any message schema with `hibi schema --name <Name>` (for example `ResolveParams`, `VerifyParams`, `Verdict`). `hibi schema` with no name lists the names. The schemas in `schemas/*.v3.json` are generated from the Zod model.

## Enabling a resolver

The manifest is default-deny. A resolver not listed in `.claims/resolvers.json` is never launched.

```json theme={null}
{
  "resolvers": [
    {
      "name": "my-grader",
      "command": "bun",
      "args": ["run", "resolvers/my-grader.ts"],
      "timeoutMs": 5000
    }
  ]
}
```

| Field                     | Default         | Meaning                                                 |
| ------------------------- | --------------- | ------------------------------------------------------- |
| `name`, `command`, `args` |                 | How to spawn it.                                        |
| `timeoutMs`               | `5000`          | Per-request timeout; a slow resolver is killed.         |
| `kinds`                   | from `describe` | Optional explicit allow-list of anchor kinds.           |
| `override`                | `false`         | Allow a non-advisory resolver to claim a built-in kind. |
| `modelBacked`             | `false`         | The resolver's advisories are produced by a model.      |

### `override`

The built-in kinds are `text-quote`, `text-position`, `ast-node`, `value`, and `coarse`. A non-advisory external resolver that claims one of them replaces the deterministic core verdict for every anchor carrying that kind. That is refused by default: without `"override": true` on the manifest entry, the built-in kinds are dropped from the resolver's list with a warning on stderr. An advisory resolver may declare any kinds; it never produces a verdict.

### Provenance for model-backed advisors

An advisory from a `modelBacked` resolver must carry `provenance: { model, promptHash, contextHash, params? }`. The registry drops advisories without it and prints one warning per run per resolver.

## Verifier kinds and the built-in command runner

A verifier's `kind` is an open string matched against the `verifierKinds` a runner declares. The built-in runner handles `command`: it executes `ref` as a shell command from the repository root. Exit `0` is `supported`, non-zero is `refuted`, a timeout or spawn failure is no result. The default timeout is 120 seconds, set with `--verifier-timeout <seconds>`.

<Warning>
  Verifiers execute repo-committed commands. They run only under `check --run-verifiers`. `check` without that flag, `list`, and `coverage` never spawn a verifier. External runners also require the manifest.
</Warning>

## Writing your own

Import the server from the main package:

```ts theme={null}
import { serveResolver } from "@npupko/hibi/resolver";

serveResolver({
  describe: () => ({
    name: "my-grader", version: "1", kinds: ["my-kind"], tier: 2, advisory: false,
  }),
  resolve: ({ assertion, files }) => ({ verdict: grade(assertion, files) }),
});
```

`serveResolver` owns the framing and dispatch. The same module exports the protocol types (`ResolveParams`, `ResolveResult`, `VerifyParams`, `VerifyResult`, `DescribeResult`) and the model types (`Assertion`, `Verdict`, `Selector`, and the rest). A resolver in another language reads requests on stdin, writes responses on stdout, and validates against `hibi schema`.

## Where to go next

<CardGroup cols={2}>
  <Card title="SDK" icon="cube" href="/sdks">
    The `@npupko/hibi/resolver` export.
  </Card>

  <Card title="Behavioral claims" icon="flask-vial" href="/behavioral">
    Where `verify` fits.
  </Card>
</CardGroup>
