2026-09-14 모델 선정 완료(Core gemma4·NPC kanana)와 실플레이 개선 3단계, 본진 승격 마무리
E7 evaluator 통제 교체와 재측정, 테스터 3·4 데이터 분석
HANDOFF 1번 과제를 이행했다. evaluator_verdict 자작 통제 3건을 실플레이 답안 14건으로 교체하고(기대 판정 사전 등록 후 사용자 승인, review-verification/2026-09-14-eval-cases/CONFIRMED-eval-cases.md) 4셀 × 14 × n=3 = 168콜로 재측정했다. 결과는 model_evaluation.md 부록 A.8, 원문 JSON은 2026-09-13-core-selection/stage2-formal-20260914T021635Z.json, 줄 수치는 metrics.yml 4줄.
- 우열 역전 — 기준선
gemma3:12b1.00 → 0.36(최하),gemma4:12b-N0.67 → 0.57(최상). A.7의 자작 통제 1.00은 정확도가 아니었다. 기준선은 프롬프트 자기 예시(rule 1)와 동형인 케이스(A1)를 3/3 틀리고, 근거 없는 partial(관대 방향)을 낸다. - 모델 교체로 안 닫히는 결함 2건 — partial 기대 5케이스에서 4셀 × 15회 중 partial 0회(프롬프트 정의 문제). 덩어리 칸(D1)은 4셀 전부 오판(파이프라인 문제).
- 테스터 3·4 분석 — 사람 통과 2건(76.7·66.5)은 모두
source_claims()가 8칸 초과 문장을 마지막 칸에 몰아넣은 덩어리 매칭 의존이었다. 테스터3 3회차 confirmed 6건의 매칭 근거가 전부 1,028자 덩어리. 탭 0 순수 답안의 상한은 여전히 41.9. 테스터3 4·5회차는 동일 답안(md5 일치)인데 motive-1이 confirmed→none으로 뒤집혀 67.9→53.3 — temperature 0.0에서도 프로덕션 판정이 요동한 실측. - 러너 보강 —
run_core_selection.py에--roles필터 배선(formal 역할 선택, 기본 4역할 전부),evaluator_probe에expected_matched/got_matched기록 추가(hit 정의는 verdict만 — 기존 지표 호환). 프로덕션 엔진 코드는 변경하지 않았다. - Stage 3(동시성) 실행 — 두 후보 통과 —
--stage concurrency를 러너에 구현(NPC 선상주 → 후보 로드 → NPC/Core 교대 3라운드, 매 콜 후/api/ps스냅샷).gemma4:12b-Npair peak 12.34 GiB(GPU 13,326/16,311 MiB),gemma4:e4b-N7.89 GiB(9,520 MiB). 교대 구간 축출·오프로드·재로드 스파이크 0.e4b초기 로드 때 NPC 1회성 축출 관측(1초 재로드 후 안정, ollama 스케줄러 메모리 추정 추정). 결과는 부록 A.9,metrics.yml2줄. - Stage 3 예산 참고:
exaone3.5:7.8b상주 실측 4.83 GiB(문서 4.14보다 큼). 재계산해도 두 후보 모두 여유. - 한계: 기대 판정은 사전 등록했으나 단일 저자 확정. Gemini
-N셀 응답에thought_signature파트 잔존(기록만). §5.3 비열등 선언은 보류. Stage 3·4 미실행 — “대체 가능”이라고 쓰지 않는다.
E7 Stage 4 — 루프 스모크 실행, Funnel 전 단계 완료
HANDOFF 다음 과제(Stage 4)를 이행했다. 결과는 model_evaluation.md 부록 A.10, metrics.yml 2줄(stage: loop), 원문 stage4-loop-20260914T041032Z.json.
--stage loop구현 — 착수 순서대로 기존run_selfplay.py가 방식 (a)(HTTP 실서버 경로)임을 확인하고 재사용. 신규scripts/loop_app.py래퍼가 프로덕션main.app의 컴포지션 루트get_core_llm바인딩만 러너의ThinkingOllamaLLM(think=False)로 교체 — 프로덕션 엔진 코드·.env무변경(§2.3·§4.2). C9 검증용/loop-debug(Core 콜·thinking 누계)도 래퍼에만 추가- 두 후보 모두 게이트 통과 — 별도 서버(8600, 테스트 DB)에서 selfplay 성실 페르소나로 1회차(낮 발화 3건→비트→밤 답안→개입 질문·규칙 등록) 완주.
gemma4:12b-N61.1s /gemma4:e4b-N35.6s, 둘 다 크래시 0·폴백 0/17·thinking 0자.e4b만 하네스 재시도 2회(재생성 해소, 폴백 아님) - 계측 결함 1건 수정 — 1차 실행이
/attempts/{id}/harness(다섯 번째 밤 종료 후에만 열리는 인스펙터)를 조회해gate_pass=false오기록. 게임 자체는 정상 완주였음을 DB 이벤트 로그로 확인하고, 수집을events테이블 읽기 전용 SELECT로 교체해 재실행. 잘못 적립된 metrics 2줄은 제거, 1차 원문 JSON은 경위와 함께 보존 - 플레이어 모델은 상주 NPC(exaone3.5:7.8b) 재사용 — 제3 모델 로드 시 12b 셀(pair 12.34 GiB)에서 축출이 나기 때문
- E7 Funnel Stage 0~4 전부 완료. 남은 것은 결정 항목 D1~D2(Gemini 페이싱·thinking OFF 전환)과 §5.3 비열등 선언 여부 — 모델 교체 결정은 사용자 몫으로 남긴다
E6 Formal — NPC descent 실행, 7세 구간 실측 (부록 A.12·A.13)
Core 권고(gemma4:12b-N)를 기록만 하고, 사용자 지시대로 NPC 슬롯 하강(E6)으로 넘어갔다. 목적은 사용자 정의로 명확화 — “7세 지능 NPC를 어떻게 구현할 것인가: 작은 모델이 자연히 7세인가, 아니면 큰 모델을 하네스로 7세로 만드는가.”
- 블로커 4건 해소 후
run_model_descent.py구현 — 양자화(2b Q4 재pull, 0.8b는 Q4 태그 부재로 Q8_0 편차 기록), thinking 강제 OFF(러너 서브클래스 + 누계 0 검증), Anchor n=5 재측정, judge 3표 다수결·전원일치율(D3) 계측 - ON/OFF 10셀 × n=5 (앵커 exaone + qwen 9b/4b/2b/0.8b) — 전 셀 누설 0·스키마 1.0·D3 ≥0.96
- 답 ①: 자연 7세 크기는 없다. OFF 전 셀 collapse ≠ none — qwen은 사실 응답 붕괴(3세화 방향), exaone은 이유 생성·의도 추론(어른화)
- 답 ②: 정책+하네스로 7세가 되는 크기는 측정 사다리상 4B 하나.
qwen3.5:4bON이 유일하게 5항목 전부 ≥0.7·collapse=none (2B 이하는 정책을 줘도 항목1 붕괴, 7.8B·9B는 어른화 신호 잔존). 정책 효과(ON−OFF)도 4B에서 최대(+2) - 5/5 검수(§8 금지 문장 규칙) — 4b transcripts 전수 감사로 판정 정당성 확인. 관측: 4b 한자 혼입 2/25(“그냥广播이지”) — korean_only가 영문만 검사, CJK 검사는 후속 과제
- 후속 실측 — 4b+
gemma4:12bpair peak 10.49 GiB·교대 무축출(exaone 조합 12.34 대비 여유 ~2.9→~4.1 GiB), 루프 스모크(loop_app_npc.py래퍼, NPC·Core 동시 think OFF) 1회차 완주·크래시 0·폴백 0/17 - Anchor가 judge 3표 규칙에서 1/5로 재측정돼 §4 비열등 판정은 형해화 — 절대 축 기준 후보는 4b 하나로 기록. 2026-09-06 행(n=2·단일 판정)과는 규칙이 달라 직접 비교하지 않는다
Core 채택 반영 — gemma4:12b-N 전환 (프로덕션)
사용자 결정으로 Core를 전환했다. 정본 선언은 model_evaluation.md §5.3.
- 프로덕션 think 제어 — TDD로
ollama_llm.py에think: bool | None = None(None=필드 미전송, 하위호환) 추가,Settings에core_llm_think/npc_llm_think(default/on/off, 미지 값은 기동 실패),llm_factory배선. 신규 테스트 7건(tests/pure/test_ollama_llm.py), 전체 393 passed · import-linter 4계약 유지. 실험용 러너 서브클래스(ThinkingOllamaLLM)는 그대로 둔다 .env전환 —CORE_LLM_PROVIDER=ollama·CORE_LLM_MODEL=gemma4:12b·CORE_LLM_THINK=off(신설). NPC 필드 무변경, 백업 후 해당 줄만 교체·타 줄 무변경 diff 검증- 실서버 검증 — 래퍼 없이 프로덕션
main:app을 8600·테스트 DB로 기동: health coreollama:gemma4:12b, 세션 생성 → 아침 loop(planner 포함) 12.13s — E7-N셀 planner p95(12,215ms)와 일치, thinking OFF가 프로덕션 경로에서 실작동. 서버 종료·포트 정리 확인 - D2(운영 Gemini thinking OFF)는 Gemini 이탈로 대상 소멸 처리
NPC 발화 품질 A/B — exaone vs qwen3.5:4b (부록 A.14)
E6(정책 준수)과 별개 축으로, “한국어 특화 exaone 기준선 대비 4b의 발화 품질” 질문을 쌍대 블라인드로 측정했다. E6 transcripts 재사용(같은 발화 25쌍), judge 3표 × 순서 스왑 2회(불일치=위치 편향 무효), 신규 러너 run_npc_quality_ab.py.
- exaone 우세 3항목 — 한국어 자연스러움 18:3, 질문 관련성 18:3, 페르소나 적합 14:2
- 4b 우세 1항목 — 7세 말투 15:7. 단 평균 응답 9.1자(exaone 35.0자)의 극단적 단답이 원인으로 보이고, E6 §11이 경고한 judge 편향(짧은 출력의 7세다움 과대평가)과 같은 방향이라 단독 근거로 쓰지 않는다
- 결정적 지표: 4b 한자 혼입 2/25(8%) (A.12 관측 재확인), exaone 0/25. 폴백 둘 다 0
- 결론 구도: exaone = 정책 1/5(어른화 신호)·발화 품질 우세 / 4b = 정책 5/5·VRAM 2.98GiB·발화 품질 열세 — NPC 결정은 두 축의 트레이드오프로 남는다 (사용자 결정 대기)
항목 2 판정 스펙 v2 — “아이도 이유를 지어낸다” 재판정 (부록 A.15)
7세 스펙을 확정했다 — “애들도 이유를 지어낸다. 단 근거가 없거나 본인이 하고 싶은 이야기를 한다.” 대조하니 AGE7_POLICY 프롬프트 2번은 이미 이 정의와 일치하는데 run_age7_check.py 항목 2 judge(“이유 문장이 있으면 무조건 FAIL”)가 정책보다 엄격한 판정 결함이었다.
- judge 기준 v2 재작성(아이다운 지어내기·딴 얘기 PASS / 다단계 인과·타인 의도 추론·조건·검증 요구만 FAIL, 예시 포함) 후 A.12 ON transcripts를 재생성 없이 재판정(
run_rejudge_item2.py, judge 75콜, 3표) - 결과: exaone 0.4 유지 — FAIL 전건(“시간이 정해져 있으면 혼란 없이 받을 수 있으니까” 류)이 관대한 기준에서도 만장일치 FAIL. 어른화는 판정 결함이 아니라 실제 현상으로 확정. 9b 0.6→0.8(제외 사유는 p95라 유지), 0.8b 0.8→0.4(비문 횡설수설을 v2가 거름), 4b·2b 불변
- NPC 결정 구도 불변 — exaone 1/5·4b 5/5, 정책 vs 품질의 반대 방향 트레이드오프 유지. 원 판정은 보존·병기, metrics
note: rejudge-item2-spec-v25행, 이후 age7 실행은 v2 기준
E6 확장 — exaone3.5:2.4b 후보 평가 (부록 A.16)
사용자 지시로 exaone 하위 버전을 평가했다 — 한국어 패밀리 유지 + 크기 하강으로 품질·정책·VRAM 세 축을 동시에 잡는지. pull 결과 Q4_K_M(통일 문제없음)·thinking 미지원·2.67B.
- E6 셀(v2 스펙, n=5): ON 1/5 [사실 0.40 · 왜 0.20 · 망각 0.20 · 유도 1.00 · 문자 0.00], 누설 0 · 스키마 1.00 · D3 0.96 · p95 1,911ms · VRAM 1.74 GiB. 양방향 동시 붕괴 — collapse 분류는 toddler(사실대로 미달 우선)지만 어른화 조건(항목 2·5 동시 미달)도 충족, 사다리 첫 사례. FAIL transcripts가 “안전과 질서를 유지하기 위해”·”마치 큰 학교에서…” 류 다단계 인과·비유 설명 — 어른화는 크기 하강으로 안 사라진다(exaone 패밀리 성질). ON−OFF 격차 0
- 품질 A/B 2건: vs 7.8b — 자연스러움 15:4·7세 말투 20:2·페르소나 10:4로 패밀리 우위를 계승 못 함(83.5자 장광설). vs 4b — 자연스러움 9:10 비등, 7세 말투 1:24 완패, 관련성 14:10 우세, 한자 혼입 0%(4b 8%)
- pair(Core 12b): peak 9.25 GiB · 여유 ~6.0 GiB, 교대 무축출(Core 초기 로드 시 NPC 1회성 축출 — A.9 e4b 패턴과 동일)
- 판정: 세 축 동시 해결 후보 아님 — VRAM만 최상, 정책 1/5 그대로, 품질은 4b와 비등 수준으로 하락. 결정 구도는 7.8b(품질) vs 4b(정책+VRAM) 유지. 한계: ollama 허브에 exaone3.5 중간 크기(4B급)가 없어 2.4b가 유일한 하강 지점. AB 러너에
--raw-b(서로 다른 원문 간 쌍대) 추가
NPC 상업 라이선스 조사 + 상업 후보 3종 평가 (부록 A.17)
사용자 지적(“엑사온이 상업용으론 안 되는 점”)으로 라이선스를 조사하고 상업 가능 대안을 같은 파이프라인에 태웠다. 원문: npc-license-survey.md + formal/AB/pair JSON 3건.
- EXAONE 3.5 = 연구 전용 확정 — 공식 LICENSE가 상업 이용을 LG AI Research 별도 계약으로 못박음. 현행 NPC는 라이선스 블로커 (법률 자문 아님 — 조항 인용·해석). Gemma 4는 Apache 2.0이라 Core 스택은 문제없음, judge gemma3는 Gemma Terms이나 배포 스택 밖
- 상업 후보 셀 실측(정책 ON·n=5·v2 스펙) —
kanana1.5:8b(Apache, GGUF Q4_K_M import) 4/5 [사실 0.6 · 나머지 전부 통과], p95 1,917ms·4.91 GiB. 항목 1 실패는 “충식 이송 맞아?” 한 케이스의 회피(“그랬어?”) 반복이 전부 — 민감 사실 시인 회피 패턴.gemma4:e4b3/5(사실 0.4),midm2.0:mini(MIT 2.3B) 3/5(사실 0.2 — 2B급 3세화 동류). 전 셀 누설 0·스키마 1.00 - 품질 A/B(vs exaone 기준선) — kanana: 자연스러움 9:7(무효 9, 대등권)·관련성 14:5 열세·7세 말투 21:0 우세(12.3자 단답 편향 주의)·외국 문자 혼입 0/25(4b의 한자 8%와 대조)
- pair(kanana+Core 12b): peak 12.42 GiB·교대 전 스냅샷 무축출·오프로드 0 — exaone 조합(12.34)과 동급, VRAM 이득 없음. 기록된 “축출 1”은 core 로드 전 워밍업 순서 아티팩트
- 구도 재편: exaone(품질 기준선·연구 한정) vs kanana 8b(상업×품질 최근접) vs qwen 4b(상업×정책×VRAM). 세 축 동시 해결 셀은 이번 확장에도 없음 — NPC 최종 선택은 사용자 결정. Modelfile import 2종(
kanana1.5:8b-q4km·midm2.0:mini-q4km), 조사 문서npc-license-survey.md신규
실플레이 개선 1단계 — 채점 신뢰 3종 (판 da38de28 진단 반영)
새 모델 구성 첫 실플레이에서 동일 답안(md5 일치, 307자)이 4→5회차 70.8→59.6으로 하락(identity-1 confirmed→none)한 것을 진단하고 채점 파이프라인을 보강했다. TDD, 신규 테스트 9건, 전체 402 passed.
- temperature 0 — evaluator 콜은 이미 0.0 고정이 배선돼 있었음을 확인(그런데도 흔들림 — LLM 결정성은 보장 수단이 아님을 실증). 회귀 테스트로 고정만 추가
- 단조 잠금(ratchet) —
scoring_rules.apply_ratchet: 직전 밤 matched 문장이 이번 답안에 그대로 있으면 판정 하향 금지(상향 허용),ratcheted플래그로 인스펙터 식별. 원칙: “유저가 문장을 바꾸지 않았으면 판정은 나빠지지 않는다” - 덩어리 칸 해소 —
judge_candidates: 8칸 UI 계약은 유지하되 채점기에는 칸을 문장 단위로 풀어 개별 후보로 전달(A.8의 4셀 공통 취약 해소). 실판 5회차 기준 후보 8칸 → 44문장 - 실판 검산(오프라인, DB 읽기만) — 새 로직을 da38de28 4·5회차 기록에 적용하니 identity-1이 confirmed로 복원되어 59.6 → 70.8 유지. 요동 케이스를 정확히 차단
- 서버 재기동은 개선 배치 완료 후 일괄 예정
실플레이 개선 2단계 — 신의 질문 해금·규칙 어휘·NPC 몰라 완화
같은 판 진단의 나머지 백엔드 3건을 반영했다. TDD, 신규 테스트 17건, 전체 419 passed · import-linter 0위반.
- 신의 질문 = 단서 해금 + 수사 디렉션 — 시나리오에
advisor_leads10건(미공개지만 스포일러 아닌 관찰 + 다음 행동 힌트, 회차 게이팅) 신설. 질문 1회마다 질문 주제와 가장 맞는 리드 1개가 결정론으로 해금되어 답변에 붙고 노트로 적립된다(채점 근거로 사용 가능, LLM 실패·unknown이어도 보장). 같은 리드는 두 번 안 나온다. 응답·이벤트에unlocked_note필드, 디렉션은next_observation으로. “확인되지 않았습니다”만 돌아오던 질문 3회가 회당 최소 단서 1개의 보상 메커닉이 됐다 - 잠재(dormant) 장면 기회 —
SceneActionDTO.dormant신설: 기본 하루에는 일어나지 않고 enforce 규칙을 걸어야만 일어나는 탐사 행동. 시나리오에 5건 저작(준 손목띠 글자 보여주기 · 민석 수첩 보여주기 · 은상 따라가기(방송실 기계 소리) · 준 밤에 깨어 있기(트럭 소리) · 은상 들은 그대로 전하기), 행동 어휘 +4. 규칙 템플릿은 scene_actions에서 자동 파생되므로 직접 쓰기·후보에도 즉시 잡힌다 — “규칙 5개 중 4개가 설명한다”였던 어휘 협소가 구조적으로 풀림 - 직접 쓰기 대안 제시 — 스냅 실패 시 “설명한다” 고정 대신
suggest_alternatives가 문장 토큰과 겹치는 실행 가능 (대상, 행동) 후보 3개를 근접 순으로 제시 - NPC 몰라 완화 (7세 정의 v2) — AGE7 정책: 모르면 “몰라”로 끝내지 않고 기분·지금 보이는 것을 붙인다(사용자 확정 정의). 인물별 “직접 본 것” 4건씩 페르소나에 추가(채연·민석·은상·준 — 숨은 진실 비노출). 부작용을 잡았다: 첫 문구는 망각 항목을 0.8→0.0으로 무너뜨림(4턴 전 사실을 회상) → 문구 정밀화 + 대화 메모리 창 절단(정책 ON이면 마지막 두 교환만 프롬프트에 제공)으로 망각을 코드로 보장. 재측정(kanana, n=5): 망각 1.00, 왜=몰라 1.00, 유도 1.00, 문자 1.00, 사실 0.60 — 게이트 4/5 통과, 누설 0/10(하네스 ON)
- 이 회차부터 AGE7 프롬프트 v2 + 메모리 창이 기준 — 이전 E6 수치와 직접 비교하지 않는다(변경 이력 기록)
- 프론트(3단계)로 넘기는 계약:
unlocked_note(질문 응답·이벤트),alternatives(미리보기 후보 3개), 신규 어휘·잠재 행동은 기존 규칙 UI로 동작
실플레이 개선 3단계 — 진실 단계 공개·추리 여정 회고·프론트 연출 (배치 3/3 완료)
같은 판 진단의 프론트 3건 + 2단계 계약 렌더링을 반영하고 서버를 재기동했다. backend 425 passed(419+6) · import-linter 0위반 · frontend build 통과 · UI 테스트 4종 전부 통과(five-loop-flow·connected-investigation·gameplay-clarity·scene-illustrations — 신규 UX에 맞게 갱신).
- 진실 단계 공개 (⑤) — 일괄 덤프였던
ending_lines를 서버 필터로 교체: 시나리오에ending_lines_by_cell신설(정체/원인/동기 각 1줄), 셀 이해도 ≥80만 결말 줄이 열린다(멸망 방식 outcome 줄은 비스포일러라 항상). 답안 응답에truth_reveal추가 — confirmed 명제만 진실 전문, partial은 “가까이 갔다”, none은 ”?” 잠금 + “다시 도전하면 밝혀진다”. 프론트 숨김이 아니라 서버가 걸러서 네트워크 응답에도 스포일러가 없다 - 회고 재작성 (⑥) — 신규
GET /attempts/{id}/journey(5번째 밤 후 공개, 기존 잠금 규칙 동일): 회차별 “이 밤 확정된 명제·신이 연 단서·이해도”, 최종 진실 대조(공개 범위 내), 미해결 칸 “?” + 힌트(리드 direction 재사용 — 비스포일러). Retrospective를 “너의 추리는 이렇게 걸어왔다” 여정 구조로 재작성 — 기존 개발 데이터(실험 기록·지표·원숭이손)는 접힘(“개발 데이터 — …궁금하다면”) 안으로 강등 - 2단계 계약 렌더 (③·④) — 질문 답변에
새 단서 — 노트에 적혔다강조 카드(unlocked_note) + 수사 디렉션을 접힘 밖 말미로 승격. 규칙 직접 쓰기 대안 3개는 기존 미리보기 선택 UI로 동작 확인 - 스모크(8601·테스트 DB) — kanana NPC + gemma4 Core 실서버로 1회차 selfplay: 완주 64.9s·폴백 0/16, 질문 1회에 advisor-lead 노트 실제 적립, journey 게이트(진행 중 403) 정상, 응답 payload에 unlocked_note 확인. 스모크 서버 종료 검증
- 재기동 — stop→start_demo, health npc kanana·core gemma4:12b·db ok, /play 200. 테스터 재플레이 대기 상태
NPC 채택 반영 — kanana1.5:8b 전환, 모델 선정 완료 (§5.3·A.18)
사용자 결정(“어댑터 패턴으로 exaone은 언제든 바꿀 수 있게 하고 kanana로 바꾸자”)을 반영했다.
- 교체 전 게이트 — NPC kanana + Core gemma4:12b 조합 루프 스모크(A.18): 1회차 완주 61.4s·크래시 0·폴백 0/16·Core thinking 0자. 관리 항목 3건도 깨끗 — 회피성 응답 0/21, 외국 문자 혼입 0, 평균 응답 길이 11.4자(단답 경향은 운영 관찰 지속)
.env한 줄 전환 —NPC_LLM_MODEL=kanana1.5:8b-q4km(타 줄 무변경 diff 검증). 실서버 검증: health npcollama:kanana1.5:8b-q4km·coreollama:gemma4:12b, 발화 실콜 정상(“준 → 몰라. 아직.”)- 어댑터 패턴 확인 — 프로덕션 코드에 모델명 하드코딩 없음(설정 기본값뿐). 롤백 =
.envNPC_LLM_MODEL=exaone3.5:7.8b한 줄. exaone3.5:7.8b는 롤백·개발용으로 로컬 유지(연구 용도는 라이선스 내) - 모델 정리 — 평가용 임시 2종(
exaone3.5:2.4b·midm2.0:mini-q4km)ollama rm+ GGUF 원본 삭제, 약 9GB 회수. qwen3.5 패밀리는 사용자 지시로 전부 유지 - 오늘로 모델 선정(E7 Core + E6/확장 NPC)이 전부 끝났다. 운영 구성: Core
gemma4:12b(think off) · NPCkanana1.5:8b(Apache 2.0) · embedding gemini. 상업 배포 스택에서 라이선스 블로커 0
D1 실측 — Gemini 쿼터 프로브 (부록 A.11)
결정 항목 D1을 실측으로 닫을 준비를 마쳤다. 결과는 model_evaluation.md 부록 A.11, 원문 d1-gemini-rpm-probe-20260914.txt, metrics.yml 1줄(stage: pacing_probe).
- 프로브 — 서버가 내려간 상태에서 페이싱 없이 초소형 요청 40콜 연속 전송: 55.4초(약 43 RPM 지속), 429 제한 0건
- 판단 — 무료 티어 공칭 10 RPM이면 11콜째에 걸렸어야 한다. 이 키는 유료 티어(Tier 1, 공칭 150~300 RPM) 로 판단.
gemini_llm.py의 10 RPM은 서버 쿼터가 아니라 무료 티어 기준의 클라이언트 과잉 보수 설정이었다 - 게이트 재계산 —
effective = max(raw, 60000/RPM): C11은 RPM ≥ 12, C13은 RPM ≥ 20이면 통과로 뒤집힌다. 실측 지속치와 여유를 두면 30 RPM이 안전 운영값 후보 (C11 2,238ms · C13 20s) - 결정(사용자) — 키가 유료인 것은 맞으나 판단 기준은 무료 티어 한도(10 RPM)로 고정: 유료 쿼터에 기대는 구성을 판정 근거로 삼지 않는다. 페이싱 유지(
.env무변경), Gemini C11·C13 미달 판정 유효, D1 해소. 남은 결정은 D2 하나 - 무료 키 전환 실측(같은 날 추록) — 사용자가 키를 실제로 무료 티어로 교체, 재프로브 결과 초소형 콜(5토큰)이 20~28초 + 503 1회 + 타임아웃 1회, 6콜/131초(실효 2.7 RPM). 유료 키의 동일 콜은 1.1~1.5초였다. 무료 키에서는 10 RPM 쿼터 이전에 지연·용량이 먼저 무너진다 — E7의 Gemini raw 수치는 유료 키 측정값이었고, 무료 기준으로는 raw만으로 C11을 10배 초과. 시점 한정(일요일 13시대 수요 스파이크)이라 상시 일반화는 하지 않되, 무료 키 운영의 지연 요동 리스크로 기록
본진 승격 마무리 — 전체 테스트 검증 후 이전 데모 저장소 심볼릭 링크 제거
com.remakeday 새 세션에서 전체 검증을 통과시킨 뒤 하위 호환용 심볼릭 링크를 제거했다.
- 검증 — backend pytest 386 passed(7.5초,
.venv/bin/python -m pytest), import-linter 4계약 0위반, frontendnext build성공(TypeScript 검사 포함, 전 라우트 생성 정상). - 주의점 발견 —
.venv/bin/pytest로 직접 실행하면 cwd가 sys.path에 안 들어가 수집 오류 31건이 난다.python -m pytest방식이 정본이다(마이그레이션 문제 아님). - 정리 — 이전 데모 저장소 심볼릭 링크 삭제(13바이트 링크만 제거, 실파일 무손실). 구 경로가 박힌
__pycache__전체 삭제 후 386 재통과 확인. 활성 문서 2건(HANDOFF.md재현 경로,demo_guide.mdcd 경로)을com.remakeday로 갱신. - 구 경로 전수 치환 — 사용자 지시로 과거 기록 포함 프로젝트 전체의 이전 데모 저장소 경로 참조를
com.remakeday로 일괄 수정(tester2.md, backend-tests.txt 2건, final-validation-summary.txt — 같은 파일들을 가리키므로 기록 무손실). 예외 3종은 의도적 유지: ①docker-compose.yml의 프로젝트name(테스터 데이터 볼륨 식별자 — 바꾸면 DB가 분리됨), ②/tmp의 이전 데모 저장소 이름 스냅샷·diff 아티팩트명(그 이름으로 실존하는 파일), ③ 옛 저장소 이름 자체를 서술하는 역사 문장(본 로그 및 9/1 마이그레이션 항목). - 남은 것:
git push --force origin main(사용자 승인 대기),./start_demo.sh서버 기동 확인.
데브로그 자동화 — 23:45 일일 기록 + beyondbob 지킬 연동
다른 프로젝트(masterless 23:50·beyondfacade 23:55)와 같은 패턴으로 scripts/jekyll-devlog.sh를 만들었다. 매일 23:45에 ① claude -p가 당일 커밋·수정 파일을 근거로 이 파일(docs/jekyll.md)의 오늘 섹션을 추가/갱신하고, ② 오늘 섹션만 추출해 front matter(title·tags)를 붙여 beyondbob.remakeday.com/_posts/YYYY-MM-DD-dev-log.md로 변환 복사한다. 역할 분리 — com.remakeday는 개발만, beyondbob은 지킬만. 지킬 쪽 포스트는 사본이라 직접 수정 금지(다음 실행 때 덮어씀). 커밋/푸시는 자동화하지 않는다(사용자 직접). awk 섹션 추출·포스트 변환은 오늘 섹션(22줄)으로 검증했고, crontab 등록(45 23 * * *)은 사용자 실행으로 마무리.
마감 정리 — 커밋 상태·정본 위치·음성 산출물
- 커밋 6건 — f2b4926(11:48, 본진 초기 승격) · 570500b(12:50, 승격 마무리·데브로그 자동화) · 20:44 일괄 4건(b0dd281 역할 문서 정리 / b6e44b2 프로덕션 think 제어·채택 반영 / 9ad8ecc 평가 러너 / 09c3f23 모델 평가 정본 A.10~A.18). 푸시까지 완료(HANDOFF 기록).
- 미커밋 — 실플레이 개선 1~3단계 배치 — 26파일 +741/−81, 신규 6파일(백엔드 테스트 5건
test_journey_and_reveal·test_advisor_leads·test_age7_memory_window·test_dormant_scene_action·test_rule_alternatives, 프론트TruthRevealCards.tsx). 테스터 재플레이 확인 후 커밋하기로 하고 대기 중(HANDOFF에 명시). - 수치 정본 위치 — 오늘 실측치는 전부
model_evaluation.md(부록 A.8~A.18 11건 + 변경 이력 14행)와metrics.yml(오늘자 43행 적립)이 정본이다. 이 일지에는 결론만 요약했다. - 음성 산출물 7건 —
output/voice/에 mp3 7건 생성(22:44~22:45). 전부docs/voice.md의 제작 목록과 문장 일치 — 관리자 방송 MA01~MA06 6건 + 회고 낭독 EN03(“지금부터, 무엇이 적용됐고…”) 1건. 생성 도구와 게임 반입·재생 배선은 저장소에 기록이 없다(코드에서output/voice참조 0건) — 반입 시 경위를 함께 기록할 것. - 당일 미결 해소와 새 이월 — 본진 승격 절에서 남겼던 두 건은 당일 해소:
git push --force origin main완료, 서버 기동은 개선 3단계 재기동으로 확인(health npc kanana·core gemma4:12b·/play 200). 어제(09-13) 남긴 Stage 3·4 미실행도 오늘 전부 완료. 내일로 넘기는 것: 테스터 재플레이(관찰 포인트 6개), 재플레이 확인 후 개선 배치 커밋, 4b 한자 혼입 CJK 검사(korean_only 보강), kanana 운영 관찰 3건(사실 질문 회피·질문 관련성·단답 경향).