Referencia Técnica

Wiki Desarrollador

Arquitectura interna, patrones, servicios core y sistema autónomo de Coclico. Referencia para contribuidores e integradores.

Visión general

Coclico está arquitecturado alrededor de un bucle autónomo: Observar → Analizar → Actuar → Validar

  • Observar: DynamicTracerService recopila telemetría CPU/RAM/red
  • Analizar: OptimizationEngineService + SourceAnalyzerService (Roslyn AST)
  • Actuar: AutoPatcherService aplica parches validados
  • Validar: DigitalTwinService asegura que la complejidad ciclomática no aumenta

Framework: .NET 10 / C# (LangVersion: preview), UI en WPF + WPF-UI 4.x, DI via Microsoft.Extensions.DependencyInjection.

Arranque & DI

Punto de entrada: App.xaml.cs. Secuencia de arranque:

// App.xaml.cs — secuencia de arranque simplificada
protected override async void OnStartup(StartupEventArgs e)
{
    // 1. Elevación UAC obligatoria
    if (!ElevationHelper.IsElevated())
        ElevationHelper.RestartAsAdmin();

    // 2. Construcción del contenedor DI
    ServiceContainer.Build(services =>
    {
        services.AddSingleton<ICacheService, CacheService>();
        services.AddSingleton<IDynamicTracer, DynamicTracerService>();
        services.AddSingleton<IRollbackService, RollbackService>();
        services.AddSingleton<AiChatService>();
        services.AddTransient<CleaningService>();
    }, validateOnBuild: true);

    // 3. SplashWindow durante el calentamiento de servicios
    var splash = new SplashWindow();
    splash.Show();
    await Task.Delay(2000).ConfigureAwait(false);

    // 4. Apertura de MainWindow
    new MainWindow().Show();
    splash.Close();
}

ServiceContainer

Un wrapper estático thread-safe alrededor de IServiceProvider. Dos métodos principales:

public static class ServiceContainer
{
    /// Resolución obligatoria — lanza excepción si falta
    public static T GetRequired<T>() where T : notnull
        => _provider!.GetRequiredService<T>();

    /// Resolución opcional — devuelve null si falta
    public static T? GetOptional<T>() where T : class
        => _provider!.GetService<T>();
}
Prefiere la inyección por constructor en código nuevo. ServiceContainer.GetRequired<T>() está reservado para casos donde la inyección es imposible (handlers estáticos, convertidores WPF, etc.).

Patrón MVVM

Coclico sigue estrictamente el MVVM con CommunityToolkit.Mvvm 8.4:

  • Vistas (Views/*.xaml) — XAML puro, sin lógica de negocio
  • ViewModels (ViewModels/*ViewModel.cs) — [ObservableProperty], [RelayCommand]
  • Servicios (Services/*.cs) — lógica de negocio, acceso al sistema, IA
// ViewModels/DashboardViewModel.cs
public partial class DashboardViewModel : ObservableObject
{
    [ObservableProperty] private double _cpuUsage;
    [ObservableProperty] private long _ramUsedMb;

    [RelayCommand]
    private async Task RefreshAsync()
    {
        var snap = await _tracer.GetSnapshotAsync().ConfigureAwait(false);
        // Siempre Dispatcher.InvokeAsync para actualizaciones de UI
        await Application.Current.Dispatcher
            .InvokeAsync(() => { CpuUsage = snap.CpuPercent; });
    }
}

Dual LLM Executor

AiChatService mantiene dos pares de contexto/executor LLamaSharp completamente aislados para evitar contención entre el chat de usuario y el motor de optimización:

public sealed class AiChatService
{
    // Contexto dedicado al chat de usuario (AiChatView)
    private LLamaContext _chatCtx;
    private readonly SemaphoreSlim _chatSem = new(1, 1);

    // Contexto dedicado al OptimizationEngine (segundo plano)
    private LLamaContext _engineCtx;
    private readonly SemaphoreSlim _engineSem = new(1, 1);

    // Immutable Context Swap — reset sin bloquear consumidores
    public async Task ResetChatContextAsync()
    {
        var old = Interlocked.Exchange(ref _chatCtx, await BuildContextAsync());
        old?.Dispose();
    }
}

FeatureExecutionEngine

Todas las acciones de larga duración deben pasar por FeatureExecutionEngine.RunFeatureAsync, que añade automáticamente protección circuit-breaker, telemetría y soporte de cancelación.

RollbackService

Cada operación de escritura disparada por la IA debe ir precedida de un snapshot de rollback:

// Patrón obligatorio antes de File.WriteAllText
var snapshotId = await _rollback
    .CreateSnapshotAsync(targetFilePath)
    .ConfigureAwait(false);
try
{
    File.WriteAllText(targetFilePath, newContent, Encoding.UTF8);
}
catch
{
    await _rollback.RestoreAsync(snapshotId).ConfigureAwait(false);
    throw;
}

Sistema Flow Chains

Tres servicios gestionan el ciclo de vida del pipeline de automatización:

  • WorkflowPipelineService — CRUD para definiciones de pipeline (JSON en %APPDATA%\Coclico\flow-chains\)
  • WorkflowPipelineExecutionService — ejecución secuencial con circuit-breaker y aplicación de política de seguridad
  • WorkflowExecutionService — orquestación de alto nivel y planificación

Modelo WorkflowPipeline

public record WorkflowPipeline
{
    public Guid Id { get; init; } = Guid.NewGuid();
    public string Name { get; init; } = string.Empty;
    public List<PipelineNode> Nodes { get; init; } = [];
}

// 28 valores NodeType, 10 valores ConditionOperator, 3 valores OnErrorAction
public enum NodeType
{
    KillProcess, LaunchProcess, RestartService, StopService, StartService,
    SetRegistryValue, DeleteRegistryKey, CreateDirectory, DeleteFile,
    MoveFile, CopyFile, RunScript, CleanTemp, EmptyRecycleBin, FlushDns,
    ClearBrowserCache, ClearEventLogs, ClearPrefetch, ClearThumbnailCache,
    ClearWindowsErrorReports, FreeRam, SetWorkingSet, PingHost,
    DisableNetworkAdapter, EnableNetworkAdapter, Wait, Condition, Log, Notification
}

SourceAnalyzer (Roslyn AST) — Fase 3.3

SourceAnalyzerService usa Roslyn para analizar el propio código fuente C# de Coclico. Calcula por método: Complejidad Ciclomática (CC), métricas Halstead (V, D, E) e Índice de Mantenibilidad (MI).

Digital Twin Gate — Fase 3.3

Antes de aplicar cualquier parche generado por IA, DigitalTwinService valida que el parche no aumente la complejidad ciclomática. Si patchedCC > originalCC, el parche es rechazado.

AutoPatcher — Fase 3.4

Gestiona el ciclo de vida de los parches de IA con aprobación humana. Por defecto: AutoPatcherAuditOnly = true — los parches se registran en el log de auditoría pero nunca se aplican sin aprobación explícita vía ApproveAndApplyAsync(proposalId).

OptimizationEngine — Fase 2

Se ejecuta cada 30 segundos en segundo plano. Reglas críticas: usar ArrayPool<byte>.Shared para buffers de telemetría, nunca closures en el bucle principal, siempre ConfigureAwait(false).

Seguridad & Auditoría

SecurityPolicyService fusiona %APPDATA%\Coclico\security-policy.json con valores predeterminados codificados no suprimibles. AuditLogService escribe NDJSON de solo anexión incluyendo AiDecisionContext para trazabilidad completa de decisiones LLM.

Convenciones de código

  • Nomenclatura: PascalCase para clases/interfaces, _camelCase para campos privados, sufijo Async para métodos async
  • Inyección: Solo por constructor — nunca service-locate dentro de un constructor
  • Segundo plano: ConfigureAwait(false) en cada await en servicios
  • Logs: LoggingService.LogInfo / LoggingService.LogException — nunca silenciar excepciones
  • DTOs: Usar record para snapshots y resultados (inmutabilidad)
  • Secretos: Nunca codificar en duro — usar SettingsService o variables de entorno
  • C# 12: Usar primary constructors y collection expressions ([])