#!/usr/bin/env python3 """Automated readiness checks for judge demo cases.""" from __future__ import annotations import json import os import sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from plane_mode_scholar.gradio_ui.layout import ( STATE, case_01_recall_restart, grade_quiz_intentionally_wrong, load_readiness_cases, start_study_session, ) from plane_mode_scholar.ingestion.pack_builder import PackBuilder from plane_mode_scholar.memory.scheduler import get_due_reviews, schedule_review from plane_mode_scholar.storage.sqlite_store import SQLiteStore from plane_mode_scholar.storage.trace_export import export_session_trace def load_cases() -> list[dict]: return load_readiness_cases() def check_srs_due() -> bool: store = SQLiteStore() pb = PackBuilder(store) demo = os.path.normpath("plane_mode_scholar/data/demo_notes.txt") if not os.path.exists(demo): print("SKIP srs: demo notes missing") return True result = pb.create_pack("RC", "ML", file_paths=[demo], user_id="rc_user") pack_id = result["pack"]["pack_id"] schedule_review(store, pack_id, "overfitting", "sess_rc", user_id="rc_user", interval_days=0.0) due = get_due_reviews(store, pack_id, "rc_user") ok = len(due) >= 1 print(f"{'PASS' if ok else 'FAIL'} case_03_srs: due_count={len(due)}") return ok def check_trace_shape() -> bool: store = SQLiteStore() trace = export_session_trace(store, "sess_missing", "pack_missing", "user") ok = "pipeline_steps" in trace and "memory_operations" in trace print(f"{'PASS' if ok else 'FAIL'} case_04_trace: keys present") return ok def check_case_01_recall_flow() -> bool: store = SQLiteStore() pb = PackBuilder(store) demo = os.path.normpath("plane_mode_scholar/data/demo_notes.txt") if not os.path.exists(demo): print("SKIP case_01: demo notes missing") return True result = pb.create_pack("C01", "ML", file_paths=[demo], user_id="c01_user") pack_id = result["pack"]["pack_id"] goals = "Review ML concepts" start_study_session(pack_id, goals, 45, "c01_user") sid1 = STATE.session_id STATE.quiz_data = [ { "question": "What is gradient descent?", "options": ["Optimization", "Overfitting", "Clustering", "Sampling"], "correct_index": 0, "concept": "gradient descent", "explanation": "Gradient descent optimizes loss.", } ] STATE.quiz_index = 0 grade_quiz_intentionally_wrong(pack_id, sid1, "c01_user") out = case_01_recall_restart( "case_01_recall", sid1, pack_id, "", [], goals, 45, "c01_user" ) recall_html = out[1] ok = "recall" in recall_html.lower() or "remember" in recall_html.lower() or "due" in recall_html.lower() print(f"{'PASS' if ok else 'FAIL'} case_01_recall: restart recall banner present") return ok def main() -> int: cases = load_cases() print(f"Loaded {len(cases)} readiness cases") results = [check_srs_due(), check_trace_shape(), check_case_01_recall_flow()] for case in cases: print(f" - {case['id']}: {case['title']}") if all(results): print("All automated checks passed.") return 0 print("Some checks failed.") return 1 if __name__ == "__main__": raise SystemExit(main())