Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,25 @@ Every entry reports millisecond measurement error and a confusion matrix. See `d

## [Unreleased]

## [1.15.1] - 2026-07-22

### Changed
- **`hotato prove` states its claim scope.** The proof envelope gains
`claim_scope` (captured_evidence, test_suite, candidate_revision,
deployed_revision) and `evidence_authority`, and the renderer headlines the
scope. A contracts-only run reads **Captured Evidence**, not a "release
proof"; a before/after run reaches **Candidate Revision** only when the caller
binds the candidate identity with `--candidate-config-hash` and `--provider`
(and `--deployment-id` for a deployed revision). The proof never claims more
than its lanes support. No new scoring engine; this is a calibration.
- **Corrected three overclaims on the public surfaces.** The package
description drops "everything you use a hosted platform for" (the public
package has no dataset/prompt management, hosted execution, or team
collaboration). The product one-liner is a capability, not an automatic
guarantee. `docs/COMPARE.md` replaces the caricature of hosted platforms with
an honest property-by-property table that names where a managed platform is
the stronger fit.

## [1.15.0] - 2026-07-22

### Added
Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type: software
authors:
- name: "Attention Labs, Inc."
license: MIT
version: 1.15.0
version: 1.15.1
date-released: "2026-07-21"
repository-code: "https://github.com/attenlabs/hotato"
url: "https://hotato.dev"
Expand Down
27 changes: 13 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ That transcript passed every text eval. The timing did not. hotato pins the catc

## The loop

Every production failure becomes a portable test, every candidate runs against it, and every release carries evidence. Five steps, one command each, nothing leaves your machine.
Turn production failures into portable tests, run candidate releases against them, and carry evidence with every release. Five steps, one command each, nothing leaves your machine.

| | | |
| :-- | :-- | :-- |
| **Observe** | traces, tokens, cost, and latency, from the OTel spans you already emit | `hotato observe report traces/` |
| **Catch** | deterministic scoring finds what text evals miss: timing, say-do, policy | `hotato investigate call.wav` |
| **Pin** | your label turns the catch into a portable, content-addressed contract | `hotato investigate label STATE#1 --expect yield` |
| **Test** | simulate, stress, and drive candidates against everything you pinned | `hotato gauntlet` |
| **Prove** | every evidence lane composed into one fail-closed release proof, in CI | `hotato prove --contracts contracts/` |
| **Prove** | every evidence lane composed into one fail-closed, content-addressed proof, in CI | `hotato prove --contracts contracts/` |

Deterministic. Byte-reproducible. Free, MIT. Agent-native over MCP. Every verdict carries its evidence across five dimensions (outcome, policy, conversation, speech, reliability), and production feeds the next loop: `hotato production export-regression` turns a live session back into a test.

Expand All @@ -54,15 +54,15 @@ Same loop a hosted platform runs. Three things it cannot offer.
| :-- | :-- | :-- |
| Observe, catch, pin, test, prove | yes | yes |
| Price at scale | free, MIT, any volume | metered per seat and per event |
| Verdicts | byte-for-byte reproducible, gate a build | vary run to run |
| Verdicts | byte-for-byte reproducible, gate a build | model-judge lanes vary run to run |
| Your traces and prompts | stay on your machine | live on their servers |
| Runs in CI, offline | yes | needs their service |

Full comparison: [`docs/COMPARE.md`](docs/COMPARE.md)

## From a bad call to a release proof
## From a bad call to a proof

One recording in. The pinned failure becomes a gate that stays red until the agent stops failing that call, and every gate you have composes into one receipt:
One recording in. The pinned failure becomes a gate that stays red until the agent stops failing that call, and every gate you have composes into one receipt whose headline states exactly what it establishes:

```console
$ hotato investigate ./call.wav
Expand All @@ -73,14 +73,13 @@ $ hotato investigate label '.hotato/investigate-state.json#1' --expect yield
created hotato contract: call-8s-yield

$ hotato prove --contracts contracts/
hotato prove: proof -- overall FAIL (exit 1)
lane verdict counts
contracts fail contracts=1 passed=0 failed=1 tampered=0 refused=0
content_id: sha256:2959c905ee6c1030...
proof: .hotato/proofs/proof/proof.json
Captured Evidence: FAIL
A lane failed or regressed; see the table.
contracts fail contracts=1 passed=0 failed=1
content_id: sha256:c907143d711a84ae...
```

A contract re-measures the captured failure under the pinned policy on every CI run, the same discipline a snapshot test gives you. `hotato prove` composes every lane you have (contracts, suites, before/after batteries, the stress suite) into one fail-closed verdict with a content-addressed receipt: pass only when every lane passed, and "could not tell" is never green.
`hotato prove` composes every lane you have (contracts, suites, before/after batteries, the stress suite) into one fail-closed, content-addressed receipt: pass only when every lane passed, and "could not tell" is never green. The headline is the **claim scope** the evidence supports, never more: contracts alone re-measure stored evidence (**Captured Evidence**), a suite establishes a **Test Suite** ran, and a before/after run reaches **Candidate Revision** only when you bind the candidate identity (`--candidate-config-hash`, `--provider`).

## Quickstart

Expand All @@ -91,7 +90,7 @@ uvx hotato start --demo
hotato investigate ./call.wav
# 3. pin the caught moment as a regression contract
hotato investigate label '.hotato/investigate-state.json#1' --expect yield
# 4. compose every gate into one release proof, on every pull request
# 4. compose every gate into one proof, scoped to what it establishes
hotato prove --contracts contracts/
```

Expand All @@ -109,10 +108,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: attenlabs/hotato@v1.15.0
- uses: attenlabs/hotato@v1.15.1
with:
contracts: contracts/
hotato-version: 1.15.0
hotato-version: 1.15.1
```

Copy-paste workflow with a commit-SHA pin: [`docs/CI.md`](docs/CI.md).
Expand Down
27 changes: 13 additions & 14 deletions README.pypi.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions atlas/records/addressed-backchannel-yielded.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@
"provenance": {
"hotato": {
"name": "hotato",
"version": "1.15.0"
"version": "1.15.1"
},
"inputs": [
{
Expand Down Expand Up @@ -196,7 +196,7 @@
],
"source_result_digest": "sha256:7a691d5993389b47f2b43b7afbe7316bbb0d662e703fa0f8a82e39b93b052c08"
},
"record_id": "sha256:dd3c63fcaeff31c7af4cecce0612aa524e554f7ae40d0c362f2d5ddef8491472",
"record_id": "sha256:70f0fc141627f293d1ca134f307a0560f41103f43d5ef967b7d27f40c060cb4f",
"reproduction": {
"argv": [
"hotato",
Expand All @@ -222,7 +222,7 @@
"version": "1.0"
},
"reproduction_metadata": {
"hotato_version": "1.15.0",
"hotato_version": "1.15.1",
"reviewer_principal": "hotato-examples",
"working_directory": ".",
"bundle": {
Expand All @@ -240,7 +240,7 @@
"verify_output": "verify.json",
"selector": "fd-02-backchannel-yielded",
"record_out": "record",
"expected_record_id": "sha256:dd3c63fcaeff31c7af4cecce0612aa524e554f7ae40d0c362f2d5ddef8491472"
"expected_record_id": "sha256:70f0fc141627f293d1ca134f307a0560f41103f43d5ef967b7d27f40c060cb4f"
},
"supersedes": {
"record_id": "sha256:6c5e0e6de73004d8683c0987812d849c46fa9f9f8f204eb4da71e600b636e3a0",
Expand Down Expand Up @@ -268,8 +268,8 @@
},
{
"command": "hotato record render verify.json#fd-02-backchannel-yielded --out record",
"output": "wrote failure record (FAIL, fd-02-backchannel-yielded) to record/: failure-record.html, failure-record.json, failure-record.md, failure-record.svg\nrecord_id: sha256:dd3c63fcaeff31c7af4cecce0612aa524e554f7ae40d0c362f2d5ddef8491472\n"
"output": "wrote failure record (FAIL, fd-02-backchannel-yielded) to record/: failure-record.html, failure-record.json, failure-record.md, failure-record.svg\nrecord_id: sha256:70f0fc141627f293d1ca134f307a0560f41103f43d5ef967b7d27f40c060cb4f\n"
}
],
"content_digest": "sha256:dc05c98c555099225b575ebc5de7f8f95f9c94bcfd6e01345cf3f02f92c258ec"
"content_digest": "sha256:6efe74abf4d49ceb0d51f8673e174510eff437a89958cbdf90901049e3b36980"
}
12 changes: 6 additions & 6 deletions atlas/records/addressed-interruption-missed.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@
"provenance": {
"hotato": {
"name": "hotato",
"version": "1.15.0"
"version": "1.15.1"
},
"inputs": [
{
Expand Down Expand Up @@ -196,7 +196,7 @@
],
"source_result_digest": "sha256:d3ec5aa5bbbdac05ef1ee7ad6d2612afd3916504e313e16df56ea3c334cb1346"
},
"record_id": "sha256:ad9c62d49f76f62c11c25184a13cd63669e5e6fee9f1dfc5f8093fb35dbe6eaa",
"record_id": "sha256:25f01ea209620cbd36b6ec662dfce124eb989f53f303be808c65f2f6d90ed674",
"reproduction": {
"argv": [
"hotato",
Expand All @@ -222,7 +222,7 @@
"version": "1.0"
},
"reproduction_metadata": {
"hotato_version": "1.15.0",
"hotato_version": "1.15.1",
"reviewer_principal": "hotato-examples",
"working_directory": ".",
"bundle": {
Expand All @@ -242,7 +242,7 @@
"verify_output": "verify.json",
"selector": "fd-01-missed-interruption",
"record_out": "record",
"expected_record_id": "sha256:ad9c62d49f76f62c11c25184a13cd63669e5e6fee9f1dfc5f8093fb35dbe6eaa"
"expected_record_id": "sha256:25f01ea209620cbd36b6ec662dfce124eb989f53f303be808c65f2f6d90ed674"
},
"supersedes": {
"record_id": "sha256:772fbb2a13addeb5cfbfb82d3c1652b15cb547d004e2db3db4341779c99c4336",
Expand Down Expand Up @@ -270,8 +270,8 @@
},
{
"command": "hotato record render verify.json#fd-01-missed-interruption --out record",
"output": "wrote failure record (FAIL, fd-01-missed-interruption) to record/: failure-record.html, failure-record.json, failure-record.md, failure-record.svg\nrecord_id: sha256:ad9c62d49f76f62c11c25184a13cd63669e5e6fee9f1dfc5f8093fb35dbe6eaa\n"
"output": "wrote failure record (FAIL, fd-01-missed-interruption) to record/: failure-record.html, failure-record.json, failure-record.md, failure-record.svg\nrecord_id: sha256:25f01ea209620cbd36b6ec662dfce124eb989f53f303be808c65f2f6d90ed674\n"
}
],
"content_digest": "sha256:c3d8d1ed551fc070610b61304a316e9166296a84128b23b963a533ad610f371e"
"content_digest": "sha256:d38d9900d7e3265b62b96fb05bdcb8189717b239ce5796d35a1cd06bee246967"
}
10 changes: 5 additions & 5 deletions docs/CI.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Conversation failed: Agent did not yield; measured talk-over was 2.66 s.

Share in a PR: hotato-failure-record/failure-record.md
Share as an image: hotato-failure-record/failure-record.svg
Verify the record: uvx --from hotato==1.15.0 hotato record verify hotato-failure-record/failure-record.json
Verify the record: uvx --from hotato==1.15.1 hotato record verify hotato-failure-record/failure-record.json
```

Preview it locally, then scaffold the durable gate into your own repository
Expand All @@ -43,11 +43,11 @@ offline -- it runs the pinned Action revision itself off PYTHONPATH (no
pip, no package index), installs no model, no ASR, no Node tool, calls no
external judge, and reads no secret.

Composite Action since v1.4.0. Adopt the current release (v1.15.0), pinned
Composite Action since v1.4.0. Adopt the current release (v1.15.1), pinned
by its full commit SHA; resolve the tag to its SHA first:

```bash
git ls-remote https://github.com/attenlabs/hotato refs/tags/v1.15.0
git ls-remote https://github.com/attenlabs/hotato refs/tags/v1.15.1
```

Then commit this workflow (replace the `attenlabs/hotato` pin with the SHA
Expand All @@ -69,7 +69,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- id: hotato
# Pin by full commit SHA (immutable); the comment names the release.
uses: attenlabs/hotato@<full-commit-sha> # v1.15.0
uses: attenlabs/hotato@<full-commit-sha> # v1.15.1
with:
suite: tests/voice/qa.suite.json
agent: support-agent
Expand Down Expand Up @@ -107,7 +107,7 @@ Everything else is optional:
| Value | Effect |
|---|---|
| `action` (default) | Installs the pinned Action revision itself, `--no-deps`, no package-index egress -- exactly the revision your workflow pinned |
| an exact version, e.g. `1.15.0` | `pip install --no-deps hotato==1.15.0` |
| an exact version, e.g. `1.15.1` | `pip install --no-deps hotato==1.15.1` |
| `preinstalled` | Skips installation (hotato is already on the runner) |

A range or `latest` is refused, so the pin always names one exact
Expand Down
Loading
Loading