axagent experiencelivev0.43.18

release v0.40.1

The fix wave: 19 bugs from a systematic hunt, closed in one day

v0.40.1 lands the fixes for 19 of the 24 bugs a five-lane audit fleet found in v0.40.0 - mixed-model session costs, FTS digest blindness, silent duplicate-row drops, disabled blocking guards, and a proposal-signature scheme that a bun upgrade could invalidate.

2026-08-21ax v0.40.110 referenced changes
announcement

How we got here

A day after v0.40.0 shipped, a five-lane audit fleet swept the new storage engine, the ingest pipeline, the query layer, and the CLI/hooks surface for bugs - each finding required a pinned repro before it counted. The sweep produced 24 verified issues. This release closes 19 of them; the remaining five are design questions or follow-up investigations, tracked open on the run map (#956).

What was actually wrong

The critical one: a mixed-model session billed every token at its last model (#936). Session cost was priced from session-total tokens at the session's display model, so a run that started on a frontier model and finished on a cheap one - or dispatched to both - overcounted by 30.9% on live data. Session cost is now the sum of per-turn estimates, each priced at its own turn's model, on both the Claude and Codex parsers. Pricing also stopped trusting partial answers elsewhere: a cost total is now null rather than a silent undercount when any used token component has no rate (#941), rollup groups with mixed priced/unpriced rows recompute or flag instead of reporting a partial sum as the total (#944), and ingest prices against the merged catalog instead of the built-in one (#937).

The storage seams got four hardening fixes (#964): the FTS content digest could miss a rebuild when text moved between existing rows (the XOR aggregate was pairing-blind), `putMany` could silently lose duplicate-id rows inside one batch, a WAL stat error could green-light a snapshot clone over a non-quiescent database, and the NDJSON spool deduped on raw ids while writing encoded ones. Each now has a pinned regression test - and the duplicate-collapse warning fired on its first real ingest, which is exactly what it is for.

Two runtime races are gone: a hook guard that threw synchronously could disable every later blocking guard in the dispatcher (#946), and two concurrent stale reads could both fork a background ingest (#947) - the spawn now runs under an exclusive claim that also survives a hard process kill.

The judgment sidecar's proposal dedupe signatures were hashed with `Bun.hash`, meaning a bun upgrade would re-key every signature and re-mint duplicates of settled proposals (#942). Signatures are SHA-256 now, with a one-time lossless migration that re-keys ids and links in a single transaction without dropping any decision row.

The rest: recall and cost query selectors rank matches by recency before applying their limit instead of keeping an arbitrary subset (#930, #931), the session inspector no longer loses tool cards past row 4,000 and reports whole-session totals on paginated views (#934, #935), derived SQL-model rows now clear when a reparse invalidates their source (#928, #929), routing-impact blocks price at turn grain instead of attributing whole overlapping sessions (#940), and the otel coverage and skills-recovery rollups count what they claim to count (#932, #933).

The one cross-fix interaction

Moving turn-level cost columns into the enrichment set (#966's catalog fix) silently changed what `ax segment export` ships: cost columns no longer ride a segment. The full-suite gate on merged main caught the contract tests still pinning the old decision, and the pin was retracted in place (#967) - an imported segment now re-prices against the importing machine's catalog, which the same release's backfill extension makes automatic.

Upgrade notes

The first ingest after upgrading runs three one-time cutovers: a full FTS rebuild (digest formula v3), a full re-derive of the cache-bust and run-evidence SQL models, and the proposal signature migration. Measured on a 16 GB live store: one 62s warm ingest, then back to the ~30s steady state.

referenced changes

10 linked changes

Generated from Release Please and grouped by change type. Each row keeps its issue and commit references.

Bug Fixes

  1. 01correct core model pricing (#966) (8b92391), closes #936 #937 #938 #941
  2. 02cost: correct window and partial pricing reads (#963) (d8c629d), closes #940 #944
  3. 03dashboard: rank query matches before limit (#959) (3f8c158), closes #930 #931
  4. 04ingest: stabilize proposal dedupe signatures (#965) (f849b98)
  5. 05inspect: preserve late page details (#960) (1a42924), closes #934 #935
  6. 06lib: harden DuckDB storage seams (#964) (d20c2ab), closes #948 #949 #950 #951
  7. 07models: replace stale derived rows (#962) (7e5bdf9), closes #928 #929
  8. 08queries: correct session-based rollups (#957) (58b6c61), closes #932 #933
  9. 09segment: retract the turn-cost-rides pin after #966 (#967) (892501f)
  10. 10sync-throw guard fail-open + atomic freshness spawn claim (#961) (e5a1ce9)
generated by release please
Show generated changelog for v0.40.1commit-level detail from Release Please

0.40.1 (2026-08-21)

Bug Fixes