Models use Money = Annotated[Decimal, PlainSerializer(float)] so storage
is exact NUMERIC(15,2) (rates 15,6) while JSON keeps emitting plain
numbers — the frontend contract is unchanged, pinned by
test_models_serialization.py. Service layers coerce to float at their
boundaries (projection math, rate multipliers, agent tool output, the
savings constants become Decimal) so no naive Decimal/float mixing can
raise. Migration 7f567c8bafdb applied to dev: per-row values and the
table sum byte-identical before/after; endpoints verified live on the
new schema. 59/59 tests green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SQLModel enum columns need col() to expose SQLAlchemy operators like
notin_. Without it the agent tool raised at query build time and the
chat card flashed away.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 'last N transactions' answer was including salary deposits, which the
user reads as expense activity. Filter income types out at the query level.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires up an OpenAI-backed MAF agent that exposes WealthySmart
data through tool calls (recent transactions, cycle summary,
analytics, pensions). Pulls in agent-framework + AG-UI adapter
+ OpenAI client deps.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>