fix(optimize): strengthen the result-cache fingerprint against collisions - #910
Conversation
…ions cacheKey fingerprinted only project count + api-call sum, so two datasets agreeing on those two numbers collided onto one cached OptimizeResult, and a cost/token change that left call count unchanged (e.g. a re-price) served stale findings within the 60s TTL - reachable in the long-lived menubar. Fold total cost, savings and proxied cost (scaled to micro-dollars) into the key. Exported cacheKey and mutation-checked: the old key collides two same-shape datasets and a re-price; the new one separates both, while an identical dataset still keys identically.
iamtoruk
left a comment
There was a problem hiding this comment.
Reviewed on the merged tree. Correct cache-correctness fix: the old cacheKey fingerprinted only project count + api-call sum, so two materially different datasets sharing those two numbers collided onto one cached OptimizeResult, and a re-price that left call count unchanged served stale findings within the 60s TTL (reachable in the long-lived menubar). The new key folds total cost, savings and proxied cost, each rounded to whole micro-dollars so float jitter cannot thrash the key while a real cost change gets a distinct key. It only ever invalidates more (never serves stale), and an identical dataset still keys identically. Mutation-checked: reverting to the old key fails both the collision and the re-price test, while the identical-dataset test passes either way. tsc clean, optimize suite green. Good to merge.
Cache-correctness fix from the systematic audit (find -> verify -> adversarial -> manual confirmation + mutation check).
optimize.tscacheKeyfingerprinted only project count + api-call sum, so two datasets agreeing on those two numbers collided onto one cachedOptimizeResult(the second scan received the first's findings), and a cost/token change that left call count unchanged - e.g. a re-price - served stale findings within the 60s TTL. Reachable in the long-lived menubar process. Fold total cost, savings and proxied cost (scaled to micro-dollars so float jitter cannot thrash the key) into the fingerprint.Mutation-checked:
cacheKeyis exported and the old key is shown to collide two same-shape datasets and a re-price, while the new key separates both and still keys an identical dataset identically.tsc --noEmitclean, 121 optimize tests green.