ADR-005: Mirrored Contracts and Generated SAM Models
Status
Accepted
Context
The platform’s Pydantic models are the source of truth of its api: the SAM models of every manifest kind, and the published contracts (the Smarter Chat api, the Smarter Journal, the Django-React integration). The SDK can’t import them: the platform’s package is also named smarter, and its SAM models depend on Django.
Decision
SAM models are generated from the JSON Schema that the platform publishes for each kind (
/api/v1/cli/json-schema/<Kind>/), byscripts/generate_sam_models.py(datamodel-code-generator) intosmarter/models/sam/. The schemas and example manifests are saved intests/data/sam/, and a test parses every kind’s example with its model. Generated code is never edited by hand.Contracts are mirrored by hand in
smarter/models/chat.pyandjournal.py, and copied inreact.py(which is pure Pydantic).scripts/sync-contracts.shcopies the platform’s committed JSON Schemas and examples intotests/data/contracts/, and a test fails when the platform declares a field that the mirror doesn’t, or when an example doesn’t parse.The SDK reads only version 2 of the chat contract, and asks for it in every request (
X-Smarter-Capabilities: chat-contract-v2).
Alternatives Considered
Import the platform’s models. Impossible, as above.
Hand-write the SAM models. 25 kinds, which drift as soon as they are written.
Generate the contracts too. Hand-mirroring keeps their docstrings, helpers (
.text) and forward-compatible types (ADR-004).
Consequences
Positive:
Callers get the platform’s own models.
Drift is caught by tests, not by users.
Negative:
Refreshing is a manual step (
make sam-models,make contracts) that someone must run when the platform changes.Generated models check structure, not the platform’s business rules:
manifests.validate()does.