$ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot $backendRoot = Join-Path $projectRoot 'backend' $runLogDir = Join-Path $projectRoot ('test-evidence/local-operations-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) New-Item -ItemType Directory -Path $runLogDir -Force | Out-Null function Test-Listener([int]$Port) { return [bool](Get-NetTCPConnection -State Listen -LocalPort $Port -ErrorAction SilentlyContinue) } # These are child-process settings only. Existing Docker services are untouched. $env:HF_HUB_OFFLINE = '1' $env:TRANSFORMERS_OFFLINE = '1' $env:NO_PROXY = '*' $env:HTTP_PROXY = '' $env:HTTPS_PROXY = '' $env:ALL_PROXY = '' $env:PYTHONIOENCODING = 'utf-8' $env:RISK_AGENT_BACKEND_URL = 'http://127.0.0.1:8003' if (-not (Test-Listener 8003)) { $pythonPath = Join-Path $backendRoot 'venv/Scripts/python.exe' $backendProcess = Start-Process -FilePath $pythonPath -ArgumentList '-u','-m','uvicorn','app:app','--host','127.0.0.1','--port','8003' -WorkingDirectory $backendRoot -WindowStyle Hidden -PassThru -RedirectStandardOutput (Join-Path $runLogDir 'backend.log') -RedirectStandardError (Join-Path $runLogDir 'backend-error.log') Write-Output "Backend starting: PID $($backendProcess.Id), port 8003" } else { Write-Output 'Port 8003 is occupied; verifying existing service without stopping it.' } if (-not (Test-Listener 3000)) { $nodePath = (Get-Command node.exe).Source $nextPath = Join-Path $projectRoot 'node_modules/next/dist/bin/next' $frontProcess = Start-Process -FilePath $nodePath -ArgumentList ('"' + $nextPath + '"'),'dev','--hostname','127.0.0.1','--port','3000' -WorkingDirectory $projectRoot -WindowStyle Hidden -PassThru -RedirectStandardOutput (Join-Path $runLogDir 'frontend.log') -RedirectStandardError (Join-Path $runLogDir 'frontend-error.log') Write-Output "Frontend starting: PID $($frontProcess.Id), port 3000" } else { Write-Output 'Port 3000 is occupied; verifying existing service without stopping it.' } $startupDeadline = (Get-Date).AddMinutes(4) $healthy = $false while ((Get-Date) -lt $startupDeadline) { try { $probe = Invoke-RestMethod 'http://127.0.0.1:3000/api/risk-agent/project-assistant/operations/overview?domain=lab' -TimeoutSec 5 if ($probe.domain -eq 'lab') { $healthy = $true; break } } catch { } Start-Sleep -Seconds 2 } if (-not $healthy) { throw "Startup check failed. Check logs or authentication: $runLogDir. No occupied process was stopped." } Write-Output 'Ready: http://127.0.0.1:3000/operations-center?domain=lab&view=lab' Write-Output "Logs: $runLogDir"