feat(cognition): dataclasses Trace + SceneExpected + Precondition (Phase 2.1)
Crée les 3 dataclasses du modèle Mandat/Protocoles/Scènes v0.3 dans core/cognition/, standalone (aucun branchement runtime), avec sérialisation JSON explicite et tests offline. Préparation des phases : - Phase 2.1 plan : objet Trace (mandate_id, intention_id, scene_id, affordance_signature, expected_retour, level_of_delegation) - Workpack A : SceneExpected (monitor_index, app_name, title_patterns, title_anti, window_rect_hint, scene_role, accepted_transitions, stability_ms) + helper matches_title() - Workpack B : Precondition (kind, window_title_must_contain/anti, critic_question, verify_timeout_ms) + PreconditionRecovery (max_attempts, on_recovery_fail, actions) Toutes les dataclasses sont frozen, immutables, avec to_dict/from_dict tolérants (champs vides/None -> instance vide). Validation au __post_init__ pour Precondition.kind et PreconditionRecovery.on_recovery_fail. Aucune dépendance runtime obligatoire : si l'objet n'est pas posé sur une action, fallback comportement actuel. Aucune modif executor / api_stream / replay_engine / grounding. Tests : 22/22 passent (sérialisation JSON, contrats from_dict tolérants, validation kinds, helpers matches_title/check_title, anti-intention). Tag rollback : rollback/pre-cognition-dataclasses-2026-05-25_0610
This commit is contained in:
59
core/cognition/trace.py
Normal file
59
core/cognition/trace.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""Trace causale d'une action — modèle Mandat/Protocoles/Scènes v0.3.
|
||||
|
||||
Cf. docs/architecture/MODELE_MANDAT_PROTOCOLS_LEA_2026-05-25_v0.3_ARBITRAGES_DOM.md
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field, asdict
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Trace:
|
||||
"""Contrat unificateur transporté du build au runtime à la preuve.
|
||||
|
||||
Tous les champs sont optionnels (str vide / None) pour permettre une
|
||||
introduction progressive sans casser les actions existantes qui n'en
|
||||
portent pas. Fallback : comportement actuel si trace absente.
|
||||
|
||||
Attributs
|
||||
mandate_id : ID du mandat humain de niveau supérieur
|
||||
intention_id : ID du sous-but courant servant le mandat
|
||||
scene_id : ID de la scène d'intention pertinente
|
||||
affordance_signature: signature stable de l'affordance ciblée
|
||||
expected_retour : description courte du retour attendu
|
||||
level_of_delegation : N0..N4 (cf v0.3 arbitrage 3)
|
||||
"""
|
||||
|
||||
mandate_id: str = ""
|
||||
intention_id: str = ""
|
||||
scene_id: str = ""
|
||||
affordance_signature: str = ""
|
||||
expected_retour: str = ""
|
||||
level_of_delegation: int = 0
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return asdict(self)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Optional[Dict[str, Any]]) -> "Trace":
|
||||
if not data:
|
||||
return cls()
|
||||
return cls(
|
||||
mandate_id=str(data.get("mandate_id", "") or ""),
|
||||
intention_id=str(data.get("intention_id", "") or ""),
|
||||
scene_id=str(data.get("scene_id", "") or ""),
|
||||
affordance_signature=str(data.get("affordance_signature", "") or ""),
|
||||
expected_retour=str(data.get("expected_retour", "") or ""),
|
||||
level_of_delegation=int(data.get("level_of_delegation", 0) or 0),
|
||||
)
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
return not (
|
||||
self.mandate_id
|
||||
or self.intention_id
|
||||
or self.scene_id
|
||||
or self.affordance_signature
|
||||
or self.expected_retour
|
||||
)
|
||||
Reference in New Issue
Block a user