Skip to content

Commit 3a51ff3

Browse files
committed
Add TWM runtime benchmark gate
1 parent 2e74568 commit 3a51ff3

11 files changed

Lines changed: 1211 additions & 0 deletions

data_agent/benchmarks/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Benchmark runners for development-time validation."""
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""TWM Runtime Benchmark v1."""
2+
3+
from .runner import run_twm_runtime_benchmark
4+
5+
__all__ = ["run_twm_runtime_benchmark"]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"schema": "territory_world_model.twm_runtime_benchmark_manifest.v1",
3+
"suite_id": "twm_runtime_v1",
4+
"created_at": "2026-07-03",
5+
"state_dataset_dir": "data_agent/test_data/twm_bishan_multi_admin_eval",
6+
"synthetic_experiment_foundation": "docs/reports/twm_synthetic_experiment_foundation.csv",
7+
"structural_validation_history": "docs/reports/twm_structural_validation_observed_history.csv",
8+
"same_case_baselines": [
9+
"data_agent/test_data/twm_baseline_metrics/twm_candidate_triage_same_case_outputs.csv",
10+
"data_agent/test_data/twm_baseline_metrics/optimization_only_candidate_triage_same_case_outputs.csv"
11+
],
12+
"claim_boundary": {
13+
"benchmark_scope": "development_runtime_contract",
14+
"production_accuracy": "not_supported",
15+
"production_decision": "blocked_without_real_observed_history",
16+
"flus_superiority": "not_evaluated_by_this_benchmark"
17+
}
18+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"schema": "territory_world_model.twm_runtime_negative_controls.v1",
3+
"controls": [
4+
{
5+
"control_id": "impossible_action",
6+
"description": "Hard-blocked land-use conversion or approval must be blocked.",
7+
"required_signal": "block"
8+
},
9+
{
10+
"control_id": "support_material_missing_action",
11+
"description": "Low support-material coverage must remain review-only.",
12+
"required_signal": "review"
13+
},
14+
{
15+
"control_id": "policy_conflict_action",
16+
"description": "Action mask policy conflict must be recalled as blocked.",
17+
"required_signal": "block"
18+
},
19+
{
20+
"control_id": "shuffled_action_control",
21+
"description": "Performance must drop when action type is shuffled.",
22+
"required_signal": "performance_drop"
23+
},
24+
{
25+
"control_id": "shuffled_label_control",
26+
"description": "The gate must fail when utility and risk labels are shuffled.",
27+
"required_signal": "fail"
28+
}
29+
]
30+
}

data_agent/benchmarks/twm_runtime_v1/runner.py

Lines changed: 538 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"dataset_integrity_gate": {
3+
"relation_rows_min": 1700,
4+
"evidence_rows_min": 200,
5+
"synthetic_experiment_rows": 256,
6+
"counterfactual_pairs": 128,
7+
"train_rows": 128,
8+
"validation_rows": 64,
9+
"test_rows": 64,
10+
"action_type_count": 4,
11+
"allowed_rows": 128,
12+
"blocked_rows": 128
13+
},
14+
"renderer_gate": {
15+
"object_count_min": 21000,
16+
"relation_count_min": 1700,
17+
"project_count_min": 90,
18+
"rule_evaluation_count_min": 360,
19+
"review_task_count_min": 100,
20+
"support_material_count_min": 200
21+
},
22+
"simulator_gate": {
23+
"transition_mae_max": 0.05,
24+
"constraint_risk_mae_max": 0.05,
25+
"planning_utility_mae_max": 0.05,
26+
"ranking_correlation_proxy_min": 0.6,
27+
"action_mask_accuracy_min": 0.85,
28+
"blocked_action_recall_min": 0.85
29+
},
30+
"planner_gate": {
31+
"legal_feasible_topk_precision_min": 0.8,
32+
"candidate_rejection_reason_coverage_min": 0.85,
33+
"planner_regret_against_human_oracle_max": 0.15
34+
},
35+
"negative_control_gate": {
36+
"impossible_action_block_rate_min": 0.95,
37+
"support_missing_review_rate_min": 0.95,
38+
"policy_conflict_block_recall_min": 0.9,
39+
"shuffled_action_performance_drop_min": 0.15
40+
}
41+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from __future__ import annotations
2+
3+
import subprocess
4+
import sys
5+
from pathlib import Path
6+
7+
8+
REPO_ROOT = Path(__file__).resolve().parents[1]
9+
10+
11+
def test_twm_runtime_benchmark_blocks_current_facade_without_simulator_trace(tmp_path):
12+
from data_agent.benchmarks.twm_runtime_v1.runner import run_twm_runtime_benchmark
13+
14+
output = tmp_path / "twm_runtime_benchmark_v1.json"
15+
markdown_output = tmp_path / "twm_runtime_benchmark_v1.md"
16+
17+
report = run_twm_runtime_benchmark(
18+
output_path=output,
19+
markdown_output_path=markdown_output,
20+
fail_on_failed=False,
21+
)
22+
23+
assert report["schema"] == "territory_world_model.twm_runtime_benchmark.v1"
24+
assert report["suite_id"] == "twm_runtime_v1"
25+
assert report["status"] == "fail"
26+
assert "simulator_gate" in report["failed_gates"]
27+
assert "planner_gate" in report["failed_gates"]
28+
29+
simulator_gate = report["gates"]["simulator_gate"]
30+
assert simulator_gate["status"] == "fail"
31+
assert "simulator_trace" in simulator_gate["missing"]
32+
assert simulator_gate["checks"]["facade_backend_forbidden"]["status"] == "fail"
33+
assert simulator_gate["checks"]["facade_backend_forbidden"]["observed"] == "deterministic_planner_facade"
34+
35+
planner_gate = report["gates"]["planner_gate"]
36+
assert planner_gate["status"] == "fail"
37+
assert "planner_consumes_simulator_trace" in planner_gate["missing"]
38+
39+
claim_boundary = report["claim_boundary"]
40+
assert claim_boundary["production_decision"] == "blocked_without_real_observed_history"
41+
assert claim_boundary["production_accuracy"] == "not_supported"
42+
assert claim_boundary["flus_superiority"] == "not_evaluated_by_this_benchmark"
43+
assert claim_boundary["not_for_production_boundary_preserved"] is True
44+
45+
assert output.exists()
46+
assert markdown_output.exists()
47+
48+
49+
def test_twm_runtime_benchmark_cli_writes_outputs_and_exits_nonzero_on_failed(tmp_path):
50+
output = tmp_path / "cli_report.json"
51+
markdown_output = tmp_path / "cli_report.md"
52+
53+
completed = subprocess.run(
54+
[
55+
sys.executable,
56+
str(REPO_ROOT / "scripts/run_twm_runtime_benchmark.py"),
57+
"--suite",
58+
"twm_runtime_v1",
59+
"--output",
60+
str(output),
61+
"--markdown-output",
62+
str(markdown_output),
63+
"--fail-on-failed",
64+
],
65+
cwd=REPO_ROOT,
66+
text=True,
67+
capture_output=True,
68+
check=False,
69+
)
70+
71+
assert completed.returncode == 1
72+
assert output.exists()
73+
assert markdown_output.exists()
74+
assert "status=fail" in completed.stdout
75+
76+
77+
def test_twm_runtime_benchmark_requires_explicit_leakage_guard_contract(tmp_path):
78+
from data_agent.benchmarks.twm_runtime_v1.runner import run_twm_runtime_benchmark
79+
80+
report = run_twm_runtime_benchmark(
81+
output_path=tmp_path / "report.json",
82+
markdown_output_path=tmp_path / "report.md",
83+
)
84+
85+
leakage_gate = report["gates"]["leakage_guard_gate"]
86+
assert leakage_gate["status"] == "fail"
87+
assert "feature_vector_contract" in leakage_gate["missing"]
88+
assert leakage_gate["checks"]["target_feature_columns_present_in_source"]["status"] == "review"
89+
assert "leakage_guard_gate" in report["failed_gates"]

0 commit comments

Comments
 (0)