Skip to content

feat: score-on-arrival — the console engine (serve --score-production)#42

Merged
quantumCF merged 2 commits into
mainfrom
console/score-on-arrival
Jul 23, 2026
Merged

feat: score-on-arrival — the console engine (serve --score-production)#42
quantumCF merged 2 commits into
mainfrom
console/score-on-arrival

Conversation

@quantumCF

Copy link
Copy Markdown
Contributor

Wave A PR-1 of the console program: every completed production session gets scored deterministically as it lands.

  • hotato serve --score-production: a supervisor-pattern background worker polls the production evidence db (strictly read-only: mode=ro + query_only + write-denying authorizer) for COMPLETE/QUIESCENT sessions and scores each — one at a time, bounded memory — with the existing deterministic scorer over the session's two-channel recording.
  • console.sqlite3 sidecar (derived, versioned, rebuildable): per-dimension observations (never blended), ranked candidate moments, one measured failure-reason sentence, timing derived from evidence event timestamps with provenance (per-hop latency keeps the reporting event's declared authority; derived spans labeled derived:event_timestamps), scorer version + config hash on every record.
  • Fail-closed at every edge: refusal is a first-class NOT_SCORABLE record with its reason; a scorer crash or persist failure becomes a visible ERROR record — never a silent skip, never a claimed score before the sidecar write commits — and the worker continues.
  • --rebuild-scores: regenerates the sidecar entirely from evidence, deterministically — same evidence db, byte-identical content (schema migration = rebuild).
  • Bind, auth, and the read-only route surface unchanged. 11 new tests: end-to-end scoring through production.py's own ingest API, determinism (rebuild==rebuild==incremental-worker), crash/persist-failure visibility, keyset one-at-a-time proof, refusal reasons.

Independently verified by a fresh reviewer (48 checks green, own harness): read-only discipline, determinism incl. the incremental path, error-visibility injections, bounded-memory query shape, no new outbound calls. Two verifier blockers resolved in follow-up commits: restored a CHANGELOG heading the new entry had consumed, import-sort. Full suite green locally (4795 passed); CI is the clean-environment confirmation.

Spec: hotato-growth/research/CONSOLE-WAVE-A-SPEC.md (R1–R4, invariants I1–I5, I7)

https://claude.ai/code/session_015njkxtoAKioqTPT2k14xFr

…ebuild-scores)

A supervisor-pattern worker inside hotato serve polls the production
evidence db (mode=ro + query_only + write-denying authorizer) for sessions
reaching COMPLETE/QUIESCENT and scores each one -- one at a time, keyset
queries only -- with the deterministic scan scorer over the session's
recorded two-channel audio, writing durable records to a versioned
console.sqlite3 sidecar beside the evidence db: per-dimension observations
(never blended), ranked candidate moments, one measured failure-reason
sentence, and timing derived purely from evidence event timestamps (per-hop
latency keeps the reporting event's declared authority; turn spans and
end-to-end are labeled derived:event_timestamps).

Refusal is first-class: absent/unavailable/mono/unreadable audio is a
NOT_SCORABLE record with its reason; a scorer crash on one session becomes
an ERROR record and the loop continues; a persist failure surfaces through
a minimal ERROR write path plus a counter and is retried -- a score is
claimed only after its sidecar write commits. The sidecar is derived data,
never authority: --rebuild-scores regenerates it entirely from the evidence
db and exits, and the same evidence db always rebuilds to a byte-identical
canonical dump (the one wall-clock column, created_at, is excluded from the
comparison). Bind, auth, and the server's read-only route surface are
unchanged.

Claude-Session: https://claude.ai/code/session_015njkxtoAKioqTPT2k14xFr
@github-actions

Copy link
Copy Markdown

hotato turn-taking eval

8 of 8 scenarios pass. 0 fail. No regression.

scenario expect yielded time to yield talk over result
01-hard-interruption yield yes 0.50s 0.50s pass
02-backchannel-mhm hold no - 1.57s pass
03-filler-start yield yes 0.65s 0.56s pass
04-correction yield yes 0.50s 0.50s pass
05-telephony-8khz yield yes 0.50s 0.50s pass
06-double-talk yield yes 1.05s 1.05s pass
07-echo-bleed hold no - 3.00s pass
08-rapid-turn-taking yield yes 0.50s 0.50s pass

Regressions

None.

Reproducible timing measured locally from call audio. Swap the bundled self-test step for your own captured recordings to gate on your agent. github.com/attenlabs/hotato

@quantumCF
quantumCF merged commit 48f804c into main Jul 23, 2026
15 checks passed
@quantumCF
quantumCF deleted the console/score-on-arrival branch July 23, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant