Commit graph

41 commits

Author SHA1 Message Date
Yun Chan
391fb9f4d0 운영 복구 상태를 문서화 2026-08-28 18:27:02 +09:00
Yun Chan
dcb76a2373 운영 배포 검증 근거를 반영 2026-08-28 17:17:34 +09:00
Yun Chan
2a39636163 개선관리 요구사항과 Google 로그인을 완료 2026-08-28 16:07:09 +09:00
Yun Chan
16b079052e 직렬 게이트 잔여 원인을 70d7cb34 코칭 기능 통합으로 특정·기록
- 저녁 재실행 19실패의 지배 원인이 소유자 코칭 버튼·버블 커밋의 세션 UI 통합임을 규명
- 세부: strict 위반(버튼 3개)·체크포인트 포인터 차단(오버레이 의심, 결정적 3/3)
- TODO에 잔여 작업 항목 신설, 우연 커밋된 *.bak 로그 4건 제거 권고 기록
2026-08-23 13:50:43 +09:00
Yun Chan
0a00ff245a NAS current GREEN 달성과 심야 연쇄 복구 증거
- 대청소 사건·Docker 사망·WinNAT 포트 예약·DHCP IP 회수 연쇄 복구 기록
- 릴레이 bf5f7352 재핀(r3) + 192.168.0.224 계약 이전(방화벽·NAS .env 재구성)
- NAS agy_cli 전환으로 health 3/3 engine true + actual-origin turn→review smoke 통과
  — 201차 current GREEN 조건 전부 충족, TODO 항목 종결
- 직렬 게이트 잔여: 동맹 포인터 타임아웃 결정 재현(3/3)·스윕 협폭 결함과 함께 조사 이관 기록
- 대시보드 213차 노트, 수집량 1111 갱신(체커 요구), SSOT 59 PASS
2026-08-23 13:49:52 +09:00
Yun Chan
6a42063d49 NAS 엔진 릴레이 실제 시작 성공과 15:05 게이트 재검증 결과 기록
- 릴레이 실제 1회 시작 passed(4종 SHA pin, ready 실생 통과, PID 65328) 후
  LAN 한정 9100 방화벽 규칙 추가(Private 프로필 누락이 transport error 원인)로
  NAS origin health 3/3 ok·engine true, auth 401, OpenAPI 126 실측 — 8-12 이후 첫 회복
- 직렬 게이트 재실행 31/14/12did-not-run 실패를 정직 기록: 스윕 91건 협폭 레이아웃 결함
  보고(아침 연쇄 중단으로 미실행이던 테스트) + 스택·데이터 드리프트 의심 실패군,
  교사 재평가 2건 미실행 — pending 유지, 원인 조사 이관
- 대시보드 211차 노트, TODO NAS 항목 갱신, SSOT 체커 59 PASS
2026-08-18 15:45:06 +09:00
Yun Chan
0d5e211bd5 TODO Pages 배포 완료·NAS 릴레이 1단계 상태 동기화
- 공개 Web Pages 배포 항목 완료 처리(cf899b7f, production 4edc02d3, 증거 JSON 경로)
- NAS relay 항목에 2026-08-18 CheckOnly 통과 사실과 15:05 자동화 잔여 범위 반영
2026-08-18 12:08:29 +09:00
Yun Chan
cf899b7f15 유스케이스 TDD 16테마 스펙과 접근성 제품 결함 수정
- 지원 티켓 작성 UI 신설(설정)·관리자 해결 노트 입력 신설(Admin): 서버 계약은 있었으나
  웹 진입점이 없던 2결함
- a11y: outline 채널 포커스 링(ui/shell css), 세션바 44px 터치 타깃, 청록 하드코딩
  그라디언트를 테마 토큰으로 교체, 설정 라벨/헤딩/대비·리뷰 44px·모바일 오버플로 수정
- uc-*.spec.ts 16테마 239 시나리오 신규(수집 1109 tests/61 files), 기존 스펙 5종 계약 드리프트 교정
- breakpoint-sweep: widthsFor 솎아내기가 실기기 대표 폭(360/390/1024)을 탈락시키는 테스트 결함 수정
  — keep 시드를 전체 DEVICE_WIDTHS로, 3연폭 예외는 솎아내기 발생 여부 기준으로
- 검증: tsc PASS, 병렬 게이트 1040 passed(데스크톱 밀도 충돌 1건 해소 후 focused 68/68 GREEN),
  직렬 게이트 52/5/4 삼각화 — breakpoint(테스트 결함)·kb(낡은 dev API 재기동)·voice(일시적) 해소,
  교사 재평가 2건은 엔진 구독 한도(resets 3pm)로 skip 후 재검증 대기
- 문서/SSOT: HANDOFF·TODO·대시보드·testing 가이드 동기화, 증거 usecase-tdd-2026-08-18.json,
  SSOT 체커 PASS(59)
2026-08-18 11:47:58 +09:00
Yun Chan
80bcacc723 공개 Web 후보 사전검증 증거 고정 2026-08-12 18:20:53 +09:00
Yun Chan
28752836bd NAS 엔진 사전검증 증거 갱신 2026-08-12 17:54:00 +09:00
Yun Chan
0b9da9ca15 G7 종료 증거 기준 갱신 2026-08-12 17:37:13 +09:00
Yun Chan
cea2e86c5a 주기 회기와 UX 증거 갱신 2026-08-12 17:29:36 +09:00
Yun Chan
0f08c91286 주기 회기 GREEN 증거 갱신 2026-08-12 17:01:27 +09:00
Yun Chan
f380cc4641 셸 초기화 LF 계약 고정 2026-08-12 16:43:45 +09:00
Yun Chan
f97e7fadac 주기 회기 진단과 로그인 폭 보강 2026-08-12 16:33:59 +09:00
Yun Chan
946661926b NAS 엔진 릴레이 복구 계약 보강 2026-08-12 15:53:22 +09:00
Yun Chan
2605661f0c 공개 복구 상태 동기화 2026-08-12 12:01:10 +09:00
Yun Chan
3067b72526 G7 독립 평가 입력 검증 도구 추가 2026-08-10 02:32:16 +09:00
Yun Chan
fcc45e083e 주기 회기 GREEN 기준선 기록 2026-08-10 02:16:23 +09:00
Yun Chan
aa81af2958 회기 후속 검증과 표시 경계 보강 2026-08-10 01:55:21 +09:00
Yun Chan
4cd354881f 주기 회기 검증 격리 보강 2026-08-10 01:25:45 +09:00
Yun Chan
9a7dd98cb6 회기 원장 상태 복원 보강 2026-08-10 00:52:27 +09:00
Yun Chan
13d1c39a33 주기 회기 실패 경계 기록 2026-08-10 00:23:10 +09:00
Yun Chan
7b4955c3fc 주기 실회기 검증과 G7 종료계약 보강 2026-08-09 23:37:19 +09:00
Yun Chan
83590e9ef7 G7 공개 증거와 SSOT 동기화 2026-08-09 22:56:05 +09:00
Yun Chan
7cece90e33 PII 표시 토큰 누출 보정 2026-08-09 21:04:29 +09:00
Yun Chan
61a41d1f08 G8 재검증 기준 동기화 2026-08-09 19:41:31 +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
b866a48b01 G7 선행 조건 발견 — 공개 런타임에 admin/voice-runtime 이 없다
실측으로 찾았다. 공개 런타임은 119 paths 구버전이고 /admin/voice-runtime 이
배포돼 있지 않다. capture-g7-runtime-evidence.py 는 정확히 그 경로만 부르므로
artifact 2 를 만들 수 없다. 즉 마이크와 사람을 다 준비해도 오늘 실행하면
50분을 버리고 실패한다. 현재 소스에는 있다(admin.py:1699, 프리뷰 126 paths).

오케스트레이터가 시작 전에 이걸 검사하고 admin_voice_runtime_not_deployed 로
즉시 멈춘다. 공개 런타임 대상 --rehearse 가 exit 2 로 몇 초 만에 차단됐다.

판정 방식을 한 번 고쳤다. 처음엔 미인증 404/401 상태로 짰는데, Cloudflare 앞단이
자동화 클라이언트에게 존재하지 않는 경로까지 포함해 모든 경로를 403(error code
1010)으로 돌려주는 것을 확인했다. 그 신호로는 "배포 누락"과 "edge 차단"을 구분할
수 없어 작동하는 것처럼 보이지만 무의미한 검사였다. OpenAPI spec 의 paths 만
authoritative 하게 쓰도록 바꾸고 그 이유를 테스트로 남겼다.

G7 실행 순서가 이렇게 확정된다.
1. current source 를 공개 런타임에 승격(비-secure origin crypto.randomUUID 수정 포함)
2. --rehearse 로 배관 확인
3. 동의 하 물리 마이크 50분 + human pack 으로 실제 실행

검증: 오케스트레이터 25/25, SSOT FAIL 0, dashboard E2E 10/10, ruff clean.
2026-08-08 09:46:10 +09:00
Yun Chan
f3491be63f G7 외부 증거 3-artifact 동시 시간창 오케스트레이터
soak / runtime / topology 세 캡처는 같은 public host 의 겹치는 시간창이어야 하는데,
지금까지는 운영자가 세 명령을 따로 띄우고 시계를 손으로 맞춰야 했다. 50분짜리
실행에서 한 번 어긋나면 처음부터 다시 해야 하는 취약점이라 한 명령으로 묶었다.
세 캡처를 동시에 시작하고 전부 끝나면 human pack 을 더해 checker 까지 잇는다.

게이트를 약화시키지 않았다. CLI 로 실증한 fail-closed 경계 4종:
- 동의/장치 없이 운영 실행     physical_microphone_consent_required  exit 2
- human pack 없이 운영 실행    human_voice_gain_pack_required        exit 2
- 50분 미만 시간창             production_window_too_short           exit 2
- 세 캡처 host 불일치          hosts_must_match:[...]                exit 2

--rehearse 는 마이크를 열지 않고(soak 을 --preflight-only 로) 배관만 확인하며
보고서의 gate_closed 는 항상 false 다. 실제 실행 전 실패를 먼저 뽑기 위한 모드다.

기대 provider 기본값은 2026-08-08 결정에 맞춰 local_whisper / melotts 다.

이것으로 G7 에서 기계로 할 수 있는 부분은 끝났다. 남은 것은 코드로 만들 수 없는
둘뿐이다. 명시 동의 하 물리 마이크 50분 발화, 그리고 참가자 30명·독립 평가자 2인의
blind human voice-gain pack.

검증: 오케스트레이터 20/20, SSOT FAIL 0, dashboard E2E 10/10, ruff clean.
2026-08-08 09:40:08 +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
05aa7b312e 로컬 whisper STT 사이드카 디바이스 폴백과 deprecated audioop 제거
cuDNN 부재 환경에서 ctranslate2 는 Python 예외가 아니라 네이티브 크래시로 죽어
프로세스가 통째로 사라진다. 같은 프로세스의 try/except 로는 절대 잡을 수 없어
디바이스 확인을 버릴 수 있는 자식 프로세스(--self-check)로 분리했다.
auto 는 CUDA 프로브 실패 시 CPU(int8)로 폴백하고, 명시적 --device cuda 는 조용히
강등하지 않는다.

함께 고친 것:
- warmup PCM 생성의 연산자 우선순위 버그(b"\x00\x00" * N // 2 가 바이트열 정수
  나눗셈이 되어 TypeError). warmup_pcm() 으로 분리하고 테스트로 고정했다.
- audioop 은 Python 3.13 에서 제거되므로 array + 정수 연산으로 RMS 를 직접 구한다.

실측(저장소 무참조 synthetic seed 8.72초, CPU int8 small):
interim 9 · final 5 · word timestamp 12개 present, 전사는 원문과 한 글자 차이.
사이드카 회귀 37/37.
2026-08-08 01:39:58 +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
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
6b6241f468 한신대 피드백 개선팩 반영 2026-07-03 19:53:14 +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