test: govern unavailable conditional environments

This commit is contained in:
Joseph Magly
2026-08-16 09:05:41 -04:00
parent b961623513
commit c90240f1e9
5 changed files with 352 additions and 9 deletions
+42
View File
@@ -14,6 +14,48 @@
"timeout_minutes": 20
}
},
"environment_waivers": [
{
"gate": "cuda-runtime",
"reason": "No dedicated CUDA runner is confirmed; the enable variable is unset and the current maintainer token cannot enumerate repository runners.",
"issue": "https://github.com/elder-plinius/OBLITERATUS/issues/110",
"opened": "2026-08-16",
"expires": "2026-09-15",
"blocked_claim": "CUDA runtime support, compatibility, and performance are not claimed while this waiver is active."
},
{
"gate": "bitsandbytes-runtime",
"reason": "No dedicated CUDA and bitsandbytes runner is confirmed; the enable variable is unset and the current maintainer token cannot enumerate repository runners.",
"issue": "https://github.com/elder-plinius/OBLITERATUS/issues/110",
"opened": "2026-08-16",
"expires": "2026-09-15",
"blocked_claim": "bitsandbytes runtime support, compatibility, and performance are not claimed while this waiver is active."
},
{
"gate": "mps-runtime",
"reason": "No Apple Silicon MPS runner is confirmed; the enable variable is unset and the current maintainer token cannot enumerate repository runners.",
"issue": "https://github.com/elder-plinius/OBLITERATUS/issues/110",
"opened": "2026-08-16",
"expires": "2026-09-15",
"blocked_claim": "Apple MPS runtime support, compatibility, and performance are not claimed while this waiver is active."
},
{
"gate": "mlx-runtime",
"reason": "No Apple Silicon MLX runner is confirmed; the enable variable is unset and the current maintainer token cannot enumerate repository runners.",
"issue": "https://github.com/elder-plinius/OBLITERATUS/issues/110",
"opened": "2026-08-16",
"expires": "2026-09-15",
"blocked_claim": "Apple MLX runtime support, compatibility, and performance are not claimed while this waiver is active."
},
{
"gate": "remote-execution",
"reason": "No least-privileged remote test target or required repository credentials are configured.",
"issue": "https://github.com/elder-plinius/OBLITERATUS/issues/110",
"opened": "2026-08-16",
"expires": "2026-09-15",
"blocked_claim": "Remote execution support, compatibility, and performance are not claimed while this waiver is active."
}
],
"gates": [
{
"id": "model-download-runtime",
+12 -1
View File
@@ -12,6 +12,13 @@ days, and treats evidence older than eight days as stale. Every workflow run pub
a summary showing selected, successful, failed, and not-selected/no-fresh-evidence
gates.
Unavailable hardware or credential-bound gates may use a committed environment
waiver for at most 30 days. Each waiver names one gate, a canonical tracking issue,
the reason, its opening and expiry dates, and the support claim it blocks. Invalid,
duplicate, future-dated, overlong, or expired waivers fail the policy job. The current
waivers are tracked by [issue #110](https://github.com/elder-plinius/OBLITERATUS/issues/110)
and expire on 2026-09-15; they are not evidence that any waived backend works.
## Hosted gates
The model gate downloads only
@@ -99,4 +106,8 @@ hosted runner-minutes plus any provider charge.
failure, error, or skip. A selected workflow job therefore cannot become green through
an availability skip or unconditional success conversion. The final summary also
fails if any selected job is not successful. Unselected jobs are explicitly reported
as `not_selected_no_fresh_evidence`; they are not evidence of backend support.
as `not_selected_no_fresh_evidence`; they are not evidence of backend support. An
unselected hardware or credential-bound gate with a valid waiver is reported as
`waived_no_support_claim`, including its tracker, expiry, and blocked claim. Selecting
and successfully running that gate produces `success` instead of relying on the
waiver.
+99 -1
View File
@@ -13,6 +13,9 @@ from pathlib import Path
REQUIRED_GATE_FIELDS = {
"id", "job", "marker", "runner", "prerequisites", "expected_cost", "coverage_paths"
}
REQUIRED_WAIVER_FIELDS = {
"gate", "reason", "issue", "opened", "expires", "blocked_claim"
}
SOFTWARE_ONLY_GATES = (
"model-download-runtime",
"external-evaluation",
@@ -24,9 +27,99 @@ ISSUE_URL = re.compile(
r"^https://github\.com/elder-plinius/OBLITERATUS/issues/[1-9][0-9]*$",
)
MAX_STALE_EXCEPTION_DAYS = 30
MAX_ENVIRONMENT_WAIVER_DAYS = 30
def validate(policy_path: Path, quality_path: Path, workflow_path: Path) -> list[str]:
def validate_environment_waivers(
policy: dict,
*,
today: date | None = None,
) -> tuple[dict[str, dict], list[str]]:
"""Return active gate waivers and structural/lifetime errors."""
errors: list[str] = []
active: dict[str, dict] = {}
today = today or date.today()
gates = policy.get("gates", [])
gate_ids = {
gate.get("id")
for gate in gates
if isinstance(gate, dict) and isinstance(gate.get("id"), str)
}
waivers = policy.get("environment_waivers", [])
if not isinstance(waivers, list):
return {}, ["conditional policy environment_waivers must be a list"]
seen: set[str] = set()
for index, waiver in enumerate(waivers):
label = f"environment waiver {index}"
if not isinstance(waiver, dict):
errors.append(f"{label} must be an object")
continue
missing = REQUIRED_WAIVER_FIELDS - set(waiver)
if missing:
errors.append(f"{label} is missing fields: {sorted(missing)}")
continue
gate_id = waiver["gate"]
if not isinstance(gate_id, str) or not gate_id:
errors.append(f"{label} gate must be a non-empty string")
continue
if gate_id in seen:
errors.append(f"duplicate environment waiver gate: {gate_id}")
continue
seen.add(gate_id)
valid = True
if gate_id not in gate_ids:
errors.append(f"environment waiver references unknown gate: {gate_id}")
valid = False
if gate_id in SOFTWARE_ONLY_GATES:
errors.append(f"software-only gate may not use an environment waiver: {gate_id}")
valid = False
for field in ("reason", "blocked_claim"):
value = waiver[field]
if not isinstance(value, str) or not value.strip():
errors.append(f"environment waiver {gate_id} {field} must be non-empty")
valid = False
issue = waiver["issue"]
if not isinstance(issue, str) or ISSUE_URL.fullmatch(issue) is None:
errors.append(f"environment waiver {gate_id} issue must be a canonical issue URL")
valid = False
try:
opened = date.fromisoformat(waiver["opened"])
expires = date.fromisoformat(waiver["expires"])
except (TypeError, ValueError):
errors.append(f"environment waiver {gate_id} opened/expires must be ISO dates")
continue
if opened > today:
errors.append(f"environment waiver {gate_id} opens in the future: {opened}")
valid = False
if expires < opened:
errors.append(f"environment waiver {gate_id} expires before it opens")
valid = False
elif expires > opened + timedelta(days=MAX_ENVIRONMENT_WAIVER_DAYS):
errors.append(
f"environment waiver {gate_id} exceeds {MAX_ENVIRONMENT_WAIVER_DAYS} days",
)
valid = False
if expires < today:
errors.append(f"environment waiver {gate_id} expired on {expires}")
valid = False
if valid:
active[gate_id] = waiver
return active, errors
def validate(
policy_path: Path,
quality_path: Path,
workflow_path: Path,
*,
today: date | None = None,
) -> list[str]:
errors: list[str] = []
policy = json.loads(policy_path.read_text())
quality = json.loads(quality_path.read_text())
@@ -44,6 +137,9 @@ def validate(policy_path: Path, quality_path: Path, workflow_path: Path) -> list
by_id: dict[str, dict] = {}
for index, gate in enumerate(gates):
if not isinstance(gate, dict):
errors.append(f"gate {index} must be an object")
continue
missing = REQUIRED_GATE_FIELDS - set(gate)
if missing:
errors.append(f"gate {index} is missing fields: {sorted(missing)}")
@@ -77,6 +173,8 @@ def validate(policy_path: Path, quality_path: Path, workflow_path: Path) -> list
for token in required_workflow_tokens:
if token not in workflow:
errors.append(f"conditional workflow is missing {token!r}")
_, waiver_errors = validate_environment_waivers(policy, today=today)
errors.extend(waiver_errors)
return errors
+47 -7
View File
@@ -6,24 +6,49 @@ from __future__ import annotations
import argparse
import json
import os
from datetime import datetime, timezone
from datetime import date, datetime, timezone
from pathlib import Path
try:
from scripts.check_conditional_policy import validate_environment_waivers
except ModuleNotFoundError: # Direct execution adds scripts/, not the repository root.
from check_conditional_policy import validate_environment_waivers
def summarize(policy: dict, results: dict, selected: dict) -> tuple[list[dict], list[str]]:
def summarize(
policy: dict,
results: dict,
selected: dict,
*,
today: date | None = None,
) -> tuple[list[dict], list[str]]:
"""Return per-gate rows and selected-job failures."""
failures: list[str] = []
waivers, waiver_errors = validate_environment_waivers(policy, today=today)
failures = [f"waiver policy: {error}" for error in waiver_errors]
rows: list[dict] = []
failed_jobs: set[str] = set()
for gate in policy["gates"]:
job = gate["job"]
is_selected = bool(selected.get(job, False))
result = results.get(job, "unknown")
status = result if is_selected else "not_selected_no_fresh_evidence"
waiver = waivers.get(gate["id"])
if is_selected:
status = result
elif waiver is not None:
status = "waived_no_support_claim"
else:
status = "not_selected_no_fresh_evidence"
if is_selected and result != "success" and job not in failed_jobs:
failures.append(f"{job}: selected but result was {result}")
failed_jobs.add(job)
rows.append({"gate": gate["id"], "job": job, "selected": is_selected, "status": status})
row = {"gate": gate["id"], "job": job, "selected": is_selected, "status": status}
if not is_selected and waiver is not None:
row["waiver"] = {
"issue": waiver["issue"],
"expires": waiver["expires"],
"blocked_claim": waiver["blocked_claim"],
}
rows.append(row)
return rows, failures
@@ -50,8 +75,23 @@ def main() -> int:
args.output.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n")
summary_path = os.environ.get("GITHUB_STEP_SUMMARY")
if summary_path:
lines = ["## Conditional test evidence", "", "| Gate | Job | Status |", "|---|---|---|"]
lines.extend(f"| {row['gate']} | {row['job']} | {row['status']} |" for row in rows)
lines = [
"## Conditional test evidence",
"",
"| Gate | Job | Status | Constraint |",
"|---|---|---|---|",
]
for row in rows:
waiver = row.get("waiver")
constraint = ""
if waiver is not None:
constraint = (
f"No support claim; expires {waiver['expires']}; "
f"[tracker]({waiver['issue']})"
)
lines.append(
f"| {row['gate']} | {row['job']} | {row['status']} | {constraint} |",
)
lines.extend(["", f"Evidence becomes stale after {policy['maximum_evidence_age_days']} days."])
with Path(summary_path).open("a") as handle:
handle.write("\n".join(lines) + "\n")
+152
View File
@@ -3,6 +3,7 @@
from __future__ import annotations
import json
from datetime import date
from pathlib import Path
from scripts import check_conditional_policy
@@ -11,6 +12,20 @@ from scripts import run_conditional_gate
ROOT = Path(__file__).parents[1]
TODAY = date(2026, 8, 16)
def _waiver(gate: str, **overrides) -> dict:
value = {
"gate": gate,
"reason": "No runner is currently attached.",
"issue": "https://github.com/elder-plinius/OBLITERATUS/issues/110",
"opened": "2026-08-16",
"expires": "2026-09-15",
"blocked_claim": f"{gate} support is not claimed.",
}
value.update(overrides)
return value
def test_committed_conditional_policy_is_complete():
@@ -18,6 +33,7 @@ def test_committed_conditional_policy_is_complete():
ROOT / "ci" / "conditional-test-policy.json",
ROOT / "ci" / "test-quality-policy.json",
ROOT / ".github" / "workflows" / "conditional-tests.yml",
today=TODAY,
) == []
@@ -92,3 +108,139 @@ def test_summary_rejects_selected_failure_and_marks_unselected_stale():
assert rows[0]["status"] == "failure"
assert rows[1]["status"] == "failure"
assert rows[2]["status"] == "not_selected_no_fresh_evidence"
def test_summary_records_active_waiver_and_selected_success_overrides_it():
policy = {
"gates": [{"id": "cuda-runtime", "job": "cuda"}],
"environment_waivers": [_waiver("cuda-runtime")],
}
rows, failures = conditional_gate_summary.summarize(
policy,
{"cuda": "skipped"},
{"cuda": False},
today=TODAY,
)
assert failures == []
assert rows == [{
"gate": "cuda-runtime",
"job": "cuda",
"selected": False,
"status": "waived_no_support_claim",
"waiver": {
"issue": "https://github.com/elder-plinius/OBLITERATUS/issues/110",
"expires": "2026-09-15",
"blocked_claim": "cuda-runtime support is not claimed.",
},
}]
rows, failures = conditional_gate_summary.summarize(
policy,
{"cuda": "success"},
{"cuda": True},
today=TODAY,
)
assert failures == []
assert rows[0]["status"] == "success"
assert "waiver" not in rows[0]
def test_environment_waiver_validation_rejects_duplicate_expired_and_overlong_records():
policy = {
"gates": [
{"id": "cuda-runtime"},
{"id": "mps-runtime"},
{"id": "mlx-runtime"},
],
"environment_waivers": [
_waiver("cuda-runtime"),
_waiver("cuda-runtime"),
_waiver("mps-runtime", opened="2026-07-01", expires="2026-07-31"),
_waiver("mlx-runtime", expires="2026-09-16"),
],
}
active, errors = check_conditional_policy.validate_environment_waivers(
policy,
today=TODAY,
)
assert active == {"cuda-runtime": policy["environment_waivers"][0]}
assert "duplicate environment waiver gate: cuda-runtime" in errors
assert "environment waiver mps-runtime expired on 2026-07-31" in errors
assert "environment waiver mlx-runtime exceeds 30 days" in errors
def test_environment_waiver_validation_rejects_malformed_or_software_records():
policy = {
"gates": [
{"id": "network-services"},
{"id": "remote-execution"},
],
"environment_waivers": [
_waiver("network-services"),
_waiver("remote-execution", issue="not-an-issue", blocked_claim=""),
"not-an-object",
],
}
active, errors = check_conditional_policy.validate_environment_waivers(
policy,
today=TODAY,
)
assert active == {}
assert "software-only gate may not use an environment waiver: network-services" in errors
assert "environment waiver remote-execution issue must be a canonical issue URL" in errors
assert "environment waiver remote-execution blocked_claim must be non-empty" in errors
assert "environment waiver 2 must be an object" in errors
def test_environment_waiver_validation_rejects_missing_future_and_reversed_dates():
missing = _waiver("remote-execution")
missing.pop("reason")
policy = {
"gates": [
{"id": "remote-execution"},
{"id": "mps-runtime"},
{"id": "mlx-runtime"},
],
"environment_waivers": [
missing,
_waiver("mps-runtime", opened="2026-08-17", expires="2026-09-15"),
_waiver("mlx-runtime", opened="2026-08-16", expires="2026-08-15"),
],
}
active, errors = check_conditional_policy.validate_environment_waivers(
policy,
today=TODAY,
)
assert active == {}
assert "environment waiver 0 is missing fields: ['reason']" in errors
assert "environment waiver mps-runtime opens in the future: 2026-08-17" in errors
assert "environment waiver mlx-runtime expires before it opens" in errors
assert "environment waiver mlx-runtime expired on 2026-08-15" in errors
def test_summary_fails_an_expired_waiver():
policy = {
"gates": [{"id": "cuda-runtime", "job": "cuda"}],
"environment_waivers": [
_waiver("cuda-runtime", opened="2026-07-01", expires="2026-07-31"),
],
}
rows, failures = conditional_gate_summary.summarize(
policy,
{"cuda": "skipped"},
{"cuda": False},
today=TODAY,
)
assert rows[0]["status"] == "not_selected_no_fresh_evidence"
assert failures == [
"waiver policy: environment waiver cuda-runtime expired on 2026-07-31",
]