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

# VerificationResult: Post-Action State Verification Object

> Reference for the VerificationResult object — how NSP evaluates a verify_expression after action dispatch and what the outcome fields mean.

The `VerificationResult` object gives you deterministic confirmation that an action had its intended effect in application state, rather than requiring you to trust an HTTP 200 alone. When you set `verify: true` on a `POST /action` request, NSP waits a short settling period after dispatch, then polls the post-action substrate state and evaluates your `verify_expression` against it in a loop until the expression becomes `true` or a timeout is reached. The `VerificationResult` captures the outcome of that loop — whether the expression was satisfied, the value it computed, and when the final evaluation occurred. You receive this object nested inside an [`ActionResponse`](/models/action-response) and you can also trigger standalone verification via `POST /verify`.

<ResponseField name="satisfied" type="boolean" required>
  `true` when `verify_expression` evaluated to a truthy value within the allowed polling window. `false` when the expression remained falsy for every poll cycle until `verify_timeout_ms` was reached. A `satisfied: false` result causes NSP to return `HTTP 422 Unprocessable Entity` on the parent `POST /action` call.
</ResponseField>

<ResponseField name="actual_value" type="any" required>
  The computed value of `verify_expression` at the poll cycle that ended polling. When `satisfied: true` this is the value that passed the truthiness check — most commonly the boolean `true` from a comparison expression, but it can be any truthy value such as a positive integer or a non-empty string. When `satisfied: false` this is whatever the expression last evaluated to, which helps you diagnose why the expression did not pass.
</ResponseField>

<ResponseField name="expression" type="string" required>
  The exact `verify_expression` string that was evaluated, echoed back from the request. Useful when logging verification outcomes or constructing debug messages.
</ResponseField>

<ResponseField name="evaluated_at" type="string" required>
  ISO 8601 UTC timestamp of when the final evaluation cycle ran — either the cycle that satisfied the expression (when `satisfied: true`) or the last cycle before the timeout (when `satisfied: false`).
</ResponseField>

<ResponseField name="latency_ms" type="integer" required>
  Total time in milliseconds spent in the post-action polling loop, measured from after the initial settling delay through to the final poll cycle. Does not include the action dispatch time itself — for total request latency, see `ActionResponse.latency_ms`.
</ResponseField>

***

## JSON Example — Satisfied

```json theme={null}
{
  "satisfied": true,
  "actual_value": true,
  "expression": "inbox.sent_count > 0",
  "evaluated_at": "2026-07-20T13:00:00.280Z",
  "latency_ms": 280
}
```

## JSON Example — Not Satisfied (Timeout)

```json theme={null}
{
  "satisfied": false,
  "actual_value": false,
  "expression": "inbox.sent_count > 14",
  "evaluated_at": "2026-07-20T13:00:05.000Z",
  "latency_ms": 5000
}
```

***

## How Verification Works

After NSP dispatches your action to the target runtime, it does not return immediately. Instead it runs a polling loop against the probe:

1. **Settling wait** — NSP pauses briefly (default: 200 ms) to let UI animations and asynchronous backend writes settle before the first probe cycle.
2. **Poll cycle 1** — NSP captures a fresh state snapshot and evaluates your expression against `objects`. If the expression is truthy, verification passes and the response is returned immediately with `satisfied: true`.
3. **Poll cycle N** — If the expression is falsy, NSP waits for the next probe tick and evaluates again. This repeats until either the expression passes or `verify_timeout_ms` is reached.
4. **Timeout** — If the timeout expires with the expression still falsy, NSP returns `satisfied: false` and the parent `POST /action` response carries `HTTP 422 Unprocessable Entity`.

## Expressions

Expressions are evaluated against the post-action `objects` map using a lightweight, safe evaluator. Reference any dot-notation state key directly by name:

```
inbox.sent_count > 14
inbox.emails[0].is_read == true
flight.mode == 'GUIDED'
compose.is_open == false
```

Compound expressions with `&&` and `||` are supported. Expressions may not call functions, import modules, or access any scope outside the `objects` map. Maximum expression length is 2048 bytes.

## HTTP 422 on `satisfied: false`

When verification is requested and the expression is not satisfied within the timeout, NSP returns `HTTP 422 Unprocessable Entity` — not `HTTP 200`. This is intentional: a `2xx` status code is reserved for outcomes NSP can positively confirm. A `422` means the action was dispatched but the expected state change was not observed in time. The body still contains the full `ActionResponse` (with `success: false`) so you can inspect `verification.actual_value` and decide whether to retry, increase `verify_timeout_ms`, or revise the expression.

Treat a `422` as an **indeterminate** outcome, not a definitive failure. The action may have succeeded on the application side but the probe did not see the change within the window — for example, a slow network reply or a deferred server write may land after the timeout. Inspect `GET /state` directly before deciding to retry.
