Spaces:
Sleeping
Sleeping
| """SecureCodeEnv - Consistency Grader v4 — clamped scores""" | |
| from codegraph.graph import CodeGraph | |
| from codegraph.extractor import extract_metadata | |
| from graders.clamp import clamp | |
| GOOD_PRACTICES = { | |
| "uses_type_hints": 0.15, | |
| "uses_docstrings": 0.15, | |
| "uses_try_catch": 0.10, | |
| "no_print_stmts": 0.10, | |
| "no_hardcoded_secrets": 0.10, | |
| } | |
| def grade_consistency(code: str, filename: str, graph: CodeGraph, step: int) -> dict: | |
| new_meta = extract_metadata(code, filename, step) | |
| conv = new_meta.conventions | |
| if not graph.components: | |
| checks = {k: 1.0 if conv.get(k, False) else 0.0 for k in GOOD_PRACTICES} | |
| raw = sum(checks.values()) / max(len(checks), 1) | |
| raw = max(0.45, raw) # floor so first step never crushes reward | |
| return {"score": clamp(raw), "checks": checks, | |
| "feedback": _first_feedback(raw, checks)} | |
| established = graph.conventions | |
| checks = {} | |
| naming = established.get("naming") | |
| if naming and naming != "mixed" and new_meta.functions: | |
| fns = new_meta.functions | |
| if naming == "snake_case": | |
| correct = sum(1 for f in fns if "_" in f["name"] or f["name"].islower()) | |
| else: | |
| correct = sum(1 for f in fns if f["name"] and f["name"][0].islower() | |
| and any(c.isupper() for c in f["name"])) | |
| checks["naming_convention"] = correct / len(fns) | |
| if established.get("error_handling") == "try_catch": | |
| checks["error_handling"] = 1.0 if conv.get("uses_try_catch") else 0.3 | |
| if established.get("uses_type_hints"): | |
| checks["type_hints"] = 1.0 if conv.get("uses_type_hints") else 0.4 | |
| if established.get("uses_docstrings"): | |
| checks["docstrings"] = 1.0 if conv.get("uses_docstrings") else 0.5 | |
| existing_no_print = all(c.conventions.get("no_print_stmts", True) | |
| for c in graph.components.values()) | |
| if existing_no_print: | |
| checks["no_print_drift"] = 1.0 if conv.get("no_print_stmts", True) else 0.3 | |
| reuse_opp = reuse_taken = 0 | |
| for name in graph.components: | |
| if name.lower() in code.lower(): | |
| reuse_opp += 1 | |
| if name in code: | |
| reuse_taken += 1 | |
| if reuse_opp > 0: | |
| checks["component_reuse"] = reuse_taken / reuse_opp | |
| raw = sum(checks.values()) / max(len(checks), 1) if checks else 0.7 | |
| return {"score": clamp(raw), "checks": checks, | |
| "feedback": _feedback(raw, checks)} | |
| def _first_feedback(score, checks): | |
| missing = [k for k, v in checks.items() if v == 0.0] | |
| if not missing: | |
| return f"Good conventions established ({score:.2f})" | |
| return f"Missing practices: {', '.join(missing)}" | |
| def _feedback(score, checks): | |
| if score >= 0.85: return "Excellent consistency with codebase" | |
| failing = [k for k, v in checks.items() if isinstance(v, float) and v < 0.5] | |
| return f"Convention drift in: {', '.join(failing)}" if failing else f"Minor drift ({score:.2f})" | |