mirror of
https://github.com/we-promise/sure.git
synced 2026-09-06 15:14:19 +00:00
* fix(holdings): an outbound transfer must not clear a cost basis Found by Codex on #3154, reported after it merged. The migration cleared any calculated basis on a position that had ever been part of a Transfer, in either direction. The runtime does not: both `Holding#calculate_avg_cost` and the calculators drop `qty <= 0` rows before they look at the label, so only a transfer IN makes a position unknowable. Shares sent elsewhere say nothing about what the remaining ones cost. That figure came from real purchases and is correct, and the migration destroyed it — irreversibly, on a position the app still stands behind. The `EXISTS` clause gains the same `qty > 0` the runtime applies, and a test holds both directions down: a transfer in clears, a transfer out does not, and each asserts what the computed path says before running the migration so the two cannot drift apart again. On the old SQL the outbound case fails. Installs that already ran the previous version cannot have those figures restored. A connected account recomputes its basis when it next materializes; a manual or disconnected one will not, which is the case this migration was written for in the first place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016GTNba5qE5NwzaHzbp27ye * test(holdings): reach the runtime through its public door Review on #3237. The test asserted the runtime precondition by sending to Holding's private calculate_avg_cost, which ties migration coverage to a model's internals — the thing the repo's own guidance says not to do. `avg_cost` answers the same question in public; it only returned the stored figure first because this test had stored one. It now leaves the basis empty until after the precondition, so the read path falls through to the computation on its own, and each case stores the figure the migration is then asked to judge. The precondition stays rather than moving to the holding suite, because it is the point: the migration and the runtime have to agree about which positions are unknowable, and the bug was that they did not. A test on either side alone would not fail if they drifted apart again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016GTNba5qE5NwzaHzbp27ye --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>