Did the task happen, or just get claimed?

Outcome and policy are graded from the trace and the system of record, never from words.

eleven deterministic outcome & workflow assertion kinds
kindwhat it readsexample verdict
outcomea composite over the sub-predicates below, as a met / of fractionmet 3 / of 3 → pass
tool_callthe ingested trace spans, never the transcriptissue_refund span present → pass
tool_resulta tool’s returned value, from the tracerefund result ok → pass
tool_errora tool’s raised error, from the tracecharge raised timeout → fail
statea state adapter snapshot: the system of recordbalance shows the credit → pass
state_changea before / after delta (mock adapter)balance moved by the refund → pass
sequencean ordered set of steps across toolslookup before refund → pass
counta bounded number of occurrencesat most one refund → pass
A missing trace or state reports INCONCLUSIVE; zero spans against a populated trace is a grounded fail.
Authority 1 · trace spans

What the agent did.

tool_result and tool_error read the authenticated voice_trace. The span is the evidence a tool ran.

Authority 2 · system of record

What your data shows.

state and state_change query a post-call state adapter: your DB or API. Absent adapter → INCONCLUSIVE.

Authority 3 · human-verified

What a person confirmed.

An Ed25519-signed human label record: the final word when a machine can’t settle it.

Three authorities: the trace, your data, a human.

Every verdict is grounded in one of three sources, and structurally cannot read a fourth.

A state query resolves three ways: match (PASS), no such row (a grounded FAIL), or unreachable (INCONCLUSIVE, with a reason).

A model’s opinion never wears Authority 1 or 2.

A model verdict lives on its own advisory lane and never certifies an outcome.

conversation-test.v1 · scorecard · support-bot
conversation-test.v1 · agent support-bot · call 8f2a
Outcomerefund posted · state adapterAuthority 2pass
tool_resultissue_refund returned ok · traceAuthority 1pass
stateno adapter suppliedAuthority 2inconclusive
Model judge“sounded confident it refunded”advisoryadvisory
The judge reads words. The lanes never cross.
The advisory lane in full →
assertions.yaml
version: 1
assertions:
  - id: disclosure-and-language
    kind: policy        # banned language + required disclosures
    dimension: policy   # a named, versioned, offline pack
  - id: workflow-order
    kind: tool_call     # from the ingested trace
    require_order: [verify_identity, lookup_account, issue_refund]
    never_before: {tool: issue_refund, until: verify_identity}
A hard never_before constraint on issuing the refund, plus its required order.
  • policy pack · versioned
  • tool_call · required order
  • value never echoed

Did it follow the rules? Same evidence, same lane.

A versioned, offline policy pack checks banned language and disclosures; a tool_call assertion holds the workflow to its required order.

The same deterministic machinery grounds both: no model runs, byte-stable on a fixed version.

Outcome answers whether the task happened. Conversation checks whether it listened; Speech checks what was said.

Prove it happened. Not just claimed.

Eleven deterministic outcome checks and a versioned policy pack, in one command.

$ uvx hotato start --demo

One recording is enough to start. Get started → · Turn-taking →