1"""Per-attempt record schema (machine-validated) and append-only storage."""2from __future__ import annotations3import json, uuid4from pathlib import Path5from jsonschema import Draft202012Validator6from .util import ROOT, utc_now, append_jsonl, sha256_json, git_commit78STATUSES = ["success", "invalid_output", "timeout", "oom", "incompatible", "implementation_error", "unavailable", "budget_exhausted"]910SCHEMA = {11 "$schema": "https://json-schema.org/draft/2020-12/schema",12 "type": "object",13 "required": ["schema_version", "study_id", "experiment_id", "trial_id", "attempt_id", "run_group_id", "protocol_hash", "config_hash",14 "git_commit", "timestamp_utc", "task_family", "document_id", "document_hash", "question_id", "split", "cluster_id",15 "sender_model_revision", "receiver_model_revision", "tokenizer_hashes", "backend_versions", "hardware_id", "device_state",16 "weight_precision", "method_id", "implementation_fidelity", "compression_config", "question_access", "topology",17 "handoff_index", "reuse_count", "cache_hit", "cache_compatibility_hash", "random_seed", "source_tokens_sender",18 "source_tokens_receiver", "query_tokens", "message_tokens", "message_utf8_bytes", "cache_tensor_bytes",19 "serialized_payload_bytes", "side_information_bytes", "fetched_bytes", "transport_bytes_if_measured", "timing_spans",20 "total_wall_ms", "ttft_ms", "input_usage", "output_usage", "provider_cached_usage", "process_memory", "backend_memory",21 "peak_prefill_memory", "peak_decode_memory", "mapper_memory", "cost_with_source", "prediction_artifact", "evidence_artifact",22 "reference_key_id", "task_scores", "status", "error_code", "retry_of", "log_artifact", "payload_hash", "output_hash"],23 "properties": {24 "schema_version": {"const": "wp30-attempt-1"},25 "status": {"enum": STATUSES},26 "question_access": {"enum": ["blind", "aware", "none"]},27 "implementation_fidelity": {"enum": ["official", "faithful_reimplementation", "adapted", "inspired", "custom", "n/a"]},28 "timing_spans": {"type": "object"},29 "task_scores": {"type": ["object", "null"]},30 "handoff_index": {"type": "integer"}, "reuse_count": {"type": "integer"},31 },32}33_validator = Draft202012Validator(SCHEMA)3435def new_record(**kw) -> dict:36 rec = {k: None for k in SCHEMA["required"]}37 rec.update({"schema_version": "wp30-attempt-1", "study_id": "WP30", "attempt_id": uuid.uuid4().hex[:12], "timestamp_utc": utc_now(),38 "git_commit": git_commit(), "handoff_index": 0, "reuse_count": 1, "cache_hit": False, "timing_spans": {}, "fetched_bytes": 0,39 "side_information_bytes": 0, "transport_bytes_if_measured": None, "retry_of": None})40 rec.update(kw)41 return rec4243def validate_record(rec: dict) -> list[str]:44 return [e.message for e in _validator.iter_errors(rec)]4546def write_record(rec: dict, path: str | Path) -> None:47 errs = validate_record(rec)48 if errs:49 raise ValueError("invalid record: " + "; ".join(errs[:5]))50 append_jsonl(path, rec)5152def trial_key(experiment_id: str, document_id: str, question_id: str, method_id: str, compression_config: dict, sender: str, receiver: str,53 question_access: str, protocol_hash: str, seed: int, topology: str = "single", handoff_index: int = 0, extra: dict | None = None) -> str:54 return sha256_json({"e": experiment_id, "d": document_id, "q": question_id, "m": method_id, "c": compression_config, "s": sender, "r": receiver,55 "a": question_access, "p": protocol_hash, "seed": seed, "t": topology, "h": handoff_index, "x": extra or {}})[:24]56