Skip to content

hotato 1.2.0 — investigate + assert + Evidence Kernel v2

Choose a tag to compare

@quantumCF quantumCF released this 12 Jul 10:15

[1.2.0] - 2026-07-12

Added

  • hotato investigate -- one call to a CI-ready contract. Takes a local
    dual-channel WAV or a provider --stack/--call-id and, in one guided flow,
    pulls or opens the audio, authenticates the capture origin honestly
    (frozen-regression / provider-pulled / operator-asserted-local), runs the
    channel-eligibility gate, ranks candidate moments, then investigate label <ref> --expect yield|hold mints a signed label-record and builds a portable
    signed contract plus the exact CI verify and recapture commands. Reuses only
    shipped primitives; never fabricates a label or a verdict.
  • hotato assert -- a deterministic assertion DSL. Five no-model, offline,
    byte-stable assertion kinds over the conversation: phrase (regex on the
    transcript, with absent/compliance mode), pii (ssn/card-Luhn/email/phone
    detectors with a must_not_leak gate and a redacted-transcript artifact that
    never echoes the raw value), policy (named, versioned offline rule packs),
    tool_call (name/args/order/count/never-before checked against the
    voice_trace.v1 spans, not the transcript), and outcome (task success as
    all-of/any-of deterministic predicates). Every result carries its kind and
    deterministic flag; the summary splits deterministic vs judge counts and by
    construction emits no blended overall_score. Embeddable in a contract so
    contract verify gates on a failing assertion, reported separately from the
    timing verdict. New docs/ASSERTIONS.md.
  • Signed label-records + Ed25519 signing ([sign] extra). A human label is
    now a signed label-record.v1 bound to the exact audio, not an inference; the
    opt-in [sign] extra adds asymmetric Ed25519 attestation, with HMAC kept as a
    separately-named shared-secret tier.
  • Opt-in [transcribe] extra (faster-whisper). A transcript layer that is
    context only and never alters the timing score.
  • Copy-paste CI configs for GitLab, Jenkins, Azure DevOps, and CircleCI in
    the docs (alongside the existing GitHub Actions gate).
  • --notify URL webhook on sweep and hotato fleet run. Opt-in,
    repeatable, off by default: when the run finishes it POSTs one JSON summary
    (counts, the top candidate moments -- id, kind, timing numbers only -- and
    local artifact paths, plus a one-line text field a Slack incoming webhook
    renders directly) to each URL. No audio, no credentials, no transcript text
    ever leaves the machine through it. A non-http(s) URL is refused before any
    network attempt (exit 2); once sent, delivery is fail-open -- a down or slow
    webhook logs one stderr warning and never breaks the run. New module
    src/hotato/notify.py; documented in docs/EGRESS.md and the README.
  • hotato fleet trend. Reads the local fleet SQLite registry and writes
    one self-contained HTML page: per-agent talk-over and time-to-yield trend
    lines (p50/p95 per day), candidate moments discovered over time, and
    experiment outcomes (improved/inconclusive/refused). Offline, zero external
    assets, hand-rendered inline SVG in the same house style as the sweep
    dashboard. A day with no measurements gets no point; a series with fewer
    than two days of history is reported plainly as "not enough history to
    trend" rather than a faked or interpolated line. New module
    src/hotato/fleet/trend.py; documented in the README.

Changed

  • HTML report template: deduped boilerplate, no scoring change. The same
    determinism/reproducibility/ceiling/no-accuracy-score story used to be
    restated 4-5 times across a header line and three separate footer
    paragraphs; it is now one Method line. The stamped out-of-scope negation
    bullet list (no speaker ID, no diarization, no STT, no emotion) is now one
    link to the canonical explanation instead. The thresholds table is now a
    single collapsed <details> block rather than an always-open section. The
    analytics rollup now renders after the per-event cards it aggregates
    (previously before them), and only once a page has at least 3 events --
    a rollup over one or two cards had nothing to add. Every measured number
    and event datum on the page is unchanged; this is layout and copy only.
    src/hotato/report.py, docs/REPORTS.md.

Fixed

  • Fleet registry: concurrent construction no longer deadlocks (was a CI hang
    on Python 3.11/3.12).
    Two threads or processes opening a Registry on the
    same fresh fleet.db at once raced on the schema-init writes: PRAGMA journal_mode=WAL needs a brief exclusive lock and is not covered by the
    connect busy timeout, so the loser could raise database is locked, and the
    check-then-seed of the meta schema_version row could raise a UNIQUE
    IntegrityError. The connection now opens in autocommit
    (isolation_level=None) so the manual BEGIN IMMEDIATE in
    JobQueue.enqueue/claim is the sole, version-stable transaction control --
    removing the implicit-transaction interaction whose timing changed across
    CPython 3.11/3.12; the idempotent init sequence retries locked/busy with
    bounded backoff; the schema_version seed is now INSERT OR IGNORE and the
    additive column migration tolerates a concurrent duplicate add. JobQueue
    writes retry the same way. Batch candidate reclustering
    (FleetAPI.recluster_agent) now wraps its per-candidate rewrite in an explicit
    BEGIN IMMEDIATE..COMMIT, so it stays all-or-nothing under autocommit instead
    of committing each row individually. The concurrency regression test's worker
    threads are now daemons, so any future regression fails fast instead of a leaked
    non-daemon thread hanging the run. src/hotato/fleet/registry.py,
    src/hotato/fleet/jobs.py, src/hotato/fleet/api.py,
    tests/test_fleet_jobs_concurrency.py, tests/test_fleet_recluster_atomicity.py.

Security

  • Evidence kernel hardened (external review). A forged, altered, or
    wrong-key manifest/attestation signature can no longer reach the signed tier
    (it is refused, never silently downgraded); the scorer pin now covers the real
    scorer bytes and refuses on mismatch; a suspected channel swap or crosstalk
    yields advisory candidates but a null verdict and a refused contract until the
    mapping is confirmed. A temporal precommit + replay ledger binds recapture
    receipts. The 19-finding robustness audit is closed and the FIFO/blocking-open
    hang class is eliminated with an AST lint that fails CI on any new unguarded
    external open.