Commit graph

74 commits

Author SHA1 Message Date
Yun Chan
7cece90e33 PII 표시 토큰 누출 보정 2026-08-09 21:04:29 +09:00
Yun Chan
ba5e6326d5 평문 환경 숙의 연습 해시 보정 2026-08-09 19:38:04 +09:00
Yun Chan
21461ab323 릴리스 후보 부트 진단 게이트 보정 2026-08-09 18:42:51 +09:00
Yun Chan
5221f79e3f G7 증명과 G8 clean-head 승격 준비 2026-08-09 18:22:03 +09:00
Yun Chan
f0c2240ffa 회기 전 자기점검 게이트 화면 재설계와 시간 만료 상태 대비·오버레이 수정
pre 게이트 카드가 행 높이만큼 늘어나면서 base flex의 align-items:center가
살아남아 3축 블록이 1fr 행 한가운데 떠 있었다. 1920x1080에서 카드의 66.5%가
빈 공간이고 축 위아래로 각 277px의 죽은 여백이 생겼다. 척도 라벨은 0.54rem에
nowrap+ellipsis라 901~1279px에서 최대 12개가 잘렸고, 620px 이하에서는 15개
전부 display:none으로 사라져 숫자만 남았다. 320x568에서는 접힌 mid 전용 40px
고정 행이 게이트에도 걸려 카드가 눌리고 헤더와 축이 겹쳤다.

- 게이트 카드는 align-self:center + max-height:100% + 내부 스크롤로 중앙에 서고
  높이는 내용이 정한다
- 3열 격자를 축별 세로 스택(질문 한 줄 + 전폭 5칸 척도)으로 바꿔 어느 폭에서도
  라벨을 자르거나 숨기지 않는다. word-break:keep-all + overflow-wrap:normal로
  어절 경계에서만 줄바꿈한다
- 정보가 없던 3 AXES 배지를 제출 버튼이 왜 잠겨 있는지 답하는 0/3 진행 표시로
  교체한다
- 40px 고정 행 규칙을 :not(.sx-alliance-gated)로 접힌 mid 전용으로 되돌린다
- 선택 상태 글자색을 반투명 --surface에서 --text-on-accent로 고친다

시간 만료 상태에서 드러난 네 결함도 함께 닫는다. sx-timebar와 종료 모달 패널은
다크 stage 팔레트 시절 잔재로, 정의된 적 없는 --bg-panel의 하드코딩 다크 폴백
위에 테마 토큰 글자를 얹어 라이트에서 대비가 1.13:1까지 떨어졌다. 의미색 토큰과
불투명 표면으로 되돌렸다. sx-page--active > * 의 position:relative가 같은
특이도로 뒤에 있어 종료 모달의 fixed를 덮어써 오버레이가 1532x32px 띠로 눌렸고,
게이트 행 정의는 :has() 두 개짜리 규칙보다 특이도가 낮아 시간 만료 바가 뜨면
밀려나 빈 트랙이 남았다. 둘 다 선택자를 맞춰 정정했다.

계측: 빈 공간 0.665→0.127, 라벨 잘림 12→0, 숨김 15→0, 최소 탭 46x60,
가로 오버플로 0. 배너 대비 1.13→13.88, 모달 제목 2.68→15.79(다크 13.86/15.18).
검증: typecheck, session-layout+alliance-pulse+layout-visual-gate 31/31,
시간만료 종료 다이얼로그 2/2, pre/mid 잠금 2/2, full-sweep+self-directed 30 pass.
남은 음성 4건은 baseline에서도 동일 실패하는 기존 회귀다.
2026-08-08 11:20:01 +09:00
Yun Chan
2624d49984 설치형 로컬 TTS를 MeloTTS 한국어(MIT)로 채택하고 엔드포인트로 연결
Higgs Audio v3 는 연구/비상업 라이선스라 config.py 가 environment != dev 에서
차단하고 있었다. 그 가드를 푸는 건 법적 판단이라 코드로 결정할 수 없어서,
상업 사용이 허용된 설치형을 다시 찾아 MeloTTS Korean 으로 바꿨다. 결과적으로
가드를 건드릴 필요 자체가 사라졌다 — Higgs 가드는 그대로 두고 provider 만
melotts 로 두면 운영에서도 동작한다.

검토 결과:
- MeloTTS   MIT       한국어 지원  -> 채택. CPU 실시간, 사전학습 다화자
- Kokoro-82M Apache2.0 한국어 없음  -> 탈락. 공식 VOICES.md 언어 목록에 부재
- Piper      GPL                   -> 탈락
- XTTS-v2 / Fish Speech 비상업      -> 탈락. Higgs 와 같은 문제

사전학습 다화자 모델이라 실존 인물 reference 를 쓰지 않는다. Higgs 경로가
P1 프리셋 한정이던 이유가 없으므로 모든 페르소나 프리셋에 적용된다.

구현:
- scripts/melotts-server.py  loopback HTTP 사이드카(/health, POST /tts -> WAV)
- voice_tts_provider=melotts 경로와 VIGNETTE_MELOTTS_TTS_* 설정
- scripts/start-melotts.ps1  런처(설치 순서 안내 포함)

실측:
- CPU 정상 상태 RTF 0.27~0.28(실시간 3.6배). 첫 실행 13.25 는 모델 다운로드
- POST /tts 200, WAV 350,566 bytes, 3.61s, 헤더 provider/model/license
- 빈 텍스트 422, 미지 경로 404 로 fail-closed
- 왕복 검증: MeloTTS 합성음을 로컬 faster-whisper 가 완전 일치 전사
  "그렇게 느끼셨군요. 조금 더 이야기해 주실 수 있을까요?" (word timestamp 8개)

설치 함정 3가지를 decisions/local-voice-stack.md 에 남겼다.
librosa 0.9.1 의 pkg_resources(setuptools<81), MeloTTS 가 언어와 무관하게
임포트하는 일본어 unidic 사전, Windows 한국어 g2p 의 eunjeon.

G7 게이트의 TTS 허용목록에 melotts 를 추가했다. 선언/실제 불일치 차단과
배치 STT 배제는 그대로다.

검증: API 914 passed, 사이드카 melotts 16/16 + whisper 37/37, SSOT FAIL 0, ruff clean.
2026-08-08 09:29:57 +09:00
Yun Chan
16e791e044 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 산출물은 커밋에서 제외했다.
2026-08-08 01:30:53 +09:00
Yun Chan
93dd8f82d7 G8 실제 rollback 증명 종료와 비-secure origin 회기 리뷰 크래시 수정
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 체커가 실패한다.
2026-08-07 22:17:20 +09:00
Yun Chan
12bdc59497 세션 화면 디자인 개편 2026-07-31 09:19:42 +09:00
Yun Chan
c788343467 feat: 운영 안정성과 세션 음성 경험 개선 2026-07-31 00:13:08 +09:00
Yun Chan
4511383cd9 전수 E2E 순회·소유자 결정 6건 구현·디자인 감사 반영
- 전수 순회: IA 전 라우트 412개 기능 인벤토리를 체크리스트 백로그로 관리
  (docs/ops/e2e-full-sweep-2026-07-27.md), 신규 full-sweep 스펙 10파일 추가.
  RED→GREEN으로 결함 12건 수정: 관리자 무한 렌더 프리즈(TanStack autoReset
  루프), 복수 코호트 저장 유실, 페르소나 보관 503(SQL 컬럼 모호성), PII 과잉
  마스킹, /admin/ai watchdog 오탐 오버레이, 모바일 겹침 2건, 설정 스크롤
  스파이, 온보딩 전화번호 무검증, 리뷰 조사·난도 라벨, pending 피드백 등.
- 소유자 결정 구현: 설정 아바타 변경, 동의 철회·재동의 전체 흐름, 신규
  학습자 기초 우선 추천, 학생 분석 테이블 가상화(@tanstack/react-virtual),
  저작 모드 죽은 레일 정리, 감정 밸런스 타임라인 차트(deep turn_valence +
  결정론 파생 폴백).
- 디자인 감사(142차): 라이트 팔레트 AA 대비, 다크 토큰 별칭 통일, 미정의
  CSS 변수 정리, 한글 keep-all 전역화, 탭 타깃 24px, LCP preconnect.
- 검증: npm run e2e 병렬 432 수집 GREEN + 직렬 49/49 exit 0, 백엔드 pytest
  421, gateway 29, typecheck/build/design-ssot/dead-code/중복 게이트 통과,
  layout-visual-gate 15/15, session-layout 8/8. 상세는 SSOT 대시보드
  142~144차 노트.
2026-07-27 14:25:24 +09:00
Yun Chan
3dfddcac6f 전 저장소 리팩터링과 SSOT 정비 2026-07-15 21:31:30 +09:00
Yun Chan
d80e33da5e 텍스트 응답 음성 재생 연결 2026-07-13 16:09:34 +09:00
Yun Chan
64e06a1185 관리자 빈 화면 진단 로그 추가 2026-07-03 23:24:09 +09:00
Yun Chan
b67fd5d471 흰 화면 부트 진단 추가 2026-07-03 23:08:05 +09:00
Yun Chan
287029f2a2 관리자 흰 화면 진단 보강 2026-07-03 22:50:14 +09:00
Yun Chan
50524f14ae 관리자 빈 화면 진단 2026-07-03 20:45:41 +09:00
Yun Chan
a5a2e2ea78 관리자 화면 스크롤 복원 2026-07-03 20:27:54 +09:00
Yun Chan
6b6241f468 한신대 피드백 개선팩 반영 2026-07-03 19:53:14 +09:00
Yun Chan
998acb44b0 OAuth 관리자 진입 경로 정규화 2026-07-03 19:46:05 +09:00
Yun Chan
bd046c4501 관리자 기본 진입 경로 수정 2026-07-02 10:52:12 +09:00
Yun Chan
778e8526d4 세션 평가·라이브코치·교수자 분석 라운드 마감 + 문서 정리 + 코드품질 리팩터
- 누적 작업트리 커밋: 회기 평가 복구·durable 저장, 라이브 코치 이력/근거, 교수자 학생분석, 음성 비언어 메타, PII 마스킹, 운영 티켓/헬스 등
- 문서: 완료 기록 docs/archive/ 냉동 보관, docs/ 단일 인덱스(docs/README.md)+통합 TODO(docs/TODO.md)로 정리
- 리팩터(행위 보존): Stage enum SSOT(taxonomy 소유·state_machine re-export), store recent/masked_turns 중복 제거, speaker_ko_label 단일 헬퍼, _list_sessions N+1 제거(state/turns 배치 + 턴평가 하이드레이션 배치)
- 검증: 백엔드 pytest 352 passed, _list_sessions E2E chromium-single-run 2 passed
2026-07-02 02:50:36 +09:00
Yun Chan
7c41c3ce79 검증 증거 문서 보강 2026-07-01 12:48:26 +09:00
Yun Chan
69fece56bf 학생 분석 목록 펼침 보강 2026-07-01 12:41:17 +09:00
Yun Chan
51053af536 안전 이벤트 대시보드 보강 2026-07-01 12:34:46 +09:00
Yun Chan
fe2796f05a 세션 평가와 교수자 분석 보강 2026-07-01 12:10:52 +09:00
Yun Chan
5c4ac04e06 preview host 허용 회귀 가드 추가 (check:preview-hosts)
배포 도메인 블랭크(vite preview allowedHosts 누락) 재발을 막는 행동 검증
스크립트를 추가. preview를 띄워 공개 Host(vnet/api-vnet/chanpaca) 3종이
200으로 허용되고 임의 Host는 403으로 차단(DNS 리바인딩 보호 유지)되는지
http.request로 직접 Host 헤더를 보내 확인한다. package.json에
check:preview-hosts로 등록.

검증: npm run check:preview-hosts → 공개 3 allowed + unlisted blocked PASS,
exit 0. 대시보드 104차 갱신.
2026-06-30 12:27:46 +09:00
Yun Chan
09d3220f68 배포 도메인 관리자 페이지 블랭크 수정 (vite preview allowedHosts)
vnet.18ka.net 공개 배포에서 vite preview 서버가 Host 검증으로 공개 도메인
요청을 "Blocked request. This host is not allowed." 403으로 막아 SPA 전체가
블랭크로 뜨던 문제를 수정. server.allowedHosts와 같은 목록을 preview에도
적용하고 기본 허용 호스트에 vnet.18ka.net/api-vnet.18ka.net/vignette.chanpaca.net 추가.

검증: curl -H "Host: vnet.18ka.net" 127.0.0.1:5174 가 수정 전 Blocked →
수정 후 200+정상 index, 로컬 dev·preview 일반/슈퍼관리자 전 페이지 정상 렌더,
npm run typecheck. 대시보드 104차 기록.
2026-06-30 12:16:51 +09:00
Yun Chan
4e6b0045e3 관리자 워크스페이스 접근 확장과 소유자 결정 7건 확정 반영
- 관리자(role=admin)가 학습자·교수자·관리자 워크스페이스를 모두 접근하도록
  can_access_role/require_role와 프론트 auth 헬퍼·Sidebar 내비를 정리하고
  admin 워크스페이스 내비 E2E를 추가.
- 소유자 결정 7건 전건 확정(2026-06-30)을 SSOT 대시보드·백로그에 반영하고
  결정 필요 7→0으로 동기화. SSOT drift 게이트 기대 카운트도 갱신.
- 확정된 H1 평가설계(κ≥0.70·ICC≥0.75·환각률≤0.03·t-검정 α=0.05·무작위 배정)를
  approved-export κ 게이트(checker·dataset_export·recursive export)와
  KPI 측정계획·export manifest 문서에 반영.

검증: npm run typecheck, npm run check:api-types, 백엔드 pytest 290 passed,
admin 내비 E2E 1 passed, 레이아웃 시각게이트 9/9, session-layout 4 passed,
SSOT drift 게이트 PASS.
2026-06-30 10:57:46 +09:00
Yun Chan
1274ba9ccc 테스트 메일 수신자 제한 2026-06-29 17:13:34 +09:00
Yun Chan
3bf38c50df 메일 알림 시스템 추가 2026-06-29 17:07:01 +09:00
Yun Chan
206018b088 런타임 계약과 학습자 흐름 보강 2026-06-29 08:12:14 +09:00
Yun Chan
f456b8997a 세션 진행 패널 스타일 보강 2026-06-29 00:01:40 +09:00
Yun Chan
d18e4b6b4b Phase 3 KPI 계약 상수 분리 2026-06-29 00:01:24 +09:00
Yun Chan
30441bd93b 워크시트 검수 UI와 세션 다크톤 정리 2026-06-28 23:53:37 +09:00
Yun Chan
f7aae885b2 Phase 3 KPI 상태값 명시 2026-06-28 23:53:17 +09:00
Yun Chan
1e9f293fda 라이브코치 소스팩 새로고침 보강 2026-06-28 23:52:55 +09:00
Yun Chan
84599bbaa2 한국어 PII 인식기 경계 추가 2026-06-28 23:52:37 +09:00
Yun Chan
2bb052f624 세션 계약과 메모리 경계 보강 2026-06-28 23:52:18 +09:00
Yun Chan
391639c1de 평가 및 화면 구조 정리 2026-06-28 21:50:21 +09:00
Yun Chan
3a9f70a97b 운영 화면과 회기 리뷰 UI 갱신 2026-06-28 20:13:21 +09:00
Yun Chan
e7ebb38177 운영 지표와 지원 요청 저장소 추가 2026-06-28 20:13:06 +09:00
Yun Chan
50fa4ad432 세션 메모리와 비언어 이벤트 저장 2026-06-28 20:12:50 +09:00
Yun Chan
e8e08935ed 페르소나 소스팩 동기화 정리 2026-06-28 20:12:35 +09:00
Yun Chan
6a81ec596c 평가 캐시와 개인정보 마스킹 보강 2026-06-28 20:12:20 +09:00
Yun Chan
f0771db919 엔진 게이트웨이 계약 고정 2026-06-28 20:12:05 +09:00
Yun Chan
ac7db95542 음성 재생과 운영 배포 정리 2026-06-28 12:18:20 +09:00
Yun Chan
8ed185ce6c 외부 계정 수동 등록 허용 2026-06-28 11:31:07 +09:00
Yun Chan
bd389a97cc 사례개념화 워크시트 저장 추가 2026-06-27 19:27:34 +09:00
Yun Chan
7f4a2d90c7 P4-P7 페르소나와 Tailnet 허용 보강 2026-06-27 19:04:46 +09:00