Viewing files at commit b76ab8b42dfdCommit detailsView latest

Browse files
scripts/oakbench/public_output.py 178 lines · 11.2 KB · python
1
"""Evidence requirements for publishing output-usefulness measurements.
2
3
Legacy structural markers remain diagnostic data. They cannot certify that
4
standard patch tooling reconstructs the intended repository tree.
5
"""
6
7
from __future__ import annotations
8
9
from typing import Any
10
import math
11
import re
12
import json
13
14
from oakbench.rows import row_returncode
15
from oakbench.populations import comparison_identity
16
from oakbench.output_semantics import OUTPUT_ORACLE_VERSION, PATCH_ORACLE_VERSION
17
from oakbench.workflow_oracles import SCENARIOS as TRUSTED_WORKFLOWS, VERSION as WORKFLOW_ORACLE_VERSION
18
19
20
def output_evidence_failures(row: dict[str, Any]) -> list[str]:
21
    failures: list[str] = []
22
    for flag in ("pipe_compatible_unified", "patch_apply_ok", "patch_tree_matches", "patch_application_required"):
23
        if row.get(flag) is not None and type(row[flag]) is not bool:
24
            failures.append(f"{flag} is not a nullable boolean")
25
    for metric, source in (
26
        ("information_recall", "information_recall_source"),
27
        ("information_precision", "information_precision_source"),
28
    ):
29
        value = row.get(metric)
30
        if value is not None and (
31
            type(value) not in (int, float) or not math.isfinite(value) or not 0 <= value <= 1
32
        ):
33
            failures.append(f"{metric} is not a finite fraction")
34
        if row.get(metric) is not None and (row.get("output_truncated") is True or row.get("probe_output_truncated") is True):
35
            failures.append(f"{metric} is measured from incomplete output")
36
        if row.get(metric) is not None and (
37
            row.get("output_oracle_version") != OUTPUT_ORACLE_VERSION
38
            or row.get(source) != "exact_metadata_path_set"
39
        ):
40
            failures.append(f"{metric} lacks versioned exact-path evidence")
41
42
    claims_applicability = row.get("patch_application_required") is True or row.get("patch_apply_ok") is True
43
    if claims_applicability and not (
44
        row.get("patch_apply_ok") is True
45
        and row.get("patch_tree_matches") is True
46
        and row.get("patch_apply_returncode") == 0
47
        and type(row.get("patch_apply_returncode")) is int
48
        and row.get("patch_oracle_version") == PATCH_ORACLE_VERSION
49
        and row.get("patch_apply_source") == "git_apply_exact_tree"
50
        and isinstance(row.get("patch_instrument_sha256"), str)
51
        and re.fullmatch(r"[0-9a-f]{64}", row["patch_instrument_sha256"])
52
        and isinstance(row.get("patch_instrument_version"), str)
53
        and row["patch_instrument_version"].strip()
54
        and not row.get("patch_skip_reason")
55
        and not row.get("patch_failure_reason")
56
        and not row.get("probe_output_truncated")
57
        and not row.get("output_truncated")
58
    ):
59
        failures.append("structural/applicability success lacks a successful exact-tree patch application")
60
    return failures
61
62
63
def workflow_evidence_failures(rows: list[dict[str, Any]]) -> list[str]:
64
    """Require independent persisted-state evidence for trusted payload tasks.
65
66
    Source labels describe how observations were obtained; they are not
67
    equivalence classes. Scripted summaries must pass; measured agent failures
68
    remain evidence for success-rate accounting.
69
    Successful comparisons require the shared committed-content contract.
70
    """
71
    groups = {}
72
    failures = []
73
    for row in rows:
74
        operation = row.get("operation")
75
        if operation not in {"agent.workflow", "workflow.total", "workflow.skipped"}:
76
            continue
77
        code = row_returncode(row)
78
        integrity = row.get("workflow_integrity_passed")
79
        measured_agent_failure = (
80
            operation == "agent.workflow" and type(integrity) is bool
81
            and row.get("outcome") in {"fail", "timeout", "error"}
82
            and row.get("success") is False and code not in {0, 77}
83
            and not row.get("skipped")
84
            and row.get("outcome_attribution") == "agent" and row.get("agent_launched") is True
85
        )
86
        if not measured_agent_failure and (
87
            operation == "workflow.skipped" or integrity is not True or code != 0
88
            or row.get("skipped") or row.get("success") is False
89
            or row.get("correctness_passed") is False
90
            or (operation == "agent.workflow" and row.get("outcome") not in {None, "pass"})
91
        ):
92
            failures.append(f"{row.get('subject')}/{row.get('scenario')}: workflow correctness is failed, skipped or unmeasured")
93
        if row.get("operation") in {"agent.workflow", "workflow.total"} and row.get("workflow_integrity_evidence_class") in {"independent_committed_tree", "independent_committed_payload"}:
94
            if row.get("workflow_integrity_source") == "trusted_task_worktree;independent_oak_sqlite_reader":
95
                from oakbench.oak_sqlite_reader import READER_VERSION
96
                valid = row.get("oak_reader_version") == READER_VERSION
97
                valid = valid and all(isinstance(row.get(field), str) and re.fullmatch(r"[0-9a-f]{64}", row[field])
98
                    for field in ("oak_reader_sha256", "oak_reader_head", "oak_reader_python_sha256"))
99
                valid = valid and all(isinstance(row.get(field), str) and row[field].strip()
100
                    for field in ("oak_reader_blake3_version", "oak_reader_zstandard_version"))
101
                if not valid:
102
                    failures.append("independent Oak reader lacks versioned instrument/object evidence")
103
            else:
104
                instrument = row.get("git_head_instrument_sha256")
105
                subject = row.get("workflow_subject_binary_sha256")
106
                if (not all(isinstance(value, str) and re.fullmatch(r"[0-9a-f]{64}", value) for value in (instrument, subject))
107
                        or instrument == subject or "subject_produced" in str(row.get("workflow_integrity_source", ""))):
108
                    failures.append("independent reader lacks distinct observed subject/instrument identities or uses subject-produced evidence")
109
        agent = row.get("agent") if isinstance(row.get("agent"), dict) else {}
110
        key = (row.get("scenario"), "workflow.total" if operation == "workflow.skipped" else operation)
111
        groups.setdefault(key, []).append(row)
112
    for key, items in groups.items():
113
        if len({item.get("subject") for item in items}) < 2:
114
            continue
115
        conditions = {}
116
        for item in items:
117
            agent = item.get("agent") if isinstance(item.get("agent"), dict) else {}
118
            condition = comparison_identity(item)
119
            condition.pop("workflow_integrity_evidence_class", None)  # failed pre-HEAD observations remain task failures
120
            condition["agent.name"] = agent.get("name")
121
            conditions.setdefault(item.get("subject"), set()).add(json.dumps(condition, sort_keys=True))
122
        if len({tuple(sorted(values)) for values in conditions.values()}) != 1:
123
            failures.append(f"{key}: subjects have unmatched experimental conditions")
124
        verified = [item for item in items if item.get("workflow_integrity_passed") is True]
125
        if len({item.get("workflow_integrity_evidence_class") for item in verified}) > 1:
126
            failures.append(f"{key}: successful subjects have unequal correctness evidence classes")
127
        if any(item.get("oracle_version") != WORKFLOW_ORACLE_VERSION for item in items):
128
            failures.append(f"{key}: trusted task validator version is incompatible or missing")
129
        # Failed task validation can finish before any HEAD reader runs. It
130
        # measures failure, not persisted completion; keep those trials in
131
        # success-rate evidence without inventing an independent reader.
132
        if any(item.get("workflow_integrity_evidence_class") not in {"independent_committed_tree", "independent_committed_payload"} for item in items
133
               if not (item.get("operation") == "agent.workflow" and item.get("workflow_integrity_passed") is False)):
134
            failures.append(f"{key}: trusted persisted-state comparison requires independent committed-tree readers; subject-produced exports and metadata are insufficient")
135
        if any(not isinstance(item.get("workflow_integrity_source"), str) or not item["workflow_integrity_source"].strip() for item in items):
136
            failures.append(f"{key}: correctness evidence source is missing")
137
        if any("subject_produced" in str(item.get("workflow_integrity_source", ""))
138
               and item.get("workflow_integrity_evidence_class") in {"independent_committed_tree", "independent_committed_payload"} for item in items):
139
            failures.append(f"{key}: subject-produced evidence cannot declare an independent reader class")
140
        if any(type(item.get("workflow_integrity_passed")) is not bool for item in items):
141
            failures.append(f"{key}: correctness evidence is failed or unmeasured")
142
    return failures
143
144
145
def workflow_qualification_failures(rows: list[dict[str, Any]], min_samples: int = 30) -> list[str]:
146
    """Necessary publication hygiene, not a power calculation or study certification."""
147
    selected = [row for row in rows if row.get("operation") in {"workflow.total", "workflow.skipped", "agent.workflow", "agent.setup"}]
148
    failures = []
149
    if not selected:
150
        return failures
151
    values = [row.get("env_isolation_version") for row in selected]
152
    versions = {value for value in values if isinstance(value, str)}
153
    if len(versions) != 1 or any(not isinstance(value, str) or not value.strip() or value in {"unknown", "unmeasured"} for value in values):
154
        failures.append("workflow env-isolation is missing or inconsistent")
155
    groups = {}
156
    for row in selected:
157
        failures.extend(output_evidence_failures(row))
158
        if row.get("operation") == "agent.setup":
159
            failures.append("agent setup infrastructure failure cannot qualify a study")
160
        randomized = next((row[name] for name in ("randomized_subject_order", "randomize_subject_order", "subject_order_randomized") if name in row), None)
161
        order = row.get("subject_order", row.get("run_subject_order"))
162
        if randomized is not True or not isinstance(order, list) or row.get("subject") not in order:
163
            failures.append("workflow subject randomization/order is unmeasured")
164
        agent = row.get("agent") if isinstance(row.get("agent"), dict) else {}
165
        key = (row.get("scenario"), row.get("operation"), row.get("subject"), row.get("benchmark_track"),
166
               row.get("instruction_level", agent.get("instruction_level")), json.dumps(agent, sort_keys=True))
167
        identity = (row.get("bench_id"), row.get("run"))
168
        if not isinstance(identity[0], str) or not identity[0] or type(identity[1]) is not int:
169
            failures.append("workflow independent trial identity missing")
170
        groups.setdefault(key, []).append(json.dumps(identity, sort_keys=True))
171
        if row.get("operation") == "agent.workflow" and (row.get("agent_launched") is not True or row.get("outcome_attribution") != "agent"):
172
            failures.append("workflow outcome is not an observed agent trial")
173
    for key, identities in groups.items():
174
        if len(set(identities)) != len(identities):
175
            failures.append(f"{key[:3]}: duplicate workflow trial identities")
176
        if len(set(identities)) < min_samples:
177
            failures.append(f"{key[:3]}: workflow samples below n={min_samples}")
178
    return list(dict.fromkeys(failures))