Spaces:
Runtime error
Runtime error
File size: 7,671 Bytes
dbf5e96 b2b578f dbf5e96 74c9d03 dbf5e96 74c9d03 dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f 74c9d03 dbf5e96 74c9d03 dbf5e96 b2b578f 3ea78ad dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 74c9d03 b2b578f dbf5e96 b2b578f 3ea78ad dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 74c9d03 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 74c9d03 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 74c9d03 b2b578f 74c9d03 dbf5e96 74c9d03 dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 b2b578f 74c9d03 dbf5e96 74c9d03 b2b578f 74c9d03 b2b578f 74c9d03 b2b578f 74c9d03 dbf5e96 74c9d03 b2b578f dbf5e96 74c9d03 dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 74c9d03 b2b578f dbf5e96 74c9d03 dbf5e96 b2b578f dbf5e96 b2b578f dbf5e96 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | #!/usr/bin/env python3
"""
OpenEnv Spec Compliance Validator for CodeReviewEnv v2 (MCP pattern)
"""
import sys
import os
import random
import yaml
from server.code_review_environment import CodeReviewEnvironment
from models import CodeReviewAction, CodeReviewObservation, CodeReviewState
from snippet_bank import SNIPPET_BANK, BUG_INJECTORS, generate_episode
def check(name: str, condition: bool, reason: str = "") -> bool:
status = "PASS" if condition else "FAIL"
msg = f" [{status}] {name}"
if not condition and reason:
msg += f" -- {reason}"
print(msg)
return condition
def _tool(tool_name, arguments=None):
return CodeReviewAction(action_type="ToolCallAction", tool_name=tool_name, arguments=arguments or {})
def validate():
print("=" * 60)
print("CodeReviewEnv -- OpenEnv Compliance Validation (MCP pattern)")
print("=" * 60)
results = []
# 1. reset() returns observation with tools_list
print("\n--- Core Interface (MCP) ---")
for difficulty in ["easy", "medium", "hard"]:
try:
env = CodeReviewEnvironment()
obs = env.reset(seed=42, difficulty=difficulty)
results.append(check(
f"reset() returns tools_list ({difficulty})",
isinstance(obs, CodeReviewObservation) and obs.tools_list is not None and len(obs.tools_list) == 8,
))
except Exception as e:
results.append(check(f"reset() ({difficulty})", False, str(e)))
# 2. ListToolsAction works
try:
env = CodeReviewEnvironment()
env.reset(seed=42)
obs = env.step(CodeReviewAction(action_type="ListToolsAction"))
tool_names = {t["name"] for t in obs.tools_list}
results.append(check(
"ListToolsAction returns 5 tools",
tool_names == {"get_code", "run_code", "run_tests", "analyze_code", "check_line", "get_hint", "submit_fix", "submit_review"},
))
except Exception as e:
results.append(check("ListToolsAction", False, str(e)))
# 3. get_code returns code
try:
env = CodeReviewEnvironment()
env.reset(seed=42)
obs = env.step(_tool("get_code"))
results.append(check(
"get_code returns code",
obs.success and obs.tool_result and len(obs.tool_result.get("code", "")) > 0,
))
except Exception as e:
results.append(check("get_code", False, str(e)))
# 4. check_line returns reward
try:
env = CodeReviewEnvironment()
env.reset(seed=42)
state = env.state
if state.gold_bugs:
line = state.gold_bugs[0]["lines"][0]
obs = env.step(_tool("check_line", {"line": line}))
results.append(check(
f"check_line({line}) gives positive reward",
obs.success and obs.reward > 0,
))
else:
results.append(check("check_line (no bugs to test)", True))
except Exception as e:
results.append(check("check_line", False, str(e)))
# 5. submit_review ends episode
try:
env = CodeReviewEnvironment()
env.reset(seed=42)
obs = env.step(_tool("submit_review", {"issues": ["test"], "comment": "review"}))
results.append(check(
"submit_review ends episode (done=True)",
obs.done is True and obs.reward is not None and 0.0 <= obs.reward <= 1.0,
))
except Exception as e:
results.append(check("submit_review", False, str(e)))
# 6. state contains gold_bugs
try:
env = CodeReviewEnvironment()
env.reset(seed=42)
state = env.state
results.append(check(
"state contains gold_bugs",
isinstance(state, CodeReviewState) and isinstance(state.gold_bugs, list),
))
except Exception as e:
results.append(check("state", False, str(e)))
# 7. Reward in [0,1] across many seeds
try:
all_valid = True
for seed in range(50):
env = CodeReviewEnvironment()
env.reset(seed=seed, difficulty=random.choice(["easy", "medium", "hard"]))
obs = env.step(_tool("submit_review", {"issues": ["bug"], "comment": "test"}))
if obs.reward < 0.0 or obs.reward > 1.0:
all_valid = False
break
results.append(check("reward always in [0, 1]", all_valid))
except Exception as e:
results.append(check("reward bounds", False, str(e)))
# 8. Max steps forces submit
try:
env = CodeReviewEnvironment()
env.reset(seed=42)
for i in range(10):
obs = env.step(_tool("analyze_code"))
if obs.done:
break
results.append(check("max_steps forces submit", obs.done is True))
except Exception as e:
results.append(check("max_steps", False, str(e)))
# ββ Procedural Generation ββ
print("\n--- Procedural Generation ---")
try:
codes = {generate_episode(seed=s, difficulty="easy")[1][:100] for s in range(10)}
results.append(check(f"Different seeds -> different episodes ({len(codes)}/10)", len(codes) >= 3))
except Exception as e:
results.append(check("different seeds", False, str(e)))
try:
_, c1, _ = generate_episode(seed=42)
_, c2, _ = generate_episode(seed=42)
results.append(check("seed=42 reproducibility", c1 == c2))
except Exception as e:
results.append(check("reproducibility", False, str(e)))
results.append(check(f"Snippet bank has {len(SNIPPET_BANK)} entries (>= 30)", len(SNIPPET_BANK) >= 30))
results.append(check(f"Bug injectors: {len(BUG_INJECTORS)} (>= 9)", len(BUG_INJECTORS) >= 9))
# ββ Reward Quality ββ
print("\n--- Reward Quality ---")
try:
env = CodeReviewEnvironment()
env.reset(seed=42)
state = env.state
if state.gold_bugs:
g = state.gold_bugs[0]
obs = env.step(_tool("submit_review", {
"issues": [g["description"]],
"flagged_lines": g["lines"],
"suggestion": g["fix"],
"comment": f"Found {g['bug_type']}. {g['fix']}",
}))
results.append(check(f"Perfect agent >= 0.5 (got {obs.reward:.3f})", obs.reward >= 0.5))
else:
results.append(check("Perfect agent (no bugs)", True))
except Exception as e:
results.append(check("perfect agent", False, str(e)))
try:
env = CodeReviewEnvironment()
env.reset(seed=42)
obs = env.step(_tool("submit_review", {}))
results.append(check(f"Empty agent < 0.15 (got {obs.reward:.3f})", obs.reward < 0.15))
except Exception as e:
results.append(check("empty agent", False, str(e)))
# ββ Packaging ββ
print("\n--- Packaging ---")
try:
with open("openenv.yaml") as f:
config = yaml.safe_load(f)
required = ["spec_version", "name", "type", "runtime", "app", "port"]
results.append(check("openenv.yaml has required fields", all(k in config for k in required)))
except Exception as e:
results.append(check("openenv.yaml", False, str(e)))
results.append(check("Dockerfile exists", os.path.exists("Dockerfile")))
# ββ Summary ββ
print(f"\n{'=' * 60}")
passed = sum(results)
total = len(results)
print(f"Results: {passed}/{total} checks passed")
print("ALL CHECKS PASSED" if passed == total else f"{total - passed} checks FAILED")
return 0 if passed == total else 1
if __name__ == "__main__":
sys.exit(validate())
|