File size: 2,706 Bytes
69458c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""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']}"
    )