Files
wehub-resource-sync 4b6817381b
Benchmark image — build + push to ECR (any adapter) / build + push (push) Waiting to run
CI / quality (ubuntu-latest) (push) Waiting to run
CI / test (tools-runtime) (push) Waiting to run
CI / test (e2e-general) (push) Waiting to run
CI / test (cli-runtime) (push) Waiting to run
CI / test (e2e-provider-and-openclaw) (push) Waiting to run
CI / test (integrations-and-misc) (push) Waiting to run
CI / coverage-report (push) Blocked by required conditions
CI / test-kubernetes (push) Waiting to run
CI / should-run-thorough (push) Waiting to run
CI / test-thorough (cloudwatch-demo) (push) Blocked by required conditions
CI / test-thorough (flink-ecs) (push) Blocked by required conditions
CI / test-thorough (upstream-lambda) (push) Blocked by required conditions
CI / test-thorough (prefect-ecs-fargate) (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Blocked by required conditions
Release / publish-release (push) Blocked by required conditions
Release / publish-main-release (push) Blocked by required conditions
Release / prepare (push) Waiting to run
Release / verify (push) Blocked by required conditions
Release / build-python-dist (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Blocked by required conditions
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Waiting to run
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

71 lines
3.0 KiB
Python

"""Held-out 20% test split for the Cloud-OpsBench corpus.
Implements integrity Mechanism 8 (generalization gate) from the framework's
Pillar 0: 20% of cases are eval-only, never inspected during BDIL
optimization cycles. The split is **derived deterministically** from the
sorted ``case_id`` list — same corpus + same seed → same split, forever.
Policy (mirrors the pre-registration YAML at
``tests/benchmarks/cloudopsbench/configs/preregistrations/cloudopsbench_v1.yml``):
- 80% optimize-against / 20% eval-only
- ``HELD_OUT_SEED = 42`` — distinct from ``config.seed`` (case-selection seed
inside each run). Sharing seeds would couple "which 20% is held out" to
"which N cases this run drew", which would silently invalidate the gate.
- Selection is uniform random over the SORTED case_id list, not the order
the loader returns. Sorting first guarantees stability across loader
iteration-order changes.
- The split is computed at adapter ``load_cases`` time and tagged on each
``BenchmarkCase.metadata["is_held_out"]``. Reports stratify on this.
Inspecting a held-out case's results DURING a BDIL cycle is a contamination
event — the cycle becomes invalid per the pre-registration's
``generalization_gate`` clause.
"""
from __future__ import annotations
import random
from collections.abc import Iterable
# Constants — change these only via committed PR + matching pre-registration update.
HELD_OUT_SEED: int = 42
HELD_OUT_FRAC: float = 0.20
def compute_held_out_set(case_ids: Iterable[str]) -> set[str]:
"""Return the deterministic set of held-out case_ids for the given corpus.
Sorts the input first, so the result is stable regardless of the order
in which the loader yielded cases. Uses ``HELD_OUT_SEED`` — passing a
different seed is not supported; the seed is policy, not configuration.
Args:
case_ids: every case_id in the full corpus (not a filtered subset).
Passing a filtered subset would produce a split of the
subset, which is NOT what the generalization gate wants —
it wants the same 20% relative to the full corpus,
consistently across runs that filter differently.
Returns:
The held-out subset as a set. Membership-check is O(1) at the
adapter's ``load_cases`` tagging site.
"""
sorted_ids = sorted(set(case_ids))
if not sorted_ids:
return set()
held_out_count = max(1, int(round(len(sorted_ids) * HELD_OUT_FRAC)))
rng = random.Random(HELD_OUT_SEED)
return set(rng.sample(sorted_ids, held_out_count))
def is_held_out(case_id: str, full_corpus_case_ids: Iterable[str]) -> bool:
"""Convenience: True if ``case_id`` belongs to the held-out set.
The full corpus must be passed every call because the split is defined
relative to the entire corpus, not relative to any subset. If you're
calling this in a loop, prefer ``compute_held_out_set`` once and use
set membership directly.
"""
return case_id in compute_held_out_set(full_corpus_case_ids)