"""Deterministic research-readiness checks for the NEURAL LAB dashboard.""" from __future__ import annotations from html import escape TRACK_REQUIREMENTS: dict[str, tuple[str, ...]] = { "Language model experiment": ( "Pinned configuration", "Dataset provenance", "Tokenizer revision", "Seed and environment", "Evaluation protocol", "Limitations and release gate", ), "Dataset release": ( "Source manifest", "Licence and permissions", "Privacy and consent review", "Quality report", "Versioned preprocessing", "Evaluation and limitations", ), "Agent system experiment": ( "Task and verifier revision", "Tool permission policy", "Sandbox boundary", "Trace schema", "Failure-injection plan", "Human approval gates", ), } def requirement_choices(track: str) -> list[str]: return list(TRACK_REQUIREMENTS.get(track, TRACK_REQUIREMENTS["Language model experiment"])) def assess_readiness(track: str, completed: list[str] | None) -> dict[str, object]: if track not in TRACK_REQUIREMENTS: raise ValueError("unknown research track") completed_set = set(completed or []) requirements = TRACK_REQUIREMENTS[track] unknown = sorted(completed_set - set(requirements)) if unknown: raise ValueError("completed requirements contain unknown values") missing = [item for item in requirements if item not in completed_set] score = round(100 * (len(requirements) - len(missing)) / len(requirements)) return { "track": track, "score": score, "completed_count": len(requirements) - len(missing), "requirement_count": len(requirements), "missing": missing, "ready": not missing, "scope_note": "Deterministic documentation gate; not evidence that an experiment is safe, valid, or publishable.", } def render_assessment(track: str, completed: list[str] | None) -> str: result = assess_readiness(track, completed) missing = result["missing"] status = "READY FOR CONTROLLED REVIEW" if result["ready"] else "EVIDENCE INCOMPLETE" if missing: missing_text = "\n".join(f"- {escape(item)}" for item in missing) else: missing_text = "- No checklist items are missing. Independent review is still required." return ( f"### {status}\n\n" f"**Track:** {escape(track)} \n" f"**Checklist coverage:** {result['completed_count']}/{result['requirement_count']} " f"({result['score']}%)\n\n" f"**Missing evidence**\n\n{missing_text}\n\n" f"> {result['scope_note']}" )