운영 복구 상태를 문서화

This commit is contained in:
Yun Chan 2026-08-28 18:27:02 +09:00
parent 99779a6ab2
commit 391fb9f4d0
4 changed files with 48 additions and 36 deletions

View file

@ -28,11 +28,13 @@
| REQ-005 | **DONE · 내부 기술·운영 실증** | 새 회기는 승인 페르소나 `persona_id/version` 고정. P20의 `suicide_ideation_stage=0.9 → int(0) → DB 1..5` 장애를 clamp로 제거했고, 공개 P20 회기 생성·실제 AI 응답·종료·평가를 확인 |
| REQ-006 | **DONE · 내부 기술** | prompt와 구조화 결과의 상담자/내담자 identity를 `[COUNSELOR]`/`[CLIENT]`로 역할 마스킹 |
| REQ-007 | **DONE · 내부 기술** | 회기 종료를 평가보다 먼저 영속화해 옛 평가 실패 뒤에도 새 회기 생성·턴 진행 가능 |
| REQ-008 | **DONE · 내부 기술** | 기본 엔진+live-client readiness, 구조화 done 없는 SSE EOF는 `client_stream_incomplete`로 실패 |
| REQ-008 | **DONE · 내부 기술** | 기본 엔진+live-client readiness, 구조화 done 없는 SSE EOF는 `client_stream_incomplete`로 실패. 복구 launcher는 전역 mutex·단계별 상한·프로세스 트리 종료·전체 다운 즉시복구로 보강 |
운영 반영 기준은 clean commit `2a396361…89c`, Pages production
`1f1ddf18-9d5c-4d83-95a7-8cd71245e646`이다. API/engine/web/STT/TTS/cloudflared와 두 예약 작업은
같은 릴리스 루트에 고정했고 watchdog 8개 check, 공개 Google callback, P20 회기 폐루프를 통과했다.
현재 공개 API/engine/web/STT/TTS/cloudflared와 Pages production
`1f1ddf18-9d5c-4d83-95a7-8cd71245e646`의 서비스 소스는 clean `2a396361…89c`다. 재부팅 복구용
로그온·watchdog 작업은 detached-clean `99779a6a…fbc8`·tree `57da86aa…6b91`로 별도 승격했고,
60분 상한·`IgnoreNew`·복구 mutex·전체 다운 즉시복구를 고정한 뒤 두 작업 수동 실행 결과 0을 확인했다.
새 학습자 라포 헤더 번들은 준비됐지만 Pages 승격은 명시 승인 전이라 아직 공개되지 않았다.
---
@ -67,8 +69,9 @@
- [ ] **자동 DB 백업·정기 복원 리허설**`scripts/backup-vignette-db.ps1`의 custom dump→TOC 검증→
SHA manifest 원자 게시와 현재 public-target 일회용 복원(129 tables/9,646 rows/orphan 0)을 통과했다.
남은 범위는 예약 실행, 실패 알림, NAS/off-host 암호화 복제, 주기적 restore drill과 보존 정책이다.
- [ ] **공개 Google OAuth 실제 `/turn` proof** — 로그인 계정으로 `storageState` 캡처 → `E2E_PUBLIC_AUTH=1` +
`chromium-public-auth` 1회 통과. 실행 명령은 대시보드 "다음 실행 명령"/`HANDOFF.md`. (소유자 보류 중)
- [x] **공개 Google OAuth 실제 `/turn` proof** — 2026-08-28 기존 Google 세션으로 callback→관리자 진입을
확인하고 P20 회기 생성→자기점검 잠금→실제 학습자 발화/AI 내담자 응답→종료→리뷰·평가→다음 회기 버튼
재노출까지 공개 브라우저 폐루프를 통과했다. 별도의 신규 Gmail 선택은 새 Vignette 계정 생성 확인 항목이다.
- [x] **공개 Web 모바일 보정 Pages 배포** — 2026-08-18 소유자 승인 후 detached-clean `cf899b7f…7c96`
완료했다(00f851a6 후보의 모바일 보정을 포함한 상위 커밋). API type/typecheck, 2회 결정적 build(599파일
sha256 전일치), 7개 origin 자산 143개 보존(최종 742파일) 후 Cloudflare Pages production `4edc02d3` 배포 —
@ -127,10 +130,12 @@
- [ ] **stable-source task 재등록 + 재부팅 후 watchdog smoke** — 2026-08-27 stale AF_UNIX socket으로
Docker Desktop 백엔드와 공개 DB가 중단된 사건을 기존 container·volume 삭제/교체 없이 복구했다. 부모 IPC 폴더는
timestamp `.stale` 이름으로 보존했고, 기존 `vignette-dev-db``vignette_recovered_prod_20260807`만 재기동했다.
detached-clean `bf5f7352…0092`·tree `c39f917b…c88`에 watchdog·로그온 boot task를 재등록해
action root/commit/tree/script SHA pin, 5분 watchdog `LastTaskResult=0`·failcount `0`, local/public health
`status=ok·db=true·engine=true` 3/3을 확인했다. 남은 것은 실제 Windows 재부팅 후 엔진/API/터널 자동 복구와
authenticated public `/turn` 실측이다. DNS 개통 후 `api-vnet.18ka.net`
2026-08-28에는 detached-clean `99779a6a…fbc8`·tree `57da86aa…6b91`로 watchdog·로그온 boot task를
다시 등록했다. 두 작업 모두 `ExecutionTimeLimit=PT1H`·`MultipleInstances=IgnoreNew`, scheduler 재시도 0이며,
launcher 전역 mutex·bounded API/voice/web build·부모/자식 process-tree 종료와 cloudflared 또는 전체 동적
서비스 hard-down 즉시복구를 회귀 50건으로 고정했다. action root/commit/tree/script SHA pin, watchdog
18:10:57 KST·boot 18:14:27 KST 수동 실행 `LastTaskResult=0`, failcount 0을 확인했다. 로그인 뒤 수동 복구는
증명됐지만 실제 Windows 재부팅 후 엔진/API/터널 자동 복구는 아직 실측하지 않았다. DNS 개통 후 `api-vnet.18ka.net`
`-AdditionalPublicHealthUrls`로 명시 추가한다.
- [x] **노트북 로컬 음성 스택 STT 구현** — 2026-08-08 소유자 결정으로 음성 양쪽을 노트북 상주
로컬 모델로 쓴다(STT faster-whisper, TTS는 아래 항목대로 MeloTTS). 이전에는 코드에 로컬 STT 경로가 아예 없었고

View file

@ -291,7 +291,7 @@
<div class="brand"><span class="mark" aria-hidden="true"></span><span>Vignette 커맨드센터<small>팀장 리뷰 · dev status</small></span></div>
<div class="head-right">
<a class="owner-pill" href="#owner"><span class="d" aria-hidden="true"></span>내 차례 <b id="pill-owner">0</b></a>
<span class="stamp">2026-08-10 KST</span>
<span class="stamp">2026-08-28 KST</span>
</div>
</header>
@ -300,11 +300,12 @@
<section class="pulse">
<div class="pulse-main">
<span class="eyebrow">project pulse</span>
<h1>지금 위치: <em>G0~G6 · G8 증거 DONE</em>. <em>G7 external proof · 재부팅 실증</em>이 남았다.</h1>
<p class="pulse-state"><b>현재:</b> 공개 앱·API·DB와 current NAS 실회기는 GREEN이다. <b>다음:</b> 실제 Windows 재부팅 자동복구 → authenticated public 회기 → G7 mic·human proof.</p>
<h1>지금 위치: <em>G0~G6 · G8 증거 DONE</em>. <em>G7 external proof · C-001 · 재부팅 실증</em>이 남았다.</h1>
<p class="pulse-state"><b>현재:</b> 공개 앱·API·DB와 current NAS 실회기는 GREEN이고 재부팅 복구 task 계약도 보강했다. <b>다음:</b> 새 Pages 후보 명시 승인 → 실제 Windows 재부팅 자동복구 → G7 mic·human proof.</p>
<details class="pulse-details">
<summary>운영 복구·watchdog·배포 상세 보기</summary>
<p class="pulse-state"><b>2026-08-27 Docker stale socket 인시던트·복구:</b> 공개 로그인 화면은 유지됐지만 API가 <code>db=false</code> degraded 뒤 502가 됐다. 원인은 Docker Desktop 4.82.0 백엔드가 이전 비정상 종료에서 남은 0바이트 AF_UNIX reparse socket <code>Docker\run\dockerInference</code><code>docker-secrets-engine\engine.sock</code>을 ERROR 1920으로 제거하지 못해 startup crash-loop한 결함이다. Docker 전체 종료 후 두 부모 IPC 디렉터리를 <code>run.stale-20260827-232006</code>·<code>docker-secrets-engine.stale-20260827-232006</code>으로 이동해 복구 가능하게 보존했고, container·image·volume 생성/삭제/교체 없이 기존 <code>vignette-dev-db</code><code>vignette_recovered_prod_20260807</code>만 시작했다. API는 detached-clean <code>bf5f7352…0092</code>·tree <code>c39f917b…c88</code>에서 routine API-only 복구했고 public health 3/3 <code>status=ok·db=true·engine=true</code>를 확인했다. 로그온·5분 watchdog도 같은 root/commit/tree와 exact boot/watchdog/start SHA에 재등록했으며 watchdog <code>LastTaskResult=0</code>·failcount <code>0</code>이다. 실제 공개 로그인 브라우저는 console error/warning 0이다. 실제 Windows 재부팅과 authenticated public <code>/turn</code>은 아직 별도 gate다.</p>
<p class="pulse-state"><b>2026-08-28 재부팅 복구 hardening:</b> 로그온·5분 watchdog을 detached-clean <code>99779a6a…fbc8</code>·tree <code>57da86aa…6b91</code>에 재등록했다. 두 task는 <code>ExecutionTimeLimit=PT1H</code>·<code>MultipleInstances=IgnoreNew</code>이고 scheduler 이중 재시도는 제거했다. launcher는 exclusive mutex, API 180초·voice 90초·web build 600초 상한, timeout 시 parent+child process-tree 종료를 적용했고 watchdog은 cloudflared 누락 또는 API/web/voice-sidecar 전체 다운을 debounce 없이 즉시 복구한다. focused 회귀 <code>50 passed</code>, watchdog 18:10:57 KST·boot 18:14:27 KST 수동 실행 결과 0·failcount 0을 확인했다. 이것은 로그인 뒤 복구 증거이며 실제 Windows 재부팅 smoke와 PC 비종속 상시 호스트 이전은 여전히 별도 gate다.</p>
<p class="pulse-state"><b>2026-08-27 Docker stale socket 인시던트·복구:</b> 공개 로그인 화면은 유지됐지만 API가 <code>db=false</code> degraded 뒤 502가 됐다. 원인은 Docker Desktop 4.82.0 백엔드가 이전 비정상 종료에서 남은 0바이트 AF_UNIX reparse socket <code>Docker\run\dockerInference</code><code>docker-secrets-engine\engine.sock</code>을 ERROR 1920으로 제거하지 못해 startup crash-loop한 결함이다. Docker 전체 종료 후 두 부모 IPC 디렉터리를 <code>run.stale-20260827-232006</code>·<code>docker-secrets-engine.stale-20260827-232006</code>으로 이동해 복구 가능하게 보존했고, container·image·volume 생성/삭제/교체 없이 기존 <code>vignette-dev-db</code><code>vignette_recovered_prod_20260807</code>만 시작했다. API는 detached-clean <code>bf5f7352…0092</code>·tree <code>c39f917b…c88</code>에서 routine API-only 복구했고 public health 3/3 <code>status=ok·db=true·engine=true</code>를 확인했다. 로그온·5분 watchdog도 같은 root/commit/tree와 exact boot/watchdog/start SHA에 재등록했으며 watchdog <code>LastTaskResult=0</code>·failcount <code>0</code>이다. 실제 공개 로그인 브라우저는 console error/warning 0이다. authenticated public <code>/turn</code>은 2026-08-28 폐루프를 통과했고 실제 Windows 재부팅만 별도 gate다.</p>
<p class="pulse-state"><b>2026-08-18 엔진 readiness 장애·수정:</b> 06:30~10:05 KST 공개 API가 <code>engine=false</code>로 약 3.5시간 degraded였다. 원인은 (1) <code>reasoning_effort=high</code> 콜드 프로브가 20초 타임아웃을 넘기면 실패가 성공과 같은 TTL(운영 1800초)로 캐시되는 게이트웨이 결함, (2) 공개 엔진 <code>claude -p</code>가 소유자 Claude 구독을 개발 에이전트 작업과 공유해 사용량 한도 소진 시 생성이 실패하는 운영 경계다. 워치독은 기본 <code>/ready</code>의 캐시 200만 보고 엔진을 healthy로 오판해 API만 재시작하는 루프에 빠졌다. 수정: 실패 전용 <code>ENGINE_READY_FAILURE_TTL_SECONDS</code>(기본 30초) 분리 + 프로브 타임아웃 20→45초, 회귀 4건 신설(게이트웨이 62/62·backend 986). detached-clean <code>4771b97c…c880</code>·tree <code>286723de…c1fa</code>로 API/게이트웨이/워치독·부트 task를 재승격·재등록했고 명시 실행 <code>LastTaskResult=0</code>, 공개 health ok·OpenAPI 126·local voice exact를 재확인했다. 1차 승격은 새 worktree에 <code>apps/api/.env</code>(gitignored 비밀값)가 없어 fail-closed로 실패했다 — 승격 절차에 env 이관 단계가 필요함을 기록한다(약 4분 다운타임).</p>
<p class="pulse-state"><b>2026-08-12 인시던트(NAS relay 복구 대기):</b> 공개 API는 health ok·db/engine true·OpenAPI 126·auth 401과 local voice를 유지한다. NAS 프리뷰는 앞선 3/3 <code>degraded·db=true·engine=false</code>에서 15:24 KST local health 3회 타임아웃으로 악화됐고 정적 로그인 화면만 계속 보인다. NAS API의 고정 <code>ENGINE_URL=http://192.168.0.223:9100</code> 대상 listener가 사라졌으며 공개 엔진은 별도 loopback <code>127.0.0.1:9099</code>에서 정상이다. G8 clean-head candidate 112/112·실제 origin 112/112와 rollback receipt는 완료 증거로 보존하지만, 현 NAS runtime은 relay를 source/secret/task에 결속해 복구하고 health 3/3·auth·OpenAPI·assets·실제 회기를 다시 통과할 때까지 DEGRADED다. 자동 재시작·포트 노출·배포는 실행하지 않았다. G7은 별도로 명시 동의 mic·동시 high-water·human evidence가 남는다.</p>
<p class="pulse-state">2026-08-07 공개 DB는 recovered named volume으로 전환했고 원본 container·dump·volume을 보존했다. 2026-08-12에는 휴면 Gradle daemon의 <code>8001</code> 점유·cloudflared/voice sidecar 중단과 PowerShell 5.1 native stderr 조기 종료 결함을 복구했다. DB mutation 전에 fresh custom dump <code>9cbda31e…0ce5</code>(7,532,625 bytes·TOC 1,492)를 고정했다. 공개 API·cloudflared는 detached-clean <code>a73bcd24…</code>·tree <code>b02b3a1b…</code>로 fresh 교체했고 public health 3/3·db/engine true·OpenAPI 126·local voice exact를 통과했다. 로그온·5분 watchdog 두 task도 같은 root/commit/tree/script SHA에 pin해 명시 실행 결과 0을 확인했다. 공개 runtime receipt는 <code>47388d58…9b08</code>, 무마이크 rehearsal evidence는 voice <code>61af2e98…</code>·runtime <code>c6e8670e…</code>·topology <code>89f1cb86…</code>이며 UUID/email literal 0이다. G7은 배포가 아니라 실제 mic·동시 high-water·human evidence만 남은 external GATE다.</p>
@ -343,7 +344,7 @@
<div class="ocol">
<div class="ocol-h">🚧 GO를 막는 블로커 <span class="ct" id="ct-block">0</span></div>
<div class="ostack" data-owner-col="block">
<article class="ocard" data-owner="1"><div class="otop"><span class="otag block">블로커</span><span class="oblocks">Phase 0 마감 · P1 진입</span></div><h3>공개 Google OAuth 실제 <code>/turn</code> 증명</h3><p class="ask">필요: 로그인 가능한 계정으로 storageState 캡처 → <code>public-auth-turn</code> E2E 1회 통과.</p><p class="why">왜 당신인가: 실제 Google 계정 인터랙티브 로그인이라 자동화 불가. (owner 지시로 현재 보류 상태)</p><span class="opt">증거: public-auth.json + public /turn 성공 로그</span></article>
<article class="ocard" data-owner="1"><div class="otop"><span class="otag block">블로커</span><span class="oblocks">Web production 승격</span></div><h3>Cloudflare Pages production 배포 승인</h3><p class="ask">필요: 준비된 <code>99779a6a…fbc8</code> Web 후보를 Cloudflare Pages production에 업로드한다는 명시 승인.</p><p class="why">왜 당신인가: 저장소 코드와 번들을 외부 배포 서비스로 전송하는 운영 변경이다.</p><span class="opt">승인 문구: Cloudflare Pages production 배포 승인</span></article>
<article class="ocard" data-owner="1"><div class="otop"><span class="otag block">게이트</span><span class="oblocks">Phase 3 파일럿 · 데이터</span></div><h3>한신대 데이터/SSO 거버넌스</h3><p class="ask">필요: SSO claim 스키마, 추가 축어록 수급, 미성년 원본 활용동의, 개인정보 처리방침에 대한 한신대/데이터 steward의 written evidence.</p><p class="why">왜 당신인가: 기관 공문·협의 영역. 로컬 문서 골격은 준비됨(<code>hanshin-data-governance-gate.md</code>).</p></article>
</div>
</div>
@ -1086,7 +1087,7 @@
<div class="task-row"><div><span class="task-status s-done">DONE</span></div><div><b>Docker compose 패키징 smoke</b><p>더미 운영 env 기준 fresh compose 기동을 통과했다. API 컨테이너 import 실패, 구현 없는 RAG 사이드카, 로컬 <code>apps/api/.env</code> 이미지 혼입, startup owner-DDL, 빈 <code>admin_engine_config</code> 행 때문에 prod가 죽던 경로를 수정했다. 루트 계산은 <code>app.paths.repo_root()</code>로 모았고, backend requirements는 exact pin으로 고정했다.</p></div><div><b>운영 주의</b><p>패키징은 OK지만 실제 이식 전에는 배포지 <code>infra/.env</code><code>APP_DB_PASSWORD</code>, OAuth client id/secret, <code>OPENAI_API_KEY</code>, <code>SESSION_SECRET</code> 등 소유자 비밀값을 채워야 한다. <code>data/kb</code> live-coaching source pack은 commit 또는 같은 경로 provision이 필요하다. 현재 로컬 env의 <code>ENGINE_MODE=claude_cli</code>와 prod 금지 샘플 TTS 플래그는 운영값으로 쓰면 안 된다.</p></div><div><b>검증</b><p><code>docker compose -f infra/docker-compose.yml config --quiet</code>, API/Web image build, API image <code>.env*</code> 미포함, prod import smoke, fresh <code>docker compose up -d --build</code><code>/api/health</code> 200, preflight <code>OK requirements_pinned/live_coach_kb/env_file</code>.</p></div></div>
<div class="task-row"><div><span class="task-status s-risk">BLOCKED</span></div><div><b>공개 vnet.18ka.net 런타임</b><p><code>vnet.18ka.net</code><code>api-vnet.18ka.net</code>을 정식 공개 도메인으로 허용하도록 코드 경로는 보강했다.</p></div><div><b>산출물</b><p><code>FRONTEND_ORIGIN_MAP</code>, 공개 host별 API 매핑, <code>scripts/start-public-runtime.ps1</code> vnet ingress 옵션</p></div><div><b>블로커</b><p>현재 DNS 미해결, Cloudflare credential의 18ka.net zone 권한 불일치, Google OAuth redirect URI 등록 필요.</p></div></div>
<div class="task-row"><div><span class="task-status s-done">DONE</span></div><div><b>서버 정리 상태</b><p>운영 API와 로컬/Tailnet 테스트 API를 구분해 유지한다.</p></div><div><b>산출물</b><p>8001 prod API, 8000 local API, 8010 Tailnet API, 5173 web, 9099 engine, 20241 cloudflared</p></div><div><b>검증</b><p><code>Get-NetTCPConnection</code> 대상 포트 확인</p></div></div>
<div class="task-row"><div><span class="task-status s-plan">GATE</span></div><div><b>재부팅 후 런타임 재기동</b><p>engine gateway, prod API, cloudflared를 health-check하고 복구하는 watchdog과 Scheduled Task installer는 준비됐다. 아직 DNS가 없는 <code>api-vnet.18ka.net</code>은 기본 watchdog 검사에서 제외해 불필요한 restart loop를 막고, 실제 개통 후 <code>-AdditionalPublicHealthUrls</code>로 명시 추가한다. 남은 것은 실제 Windows 재부팅 후 자동 복구와 authenticated public <code>/turn</code> smoke 증거다.</p></div><div><b>산출물</b><p><code>watch-public-runtime.ps1</code>, <code>install-public-runtime-task.ps1</code>, <code>docs/ops/public-runtime-watchdog.md</code></p></div><div><b>검증</b><p>PowerShell parser OK. 2026-06-30 복구 후 <code>powershell -NoProfile -ExecutionPolicy Bypass -File scripts\watch-public-runtime.ps1 -CheckOnly</code>는 healthy: engine, api, web-preview, cloudflared, public-api. 실제 Windows 재부팅은 아직 미실행.</p></div></div>
<div class="task-row"><div><span class="task-status s-plan">GATE</span></div><div><b>재부팅 후 런타임 재기동</b><p>engine gateway, prod API, cloudflared를 health-check하고 복구하는 watchdog과 Scheduled Task installer는 준비됐다. 아직 DNS가 없는 <code>api-vnet.18ka.net</code>은 기본 watchdog 검사에서 제외해 불필요한 restart loop를 막고, 실제 개통 후 <code>-AdditionalPublicHealthUrls</code>로 명시 추가한다. authenticated public <code>/turn</code>은 완료됐고 남은 것은 실제 Windows 재부팅 후 자동 복구다.</p></div><div><b>산출물</b><p><code>watch-public-runtime.ps1</code>, <code>install-public-runtime-task.ps1</code>, <code>docs/ops/public-runtime-watchdog.md</code></p></div><div><b>검증</b><p>PowerShell parser와 focused 회귀 50/50. detached-clean <code>99779a6a…fbc8</code> task pin·PT1H·IgnoreNew·mutex를 확인하고 watchdog/boot 수동 실행 결과 0을 받았다. 실제 Windows 재부팅은 아직 미실행.</p></div></div>
<div class="task-row"><div><span class="task-status s-done">DONE</span></div><div><b>레이아웃 감사팀 / 전면 레이아웃 개선</b><p>서브에이전트 전담으로 1차 overflow/clipping 수리 후 2차 전면 재설계를 진행했고, 2026-06-28 라운드에서 빈 회기리뷰까지 포함해 7개 권장 너비 시각 수용을 닫았다. 세션, 학습자 홈/리뷰, 교수 콘솔, 관리자, 설정 화면을 작업 화면 기준으로 재배치했고, 과한 빈칸·튀어나감·버튼/텍스트 잘림·모바일 테이블 사용성을 줄였다. 당시 엄격한 시각 게이트 + 화면별 적대적 시각 재검수에서 critical/major 0, 회귀 0을 받아 DONE으로 닫았다.</p></div><div><b>산출물</b><p><code>docs/archive/ops/layout-redesign-handoff-2026-06-26.md</code>, page-by-page redesign patches, <code>apps/web/e2e/layout-visual-gate.spec.ts</code></p></div><div><b>검증</b><p><code>npm run typecheck</code> OK, 최신 엄격 시각 게이트 9 passed, layout focused E2E desktop/mobile 54 passed, 2026-06-28 적대적 시각 재검수 7/7 accept·회귀 0.</p></div></div>
<div class="task-row"><div><span class="task-status s-done">DONE</span></div><div><b>엄격한 레이아웃 시각 게이트 구축 · 병렬 수정 · 적대적 재검수</b><p>핸드오프가 요구한 7개 권장 너비(390/720/861/900/1024/1280/1440) 시각 수용을 자동 게이트로 고정했다. 현재는 빈 회기리뷰 전용 화면까지 9개 화면을 각 너비에서 렌더링해 가로 overflow 0, 컨트롤 하드클립/텍스트클립 0, 다크 테마 캡처를 강제하고 화면당 7장 총 63장 풀페이지 스크린샷을 남긴다. 2026-06-28 당시 화면별 1에이전트 병렬 시각 리뷰로 49장 직접 판독 → 6개 병렬 수정 에이전트(파일 비중첩)가 결함 수정 → 화면별 적대적 재검수로 해소·무회귀를 확정했다.</p></div><div><b>산출물</b><p><code>apps/web/e2e/layout-visual-gate.spec.ts</code>, <code>node_modules/.tmp/layout-gate/*.png</code> 63장, 2× workflow(review/verify)·6× fix agent</p></div><div><b>검증</b><p>최신 게이트 9 passed(재스크린샷). 해소된 핵심 결함: 학습자홈 1280/1440 3열 가운데 컬럼 붕괴(critical → 2열 분기 상향 + word-break:keep-all), 교수 'API 404' raw 배너 제거, 리뷰 빈상태 위계 역전과 1280 sparse third-column, 관리자 스켈레톤, 설정 와이드 좌측 데드존 제거, 세션 모바일 44px 터치타깃. 2026-06-28 적대적 재검수 7/7 accept, regression 0.</p></div></div>
<div class="task-row"><div><span class="task-status s-done">DONE</span></div><div><b>레이아웃 cosmetic minor 폴리시 일괄 처리</b><p>적대적 재검수 잔여 cosmetic minor를 5개 병렬 폴리시 에이전트로 처리했다. 학습자홈 헬퍼문구 고아 글자, 세션 1024 일시정지 아이콘 정리 + 보내기 버튼 대비 강화, 설정 2x2 칩 행 높이 균일, 교수 검토 큐 카드 갭 제거, 관리자 2열 높이 동기화를 적용했다.</p></div><div><b>산출물</b><p>page-by-page polish patches(LearnerHome/Session/Settings/Professor/Admin)</p></div><div><b>검증</b><p><code>npm run typecheck</code> OK, 당시 cosmetic 시각 게이트 7 passed, 최신 통합 시각 게이트 9 passed, 레이아웃 E2E desktop/mobile 54 passed, session-layout 8/8 — 회귀 0.</p></div></div>
@ -1104,7 +1105,7 @@
<tbody>
<tr><td>Web typecheck</td><td><code>npm run typecheck</code></td><td>Passed</td></tr>
<tr><td>Design SSOT / auth visual</td><td><code>npm run check:design-ssot</code> / <code>npx playwright test e2e/auth-visual.spec.ts --project=chromium-single-run --reporter=line</code> / <code>npx playwright test e2e/layout-visual-gate.spec.ts --project=chromium-single-run --reporter=line</code></td><td>SSOT checker passed; login/onboarding light-dark desktop-mobile 1 passed; 14 core screens × 7 widths visual gate 14 passed.</td></tr>
<tr><td>Full Playwright E2E baseline</td><td><code>npm run e2e:parallel</code> / <code>npm run e2e:single-run</code> / <code>npm run e2e:list</code></td><td>2026-08-27 현재 수집은 <b>1136 tests / 62 files</b>다. 이 숫자는 수집량이며 현 작업트리 전체 GREEN과 동일하지 않다. G8 clean-head release gate는 candidate 112/112와 실제 NAS-origin 112/112를 통과했다. 이전 단일 120/120과 2026-07-15의 fixture desktop/mobile 166/166 + DB/engine/provider 직렬 49/49 = 215/215는 범위가 다른 역사 기준선으로 보존한다.</td></tr>
<tr><td>Full Playwright E2E baseline</td><td><code>npm run e2e:parallel</code> / <code>npm run e2e:single-run</code> / <code>npm run e2e:list</code></td><td>2026-08-28 현재 수집은 <b>1138 tests / 62 files</b>다. 이 숫자는 수집량이며 현 작업트리 전체 GREEN과 동일하지 않다. G8 clean-head release gate는 candidate 112/112와 실제 NAS-origin 112/112를 통과했다. 이전 단일 120/120과 2026-07-15의 fixture desktop/mobile 166/166 + DB/engine/provider 직렬 49/49 = 215/215는 범위가 다른 역사 기준선으로 보존한다.</td></tr>
<tr><td>Refactor governance P1~P8</td><td><code>ruff check app</code> / <code>pytest -q app</code> / <code>pytest -q engine_gateway</code> / <code>npm run typecheck</code> / <code>npm run check:api-types</code> / <code>npm run check:design-ssot</code> / <code>npm run check:dead-code</code> / <code>npm run check:duplication</code> / <code>npm run build</code> / <code>npm audit --audit-level=high</code> / full Playwright</td><td>Backend 400 passed, gateway 29 passed, web gates/build/audit passed, vulnerabilities 0, production duplication 1 clone/15 lines/0.03%, Playwright 215/215 passed. 상세 근거는 <code>ops/refactor-governance-2026-07-15.md</code>.</td></tr>
<tr><td>API typegen SSOT</td><td><code>npm run check:api-types</code></td><td>Passed; FastAPI OpenAPI → <code>src/lib/api.gen.ts</code> stale check</td></tr>
<tr><td>Outcome &amp; Alliance OS G0</td><td><code>py -3.11 -X utf8 -m pytest -p no:cacheprovider apps/api/app/test_measurement_contract.py apps/api/app/test_runtime_schema_ssot.py -q</code> / <code>scripts/check-measurement-ledger.sql</code> / measurement·API contract checks / web typecheck / DB-backed <code>session-persistence</code> focused E2E 3종</td><td>G0 contract/schema 11 passed, 기존 backend 100 passed, auth 39 passed. Python→JSON Schema→TypeScript→PostgreSQL enum·필수필드 계약이 일치하고 8개 deterministic benchmark가 검증됐다. Live PostgreSQL에서 learner/client/evaluator 가시 행 1/1/2, 교차 누수 0, append-only guard 2를 확인했다. 학습자 턴→교수자 대시보드, 워크시트 검수, 종료 deep 평가→durable 리뷰 E2E는 각각 1 passed. G0/AOS-001~004 완료.</td></tr>
@ -1201,12 +1202,13 @@
<tr><td>Public OAuth start</td><td><code>/auth/config</code> + <code>/auth/login?provider=google</code></td><td>2026-08-28 public auth config 200, Google configured true, <code>allowed_email_domains=[]</code>, redirect URI <code>https://api-vignette.chanpaca.net/auth/callback</code>, dev-login disabled. 로그인 DOM은 모든 Google 계정을 명시하고 실제 Google 선택기에 <code>yunchan@twentyoz.kr</code><code>yunchan8804@gmail.com</code>이 함께 노출됐다. 기존 Google 계정 선택→callback→<code>/admin</code> 성공을 확인했다. 신규 Gmail 선택은 Vignette 계정 생성이므로 사용자 행동시점 확인 뒤 별도 실증한다.</td></tr>
<tr><td>Persona auth boundary</td><td><code>GET /personas</code></td><td>2026-06-30 복구 후 public unauth <code>/personas</code>는 401 <code>not authenticated</code>를 반환한다.</td></tr>
<tr><td>Public login</td><td><code>auth.spec.ts --grep public login</code></td><td>1 passed</td></tr>
<tr><td>Public runtime scripts · source pin</td><td><code>start/watch/boot-public-runtime*.ps1</code> · <code>install-public-runtime-task.ps1</code> · <code>register-boot-task.ps1</code></td><td>2026-08-28 detached-clean <code>2a396361…89c</code>·tree <code>c26bf816…fef</code>에 로그온·watchdog 두 task를 재등록했다. action working directory/root/commit/tree/SHA pin은 PASS다. watchdog 수동 실행은 Running→Ready, <code>LastTaskResult=0</code>·failcount 0이며 17:12:10 KST engine/API/voice/web/cloudflared/DB/public API 8개 check가 모두 healthy였다. Boot task는 Ready이며 이전 user-terminated 결과 <code>0x41306</code>은 이력으로 남는다. 실제 Windows 재부팅 자동복구 smoke는 별도 운영 gate다.</td></tr>
<tr><td>Public runtime scripts · source pin</td><td><code>start/watch/boot-public-runtime*.ps1</code> · <code>install-public-runtime-task.ps1</code> · <code>register-boot-task.ps1</code></td><td>2026-08-28 detached-clean <code>99779a6a…fbc8</code>·tree <code>57da86aa…6b91</code>에 로그온·watchdog 두 task를 재등록했다. action working directory/root/commit/tree/SHA pin, <code>PT1H</code>, <code>IgnoreNew</code>, scheduler retry 0은 PASS다. focused 회귀 50/50 뒤 watchdog 18:10:57 KST·boot 18:14:27 KST 수동 실행은 모두 <code>LastTaskResult=0</code>, failcount 0이었다. 실제 Windows 재부팅 자동복구 smoke는 별도 운영 gate다.</td></tr>
<tr><td>Public API health</td><td><code>http://127.0.0.1:8001/health</code> / <code>https://api-vignette.chanpaca.net/health</code></td><td>2026-08-28 17:11:47 KST local/public 모두 <code>status=ok·environment=prod·db=true·engine=true</code>. voice는 local/public 모두 <code>local_whisper small</code>·<code>melotts-korean</code>·WS queue 4, web은 local/public 200과 동일 asset <code>index-DJPgoeJy.js</code>/<code>index-CXOy3QyV.css</code>를 반환했다. DB는 백업 <code>vignette-dev-db-vignette-20260828-065331Z.dump</code>를 검증하고 recovered named volume을 보존한 채 migration 17을 적용했다.</td></tr>
<tr><td>Public runtime current snapshot</td><td><code>health + provenance + Scheduled Tasks + Pages</code></td><td>clean source <code>2a396361…89c</code>·tree <code>c26bf816…fef</code>로 API/engine/web/STT/TTS/cloudflared 전 프로세스를 정렬했다. old <code>bf5f7352</code> 참조 runtime은 0개다. Cloudflare Pages production <code>1f1ddf18-9d5c-4d83-95a7-8cd71245e646</code>은 source <code>2a39636</code>이며 current와 이전 5세대 entry/lazy JS·CSS를 custom/preview 양쪽에서 MIME·SHA 일치로 검증했다.</td></tr>
<tr><td>Public runtime current snapshot</td><td><code>health + provenance + Scheduled Tasks + Pages</code></td><td>현재 동작 중인 API/engine/web/STT/TTS/cloudflared와 Cloudflare Pages production <code>1f1ddf18-9d5c-4d83-95a7-8cd71245e646</code> clean source <code>2a396361…89c</code> 계열이다. 다음 장애/로그온 복구 task만 <code>99779a6a…fbc8</code>에 pin했다. 새 학습자 헤더를 포함한 dist는 714파일·assets 164개로 빌드하고 최근 production 5세대를 보존했지만, Pages upload는 명시 승인이 없어 실행하지 않았다.</td></tr>
<tr><td>Public/local/Tailnet login recovery</td><td><code>https://vignette.chanpaca.net/login</code> / <code>https://api-vignette.chanpaca.net/health</code> / <code>https://alpaca-home.taile93291.ts.net/login</code></td><td>2026-08-28 public web 200, public API health 200, auth config 200, Google login start와 callback 성공, P20 실제 회기·응답·종료·평가 폐루프 성공. Earlier Tailnet checks remain recorded separately; vnet DNS A records are still 0.</td></tr>
<tr><td>Local 5175 login</td><td><code>PLAYWRIGHT_BASE_URL=http://127.0.0.1:5175 auth.spec.ts</code></td><td>desktop/mobile passed</td></tr>
<tr><td>Learner/readiness E2E</td><td><code>learner.spec.ts + readiness.spec.ts desktop/mobile</code></td><td>14 passed</td></tr>
<tr><td>Learner growth header</td><td><code>uc-learner-home-dashboard.spec.ts --grep "성장 지표 라포 헤더"</code></td><td>2026-08-28 chromium desktop/mobile 2 passed. 라포 문구 부모를 inset surface에서 plain div로 바꾸고 computed background transparent·border/radius/padding 0을 고정했다. typecheck·design SSOT·cosmetic filter safety도 통과했으며 Pages에는 아직 미배포다.</td></tr>
<tr><td>Learner screenshots</td><td><code>learn-empty-desktop.png / learn-empty-mobile-compact.png</code></td><td>document overflow 0, empty history visible</td></tr>
<tr><td>Session layout/turn</td><td><code>session-layout.spec.ts desktop/mobile</code></td><td>8 passed</td></tr>
<tr><td>Session voice guard/view-model</td><td><code>npm run typecheck</code> / <code>npm run build</code> / <code>npx playwright test e2e/session-mvp.spec.ts --project=chromium-single-run --workers=1</code> / <code>npx playwright test e2e/voice-success.spec.ts --project=chromium-single-run --workers=1</code> / <code>npx playwright test e2e/session-layout.spec.ts --project=chromium-desktop --project=chromium-mobile --workers=1</code></td><td>typecheck/build passed; P1 text MVP 1 passed, voice cascade + Session text/mic UI 2 passed, session-layout desktop/mobile 8 passed. <code>isVoiceStatusBusy()</code> and <code>sessionVoiceStatusView()</code> own mic busy/disabled, aria label, transcript/response/status labels, and text-turn blocking; persisted text-turn replies now share the OpenAI TTS Web Audio lifecycle without changing the recording click-to-send path.</td></tr>
@ -1231,7 +1233,7 @@
<tr><td>Learner session archive</td><td><code>python -B -m pytest app/ -q</code> / <code>python -B -m pytest engine_gateway/ -q</code> / <code>npm run check:api-types</code> / <code>npm run typecheck</code> / <code>npm run build</code> / <code>npx playwright test e2e/learner.spec.ts --project=chromium-desktop --workers=1</code></td><td>Archive 당시 178 backend passed + 11 gateway passed; 최신 gateway contract gate는 27 passed. OpenAPI generated archive DTOs are current; learner history can archive/restore an ended session and keeps archived sessions out of the review queue while preserving records.</td></tr>
</tbody>
</table>
<div class="tab-subhead"><h4>다음 실행 명령</h4><p>남은 public OAuth <code>/turn</code> proof 확보용 명령이다.</p></div>
<div class="tab-subhead"><h4>재검증 명령</h4><p>완료된 public OAuth <code>/turn</code> 증거를 독립 브라우저 상태로 다시 확인할 때 쓰는 명령이다.</p></div>
<div class="commands">
<pre>cd D:\workspace\vignette\apps\web
npx playwright codegen https://vignette.chanpaca.net/login --save-storage=.\node_modules\.tmp\public-auth.json
@ -1243,7 +1245,7 @@ $env:E2E_PUBLIC_STORAGE_STATE=".\node_modules\.tmp\public-auth.json"
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\start-public-runtime.ps1</pre>
</div>
<div class="source-note"><b>닫은 항목(live 증거):</b> ① engine config 운영값(<code>claude_cli / 9099 / gateway-default</code>, durable, db). ② 상주 엔진풀 probe — 단일 session_id 2회 reused stream, TTFT 16674199ms, cost 누적 0.068→0.123. ③ 상주 엔진풀 RSS — gateway session 1개에서 <code>claude -p</code> child RSS 363.3MB, gateway RSS 16.2MB. ④ Postgres RLS/audit smoke 5 checks PASS. ⑤ turn cost telemetry — <code>app.turns</code> client_ai 13행에 provider/model/cost_usd 실적재(합 $1.22). ⑥ 레이아웃 시각 게이트 최신 9/9 + 2026-06-28 적대적 재검수 7/7 accept.</div>
<div class="source-note"><b>환경·외부 승인 때문에 아직 못 닫는 항목(정직 표기):</b> 신규 Gmail 선택→Vignette 계정 생성은 사용자 행동시점 확인 필요 · C-001 외부 임상 검토자 이름·소속 기관·검토일·서면 결정 · <code>vnet.18ka.net</code>/<code>api-vnet.18ka.net</code> DNS·OAuth redirect 등록 · 한신대 데이터/SSO 거버넌스 · G7 명시 동의 물리 마이크 3,120초와 공통 3,000초 운영 high-water, 독립 human voice-gain pack, canonical checker exit 0 · claude_cli↔Messages API 폴백 동일성 · 실제 Windows 재부팅 후 watchdog smoke · Phase 3 파일럿 게이트. current source 공개 배포, generic Google callback, P20 실제 턴·종료·평가, local/public voice exact ready, authenticated WSS 무마이크 rehearsal은 완료했다. 운영 원칙상 가짜 증거로 DONE 표기하지 않는다.</div>
<div class="source-note"><b>환경·외부 승인 때문에 아직 못 닫는 항목(정직 표기):</b> 새 학습자 헤더 Cloudflare Pages production upload 명시 승인 · 신규 Gmail 선택→Vignette 계정 생성은 사용자 행동시점 확인 필요 · C-001 외부 임상 검토자 이름·소속 기관·검토일·서면 결정 · <code>vnet.18ka.net</code>/<code>api-vnet.18ka.net</code> DNS·OAuth redirect 등록 · 한신대 데이터/SSO 거버넌스 · G7 명시 동의 물리 마이크 3,120초와 공통 3,000초 운영 high-water, 독립 human voice-gain pack, canonical checker exit 0 · claude_cli↔Messages API 폴백 동일성 · 실제 Windows 재부팅 후 watchdog smoke · Phase 3 파일럿 게이트. current source 공개 배포, generic Google callback, P20 실제 턴·종료·평가, local/public voice exact ready, authenticated WSS 무마이크 rehearsal은 완료했다. 운영 원칙상 가짜 증거로 DONE 표기하지 않는다.</div>
</div>
<div class="tab-panel" id="panel-decisions" role="tabpanel" aria-labelledby="tab-decisions" hidden>
<div class="detail-head"><div><h3>윤찬 결정 상세 (전건 확정)</h3><p>람다가 단독으로 정하면 월권인 항목이었다. 2026-06-30 owner 결정으로 전건 확정됐고, 각 결정의 구현·실측은 후속 build/GATE로 남는다.</p></div><div class="mini-metrics"><span>결정 0개(전건 확정)</span><span>조건부 GO 사유</span></div></div>

View file

@ -20,7 +20,7 @@ Vignette 저장소의 모든 검증 수단(백엔드 단위 테스트, 웹 타
| API 타입 생성 체크 | `apps/web` | `npm run check:api-types` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass |
| 웹 타입체크 | `apps/web` | `npm run typecheck` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass |
| 웹 빌드 | `apps/web` | `npm run build` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass |
| Playwright E2E(전체) | `apps/web` | `npm run e2e` | **필요(+시드)** | **필요** | 자동기동 | 일부만 | **필요** | 현재 수집 1136 tests / 62 files · 현 작업트리 전체 GREEN 미검증 |
| Playwright E2E(전체) | `apps/web` | `npm run e2e` | **필요(+시드)** | **필요** | 자동기동 | 일부만 | **필요** | 현재 수집 1138 tests / 62 files · 현 작업트리 전체 GREEN 미검증 |
핵심 원칙: **단위 테스트(pytest)와 타입체크/빌드는 외부 서비스 없이 단독 실행된다.**
**E2E만 풀스택(DB+API+웹+브라우저)을 요구한다.** 아래 각 절에서 근거와 절차를 설명한다.
@ -96,9 +96,10 @@ python -m pytest engine_gateway/ --collect-only -q
| REQ-006 | `app/test_pii_masking_eval.py app/test_live_coach_sources.py app/test_client_reply_quality.py` | 24 passed — raw prompt와 구조화 결과의 counselor/client role masking |
| REQ-007 | session persistence/evaluation 관련 API 9 files, live/session 묶음, 실제 DB persistence E2E | 163 + 50 pytest, DB E2E 1 passed — 실패한 옛 평가 뒤 새 회기 가능 |
| REQ-008 | `app/test_engine_health_contract.py`와 session stream 회귀 | health contract 1 passed; incomplete EOF는 live/session 50 묶음에 포함 |
| 학습자 성장 패널 헤더 | `uc-learner-home-dashboard.spec.ts --grep "성장 지표 라포 헤더"` + `check:design-ssot` + `check:cosmetic-filter-safety` + typecheck | chromium desktop/mobile 2 passed — 선택된 라포 문구의 부모는 plain `div`, 배경 transparent·border/radius/padding 0이며 주변 panel 구조는 유지 |
| REQ-001 공개 운영 | `https://vignette.chanpaca.net/login` + Google account chooser/callback | 로그인 DOM ‘모든 Google 계정’, `allowed_email_domains=[]`, twentyoz.kr/Gmail 동시 노출, 기존 Google 계정 callback→`/admin` 성공. 신규 Gmail 선택은 계정 생성 행동시점 확인 뒤 별도 실행 |
| REQ-005·007·008 공개 운영 | P20 회기 `03dddadd-adf3-4922-acbf-31002470da52` | 생성→자기점검 원장 잠금→실제 학습자/AI 내담자 2턴→종료→AI 평가 완료→P20 1회 기록 영속→다음 회기 버튼 재노출 |
| 운영 배포 | clean `2a396361…89c`, Pages `1f1ddf18-9d5c-4d83-95a7-8cd71245e646`, watchdog | local/public prod·db·engine·voice·web 정상, old-root runtime 0, watchdog 8 checks·LastTaskResult 0·failcount 0 |
| 운영 배포·복구 | live clean `2a396361…89c`, Pages `1f1ddf18-9d5c-4d83-95a7-8cd71245e646`; recovery task `99779a6a…fbc8` | local/public prod·db·engine·voice·web 정상. recovery root/tree/script pin, 60분·IgnoreNew·mutex·hard-down 즉시복구 계약 50 passed; watchdog·boot 수동 실행 결과 0. 실제 Windows 재부팅 smoke와 새 Pages 승격은 미실행 |
로컬 Playwright는 기존 포트의 서버를 기본 재사용하지 않는다. 공개 preview나 다른 checkout의 stale bundle을
현 작업트리 증거로 오인하지 않도록 충돌 시 fail-closed하며, 동일 dev server를 의도적으로 공유할 때만
@ -303,7 +304,7 @@ VITE_API_BASE=http://127.0.0.1:8000 npm run e2e # 프록시 대신 API
### 3.6 실측 테스트 개수 (현재)
2026-08-27 `npx playwright test --list` 기준 **현재 수집 1136 tests / 62 files**다
2026-08-28 `npx playwright test --list` 기준 **현재 수집 1138 tests / 62 files**다
(유스케이스 16테마 `uc-*.spec.ts` 239 시나리오 포함).
이 숫자는 수집량이지 통과량이 아니다. 현 작업트리 전체 1109개 완주는 아직 증거가 없으며,
과거 전체 GREEN 기록과 이번 focused/release gate 결과를 구분해 적는다.

View file

@ -12,8 +12,9 @@
> 섹션과 상세 근거 `docs/ops/source-docs-gap-analysis-2026-06-26.md`에서 추적한다. C1~C3/H·M 구조는 코드로
> 선제 구축했고, 임상 문안·평가기준·골든셋 콘텐츠는 임상팀(구훈정·어유경) 외부 정의로 받는다.
>
> **개선관리 워크북(2026-08-28)** — C-002·C-003과 REQ-001~008은 내부 기술 구현 DONE이며 clean
> `2a396361…89c`/Pages `1f1ddf18…e646`, generic Google callback, 공개 P20 생성→응답→종료→평가 폐루프까지
> **개선관리 워크북(2026-08-28)** — C-002·C-003과 REQ-001~008은 내부 기술 구현 DONE이며 live clean
> `2a396361…89c`/Pages `1f1ddf18…e646`, recovery task `99779a6a…fbc8`, generic Google callback,
> 공개 P20 생성→응답→종료→평가 폐루프까지
> 운영 실증했으므로 열린 백로그에 중복하지 않는다. C-001은 자동 안전 게이트의 기술 사전검증만 완료됐고
> 임상 검토자 이름·소속 기관·검토일·서면 결정이 없어 B4 외부 GATE로 유지한다. 네 값이 모두 기록되기 전에는
> 완료로 닫지 않는다.
@ -66,8 +67,9 @@
내부 토큰 6개, 필수 운영키, DB `current_user=vignette` non-owner app-role preflight와 공개 health를 통과했다.
향후 Compose 패키징 전환 시 `APP_DB_PASSWORD` 등 패키징 비밀과 prod-safe engine/voice flags를 별도 주입하고
compose profile preflight를 다시 닫는다.
- [ ] **공개 Google OAuth 실제 `/turn` proof** — 로그인 가능한 계정으로 `storageState` 캡처 후 `E2E_PUBLIC_AUTH=1`
+ `chromium-public-auth` 1회 통과 필요. (소유자 지시로 보류 중.) 실행 명령은 대시보드 "다음 실행 명령" 참조.
- [x] **공개 Google OAuth 실제 `/turn` proof** — 2026-08-28 기존 Google 세션 callback→관리자 진입과 공개 P20
회기 생성→자기점검 잠금→실제 학습자/AI 내담자 턴→종료→리뷰·평가→다음 회기 버튼 재노출을 브라우저로
확인했다. 신규 Gmail 선택은 별도의 Vignette 계정 생성 행동시점 확인 항목이다.
- [ ] **음성 캐스케이드 live** — 공개 G7 API route와 TLS 1.3 WSS handshake, 비인증 1008 차단, 로컬
synthetic short soak는 통과했다. Deepgram/OpenAI fallback adapter와 운영 기본 `local_whisper`/`melotts`의 interim/final/word timestamp, HMAC word pseudonym,
streaming 중 1초 동의 재검사, 공통 consent transaction lock, bounded queue/10MiB cap, 텍스트 보존·음성 재연결
@ -116,20 +118,22 @@
- [ ] **stable-source 재부팅 후 watchdog smoke** — 2026-08-27 Docker Desktop 4.82.0이 stale
`dockerInference`/`engine.sock` AF_UNIX reparse socket(ERROR 1920)에서 crash-loop한 사건은 두 부모 IPC
디렉터리를 `.stale` 백업명으로 이동한 뒤 정상 복구했다. container·image·volume은 생성/삭제/교체하지 않았고,
기존 `vignette-dev-db`와 recovered volume만 재기동했다. watchdog·로그온 boot는 detached-clean
`bf5f7352…0092`·tree `c39f917b…c88`와 exact commit/tree/script SHA에 재등록했으며, watchdog
`LastTaskResult=0`·failcount `0`, public health 3/3 `status=ok·db=true·engine=true`, 실제 로그인 브라우저
console error/warning 0을 확인했다. 남은 것은 실제 Windows 재부팅 후 엔진/API/터널 복구와 authenticated
public `/turn` 실측이다. DNS 개통 후 `api-vnet.18ka.net``-AdditionalPublicHealthUrls`로 명시 추가한다.
기존 `vignette-dev-db`와 recovered volume만 재기동했다. 2026-08-28 watchdog·로그온 boot는 detached-clean
`99779a6a…fbc8`·tree `57da86aa…6b91`와 exact commit/tree/script SHA에 재등록했다. 두 작업의 60분 상한·
`IgnoreNew`, launcher mutex·bounded readiness/build·process-tree 종료, hard-down 즉시복구를 focused 50/50으로
검증했고 watchdog 18:10:57 KST·boot 18:14:27 KST 수동 실행 `LastTaskResult=0`·failcount 0을 확인했다.
public P20 authenticated `/turn` 폐루프도 완료됐다. 남은 것은 실제 Windows 재부팅 후 엔진/API/터널 복구다.
DNS 개통 후 `api-vnet.18ka.net``-AdditionalPublicHealthUrls`로 명시 추가한다.
상세: `docs/ops/public-runtime-watchdog.md`.
---
## B3. 소유자(윤찬) 결정 — 전건 확정(2026-06-30)
- [ ] **공개 Web 후보 Pages 승격 승인**`00f851a6…c229`·tree `9f78cd16…9486`의 deterministic build와
focused E2E 12/12, 현행/최근 Pages 자산 133개 보존은 완료됐다. 실제 공개와 NAS에는 아직 배포하지 않았다.
승인 시 Pages Web만 승격하고 공개 API/DB·task·NAS runtime은 범위 밖으로 유지한다.
- [ ] **공개 Web 후보 Pages 승격 승인**`99779a6a…fbc8`·tree `57da86aa…6b91`의 production build와
학습자 라포 헤더 desktop/mobile focused E2E 2/2, 현행 포함 최근 production 5세대 자산 보존(최종 dist
714파일·assets 164개)은 완료됐다. 실제 Pages upload는 코드 외부 전송 명시 승인이 없어 중단했다.
`Cloudflare Pages production 배포 승인`을 받으면 Pages Web만 승격하고 공개 API/DB·task·NAS runtime은 건드리지 않는다.
> 7건(평가설계 H1 κ/ICC·환각률, s2s 2차 PoC 채택, 페르소나 음성 모델·권리, fast-loop 외부 API 허용,
> 재귀학습 fine-tuning 범위, 운영 보존기간·에스컬레이션, 추가 축어록 수급 20건/1개월)은 **전건 확정**됐다.