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

@ -39,19 +39,27 @@
예측 불가능성을 유지한다. 회귀는 `e2e/insecure-context-uuid.spec.ts` 6/6으로 고정했다(직접 호출
0건 검사 포함). **주의: 이 수정은 아직 NAS 프리뷰에 배포되지 않았다** — 배포된 SHA
`6030a677…c611`은 여전히 결함이 있는 빌드다.
- [ ] **워치독 engine readiness 사각지대** — 2026-08-07 21:5x KST 공개 API가 `engine=false`
(`engine_detail=empty engine response`)로 degraded인데 워치독은 `lastResult=0`(정상)으로 끝났다.
원인은 판정 기준이다. `scripts/watch-public-runtime.ps1:107`의 engine 검사는 게이트웨이
`/health``ok==true`만 보는데 이 엔드포인트는 claude readiness probe를 돌리지 않는다.
같은 파일 `:112`의 API 검사도 `environment=="prod" && db`만 보고 `engine`은 보지 않는다.
실제로 게이트웨이 9099의 `/ready?force=true`는 503이었고(readiness 캐시 TTL 30초라 stale 아님),
NAS용 게이트웨이 9100은 정상이었다. **결정적 확인:** 같은 `.env`·같은 `claude` CLI로 새 게이트웨이
프로세스를 별도 포트(9199)에 띄우자 `/ready?force=true`가 즉시 `ok=true, detail=OK`를 반환했다.
따라서 CLI나 인증 문제가 아니라 16:06부터 상주하던 9099 **프로세스의 claude 세션만 죽은** 형태이고,
프로세스가 살아 있으므로 `/health``ok`만 보는 워치독은 이를 감지할 수 없다.
조치: (1) engine 판정을 게이트웨이 `/ready`(또는 API health의 `engine` 필드)로 바꾸고 복구 후
재검증에도 같은 기준을 적용한다. (2) 9099 재기동으로 공개 API를 복구한다 — 공개 서비스 영향이 있어
소유자 승인 후 수행한다.
- [x] **워치독 engine readiness 사각지대** — 2026-08-07 22:0x KST 소유자 승인으로 9099 재기동과
판정 기준 교정을 모두 마쳤다. 복구 실측: 9099 `/ready?force=true` 200 `ok:true, detail:OK`,
API 8001과 공개 `api-vignette.chanpaca.net` 모두 `status:ok, engine:true, engine_detail:OK`.
원인은 16:06부터 상주하던 9099 **프로세스 하나**였다. 같은 인자로 `claude -p`를 직접 실행하고
`EngineSession`을 그대로 재현하면 양쪽 다 `"OK"`를 반환해 CLI·코드·cwd는 무관함을 확인했다
(별도 포트 9199 실험과 동일 결론).
재발 방지 3건:
(1) `scripts/watch-public-runtime.ps1`·`scripts/start-public-runtime.ps1`의 engine 판정을
`/health`(프로세스 liveness) → `/ready`(실제 생성)로 바꾸고, API 판정에 `engine`을 추가했다.
shared secret 인스턴스를 401로 오판하지 않도록 `X-Vignette-Engine-Token` 헤더를 붙이고,
503 응답 **본문**을 로그 detail에 남긴다.
(2) `engine_gateway/gateway.py`가 자식 `claude -p`의 stderr를 상시 드레인해(PIPE를 아무도 읽지
않으면 자식이 블록되는 문제도 함께 차단) 실패 detail에 `exit`·stderr를 붙인다. 실증:
`empty engine response (error: unknown option '--vignette-nonexistent-flag-xyz')`.
`str()`이 비는 `TimeoutError` 등에는 타입명을 최소 보장한다.
(3) 기동 시 게이트웨이 로그 회전, `Stop-UvicornByPort``Name -like python*` 조건 추가
(명령 문자열만 매칭해 호출자 자신을 죽이는 사고 방지).
검증: `pytest engine_gateway` 58/58, 워치독 `-CheckOnly` healthy 5/5, 장애 재현(9299를
`CLAUDE_BIN` 부재로 기동)에서 `/health``ok:true`로 통과하고 `/ready`는 503으로 검출되어
워치독이 `unhealthy (1/3)` + 503 본문을 남겼다.
남은 것: NAS용 9100은 실사용 세션 7개가 있어 미접촉이라 (2)는 다음 재기동 때 반영된다.
- [ ] **재부팅 후 watchdog smoke** — 실제 Windows 재부팅 후 엔진/API/터널 자동 복구 + public `/turn` 실측.
DNS 개통 후 `api-vnet.18ka.net``-AdditionalPublicHealthUrls`로 명시 추가.
- [ ] **음성 캐스케이드 live** — Deepgram streaming adapter와 interim/final·word timestamp, bounded event queue,