G8 마지막 게이트인 receipt-bound 실제 image rollback을 격리 NAS vignette-preview-20260807 에서 실행해 종료했다. Gate6 계약 정정: 감사 대상 current API 이미지가 com.docker.compose.project/service/version image label 을 갖고 있어 "helper 의 compose label 0개" 계약은 감사되지 않은 다른 이미지를 쓰지 않는 한 성립하지 않는다. 계약을 key 부재가 아니라 소속(membership) 으로 바꿔 launch-nas-preview-g8-helpers.py 에 구현했다. image 상속 label 을 baseline 으로 읽고 container 의 모든 compose label 이 baseline 과 같거나 선언된 격리 override 인지 검사하며, 최종 project 는 target 이 아니고 service 는 api/web/db/proxy 가 아니어야 한다. docker run argv 에 target label 을 주입하면 fake-runner 테스트가 먼저 깨진다 (37/37). 실행 결과: - rollback-old receipt nas-g8-723eeef22eab05e63e3fafb0 -> 79ec../c530.. - restore-current receipt nas-g8-2738846cf2cf4fbe8ce0fc26 -> 52e0../6fdb.. - release gate/approval 각 2회 멱등, audit.ci_lifecycle_event rollback/executed 2, audit.ci_human_approval_event authorize_rollback 2, silent auto-promotion 0 - HMAC journal 6-record 체인 검증, health 3/3, OpenAPI 126, auth 401, Web 200 - helper 0, listener 0, 비밀 env 파기. down/volume rm/prune 미실행, 공개 런타임 미접촉 - 계획했던 Windows SSH 터널은 NAS sshd 가 direct-tcpip 를 거부해 사용할 수 없어 sshd 설정 변경 대신 같은 격리 계약의 NAS-side probe 컨테이너로 실행했다 비-secure origin 크래시 수정: 배포된 NAS 프리뷰(평문 HTTP, 비-localhost)에 회기 스펙을 돌려 24건 실패를 확인했고 원인은 하나였다. crypto.randomUUID 는 secure context 전용인데 제품 코드 18곳이 fallback 없이 호출했고 RuptureRepairCard 는 렌더 시점 호출이라 회기 리뷰 라우트 전체가 error boundary 로 떨어졌다. 릴리스 게이트 108/108 은 localhost 후보 스택에서만 돌아 이 경로를 밟은 적이 없다. src/lib/uuid.ts 의 randomUuid() 로 통일하고 fallback 도 crypto.getRandomValues 를 우선 사용해 idempotency key 의 예측 불가능성을 유지했다. 회귀는 insecure-context-uuid.spec.ts 6/6 으로 고정했다(직접 호출 0건 검사 포함). 이 수정은 아직 NAS 에 배포하지 않았다. 검증: API 898, gateway 58, executor 28, probe 11, helper launcher 37, release agent 21, ruff clean, web api-types/typecheck/build, SSOT FAIL 0, SSOT unit 5/5, dashboard E2E 10/10, 학생 폐루프 실 DB 브라우저 4/4(일회용 클론), crypto 수정 후 기존 스펙 회귀 70/70, 복원된 NAS 실제 브라우저 SSE->DB 리뷰 PASS. 부수 발견(열린 항목): 공개 API 가 engine=false 로 degraded 인데 워치독이 이를 감지하지 못한다. engine 판정이 게이트웨이 /health 의 ok 만 보고 claude readiness probe 를 돌리지 않기 때문이다. 같은 .env 와 같은 CLI 로 새 게이트웨이를 다른 포트에 띄우면 즉시 ready 이므로 상주 프로세스의 세션만 죽은 형태다. TODO A절과 대시보드에 기록했다. 이 커밋은 파일 단위로 담겼다. 위 파일들에는 이전 세션의 미커밋 G0~G8 작업이 함께 들어 있으며, hunk 를 쪼개면 대시보드/체커/TODO 정합성이 깨져 SSOT 체커가 실패한다. |
||
|---|---|---|
| .codex-remote-attachments | ||
| .github/workflows | ||
| apps | ||
| data | ||
| docs | ||
| infra | ||
| scripts | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| AGENT.md | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| README.md | ||
Vignette 저장소 README
Vignette — AI 심리상담 시뮬레이션 훈련 플랫폼. 한신대학교 산학협력(구훈정 교수) 프로젝트. 상담 수련생(학습자)이 AI 내담자 페르소나와 회기를 진행하고, 백그라운드 평가 엔진이 회기 리뷰 피드백을 제공한다. "임상 비네트(사례 삽화)"로 안전하게 연습한다는 의미에서 Vignette.
핵심 구성: 페르소나 엔진(persona_repository, SEED P1~P3) · 이론모드(humanistic 등) ·
오케스트레이터(services/orchestrator.py, prepare_turn/run_turn_generate, eval_hook/log_hook 주입형) ·
저항엔진(state_machine openness) · 마스킹 게이트(PII, Presidio + 정규식) ·
음성 캐스케이드(STT/TTS, voice.py) · 회기 리뷰(evaluator.py deep-loop + make_eval_hook fast-loop) ·
평가 KPI(SUS·자기효능감·κ/ICC·환각률) · 재귀학습(ds.* 스키마) · 데이터/SSO 거버넌스(saml.py, auth allowlist) ·
회기 리뷰 공유 URL(공개 토큰 + Open Graph/요약 카드) · SEO/GEO 정적 메타(robots.txt, sitemap.xml, llms.txt).
AI 턴 생성 엔진은 별도 서비스인 engine_gateway(포트 9099)가 담당하며
ENGINE_MODE로 백엔드를 고른다(claude_cli / claude_api / openai / solar).
저장소(SoR)는 PostgreSQL 16 + pgvector 단일 출처, 미가용 시 store.py 인메모리 degraded 폴백.
1. 모노레포 구조
| 경로 | 설명 |
|---|---|
apps/api/ |
FastAPI/Python 백엔드. 오케스트레이터·페르소나·저항엔진·마스킹·음성·평가·인증. 엔진 게이트웨이(apps/api/engine_gateway/) 포함 |
apps/web/ |
React 19 + Vite 프론트엔드(3역할: 관리자/교수자/학습자). Playwright E2E |
docs/ |
설계·운영 문서. docs/dev_dashboard.html이 SSOT(단일 진실 공급원) |
infra/ |
Docker Compose 스택(db=pgvector pg16, api, web, proxy=Caddy) 및 .env.example |
scripts/ |
운영 스크립트(PowerShell/Python): 공개 런타임 기동·감시, 엔진 게이트웨이 프로브, Postgres RLS 감사 등 |
2. 빠른 시작 (로컬 dev)
주 개발 환경은 Windows 11 + PowerShell. 아래는 PowerShell 기준 최소 명령이다. (엔진 게이트웨이가 없어도 UI·로그인·페르소나·세션 생성(in-memory)·네비게이션은 동작하며, 실제 AI 턴 생성만 실패한다. DB가 없어도 인메모리 degraded로 기동된다.)
2-1. API 백엔드
cd apps\api
# 로컬 dev 기본값 복사 (pydantic-settings가 apps/api/.env 를 자동 로드)
Copy-Item ..\..\.env.example .env
# (선택) seed 페르소나가 필요하면 기동 전에 환경변수 설정
$env:AUTO_SEED_PERSONAS = "true"; $env:ALLOW_SEED_PERSONA_FALLBACK = "true"
python -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload
- 기동 로그에
Application startup complete가 뜨면 정상. DB 연결 실패 시store인메모리 degraded로 기동되고GET /health는{"status":"degraded","db":false,...}를 반환한다. - dev 로그인 활성 조건:
.env에ENVIRONMENT=dev,AUTH_DEV_LOGIN_ENABLED=true(루트.env.example기본값에 이미 포함).
2-2. Web 프론트엔드
cd apps\web
npm install
npm run dev # http://localhost:5173
- Vite dev 서버는
/api요청을http://127.0.0.1:8000으로 프록시하고/api프리픽스를 제거한다 (예:/api/auth/dev-login→ 백엔드/auth/dev-login).
2-3. dev-login 으로 진입
웹 UI의 로그인 화면에서 dev-login 경로로 들어가거나, 직접 호출한다.
# 웹 프록시 경유 (web dev 서버가 떠 있을 때)
curl -X POST http://localhost:5173/api/auth/dev-login `
-H "Content-Type: application/json" `
-d '{"email":"learner@hs.ac.kr","role":"learner","display_name":"테스트 학습자"}'
- 요청 바디:
email(필수),role(learner|teacher|admin, 기본learner),display_name(선택). - 성공 시
__Host-vignette_sid세션 쿠키가 발급된다. - 로그인 후 신규 사용자 또는 온보딩 미완료 사용자는
/onboarding에서 닉네임, 자기소개, 선택 아바타 이미지, 이름, 소속, 학과, 학년/직위, 전화번호, 주소/수령지와 약관·개인정보 동의를 완료해야 역할 홈과 학습 회기 시작이 열린다.
2-4. (선택) AI 턴 생성용 엔진 게이트웨이
ENGINE_MODE=claude_cli 인 경우 호스트에서 게이트웨이를 9099 포트로 띄운다(claude CLI 사용).
cd apps\api
uvicorn engine_gateway.gateway:app --host 0.0.0.0 --port 9099
게이트웨이가 없으면 GET /health 의 engine:false 이고 턴 생성만 실패한다.
2-5. 테스트 / 검증
# 백엔드
cd apps\api; python -m pytest app/ -q # 백엔드 기준선 400 pass
python -m pytest engine_gateway/ -q # 현재 29 pass
# 프론트엔드
cd apps\web; npm run typecheck # tsc -b
npm run build # tsc -b && vite build
npm run e2e # Playwright (web + api + DB 스택 필요)
2-6. (선택) Docker Compose 전체 스택
cd infra
Copy-Item .env.example .env # 실제 시크릿은 .env 에만
docker compose up -d # db(pgvector pg16) + api + web + proxy(Caddy)
Docker Desktop이 필요하다. RAG 모델 의존성까지 API 이미지에 넣을 때만 INSTALL_RAG=true를 infra/.env에 둔다.
다른 환경에 심기 전에는 저장소 루트에서 python scripts\check-deploy-preflight.py --env-file infra\.env를 먼저 실행해
고정 의존성, 라이브 코칭 data/kb source pack, 운영 env를 확인한다.
3. 주요 문서
| 문서 | 용도 |
|---|---|
docs/README.md |
문서 인덱스(먼저 여기서 시작) — docs 전체 통합 목차 |
docs/TODO.md |
할 일(안된 것들) 통합 — 흩어진 열린 작업을 주제별로 모은 인덱스 |
docs/dev_dashboard.html |
SSOT(단일 진실 공급원) — 상태·검증 증거·결정 필요·로드맵의 권위 기준 |
docs/ops/backlog-2026-06-26.md |
운영 백로그 — 열린 항목만 얇게 유지(B1~B4·Phase3 게이트). 대시보드와 일치 |
docs/archive/ |
냉동 보관소 — 완료 기록·실행된 계획·일회성 스냅샷. 평상시 읽지 않음(이력용) |
docs/guides/source-docs-and-gaps.md |
원천문서·갭 로드맵 요약(대시보드 상태와 동기화) |
docs/ops/source-docs-gap-analysis-2026-06-26.md |
원천문서 갭 분석 상세 근거 |
docs/guides/local-development.md |
로컬 개발 환경 구축·실행 상세 가이드 |
docs/guides/architecture.md |
시스템 아키텍처(엔진/오케스트레이터/저항/마스킹/음성/평가/데이터) 상세 |
docs/guides/testing.md |
테스트·검증(pytest, typecheck, Playwright E2E 게이트) 가이드 |
AGENTS.md |
작업·에이전트 운영 지침의 원본(OS 선파악, 증거 정직성, SSOT 동기화). CLAUDE.md / AGENT.md는 호환성 진입점 |
참고 설계 문서: docs/MASTERPLAN.md(마스터플랜) · docs/HANDOFF.md(인수인계) ·
docs/DEPLOYMENT.md(배포) · docs/DESIGN_CONCEPT.md(디자인 컨셉) ·
docs/MEMORY_KNOWLEDGE_PERSONA_DESIGN.md(메모리·지식·페르소나).
4. 핵심 운영 원칙
- OS를 먼저 파악하고 시작한다(최우선). 주 환경은 Windows 11 + PowerShell.
POSIX를 가정하지 말고 경로·인코딩·도구 가용성을 먼저 확정한다(한글·공백 경로 주의,
파일 출력은
-Encoding utf8). 자세한 내용은AGENTS.md규칙 0. - 가짜 증거로 DONE 표기 금지. 실증 불가/외부 의존/소유자 결정 항목은
docs/ops/backlog-*.md에 분류·추적하고, 변경 후 검증(typecheck / pytest / E2E 게이트)을 실제로 돌려 결과를 그대로 보고한다. docs/dev_dashboard.html이 SSOT. 새 발견·작업 결과·상태 변경은 별도 문서로만 남기지 말고 대시보드에 반영·동기화한다. 백로그가 대시보드와 어긋나면 대시보드를 기준으로 맞춘다.- 소유자(윤찬) 단독 결정 사안은 임의로 정하지 않는다(월권 금지).
- 모든 소통·주석·커밋 메시지는 한글. 커밋 메시지에 Co-Authored-By / Claude 관련 문구 금지.