Closed record of one local qualification run: source identity, execution envelope, selected backend and device, optional model identity, workload inputs, effective configuration, case outcomes, measurements, and hashed evidence. The Python validator enforces cross-field verdict, timestamp, platform, model, source, and artifact rules beyond this JSON Schema. A receipt is unsigned and has no self-digest; validate it and independently establish custody before treating it as trusted evidence.
Schema identity
| Property | Value |
|---|---|
| Title | Kiln local qualification receipt |
$id |
https://kiln.local/schemas/qualification-receipt-v1.json |
| Dialect | https://json-schema.org/draft/2020-12/schema |
| Root type | object |
| Root object | closed |
Root fields
| Field | Required | Type | Constraints and default | Description |
|---|---|---|---|---|
schema_version |
yes | any |
const 1 | Qualification receipt contract version. The validator accepts only version 1. |
receipt_id |
yes | string |
pattern ^[a-z0-9][a-z0-9._-]{2,127}$ | Stable receipt label generated from time, backend, host, workload, and variant identity. It names the record but is not a content hash, signature, or uniqueness proof. |
created_at_utc |
yes | timestamp |
- | UTC time when the receipt was created. The semantic validator requires it not to precede qualification.finished_at_utc. |
source |
yes | object |
closed object | Identity of the source inputs and Git state observed for the run. The source-tree digest covers a defined repository subset; it does not hash this receipt, model files, result artifacts, or historical receipts. |
qualification |
yes | object |
closed object | Runner-owned summary of the qualification category, backend family, profile, final verdict, wall-clock interval, and argv invocation. |
environment |
yes | object |
closed object | Host, operating-system, selected-device, runtime, compiler, and optional platform-specific observations captured around the run. These observations identify the measured environment; they are not a portable device allowlist. |
model |
yes | null | model |
- | Model and tokenizer content identity for the measured run, or null when no model applies or a failed run could not establish it. Passed serving, performance, training, eval, and soak receipts require this object. |
workload |
yes | null | workload |
- | Committed workload identity, seed, and resolved parameters, or null only for environment qualification. The digest identifies the exact workload file bytes. |
effective_config |
yes | configObject |
- | Configuration the command-produced cases proved they actually used. The local runner copies the selected variant only when every command-owned case reports an exact match; otherwise this object is empty and affected results fail. |
results |
yes | array<result> |
minimum items 1 | Runner-normalized, repetition-aggregated case outcomes in workload order. Required result status determines the receipt verdict; a passed receipt cannot contain a failed or skipped required result. |
metrics |
yes | array<metric> |
- | Optional run-level measurements. The local workload runner currently emits case measurements under results and leaves this array empty; consumers must not silently combine the two scopes. |
artifacts |
yes | array<artifact> |
- | Content-addressed evidence files for probes, model fingerprints, command output, normalized case results, and effective run configuration. Hash verification is opt-in for local_ignored files and is not performed for external locations. |
unsupported |
yes | array<string> |
- | Non-empty capability or probe limitations reported by environment capture. Entries explain missing evidence; they do not automatically change the verdict. |
notes |
yes | array<string> |
- | Non-empty runner annotations about this record, including receipt downgrades. Notes are explanatory text, not signed assertions or machine-enforced policy. |
Composition and conditional rules
Show exact composition rules
{
"allOf": [
{
"if": {
"properties": {
"qualification": {
"properties": {
"kind": {
"not": {
"const": "environment"
}
}
},
"required": [
"kind"
]
}
},
"required": [
"qualification"
]
},
"then": {
"properties": {
"workload": {
"$ref": "#/$defs/workload"
}
}
}
},
{
"if": {
"properties": {
"qualification": {
"properties": {
"kind": {
"enum": [
"serving",
"performance",
"training",
"eval",
"soak"
]
},
"verdict": {
"const": "passed"
}
},
"required": [
"kind",
"verdict"
]
}
},
"required": [
"qualification"
]
},
"then": {
"properties": {
"model": {
"$ref": "#/$defs/model"
}
}
}
}
]
}
Definitions
capabilityStatusWhether a platform-specific probe established the named capability. For observed WSL2 and macOS capabilities, this declaration must agree with the corresponding evidence.0 fields
Type: any. Constraints: enum "available", "unavailable".
configValueOne finite JSON scalar, null, or recursively nested configuration object. List values are excluded so comparison code can address leaves with unambiguous dot paths.0 fields
Type: string | number | boolean | null | configObject.
Composition and conditional rules
The following JSON is copied exactly from this schema node.
{
"oneOf": [
{
"type": [
"string",
"number",
"boolean",
"null"
]
},
{
"$ref": "#/$defs/configObject"
}
]
}
configObjectConfiguration namespace with lowercase, dot-path-compatible keys and finite scalar, null, or nested-object values.0 fields
Type: object.
Composition and conditional rules
The following JSON is copied exactly from this schema node.
{
"propertyNames": {
"pattern": "^[a-z][a-z0-9_-]*$"
},
"additionalProperties": {
"$ref": "#/$defs/configValue"
}
}
timestampUTC RFC 3339 timestamp ending in Z, with optional fractional seconds. The Python validator parses the value and enforces relevant ordering relationships.0 fields
Type: string. Constraints: pattern ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:.\d+)?Z$.
sha256SHA-256 digest written as sha256: followed by 64 lowercase hexadecimal characters. Syntax alone does not verify the referenced content.0 fields
Type: string. Constraints: pattern ^sha256:[0-9a-f]{64}$.
nonemptyStringMapNon-empty object of non-empty string values used for probe-reported runtime, compiler, or platform detail identities.0 fields
Type: object. Constraints: minimum properties 1.
Composition and conditional rules
The following JSON is copied exactly from this schema node.
{
"additionalProperties": {
"type": "string",
"minLength": 1
}
}
nullableSha256A SHA-256 content digest or null when the corresponding optional input does not exist.0 fields
Type: sha256 | null.
Composition and conditional rules
The following JSON is copied exactly from this schema node.
{
"oneOf": [
{
"$ref": "#/$defs/sha256"
},
{
"type": "null"
}
]
}
weightFileOne model weight shard identified by path, byte length, and SHA-256 content digest.3 fields
Type: object. Constraints: closed object.
| Field | Required | Type | Constraints and default | Description |
|---|---|---|---|---|
path |
yes | string |
minimum length 1 | Weight-file path recorded by model fingerprinting. Paths must be unique within the model record. |
sha256 |
yes | sha256 |
- | SHA-256 digest of this weight file's bytes. |
bytes |
yes | integer |
minimum 1 | Positive weight-file size in bytes. |
modelContent identity for the exact model directory observed before and after qualification. The runner fails if the final fingerprint differs from the initial one.6 fields
Type: object. Constraints: closed object.
| Field | Required | Type | Constraints and default | Description |
|---|---|---|---|---|
id |
yes | string |
minimum length 1 | Operator- or workload-selected model label. |
path |
yes | string |
minimum length 1 | Model directory path used by fingerprinting. This is location evidence, not a portable download identifier. |
weight_files |
yes | array<weightFile> |
minimum items 1 | Non-empty set of uniquely named weight shards and their content identities. |
config_hash |
yes | sha256 |
- | SHA-256 identity of the model configuration content selected by fingerprinting. |
tokenizer_hash |
yes | sha256 |
- | Aggregate SHA-256 identity of tokenizer inputs selected by fingerprinting. |
chat_template_hash |
yes | nullableSha256 |
- | SHA-256 identity of the chat template when present, otherwise null. |
workloadIdentity and resolved inputs for the workload contract that produced the receipt.4 fields
Type: object. Constraints: closed object.
| Field | Required | Type | Constraints and default | Description |
|---|---|---|---|---|
id |
yes | string |
minimum length 1 | Workload ID copied from the validated workload contract. |
sha256 |
yes | sha256 |
- | SHA-256 digest of the exact committed workload JSON file bytes. |
seed |
yes | integer | null |
- | Deterministic non-negative seed delivered to each case, or null for a workload that explicitly declares no seed. |
parameters |
yes | object |
- | Resolved run parameters. The local runner records variant_id plus every operator-supplied workload variable. |
metricOne finite measurement and the unit, aggregation, and direction required to interpret it. Metric names must be unique within their containing array.5 fields
Type: object. Constraints: closed object.
| Field | Required | Type | Constraints and default | Description |
|---|---|---|---|---|
name |
yes | string |
pattern ^[a-z][a-z0-9_.-]{0,127}$ | Stable metric identifier declared by the workload result protocol and, when compared, by its metric rule. |
value |
yes | number |
- | Finite observed or repetition-aggregated value. The Python validator rejects NaN and infinity. |
unit |
yes | string |
minimum length 1 | Non-empty measurement unit. Compared metrics must match the committed workload rule exactly. |
aggregation |
yes | string |
minimum length 1 | Non-empty aggregation label. Repeated command metrics are emitted as mean_of_ |
lower_is_better |
yes | boolean |
- | Recorded metric direction. It must match the committed workload rule when the metric participates in comparison. |
resultRunner-normalized outcome for one workload case after all repetitions, output assertions, structured-result checks, and infrastructure checks.6 fields
Type: object. Constraints: closed object.
| Field | Required | Type | Constraints and default | Description |
|---|---|---|---|---|
id |
yes | string |
pattern ^[a-z0-9][a-z0-9._-]{0,127}$ | Unique case ID copied from the selected workload variant. |
required |
yes | boolean |
- | Whether this case gates the receipt verdict. Every required result must pass for the receipt to pass. |
status |
yes | any |
enum "passed", "failed", "skipped" | Final runner-owned case status after command status and runner, contract, source, model, and infrastructure failures are applied. |
duration_seconds |
yes | number |
minimum 0 | Finite sum of runner-observed monotonic durations across this case's repetitions. |
metrics |
yes | array<metric> |
- | Command- or runner-owned measurements aggregated across repetitions. Per-execution advisory tolerances are not copied into this result. |
details |
yes | string | null |
- | Optional bounded diagnostic text combined from case executions and runner or infrastructure failures. |
artifactContent identity for one evidence file referenced by the receipt. The receipt records hashes but does not embed, sign, or automatically retrieve the content.5 fields
Type: object. Constraints: closed object.
| Field | Required | Type | Constraints and default | Description |
|---|---|---|---|---|
kind |
yes | string |
minimum length 1 | Evidence-role label, such as environment_probes, case_stdout, case_result, model_fingerprint, or effective_run_config. |
location |
yes | any |
enum "local_ignored", "external" | Custody class. local_ignored evidence can be verified under .qualification with --require-local-artifacts; external evidence is not fetched or hash-checked by the validator. |
path |
yes | string |
minimum length 1 | Artifact path or external locator. The validator constrains local_ignored paths to .qualification only when local verification is requested. |
sha256 |
yes | sha256 |
- | Claimed SHA-256 digest of the artifact bytes. It is recomputed only for locally verified local_ignored evidence. |
bytes |
yes | integer |
minimum 0 | Claimed artifact size in bytes. It is checked against file length only for locally verified local_ignored evidence. |