SYNOMAP – B4 EXECUTION MODEL v1 (DIGEST) ======================================= SCOPE ----- B4 exécute réellement les actions proposées par B3. Objectif : - modifier l'environnement (qBittorrent, filesystem, tags…) - de manière déterministe, sécurisée, idempotente, - en cycle : ACTION → RUN B1 → RUNNER B2 → correction B3 → ACTION… DEPENDANCES ----------- - B3 (ACTION_PLAN) - B2 (RUN_RECORD, CHANGESET) - B1 (OUTPUT_SET) - A1–A4 (modèle d’état) - A1.1 (identity preconditions) ENTITES ------- EXECUTOR : moteur qui valide et exécute les actions. ACTION_PLAN : liste ordonnée (types, raisons, safe flags). ACTION_EXECUTION_RECORD : journal structuré d’exécution : { action_id, torrent_id, type, params, result, timestamp } ENVIRONMENT_ADAPTERS : Surfaces contrôlées : - qb_adapter (API qBittorrent) - fs_adapter (FileSystem) - tag_adapter (qB tags) Chaque action B3 est mappée vers un appel précis sur ces adapters. INVARIANTS ---------- B4-I1 : Aucun effet non explicitement demandé par une action B3. B4-I2 : Idempotence stricte : exécuter la même action deux fois produit le même état. B4-I3 : Pas d’action si identity_invalid. B4-I4 : Pas d’action si le record courant contredit l’action. B4-I5 : Tous les effets sont suivis d'un nouveau cycle B1/B2. B4-I6 : Aucune action destructrice de données (delete/move) dans B4 v1. SEQUENCE B4 ----------- B4-0 : Entrée = ACTION_PLAN (B3) + OUTPUT_SET/B2 state. B4-1 : Pour chaque action : → VALIDATION → EXECUTION → LOGGING B4-2 : En fin de plan (ou après chaque action si mode strict) : → TRIGGER RUN B1 → TRIGGER RUNNER B2 B4-3 : Fin : publier EXECUTION_SUMMARY. VALIDATION (PRÉ-ACTION) ----------------------- V1 : Vérifier identity.* conforme (A1.1). V2 : Vérifier que le record courant correspond encore à la raison/action. V3 : Vérifier que l’action est encore cohérente avec CHANGESET : - Si l’état a changé depuis la production du plan → SKIP. V4 : Vérifier que safe=false nécessite confirmation opérateur (optionnel). ACTIONS SUPPORTÉES ================== 1. PAUSE (qB) Adapter : qb_adapter.pause(torrent_id) Préconditions : - qb_status ∈ UNSAFE OR save_path_invalid - torrent actif Post-condition : - qb_status = PAUSED 2. RESUME (qB) [optionnel B4 v1] Adapter : qb_adapter.resume(torrent_id) Préconditions : - qb_status = PAUSED Post-condition : - qb_status = RESUMED 3. FIX_SAVE_PATH Adapter : qb_adapter.set_save_path(torrent_id, new_path) Préconditions : - save_path_ok = FALSE Post-condition : - save_path_ok = TRUE 4. FORCE_RECHECK Adapter : qb_adapter.force_recheck(torrent_id) Préconditions : - fs_dst OK AND mirror OK AND qb_incomplete Post-condition (attendu via run suivant) : - qb reports progress recalculé 5. FIX_TAGS Adapter : tag_adapter.apply(tags_expected) Préconditions : - tags_state = MISMATCH Post-condition : - tags_state = OK 6. MIRROR_CLEANUP (safe=false) Adapter : fs_adapter.no_op() (placeholder B4 v1) Préconditions : - mirror incomplete AND abc=C Post-condition : - aucune en B4 v1 (exécution réelle déléguée B4 v2/B5) EXECUTION MODEL =============== Pour chaque action : EX-1 : valider (voir VALIDATION) EX-2 : appeler l’adapter correspondant EX-3 : capturer résultat (success/failure) EX-4 : produire ACTION_EXECUTION_RECORD EX-5 : marquer action comme “done” dans persistence POST-CYCLE ---------- Après exécution d’un ou plusieurs actions : PC-1 : TRIGGER B1 (nouveau diagnostic) PC-2 : TRIGGER B2 (analyse du changement) PC-3 : remettre à B3 (nouveau plan si nécessaire) FAILURES -------- F1 : Échec adapter → LOG + retry future cycle F2 : Action non applicable → SKIP + LOG F3 : État instable → STOP_SAFE_MODE SORTIE ------ EXECUTION_SUMMARY = { "run_id": ..., "actions_executed": [...], "actions_skipped": [...], "next_required_cycle": "B1" | "STOP" } [END DIGEST]