Artifacts and schemas¶
Every stage communicates through schema-versioned files under one run directory, and this page is the file-level contract: where each file lives, which schema its records carry, and the exact fields of every schema. The reasoning behind the design is in Artifacts as the interface; this page is for looking things up while staring at a run directory.
The run directory¶
Everything a run produces lives under <artifact_root>/runs/<run_id>/:
<artifact_root>/runs/<run_id>/
├── config.resolved.yaml the frozen config (sommelier.config.v2 as YAML);
│ its SHA-256 is the config_sha256 every manifest carries
├── manifest.json run manifest: stage → stage-manifest path, run status
├── data_manifest.json stage manifests, one per stage, at the run root
├── format_manifest.json
├── tokenization_manifest.json
├── train_manifest.json
├── eval-base_manifest.json
├── eval-adapter_manifest.json
├── report_manifest.json
├── data/
│ ├── train.jsonl sommelier.prepared_example.v2, all languages in one file
│ ├── validation.jsonl
│ ├── test.jsonl
│ ├── drop_summary.json sommelier.drop_summary.v2: what was filtered per language, and why
│ └── source_inputs/ checksummed raw root/paired rows plus translation
│ summary and publication manifest; full Hebrew
│ also has review template + finalized review
├── formatted/
│ ├── train.jsonl sommelier.formatted_example.v2
│ ├── validation.jsonl
│ └── test.jsonl
├── analysis/
│ └── tokenization/
│ ├── tokenizer_tax_records.jsonl sommelier.tokenizer_tax_record.v1
│ └── tokenizer_tax_report.json sommelier.tokenizer_tax_report.v1
├── train/
│ ├── adapter/ LoRA adapter weights as saved by peft
│ └── training_metrics.jsonl sommelier.training_metric.v1, one record per logged step
├── eval/
│ ├── base/
│ │ ├── generations.<slice>.jsonl sommelier.generation.v2, one record per test prompt, one file per language slice
│ │ ├── inference_telemetry.json sommelier.inference_telemetry.v2
│ │ └── evaluation_report.json sommelier.evaluation_report.v3
│ └── adapter/ the same generations, telemetry, and report files, model_kind "adapter"
├── report/
│ ├── comparison_report.json sommelier.comparison_report.v3 (authoritative)
│ └── comparison_report.md human rendering of the JSON report
└── runtime_metadata.json sommelier.runtime_metadata.v1: wall clock, GPU, cost evidence
Details worth knowing:
- Stage manifests sit at the run root, named
<stage>_manifest.json. Base and adapter evaluation use distincteval-baseandeval-adapterstages, so neither arm overwrites the other's manifest and both remain joined from the run manifest to their generation, telemetry, and report artifacts. - The manifest schema reserves a failed shape:
status: "failed"pluserror_codeanderror_message, redacted at build time (any secret-looking fragment replaces the whole message withstage failed; details redacted). Current stages fail by raising instead of writing one, so a missing stage manifest means the stage did not succeed. sommelier release preflightwritesrelease_preflight.jsonat the selected artifact root itself, not inside a run. The v2 identity certifies every regular file under that root except the report itself, so adapter publication runs it against the final curated bundle rather than a broader run tree.- Structured JSONL logging (
sommelier.log_event.v1) is designed as the source of truth for events, with console output as a rendering. In the current pipeline only the serving endpoint writes such a log (train/logs/serve.jsonl, next to the adapter it serves); the pipeline stages themselves do not write a run-rootlogs/directory.
Schema catalog¶
SUPPORTED_SCHEMAS in sommelier/artifacts.py is the closed set used by the generic JSON/JSONL readers; the code is authoritative for its current size. Parser/runtime identities and the provider, diagnostic, and publication-transaction contracts use dedicated validators or writers and live outside that set, as marked below. Superseded versions, including v1/v2 evaluation and comparison reports and the v1 translation summary, stay in the set with no current writer so artifacts from earlier runs keep validating.
| Schema id | One record is | Written by |
|---|---|---|
sommelier.config.v2 |
the resolved run configuration (config.resolved.yaml) |
run-directory creation, before any stage runs |
sommelier.manifest.v1 |
a stage manifest or the run manifest | every stage |
sommelier.raw_tool_call_row.v1 |
one untrusted source row: query plus raw tools/answers JSON strings, plus source_example_id on paired-source rows |
produced upstream (dataset export, fixtures); consumed by data prepare |
sommelier.prepared_example.v2 |
one validated example with parsed tools, gold call, language, and split assignment | data prepare |
sommelier.drop_summary.v2 |
per-language counts of dropped rows per drop reason, plus split accounting | data prepare |
sommelier.formatted_example.v2 |
one rendered prompt/target pair with its language and prompt digest | format build |
sommelier.generation.v2 |
one raw model output with its language, parse status, and decoding config | eval run |
sommelier.inference_telemetry.v1 |
superseded inference telemetry boundary retained for older artifacts | no current writer |
sommelier.inference_telemetry.v2 |
sequential end-to-end generator-call elapsed time, one untimed warmup, configured GPU label, decoding, and artifact binding for one evaluation arm | eval run |
sommelier.evaluation_report.v3 |
the five metrics per slice and overall, model identity, and exact paired-language cohorts with confidence intervals | eval run |
sommelier.comparison_report.v3 |
the gated base-versus-adapter comparison with adapter-gain intervals, primary paired gaps, and labeled marginal gaps | report compare |
sommelier.experiment_report.v1 |
historical three-arm experiment report retained for generic artifact inspection; not accepted for current release/publication | historical readers only |
sommelier.experiment_report.v2 |
gated base/v1/v3 evidence, independently recomputed marginal and exact matched-pair metrics, paired intervals, bounded TCO evidence, and machine-readable claim decisions | report experiment; current release/publication validators |
sommelier.evaluation_release_evidence_manifest.v1 |
closed privacy policy, experiment-report digest, arm/cohort identities, source hashes, and exact released-file allowlist | report experiment; dedicated publication validator |
sommelier.evaluation_metric_components.v1 |
one privacy-minimized row index plus additive numerator/denominator components for all five metrics | report experiment; dedicated publication validator |
sommelier.training_metric.v1 |
one training log step (loss, learning rate, tokens) | train run |
sommelier.translation_summary.v2 |
a paired-dataset build's target policy, input/output digests, translator request identity, decoding, and drop counts | data translate |
sommelier.translation_run_identity.v1 |
exclusively reserved full-Hebrew pre-provider identity binding exact config, reviewer, selection, translator, provider, source, and allocation identity | remote_translate.py; dedicated exact-match validator |
sommelier.openai_responses_provider_journal.v2 |
one raw provider response, error, or replay event with source-id/attempt attribution, returned identity, completion status, usage, and output bytes where applicable | remote_translate.py OpenAI backend; dedicated validator |
sommelier.openai_responses_provider_journal_summary.v2 |
a content-free validated aggregate of one raw provider journal | provider-evidence builder; dedicated validator |
sommelier.openai_provider_evidence.v2 |
journal digest, exact requested/returned model and tier, clean counts, complete usage, and calculated public-list-price boundary | nested in translation_summary.json; dedicated validator |
sommelier.translation_semantic_review_template.v1 |
machine-locked 200-row Hebrew sample and immutable back-translations before reviewer edits | semantic-review-create |
sommelier.translation_semantic_review_attestation.v1 |
canonical reviewer identity, decision digest, recomputed back-translation receipt, gate counts, and human statement submitted for an OpenSSH signature | semantic-review-attestation-create; dedicated signature validator |
sommelier.translation_semantic_review.v1 |
locked 200-row Hebrew back-translation sample, immutable model/input identities, human-signed attestation, review decisions, and whole-publication gate | semantic-review release gate |
sommelier.translation_publication_manifest.v1 |
canonical paired-row identity and digests binding the summary and finalized semantic review at publication | translation publication |
sommelier.tokenizer_tax_record.v1 |
exact per-example query/prompt/target/full token counts and ratios to its root | analyze tokenization |
sommelier.tokenizer_tax_report.v1 |
per-language distributions, matched-pair coverage and ratios, budget counts, and projected non-padding workload | analyze tokenization |
sommelier.sovereign_tco_evidence.v1 |
evidence-joined tokenizer, QLoRA training/storage, and three-arm inference-efficiency measurements with unavailable fields kept explicit | nested in report experiment |
sommelier.log_event.v1 |
one structured log line | stage loggers (the serving endpoint logs with it) |
sommelier.release_preflight.v1 |
historical unbound release-gate results | no current writer; readable for inspection only |
sommelier.release_preflight.v2 |
release gates plus exact config, revision, source, lock, and artifact-tree identity | release preflight; strict adapter-publication validator |
sommelier.qlora_shape_preflight.v1 |
diagnostic-only full-shape QLoRA execution, hardware, memory, and failure/success evidence | remote_qlora_preflight.py; dedicated validator/writer |
sommelier.qlora_shape_preflight_artifact_manifest.v1 |
stable digests of the non-recursive diagnostic artifact set | QLoRA shape preflight; dedicated validator/writer |
sommelier.huggingface_publication_receipt.v1 |
validation plan or durable pending / commit_submitting / commit_returned_unverified / verified Hub transaction journal with exact file hashes and parent/created commits |
release publish-dataset / publish-adapter; preallocated dedicated writer |
sommelier.parser.v1 |
not a file schema: the version string of the tool-call parser, recorded in the eval config and every evaluation report | eval run |
sommelier.runtime_metadata.v1 |
per-stage wall clock, hardware, and cost evidence | pipeline run |
Readers fail closed¶
read_json_with_schema and read_jsonl_with_schema require a schema_version on every JSON object and every JSONL line, and that version must be in SUPPORTED_SCHEMAS. A missing, unknown, or unexpected version raises SchemaValidationError (SOM202, exit 2) naming the file and line; see the error reference. There is no best-effort mode: an artifact from a different pipeline version is rejected, not reinterpreted.
The ids outside the closed set behave differently by design.
sommelier.parser.v1 is a version string, not a file format.
sommelier.runtime_metadata.v1 has its own reader that treats an unknown
version as absent evidence: the comparison report then renders its runtime
section as {"available": false} instead of failing, because missing cost data
should never block a metrics comparison. The OpenAI journal, journal summary,
and provider-evidence v2 contracts have strict dedicated validators; an unknown
schema, malformed attribution, mixed model/tier, incomplete usage, or dirty
full-run evidence fails the translation publication gate.
The QLoRA shape-preflight report/manifest and Hugging Face publication receipt
also stay outside the generic stage-artifact registry. Their producers validate
their complete closed contracts directly. The QLoRA digest manifest covers
every regular run-directory file present at finalization except the report and
manifest themselves, which cannot recursively hash their own final bytes;
the validator rehashes the on-disk set and rejects additions, omissions,
reordering, malformed paths, or digest drift. Publication receipts are reserved
with exclusive creation before any Hub access, then durably advance through
pending, commit_submitting, commit_returned_unverified, and finally
verified only after immutable-revision enumeration and per-file round-trip
SHA-256 succeeds.
For Modal pipeline runs, remote_execution.function_timeout_seconds is the
provider-enforced outer deadline. The adjacent
configured_stage_planning_estimate_seconds and
outer_timeout_planning_headroom_seconds values are arithmetic planning
evidence, not stage deadlines; per_stage_watchdogs_enforced is recorded as
false explicitly.
Record schemas¶
Field lists below are verified against the code; the config schema has its own page.
sommelier.raw_tool_call_row.v1¶
| Field | Type | Notes |
|---|---|---|
source_id |
str | identifier of the row in the source dataset |
query |
str | the natural-language request |
tools |
str | raw JSON string, untrusted until validation |
answers |
str | raw JSON string, untrusted until validation |
source_revision |
str | the pinned dataset revision the row came from |
source_example_id |
str, optional | paired-source rows only: the root example this row translates |
sommelier.prepared_example.v2¶
| Field | Type | Notes |
|---|---|---|
example_id |
str | stable per-example identifier, unique across languages |
source_id |
str | carried through from the raw row |
language |
str | the dataset source this example came from |
source_example_id |
str | null | on paired rows, the root example this row translates; null on root rows |
query |
str | the request text |
tools |
list[ToolSchema] | parsed {name, description, parameters} objects |
gold_calls |
list[ToolCall] | parsed {name, arguments}; exactly one call |
split |
train | validation | test |
a query_sha256 appears in exactly one split; paired rows share their root's split |
query_sha256 |
str | digest of the normalized query, the per-language dedupe key |
source_revision |
str | pinned dataset revision |
sommelier.drop_summary.v2¶
| Field | Type | Notes |
|---|---|---|
languages |
dict | per language: counts per drop reason, valid_rows, deduplicated_rows, and final split_sizes |
requested |
dict | the configured train/validation/test sizes (they describe the root source; paired sources may run short) |
sommelier.formatted_example.v2¶
| Field | Type | Notes |
|---|---|---|
example_id, split |
str | join keys back to the prepared example |
language |
str | carried from the prepared example; evaluation slices filter on it |
source_example_id |
str | null | carried from the prepared example |
messages |
list | {role, content} for system, user, assistant |
prompt_text |
str | system and user messages rendered with the generation prompt |
target_text |
str | the canonical JSON of the gold calls, nothing else |
full_text |
str | all three messages rendered; must start with prompt_text |
prompt_sha256 |
str | SHA-256 of prompt_text; proves prompt identity later |
tokenizer_id, tokenizer_revision |
str | which tokenizer rendered the template |
template_policy |
str | tokenizer_chat_template |
sommelier.generation.v2¶
| Field | Type | Notes |
|---|---|---|
example_id |
str | must reference a formatted test example |
model_kind |
base | adapter |
which model produced the output |
language |
str | the evaluation slice this generation belongs to |
prompt_sha256 |
str | must equal the formatted example's digest (INV-ARCH-004) |
raw_text |
str | the full generation, retained even on parse failure |
parsed_call |
ToolCall | null | null whenever parse_status is not ok |
parse_status |
ok | no_json | invalid_json | invalid_shape |
see the metric reference |
decoding |
dict | {temperature, do_sample, max_new_tokens}; must be uniform across the file |
sommelier.evaluation_report.v3¶
| Field | Type | Notes |
|---|---|---|
created_at, run_id, model_kind |
str | report identity |
model_identity |
dict | pinned base model and tokenizer ids/revisions; checked by the comparison gate |
config_sha256 |
str | digest of config.resolved.yaml |
split |
test |
the only split evaluation reads |
slices |
dict | per language: metrics, examples, prompt_set_sha256, and the generation_artifact path |
paired_slices |
dict | per target language: exact pair count/coverage/digest, root and target metrics, target-minus-root gaps, and deterministic paired-bootstrap intervals |
metrics |
dict | the five metric names across all slices, mapped to {value, numerator, denominator} |
adapter_source |
dict | null | on adapter reports, where the weights came from, plus a local tree digest or immutable-revision signal when available |
parser_version |
sommelier.parser.v1 |
checked by the comparison gate |
test_split_sha256 |
str | digest of the formatted test split file |
decoding |
dict | the uniform decoding config of the generations |
The identity the comparison gate checks is model_identity, config_sha256, split, test_split_sha256, parser_version, decoding, the slice set, every slice's prompt_set_sha256, and every translated slice's pair_set_sha256. Generation artifact paths are evidence, not identity.
sommelier.inference_telemetry.v2¶
Each evaluation arm writes one inference_telemetry.json next to its
generations. It binds the two generation artifacts, deterministic decoding,
configured GPU label/count, and per-slice and total elapsed time. The clock
scope is the sum of sequential per-example, end-to-end
TextGenerator.generate calls after model load. The default Transformers
implementation includes prompt tokenization, input device transfer,
model.generate, and generated-token decoding, and does not insert an explicit
device synchronization. Exactly one call using the first example in the first
configured slice warms the same path before measurement; its output is
discarded and the clock is not read around it. Model loading, parsing, and
artifact I/O are excluded, concurrency is one, and English then Hebrew slice
order is recorded. Derived GPU-seconds per exact successful call therefore
describes this bounded configured-allocation path, not kernel-only model time or
serving throughput under batching or concurrency.
sommelier.comparison_report.v3¶
| Field | Type | Notes |
|---|---|---|
created_at, run_id |
str | report identity |
shared |
dict | the identity fields both evaluation reports agreed on |
base, adapter |
dict | each holds run_id, overall metrics, and adapter provenance where applicable |
deltas |
dict[str, float] | adapter value minus base value, per metric |
adapter_gain_ci95 |
dict | paired-bootstrap method/seed/resample contract and overall per-metric intervals |
slices |
dict | per-language base/adapter metrics, deltas, adapter-gain intervals, prompt digest, and generation paths |
paired_language_gaps |
dict | primary target-minus-exact-root estimates, pair coverage/digest, and base/adapter intervals |
language_gaps |
dict | descriptive complete-slice gaps labeled marginal_full_slices; cohorts can differ |
runtime |
dict | from runtime_metadata.json; {"available": false} when missing |
Tokenizer-tax schemas¶
Every sommelier.tokenizer_tax_record.v1 line carries the example/root identity, language, split, counts for query characters/UTF-8 bytes/whitespace words and query/prompt/target/full tokens, the sequence-budget result, and ratios to the exact root for translated rows.
sommelier.tokenizer_tax_report.v1 binds those records to the config digest, tokenizer id/revision, formatted-split checksums, and maximum sequence length. Its languages section reports mean, p50, p95, p99, max, totals, token rates, and over-budget counts. pairing reports exact root-matched coverage and aggregate/per-pair ratios by language and split. training_workload retains the configured combined examples and non-padding full tokens, and Hebrew en+he runs also carry english_only_counterfactual, additive hebrew_increment, and combined_vs_english_only. The Hebrew block reports its example/token ratios to English; the combined block reports the corresponding multipliers. Counts are re-derived from train records, the combined counts must equal English plus Hebrew, and every projected count must equal its per-epoch count times the configured epochs. Dynamic padding is excluded: these are deterministic lower-bound workload projections, not billed-token, wall-time, or separately trained English-only estimates.
Final Hebrew adapter publication independently closes the nested TCO contract: paired scope counts must match the observed data cohorts and sum across splits; training and inference measurements must be finite, non-negative, and arithmetically consistent; inference must retain the preregistered timing boundary; and every TCO source must carry its expected run-relative path, hash, schema, and positive byte count.
Translation publication schemas¶
Before a full Hebrew producer accesses the dataset or provider,
translation_run_identity.json is exclusively reserved under
artifacts/translation/<run-id>/. Its sommelier.translation_run_identity.v1
payload is a closed exact-match contract over the submitted config digest and
preregistered reviewer, selection, translator request and implementation
revision, backend-specific provider/resource fields, and clean source identity.
A progress-only resume must match the complete object; unknown, missing, or
changed fields fail before provider construction. The exact submitted config
bytes are retained beside it as config.yaml. Public dataset assembly copies
those bytes without reserialization to translation_config.yaml and includes
both files in the exact publication allowlist.
sommelier.translation_summary.v2 records the accepted-row digest and
canonical publication identity, target-script/bidi policy, retry/drop counts,
source selection, clean implementation revision, translator model revision,
request digest, explicit interface, trust_remote_code, output decoder, and
postprocessing/audit schemas. Provider-backed summaries additionally record the
transport independently of the prompt family, the exact dated API snapshot,
provider SDK/request identity, explicit requested and returned service tier,
900-second request timeout, zero SDK retries, worker/chunk contract, CPU runtime, and nested
sommelier.openai_provider_evidence.v2. Its v2 accounting publishes both the
maximum canonical request-body UTF-8 byte proxy and the independently observed
maximum response usage.input_tokens; both must remain within the pinned
base-rate boundary. The dated snapshot is not a public
weight digest or a guarantee of byte-identical provider regeneration. The
request identity also pins the protected-
placeholder schema used by chat translators. For the generic instruction-chat
interface it additionally pins the v1 selected-tool semantic-context builder:
a unique case-sensitive exact gold-call-name match, name/description plus
sorted parameter name/type/description projection, canonical ASCII JSON with
HTML delimiters escaped, the 8,192-character fail-closed bound, and the inert
non-output/non-executable envelope. Missing or duplicate exact tool names are
checkpointed as invalid_row. TranslateGemma and MADLAD identities explicitly
pin semantic context to none; their structured and raw-source formats are
unchanged. The complete source-row digest binds the actual tools and
answers bytes, while the request digest binds the builder policy, so neither
a schema edit nor an old instruction-chat checkpoint can be silently reused.
The audit schema pins
boundary-matched extraction of direct values and comma-delimited components,
explicit code-like function names, source list/dict literals proven equivalent
to gold structures, the Hebrew/Latin-only unprotected-script policy, and
rejection of the Unicode replacement character as corrupt output.
sommelier.openai_responses_provider_journal.v2 is the private durable replay
surface for the selected Hebrew provider. Every response, request-error, and
replay event has top-level attribution with a non-empty source_id and
positive attempt. Those producer-local fields are excluded from the provider
body and request hash. Identical bodies may coalesce, but each consumer receives
its own attributed replay record. Terminal row progress records
accepted_attempt for accepted output or final_attempt after an exhausted
drop. Responses are fsynced before the row pipeline receives them; the Modal
volume is committed at the 32-row chunk boundary. This is not exactly once: a
hard kill can lose the current uncommitted chunk, and a death after provider
acceptance but before receipt/fsync can repeat a billed request.
The raw journal contains decoded output and provider ids. It remains in the
durable producer artifacts and is not part of the public paired dataset. Its
content-free sommelier.openai_responses_provider_journal_summary.v2 feeds the
nested provider evidence, which publishes the journal SHA-256, identity,
counts, usage, both input-bound maxima, and a cost calculated from the pinned
public price table. Full-publication validation binds the runtime ceiling to
that calculated value. The USD value is a local estimate, not an invoice,
observed billing, or provider account/project cap. store=false is recorded but is
not evidence of Zero Data Retention, and strict structured output is not a
semantic-accuracy guarantee.
For Hebrew full publication,
sommelier.translation_semantic_review_template.v1 binds the full paired-row
corpus and summary to a deterministic 200-row sample selected before judgments.
It records the pinned independent Helsinki-NLP OPUS-MT Marian back-translator
and every locked machine input. The template also locks the named human
reviewer's stable id, canonical comment-free Ed25519 public key, and matching
OpenSSH fingerprint from the exact committed Phase-A config. A reviewer edits
only a copy's rubric fields. semantic-review-attestation-create independently
recomputes the pinned back-translations and emits the canonical
sommelier.translation_semantic_review_attestation.v1 payload. The named human
signs that file with OpenSSH namespace
sommelier-hebrew-v3-semantic-review; the private key never enters the
repository, Modal, Sommelier, or Codex. Finalization verifies the signature and
all locked bytes against the untouched template, then writes
sommelier.translation_semantic_review.v1 with the attestation, signature,
non-native reviewer boundary, decision digest, and zero-critical-error
whole-publication gate. The semantic sample cannot be used to remove a failed
row and resample.
sommelier.translation_publication_manifest.v1 is the bridge from local build
to immutable Hub commit. It binds the canonical paired rows and SHA-256 digests
of the translation summary, untouched machine template, and finalized semantic
review. Finalization writes a fresh translation_publication.reviewed.json; it
never overwrites the stale initial translation manifest. Dataset assembly must
copy that reviewed file into a fresh bundle under the canonical name
translation_publication.json. The exact public allowlist is README.md,
rows.he.jsonl, translation_summary.json, translation_publication.json,
translation_semantic_review_template.json,
translation_semantic_review.json, translation_config.yaml, and
translation_run_identity.json. A full remote run downloads and validates the
complete chain, including proof that Phase B changed only the immutable Hebrew
dataset revision from the exact Phase-A config, and fails before preparation if
any identity or gate differs. Direct
--translation-run-id staging is smoke-only. For provider translation, the
published summary contains the content-free provider evidence and raw-journal
digest; the raw journal itself stays out of the Hub commit.
sommelier.experiment_report.v2¶
The Hebrew three-arm report binds base, the exact preregistered v1 English
adapter, and the canonical train-manifest-bound local v3 English+Hebrew adapter
to one independently verified evaluation identity. data_provenance traverses
the exact root rows, paired rows, translation summary, publication manifest,
untouched semantic template, finalized review, succeeded data manifest,
prepared splits, format manifest, formatted splits, tokenizer-tax manifest,
and adapter evaluation input. Every edge is an observed path, byte count, and
SHA-256 reference. It also records the requested and observed full cohort
counts, immutable dataset revisions, zero-critical semantic gate, and clean
source revision.
arms includes metrics and SHA-256 evidence for the formatted split,
generations, and evaluation report. Version 2 additionally retains each arm's
exact matched English-Hebrew slice under paired_slices.he, including the
target-row-to-reference-row mapping identity, coverage, reference and target
metrics, target-minus-reference gaps, and deterministic paired-bootstrap
intervals. The shared evaluation identity binds the common pair-set and ordered
reference-index digests. comparisons.v3_vs_v1 contains English and Hebrew
deltas plus paired-bootstrap contracts. claims stores the estimate, interval,
criterion, pass decision, and predeclared English margin; a human-readable
statement exists only for a passed gate. approved_claims and
all_claims_passed therefore cannot imply success when either bound fails.
The report finalizer itself must run from that same clean immutable source
revision; preregistration.finalizer_source_code records the check before any
outcome artifact is loaded.
sommelier.experiment_report.v1 remains in the generic schema registry so old
artifacts can be inspected. The current finalizer emits v2, and release and
publication validation reject v1 evidence rather than inferring the missing
matched-pair identity.
Its sovereign_tco_evidence field has schema
sommelier.sovereign_tco_evidence.v1. The builder revalidates the resolved
config, tokenization/train/evaluation manifests, exact artifact paths and
hashes, adapter tree, runtime metadata, deterministic decoding, hardware
labels, and inference telemetry before joining them. It distinguishes observed
training/storage/timing values from the deterministic non-padding-token
projection. Cross-arm inference comparability additionally requires identical
observed runtime package versions. Currency cost is forbidden without observed billing evidence, and
full-fine-tuning savings are forbidden without a matched full-parameter arm;
both stay machine-readably unavailable otherwise.
Evaluation release evidence¶
report experiment also writes this fresh sibling tree:
evaluation_evidence/
├── manifest.json
├── base/
│ ├── correctness.en.jsonl
│ ├── correctness.he.jsonl
│ ├── evaluation_manifest.json
│ └── inference_telemetry.json
├── v1_en/ same four files
└── v3_en_he/ same four files
Each correctness row is exactly schema_version, zero-based row_index, and
the additive {numerator, denominator} contribution for all five metrics.
It deliberately excludes example IDs, prompt/target text, gold or parsed
calls, and generated text. The manifest binds row order to the shared ordered
example-ID and prompt-set digests, records original formatted/generation/report
paths and hashes, and hashes every released metadata file. Its opaque Hebrew
row-position to English-row-index map is type/range/uniqueness checked and
digest-bound, allowing the exact matched English baseline to be reconstructed
without publishing example IDs or content. The copied stage
manifest and telemetry preserve source revision, config, decoding, generation
hash, hardware, timing, and count evidence without publishing model outputs.
Adapter publication requires this exact tree. Its dedicated validator rejects
missing or extra files, noncanonical rows, checksum or identity drift, stale
report bindings, and inconsistent component semantics. It then recomputes all
arm/slice/overall metrics, v3-vs-v1 deltas, seeded paired-bootstrap intervals,
exact matched Hebrew-minus-English gaps and intervals, and exact McNemar counts
and p-values before Hub access. These two schemas are publication contracts
outside the generic SUPPORTED_SCHEMAS registry.
sommelier.manifest.v1¶
Stage manifest fields:
| Field | Type | Notes |
|---|---|---|
stage |
data | format | tokenization | train | eval | eval-base | eval-adapter | report | serve |
pipeline evaluations use the two arm-specific names |
run_id, created_at, git_commit |
str | git_commit is unknown outside a repo |
config_sha256 |
str | ties the stage to the resolved config |
dependency_lock_sha256 |
str | null | SHA-256 of uv.lock, null when absent |
command |
list[str] | the CLI invocation that produced the outputs |
seed |
int | project.seed |
inputs, outputs |
list[ArtifactRef] | every file read and written, with checksums |
status |
succeeded | failed |
failed manifests add error_code and a redacted error_message |
The run manifest (manifest.json) shares the schema id and carries run_id, stages (stage name to stage-manifest path), config (an ArtifactRef to the resolved config), status (running, succeeded, or failed), and an optional tracking object with the external tracker's provider, project, and run URL.
sommelier.log_event.v1¶
| Field | Type | Notes |
|---|---|---|
timestamp |
str | UTC ISO 8601 |
level |
debug | info | warning | error |
|
run_id, stage, event |
str | correlation keys for offline joins |
message |
str | redacted before writing |
fields |
dict | JSON-native scalars only; non-finite floats are rejected at write time |
sommelier.training_metric.v1¶
| Field | Type | Notes |
|---|---|---|
step |
int | trainer global step |
epoch |
float | position within training |
train_loss, eval_loss |
float | null | non-finite values fail closed instead of being persisted |
learning_rate |
float | |
tokens_seen |
int | cumulative input tokens |
peak_gpu_memory_mb |
int | null | run-level measurement, recorded on the final record only |
sommelier.release_preflight.v2¶
| Field | Type | Notes |
|---|---|---|
schema_version |
str | exactly sommelier.release_preflight.v2 |
created_at |
timezone-aware str | report creation time |
status |
pass | fail |
the report is written even when gates fail, provided the artifact root itself is a safe writable directory |
identity.config |
object | canonical normalized-config algorithm, SHA-256, and byte count |
identity.model |
object | exact base-model and tokenizer revisions plus immutability decisions |
identity.datasets |
list | ordered root/paired dataset ids, languages, revisions, and immutability decisions |
identity.source_code |
object | Git discovery mode, commit or explicit unknown, clean-state decision, and status digest; hidden index flags such as assume-unchanged or skip-worktree prevent a clean certification, and strict adapter publication requires an immutable commit and working_tree_clean: true |
identity.dependency_lock |
object | SHA-256 and byte count for working-tree uv.lock bytes that Git's configured clean filters map to the blob at the certified commit; unavailable outside that exact Git repository or on mismatch |
identity.artifact_tree |
object | canonical tree SHA-256, file/byte counts, certification status, a second content read that detects same-size mutation independently of timestamps, and the sole release_preflight.json exclusion |
gates |
list | each gate is {name, status, evidence} with status pass, fail, or skip |
The generic reader retains v1 for historical inspection. The adapter publisher accepts only the closed v2 contract, requires all eight gates to pass, and recomputes the config and exact on-disk bundle identities while also matching the clean training source revision and training lock digest.
ArtifactRef and the relative-path rule¶
Every input and output in a manifest is an ArtifactRef:
| Field | Type | Notes |
|---|---|---|
path |
str | POSIX path relative to the artifact root |
kind |
str | e.g. dataset_split, formatted_split, generations, adapter_weights |
schema_version |
str | empty for schema-less files such as adapter weights |
sha256 |
str | checksum of the file bytes |
bytes |
int | file size |
Paths are always relative to the artifact root, so a run directory can be moved, archived, or published without breaking its own manifests. Building a ref for a path outside the artifact root raises SchemaValidationError; absolute paths never appear in input or output references (the command field records the argv verbatim, including any absolute paths you passed).
Writes validate a supplied artifact-root boundary before any filesystem mutation or writer call. The writer receives a path inside a cryptographically random private staging directory; its regular-file output is opened without following symlinks, copied to an exclusive mode-0600 staging file, and read again to detect content changes without relying on timestamps. The staged file is flushed, atomically replaced into the final name, and the parent directory is flushed where supported. Ordinary failures clean up; a hard process stop can leave a private staging directory, but not a half-written final artifact.
Run IDs¶
create_run_id produces <UTC timestamp>-<8 hex chars>, for example 20260702T091500Z-1a2b3c4d (format %Y%m%dT%H%M%SZ plus the first 8 characters of a UUID4). Smoke pipeline runs get a smoke- prefix so a later full run can never overwrite smoke artifacts. When a CLI command is pointed at a path inside a run and --run-id is omitted, the run ID is inferred from the path with the pattern /runs/([^/]+)/.