G0~G8 성과·동맹 측정 OS 작업 일괄 고정

8월 7일까지 워킹트리에만 남아 있던 미커밋 작업을 커밋한다. 여러 사본
폴더(worktree·clone)에 흩어져 있던 중간 스냅샷을 정리하기 전에 원본을
git 이력으로 고정하는 것이 목적이다.

- contracts/routes/services: measurement, outcome_trajectory, rupture_repair,
  deliberate_practice, calibration_transfer, supervision_research,
  multimodal_alliance, continuous_improvement 계열 신규 모듈과 테스트
- infra/db/init: 07~16 마이그레이션(측정 기반~calibration transfer 실행)
- apps/web: 세션 리뷰 카드·관리 화면·E2E 스펙 추가
- docs/ops: G0~G8 라이브 통합·배포·롤백 증거 문서와 evidence JSON/PNG
- scripts: smoke·ledger·릴리스 에이전트·NAS 프리뷰 운영 스크립트

engine.public 로그 .bak과 apps/web/test-results 산출물은 커밋에서 제외했다.
This commit is contained in:
Yun Chan 2026-08-08 01:30:53 +09:00
parent 93dd8f82d7
commit 16e791e044
390 changed files with 243188 additions and 499 deletions

View file

@ -64,6 +64,45 @@ function Wait-JsonHealth {
throw "Timed out waiting for healthy response from $Uri"
}
function Test-EngineReady {
param(
[int]$Port,
[int]$TimeoutSec = 45
)
$headers = $null
if ($env:ENGINE_GATEWAY_SHARED_SECRET) {
$headers = @{ "X-Vignette-Engine-Token" = $env:ENGINE_GATEWAY_SHARED_SECRET }
}
try {
if ($headers) {
$response = Invoke-RestMethod -Uri "http://127.0.0.1:$Port/ready" -TimeoutSec $TimeoutSec -Headers $headers
} else {
$response = Invoke-RestMethod -Uri "http://127.0.0.1:$Port/ready" -TimeoutSec $TimeoutSec
}
return [bool]($response.ok -eq $true)
} catch {
return $false
}
}
function Wait-EngineReady {
param(
[int]$Port,
[int]$TimeoutSec = 90
)
$deadline = (Get-Date).AddSeconds($TimeoutSec)
do {
if (Test-EngineReady -Port $Port) {
return $true
}
Start-Sleep -Seconds 3
} while ((Get-Date) -lt $deadline)
return $false
}
function Wait-HttpStatus {
param(
[string]$Uri,
@ -91,8 +130,11 @@ function Stop-UvicornByPort {
[int]$Port
)
# Name 조건이 없으면 같은 문자열을 인자로 들고 있는 셸/래퍼 프로세스까지 매칭해
# 호출자 자신을 죽일 수 있다. 대상은 항상 python 프로세스다.
Get-CimInstance Win32_Process |
Where-Object {
$_.Name -like "python*" -and
$_.CommandLine -and
$_.CommandLine -like "*uvicorn $AppImport*" -and
$_.CommandLine -like "*--port $Port*"
@ -167,14 +209,30 @@ if (!(Test-Path $WebDir)) {
throw "Web directory not found at $WebDir"
}
# 재기동 판정은 /health(프로세스 liveness)가 아니라 /ready(실제 claude -p 생성)로 한다.
# 프로세스는 살아 있는데 그 프로세스의 claude 세션만 죽은 상태는 /health를 통과하므로,
# /health 기준으로는 복구가 필요한 순간에 오히려 재기동을 건너뛴다(2026-08-07 사고).
$engineHealth = Get-JsonHealth -Uri "http://127.0.0.1:$EnginePort/health"
$engineReady = $false
if ($null -ne $engineHealth -and $engineHealth.ok) {
$engineReady = Test-EngineReady -Port $EnginePort
}
if ($SkipEngineRestart) {
if ($null -eq $engineHealth -or -not $engineHealth.ok) {
throw "Engine gateway is not healthy on http://127.0.0.1:$EnginePort/health"
if (-not $engineReady) {
throw "Engine gateway is not ready on http://127.0.0.1:$EnginePort/ready"
}
} elseif ($null -eq $engineHealth -or -not $engineHealth.ok) {
} elseif (-not $engineReady) {
Stop-UvicornByPort -AppImport "engine_gateway.gateway:app" -Port $EnginePort
# Start-Process는 리다이렉트 대상 로그를 덮어쓴다. 직전 사고 로그를 보존해야
# 재기동 후에도 원인을 추적할 수 있다.
$rotateStamp = Get-Date -Format "yyyyMMdd-HHmmss"
foreach ($logFile in @($EngineOutLog, $EngineErrLog)) {
if (Test-Path $logFile) {
Move-Item -LiteralPath $logFile -Destination "$logFile.$rotateStamp.bak" -Force -ErrorAction SilentlyContinue
}
}
Start-Process -WindowStyle Hidden -FilePath $Python `
-ArgumentList @("-m", "uvicorn", "engine_gateway.gateway:app", "--host", "127.0.0.1", "--port", "$EnginePort") `
-WorkingDirectory $ApiDir `
@ -182,15 +240,11 @@ if ($SkipEngineRestart) {
-RedirectStandardError $EngineErrLog `
-PassThru | Out-Null
try {
$engineHealth = Wait-JsonHealth `
-Uri "http://127.0.0.1:$EnginePort/health" `
-IsHealthy { param($health) $health.ok -eq $true } `
-TimeoutSec 30
} catch {
$engineReady = Wait-EngineReady -Port $EnginePort -TimeoutSec 90
if (-not $engineReady) {
Write-Warning "Engine gateway is still degraded; continuing admin/auth recovery"
$engineHealth = Get-JsonHealth -Uri "http://127.0.0.1:$EnginePort/health"
}
$engineHealth = Get-JsonHealth -Uri "http://127.0.0.1:$EnginePort/health"
}
$env:ENVIRONMENT = "prod"
@ -303,8 +357,8 @@ if (!$SkipCloudflaredRestart) {
}
}
if ($null -ne $engineHealth -and $engineHealth.ok) {
Write-Output "Engine gateway healthy on http://127.0.0.1:$EnginePort"
if ($engineReady) {
Write-Output "Engine gateway ready (real generation proven) on http://127.0.0.1:$EnginePort"
} else {
Write-Warning "Engine gateway degraded; admin/auth control plane remains available"
}