SPB Git

spb/wp29_uqo

Public
4.2 KB · 109 lines python
1"""Contracts: the serialised research contract P=(Q,Θ,D,A,G,V,B,R,L), run manifests, hashing helpers.23The contract components map to concrete files:4  Q, Θ, D  -> TASK.md (question, estimands, inputs, information-availability rules)  [task bundle]5  A        -> launcher flags (tool inventory, permission policy, model)                [configs/*.yaml]6  G        -> phase graph in the treatment protocol (arms B/C/D) and the harness state machine7  V        -> gate_spec.json (oracle-free runtime checks) + hidden evaluate.py (final evaluation)8  B        -> budget envelope (USD cap, wall seconds, turns per session, gate/review cycles)9  R        -> recovery rules (protocol text) + harness resume/retry policy10  L        -> run manifest, event stream, receipts, screenshot manifest (SQLite + files)11"""12from __future__ import annotations13import dataclasses, hashlib, json, os, pathlib, datetime, uuid14from dataclasses import dataclass, field, asdict15from typing import Optional1617ARMS = ("A", "B", "C", "D")18RUN_STATES = ("not_started", "prepared", "running", "completed", "timeout", "budget_exhausted", "error", "interrupted", "evaluated", "void")19# allowed transitions of a run (harness state machine)20RUN_TRANSITIONS = {21    "not_started": {"prepared", "error", "void"},22    "prepared": {"running", "error", "void"},23    "running": {"completed", "timeout", "budget_exhausted", "error", "interrupted"},24    "interrupted": {"running", "error"},           # resume after a standardized fault25    "completed": {"evaluated", "error"},26    "timeout": {"evaluated", "error"},27    "budget_exhausted": {"evaluated", "error"},28    "error": {"evaluated", "prepared"},            # infra error: can be re-prepared under the rerun policy29    "evaluated": set(), "void": set(),30}31PHASE_STATES = ("pending", "running", "passed", "failed", "blocked", "stale", "skipped_optional")3233def utcnow() -> str:34    return datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="milliseconds")3536def sha256_file(path) -> str:37    h = hashlib.sha256()38    with open(path, "rb") as fh:39        for chunk in iter(lambda: fh.read(1 << 20), b""):40            h.update(chunk)41    return h.hexdigest()4243def sha256_bytes(b: bytes) -> str:44    return hashlib.sha256(b).hexdigest()4546def sha256_text(s: str) -> str:47    return hashlib.sha256(s.encode("utf-8")).hexdigest()4849def dir_manifest(root, exclude=()) -> dict:50    out = {}51    root = pathlib.Path(root)52    for p in sorted(root.rglob("*")):53        if p.is_file():54            rel = p.relative_to(root).as_posix()55            if any(rel == e or rel.startswith(e.rstrip("/") + "/") for e in exclude):56                continue57            out[rel] = sha256_file(p)58    return out5960@dataclass61class Budget:62    max_budget_usd: float = 4.063    wall_seconds: int = 150064    max_turns_per_session: int = 8065    max_gate_cycles: int = 3          # arms C/D: controller-enforced gate feedback cycles66    max_review_cycles: int = 1        # arm D67    min_continuation_usd: float = 0.256869@dataclass70class RunManifest:71    run_id: str72    task_id: str73    split: str74    treatment: str75    repeat_index: int76    block_id: str = ""77    order_in_block: int = 078    node: str = ""79    task_hash: Optional[str] = None80    protocol_hash: Optional[str] = None81    effective_context_hash: Optional[str] = None82    code_commit: Optional[str] = None83    environment_id: Optional[str] = None84    client_version: Optional[str] = None85    model_requested: Optional[str] = None86    model_reported: Optional[str] = None87    session_ids: list = field(default_factory=list)88    started_at_utc: Optional[str] = None89    ended_at_utc: Optional[str] = None90    status: str = "not_started"91    terminal_reason: Optional[str] = None92    budget: dict = field(default_factory=dict)93    usage: dict = field(default_factory=dict)94    human_intervention_ids: list = field(default_factory=list)95    artifact_manifest: Optional[dict] = None96    evaluation_receipt: Optional[str] = None97    screenshot_ids: list = field(default_factory=list)98    fault: Optional[dict] = None99    notes: str = ""100101    def to_json(self) -> str:102        return json.dumps(asdict(self), indent=1, sort_keys=True)103104def new_run_id(split: str, seq: int) -> str:105    return f"R{split[0].upper()}{seq:04d}"106107def new_session_id() -> str:108    return str(uuid.uuid4())109
Files · 449400ebf8aa08d286e9899c675eeb9b3997f6a3
Menu

Theme