diff --git a/apps/web/src/pages/AvatarPreview.tsx b/apps/web/src/pages/AvatarPreview.tsx
index b55a85e..dc6b6ec 100644
--- a/apps/web/src/pages/AvatarPreview.tsx
+++ b/apps/web/src/pages/AvatarPreview.tsx
@@ -16,7 +16,7 @@ const SEOYEON: AvatarPersona = {
outfitColor: "#7C8A92",
eyeColor: "#7A5A3C",
accentColor: "#6B5E7D",
- rasterArtSet: "seoyeon",
+ rasterArtSet: "seoyeon-live2d-psb",
realism: 0.4,
expressionBias: "sad",
};
@@ -42,8 +42,8 @@ export default function AvatarPreview() {
const previewPersona: AvatarPersona = {
...SEOYEON,
rasterArtSet:
- rig === "psb"
- ? "seoyeon-live2d-psb"
+ rig === "safe"
+ ? "seoyeon"
: rig === "v3"
? "seoyeon-live2d-v3"
: SEOYEON.rasterArtSet,
@@ -53,7 +53,7 @@ export default function AvatarPreview() {
서연 아바타 미리보기 (raster / Live2D식)
diff --git a/apps/web/src/pages/Session.tsx b/apps/web/src/pages/Session.tsx
index 8b87f9c..325ab4b 100644
--- a/apps/web/src/pages/Session.tsx
+++ b/apps/web/src/pages/Session.tsx
@@ -110,7 +110,7 @@ const PERSONA_AVATAR_LOOKS = {
outfitColor: "#7C8A92",
eyeColor: "#7A5A3C",
accentColor: "#6B5E7D",
- rasterArtSet: "seoyeon",
+ rasterArtSet: "seoyeon-live2d-psb",
expressionBias: "sad",
},
P4: {
diff --git a/docs/dev_dashboard.html b/docs/dev_dashboard.html
index 461bd1d..0e9eb23 100644
--- a/docs/dev_dashboard.html
+++ b/docs/dev_dashboard.html
@@ -589,7 +589,7 @@
BLOCK
공개 Google OAuth 실제 /turn proof 확보로그인 가능한 계정으로 storageState를 저장한 뒤 public-auth-turn E2E를 실행한다.
산출물apps/web/node_modules/.tmp/public-auth.json, public /turn 성공 로그
검증E2E_PUBLIC_AUTH=1 + chromium-public-auth 1회 통과
DONE
engine config 운영값 재확인GET /admin/engine-config로 운영값을 직접 확인했다. engine_mode=claude_cli, engine_url=http://127.0.0.1:9099, model=gateway-default, durable=true, source=database로 의도값과 일치한다.
산출물config API 응답(durable, db source)
검증claude_cli / http://127.0.0.1:9099 / gateway-default 의도값 대조 완료
-
DONE
과거 Live2D demo 자산 제거Mao/Haru 샘플, Pixi/Cubism 런타임, 공개 /live2d/* 캐시 잔여 접근을 차단했다.
산출물apps/web/functions/live2d/[[path]].js, SVG-only avatar
검증운영 /live2d/mao/*, Cubism core 404
+
DONE
과거 Live2D demo 자산 제거Mao/Haru 샘플, Pixi/Cubism 런타임, 공개 /live2d/* 캐시 잔여 접근을 차단했다.
산출물apps/web/functions/live2d/[[path]].js, P1 PSB raster avatar + SVG fallback
검증운영 /live2d/mao/*, Cubism core 404
DONE
프로세스 난립 정리임시 Vite preview와 dev API를 내리고 운영 확인용 프로세스만 유지한다.
산출물9099 engine, 8001 prod API, cloudflared tunnel 1개
검증Get-NetTCPConnection에서 8000/517x/5537 비어 있음
GATE
한신대 공문/데이터 거버넌스 게이트 정리SSO 클레임, 추가 축어록 수급, 미성년 원본 활용동의, 개인정보 처리방침을 P1 진입 전 외부 의존성으로 명확히 둔다. 로컬 문서 골격은 준비됐지만 한신대/데이터 steward의 written evidence는 아직 필요하다.
산출물docs/ops/hanshin-data-governance-gate.md, 공문 질의 항목, 동의 범위 체크리스트, SSO claim mapping 표
검증문서 artifact 작성 완료; IRB 게이트가 아니라 데이터/SSO 게이트로 외부 증거 필요 상태 유지
@@ -613,7 +613,7 @@
DONE
음성 실패 턴 미저장음성 회기도 엔진 응답 생성 성공 후에만 learner/client turn을 저장한다. 실패한 transcript는 pending 상태에서 제거한다.
산출물voice failure persistence guard
검증voice + voice-success + session-layout 15 passed
DONE
비영구 상태 문구 정리admin health와 voice degraded reason은 내부 fallback/seed 표현 대신 비영구 런타임 상태를 사용자용 문구로 표시한다.
산출물operator-facing copy cleanup
검증settings/admin focused E2E 통과
DONE
직접 URL persona 차단/learn/session/:code로 직접 들어와도 DB 원본 persona가 아니면 회기 시작을 막는다.
산출물route guard, degraded/seed fallback regression
검증unavailable persona code E2E 통과
- DONE
demo Live2D 자산 제거Mao/Haru 샘플과 Pixi/Cubism 런타임을 공개 배포물에서 제거했다. 세션 화면은 SVG persona avatar만 렌더링한다.
산출물SVG-only avatar, legacy /live2d/* 404 function
검증Mao/Haru/Cubism core routes 404, no Live2D/Pixi chunks
+ DONE
demo Live2D 자산 제거Mao/Haru 샘플과 Pixi/Cubism 런타임을 공개 배포물에서 제거했다. 세션 화면은 P1 PSB raster avatar와 SVG fallback을 렌더링한다.
산출물P1 PSB raster avatar, SVG fallback, legacy /live2d/* 404 function
검증Mao/Haru/Cubism core routes 404, no Live2D/Pixi chunks
diff --git a/docs/ops/handoff-avatar-seoyeon-2026-06-27.md b/docs/ops/handoff-avatar-seoyeon-2026-06-27.md
index 725273d..9dd043c 100644
--- a/docs/ops/handoff-avatar-seoyeon-2026-06-27.md
+++ b/docs/ops/handoff-avatar-seoyeon-2026-06-27.md
@@ -3,6 +3,8 @@
> 다른 세션에서 이어서 작업하기 위한 인계. imagegen(gpt-image-2)+BiRefNet+파츠 분리 리깅 파이프라인 전체를 여기서 참조.
> 상세 원칙은 `CLAUDE.md` §4.
+> 2026-06-27 추가: PSB 레이어 기반 최신본은 `master` 기본 P1 아바타로 연결됐다. 실제 세션과 `/dev/avatar-preview` 기본값은 `rasterArtSet="seoyeon-live2d-psb"`이고, 기존 `seoyeon` 세트는 `/dev/avatar-preview?rig=safe` fallback으로만 확인한다.
+
---
## 0. 한 줄 요약
@@ -30,10 +32,10 @@
- 28표정→클러스터 매핑(`VARIANT_FOR_EXPRESSION`) 내장.
- **연결 배선**:
- `persona.ts`: `AvatarPersona.rasterArtSet?: string` 추가됨.
- - `Session.tsx`: `PERSONA_AVATAR_LOOKS.P1 = { rasterArtSet: "seoyeon", expressionBias: "sad", ... }` + avatar 객체에 `rasterArtSet` 전달.
+ - `Session.tsx`: `PERSONA_AVATAR_LOOKS.P1 = { rasterArtSet: "seoyeon-live2d-psb", expressionBias: "sad", ... }` + avatar 객체에 `rasterArtSet` 전달.
- `ClientAvatar.tsx`: `useRaster` 분기(rasterArtSet 있으면 `RasterBust`, 없으면 기존 SVG). `data-render-mode` 속성 추가.
- `App.tsx`: `/dev/avatar-preview` 라우트(인증 없음).
-- **dev 미리보기**: `apps/web/src/pages/AvatarPreview.tsx`(서연 220px, speaking/sad·idle/sad·listening/warm·thinking/anxious).
+- **dev 미리보기**: `apps/web/src/pages/AvatarPreview.tsx`(기본 PSB 최신본, `?rig=safe` 기존 safe 세트, `?rig=v3` atlas 세트).
- **스크린샷 도구**: `apps/web/scripts/avatar-shot.mjs` (`BASE_URL=http://localhost:
node ...`).
- **현재 에셋(Image #1=긴 머리 버전)**: `apps/web/public/avatar/seoyeon/{neutral,sad,tired,anxious,warm,startled,eyes-closed,speaking}.png` + `parts/`. → Image #2 재생성 시 덮어쓰기.
@@ -49,7 +51,7 @@
## 4. 환경 메모
- **dev 서버**: 5173 단일 인스턴스로 띄움(백그라운드). 끊기면 `cd apps/web && npm run dev -- --port 5173 --strictPort`. (5173/5174 중복 인스턴스가 "깨진 화면" 원인이었음 — 항상 5173 단일로.)
- codex CLI 0.142.2, auth_mode=chatgpt(구독). object-separation venv: `~/.venvs/object-separation` (CPU-only BiRefNet).
-- 서연=P1은 API 시드(`apps/api/app/services/persona.py`). 웹엔 P1이 `PERSONA_AVATAR_LOOKS`에 있고 rasterArtSet="seoyeon".
+- 서연=P1은 API 시드(`apps/api/app/services/persona.py`). 웹엔 P1이 `PERSONA_AVATAR_LOOKS`에 있고 rasterArtSet="seoyeon-live2d-psb".
## 5. 미해결/결정 필요
- Image #2 캐릭터의 **의상 색/추가 디테일** (비전 도구 불안정 → 사용자 확인 필요).