=============================================================================== AR88_JOINT_FIX_CHANGES.txt TEITAN AR-88: MODIFICACIONES EXACTAS Y JUSTIFICACIÓN (AR88-JOINT-FIX-01) Fecha: 2026-10-28 Copia de Trabajo: functional_detector_nobypass_ws =============================================================================== 1. ARCHIVO: app/remediation/self_repair/functional_diagnostic_adapter.py - Justificación: Corregir Defecto A (contrato de estados) y blindar la validación de incidentes internos contra conversiones indebidas de BLOCKED/UNPROVEN/PASS. - Cambios Exactos: a) Se introdujo PROTECTED_TARGET_PATHS con las 12 líneas base y rutas críticas (engine.py, schemas.py, live_shadow_hook.py, DIGITAL_OPTIMUS_NORTE_MAESTRO.md). b) Se agregaron las funciones auxiliares de seguridad: - _compute_sha256(path) - _is_canonically_within(parent_dir, target_path) - _is_protected_target(rel_path) c) Se reemplazó el assert por el método canónico de rechazo seguro: validate_and_convert_failure(eval_result, workspace_root) Reglas aplicadas: * Estado distinto de FAIL => REJECTED_STATUS. * Sin assertion_error ni stack_trace => REJECTED_INSUFFICIENT_EVIDENCE. * Sin target_file_rel => REJECTED_MISSING_TARGET. * Resuelve fuera de workspace_root => REJECTED_BOUNDARY_ESCAPE. * Coincide con ruta protegida => REJECTED_PROTECTED_TARGET. * No existe físicamente en disco => REJECTED_FILE_NOT_FOUND. * Hash físico no coincide con hash registrado => REJECTED_HASH_MISMATCH. d) Se preservó la firma pública original: failure_result_to_incident_and_evidence(eval_result, workspace_root) la cual invoca validate_and_convert_failure() y devuelve None ante cualquier rechazo. 2. ARCHIVO: app/remediation/self_repair/self_diagnostic.py - Justificación: Implementar la Unión B conectando los resultados auténticos de InternalFunctionalAssessor con FunctionalDiagnosticAdapter sin fabricar misiones falsas. - Cambios Exactos: a) En la dataclass SelfRepairDiagnosticReport: Se agregó el campo: internal_incidents: List[Dict[str, Any]] = field(default_factory=list) b) En run_diagnostic(): Se desempaqueta el tercer valor de retorno de _check_internal_functional_contracts() y se transfiere a internal_incidents en SelfRepairDiagnosticReport. c) En _check_internal_functional_contracts(): Se importa FunctionalDiagnosticAdapter y, ante cada resultado FAIL, se ejecuta FunctionalDiagnosticAdapter.validate_and_convert_failure(). Si es admisible, se agrega el registro a internal_incidents conteniendo: - incident_id - component_name - contract_id - target_file_rel - file_sha256 - incident (IncidentRecord canónico) - evidence (EvidenceBundle canónico) - event (MissionFailureEvent canónico) Si es rechazado, se registra la razón en actionable_diagnostics. Si el resultado es BLOCKED (como ocurre en el host con barreras no satisfechas), NO se crea ningún incidente interno. 3. ARCHIVOS QUE PERMANECEN RIGUROSAMENTE INTACTOS: - app/remediation/self_repair/engine.py (Inspeccionado; process_incident() consume directamente los contratos sin cambios). - app/remediation/self_repair/functional_assessor.py (Conserva inalterado el fail-closed no-bypass). - app/remediation/self_repair/circuit.py (Conserva intacto el defecto de CircuitTracer). - app/remediation/self_repair/schemas.py (Intacto). - app/remediation/self_repair/live_shadow_hook.py (Intacto). - app/remediation/self_repair/shadow_orchestrator.py (Intacto). - Producción C:\xampp\htdocs\Digital Optimus (0 archivos modificados).