런타임 계약과 학습자 흐름 보강

This commit is contained in:
Yun Chan 2026-06-29 08:12:14 +09:00
parent f456b8997a
commit 206018b088
56 changed files with 4306 additions and 1008 deletions

View file

@ -55,6 +55,21 @@ powershell -NoProfile -ExecutionPolicy Bypass -File scripts\start-tailscale-runt
- dev-login은 `AUTH_DEV_LOGIN_EXTRA_ORIGINS`에 Tailnet origin이 들어간 경우에만 dev 환경에서 열린다. prod에서는 열리지 않는다.
- Tailnet/로컬 dev에서는 Google OAuth를 사용하지 않는다. OAuth redirect URI가 공개 API callback으로 고정된 동안에는 콜백이 로컬/Tailnet 세션이 아니라 공개 API 세션으로 돌아가므로, 로그인 화면은 Google 버튼을 비활성화하고 직접 `/api/auth/login?provider=google`을 열어도 `local_oauth_unavailable` 안내로 되돌린다.
### 0.2 Public runtime watchdog
공개 API 복구 스크립트는 `docs/ops/public-runtime-watchdog.md`가 runbook이다. 로컬 개발 서버와 별개로
prod API 8001, web preview 5174, engine gateway 9099, cloudflared tunnel을 검사한다.
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\watch-public-runtime.ps1 -CheckOnly
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\install-public-runtime-task.ps1 -RunNow
```
- Scheduled Task는 현재 Windows 사용자 기준 `AtLogOn` + 반복 watchdog이다. 사용자 로그인 전 headless boot service가 아니다.
- secret은 task 인자에 넣지 않는다. API secret은 `apps/api/.env`, cloudflared/Claude CLI credential은 사용자 profile에 둔다.
- 아직 DNS가 없는 future host는 기본 검사에 넣지 않는다. `api-vnet.18ka.net`처럼 실제로 열린 뒤에만 `-AdditionalPublicHealthUrls`로 명시 추가한다.
- 완료 판정은 parser/check-only가 아니라 실제 재부팅 또는 로그오프/로그온 뒤 `Get-ScheduledTaskInfo`, watchdog 로그의 `restart verified`, public health, 인증된 public `/turn` smoke까지 한 세트로 남겨야 한다.
### 수동 기동(대안)
DB·엔진 없이도 UI/로그인/페르소나/세션 생성까지는 동작한다(턴 생성만 불가).
@ -73,7 +88,7 @@ DB·엔진 없이도 UI/로그인/페르소나/세션 생성까지는 동작한
## 1. 사전 준비
- **Python 3.11** (운영 스크립트가 Python 3.11 기준). 가상환경 권장.
- **Node.js**(최신 LTS) + npm — `apps/web`.
- **Node.js 22 + npm** — CI와 같은 기준. newer LTS는 별도 재검증 전까지 기준선으로 쓰지 않는다.
- (선택) **Docker Desktop**`infra/docker-compose.yml` 전체 스택을 띄울 때만.
- (선택) **`claude` CLI** — `ENGINE_MODE=claude_cli`로 실제 턴 생성을 할 때. 설치 후 로그인되어 있어야 한다.
@ -163,7 +178,27 @@ cd D:\workspace\vignette
py -3.11 scripts\materialize-persona-seeds.py --json
```
### 2.4 DB 없이 degraded 기동 (정상 동작)
### 2.4 M2 session digest worker 실행
세션 종료 시 저장되는 fallback digest를 LLM 후보로 압축해 볼 때는 명시 session id runner를 쓴다.
기본은 dry-run이며, DB row를 바꾸려면 `--apply`를 반드시 붙인다. runner는 DB에서 작업을 읽은 뒤
connection을 놓고 engine을 호출하고, accepted 결과만 짧은 DB acquire로 적용한다.
```powershell
cd D:\workspace\vignette
py -3.11 scripts\run-session-digest-worker.py --session-id <session_uuid> --json
# accepted 후보를 실제 session_summary/case_profile에 반영할 때만
py -3.11 scripts\run-session-digest-worker.py --session-id <session_uuid> --apply --json
```
- 출력은 기본적으로 metadata-only다. digest 본문은 민감할 수 있으므로 `--show-digest`를 명시할 때만 출력한다.
- 입력은 client-visible `text_masked` transcript와 open thread만 사용한다. raw `text`, evaluator-only turn, CCD, `end_state`는 압축 prompt에 넣지 않는다.
- API 서버는 `SESSION_DIGEST_WORKER_ENABLED=true`일 때만 세션 종료 뒤 같은 worker를 background task로 실행한다. 기본값은 false다.
- scheduler도 DB load/apply 구간만 connection을 잡고, engine 호출은 DB transaction 밖에서 수행한다.
- 장시간 provider 운영, 임상 골든셋 품질평가, 재압축 정책은 별도 gate다.
### 2.5 DB 없이 degraded 기동 (정상 동작)
DB 연결이 안 되어도 dev에서는 그대로 기동한다. `main.py` lifespan이 풀 초기화 예외를 잡고
`store` 인메모리 폴백으로 degraded 기동하며, 다음 경고를 남긴다.
@ -432,8 +467,8 @@ RAG 임베딩/리랭커 의존성은 기본 이미지에 설치하지 않는다.
```powershell
# 백엔드 (apps/api)
cd apps\api
python -m pytest app/ -q # 현재 178 pass
python -m pytest engine_gateway\ -q # 현재 11 pass
python -m pytest app/ -q # 백엔드 기준선 178 pass
python -m pytest engine_gateway\ -q # 현재 27 pass
# 웹 (apps/web)
cd apps\web