diff --git a/Programme/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/kit_adaptatif/svg/parcours_fraction_support.svg b/Programme/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/kit_adaptatif/svg/parcours_fraction_support.svg index 9295ec4..1df1b71 100644 --- a/Programme/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/kit_adaptatif/svg/parcours_fraction_support.svg +++ b/Programme/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/kit_adaptatif/svg/parcours_fraction_support.svg @@ -29,7 +29,7 @@ 0 1 - 3 - - 4 + 3 + + 4 diff --git a/backend/app/__pycache__/curriculum.cpython-313.pyc b/backend/app/__pycache__/curriculum.cpython-313.pyc index 773605b..18c5975 100644 Binary files a/backend/app/__pycache__/curriculum.cpython-313.pyc and b/backend/app/__pycache__/curriculum.cpython-313.pyc differ diff --git a/backend/app/__pycache__/database.cpython-313.pyc b/backend/app/__pycache__/database.cpython-313.pyc index 72d85ae..2ec09f5 100644 Binary files a/backend/app/__pycache__/database.cpython-313.pyc and b/backend/app/__pycache__/database.cpython-313.pyc differ diff --git a/backend/app/__pycache__/main.cpython-313.pyc b/backend/app/__pycache__/main.cpython-313.pyc index 969dd21..74f471c 100644 Binary files a/backend/app/__pycache__/main.cpython-313.pyc and b/backend/app/__pycache__/main.cpython-313.pyc differ diff --git a/backend/app/__pycache__/models.cpython-313.pyc b/backend/app/__pycache__/models.cpython-313.pyc index 66e37e4..6d7a174 100644 Binary files a/backend/app/__pycache__/models.cpython-313.pyc and b/backend/app/__pycache__/models.cpython-313.pyc differ diff --git a/backend/app/__pycache__/schemas.cpython-313.pyc b/backend/app/__pycache__/schemas.cpython-313.pyc index 5a728ad..0c429fc 100644 Binary files a/backend/app/__pycache__/schemas.cpython-313.pyc and b/backend/app/__pycache__/schemas.cpython-313.pyc differ diff --git a/backend/app/__pycache__/services.cpython-313.pyc b/backend/app/__pycache__/services.cpython-313.pyc index 175f5fb..7e10901 100644 Binary files a/backend/app/__pycache__/services.cpython-313.pyc and b/backend/app/__pycache__/services.cpython-313.pyc differ diff --git a/backend/app/main.py b/backend/app/main.py index 6797270..b35b9f2 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -19,6 +19,7 @@ from .auth import ( ) from .curriculum import QUESTIONS from .program_content import ( + apply_program_review_updates, build_program_tree, decode_asset_token, format_adaptive_kit_context, @@ -52,6 +53,7 @@ async def lifespan(app: FastAPI): seed_admin_user(db) finally: db.close() + apply_program_review_updates() yield diff --git a/backend/app/program_content.py b/backend/app/program_content.py index ccb01e0..b7fa893 100644 --- a/backend/app/program_content.py +++ b/backend/app/program_content.py @@ -29,6 +29,7 @@ def default_content_root() -> Path: CONTENT_ROOT = Path(os.getenv("PROGRAM_CONTENT_ROOT", default_content_root())).resolve() LESSON_BACKGROUND = "#f8fafc" REVIEW_STATE_PATH = Path(os.getenv("PROGRAM_REVIEW_STATE_PATH", CONTENT_ROOT / ".program_review_state.json")) +REVIEW_UPDATES_PATH = Path(os.getenv("PROGRAM_REVIEW_UPDATES_PATH", CONTENT_ROOT / "review_updates")) GRADE_ALIASES = { "CM1": "cm1", @@ -298,6 +299,71 @@ def save_review_state(state: dict) -> None: ) +def iter_review_update_files() -> list[Path]: + candidates = [] + single_file = CONTENT_ROOT / ".program_review_updates.json" + if single_file.exists(): + candidates.append(single_file) + if REVIEW_UPDATES_PATH.exists(): + candidates.extend(sorted(REVIEW_UPDATES_PATH.glob("*.json"))) + return candidates + + +def apply_program_review_updates() -> dict: + state = load_review_state() + applied = 0 + skipped = 0 + errors = [] + + for path in iter_review_update_files(): + try: + payload = json.loads(path.read_text(encoding="utf-8")) + except json.JSONDecodeError as exc: + errors.append({"file": str(path), "error": f"JSON invalide: {exc}"}) + continue + + if payload.get("schema") != "professeur-top-review-updates-v1": + skipped += 1 + continue + + payload_updated_at = payload.get("updated_at") or datetime.utcnow().isoformat(timespec="seconds") + "Z" + payload_reviewer = payload.get("updated_by") or "codex" + for index, update in enumerate(payload.get("updates") or []): + node_key = update.get("node_key") or update.get("path") + if not node_key: + skipped += 1 + continue + + update_id = update.get("update_id") or f"{path.name}:{index}:{node_key}" + existing = state.get(node_key, {}) + if existing.get("codex_update_id") == update_id: + skipped += 1 + continue + + next_review = { + **existing, + "status": update.get("status") or existing.get("status") or "treated", + "comment": update.get("comment", existing.get("comment", "")), + "reviewer": update.get("reviewer") or payload_reviewer, + "updated_at": update.get("updated_at") or payload_updated_at, + "codex_update_id": update_id, + } + if update.get("treated_note"): + next_review["treated_note"] = update["treated_note"] + state[node_key] = next_review + applied += 1 + + if applied: + save_review_state(state) + + return { + "applied": applied, + "skipped": skipped, + "errors": errors, + "files": [str(path) for path in iter_review_update_files()], + } + + def collect_lesson_status(lesson: dict) -> dict: lesson_dir = CONTENT_ROOT / lesson["id"] kit_dir = lesson_dir / "kit_adaptatif" diff --git a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/kit_adaptatif/svg/parcours_fraction_support.svg b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/kit_adaptatif/svg/parcours_fraction_support.svg index 9295ec4..1df1b71 100644 --- a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/kit_adaptatif/svg/parcours_fraction_support.svg +++ b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/kit_adaptatif/svg/parcours_fraction_support.svg @@ -29,7 +29,7 @@ 0 1 - 3 - - 4 + 3 + + 4 diff --git a/backend/contenus_pedagogiques/review_updates/codex-2026-05-07-fractions-kit.json b/backend/contenus_pedagogiques/review_updates/codex-2026-05-07-fractions-kit.json new file mode 100644 index 0000000..142b825 --- /dev/null +++ b/backend/contenus_pedagogiques/review_updates/codex-2026-05-07-fractions-kit.json @@ -0,0 +1,16 @@ +{ + "schema": "professeur-top-review-updates-v1", + "updated_by": "codex", + "updated_at": "2026-05-07T19:55:00Z", + "updates": [ + { + "update_id": "codex-2026-05-07-fractions-kit-parcours-fraction-support", + "node_key": "cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/kit_adaptatif/svg/parcours_fraction_support.svg", + "status": "treated", + "comment": "Aucune fraction ne doit etre representee avec un trait oblique, il faut un trait horizontal avec les enfants de cet age", + "reviewer": "codex", + "updated_at": "2026-05-07T19:55:00Z", + "treated_note": "Fractions visibles remplacees par une disposition numerateur, barre horizontale, denominateur. Etiquette de la demi-droite remontee au-dessus du point vert." + } + ] +}