feat: report "no response" as NA latency, not a zeroed success#67
Conversation
When the target agent doesn't respond, aeval still exits 0, so the daemon marked the job completed with 0 ms latencies. That ranked a dead agent as the fastest in the fleet and dragged every average toward zero. Now "no response" is a valid, honest result: - response/interrupt latency -> NULL (NA), never 0 — kept out of averages and rankings instead of looking fastest. - response rate -> 0 — the real "answered 0% of prompts" signal. - interrupt rate / false barge-in -> NA (no opportunities to measure). A "Partial response" amber tag shows whenever responseRate < 1 (job detail header + jobs list). A genuine aeval failure records NO result. Changes: - schema + migration 0020: 6 latency columns nullable (registered v21). - daemon: null latency defaults, null-safe parse guards, structure-aware Priority-1 gate (keeps a no-response metrics.json instead of falling through to stdout), dropped partial-results salvage. - complete route: insert only on success; pass latencies as ?? null. - leaderboard + api-v1 leaderboard: exclude NA from averages, sort NA last, guard composite normalization; display NA. - jobs list: batched responseRate (getResponseRatesByJobIds) for the tag. - UI: NA rendering on job detail, realtime cards, leaderboard. - tests: no-response stores NA + rate 0; failure stores no result; list exposes responseRate; daemon mirror updated to the null contract. Deploy order is safe: server migrates first (columns nullable, old daemons sending 0 still insert), then upgrade the daemon to emit null. 🤖 Built with SMT <smt@agora.build>
🤖 Claude Code ReviewReview complete. Here's my assessment. SummarySolid, well-reasoned change. The core idea — storing non-response latency as A few things worth addressing: Findings1. Zeroed placeholder result row contradicts the PR's thesis (server/routes.ts:2932-2937) — medium
Since the columns are now nullable, set these six latency fields to 2. Leaderboard rewards unreliable-but-fast providers (server/routes.ts composite; routes-api-v1) — low, arguably pre-existing 3. Minor: median-from-summary can yield non-null median with null SD/P95 Nothing else stands out — the null-sentinel refactor in the daemon, the sort/normalization null-guards, and the client formatters all look correct. |
🤖 Codex Code ReviewFindings
Open Questions
Notes
|
Context
When the target AI agent doesn't respond (job 25770 triggered this),
aevalstill exits 0, so the daemon marked the job completed with 0 ms latencies. That's actively wrong: the leaderboard/realtime pages rank and average by latency, so a 0 ms "response" from a dead agent looked like the fastest agent in the fleet and dragged every average toward zero — while the real signal ("answered 0% of prompts") was hidden.The model
Agent didn't respond (partially or fully) is a VALID result → record it:
A genuine aeval failure (non-zero exit) records no result — you didn't measure the product. A "Partial response" amber tag shows whenever
responseRate < 1(job detail header + jobs list).Changes
0020_eval_result_latency_nullable.sql, registered as version 21.vox-agentd.ts): null latency defaults, null-safe parse guards, structure-aware Priority-1 gate (keeps a valid no-responsemetrics.jsoninstead of falling through to stdout and losing rawData/rates), dropped the partial-results salvage path. Rate math (computePerCaseAndRates) was already correct — unchanged.results && !jobError); passes latencies as?? nullinstead of|| 0.avg()already ignores NULLs.responseRate(getResponseRatesByJobIds, one query) so the list can flag "Partial response".Deploy order (safe by construction)
Server merges/deploys first — migration makes the columns nullable, and old daemons still sending
0insert fine. Then upgrade the daemon (vox-upgrade.sh) so agents start emittingnull.Verification
npm run check— clean./api/eval-jobsexposesresponseRate./runregion validation, clone, built-in protection, version-gating,mergeEvalConfig) — none appear in this diff and they fail identically in isolation.Generated with SMT smt@agora.io