/** * Justified Systems - Advanced Persistent Worker Engine (.NET 8 C# SDK) * Module: web_canvas/docs/snippets/JustifiedAdvancedEngine.cs * Governance: [JUS-ENG-01.01.000], [JEF-SPEC-04.01.000], [JEF-DIST-07.02.000], * [JUS-WEB-28.02.000], [JUS-WEB-15.01.000] */ using System; using System.Diagnostics; using System.IO; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace JustifiedSystems.Engine; /// /// High-throughput persistent process pipe wrapper for justified_engine.exe. /// Utilizes 4 MB unpaged ring buffers, non-blocking stderr draining, and stream desynchronization defenses. /// public sealed class JustifiedAdvancedEngine : IAsyncDisposable, IDisposable { private const int BufferSize = 4 * 1024 * 1024; // 4 MB I/O Ring Buffer private readonly SemaphoreSlim _gate = new(1, 1); private readonly StringBuilder _stderrBuffer = new(); private readonly object _stderrLock = new(); private Process? _process; private StreamWriter? _stdin; private StreamReader? _stdout; private bool _isDisposed; private bool _isPoisoned; // Stored startup parameters for auto-healing on pipe desynchronization private string? _lastBinaryPath; private string? _lastModelPath; private string? _lastLicenseKeyOrPath; public bool IsRunning => _process is { HasExited: false } && !_isPoisoned; /// /// Initializes and starts the persistent background inference substrate child process. /// /// File coordinate to justified_engine.exe. /// File coordinate to companion .jef_bin or .gguf model vault. /// License key string, license file coordinate, or --dev-mode. public void Start(string binaryPath, string modelPath, string? licenseKeyOrPath = null) { ObjectDisposedException.ThrowIf(_isDisposed, this); if (IsRunning) { throw new InvalidOperationException("Engine process is already active."); } if (!File.Exists(binaryPath)) { throw new FileNotFoundException($"Engine executable not found: {binaryPath}", binaryPath); } if (!File.Exists(modelPath)) { throw new FileNotFoundException($"Model vault not found: {modelPath}", modelPath); } _lastBinaryPath = binaryPath; _lastModelPath = modelPath; _lastLicenseKeyOrPath = licenseKeyOrPath; // Clean up any stale or poisoned process before starting TeardownProcess(); // Differentiate between raw license key, license file coordinate, and dev-mode string licenseFlag; if (string.IsNullOrWhiteSpace(licenseKeyOrPath) || licenseKeyOrPath == "--dev-mode") { licenseFlag = "--dev-mode"; } else if (licenseKeyOrPath.StartsWith("--")) { licenseFlag = licenseKeyOrPath; } else if (File.Exists(licenseKeyOrPath)) { licenseFlag = $"--license-file \"{licenseKeyOrPath}\""; } else { licenseFlag = $"--license \"{licenseKeyOrPath}\""; } var utf8WithoutBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); var psi = new ProcessStartInfo { FileName = binaryPath, Arguments = $"--model \"{modelPath}\" --pipe {licenseFlag}", UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, StandardInputEncoding = utf8WithoutBom, StandardOutputEncoding = utf8WithoutBom, StandardErrorEncoding = utf8WithoutBom }; _process = new Process { StartInfo = psi }; // Real-time asynchronous stderr drain to prevent pipe buffer lockup _process.ErrorDataReceived += (_, e) => { if (e.Data == null) return; lock (_stderrLock) { if (_stderrBuffer.Length > 32768) { _stderrBuffer.Remove(0, 16384); } _stderrBuffer.AppendLine(e.Data); } }; if (!_process.Start()) { throw new InvalidOperationException($"Failed to spawn Justified Engine from {binaryPath}."); } _process.BeginErrorReadLine(); _stdin = new StreamWriter(_process.StandardInput.BaseStream, utf8WithoutBom, BufferSize) { AutoFlush = true }; _stdout = new StreamReader(_process.StandardOutput.BaseStream, utf8WithoutBom, detectEncodingFromByteOrderMarks: false, BufferSize); _isPoisoned = false; } /// /// Streams an NDJSON frame to the active engine substrate and awaits the synchronous RFC 8259 result. /// Auto-heals if a prior turn was canceled or desynchronized. /// /// JSON payload string. /// Asynchronous cancellation token. /// Deterministic single-line JSON response string. public async Task ExecuteFrameAsync(string ndjsonPayload, CancellationToken ct = default) { ObjectDisposedException.ThrowIf(_isDisposed, this); ArgumentException.ThrowIfNullOrWhiteSpace(ndjsonPayload); await _gate.WaitAsync(ct).ConfigureAwait(false); try { // Auto-heal if a prior query cancellation poisoned the pipe stream if (_isPoisoned || !IsRunning) { if (_lastBinaryPath != null && _lastModelPath != null) { Start(_lastBinaryPath, _lastModelPath, _lastLicenseKeyOrPath); } else { throw new InvalidOperationException("Engine is in a halted state. Call Start() before dispatching frames."); } } // Normalize JSON payload to a single-line NDJSON frame string singleLinePayload; try { using var doc = JsonDocument.Parse(ndjsonPayload); singleLinePayload = JsonSerializer.Serialize(doc.RootElement); } catch (JsonException) { singleLinePayload = ndjsonPayload.Replace("\r", "").Replace("\n", " ").Trim(); } // Assume poisoned state until the turn completes successfully _isPoisoned = true; await _stdin!.WriteLineAsync(singleLinePayload.AsMemory(), ct).ConfigureAwait(false); string? response = await _stdout!.ReadLineAsync(ct).ConfigureAwait(false); if (response == null) { string diagnosticTrace; lock (_stderrLock) { diagnosticTrace = _stderrBuffer.ToString(); } throw new IOException($"Engine terminated unexpectedly. Stderr: {diagnosticTrace}"); } // Successfully received response; restore clean state _isPoisoned = false; return response; } catch (OperationCanceledException) { // Turn was aborted mid-stream; kill engine so next call doesn't read stale output TeardownProcess(); throw; } finally { _gate.Release(); } } private void TeardownProcess() { try { _stdin?.Dispose(); _stdout?.Dispose(); if (_process is { HasExited: false }) { _process.Kill(entireProcessTree: true); _process.WaitForExit(1000); } _process?.Dispose(); } catch { // Suppress race conditions during forced process teardown } finally { _stdin = null; _stdout = null; _process = null; _isPoisoned = true; } } public async ValueTask DisposeAsync() { if (_isDisposed) return; _isDisposed = true; await _gate.WaitAsync().ConfigureAwait(false); try { TeardownProcess(); } finally { _gate.Release(); _gate.Dispose(); } GC.SuppressFinalize(this); } public void Dispose() { if (_isDisposed) return; _isDisposed = true; _gate.Wait(); try { TeardownProcess(); } finally { _gate.Release(); _gate.Dispose(); } GC.SuppressFinalize(this); } }