Buckets:
| #!/usr/bin/env python3 | |
| """Build deterministic canonical tables from append-only evidence batches. | |
| This transformation is intentionally strict. It accepts only completed raw | |
| batches, verifies every hash and declared record count, validates each record | |
| according to its type, and refuses unknown record types. Error and exclusion | |
| records remain visible in dedicated canonical tables; they are never filtered | |
| away while constructing summaries. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import csv | |
| import hashlib | |
| import json | |
| import math | |
| import os | |
| import shutil | |
| import statistics | |
| import sys | |
| import tempfile | |
| from collections import Counter, defaultdict | |
| from dataclasses import dataclass | |
| from datetime import datetime | |
| from pathlib import Path | |
| from typing import Any, Iterable, Mapping, Sequence | |
| BUILDER_VERSION = "1.1.0" | |
| SUPPORTED_SCHEMA_VERSION = "1.0.0" | |
| ALLOWED_RECORD_TYPES = { | |
| "episode", | |
| "training_run", | |
| "training_metric", | |
| "proof_certificate", | |
| "parameter_audit", | |
| "artifact", | |
| "selection", | |
| "environment", | |
| "claim_summary", | |
| "scope_limitation", | |
| "failure", | |
| "error", | |
| "exclusion", | |
| } | |
| FAILURE_STATUSES = {"error", "failed", "failure"} | |
| EXCLUSION_STATUSES = {"excluded", "not_executed"} | |
| ALLOWED_STATUSES = {"success", *EXCLUSION_STATUSES, *FAILURE_STATUSES} | |
| PROVENANCE_COLUMNS = ( | |
| "source_batch", | |
| "source_line_number", | |
| "record_sha256", | |
| ) | |
| COMMON_COLUMNS = ( | |
| "schema_version", | |
| "experiment_id", | |
| "spec_version", | |
| "paper_version", | |
| "openreview_id", | |
| "batch_id", | |
| "record_type", | |
| "recorded_at", | |
| "status", | |
| "claim_id", | |
| "panel_id", | |
| "task_id", | |
| "attempt_id", | |
| "method", | |
| "environment", | |
| "seed", | |
| ) | |
| TABLE_CORE_COLUMNS: dict[str, tuple[str, ...]] = { | |
| "episodes.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "start_position", | |
| "initial_angle", | |
| "initial_angular_velocity", | |
| "return", | |
| "episode_length", | |
| "terminal_velocity", | |
| ), | |
| "training_runs.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "timesteps", | |
| "episodes", | |
| "evaluation_mean_return", | |
| "selection_mean_return", | |
| "mean_return", | |
| "wall_time_seconds", | |
| "peak_rss_mb", | |
| "selected", | |
| ), | |
| "training_metrics.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "timesteps", | |
| "mean_return", | |
| "training_episode", | |
| "return", | |
| "episode_length", | |
| ), | |
| "proof_certificates.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "claim_scope", | |
| "historical_priority_tested", | |
| "discrete_global_optimality_tested", | |
| ), | |
| "parameter_audit.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "count_source", | |
| "parameter_count", | |
| "performance_method", | |
| "reduction_factor", | |
| ), | |
| "artifacts.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "artifact_path", | |
| "artifact_sha256", | |
| "artifact_bytes", | |
| ), | |
| "selections.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "selection_rule", | |
| "candidate_count", | |
| "selected_seed", | |
| "selected_summary", | |
| ), | |
| "environments.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "packages", | |
| "hardware", | |
| "upstream_commits", | |
| ), | |
| "claim_summaries.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "summary", | |
| ), | |
| "errors.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "error", | |
| "message", | |
| "traceback", | |
| ), | |
| "exclusions.csv": ( | |
| *PROVENANCE_COLUMNS, | |
| *COMMON_COLUMNS, | |
| "exclusion_reason", | |
| "reason", | |
| ), | |
| "summaries.csv": ( | |
| "summary_type", | |
| "experiment_id", | |
| "spec_version", | |
| "paper_version", | |
| "openreview_id", | |
| "batch_id", | |
| "claim_id", | |
| "panel_id", | |
| "environment", | |
| "method", | |
| "metric_name", | |
| "record_count", | |
| "success_count", | |
| "error_count", | |
| "exclusion_count", | |
| "value_count", | |
| "mean", | |
| "std_population", | |
| "min", | |
| "max", | |
| ), | |
| } | |
| class ValidationError(RuntimeError): | |
| """Raised when raw evidence does not satisfy the canonical contract.""" | |
| class BatchData: | |
| directory: Path | |
| manifest: dict[str, Any] | |
| records: tuple[dict[str, Any], ...] | |
| records_sha256: str | |
| manifest_sha256: str | |
| coverage_checks: tuple[dict[str, Any], ...] | |
| def sha256_file(path: Path) -> str: | |
| digest = hashlib.sha256() | |
| with path.open("rb") as handle: | |
| for chunk in iter(lambda: handle.read(1024 * 1024), b""): | |
| digest.update(chunk) | |
| return digest.hexdigest() | |
| def canonical_json(value: Any) -> str: | |
| return json.dumps( | |
| value, | |
| ensure_ascii=False, | |
| allow_nan=False, | |
| separators=(",", ":"), | |
| sort_keys=True, | |
| ) | |
| def _reject_json_constant(value: str) -> None: | |
| raise ValidationError(f"Non-standard JSON constant is forbidden: {value}") | |
| def _unique_object(pairs: Sequence[tuple[str, Any]]) -> dict[str, Any]: | |
| result: dict[str, Any] = {} | |
| for key, value in pairs: | |
| if key in result: | |
| raise ValidationError(f"Duplicate JSON object key: {key!r}") | |
| result[key] = value | |
| return result | |
| def parse_json(text: str, source: str) -> Any: | |
| try: | |
| return json.loads( | |
| text, | |
| object_pairs_hook=_unique_object, | |
| parse_constant=_reject_json_constant, | |
| ) | |
| except (json.JSONDecodeError, ValidationError) as exc: | |
| raise ValidationError(f"Invalid JSON in {source}: {exc}") from exc | |
| def require_object(value: Any, source: str) -> dict[str, Any]: | |
| if not isinstance(value, dict): | |
| raise ValidationError(f"Expected a JSON object in {source}") | |
| return value | |
| def require_string(record: Mapping[str, Any], key: str, source: str) -> str: | |
| value = record.get(key) | |
| if not isinstance(value, str) or not value.strip(): | |
| raise ValidationError(f"{source}: {key!r} must be a non-empty string") | |
| return value | |
| def require_integer( | |
| record: Mapping[str, Any], key: str, source: str, minimum: int | None = None | |
| ) -> int: | |
| value = record.get(key) | |
| if isinstance(value, bool) or not isinstance(value, int): | |
| raise ValidationError(f"{source}: {key!r} must be an integer") | |
| if minimum is not None and value < minimum: | |
| raise ValidationError(f"{source}: {key!r} must be >= {minimum}") | |
| return value | |
| def require_number(record: Mapping[str, Any], key: str, source: str) -> float: | |
| value = record.get(key) | |
| if isinstance(value, bool) or not isinstance(value, (int, float)): | |
| raise ValidationError(f"{source}: {key!r} must be numeric") | |
| number = float(value) | |
| if not math.isfinite(number): | |
| raise ValidationError(f"{source}: {key!r} must be finite") | |
| return number | |
| def validate_optional_number(record: Mapping[str, Any], key: str, source: str) -> None: | |
| if key in record and record[key] is not None: | |
| require_number(record, key, source) | |
| def validate_optional_integer(record: Mapping[str, Any], key: str, source: str) -> None: | |
| if key in record and record[key] is not None: | |
| require_integer(record, key, source) | |
| def validate_timestamp(value: Any, source: str) -> None: | |
| if not isinstance(value, str) or not value: | |
| raise ValidationError(f"{source}: recorded_at must be a non-empty ISO timestamp") | |
| normalized = value[:-1] + "+00:00" if value.endswith("Z") else value | |
| try: | |
| parsed = datetime.fromisoformat(normalized) | |
| except ValueError as exc: | |
| raise ValidationError(f"{source}: invalid recorded_at timestamp {value!r}") from exc | |
| if parsed.tzinfo is None or parsed.utcoffset() is None: | |
| raise ValidationError(f"{source}: recorded_at must include a UTC offset") | |
| def validate_json_tree(value: Any, source: str) -> None: | |
| if value is None or isinstance(value, (str, bool, int)): | |
| return | |
| if isinstance(value, float): | |
| if not math.isfinite(value): | |
| raise ValidationError(f"{source}: non-finite numeric value") | |
| return | |
| if isinstance(value, list): | |
| for index, item in enumerate(value): | |
| validate_json_tree(item, f"{source}[{index}]") | |
| return | |
| if isinstance(value, dict): | |
| for key, item in value.items(): | |
| if not isinstance(key, str): | |
| raise ValidationError(f"{source}: JSON object key is not a string") | |
| validate_json_tree(item, f"{source}.{key}") | |
| return | |
| raise ValidationError(f"{source}: unsupported JSON value type {type(value).__name__}") | |
| def validate_failure_reason(record: Mapping[str, Any], source: str) -> None: | |
| if not any( | |
| isinstance(record.get(key), str) and bool(record[key].strip()) | |
| for key in ("error", "message", "reason", "exclusion_reason") | |
| ): | |
| raise ValidationError(f"{source}: failed/excluded record has no reason") | |
| def validate_return_summary(value: Any, label: str) -> None: | |
| if not isinstance(value, dict): | |
| raise ValidationError(f"{label} must be an object") | |
| for key in ("count", "mean", "std", "min", "max"): | |
| if key not in value: | |
| raise ValidationError(f"{label} is missing {key!r}") | |
| require_integer(value, "count", label, minimum=1) | |
| for key in ("mean", "std", "min", "max"): | |
| require_number(value, key, label) | |
| if float(value["std"]) < 0: | |
| raise ValidationError(f"{label}.std must be non-negative") | |
| if float(value["min"]) > float(value["mean"]) or float(value["mean"]) > float(value["max"]): | |
| raise ValidationError(f"{label} must satisfy min <= mean <= max") | |
| def validate_record(record: dict[str, Any], source: str) -> None: | |
| validate_json_tree(record, source) | |
| for key in ( | |
| "schema_version", | |
| "experiment_id", | |
| "spec_version", | |
| "paper_version", | |
| "openreview_id", | |
| "batch_id", | |
| "record_type", | |
| ): | |
| require_string(record, key, source) | |
| validate_timestamp(record.get("recorded_at"), source) | |
| record_type = record["record_type"] | |
| if record_type not in ALLOWED_RECORD_TYPES: | |
| raise ValidationError( | |
| f"{source}: unknown record_type {record_type!r}; refusing to drop it" | |
| ) | |
| status = require_string(record, "status", source) | |
| if status not in ALLOWED_STATUSES: | |
| raise ValidationError(f"{source}: unsupported status {status!r}") | |
| if status != "success": | |
| validate_failure_reason(record, source) | |
| if record_type == "episode": | |
| for key in ("claim_id", "task_id", "method", "environment", "panel_id"): | |
| require_string(record, key, source) | |
| require_integer(record, "attempt_id", source, minimum=1) | |
| validate_optional_integer(record, "seed", source) | |
| for key in ( | |
| "start_position", | |
| "initial_angle", | |
| "initial_angular_velocity", | |
| "terminal_velocity", | |
| ): | |
| validate_optional_number(record, key, source) | |
| if status == "success": | |
| require_number(record, "return", source) | |
| if "episode_length" in record and record["episode_length"] is not None: | |
| require_integer(record, "episode_length", source, minimum=1) | |
| elif record_type == "training_run": | |
| for key in ("claim_id", "method", "panel_id"): | |
| require_string(record, key, source) | |
| require_integer(record, "seed", source) | |
| for key in ( | |
| "configured_timesteps", | |
| "actual_timesteps", | |
| "configured_episodes", | |
| "actual_training_episodes", | |
| ): | |
| if key in record and record[key] is not None: | |
| require_integer(record, key, source, minimum=0) | |
| for key in ("wall_time_seconds", "peak_rss_mb"): | |
| validate_optional_number(record, key, source) | |
| summaries = [ | |
| key | |
| for key in ("evaluation_summary", "selection_summary") | |
| if key in record and record[key] is not None | |
| ] | |
| if status == "success" and not summaries: | |
| raise ValidationError( | |
| f"{source}: successful training_run has no declared return metric" | |
| ) | |
| for key in summaries: | |
| validate_return_summary(record[key], f"{source}.{key}") | |
| elif record_type == "training_metric": | |
| for key in ("claim_id", "task_id", "method", "panel_id"): | |
| require_string(record, key, source) | |
| require_integer(record, "seed", source) | |
| has_periodic = "timesteps" in record or "mean_return" in record | |
| has_episode = "training_episode" in record or "return" in record | |
| if has_periodic == has_episode: | |
| raise ValidationError( | |
| f"{source}: training_metric must be exactly one periodic or episode metric" | |
| ) | |
| if has_periodic: | |
| require_integer(record, "timesteps", source, minimum=0) | |
| require_number(record, "mean_return", source) | |
| else: | |
| require_integer(record, "training_episode", source, minimum=0) | |
| require_number(record, "return", source) | |
| require_integer(record, "episode_length", source, minimum=1) | |
| elif record_type == "proof_certificate": | |
| require_string(record, "claim_id", source) | |
| require_string(record, "task_id", source) | |
| elif record_type == "parameter_audit": | |
| for key in ("claim_id", "task_id", "method"): | |
| require_string(record, key, source) | |
| if status == "success": | |
| if "parameter_count" in record: | |
| require_string(record, "count_source", source) | |
| require_integer(record, "parameter_count", source, minimum=1) | |
| else: | |
| count_keys = ( | |
| "chebyshev_parameter_count", | |
| "paper_stated_mlp_parameter_count", | |
| "correct_dense_2x64x64x1_parameter_count", | |
| "released_ars_comparator_parameter_count", | |
| ) | |
| for key in count_keys: | |
| require_integer(record, key, source, minimum=1) | |
| ratio_contracts = ( | |
| ("ratio_using_paper_count", "paper_stated_mlp_parameter_count"), | |
| ("ratio_using_correct_dense_count", "correct_dense_2x64x64x1_parameter_count"), | |
| ("ratio_using_released_comparator", "released_ars_comparator_parameter_count"), | |
| ) | |
| denominator = float(record["chebyshev_parameter_count"]) | |
| for ratio_key, numerator_key in ratio_contracts: | |
| ratio = require_number(record, ratio_key, source) | |
| expected = float(record[numerator_key]) / denominator | |
| if not math.isclose(ratio, expected, rel_tol=1e-12, abs_tol=1e-12): | |
| raise ValidationError( | |
| f"{source}: {ratio_key}={ratio} does not equal {numerator_key}/" | |
| "chebyshev_parameter_count" | |
| ) | |
| require_number(record, "paper_stated_ratio", source) | |
| validate_optional_number(record, "reduction_factor", source) | |
| elif record_type == "artifact": | |
| if status == "success": | |
| require_string(record, "artifact_path", source) | |
| digest = require_string(record, "artifact_sha256", source) | |
| if len(digest) != 64 or any(char not in "0123456789abcdef" for char in digest): | |
| raise ValidationError(f"{source}: artifact_sha256 is not lowercase SHA-256") | |
| require_integer(record, "artifact_bytes", source, minimum=0) | |
| elif record_type == "error": | |
| if status not in FAILURE_STATUSES: | |
| raise ValidationError(f"{source}: error record must have a failure status") | |
| elif record_type == "selection": | |
| for key in ("claim_id", "task_id", "method", "selection_rule"): | |
| require_string(record, key, source) | |
| require_integer(record, "candidate_count", source, minimum=1) | |
| require_integer(record, "selected_seed", source) | |
| elif record_type == "environment": | |
| require_string(record, "task_id", source) | |
| for key in ("packages", "hardware", "upstream_commits"): | |
| if not isinstance(record.get(key), dict) or not record[key]: | |
| raise ValidationError(f"{source}: environment.{key} must be a non-empty object") | |
| elif record_type == "claim_summary": | |
| require_string(record, "claim_id", source) | |
| if not isinstance(record.get("summary"), dict) or not record["summary"]: | |
| raise ValidationError(f"{source}: claim_summary.summary must be non-empty") | |
| elif record_type == "scope_limitation": | |
| for key in ("claim_id", "task_id", "method", "reason"): | |
| require_string(record, key, source) | |
| if status != "not_executed": | |
| raise ValidationError( | |
| f"{source}: scope_limitation must have status='not_executed'" | |
| ) | |
| elif record_type == "failure": | |
| require_string(record, "task_id", source) | |
| require_string(record, "error", source) | |
| if status not in FAILURE_STATUSES: | |
| raise ValidationError(f"{source}: failure record must have a failure status") | |
| elif record_type == "exclusion" and status not in EXCLUSION_STATUSES: | |
| raise ValidationError( | |
| f"{source}: exclusion record must have an exclusion status" | |
| ) | |
| def _safe_relative_path(value: str, source: str) -> Path: | |
| path = Path(value) | |
| if path.is_absolute() or not path.parts or any(part in {"", ".", ".."} for part in path.parts): | |
| raise ValidationError(f"{source}: unsafe relative path {value!r}") | |
| return path | |
| def validate_artifacts( | |
| batch_dir: Path, records: Sequence[Mapping[str, Any]], source: str | |
| ) -> None: | |
| artifact_records = [ | |
| record | |
| for record in records | |
| if record["record_type"] == "artifact" and record["status"] == "success" | |
| ] | |
| declared: set[str] = set() | |
| batch_root = batch_dir.resolve() | |
| for record in artifact_records: | |
| relative = _safe_relative_path(str(record["artifact_path"]), source) | |
| canonical_relative = relative.as_posix() | |
| if canonical_relative in declared: | |
| raise ValidationError(f"{source}: duplicate artifact path {canonical_relative!r}") | |
| declared.add(canonical_relative) | |
| candidate = batch_dir / relative | |
| if candidate.is_symlink() or not candidate.is_file(): | |
| raise ValidationError(f"{source}: missing or symlinked artifact {relative}") | |
| resolved = candidate.resolve() | |
| if batch_root not in resolved.parents: | |
| raise ValidationError(f"{source}: artifact escapes its batch: {relative}") | |
| if candidate.stat().st_size != record["artifact_bytes"]: | |
| raise ValidationError(f"{source}: artifact byte count mismatch for {relative}") | |
| if sha256_file(candidate) != record["artifact_sha256"]: | |
| raise ValidationError(f"{source}: artifact hash mismatch for {relative}") | |
| artifact_root = batch_dir / "artifacts" | |
| actual: set[str] = set() | |
| if artifact_root.exists(): | |
| if artifact_root.is_symlink() or not artifact_root.is_dir(): | |
| raise ValidationError(f"{source}: artifacts path is not a real directory") | |
| for path in sorted(artifact_root.rglob("*")): | |
| if path.is_symlink(): | |
| raise ValidationError(f"{source}: symlink found under artifacts: {path}") | |
| if path.is_file(): | |
| actual.add(path.relative_to(batch_dir).as_posix()) | |
| if actual != declared: | |
| missing_records = sorted(actual - declared) | |
| missing_files = sorted(declared - actual) | |
| raise ValidationError( | |
| f"{source}: artifact inventory mismatch; unrecorded={missing_records}, " | |
| f"missing={missing_files}" | |
| ) | |
| def validate_input_snapshots(batch_dir: Path, manifest: Mapping[str, Any], source: str) -> None: | |
| hashes = manifest.get("input_hashes") | |
| if not isinstance(hashes, dict) or not hashes: | |
| raise ValidationError(f"{source}: manifest input_hashes must be a non-empty object") | |
| inputs_dir = batch_dir / "inputs" | |
| if inputs_dir.is_symlink() or not inputs_dir.is_dir(): | |
| raise ValidationError(f"{source}: missing real inputs directory") | |
| actual_names = { | |
| path.name | |
| for path in inputs_dir.iterdir() | |
| if path.is_file() and not path.is_symlink() | |
| } | |
| if actual_names != set(hashes): | |
| raise ValidationError( | |
| f"{source}: input inventory mismatch; actual={sorted(actual_names)}, " | |
| f"declared={sorted(hashes)}" | |
| ) | |
| for name, expected_hash in hashes.items(): | |
| if Path(name).name != name: | |
| raise ValidationError(f"{source}: unsafe input snapshot name {name!r}") | |
| if not isinstance(expected_hash, str) or len(expected_hash) != 64: | |
| raise ValidationError(f"{source}: invalid input SHA-256 for {name}") | |
| path = inputs_dir / name | |
| if sha256_file(path) != expected_hash: | |
| raise ValidationError(f"{source}: input snapshot hash mismatch for {name}") | |
| def _successful(records: Sequence[Mapping[str, Any]], record_type: str, claim_id: str) -> list[Mapping[str, Any]]: | |
| return [ | |
| row | |
| for row in records | |
| if row["record_type"] == record_type | |
| and row["status"] == "success" | |
| and row.get("claim_id") == claim_id | |
| ] | |
| def validate_protocol_coverage( | |
| manifest: Mapping[str, Any], records: Sequence[Mapping[str, Any]], source: str | |
| ) -> tuple[dict[str, Any], ...]: | |
| """Validate predeclared unit counts encoded in the immutable config.""" | |
| config = manifest.get("config") | |
| if not isinstance(config, dict): | |
| raise ValidationError(f"{source}: manifest config must be an object") | |
| claims = config.get("claims") | |
| if not isinstance(claims, dict) or not claims: | |
| raise ValidationError(f"{source}: manifest config.claims must be non-empty") | |
| checks: list[dict[str, Any]] = [] | |
| def exact(label: str, actual: int, expected: int) -> None: | |
| check = {"check": label, "actual": actual, "expected": expected, "status": "pass"} | |
| checks.append(check) | |
| if actual != expected: | |
| raise ValidationError(f"{source}: coverage {label} is {actual}, expected {expected}") | |
| def exact_counter( | |
| label: str, | |
| actual: Mapping[tuple[str, int | None], int], | |
| expected: Mapping[tuple[str, int | None], int], | |
| ) -> None: | |
| def printable(value: Mapping[tuple[str, int | None], int]) -> dict[str, int]: | |
| return { | |
| f"{method}|seed={seed if seed is not None else 'none'}": count | |
| for (method, seed), count in sorted( | |
| value.items(), key=lambda item: (item[0][0], -1 if item[0][1] is None else item[0][1]) | |
| ) | |
| } | |
| actual_dict = dict(actual) | |
| expected_dict = dict(expected) | |
| check = { | |
| "check": label, | |
| "actual": printable(actual_dict), | |
| "expected": printable(expected_dict), | |
| "status": "pass", | |
| } | |
| checks.append(check) | |
| if actual_dict != expected_dict: | |
| raise ValidationError( | |
| f"{source}: coverage {label} mismatch; " | |
| f"actual={printable(actual_dict)}, expected={printable(expected_dict)}" | |
| ) | |
| def method_seed_counter(rows: Sequence[Mapping[str, Any]]) -> Counter[tuple[str, int | None]]: | |
| return Counter( | |
| ( | |
| str(row.get("method")), | |
| row.get("seed") if isinstance(row.get("seed"), int) else None, | |
| ) | |
| for row in rows | |
| ) | |
| def validate_mountaincar_start_grids( | |
| label: str, | |
| rows: Sequence[Mapping[str, Any]], | |
| expected_groups: Mapping[tuple[str, int | None], int], | |
| ) -> None: | |
| groups: dict[tuple[str, int | None], list[float]] = defaultdict(list) | |
| for row in rows: | |
| key = ( | |
| str(row.get("method")), | |
| row.get("seed") if isinstance(row.get("seed"), int) else None, | |
| ) | |
| value = row.get("start_position") | |
| if isinstance(value, bool) or not isinstance(value, (int, float)): | |
| raise ValidationError(f"{source}: {label} has a non-numeric start position") | |
| groups[key].append(float(value)) | |
| if set(groups) != set(expected_groups): | |
| raise ValidationError( | |
| f"{source}: {label} grid groups differ from expected method/seed groups" | |
| ) | |
| reference: tuple[float, ...] | None = None | |
| for key, expected_count in expected_groups.items(): | |
| values = tuple(sorted(groups[key])) | |
| if len(values) != expected_count or len(set(values)) != expected_count: | |
| raise ValidationError( | |
| f"{source}: {label} {key} does not contain {expected_count} unique starts" | |
| ) | |
| if not math.isclose(values[0], -0.6, abs_tol=1e-12) or not math.isclose( | |
| values[-1], -0.4, abs_tol=1e-12 | |
| ): | |
| raise ValidationError( | |
| f"{source}: {label} {key} does not span the preregistered [-0.6, -0.4] range" | |
| ) | |
| if reference is None: | |
| reference = values | |
| elif values != reference: | |
| raise ValidationError(f"{source}: {label} start grids are not identical") | |
| checks.append( | |
| { | |
| "check": label, | |
| "actual": f"{len(expected_groups)} identical complete grids", | |
| "expected": f"{len(expected_groups)} identical complete grids", | |
| "status": "pass", | |
| } | |
| ) | |
| def validate_pendulum_grids( | |
| label: str, | |
| rows: Sequence[Mapping[str, Any]], | |
| expected_groups: Mapping[tuple[str, int | None], int], | |
| ) -> None: | |
| groups: dict[tuple[str, int | None], list[tuple[float, float]]] = defaultdict(list) | |
| for row in rows: | |
| key = ( | |
| str(row.get("method")), | |
| row.get("seed") if isinstance(row.get("seed"), int) else None, | |
| ) | |
| angle = row.get("start_angle") | |
| velocity = row.get("start_angular_velocity") | |
| if ( | |
| isinstance(angle, bool) | |
| or not isinstance(angle, (int, float)) | |
| or isinstance(velocity, bool) | |
| or not isinstance(velocity, (int, float)) | |
| ): | |
| raise ValidationError(f"{source}: {label} has a non-numeric grid coordinate") | |
| groups[key].append((float(angle), float(velocity))) | |
| if set(groups) != set(expected_groups): | |
| raise ValidationError( | |
| f"{source}: {label} grid groups differ from expected method/seed groups" | |
| ) | |
| reference: tuple[tuple[float, float], ...] | None = None | |
| for key, expected_count in expected_groups.items(): | |
| values = tuple(sorted(groups[key])) | |
| if len(values) != expected_count or len(set(values)) != expected_count: | |
| raise ValidationError( | |
| f"{source}: {label} {key} does not contain {expected_count} unique points" | |
| ) | |
| if reference is None: | |
| reference = values | |
| elif values != reference: | |
| raise ValidationError(f"{source}: {label} evaluation grids are not identical") | |
| checks.append( | |
| { | |
| "check": label, | |
| "actual": f"{len(expected_groups)} identical complete grids", | |
| "expected": f"{len(expected_groups)} identical complete grids", | |
| "status": "pass", | |
| } | |
| ) | |
| claim1 = claims.get("claim1") | |
| if isinstance(claim1, dict) and claim1.get("enabled") is True: | |
| exact("claim1.proof_certificates", len(_successful(records, "proof_certificate", "claim1")), 1) | |
| claim2 = claims.get("claim2") | |
| if isinstance(claim2, dict) and claim2.get("enabled") is True: | |
| starts = claim2.get("start_count") | |
| baselines = claim2.get("baselines") | |
| if not isinstance(starts, int) or starts < 2 or not isinstance(baselines, list): | |
| raise ValidationError(f"{source}: invalid Claim 2 coverage config") | |
| expected = starts * (1 + len(baselines)) | |
| episode_rows = _successful(records, "episode", "claim2") | |
| exact("claim2.episodes", len(episode_rows), expected) | |
| expected_groups = { | |
| (method, None): starts | |
| for method in ("analytic_two_phase", *(str(value) for value in baselines)) | |
| } | |
| exact_counter( | |
| "claim2.method_episode_counts", | |
| method_seed_counter(episode_rows), | |
| expected_groups, | |
| ) | |
| validate_mountaincar_start_grids( | |
| "claim2.fixed_start_grids", episode_rows, expected_groups | |
| ) | |
| parameter_methods = { | |
| str(row.get("method")) | |
| for row in records | |
| if row["record_type"] == "parameter_audit" and row["status"] == "success" | |
| } | |
| missing = sorted(set(str(value) for value in baselines) - parameter_methods) | |
| if missing: | |
| raise ValidationError(f"{source}: missing executable parameter audits for {missing}") | |
| checks.append( | |
| { | |
| "check": "claim2.baseline_parameter_methods", | |
| "actual": sorted(parameter_methods & set(str(value) for value in baselines)), | |
| "expected": sorted(str(value) for value in baselines), | |
| "status": "pass", | |
| } | |
| ) | |
| claim3 = claims.get("claim3") | |
| if isinstance(claim3, dict) and claim3.get("enabled") is True: | |
| seeds = claim3.get("seeds") | |
| starts = claim3.get("evaluation_start_count") | |
| if not isinstance(seeds, list) or not seeds or not isinstance(starts, int) or starts < 2: | |
| raise ValidationError(f"{source}: invalid Claim 3 coverage config") | |
| exact("claim3.training_runs", len(_successful(records, "training_run", "claim3")), len(seeds)) | |
| training_rows = _successful(records, "training_run", "claim3") | |
| expected_training_groups = {("ch3_ars", int(seed)): 1 for seed in seeds} | |
| exact_counter( | |
| "claim3.method_seed_training_runs", | |
| method_seed_counter(training_rows), | |
| expected_training_groups, | |
| ) | |
| episode_rows = _successful(records, "episode", "claim3") | |
| exact("claim3.episodes", len(episode_rows), len(seeds) * starts) | |
| expected_episode_groups = { | |
| ("ch3_ars", int(seed)): starts for seed in seeds | |
| } | |
| exact_counter( | |
| "claim3.method_seed_episode_counts", | |
| method_seed_counter(episode_rows), | |
| expected_episode_groups, | |
| ) | |
| validate_mountaincar_start_grids( | |
| "claim3.fixed_start_grids", episode_rows, expected_episode_groups | |
| ) | |
| selection_rows = _successful(records, "selection", "claim3") | |
| if ( | |
| len(selection_rows) != 1 | |
| or selection_rows[0].get("method") != "ch3_ars" | |
| or selection_rows[0].get("candidate_count") != len(seeds) | |
| or selection_rows[0].get("selected_seed") not in seeds | |
| ): | |
| raise ValidationError( | |
| f"{source}: Claim 3 must contain one complete CH-3-ARS selection" | |
| ) | |
| chebyshev_parameter_rows = [ | |
| row | |
| for row in _successful(records, "parameter_audit", "claim3") | |
| if "ch" in str(row.get("method", "")).lower() | |
| or "chebyshev" in str(row.get("method", "")).lower() | |
| or "chebyshev_parameter_count" in row | |
| ] | |
| if not chebyshev_parameter_rows: | |
| raise ValidationError(f"{source}: Claim 3 has no Chebyshev parameter audit") | |
| checks.append( | |
| { | |
| "check": "claim3.chebyshev_parameter_audit", | |
| "actual": len(chebyshev_parameter_rows), | |
| "expected": ">=1", | |
| "status": "pass", | |
| } | |
| ) | |
| claim4 = claims.get("claim4") | |
| if isinstance(claim4, dict) and claim4.get("enabled") is True: | |
| ppo_seeds = claim4.get("ppo_seeds") | |
| reinforce_seeds = claim4.get("reinforce_seeds") | |
| start_count = claim4.get("evaluation_start_count") | |
| selection_count = claim4.get("reinforce_selection_episodes") | |
| if ( | |
| not isinstance(ppo_seeds, list) | |
| or not ppo_seeds | |
| or not isinstance(reinforce_seeds, list) | |
| or not reinforce_seeds | |
| or not isinstance(start_count, int) | |
| or start_count < 2 | |
| or not isinstance(selection_count, int) | |
| or selection_count < 1 | |
| ): | |
| raise ValidationError(f"{source}: invalid Claim 4 coverage config") | |
| exact( | |
| "claim4.training_runs", | |
| len(_successful(records, "training_run", "claim4")), | |
| len(ppo_seeds) + len(reinforce_seeds), | |
| ) | |
| training_rows = _successful(records, "training_run", "claim4") | |
| expected_training_groups = { | |
| **{("ch3_ppo", int(seed)): 1 for seed in ppo_seeds}, | |
| **{ | |
| ("ch3_reinforce_adamw_seeded", int(seed)): 1 | |
| for seed in reinforce_seeds | |
| }, | |
| } | |
| exact_counter( | |
| "claim4.method_seed_training_runs", | |
| method_seed_counter(training_rows), | |
| expected_training_groups, | |
| ) | |
| expected_episodes = ( | |
| len(ppo_seeds) * start_count | |
| + len(reinforce_seeds) * selection_count | |
| + start_count | |
| ) | |
| episode_rows = _successful(records, "episode", "claim4") | |
| exact("claim4.episodes", len(episode_rows), expected_episodes) | |
| selection_rows = _successful(records, "selection", "claim4") | |
| selection_by_method = { | |
| str(row.get("method")): row for row in selection_rows | |
| } | |
| if len(selection_rows) != 2 or set(selection_by_method) != { | |
| "ch3_ppo", | |
| "ch3_reinforce_adamw_seeded", | |
| }: | |
| raise ValidationError( | |
| f"{source}: Claim 4 must contain exactly one PPO and one REINFORCE selection" | |
| ) | |
| for method, candidates in ( | |
| ("ch3_ppo", len(ppo_seeds)), | |
| ("ch3_reinforce_adamw_seeded", len(reinforce_seeds)), | |
| ): | |
| if selection_by_method[method].get("candidate_count") != candidates: | |
| raise ValidationError( | |
| f"{source}: Claim 4 selection {method} has the wrong candidate count" | |
| ) | |
| selected_reinforce_seed = selection_by_method[ | |
| "ch3_reinforce_adamw_seeded" | |
| ].get("selected_seed") | |
| if not isinstance(selected_reinforce_seed, int): | |
| raise ValidationError(f"{source}: Claim 4 REINFORCE selected seed is invalid") | |
| expected_episode_groups = { | |
| **{("ch3_ppo", int(seed)): start_count for seed in ppo_seeds}, | |
| **{ | |
| ("ch3_reinforce_adamw_seeded", int(seed)): selection_count | |
| for seed in reinforce_seeds | |
| }, | |
| ("ch3_reinforce_adamw_seeded_selected", selected_reinforce_seed): start_count, | |
| } | |
| exact_counter( | |
| "claim4.method_seed_episode_counts", | |
| method_seed_counter(episode_rows), | |
| expected_episode_groups, | |
| ) | |
| fixed_grid_rows = [ | |
| row | |
| for row in episode_rows | |
| if row.get("method") | |
| in {"ch3_ppo", "ch3_reinforce_adamw_seeded_selected"} | |
| ] | |
| fixed_grid_groups = { | |
| key: count | |
| for key, count in expected_episode_groups.items() | |
| if key[0] in {"ch3_ppo", "ch3_reinforce_adamw_seeded_selected"} | |
| } | |
| validate_mountaincar_start_grids( | |
| "claim4.fixed_start_grids", fixed_grid_rows, fixed_grid_groups | |
| ) | |
| claim5 = claims.get("claim5") | |
| if isinstance(claim5, dict) and claim5.get("enabled") is True: | |
| seeds = claim5.get("seeds") | |
| points = claim5.get("grid_points_per_dimension") | |
| baselines = claim5.get("baselines") | |
| if ( | |
| not isinstance(seeds, list) | |
| or not seeds | |
| or not isinstance(points, int) | |
| or points < 2 | |
| or not isinstance(baselines, list) | |
| ): | |
| raise ValidationError(f"{source}: invalid Claim 5 coverage config") | |
| training_rows = _successful(records, "training_run", "claim5") | |
| exact("claim5.training_runs", len(training_rows), len(seeds)) | |
| expected_training_groups = { | |
| ("ch6_ars_pendulum", int(seed)): 1 for seed in seeds | |
| } | |
| exact_counter( | |
| "claim5.method_seed_training_runs", | |
| method_seed_counter(training_rows), | |
| expected_training_groups, | |
| ) | |
| # The runner keeps every learned-policy grid, emits a separately named | |
| # copy of the selected grid, evaluates the author-exact released | |
| # baseline, and adds one corrected-reset sensitivity grid disclosed in | |
| # DRIFT.md D-003. | |
| expected_episodes = (len(seeds) + len(baselines) + 2) * points * points | |
| episode_rows = _successful(records, "episode", "claim5") | |
| exact("claim5.episodes", len(episode_rows), expected_episodes) | |
| if [str(value) for value in baselines] != ["ars"]: | |
| raise ValidationError( | |
| f"{source}: Claim 5 canonical contract expects exactly the released ARS baseline" | |
| ) | |
| selection_rows = _successful(records, "selection", "claim5") | |
| if ( | |
| len(selection_rows) != 1 | |
| or selection_rows[0].get("method") != "ch6_ars_pendulum" | |
| or selection_rows[0].get("candidate_count") != len(seeds) | |
| or not isinstance(selection_rows[0].get("selected_seed"), int) | |
| ): | |
| raise ValidationError( | |
| f"{source}: Claim 5 must contain one complete CH-6-ARS selection" | |
| ) | |
| selected_seed = int(selection_rows[0]["selected_seed"]) | |
| expected_episode_groups = { | |
| **{ | |
| ("ch6_ars_pendulum", int(seed)): points * points | |
| for seed in seeds | |
| }, | |
| ("ch6_ars_pendulum_selected", selected_seed): points * points, | |
| ("ars_baseline_pendulum_released", 0): points * points, | |
| ( | |
| "ars_baseline_pendulum_released_corrected_reset", | |
| 0, | |
| ): points * points, | |
| } | |
| exact_counter( | |
| "claim5.method_seed_episode_counts", | |
| method_seed_counter(episode_rows), | |
| expected_episode_groups, | |
| ) | |
| validate_pendulum_grids( | |
| "claim5.fixed_evaluation_grids", episode_rows, expected_episode_groups | |
| ) | |
| return tuple(checks) | |
| def canonicalize_record(record: Mapping[str, Any]) -> dict[str, Any]: | |
| """Add declared canonical fields without removing any raw field.""" | |
| output = dict(record) | |
| if record["record_type"] == "episode": | |
| if "start_angle" in record: | |
| output["initial_angle"] = record["start_angle"] | |
| if "start_angular_velocity" in record: | |
| output["initial_angular_velocity"] = record["start_angular_velocity"] | |
| elif record["record_type"] == "training_run": | |
| configuration = record.get("configuration") | |
| if isinstance(configuration, dict) and isinstance(configuration.get("environment"), str): | |
| output["environment"] = configuration["environment"] | |
| if "actual_timesteps" in record: | |
| output["timesteps"] = record["actual_timesteps"] | |
| output["timesteps_source"] = "actual_timesteps" | |
| elif "configured_timesteps" in record: | |
| output["timesteps"] = record["configured_timesteps"] | |
| output["timesteps_source"] = "configured_timesteps" | |
| if "actual_training_episodes" in record: | |
| output["episodes"] = record["actual_training_episodes"] | |
| output["episodes_source"] = "actual_training_episodes" | |
| elif "configured_episodes" in record: | |
| output["episodes"] = record["configured_episodes"] | |
| output["episodes_source"] = "configured_episodes" | |
| for source_key, prefix in ( | |
| ("evaluation_summary", "evaluation"), | |
| ("selection_summary", "selection"), | |
| ): | |
| summary = record.get(source_key) | |
| if isinstance(summary, dict): | |
| for metric in ("count", "mean", "std", "min", "max"): | |
| output[f"{prefix}_{metric}_return" if metric != "count" else f"{prefix}_count"] = summary[metric] | |
| if "task_id" not in output: | |
| output["task_id"] = f"{record['method']}_seed_{record['seed']}" | |
| output["task_id_source"] = "canonical_method_seed" | |
| if "attempt_id" not in output: | |
| output["attempt_id"] = 1 | |
| output["attempt_id_source"] = "canonical_single_raw_attempt" | |
| return output | |
| def load_batch(batch_dir: Path) -> BatchData: | |
| batch_dir = batch_dir.resolve() | |
| source = str(batch_dir) | |
| manifest_path = batch_dir / "manifest.json" | |
| records_path = batch_dir / "records.jsonl" | |
| if not manifest_path.is_file() or manifest_path.is_symlink(): | |
| raise ValidationError(f"{source}: missing real manifest.json") | |
| if not records_path.is_file() or records_path.is_symlink(): | |
| raise ValidationError(f"{source}: missing real records.jsonl") | |
| manifest = require_object( | |
| parse_json(manifest_path.read_text(encoding="utf-8"), str(manifest_path)), | |
| str(manifest_path), | |
| ) | |
| for key in ( | |
| "schema_version", | |
| "experiment_id", | |
| "spec_version", | |
| "paper_version", | |
| "openreview_id", | |
| "batch_id", | |
| "status", | |
| "records_sha256", | |
| ): | |
| require_string(manifest, key, str(manifest_path)) | |
| if manifest["schema_version"] != SUPPORTED_SCHEMA_VERSION: | |
| raise ValidationError( | |
| f"{source}: unsupported schema_version {manifest['schema_version']!r}" | |
| ) | |
| if manifest["status"] != "success": | |
| raise ValidationError( | |
| f"{source}: raw manifest status is {manifest['status']!r}, not 'success'" | |
| ) | |
| if manifest.get("error") not in (None, ""): | |
| raise ValidationError(f"{source}: successful manifest contains an error") | |
| if batch_dir.name != manifest["batch_id"]: | |
| raise ValidationError( | |
| f"{source}: directory name and manifest batch_id do not match" | |
| ) | |
| actual_records_hash = sha256_file(records_path) | |
| if actual_records_hash != manifest["records_sha256"]: | |
| raise ValidationError(f"{source}: records.jsonl SHA-256 mismatch") | |
| records: list[dict[str, Any]] = [] | |
| seen_hashes: set[str] = set() | |
| seen_task_ids: set[tuple[str, str, int]] = set() | |
| seen_training_units: set[tuple[str, int, str]] = set() | |
| with records_path.open("r", encoding="utf-8", newline="") as handle: | |
| for line_number, line in enumerate(handle, start=1): | |
| if not line.strip(): | |
| raise ValidationError(f"{records_path}:{line_number}: blank JSONL line") | |
| record = require_object( | |
| parse_json(line, f"{records_path}:{line_number}"), | |
| f"{records_path}:{line_number}", | |
| ) | |
| record_source = f"{records_path}:{line_number}" | |
| validate_record(record, record_source) | |
| for key in ( | |
| "schema_version", | |
| "experiment_id", | |
| "spec_version", | |
| "paper_version", | |
| "openreview_id", | |
| "batch_id", | |
| ): | |
| if record[key] != manifest[key]: | |
| raise ValidationError( | |
| f"{record_source}: {key} differs from its manifest" | |
| ) | |
| digest = hashlib.sha256(canonical_json(record).encode("utf-8")).hexdigest() | |
| if digest in seen_hashes: | |
| raise ValidationError(f"{record_source}: duplicate canonical record") | |
| seen_hashes.add(digest) | |
| if "task_id" in record: | |
| attempt_id = record.get("attempt_id", 1) | |
| if isinstance(attempt_id, bool) or not isinstance(attempt_id, int): | |
| raise ValidationError(f"{record_source}: invalid attempt_id") | |
| identity = (record["record_type"], str(record["task_id"]), attempt_id) | |
| if identity in seen_task_ids: | |
| raise ValidationError(f"{record_source}: duplicate task/attempt identity {identity}") | |
| seen_task_ids.add(identity) | |
| if record["record_type"] == "training_run": | |
| training_identity = ( | |
| str(record["method"]), | |
| int(record["seed"]), | |
| str(record["panel_id"]), | |
| ) | |
| if training_identity in seen_training_units: | |
| raise ValidationError( | |
| f"{record_source}: duplicate training method/seed/panel {training_identity}" | |
| ) | |
| seen_training_units.add(training_identity) | |
| enriched = canonicalize_record(record) | |
| enriched["source_batch"] = manifest["batch_id"] | |
| enriched["source_line_number"] = line_number | |
| enriched["record_sha256"] = digest | |
| records.append(enriched) | |
| if not records: | |
| raise ValidationError(f"{source}: records.jsonl is empty") | |
| declared_counts = manifest.get("record_counts") | |
| if not isinstance(declared_counts, dict): | |
| raise ValidationError(f"{source}: manifest record_counts must be an object") | |
| if any(isinstance(value, bool) or not isinstance(value, int) or value < 0 for value in declared_counts.values()): | |
| raise ValidationError(f"{source}: manifest record_counts contains invalid counts") | |
| actual_counts = Counter(str(record["record_type"]) for record in records) | |
| if dict(sorted(actual_counts.items())) != dict(sorted(declared_counts.items())): | |
| raise ValidationError( | |
| f"{source}: record_counts mismatch; actual={dict(sorted(actual_counts.items()))}, " | |
| f"declared={dict(sorted(declared_counts.items()))}" | |
| ) | |
| validate_input_snapshots(batch_dir, manifest, source) | |
| validate_artifacts(batch_dir, records, source) | |
| coverage = validate_protocol_coverage(manifest, records, source) | |
| return BatchData( | |
| directory=batch_dir, | |
| manifest=manifest, | |
| records=tuple(records), | |
| records_sha256=actual_records_hash, | |
| manifest_sha256=sha256_file(manifest_path), | |
| coverage_checks=coverage, | |
| ) | |
| def discover_batches(raw_roots: Sequence[Path]) -> list[Path]: | |
| discovered: dict[Path, None] = {} | |
| for raw_root in raw_roots: | |
| root = raw_root.resolve() | |
| if not root.exists(): | |
| raise ValidationError(f"Raw root does not exist: {root}") | |
| if (root / "manifest.json").is_file() or (root / "records.jsonl").is_file(): | |
| candidates = [root] | |
| elif root.is_dir(): | |
| candidates = sorted( | |
| path.parent | |
| for path in root.rglob("manifest.json") | |
| if (path.parent / "records.jsonl").is_file() | |
| ) | |
| else: | |
| raise ValidationError(f"Raw root is not a directory: {root}") | |
| if not candidates: | |
| raise ValidationError(f"No evidence batches found under {root}") | |
| for candidate in candidates: | |
| discovered[candidate.resolve()] = None | |
| return sorted(discovered) | |
| def validate_cross_batch_identity(batches: Sequence[BatchData]) -> None: | |
| if not batches: | |
| raise ValidationError("At least one batch is required") | |
| identity_keys = ( | |
| "schema_version", | |
| "experiment_id", | |
| "spec_version", | |
| "paper_version", | |
| "openreview_id", | |
| ) | |
| expected = {key: batches[0].manifest[key] for key in identity_keys} | |
| seen_ids: set[str] = set() | |
| for batch in batches: | |
| actual = {key: batch.manifest[key] for key in identity_keys} | |
| if actual != expected: | |
| raise ValidationError( | |
| f"Cross-batch identity mismatch in {batch.directory}: {actual} != {expected}" | |
| ) | |
| batch_id = str(batch.manifest["batch_id"]) | |
| if batch_id in seen_ids: | |
| raise ValidationError(f"Duplicate batch_id across inputs: {batch_id}") | |
| seen_ids.add(batch_id) | |
| def table_for_record_type(record_type: str) -> str: | |
| mapping = { | |
| "episode": "episodes.csv", | |
| "training_run": "training_runs.csv", | |
| "training_metric": "training_metrics.csv", | |
| "proof_certificate": "proof_certificates.csv", | |
| "parameter_audit": "parameter_audit.csv", | |
| "artifact": "artifacts.csv", | |
| "selection": "selections.csv", | |
| "environment": "environments.csv", | |
| "claim_summary": "claim_summaries.csv", | |
| "scope_limitation": "exclusions.csv", | |
| "failure": "errors.csv", | |
| "error": "errors.csv", | |
| "exclusion": "exclusions.csv", | |
| } | |
| return mapping[record_type] | |
| def sort_component(value: Any) -> tuple[int, Any]: | |
| if value is None or value == "": | |
| return (0, "") | |
| if isinstance(value, bool): | |
| return (1, int(value)) | |
| if isinstance(value, (int, float)): | |
| return (2, float(value)) | |
| return (3, canonical_json(value) if isinstance(value, (dict, list)) else str(value)) | |
| SORT_FIELDS: dict[str, tuple[str, ...]] = { | |
| "episodes.csv": ( | |
| "experiment_id", | |
| "batch_id", | |
| "claim_id", | |
| "panel_id", | |
| "environment", | |
| "method", | |
| "seed", | |
| "start_position", | |
| "initial_angle", | |
| "initial_angular_velocity", | |
| "task_id", | |
| "attempt_id", | |
| "source_line_number", | |
| ), | |
| "training_runs.csv": ( | |
| "experiment_id", | |
| "batch_id", | |
| "claim_id", | |
| "panel_id", | |
| "environment", | |
| "method", | |
| "seed", | |
| "attempt_id", | |
| "task_id", | |
| "source_line_number", | |
| ), | |
| "training_metrics.csv": ( | |
| "experiment_id", | |
| "batch_id", | |
| "claim_id", | |
| "panel_id", | |
| "method", | |
| "seed", | |
| "timesteps", | |
| "training_episode", | |
| "task_id", | |
| "source_line_number", | |
| ), | |
| "proof_certificates.csv": ( | |
| "experiment_id", | |
| "batch_id", | |
| "claim_id", | |
| "task_id", | |
| "source_line_number", | |
| ), | |
| "parameter_audit.csv": ( | |
| "experiment_id", | |
| "batch_id", | |
| "claim_id", | |
| "method", | |
| "count_source", | |
| "task_id", | |
| "source_line_number", | |
| ), | |
| "artifacts.csv": ("experiment_id", "batch_id", "artifact_path", "source_line_number"), | |
| "selections.csv": ( | |
| "experiment_id", | |
| "batch_id", | |
| "claim_id", | |
| "method", | |
| "task_id", | |
| "source_line_number", | |
| ), | |
| "environments.csv": ("experiment_id", "batch_id", "task_id", "source_line_number"), | |
| "claim_summaries.csv": ( | |
| "experiment_id", | |
| "batch_id", | |
| "claim_id", | |
| "source_line_number", | |
| ), | |
| "errors.csv": ("experiment_id", "batch_id", "claim_id", "task_id", "source_line_number"), | |
| "exclusions.csv": ("experiment_id", "batch_id", "claim_id", "task_id", "source_line_number"), | |
| } | |
| def deterministic_sort(rows: Iterable[dict[str, Any]], table_name: str) -> list[dict[str, Any]]: | |
| fields = SORT_FIELDS[table_name] | |
| return sorted(rows, key=lambda row: tuple(sort_component(row.get(field)) for field in fields)) | |
| def build_record_tables(batches: Sequence[BatchData]) -> dict[str, list[dict[str, Any]]]: | |
| tables = {name: [] for name in TABLE_CORE_COLUMNS if name != "summaries.csv"} | |
| assigned_hashes: set[str] = set() | |
| all_hashes: set[str] = set() | |
| for batch in batches: | |
| for record in batch.records: | |
| digest = str(record["record_sha256"]) | |
| all_hashes.add(digest) | |
| target = table_for_record_type(str(record["record_type"])) | |
| tables[target].append(dict(record)) | |
| assigned_hashes.add(digest) | |
| if record["status"] in FAILURE_STATUSES and target != "errors.csv": | |
| tables["errors.csv"].append(dict(record)) | |
| if record["status"] in EXCLUSION_STATUSES and target != "exclusions.csv": | |
| tables["exclusions.csv"].append(dict(record)) | |
| if all_hashes != assigned_hashes: | |
| raise AssertionError("Internal error: a validated raw record was not assigned") | |
| for name in tables: | |
| tables[name] = deterministic_sort(tables[name], name) | |
| return tables | |
| SUMMARY_GROUP_FIELDS = ( | |
| "experiment_id", | |
| "spec_version", | |
| "paper_version", | |
| "openreview_id", | |
| "batch_id", | |
| "claim_id", | |
| "panel_id", | |
| "environment", | |
| "method", | |
| ) | |
| def summarize_group( | |
| summary_type: str, | |
| group_key: tuple[Any, ...], | |
| rows: Sequence[Mapping[str, Any]], | |
| metric_name: str, | |
| ) -> dict[str, Any]: | |
| successful = [row for row in rows if row.get("status") == "success"] | |
| values: list[float] = [] | |
| for row in successful: | |
| value = row.get(metric_name) | |
| if value is None: | |
| continue | |
| if isinstance(value, bool) or not isinstance(value, (int, float)) or not math.isfinite(float(value)): | |
| raise ValidationError( | |
| f"Cannot summarize non-numeric {metric_name!r} in record {row.get('record_sha256')}" | |
| ) | |
| values.append(float(value)) | |
| result = dict(zip(SUMMARY_GROUP_FIELDS, group_key)) | |
| result.update( | |
| { | |
| "summary_type": summary_type, | |
| "metric_name": metric_name, | |
| "record_count": len(rows), | |
| "success_count": len(successful), | |
| "error_count": sum(row.get("status") in FAILURE_STATUSES for row in rows), | |
| "exclusion_count": sum(row.get("status") in EXCLUSION_STATUSES for row in rows), | |
| "value_count": len(values), | |
| "mean": statistics.fmean(values) if values else None, | |
| "std_population": statistics.pstdev(values) if values else None, | |
| "min": min(values) if values else None, | |
| "max": max(values) if values else None, | |
| } | |
| ) | |
| return result | |
| def build_summaries(tables: Mapping[str, Sequence[Mapping[str, Any]]]) -> list[dict[str, Any]]: | |
| output: list[dict[str, Any]] = [] | |
| episode_groups: dict[tuple[Any, ...], list[Mapping[str, Any]]] = defaultdict(list) | |
| for row in tables["episodes.csv"]: | |
| episode_groups[tuple(row.get(field) for field in SUMMARY_GROUP_FIELDS)].append(row) | |
| for key, rows in sorted(episode_groups.items(), key=lambda item: tuple(sort_component(v) for v in item[0])): | |
| output.append(summarize_group("episodes", key, rows, "return")) | |
| training_groups: dict[tuple[Any, ...], list[Mapping[str, Any]]] = defaultdict(list) | |
| for row in tables["training_runs.csv"]: | |
| training_groups[tuple(row.get(field) for field in SUMMARY_GROUP_FIELDS)].append(row) | |
| metric_fields = ( | |
| "evaluation_mean_return", | |
| "selection_mean_return", | |
| "mean_return", | |
| "return", | |
| ) | |
| for key, rows in sorted(training_groups.items(), key=lambda item: tuple(sort_component(v) for v in item[0])): | |
| present = [metric for metric in metric_fields if any(row.get(metric) is not None for row in rows)] | |
| if not present: | |
| output.append(summarize_group("training_runs", key, rows, "")) | |
| else: | |
| output.extend(summarize_group("training_runs", key, rows, metric) for metric in present) | |
| return output | |
| def csv_value(value: Any) -> str | int: | |
| if value is None: | |
| return "" | |
| if isinstance(value, bool): | |
| return "true" if value else "false" | |
| if isinstance(value, int): | |
| return value | |
| if isinstance(value, float): | |
| if not math.isfinite(value): | |
| raise ValidationError("Cannot write non-finite float to canonical CSV") | |
| return format(value, ".17g") | |
| if isinstance(value, (dict, list)): | |
| return canonical_json(value) | |
| return str(value) | |
| def ordered_columns(table_name: str, rows: Sequence[Mapping[str, Any]]) -> list[str]: | |
| preferred = list(dict.fromkeys(TABLE_CORE_COLUMNS[table_name])) | |
| extras = sorted({key for row in rows for key in row} - set(preferred)) | |
| return [*preferred, *extras] | |
| def write_csv(path: Path, table_name: str, rows: Sequence[Mapping[str, Any]]) -> list[str]: | |
| columns = ordered_columns(table_name, rows) | |
| with path.open("w", encoding="utf-8", newline="") as handle: | |
| writer = csv.DictWriter( | |
| handle, | |
| fieldnames=columns, | |
| extrasaction="raise", | |
| lineterminator="\n", | |
| ) | |
| writer.writeheader() | |
| for row in rows: | |
| writer.writerow({column: csv_value(row.get(column)) for column in columns}) | |
| return columns | |
| def publish_directory(staging: Path, destination: Path, replace: bool) -> None: | |
| if destination.is_symlink(): | |
| raise ValidationError(f"Refusing to publish through a symlink: {destination}") | |
| destination = destination.resolve() | |
| if destination.exists() and not destination.is_dir(): | |
| raise ValidationError(f"Output path exists and is not a directory: {destination}") | |
| if destination.exists() and not replace: | |
| raise ValidationError( | |
| f"Output directory already exists: {destination}; use --replace for derived outputs" | |
| ) | |
| destination.parent.mkdir(parents=True, exist_ok=True) | |
| if not destination.exists(): | |
| os.replace(staging, destination) | |
| return | |
| backup = destination.parent / f".{destination.name}.old-{os.getpid()}" | |
| if backup.exists(): | |
| raise ValidationError(f"Refusing to overwrite stale backup directory: {backup}") | |
| os.replace(destination, backup) | |
| try: | |
| os.replace(staging, destination) | |
| except BaseException: | |
| os.replace(backup, destination) | |
| raise | |
| shutil.rmtree(backup) | |
| def build_tables(raw_roots: Sequence[Path], output_root: Path, replace: bool) -> dict[str, Any]: | |
| batch_dirs = discover_batches(raw_roots) | |
| output_resolved = output_root.resolve() | |
| for batch_dir in batch_dirs: | |
| if output_resolved == batch_dir or batch_dir in output_resolved.parents: | |
| raise ValidationError("Canonical output must not overwrite or be nested in a raw batch") | |
| batches = [load_batch(path) for path in batch_dirs] | |
| validate_cross_batch_identity(batches) | |
| tables = build_record_tables(batches) | |
| tables["summaries.csv"] = build_summaries(tables) | |
| output_root.parent.mkdir(parents=True, exist_ok=True) | |
| staging = Path( | |
| tempfile.mkdtemp(prefix=f".{output_root.name}.tmp-", dir=output_root.parent.resolve()) | |
| ) | |
| try: | |
| table_manifest: dict[str, Any] = {} | |
| for table_name in TABLE_CORE_COLUMNS: | |
| rows = tables[table_name] | |
| columns = write_csv(staging / table_name, table_name, rows) | |
| table_manifest[table_name] = { | |
| "path": table_name, | |
| "rows": len(rows), | |
| "columns": columns, | |
| "sha256": sha256_file(staging / table_name), | |
| } | |
| identity = batches[0].manifest | |
| manifest = { | |
| "schema_version": SUPPORTED_SCHEMA_VERSION, | |
| "builder": "build_tables.py", | |
| "builder_version": BUILDER_VERSION, | |
| "builder_sha256": sha256_file(Path(__file__).resolve()), | |
| "command": build_command(raw_roots, output_root, replace), | |
| "status": "success", | |
| "experiment_id": identity["experiment_id"], | |
| "spec_version": identity["spec_version"], | |
| "paper_version": identity["paper_version"], | |
| "openreview_id": identity["openreview_id"], | |
| "source_batches": [ | |
| { | |
| "batch_id": batch.manifest["batch_id"], | |
| "directory_name": batch.directory.name, | |
| "manifest_sha256": batch.manifest_sha256, | |
| "records_sha256": batch.records_sha256, | |
| "record_counts": batch.manifest["record_counts"], | |
| "coverage_checks": list(batch.coverage_checks), | |
| } | |
| for batch in batches | |
| ], | |
| "record_preservation": { | |
| "unknown_record_policy": "fail", | |
| "failure_records": "errors.csv (and their typed table when applicable)", | |
| "exclusion_records": "exclusions.csv (and their typed table when applicable)", | |
| }, | |
| "summary_contract": { | |
| "standard_deviation": "population", | |
| "successful_values_only": True, | |
| "status_counts_include_all_records": True, | |
| "group_fields": list(SUMMARY_GROUP_FIELDS), | |
| }, | |
| "tables": table_manifest, | |
| } | |
| (staging / "MANIFEST.json").write_text( | |
| json.dumps(manifest, ensure_ascii=False, allow_nan=False, indent=2, sort_keys=True) | |
| + "\n", | |
| encoding="utf-8", | |
| ) | |
| publish_directory(staging, output_root, replace) | |
| return manifest | |
| except BaseException: | |
| if staging.exists(): | |
| shutil.rmtree(staging) | |
| raise | |
| def build_command( | |
| raw_roots: Sequence[Path], output_root: Path, replace: bool | |
| ) -> list[str]: | |
| """Return the canonical, interpreter-independent command for this build.""" | |
| command = [str(Path(__file__).resolve())] | |
| for raw_root in raw_roots: | |
| command.extend(("--raw-root", str(raw_root.resolve()))) | |
| command.extend(("--output-root", str(output_root.resolve()))) | |
| if replace: | |
| command.append("--replace") | |
| return command | |
| def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace: | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument( | |
| "--raw-root", | |
| type=Path, | |
| action="append", | |
| required=True, | |
| help="Raw batch directory or a parent containing batches; repeatable.", | |
| ) | |
| parser.add_argument("--output-root", type=Path, required=True) | |
| parser.add_argument( | |
| "--replace", | |
| action="store_true", | |
| help="Atomically replace an existing derived output directory.", | |
| ) | |
| return parser.parse_args(argv) | |
| def main(argv: Sequence[str] | None = None) -> int: | |
| args = parse_args(argv) | |
| try: | |
| manifest = build_tables(args.raw_root, args.output_root, args.replace) | |
| except (OSError, ValidationError, ValueError) as exc: | |
| print(f"build_tables: ERROR: {exc}", file=sys.stderr) | |
| return 2 | |
| total_rows = sum(table["rows"] for table in manifest["tables"].values()) | |
| print( | |
| f"Built {len(manifest['tables'])} canonical tables from " | |
| f"{len(manifest['source_batches'])} batch(es), {total_rows} table rows." | |
| ) | |
| print(args.output_root.resolve() / "MANIFEST.json") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |
Xet Storage Details
- Size:
- 63.5 kB
- Xet hash:
- 70988feec00c075cef88586d798052ed8c6897ac1c1ef713632a8f5b19615b3c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.