Evidence documents
Benchmark, traced-allocation and scientific-validation outputs use the
strict versioned models in hebog.validation.evidence, so measurements keep their provenance without
implying that an exploratory run passed a gate. hebog.validation is
repository tooling, not installed from the wheel; use it from a source
checkout after uv sync --all-groups.
Every document has schema_version (currently 1) and a discriminating
evidence_type; a stable run identifier and timezone-aware timestamp;
exploratory or reviewed status; the dataset identifier, role, content
checksum, (y, x) shape and workload class; the exact configuration
checksum; and strict fields that reject unknown data.
Benchmark evidence
A benchmark document identifies the measured implementation by version
and/or 40-character commit, container image digest where available and a
checksum of the complete installed dependency inventory, with related
Rapthor, LSMTool, Hebog or PyBDSF identities recorded separately; the
environment has its own checksum so runs are never compared on display
versions alone. Each repetition distinguishes warm-up from measured work and
records wall and CPU seconds, peak resident memory, array-copy count and
bytes, Dask task count, and transfer and spill bytes. Wall time, CPU time and
peak RSS are required; optional instrumentation uses null only with a
reason in unavailable_metrics, and zero always means a measured zero. A
reviewed benchmark has at least one warm-up and five measured repetitions.
Resource records hold the executor kind, node/worker/thread topology,
allocated cores, node memory, worker limits, reserved headroom and a
storage identifier; aggregate worker limits must fit inside node memory after
headroom. Reviewed multi-node evidence adds plane count, tile core and
maximum halo, partition and graph task counts, scheduler overhead, worker
occupancy, storage throughput, retries, stragglers and strong- and
weak-scaling efficiency; separate documents per node count form the
controlled scalability curve.
Scientific-comparison evidence
A scientific document identifies candidate and reference software separately
and records a SHA-256 digest of each side's canonical product manifest plus
the beam and match gate the comparison oracle used, so the report is bound to
the exact catalogue, RMS and mask artifacts rather than to the input dataset
alone. It embeds the complete product reports. Released PyBDSF and pinned
master therefore produce separate documents even on the same dataset and
candidate output.
Writing and loading evidence
from pathlib import Path
from hebog.validation.evidence import load_evidence, write_evidence
write_evidence(Path("benchmark-results/run.json"), evidence)
reloaded = load_evidence(Path("benchmark-results/run.json"))
The writer sorts keys, rejects non-finite values, appends a final newline and
replaces the destination only after writing a temporary file.
load_evidence accepts benchmark, scientific-comparison and
traced-allocation documents. A traced-allocation document, which
just traced-peak writes, records each repetition's traced process peak, the
peak of the find_sources call alone and the import floor; the
contribution guide
says when it counts as reviewed.
Raw evidence stays under the ignored benchmark-results/ directory or
controlled external storage; commit only compact reviewed summaries and
reproduction metadata. The models expose model_json_schema(), and a
breaking change bumps the integer version without migration support before
1.0 (ADR-006).
Reference baselines
config/baselines/ holds the reviewed compact and representative benchmark
documents for released PyBDSF and pinned master, the reference-product
manifest that binds the frozen PyBDSF products, the master-versus-release
scientific comparison, the one-tile overhead record (the strict model in
hebog.validation.overhead) and three inventories without a model:
phase-0-reference-environments.json (sanitized package inventories, runner
and compiler hashes, verified checkouts and the explicit 5.0/3.0 profile),
phase-0-representative-dataset.json and phase-0-starting-revisions.json.
A unit test loads every typed record through its model and requires the
directory to contain nothing else. The master-versus-release comparison is
written by scripts/validation/compare_reference_products.py, which the
equivalence lane reruns against the committed record, so a change to the
comparison oracle that moves it fails there.
hebog.validation.evidence
Versioned machine-readable scientific and performance evidence.
Evidence documents distinguish exploratory observations from reviewed release
evidence and distinguish unavailable instrumentation from measured zeroes.
External product readers and benchmark runners create these records; loading
this module never reads data or starts work.
TRACED_PEAK_TOLERANCE_BYTES = 2 ** 20 // 10
module-attribute
Largest spread of traced peaks that still counts as one peak.
A traced peak repeats to a few kilobytes rather than to the byte, because the
strings, paths and metadata of one run allocate slightly differently in the
next. A tenth of a mebibyte is the precision a peak is quoted at, about ten
times the spread measured across repetitions, and two orders of magnitude
below the image-sized arrays a scalability change moves.
BenchmarkEvidence
Bases: _EvidenceDocument
Versioned measurements for one exact implementation and environment.
Source code in src/hebog/validation/evidence.py
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393 | class BenchmarkEvidence(_EvidenceDocument):
"""Versioned measurements for one exact implementation and environment."""
evidence_type: Literal["benchmark"]
subject: SoftwareIdentity
related_software: tuple[SoftwareIdentity, ...] = ()
environment_sha256: str = Field(pattern=_SHA256_PATTERN)
resources: ResourceAllocation
measurements: tuple[Measurement, ...] = Field(min_length=1)
storage: StorageEvidence | None = None
scalability: ScalabilityMetrics | None = None
@model_validator(mode="after")
def validate_benchmark_protocol(self) -> Self:
"""Enforce identity, ordering, and reviewed repetition requirements."""
software_names = [
self.subject.name,
*(software.name for software in self.related_software),
]
if len(set(software_names)) != len(software_names):
raise ValueError("software identity names must be unique")
repetition_indices = [
measurement.repetition_index for measurement in self.measurements
]
if len(set(repetition_indices)) != len(repetition_indices):
raise ValueError("repetition indices must be unique")
if repetition_indices != sorted(repetition_indices):
raise ValueError(
"measurements must be ordered by repetition index"
)
measured_repetition_seen = False
for measurement in self.measurements:
if measurement.warmup and measured_repetition_seen:
raise ValueError(
"warm-up repetitions must precede measured repetitions"
)
measured_repetition_seen = (
measured_repetition_seen or not measurement.warmup
)
if self.status is EvidenceStatus.REVIEWED:
warmup_count = sum(
measurement.warmup for measurement in self.measurements
)
measured_count = len(self.measurements) - warmup_count
if warmup_count < 1:
raise ValueError("reviewed evidence requires a warm-up")
if measured_count < _MINIMUM_REVIEWED_REPETITIONS:
raise ValueError(
"reviewed evidence requires five measured repetitions"
)
if self.resources.worker_nodes > 1 and self.scalability is None:
raise ValueError(
"reviewed multi-node evidence requires scalability metrics"
)
return self
|
validate_benchmark_protocol()
Enforce identity, ordering, and reviewed repetition requirements.
Source code in src/hebog/validation/evidence.py
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393 | @model_validator(mode="after")
def validate_benchmark_protocol(self) -> Self:
"""Enforce identity, ordering, and reviewed repetition requirements."""
software_names = [
self.subject.name,
*(software.name for software in self.related_software),
]
if len(set(software_names)) != len(software_names):
raise ValueError("software identity names must be unique")
repetition_indices = [
measurement.repetition_index for measurement in self.measurements
]
if len(set(repetition_indices)) != len(repetition_indices):
raise ValueError("repetition indices must be unique")
if repetition_indices != sorted(repetition_indices):
raise ValueError(
"measurements must be ordered by repetition index"
)
measured_repetition_seen = False
for measurement in self.measurements:
if measurement.warmup and measured_repetition_seen:
raise ValueError(
"warm-up repetitions must precede measured repetitions"
)
measured_repetition_seen = (
measured_repetition_seen or not measurement.warmup
)
if self.status is EvidenceStatus.REVIEWED:
warmup_count = sum(
measurement.warmup for measurement in self.measurements
)
measured_count = len(self.measurements) - warmup_count
if warmup_count < 1:
raise ValueError("reviewed evidence requires a warm-up")
if measured_count < _MINIMUM_REVIEWED_REPETITIONS:
raise ValueError(
"reviewed evidence requires five measured repetitions"
)
if self.resources.worker_nodes > 1 and self.scalability is None:
raise ValueError(
"reviewed multi-node evidence requires scalability metrics"
)
return self
|
DatasetIdentity
Bases: _EvidenceModel
Governed dataset and workload identity for evidence.
Source code in src/hebog/validation/evidence.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 | class DatasetIdentity(_EvidenceModel):
"""Governed dataset and workload identity for evidence."""
identifier: str = Field(pattern=r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
role: DatasetRole
content_sha256: str = Field(pattern=_SHA256_PATTERN)
shape_yx: tuple[int, int]
workload_class: WorkloadClass
@model_validator(mode="after")
def validate_shape(self) -> Self:
"""Reject empty or negative logical image dimensions."""
if any(dimension <= 0 for dimension in self.shape_yx):
raise ValueError("shape_yx dimensions must be positive")
return self
|
validate_shape()
Reject empty or negative logical image dimensions.
Source code in src/hebog/validation/evidence.py
| @model_validator(mode="after")
def validate_shape(self) -> Self:
"""Reject empty or negative logical image dimensions."""
if any(dimension <= 0 for dimension in self.shape_yx):
raise ValueError("shape_yx dimensions must be positive")
return self
|
EvidenceStatus
Bases: str, Enum
Review status of an evidence document.
Source code in src/hebog/validation/evidence.py
| class EvidenceStatus(str, Enum):
"""Review status of an evidence document."""
EXPLORATORY = "exploratory"
REVIEWED = "reviewed"
|
ExecutorKind
Bases: str, Enum
Execution boundary used for a measured run.
Source code in src/hebog/validation/evidence.py
| class ExecutorKind(str, Enum):
"""Execution boundary used for a measured run."""
SERIAL = "serial"
LOCAL = "local"
DASK = "dask"
EXTERNAL = "external"
|
Measurement
Bases: _EvidenceModel
One warm-up or measured complete-run repetition.
Source code in src/hebog/validation/evidence.py
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280 | class Measurement(_EvidenceModel):
"""One warm-up or measured complete-run repetition."""
repetition_index: int = Field(ge=0)
warmup: bool
complete: RuntimeMetrics
stages: tuple[StageMetrics, ...] = Field(min_length=1)
@model_validator(mode="after")
def validate_unique_stages(self) -> Self:
"""Prevent ambiguous repeated stage metrics in one repetition."""
names = [stage.stage for stage in self.stages]
if len(set(names)) != len(names):
raise ValueError("stage names must be unique within a measurement")
return self
|
validate_unique_stages()
Prevent ambiguous repeated stage metrics in one repetition.
Source code in src/hebog/validation/evidence.py
274
275
276
277
278
279
280 | @model_validator(mode="after")
def validate_unique_stages(self) -> Self:
"""Prevent ambiguous repeated stage metrics in one repetition."""
names = [stage.stage for stage in self.stages]
if len(set(names)) != len(names):
raise ValueError("stage names must be unique within a measurement")
return self
|
ResourceAllocation
Bases: _EvidenceModel
Admitted compute and storage topology for one measured run.
Source code in src/hebog/validation/evidence.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 | class ResourceAllocation(_EvidenceModel):
"""Admitted compute and storage topology for one measured run."""
executor: ExecutorKind
worker_nodes: int = Field(ge=1)
workers_per_node: int = Field(ge=1)
threads_per_worker: int = Field(ge=1)
allocated_cpu_cores: int = Field(ge=1)
node_memory_bytes: int = Field(ge=1)
worker_memory_limit_bytes: int = Field(ge=1)
reserved_headroom_per_node_bytes: int = Field(ge=0)
storage_identifier: str = Field(min_length=1)
@model_validator(mode="after")
def validate_memory_admission(self) -> Self:
"""Keep aggregate worker limits within admitted node memory."""
available_memory = (
self.node_memory_bytes - self.reserved_headroom_per_node_bytes
)
admitted_worker_memory = (
self.workers_per_node * self.worker_memory_limit_bytes
)
if available_memory <= 0:
raise ValueError("reserved headroom must leave usable node memory")
if admitted_worker_memory > available_memory:
raise ValueError(
"aggregate worker memory exceeds node memory after headroom"
)
return self
|
validate_memory_admission()
Keep aggregate worker limits within admitted node memory.
Source code in src/hebog/validation/evidence.py
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 | @model_validator(mode="after")
def validate_memory_admission(self) -> Self:
"""Keep aggregate worker limits within admitted node memory."""
available_memory = (
self.node_memory_bytes - self.reserved_headroom_per_node_bytes
)
admitted_worker_memory = (
self.workers_per_node * self.worker_memory_limit_bytes
)
if available_memory <= 0:
raise ValueError("reserved headroom must leave usable node memory")
if admitted_worker_memory > available_memory:
raise ValueError(
"aggregate worker memory exceeds node memory after headroom"
)
return self
|
RuntimeMetrics
Bases: _EvidenceModel
Required timing/resource metrics with explicit unavailable values.
Source code in src/hebog/validation/evidence.py
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 | class RuntimeMetrics(_EvidenceModel):
"""Required timing/resource metrics with explicit unavailable values."""
wall_seconds: float = Field(ge=0, allow_inf_nan=False)
cpu_seconds: float = Field(ge=0, allow_inf_nan=False)
peak_rss_bytes: int = Field(ge=0)
array_copy_count: int | None = Field(ge=0)
array_copy_bytes: int | None = Field(ge=0)
dask_task_count: int | None = Field(ge=0)
transfer_bytes: int | None = Field(ge=0)
spill_bytes: int | None = Field(ge=0)
unavailable_metrics: tuple[UnavailableMetric, ...] = ()
@model_validator(mode="after")
def validate_unavailable_metrics(self) -> Self:
"""Require one reason for every unavailable optional instrument."""
metric_values: dict[OptionalMetricName, int | None] = {
"array_copy_count": self.array_copy_count,
"array_copy_bytes": self.array_copy_bytes,
"dask_task_count": self.dask_task_count,
"transfer_bytes": self.transfer_bytes,
"spill_bytes": self.spill_bytes,
}
reason_names = [item.metric for item in self.unavailable_metrics]
if len(set(reason_names)) != len(reason_names):
raise ValueError("unavailable metric names must be unique")
unavailable_reasons = {
item.metric: item.reason for item in self.unavailable_metrics
}
for metric_name, value in metric_values.items():
reason = unavailable_reasons.get(metric_name)
if value is None and reason is None:
raise ValueError(
f"{metric_name} is unavailable without a reason"
)
if value is not None and reason is not None:
raise ValueError(
f"{metric_name} has both a value and unavailable reason"
)
return self
|
validate_unavailable_metrics()
Require one reason for every unavailable optional instrument.
Source code in src/hebog/validation/evidence.py
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 | @model_validator(mode="after")
def validate_unavailable_metrics(self) -> Self:
"""Require one reason for every unavailable optional instrument."""
metric_values: dict[OptionalMetricName, int | None] = {
"array_copy_count": self.array_copy_count,
"array_copy_bytes": self.array_copy_bytes,
"dask_task_count": self.dask_task_count,
"transfer_bytes": self.transfer_bytes,
"spill_bytes": self.spill_bytes,
}
reason_names = [item.metric for item in self.unavailable_metrics]
if len(set(reason_names)) != len(reason_names):
raise ValueError("unavailable metric names must be unique")
unavailable_reasons = {
item.metric: item.reason for item in self.unavailable_metrics
}
for metric_name, value in metric_values.items():
reason = unavailable_reasons.get(metric_name)
if value is None and reason is None:
raise ValueError(
f"{metric_name} is unavailable without a reason"
)
if value is not None and reason is not None:
raise ValueError(
f"{metric_name} has both a value and unavailable reason"
)
return self
|
ScalabilityMetrics
Bases: _EvidenceModel
Topology and efficiency evidence required for multi-node runs.
Source code in src/hebog/validation/evidence.py
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 | class ScalabilityMetrics(_EvidenceModel):
"""Topology and efficiency evidence required for multi-node runs."""
logical_plane_count: int = Field(ge=1)
tile_core_shape_yx: tuple[int, int]
maximum_halo_yx: tuple[int, int]
partition_count: int = Field(ge=1)
graph_task_count: int = Field(ge=0)
scheduler_overhead_seconds: float = Field(ge=0, allow_inf_nan=False)
worker_occupancy_fraction: float = Field(
ge=0,
le=1,
allow_inf_nan=False,
)
storage_throughput_bytes_per_second: float = Field(
ge=0,
allow_inf_nan=False,
)
retry_count: int = Field(ge=0)
straggler_count: int = Field(ge=0)
strong_scaling_efficiency: float = Field(ge=0, allow_inf_nan=False)
weak_scaling_efficiency: float = Field(ge=0, allow_inf_nan=False)
@model_validator(mode="after")
def validate_geometry(self) -> Self:
"""Require positive tile cores and non-negative halos."""
if any(dimension <= 0 for dimension in self.tile_core_shape_yx):
raise ValueError("tile core dimensions must be positive")
if any(dimension < 0 for dimension in self.maximum_halo_yx):
raise ValueError("halo dimensions cannot be negative")
return self
|
validate_geometry()
Require positive tile cores and non-negative halos.
Source code in src/hebog/validation/evidence.py
306
307
308
309
310
311
312
313 | @model_validator(mode="after")
def validate_geometry(self) -> Self:
"""Require positive tile cores and non-negative halos."""
if any(dimension <= 0 for dimension in self.tile_core_shape_yx):
raise ValueError("tile core dimensions must be positive")
if any(dimension < 0 for dimension in self.maximum_halo_yx):
raise ValueError("halo dimensions cannot be negative")
return self
|
ScientificComparisonEvidence
Bases: _EvidenceDocument
Provenance and reports for one candidate/reference comparison.
Source code in src/hebog/validation/evidence.py
474
475
476
477
478
479
480
481
482
483
484
485
486
487 | class ScientificComparisonEvidence(_EvidenceDocument):
"""Provenance and reports for one candidate/reference comparison."""
evidence_type: Literal["scientific-comparison"]
candidate: SoftwareIdentity
reference: SoftwareIdentity
candidate_product_manifest_sha256: str = Field(pattern=_SHA256_PATTERN)
reference_product_manifest_sha256: str = Field(pattern=_SHA256_PATTERN)
beam_fwhm_degrees: float = Field(gt=0, allow_inf_nan=False)
maximum_separation_beams: float = Field(gt=0, allow_inf_nan=False)
catalogue: CatalogueComparisonReport
true_sky_rms: RmsComparisonReport
flat_noise_rms: RmsComparisonReport
mask: MaskComparisonReport
|
SoftwareIdentity
Bases: _EvidenceModel
Exact software and dependency identity used by one run.
Source code in src/hebog/validation/evidence.py
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 | class SoftwareIdentity(_EvidenceModel):
"""Exact software and dependency identity used by one run."""
name: str = Field(pattern=r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
version: str | None = Field(default=None, min_length=1)
commit_sha: str | None = Field(default=None, pattern=_COMMIT_PATTERN)
source_tree_sha256: str | None = Field(
default=None,
pattern=_SHA256_PATTERN,
)
container_image_digest: str | None = Field(
default=None,
pattern=_CONTAINER_DIGEST_PATTERN,
)
dependency_inventory_sha256: str = Field(pattern=_SHA256_PATTERN)
@model_validator(mode="after")
def validate_revision(self) -> Self:
"""Require at least one independently useful revision identifier."""
if (
self.version is None
and self.commit_sha is None
and self.source_tree_sha256 is None
and self.container_image_digest is None
):
raise ValueError(
"software identity requires version, commit_sha, "
"source_tree_sha256, or container_image_digest"
)
return self
|
validate_revision()
Require at least one independently useful revision identifier.
Source code in src/hebog/validation/evidence.py
97
98
99
100
101
102
103
104
105
106
107
108
109
110 | @model_validator(mode="after")
def validate_revision(self) -> Self:
"""Require at least one independently useful revision identifier."""
if (
self.version is None
and self.commit_sha is None
and self.source_tree_sha256 is None
and self.container_image_digest is None
):
raise ValueError(
"software identity requires version, commit_sha, "
"source_tree_sha256, or container_image_digest"
)
return self
|
StageMetrics
Bases: _EvidenceModel
Metrics attributed to one named scientific or integration stage.
Source code in src/hebog/validation/evidence.py
| class StageMetrics(_EvidenceModel):
"""Metrics attributed to one named scientific or integration stage."""
stage: str = Field(pattern=r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
metrics: RuntimeMetrics
|
StorageEvidence
Bases: _EvidenceModel
Intermediate-store layout, policy, and observed footprint.
Source code in src/hebog/validation/evidence.py
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200 | class StorageEvidence(_EvidenceModel):
"""Intermediate-store layout, policy, and observed footprint."""
format_name: str = Field(min_length=1)
library_name: str = Field(min_length=1)
library_version: str = Field(min_length=1)
backend_name: str = Field(min_length=1)
chunk_shape_yx: tuple[int, int]
shard_shape_yx: tuple[int, int] | None
codec_pipeline: tuple[str, ...] = Field(min_length=1)
fill_value: str = Field(min_length=1)
missing_chunk_policy: Literal["error", "fill"]
write_empty_chunks: bool
object_count: int = Field(ge=1)
stored_bytes: int = Field(ge=1)
internal_concurrency: int = Field(ge=1)
atomic_write_guarantee: str = Field(min_length=1)
conditional_create: bool
@model_validator(mode="after")
def validate_storage_configuration(self) -> Self:
"""Require usable geometry and non-blank policy descriptions."""
if any(dimension <= 0 for dimension in self.chunk_shape_yx):
raise ValueError("storage chunk dimensions must be positive")
if self.shard_shape_yx is not None and any(
dimension <= 0 for dimension in self.shard_shape_yx
):
raise ValueError("storage shard dimensions must be positive")
descriptions = (
self.format_name,
self.library_name,
self.library_version,
self.backend_name,
self.fill_value,
self.atomic_write_guarantee,
*self.codec_pipeline,
)
if any(not description.strip() for description in descriptions):
raise ValueError("storage descriptions must not be blank")
return self
|
validate_storage_configuration()
Require usable geometry and non-blank policy descriptions.
Source code in src/hebog/validation/evidence.py
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200 | @model_validator(mode="after")
def validate_storage_configuration(self) -> Self:
"""Require usable geometry and non-blank policy descriptions."""
if any(dimension <= 0 for dimension in self.chunk_shape_yx):
raise ValueError("storage chunk dimensions must be positive")
if self.shard_shape_yx is not None and any(
dimension <= 0 for dimension in self.shard_shape_yx
):
raise ValueError("storage shard dimensions must be positive")
descriptions = (
self.format_name,
self.library_name,
self.library_version,
self.backend_name,
self.fill_value,
self.atomic_write_guarantee,
*self.codec_pipeline,
)
if any(not description.strip() for description in descriptions):
raise ValueError("storage descriptions must not be blank")
return self
|
TracedAllocationEvidence
Bases: _EvidenceDocument
Deterministic traced-allocation peaks for one input and configuration.
tracemalloc counts the allocations the process itself makes, so its
peak is reproducible for one input, one configuration and one
implementation, which is why it, and not peak resident memory, gates a
public envelope raise. Tracing roughly doubles wall time, so these
documents record no timing that may be compared with benchmark evidence.
Source code in src/hebog/validation/evidence.py
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471 | class TracedAllocationEvidence(_EvidenceDocument):
"""Deterministic traced-allocation peaks for one input and configuration.
``tracemalloc`` counts the allocations the process itself makes, so its
peak is reproducible for one input, one configuration and one
implementation, which is why it, and not peak resident memory, gates a
public envelope raise. Tracing roughly doubles wall time, so these
documents record no timing that may be compared with benchmark evidence.
"""
evidence_type: Literal["traced-allocation"]
subject: SoftwareIdentity
environment_sha256: str = Field(pattern=_SHA256_PATTERN)
resources: ResourceAllocation
measurements: tuple[TracedAllocationMeasurement, ...] = Field(min_length=1)
@model_validator(mode="after")
def validate_traced_protocol(self) -> Self:
"""Order repetitions, and require a reproduced reviewed peak."""
indices = [
measurement.repetition_index for measurement in self.measurements
]
if len(set(indices)) != len(indices):
raise ValueError("repetition indices must be unique")
if indices != sorted(indices):
raise ValueError(
"measurements must be ordered by repetition index"
)
if self.status is EvidenceStatus.REVIEWED:
peaks = [
measurement.peak_traced_bytes
for measurement in self.measurements
]
if len(self.measurements) < _MINIMUM_REVIEWED_TRACED_REPETITIONS:
raise ValueError(
"reviewed traced evidence requires two repetitions"
)
if max(peaks) - min(peaks) > TRACED_PEAK_TOLERANCE_BYTES:
raise ValueError(
"reviewed traced evidence requires one reproduced peak, "
"within a tenth of a mebibyte"
)
return self
|
validate_traced_protocol()
Order repetitions, and require a reproduced reviewed peak.
Source code in src/hebog/validation/evidence.py
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471 | @model_validator(mode="after")
def validate_traced_protocol(self) -> Self:
"""Order repetitions, and require a reproduced reviewed peak."""
indices = [
measurement.repetition_index for measurement in self.measurements
]
if len(set(indices)) != len(indices):
raise ValueError("repetition indices must be unique")
if indices != sorted(indices):
raise ValueError(
"measurements must be ordered by repetition index"
)
if self.status is EvidenceStatus.REVIEWED:
peaks = [
measurement.peak_traced_bytes
for measurement in self.measurements
]
if len(self.measurements) < _MINIMUM_REVIEWED_TRACED_REPETITIONS:
raise ValueError(
"reviewed traced evidence requires two repetitions"
)
if max(peaks) - min(peaks) > TRACED_PEAK_TOLERANCE_BYTES:
raise ValueError(
"reviewed traced evidence requires one reproduced peak, "
"within a tenth of a mebibyte"
)
return self
|
TracedAllocationMeasurement
Bases: _EvidenceModel
One traced repetition of one input through the public finder.
peak_traced_bytes is the gate figure: the highest total of
interpreter and NumPy allocations traced in the worker process, from
before Hebog is imported until the products are written.
finder_peak_traced_bytes is the peak over the find_sources call
alone, measured from the same tracing session after its peak was reset,
and import_traced_bytes is what the imports still hold when that call
begins. Both make a peak comparable with one measured over a different
span. peak_rss_bytes is an envelope, not a threshold: it varies with
machine load, and tracing inflates it further.
Source code in src/hebog/validation/evidence.py
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426 | class TracedAllocationMeasurement(_EvidenceModel):
"""One traced repetition of one input through the public finder.
``peak_traced_bytes`` is the gate figure: the highest total of
interpreter and NumPy allocations traced in the worker process, from
before Hebog is imported until the products are written.
``finder_peak_traced_bytes`` is the peak over the ``find_sources`` call
alone, measured from the same tracing session after its peak was reset,
and ``import_traced_bytes`` is what the imports still hold when that call
begins. Both make a peak comparable with one measured over a different
span. ``peak_rss_bytes`` is an envelope, not a threshold: it varies with
machine load, and tracing inflates it further.
"""
repetition_index: int = Field(ge=0)
peak_traced_bytes: int = Field(gt=0)
finder_peak_traced_bytes: int = Field(gt=0)
import_traced_bytes: int = Field(gt=0)
peak_rss_bytes: int = Field(ge=0)
traced_wall_seconds: float = Field(ge=0, allow_inf_nan=False)
source_count: int = Field(ge=0)
gaussian_component_count: int = Field(ge=0)
@model_validator(mode="after")
def validate_peaks(self) -> Self:
"""Require spans that one tracing session can have produced."""
if self.finder_peak_traced_bytes > self.peak_traced_bytes:
raise ValueError("the finder peak cannot exceed the process peak")
if self.import_traced_bytes > self.finder_peak_traced_bytes:
raise ValueError("the import floor cannot exceed the finder peak")
return self
|
validate_peaks()
Require spans that one tracing session can have produced.
Source code in src/hebog/validation/evidence.py
419
420
421
422
423
424
425
426 | @model_validator(mode="after")
def validate_peaks(self) -> Self:
"""Require spans that one tracing session can have produced."""
if self.finder_peak_traced_bytes > self.peak_traced_bytes:
raise ValueError("the finder peak cannot exceed the process peak")
if self.import_traced_bytes > self.finder_peak_traced_bytes:
raise ValueError("the import floor cannot exceed the finder peak")
return self
|
UnavailableMetric
Bases: _EvidenceModel
One unavailable optional instrument and its explicit reason.
Source code in src/hebog/validation/evidence.py
203
204
205
206
207
208
209
210
211
212
213
214 | class UnavailableMetric(_EvidenceModel):
"""One unavailable optional instrument and its explicit reason."""
metric: OptionalMetricName
reason: str = Field(min_length=1)
@model_validator(mode="after")
def validate_reason(self) -> Self:
"""Reject whitespace-only explanations."""
if not self.reason.strip():
raise ValueError("unavailable metric reason must not be blank")
return self
|
validate_reason()
Reject whitespace-only explanations.
Source code in src/hebog/validation/evidence.py
| @model_validator(mode="after")
def validate_reason(self) -> Self:
"""Reject whitespace-only explanations."""
if not self.reason.strip():
raise ValueError("unavailable metric reason must not be blank")
return self
|
WorkloadClass
Bases: str, Enum
Scientific work represented by a benchmark dataset.
Source code in src/hebog/validation/evidence.py
| class WorkloadClass(str, Enum):
"""Scientific work represented by a benchmark dataset."""
EMPTY_SPARSE = "empty-or-sparse"
NORMAL = "normal"
DENSE_EXTENDED = "dense-or-extended"
|
canonical_evidence_json(document)
Serialize evidence deterministically with a final newline.
Source code in src/hebog/validation/evidence.py
499
500
501
502
503
504
505
506
507
508
509
510 | def canonical_evidence_json(document: EvidenceDocument) -> str:
"""Serialize evidence deterministically with a final newline."""
payload = document.model_dump(mode="json")
return (
json.dumps(
payload,
allow_nan=False,
indent=2,
sort_keys=True,
)
+ "\n"
)
|
load_evidence(path)
Load and validate one benchmark or scientific evidence document.
Source code in src/hebog/validation/evidence.py
| def load_evidence(path: Path) -> EvidenceDocument:
"""Load and validate one benchmark or scientific evidence document."""
payload = path.read_text(encoding="utf-8")
return _EVIDENCE_ADAPTER.validate_json(payload)
|
write_evidence(path, document)
Atomically write one validated evidence document.
Source code in src/hebog/validation/evidence.py
513
514
515
516
517
518
519
520 | def write_evidence(path: Path, document: EvidenceDocument) -> None:
"""Atomically write one validated evidence document."""
temporary_path = path.with_suffix(f"{path.suffix}.tmp")
temporary_path.write_text(
canonical_evidence_json(document),
encoding="utf-8",
)
temporary_path.replace(path)
|
hebog.validation.overhead
Versioned evidence for warm one-tile framework overhead measurements.
OverheadEnvironment
Bases: _OverheadModel
Exact local environment used for an exploratory overhead probe.
Source code in src/hebog/validation/overhead.py
64
65
66
67
68
69
70
71
72 | class OverheadEnvironment(_OverheadModel):
"""Exact local environment used for an exploratory overhead probe."""
python: str = Field(min_length=1)
platform: str = Field(min_length=1)
machine: str = Field(min_length=1)
cpu_count: int | None = Field(ge=1)
node_memory_bytes: int = Field(ge=1)
dependency_versions: dict[str, str]
|
OverheadEvidence
Bases: _OverheadModel
Complete warm one-tile overhead observation.
Source code in src/hebog/validation/overhead.py
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 | class OverheadEvidence(_OverheadModel):
"""Complete warm one-tile overhead observation."""
schema_version: Literal[1]
status: Literal["exploratory"]
captured_at: datetime
source_commit: str = Field(pattern=_COMMIT_PATTERN)
dataset_identifier: str = Field(pattern=r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
dataset_content_sha256: str = Field(pattern=_SHA256_PATTERN)
shape_yx: tuple[int, int]
performance_contract_sha256: str = Field(pattern=_SHA256_PATTERN)
environment_sha256: str = Field(pattern=_SHA256_PATTERN)
environment: OverheadEnvironment
measurements: tuple[OverheadStatistics, ...]
@model_validator(mode="after")
def validate_document(self) -> Self:
"""Require timezone, geometry, and all six unique operations."""
if (
self.captured_at.tzinfo is None
or self.captured_at.utcoffset() is None
):
raise ValueError("captured_at must include a timezone")
if any(dimension <= 0 for dimension in self.shape_yx):
raise ValueError("shape_yx dimensions must be positive")
operations = [item.operation for item in self.measurements]
if len(set(operations)) != len(operations):
raise ValueError("overhead operations must be unique")
if set(operations) != {
"configuration",
"fits-io",
"partition-planning",
"serial-dispatch",
"local-dispatch",
"dask-dispatch",
}:
raise ValueError("overhead evidence requires all six operations")
return self
|
validate_document()
Require timezone, geometry, and all six unique operations.
Source code in src/hebog/validation/overhead.py
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 | @model_validator(mode="after")
def validate_document(self) -> Self:
"""Require timezone, geometry, and all six unique operations."""
if (
self.captured_at.tzinfo is None
or self.captured_at.utcoffset() is None
):
raise ValueError("captured_at must include a timezone")
if any(dimension <= 0 for dimension in self.shape_yx):
raise ValueError("shape_yx dimensions must be positive")
operations = [item.operation for item in self.measurements]
if len(set(operations)) != len(operations):
raise ValueError("overhead operations must be unique")
if set(operations) != {
"configuration",
"fits-io",
"partition-planning",
"serial-dispatch",
"local-dispatch",
"dask-dispatch",
}:
raise ValueError("overhead evidence requires all six operations")
return self
|
OverheadStatistics
Bases: _OverheadModel
Repeated warm timings for one isolated framework operation.
Source code in src/hebog/validation/overhead.py
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 | class OverheadStatistics(_OverheadModel):
"""Repeated warm timings for one isolated framework operation."""
operation: OverheadOperation
method: str = Field(min_length=1)
warmup_repetitions: int = Field(ge=1)
measured_repetitions: int = Field(ge=5)
minimum_seconds: float = Field(ge=0, allow_inf_nan=False)
median_seconds: float = Field(ge=0, allow_inf_nan=False)
percentile_95_seconds: float = Field(ge=0, allow_inf_nan=False)
maximum_seconds: float = Field(ge=0, allow_inf_nan=False)
budget_seconds: float = Field(gt=0, allow_inf_nan=False)
within_budget: bool
@model_validator(mode="after")
def validate_summary(self) -> Self:
"""Require ordered statistics and a truthful budget result."""
if not (
self.minimum_seconds
<= self.median_seconds
<= self.percentile_95_seconds
<= self.maximum_seconds
):
raise ValueError("overhead statistics are not ordered")
if self.within_budget != (
self.percentile_95_seconds <= self.budget_seconds
):
raise ValueError(
"within_budget does not match the 95th percentile"
)
return self
|
validate_summary()
Require ordered statistics and a truthful budget result.
Source code in src/hebog/validation/overhead.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 | @model_validator(mode="after")
def validate_summary(self) -> Self:
"""Require ordered statistics and a truthful budget result."""
if not (
self.minimum_seconds
<= self.median_seconds
<= self.percentile_95_seconds
<= self.maximum_seconds
):
raise ValueError("overhead statistics are not ordered")
if self.within_budget != (
self.percentile_95_seconds <= self.budget_seconds
):
raise ValueError(
"within_budget does not match the 95th percentile"
)
return self
|
load_overhead_evidence(path)
Load and validate one overhead-evidence document.
Source code in src/hebog/validation/overhead.py
| def load_overhead_evidence(path: Path) -> OverheadEvidence:
"""Load and validate one overhead-evidence document."""
return OverheadEvidence.model_validate_json(
path.read_text(encoding="utf-8")
)
|
write_overhead_evidence(path, evidence)
Atomically write deterministic overhead evidence.
Source code in src/hebog/validation/overhead.py
115
116
117
118
119
120
121
122
123
124
125
126
127
128 | def write_overhead_evidence(path: Path, evidence: OverheadEvidence) -> None:
"""Atomically write deterministic overhead evidence."""
payload = (
json.dumps(
evidence.model_dump(mode="json"),
allow_nan=False,
indent=2,
sort_keys=True,
)
+ "\n"
)
temporary_path = path.with_suffix(f"{path.suffix}.tmp")
temporary_path.write_text(payload, encoding="utf-8")
temporary_path.replace(path)
|