Add a result store¶
Implement ScoreStore when model scores must be persisted in a new database or warehouse.
Persistence-only implementation¶
Provide:
ensure_schema(columns);add_scores(model_id, model_name, plugin_identity, rows, columns);read_run_identity(model_id);get_unscored_variants(variant_ids, model_id);read_score()or an efficientread_scores()override.
The inherited materialize() implementation performs portable annotation loading, score reads, predicate
evaluation, and result assembly.
Warehouse implementation¶
A warehouse may override materialize() to push joins and predicate evaluation into its query engine. The
observable result must still match the portable implementation, including missing values, model/source
attribution, and three-valued predicate behavior.
Schema rules¶
Persist shared variant identity, model identity, and the complete plugin run identity separately from
declared score fields. Reject a second identity for an existing model ID and reject legacy rows whose
identity is unknown or lacks model-instance scoring context rather than assigning them the current wrapper's
meaning. The score and detail conformance suites exercise configuration-hash conflicts and incomplete
identities. If the backend requires
decomposed locus fields, return their scalar dtypes from required_row_identity(); the common scoring engine
then validates them before calling the store. The engine derives any omitted portable locus field (chr as
str, pos as int, ref and alt as str) from the canonical variant_id and verifies emitted ones
against it, so model bindings need not know which store requires them. A store must not redefine those
portable dtypes, and any other required field must come from the binding's codec. Allow a reused score column only when its complete logical
definition agrees with the existing schema. Reject incompatible collisions before writing data.
Document write idempotency. Callers use get_unscored_variants() as the portable deduplication gate; they must
not assume all stores ignore repeated inserts.
Test and register¶
Subclass ScoreStoreContract, compare materialized output with the in-memory/reference fixture, and test
schema evolution, duplicate writes, missing scores, multiple model architectures, and annotation-source
integration. Register under altar.score_stores.
Named detail storage¶
Implement DetailStore separately when the backend should hold binding-declared one-to-many model output.
Its contract creates or validates a named schema, finds missing logical row keys, adds rows, streams rows by
model/table/variant, and reports the exact stored schema and plugin provenance. Do not add model-specific
methods or pair a store with one binding.
Subclass DetailStoreContract and register the adapter under altar.detail_stores. The SQLite reference
adapter stores canonical JSON rows behind indexed model, table, variant, and logical-key columns. The
BigQuery reference adapter uses the same schema-independent shape in fixed warehouse tables and staged
MERGE writes. A backend may instead use native columns only when it can preserve exact schema/plugin
collision detection and evolve arbitrary binding-declared schemas without migration ambiguity.