Context
The Pydantic model for the top-level aggregate.json shape declares schema_version: int = 1 as a default. When the model is dumped with model_dump(by_alias=True, mode=\"json\", exclude_unset=True) — the mode the writer will use once the calculators return models — a default-only field that was never explicitly set is dropped. Downstream consumers reading aggregate.json today rely on schema_version being present; a silent drop is a wire-format regression.
The current byte-identity round-trip test only sees the field because it explicitly stamps payload[\"schema_version\"] = 1 before validation, which marks the field "set." That's the right shape for today's dict-based writer path (the orchestrator stamps the envelope). But the migrated writer must preserve the guarantee without depending on how the orchestrator populated the model.
Ask
Add a canonical test that exercises the real writer path end-to-end, once the writer accepts models, and asserts that schema_version is present in the emitted JSON regardless of whether the caller stamped it explicitly on the model.
The test can either:
- Assert the writer stamps
schema_version on-write when the caller left it default (option A — writer owns the envelope, mirrors current behaviour where the orchestrator stamps it), OR
- Assert the model construction path used by the orchestrator explicitly sets the field before dump (option B — caller owns the envelope, requires a paired constructor helper).
Either shape is fine; the point is the test pins the invariant.
Acceptance
- A canonical test that calls the migrated writer's
write_aggregate (or write_run_aggregates) with a RunAggregate where schema_version was left at default, and asserts the emitted JSON on disk contains schema_version.
- Documented in the writer's docstring: whose responsibility it is to stamp
schema_version on the model before dumping.
References
Follow-up to the stage-1 typing PR that shipped the models. The stage-2 PR (calculators + writer migration) is where this test lands.
Context
The Pydantic model for the top-level
aggregate.jsonshape declaresschema_version: int = 1as a default. When the model is dumped withmodel_dump(by_alias=True, mode=\"json\", exclude_unset=True)— the mode the writer will use once the calculators return models — a default-only field that was never explicitly set is dropped. Downstream consumers readingaggregate.jsontoday rely onschema_versionbeing present; a silent drop is a wire-format regression.The current byte-identity round-trip test only sees the field because it explicitly stamps
payload[\"schema_version\"] = 1before validation, which marks the field "set." That's the right shape for today's dict-based writer path (the orchestrator stamps the envelope). But the migrated writer must preserve the guarantee without depending on how the orchestrator populated the model.Ask
Add a canonical test that exercises the real writer path end-to-end, once the writer accepts models, and asserts that
schema_versionis present in the emitted JSON regardless of whether the caller stamped it explicitly on the model.The test can either:
schema_versionon-write when the caller left it default (option A — writer owns the envelope, mirrors current behaviour where the orchestrator stamps it), OREither shape is fine; the point is the test pins the invariant.
Acceptance
write_aggregate(orwrite_run_aggregates) with aRunAggregatewhereschema_versionwas left at default, and asserts the emitted JSON on disk containsschema_version.schema_versionon the model before dumping.References
Follow-up to the stage-1 typing PR that shipped the models. The stage-2 PR (calculators + writer migration) is where this test lands.