# WygLore Leaf 2.9.30 > 거대 챗(수백만 토큰급)의 **메모리 부족(OOM) 안정화** 를 중심으로, 2.9.22~2.9.23 에서 다진 변경을 묶은 새 릴리즈입니다. 이전 버전 위에 그대로 덮어 설치하면 되고, 진행 중이던 챗의 기억뜰은 그대로 유지됩니다. | 빌드 | 받을 파일 | |---|---| | **V3** (보통의 RisuAI) | `WygLoreLeaf-2.9.30.js` | | **V2** (Stable RisuAI) | `WygLoreLeaf-v2-2.9.30.js` | ## 2.9.30 — 한 눈에 - **[수정]** 아주 큰 챗에서 채팅 중 튕긴 뒤 **기억 "나이테"(연령 분포)가 전부 "방금"으로 뭉치던 문제** — 멈춰도 처음부터 다시 하지 않고 *멈춘 지점부터 이어서* 따라잡아, 나이테가 무너지지 않습니다. - **[개선]** **맥락 따라잡기를 기기 사양에 맞춰 여러 턴에 나눠 처리** — 모바일·저사양에서 한 번에 메모리가 터지지 않게(빠뜨림 없이 이어서, 전에 튕긴 적 있으면 더 보수적으로). - **[개선]** **튕겨도 진단 정보가 남습니다** — 재시작 후 *정보 → 로그이력* 의 [내보내기] 또는 "직전 진단" 카드로 보고할 수 있어요. - **[개선]** **봇 설정·로어북 기억을 압축 저장** — 큰 기억뜰의 메모리 부담 완화(내용 동일·자동 복원, 대화에서 직접 쌓인 기억은 미대상). - **[수정]** **브라우저에서 다른 탭을 보며 채팅해도** 기억이 "삭제"로 오인되지 않습니다. (+ 개요 탭 [지금 확인]·[변경점 보기]) 항목별 자세한 설명과 그 이전(2.9.9~2.9.21)의 변경은 아래 **상세 기록** 을 참고하세요. --- ## 상세 기록 — v2.9.9 ~ v2.9.30 (항목별) > 아래 24~30번(2.9.22~2.9.23 개발분)이 **2.9.30** 으로 묶여 배포됩니다. 그 위는 이전 누적 변경입니다. 다른 챗·봇의 기억이 섞여 들어가던 문제를 바로잡았습니다. 더불어 "초록 원이 멈추지 않던" 무한 로딩을 여러 갈래로 끊고(보조 모델 빈 응답·화면 밖 안내창·맥락 따라잡기 직후 멈춤), 로어북이 커서 최대 토큰을 넘길 때 자동으로 줄여 보내며, Gemini(Vertex 포함)의 추론(thinking) 강도를 직접 조절하는 칸도 더했습니다. 그리고 *새로 시작한 챗* 에서 캐릭터·세계관 정보를 잘 끌어오지 못하던 문제를 — RisuAI 본체의 로어북 활성화 방식을 따라 — base 로어북이 먼저 들어가도록 고치고, 전송길이 자동 조절이 한국어 토큰을 더 정확히 가늠해 *비율을 낮춰도 예산을 넘기던* 문제와 줄이는 순서가 로어북 우선순위를 따르도록 다듬었습니다. 이어 **상태창·삽화 같은 봇 출력 지침이 안 나오던 문제**, **봇 프롬프트가 예산을 꽉 채우면 기억이 통째로 빠지던(0 주입) 문제** 를 고치고, 자율주행처럼 *유저 입력이 없어도* 스토리에 등장한 캐릭터가 유지되도록 **감쇠 장면 로스터** 를 더했으며, 연관 기억 활성화도 로어북과 *같은 실제 챗* 을 읽도록 정렬했습니다. (진행 안내 문구도 "중간 맥락 따라잡기" 로 다듬었습니다.) 이어 2.9.17 부터 2.9.22 까지는 **다른 플러그인과 함께 켜도 멈추지 않도록** 다지고, 큰 패치 뒤 **적대적 점검으로 데이터 무결성 16건**을 한 번에 보강했으며, **변수·상태창이 바뀔 때 "대량 삭제"로 오인하던 문제**를 막고, **채팅에 기억뜰을 임베드할 때의 메모리 부담**을 크게 줄였습니다. 또한 **브라우저에서 다른 탭을 보며 채팅해도** 기억이 "삭제"로 오인되지 않도록 다졌습니다. 그리고 **2.9.23** 은 *아주 긴 채팅(수백만 토큰급)에서의 메모리 부족(OOM)* 을 정조준했습니다. 큰 챗에서 채팅을 칠 때 튕긴 뒤 **기억의 "나이테"(연령 분포)가 전부 "방금"으로 뭉치던 문제** 를 막고(멈춰도 처음부터 다시 하지 않고 *멈춘 지점부터 이어서* 따라잡음), **기기 사양에 맞춰 여러 턴에 나눠 처리** 해 한 번에 터지지 않게 하고, **튕겨도 진단이 남아 보고** 할 수 있게 했으며, **봇 설정·로어북 기억을 압축 저장** 해 큰 기억뜰의 메모리 부담을 줄였습니다. | 빌드 | 받을 파일 | |---|---| | **V3** (보통의 RisuAI) | `WygLoreLeaf-2.9.30.js` | | **V2** (Stable RisuAI) | `WygLoreLeaf-v2-2.9.30.js` | 이전 버전 위에 그대로 덮어 설치하면 됩니다. 진행 중이던 챗의 기억뜰은 그대로 유지됩니다. --- ## 무엇을 고쳤나 ### 1. 다른 챗·봇의 기억이 섞여 들어가던 문제 (가장 중요) **증상** — 챗 A(캐릭터 B)에서 놀다가 *다른* 챗 C(캐릭터 D)로 갔는데, 갑자기 페르소나가 B 를 언급하는 등 **이전 챗·봇의 기억이 엉뚱한 챗에 섞여** 나오던 문제. **원인** — 패널을 닫고 채팅하던 중 챗을 바꾸면, *아직 기억뜰이 없는 새 챗* 으로 들어갈 때 이전 챗의 기억이 메모리에 남아 새 챗의 자리로 저장되고 있었습니다. (패널을 열어 둔 채 전환하는 경로에는 이미 막혀 있던 누수가, 채팅 중 전환 경로에만 빠져 있었습니다.) **해결** — 기억뜰이 없는 챗으로 들어갈 때 메모리를 먼저 비웁니다. 이전 챗의 기억은 그 챗의 자리에 이미 저장돼 있어 손실 없이 보존됩니다. > 이미 섞여 버린 기억뜰은 해당 챗에서 **기억뜰 초기화**로 정리할 수 있습니다. 이 업데이트는 *새로* 섞이는 것을 막습니다. ### 2. 보조 모델이 빈 응답을 반복하면 연관기억 작업을 자동으로 멈춥니다 **증상** — 보조(연관기억) 슬롯에 빈 응답만 돌려주는 모델을 넣으면, 응답 직전에 수백 개의 기억을 헛돌며 인덱싱을 반복해 초록 표시가 멈추지 않거나 매 턴이 한참 멈췄습니다. 특히 *전체 맥락 따라잡기 직후* 자주 나타났습니다. **해결** — 보조 슬롯이 연속으로 빈 응답을 주면, 그 세션 동안 연관기억 인덱싱·검색을 자동으로 중단하고 한 번 안내합니다. 보조 모델을 정상 작동하는 것으로 바꾸면(또는 비우면 본 모델로 폴백) 즉시 회복됩니다. 같은 인덱싱이 끝나기 전에 다음 턴이 또 시작해 *중첩되던* 것도 막았습니다. > 보조 슬롯에는 *응답이 정상으로 나오는 모델* 을 쓰세요. 비워두면 본 모델을 그대로 씁니다. ### 3. 화면에 안 보이는 안내창에 묶여 멈추던 무한 로딩 **증상** — 모바일 등에서 *전체 맥락 따라잡기 확인창* 이나 *대량 삭제 경고창* 이 화면에 못 떠 보이지 않을 때, 누를 수 없는 그 창을 기다리며 응답이 영영 멈췄습니다. **해결** — 창을 띄울 수 없는 환경이면 안전한 기본 동작으로 즉시 넘어갑니다(요청은 그대로 진행, 다음 턴 재시도). 보이는데 가려진 경우를 대비한 시간 백스톱도 넣었습니다. ### 4. 로어북이 커서 최대 토큰을 넘기면 자동으로 줄여 보냅니다 **증상** — *항상 활성* 로어북이나 큰 봇 카드(설명·첫 메시지 포함)가 많으면, 전송길이 자동 조절을 켜고 비율을 낮춰도 로어북은 줄지 않아 최대 토큰을 훌쩍 넘겼습니다(요청 자체가 토큰 한도 에러). **해결** — 이제 한도를 넘기면 *우선순위가 낮은 것부터* 자동으로 줄입니다. 활성도 낮은 에피소드 기억을 먼저, 그 다음 로어북을 *봇 제작자가 매긴 우선순위(insertorder)가 낮은 것부터* 줄이며, *지금 이 장면에 살아있는 기억* 과 *설명·첫 메시지* 는 마지막까지 지킵니다. (설명·첫 메시지는 캐릭터 카드에 어차피 들어가 있어, 우리 주입에서 빠져도 프롬프트에는 남습니다. 우선순위 처리의 자세한 개선은 아래 §10.) > *동작 변경 안내*: 이전에는 로어북(세계관)을 절대 줄이지 않았지만, 최대 토큰을 넘겨 요청이 통째로 실패하는 것보다 우선순위 낮은 항목을 줄여 통과시키는 쪽으로 바꿨습니다. 깊이 모드(기본)와 전송길이 자동 조절을 켠 경우에 적용됩니다. 잘림이 잦으면 *항상활성 로어북을 줄이거나 최대 컨텍스트를 키워* 주세요. ### 5. 임베딩 연결 테스트의 잘못된 경고를 바로잡았습니다 임베딩 연결 테스트가 성공해도 동작 이력에 "vector 아님" 경고가 뜨던 오발화를 고쳤습니다. (임베딩은 출력 토큰이 0이 맞습니다.) ### 6. Gemini(Vertex 포함)에서 추론(thinking) 강도를 직접 조절할 수 있습니다 요청을 반영해, **Vertex AI · Gemini · Custom (Gemini 호환)** 프로바이더 설정에 **"추가 generationConfig (JSON)"** 칸을 더했습니다. 일부 flash-lite 계열이 과하게 추론하느라 보조 응답이 비거나 느려질 때, 여기에 값을 직접 넣어 줄일 수 있습니다. - 2.5 계열 예: `{"thinkingConfig": {"thinkingBudget": 0}}` - 3.x 계열 예: `{"thinkingConfig": {"thinkingLevel": "low"}}` - 여기 값이 플러그인 기본값을 덮어쓰며, 잘못된 JSON 은 조용히 무시됩니다. ### 7. 맥락 따라잡기 직후 응답이 한참 멈추던 시간을 줄였습니다 (2.9.10) **증상** — 로어북이 많은 큰 봇에서 *맥락 따라잡기* 가 돌면, 응답 직전이 20초 넘게 멈추곤 했습니다. **원인** — 맥락 따라잡기가 검색용 *카논 인덱스 빌드*(로어북 수백 개를 한 번에 인덱싱)까지 요청을 붙잡은 채 끝내고 있었습니다. **해결** — 인덱스 빌드를 요청 흐름 밖으로 뺐습니다. 응답이 먼저 나가고, 인덱스는 뒤에서(비차단) 짓습니다. 인덱싱에 쓰던 시간만큼 응답 직전 멈춤이 줄어듭니다. (연관 검색 보조는 한 박자 늦게 완성되지만 응답 품질엔 영향이 없습니다.) ### 8. 고급 설정이 챗을 바꾸면 도로 꺼지던 문제 (2.9.10) **증상** — 전송길이 자동 조절(자동 줄임) 등 고급 설정을 켜 둬도, 다른 챗에 갔다 오거나 새로고침·재설치하면 도로 꺼지던 문제. **원인** — 이 설정들이 *챗별 저장본* 에만 보관돼, 챗을 바꾸면 다른 챗의 옛 저장본이 불러와지며 켠 설정을 덮어썼습니다. **해결** — 고급·의미추출 설정 탭의 사용자 설정 전체(자동 줄임·깊이 모드·재정렬·단계 탐색·맥락 따라잡기 토글·임베딩 등)를 *전역* 으로 보관하도록 했습니다. 한 번 바꾸면 챗 전환·재설치와 무관하게 유지됩니다. ### 9. 새 챗에서 캐릭터·세계관 정보를 못 불러오던 문제 (2.9.11) **증상** — 어느 정도 진행된 챗은 괜찮은데, *처음 시작한 챗* 에서는 캐릭터·세계관 정보를 잘 모르는 것처럼 굴던 문제. 리퀘스트를 까 보면 관련 로어북이 거의 안 들어가 있었습니다. **원인** — 연관 검색용 인덱스가 아직 준비되기 *전* 이라(맥락 따라잡기를 거친 챗은 준비됨), 첫 입력이 로어북 키워드에 직접 안 닿으면 *관련* 로어북을 끌어올 길이 없었습니다. **해결** — 인덱스가 없어도 base 로어북이 먼저 제 역할을 하도록, RisuAI 본체의 로어북 활성화 방식을 따라 두 가지를 더했습니다: - *연쇄 활성화* — 이미 들어간 설명(desc)·항상활성 로어북의 *본문* 이 다른 항목을 언급하면 그 항목도 함께 불러옵니다. (RisuAI 본체의 재귀 스캔과 같은 방식. 예: 설명이 "엘리시아 왕국"을 언급하면 엘리시아 로어북도 자동으로.) - *새 챗 기본 로어북* — 첫 메시지가 어떤 키워드도 못 건드려도, 봇 제작자가 우선순위로 둔 로어북 상위 항목을 기본으로 넣습니다. 연관 검색(인덱싱) 기반의 정교한 끌어오기는 그 *위에* 그대로 얹힙니다 — 이건 그 전에 새 챗이 최소한 굶지 않게 하는 base 입니다. 깊이 모드(라이트/표준/깊게)에 따라 연쇄 깊이가 1~3 단계로 조절됩니다. ### 10. 전송길이 자동 조절 — 한국어 토큰 정확도 + 로어북 우선순위 (2.9.11) 위 §9 의 연쇄 활성화가 촘촘한 봇에서 로어북을 많이 끌어오면, 전송길이 자동 조절이 *제대로 줄여 주지 못해* 예산을 넘기는 경우가 있었습니다. 두 가지를 고쳤습니다: - *한국어 토큰 정확도* — 줄일 양을 가늠할 때 글자 수를 토큰으로 환산하는데, 한국어가 영어보다 토큰이 훨씬 조밀한 걸 반영하지 못해(평균치 가정) 비율을 낮춰도 예산을 넘기곤 했습니다. 이제 한국어·한자 글자를 더 무겁게 세어 *실제 토큰에 가깝게* 줄입니다. - *로어북 우선순위 존중* — 줄일 때 봇 제작자가 매긴 로어북 우선순위(insertorder)를 따릅니다. 항상활성이라고 무조건 지키고 트리거라고 무조건 먼저 버리던 걸 바꿔서, *우선순위 높은 트리거 항목이 우선순위 낮은 항상활성보다 먼저 잘리지 않게* 했습니다. (지금 장면에 살아있는 항목은 여전히 최후까지 보호.) > 참고: 자동 조절의 비율 설정이 이제 *실제 예산 대비 비율대로* 동작합니다. 이전에 한국어 봇에서 비율을 낮춰 쓰셨다면 더 줄어들 수 있으니, 너무 적게 들어가면 비율을 조금 올려 주세요. 깊은(thorough) 모드의 자동 안전장치는 과하게 깎이지 않도록 완화돼 있습니다. ### 11. 한국어 로어북 키워드 매칭 정확도 (2.9.11) **증상** — 여러 어절로 된 한국어 로어북 키워드("엘리시아 왕국")가 본문에 조사·어순·띄어쓰기 차이로 끊겨 나오면("엘리시아*의* 왕국") 아예 안 잡혀, 관련 로어북이 안 끌려오던 문제. **해결** — 키워드를 어절 단위로 나눠 *일치율*(몇 어절이 맞았는지)로 매칭합니다. 절반을 넘게 맞으면 끌어오고, *더 많이 맞는 키워드를 우선* 합니다. 띄어쓰기 차이("마법사 길드"와 "마법사길드")도 양쪽 다 잡습니다. (RisuAI 본체의 띄어쓰기 무시 매칭과 같은 방향에 어절 일치율을 더한 것.) ### 12. 유저가 직접 언급한 캐릭터·항목이 안 들어가던 문제 (2.9.11) **증상** — 대화에서 **직접 이름을 부른** 캐릭터인데도 그 정보가 프롬프트에 안 들어가고, 정작 현재 장면과 무관한 캐릭터들이 잔뜩 들어가던 문제. **원인** — 봇이 캐릭터 로어북 우선순위(insertorder)를 *전부 같은 값* 으로 둔 경우, 토큰 한도로 줄일 때 "유저가 방금 이름을 부른" 신호를 구분 못 하고 무관한 동순위 항목과 똑같이 취급해 임의로 잘렸습니다. 더해서, 캐릭터 목록(NPC 리스트)을 훑던 §9 의 연쇄 활성화가 *등장인물 전원* 을 끌어와 자리를 차지했습니다. **해결** — (1) 유저가 *직접 키워드로 부른* 항목은 우선순위와 무관하게 **끝까지 보호** 합니다(지금 장면에 살아있는 항목 다음 순위). (2) 연쇄 활성화가 한 번에 끌어오는 양에 상한을 둬, 목록류가 전원을 범람시키지 않게 했습니다. 동작 이력의 `canonical · select` 에 `matched=N`(직접 매칭 수)이 표시됩니다. ### 13. 전송길이 자동 조절이 봇 시스템 프롬프트를 인식 (2.9.11) **증상** — 자동 줄임을 켜고 비율을 정해도, 글쓰기 지침 등 *봇 자체의 거대한 시스템 프롬프트* 가 있는 봇에서는 전송 길이가 설정 예산을 훌쩍 넘겼습니다(한 사례 171%). **원인** — 자동 줄임이 *우리가 넣는 기억 블록* 만 비율 안에 맞췄을 뿐, 봇이 이미 차지한 시스템 프롬프트 크기를 몰라서 — 기억(예산의 80%) + 시스템(예산의 80%) = 예산 초과가 됐습니다. **해결** — 이제 우리 inject *전* 의 프롬프트(시스템 + 대화) 크기를 먼저 재고, *남은 자리* 에 맞춰 기억 블록을 줄입니다. 시스템 프롬프트가 클수록 우리 기억을 더 줄여 전체가 예산 안에 들어옵니다. 이때도 §12 대로 유저가 직접 부른 항목·지금 장면 항목은 끝까지 보호하므로, 남은 자리엔 *가장 관련 있는 것부터* 들어갑니다. ### 14. 유저 입력을 못 읽던 봇 대응 — 입력을 프롬프트 템플릿에 박아넣는 경우 (2.9.11) **증상** — 일부 복잡한 봇(긴 지침을 시스템 프롬프트에 넣고 유저 입력을 그 템플릿 *안에* 끼워넣는 형식)에서, 대화에서 직접 부른 캐릭터·항목이 전혀 안 잡히고 엉뚱하게 첫 메시지/세계관 기준으로만 기억이 끌려오던 문제. (§12의 "직접 부른 항목 보호"가 작동하려면 입력을 읽어야 하는데, 그 입력 자체를 못 보고 있었습니다.) **원인** — WygLore 가 최종 프롬프트(메시지 배열)의 끝쪽에서 유저 입력을 찾는데, 이런 봇은 입력을 *시스템 프롬프트 템플릿 안* 에 넣어버려 그 위치에 없었습니다. 그래서 첫 메시지/세계관 텍스트로 잘못 매칭했습니다. **해결** — 이제 *실제 챗* 에서 유저 입력을 직접 읽습니다(프롬프트 템플릿이 아니라). 입력을 어떻게 감싸든 진짜 입력을 보고 매칭합니다. (챗 접근이 안 되는 환경은 기존 방식 폴백 — 일반 봇은 결과 동일.) 이로써 §9·§12·§13 의 개선이 *비로소 올바른 입력 위에서* 맞물립니다. ### 15. 상태창·삽화 에셋이 출력 안 되던 문제 (2.9.12) **증상** — WygLore 를 켜면 봇의 *상태창·이미지(삽화)* 출력이 안 되던 문제. 특히 그 지침이 *로어북* 에 있을수록 더 심했습니다. **원인** — 상태창·이미지·포맷 같은 *출력 지침* 이 로어북에 있으면, WygLore 가 그걸 흡수해 "동원 가능 풀(선택지 · 의무 아님)" 로 재포장했습니다. 그러면 LLM 이 "상태창을 출력해라" 를 *선택지* 로 보고 건너뜀. (글로벌 노트에 있으면 WygLore 가 흡수하지 않아 덜 영향받습니다.) **해결** — 흡수된 로어북 중 *출력 지침* (상태창·이미지·포맷 명령)을 자동 감지해, "동원 가능 풀" 밖 별도 위치에 *원본 그대로* 둡니다(선택지 프레이밍 제거 — 강조 문구는 붙이지 않음). 전송길이를 줄일 때도 이 지침은 끝까지 보호해 항상 들어갑니다. ('상태창 불신론자' 같은 단순 *언급* 은 지침으로 오인하지 않습니다.) ### 16. 대화가 길어지면 연관 기억이 갑자기 0개 들어가던 문제 (2.9.13) **증상** — 새 챗 초반엔 캐릭터·세계관을 잘 가져오다가, 대화가 길어지거나 인덱싱이 돌고 난 뒤부터 *연관 기억·로어북이 거의/전혀* 안 들어가던 문제. **원인** — 봇 자체의 거대한 프롬프트(시스템 지침 + 누적된 대화 + 봇이 직접 넣는 로어북)가 전송 예산을 꽉 채우면, 전송길이 자동 조절의 "남은 자리(예산 − 기존 프롬프트)" 가 0이 되어 — WygLore 가 *고른 기억을 전부* 버렸습니다(실측: 100개 선택했는데 0개 주입). 우선순위 로직은 *버리는 순서* 만 정할 뿐, 남은 자리가 0이면 순서와 무관하게 다 잘립니다. 대화가 길수록(또는 인덱싱이 도는 시점과 겹쳐) 이 상태에 빠졌습니다. **해결** — 이제 *꼭 필요한 코어* (출력 형식 지침 · 유저가 직접 부른 캐릭터 · 지금 장면에 살아있는 기억)는 남은 자리가 0이어도 *버리지 않는 최소 보장(floor)* 을 둡니다. 동시에 *하드 한도(최대 컨텍스트)* 로 묶어 토큰 한도 에러는 그대로 막습니다 — 코어는 응답 예약의 절반까지만 차지하고(나머지 절반은 응답 보장), 코어가 그보다 크면 코어도 우선순위 순(출력 지침 > 현재 장면 > 호명)으로 한도까지만. 결과: 거대 프롬프트 봇에서도 "0 주입" 이 사라지고 핵심 기억은 항상 들어갑니다. > 그래도 잘림이 잦으면 *항상활성 로어북을 줄이거나 최대 컨텍스트를 키워* 주세요 — 봇 프롬프트 자체가 예산을 넘는 상황입니다. ### 17. 스토리에 등장한 캐릭터를 유저 입력에 없어도 유지 — 자율주행 대응 (2.9.14) **증상** — 자율주행(유저 입력이 비거나 "계속" 수준)으로 장면이 흘러갈 때, 몇 턴 전 스토리에 등장한 캐릭터·장소가 최근 입력에 다시 안 나오면 점점 빠지던 문제. **배경** — 캐릭터 매칭은 최근 메시지(*서술 포함* — 유저 입력만 보는 게 아닙니다)를 보지만, 그 윈도우(기본 4메시지) 밖으로 밀려나면 빠집니다. 원래 이걸 이어주는 건 연관 기억(episodic) 활성화인데, 인덱싱 전·초반엔 비어 있어 이어줄 게 없었습니다. **해결** — *감쇠 장면 로스터* 를 더했습니다. 매 턴 스토리에서 매칭된 캐릭터·항목을 기억해, 키워드 윈도우 밖으로 밀려나도 *가중치가 살아있는 동안(약 5턴)* 계속 끌어오고 보호합니다. 재등장하면 가중치가 1.0 으로 갱신되고, 장면에서 빠지면 서서히 fade. 유저가 직접 입력하지 않아도(자율주행) 최근 등장 인물이 유지됩니다. (전송길이가 빡빡하면 §16 코어 보호 대상에 이 장면 인물도 포함됩니다. 챗을 바꾸면 로스터는 비워져 다른 챗과 안 섞입니다.) ### 18. 연관 기억(episodic) 활성화도 실제 챗을 읽도록 정렬 (2.9.15) **배경** — §14(로어북)는 유저 입력을 *실제 챗* 에서 직접 읽도록 고쳤지만, 연관 기억(episodic) 활성화는 여전히 *전송용 프롬프트(formated)* 의 마지막 2개만 봤습니다. 그래서 (a) 입력을 시스템 프롬프트 템플릿 안에 박아넣는 봇에선 연관 기억이 실제 입력을 놓치고, (b) 활성화 윈도우가 로어북 매칭 윈도우와 어긋났습니다. **해결** — 연관 기억 활성화도 로어북과 동일하게 *실제 챗* 을 우선 읽고, 같은 윈도우(전송길이 설정의 키워드 윈도우)를 씁니다. 챗 접근이 안 되는 환경은 기존 방식으로 폴백하므로 일반 봇은 결과가 같습니다. 이로써 매칭(로어북)·활성화(연관 기억)·장면 로스터가 *모두 같은 입력* 위에서 맞물립니다. (이미 가져온 챗을 재사용 — 추가 fetch 없음.) ### 19. "맥락 따라잡기" 진행 안내 문구 정리 (2.9.16) 진행 오버레이의 제목을 "전체 맥락 따라잡기" 에서 **"중간 맥락 따라잡기"** 로 바꿨습니다. "전체" 는 대화를 통째로 다시 처리하는 것처럼 오해될 수 있는데, 실제로는 *아직 처리되지 않은 구간(중간)* 만 따라잡습니다. 동작은 그대로이고 표현만 정확하게 다듬은 것입니다. ### 20. 다른 플러그인과 함께 켜도 멈추지 않습니다 (2.9.17~2.9.18) 여러 플러그인을 같이 쓰는 환경에서, 다른 플러그인이 화면(메인 작업)을 오래 붙잡아도 위그로어가 같이 멈추지 않도록 다졌습니다. - *응답 지연 시 안전 통과* — 본체나 다른 플러그인의 응답이 늦으면, 무한정 기다리지 않고 정해진 시간이 지나면 이번 턴은 그냥 지나가게(안전 우회) 했습니다. 정상 환경에는 영향이 없습니다. - *중복 주입 방지* — 서버 오류로 재시도가 반복될 때 같은 기억이 여러 번 겹쳐 들어가지 않도록, 한 번만 들어가게 표시해 둡니다. - *앞/뒤 작업 분리* — 채팅(앞)과 뒤에서 도는 기억 처리(뒤)를 분리해, 한쪽이 느려도 다른 쪽을 막지 않게 했습니다. ### 21. 기억 안전성 — 적대적 점검으로 16건을 한 번에 보강 (2.9.19) 큰 패치 뒤라, 여러 각도에서 일부러 약점을 찾는 *적대적 점검* 을 거쳐 데이터 무결성 문제 16건을 한 번에 고쳤습니다. 가장 중요한 두 가지는 다음과 같습니다. - *챗 간 기억 섞임 차단* — 맥락 따라잡기가 뒤에서 도는 동안 다른 챗으로 옮기면, 처리 중이던 기억이 새 챗 자리에 섞여 저장될 수 있었습니다. 이제 처리 도중 매 단계마다 "지금 그 챗이 맞는지" 다시 확인해, 챗이 바뀌면 즉시 멈추고 잘못된 저장을 건너뜁니다. - *저장 실패 시 무손실* — 저장 공간이 빠듯할 때(큰 기억뜰·모바일) 일부 조각이 조용히 안 써지고도 "다 됐다"고 표시될 수 있었습니다. 이제 한 조각이라도 실패하면 옛 저장본을 그대로 두고(손실 0) 다시 시도하며, "공간 확인" 안내가 정상적으로 뜹니다. 그 밖에 흔한 별칭 키워드가 많을 때의 매 턴 멈칫함, 진단 로그를 내보낼 때 서사·로어북 본문이 평문으로 섞여 나가던 것(이제 가려서 내보냄), 일부 모델의 빈 응답 처리 등도 함께 고쳤습니다. ### 22. 멈춤·프리즈·무한 로딩을 추가로 끊었습니다 (2.9.19) - *긴 챗 맥락 따라잡기 총 시간 제한* — 처리할 분량이 아주 많아도 차단 모드가 무한정 붙잡지 않도록 전체 시간 상한을 두고, 넘으면 자동으로 뒤에서 이어 처리합니다(진행분 보존). - *인덱스 만들기 화면에 [중단] 추가* — 느리거나 응답이 안 오는 모델이 인덱스 빌드 화면으로 매 턴 가리던 것을, 멈춤 감지와 취소 버튼으로 끊을 수 있게 했습니다. - *생각(thinking) 모델의 헛도는 호출* — 보조 슬롯에 추론형 모델을 쓸 때 생각만 하고 빈 답을 주면, 이제 그걸 무용한 응답으로 세어 자동으로 호출을 멈추고 안내합니다. ### 23. 변수·상태창 봇에서 "대량 삭제" 오경고가 사라집니다 (2.9.20) **증상** — HP·호감도 같은 *변수가 바뀌거나 상태창이 갱신될 때*, 위그로어가 그걸 "채팅이 삭제됐다"고 잘못 보고 대량 삭제 경고창을 띄우거나, 기억을 불필요하게 다시 처리하던 문제. **원인** — RisuAI 는 응답을 저장할 때 본문 안의 변수·매크로를 그 순간 값으로 굳혀 다시 기록합니다. 그래서 *내용은 같은 메시지* 인데 변수 값만 달라져도, 위그로어가 "내용이 바뀌었다 = 지워졌다"로 오해하던 것입니다. **해결** — 메시지가 같은지 판단할 때 *변수로 변하는 부분(상태창·패널·재발급된 식별자)을 구조적으로 걸러내고*, 진짜 삭제(메시지 자체가 사라짐)일 때만 경고·재처리하도록 좁혔습니다. 상태창을 덧붙이는 흔한 패턴도 "삭제"로 보지 않습니다. > 기억이 실제로 사라진 적은 없습니다 — 불필요한 경고와 재처리였을 뿐이고, 최신 버전으로 올리면 더는 뜨지 않습니다. ### 24. 채팅에 기억뜰을 임베드할 때 메모리 부담을 줄였습니다 (2.9.21) *데이터 복구 → 백업·복원* 의 **[이 채팅에 임베드]** 는 지금 기억뜰을 채팅 자체에 넣어, RisuAI 채팅을 내보내거나 다른 기기로 옮길 때 기억뜰이 함께 따라가게 하는 명시적 백업입니다. **증상** — 예전에는 이때 기억뜰을 *압축 없이 통째로* 채팅에 얹어, 그 채팅이 열려 있는 동안 메모리에 크게 상주했습니다. 큰 기억뜰·모바일에서 매 턴 멈칫함이나 메모리 부족의 한 원인이었습니다. **해결** — 이제 임베드본을 *압축해 저장* 합니다(대략 7~10배 작게). 채팅에 상주하는 용량이 크게 줄어 매 턴 부담이 내려갑니다. 내용은 그대로이고, 옛 임베드본도 문제없이 복원됩니다. - *예전에 임베드해 둔 채팅* — 압축 전 형식으로 임베드해 둔 분께는 **개요 탭 위에 안내 카드** 가 뜹니다. **[지금 재압축]** 한 번이면 내용 그대로 압축 형식으로 바꿔 줍니다(기억을 다시 만드는 게 아니라 이미 저장된 것을 그대로 압축 — 안전). - *큰 기억뜰을 임베드할 때* — 임베드 전에 메모리 부담을 미리 알려 드립니다. 막지는 않되, 가벼운 대안인 *파일로 내보내기* 도 함께 안내합니다. > 기억은 그대로입니다 — 저장 방식만 압축으로 바뀌었을 뿐, 임베드한 내용도 복원 결과도 동일합니다. 임베드 기능을 쓰지 않으셨다면 따로 하실 일은 없습니다. ### 25. 다른 (크롬) 탭을 보며 채팅해도 "삭제"로 오인되지 않습니다 (2.9.22) **증상** — 채팅이 진행되는 동안 브라우저에서 *다른 탭으로 잠깐 옮겨* 두면, 돌아왔을 때 "메시지가 대량 삭제됐다"는 경고가 뜨거나 기억을 불필요하게 다시 처리하던 문제. **원인** — 브라우저는 *보이지 않는 탭* 의 작업 속도를 절전 차원에서 늦춥니다. 그 사이 RisuAI 가 최신 메시지를 미처 다 저장하지 못한 채로 위그로어가 채팅을 읽으면, *아직 안 들어온 최근 메시지* 를 "삭제됐다"고 오해한 것입니다. **해결** — 탭이 백그라운드이거나 메시지가 갑자기 크게 줄어 보이면 *바로 삭제로 단정하지 않고* 다음 정상 시점에 한 번 더 확인합니다. 일시적이면(탭으로 돌아와 전체가 다시 보이면) 조용히 넘어가고, *진짜 삭제일 때만* 경고합니다. 삭제 경고 창에도 "일시적 오류일 수 있으니 새로고침 후 다시 시도" 안내를 더했습니다. > 기억이 실제로 사라진 적은 없습니다 — 보수적으로 한 박자 늦춰 확인할 뿐이라, 정말 대량 삭제한 경우는 (탭을 보고 있을 때) 여전히 정상적으로 경고됩니다. ### 26. 새 버전 확인·변경점 보기를 개요 탭에서 바로 (2.9.22) 개요 탭에 **[지금 확인]**(6시간 캐시를 건너뛰고 최신 버전을 바로 조회하는 강제 확인)과, **최신 버전을 쓰는 중이어도 항상 누를 수 있는 [변경점 보기]**(릴리즈 노트 열람) 버튼을 더했습니다. 둘 다 익명 정적 파일 1개만 받으며 개인정보 전송은 없습니다. (이전엔 정보 탭에만 있던 [지금 확인] 을 개요에도 노출.) ### 27. 큰 챗에서 튕긴 뒤 기억 "나이테"가 전부 "방금"으로 뭉치던 문제 (2.9.23, 돌딱님 보고) **증상** — 수백만 토큰급 큰 챗에서 기억의 나이(연령 분포)가 오래된 것·최근 것으로 정상적으로 나뉘어 있다가, 채팅을 한 번 치면 메모리 부족(OOM)으로 튕기고, 그 뒤 **모든 기억이 "갓 생긴 기억"으로 뭉쳐** 보이던 문제. **원인** — 큰 챗은 맥락 따라잡기가 한 번에 못 끝나고 도중에 튕깁니다. 그러면 다음 메시지마다 *처음부터 다시* 돌면서 기억의 기준 시간을 0으로 되돌려, 기존 기억의 나이가 전부 "0(방금)"으로 무너지고 — 그 전체 재처리가 **또 메모리를 터뜨리는 악순환** 이었습니다. **해결** — 도중에 멈춰도(튕겨도) **멈춘 지점부터 이어서** 따라잡습니다(처음부터 다시 X). 기준 시간을 함부로 0으로 되돌리지 않아 나이테(연령 분포)가 무너지지 않습니다. > 이미 "방금"으로 뭉친 나이테는 백업이 없으면 원래대로 되돌릴 수 없습니다. 이 업데이트는 *그 뭉침이 새로 일어나는 것* 을 막습니다. (기억 자체가 사라진 적은 없고, 나이 표시만 초기화됐던 것입니다.) ### 28. 맥락 따라잡기를 기기에 맞춰 여러 턴에 나눠 처리 (2.9.23) 모바일·저사양에서 아주 큰 챗을 따라잡을 때, **한 번에 다 처리하지 않고** 한 턴에 안전한 만큼만 처리하고 다음 턴에 이어갑니다. 한 번에 메모리가 터지는 일을 막습니다. 데스크탑 등 여유 있는 환경은 종전대로 한 번에 처리합니다. 전에 메모리 부족으로 튕긴 적이 있으면 자동으로 **더 잘게** 나눠 처리하고(보수적 조절), 끝까지 무사히 따라잡으면 다시 평소대로 돌아옵니다. 나눠 처리해도 **빠뜨리는 기억은 없습니다** — 다음 턴에 이어서 채웁니다. ### 29. 튕겨도 진단 정보가 남아 보고할 수 있습니다 (2.9.23, 돌딱님 요청) **증상** — 메모리 부족 등으로 탭이 튕기면 그때까지의 동작 기록이 **전부 날아가** 원인을 알릴 방법이 없었습니다("튕겨서 로그를 못 따겠다"). **해결** — 이제 부팅 시점과 맥락 따라잡기 진입 시점의 진단 정보를 **저장에 남깁니다**(튕겨도 보존). 재시작한 뒤 *정보 → 로그이력* 에서 **[내보내기]** 하거나, 같은 화면의 **"직전 진단"** 카드를 캡처해 주시면 됩니다. (사적인 서사·로어북 본문은 내보낼 때 가려집니다.) ### 30. 봇 설정·로어북 기억을 압축 저장 — 큰 기억뜰의 메모리 부담 완화 (2.9.23) 봇의 설명·로어북에서 흡수한 기억(설정·세계관 부분)은 **봇 자산에서 언제든 다시 만들 수 있습니다**. 그래서 저장할 때 이 부분 본문을 비워 두고 필요할 때 **자동 복원** 하도록 바꿔, 저장·메모리 부담을 줄였습니다. 패널을 열거나 다음 메시지를 보낼 때 자동으로 채워지므로 화면에 빈칸으로 보이지 않고, **내용은 그대로** 입니다. 대화에서 직접 쌓인 기억(에피소드)은 다시 만들 수 없으므로 **압축 대상이 아니며 그대로 온전히 보관** 됩니다. (설정에서 이 압축을 끌 수도 있습니다.) --- ## 진행 중이던 챗은 그대로 이어집니다 업데이트 후에도 쓰던 챗의 **기억뜰**은 그대로 유지됩니다. 덮어 설치만 하면 되고, 따로 할 일은 없습니다. ## 받기 - V3: `WygLoreLeaf-2.9.30.js` - V2: `WygLoreLeaf-v2-2.9.30.js` 여전히 같은 증상이 보이거나 새 질문이 생기면 *RisuAI 빌드 · 함께 켠 다른 플러그인 · 사용 모델(보조 슬롯 포함) · 모바일/PC · 봇* 환경과 함께 알려 주세요. 늘 즐거운 기록 되시길. --- ## 버전별 기술 요약 기술적 변경의 압축 기록입니다. 일반 사용에는 위 설명으로 충분합니다. - **2.9.9** — 챗·봇간 기억 섞임(누수) 차단 · 보조 슬롯 빈 응답 서킷 브레이커(+중첩 빌드 락) · 화면 밖 모달 무한 로딩 가드 · 로어북 자동 토큰 cap(우선순위 trim) · 임베딩 연결 테스트 경고 오발화 수정 · Gemini thinking 직접 제어 칸(Vertex 포함). - **2.9.10** — 맥락 따라잡기 인덱스 빌드 비차단 분리(응답 직전 멈춤 단축) + 고급 설정 전역화(챗 전환·재설치에도 안 꺼짐). - **2.9.11** — 새 챗 base 로어북 — canonical 재귀(연쇄) 활성화 + 첫턴 폴백 길이 게이트 제거(RisuAI recursiveScanning 동등, 인덱스 없이도 base 보장) + 자동 cap 의 한국어 토큰 추정 교정(CJK-aware) · 로어북 insertorder 우선순위 trim(상수·트리거 한 저울) + CJK 키워드 어절 일치율 매칭(다중 어절/조사/띄어쓰기 내성) + 입력 직접 매칭 항목 cap 보호(io 동률에서 유저 호명 항목 보존) · 재귀 추가량 cap(NPC 리스트 전원 범람 차단) · 자동 cap 의 시스템 프롬프트 인식(budget − 기존 프롬프트 = 남은 자리에 맞춤, 171% 초과 수정) · 유저 입력을 프롬프트 템플릿에 박아넣는 봇 대응(triggerText 를 실제 챗에서 직접 — 위 매칭/보호가 비로소 올바른 입력 위에서 작동). - **2.9.12** — 흡수된 로어북 *출력 지침*(상태창·이미지·포맷)을 선택지 풀 밖 별도 위치에 원본 그대로(+트림 최후 보호) — "일반 위그로어에서 에셋 출력 안 됨" 수정. - **2.9.13** — inject auto-cap 의 must-have 코어 floor — 봇 프롬프트가 budget 을 꽉 채워 남은 자리 0이면 directive/matched/bridged 까지 전부 잘려 "0 주입" 되던 것을, 코어는 하드 상한(maxContext, 응답예약 절반 잠식) 안에서 항상 보장(운영자 보고 wl-snapshot: 100선택/0주입). - **2.9.14** — 감쇠 장면 로스터 — 매 턴 매칭된 canonical 을 weight 1.0 으로 기억, 턴마다 SCENE_DECAY(0.7) 감쇠, ≥SCENE_MIN(0.2, ≈5턴)이면 키워드 윈도우 밖이어도 pull + 코어 보호. 자율주행(유저 입력 없는 진행)에서 스토리 등장 인물 유지. per-chat 영속(serialize/hydrate), fresh-start 시 초기화(챗간 격리). - **2.9.15** — episodic trigger 도 실제 챗(getChatFromIndex) 우선 + canonicalTriggerWindow 동일 윈도우(formated 폴백) — §14(로어북)와 정렬. 템플릿-입력 봇에서 연관 기억이 실제 입력을 놓치던 것 + 활성화/매칭 윈도우 불일치 해소(이미 fetch 한 챗 재사용, 추가 fetch 0). - **2.9.16** — 진행 오버레이 제목을 "전체 맥락 따라잡기" 에서 "중간 맥락 따라잡기" 로 (미처리 구간만 따라잡음 — 표현 정확화, 동작 불변. 코드/로그의 전체(차단)·증분(비차단) 기술 구분은 보존). - **2.9.17~2.9.18** — 공존 하드닝: 차단형 보조 호출 상호작용 타임아웃(느린 본체·플러그인에서 안전 우회) · 서버 재시도 시 중복 주입 dedup(한 번만 주입 마킹) · 전경(채팅)/배경(기억 처리) 분리로 상호 블로킹 제거. - **2.9.19** — 적대적 점검 데이터 무결성 16건: 맥따 매 단계 세션 재확인(챗 전환 시 cross-chat 저장 차단) · 부분 persist 실패 시 옛 저장본 보존+재시도(무손실, "공간 확인" 정상 발화) · 진단 로그 export 시 서사·로어북 본문 redaction · 별칭 키워드 다수 시 매 턴 멈칫 완화 · 일부 모델 빈 응답 처리. + 무한 로딩: 맥따 총 시간 백스톱(초과 시 배경 이어처리) · 인덱스 빌드 [중단]/멈춤 감지 · thinking 모델 빈 응답 무용 카운트. - **2.9.20** — 변수·상태창 "대량 삭제" 오경고 차단: 메시지 동일성 비교 전 변수·매크로·재발급 식별자를 구조적으로 sanitize → 변수만 바뀐 재기록을 삭제로 오인하던 diffAndApply 오탐 6건 제거. cold-start commit 도 동일 sanitize 로 정합(후속 churn 제거). - **2.9.21** — 채팅 임베드 메모리 완화: 임베드 스냅샷을 압축 저장(wlz1 gzip, db 상주 footprint ~7-10배↓, v1 raw 하위호환 복원) · 개요 탭 비압축(v1) 임베드 경고 카드 + 1-클릭 재압축(내용 보존 in-place 마이그레이션) · 큰 기억뜰 임베드 전 사전 경고 모달(막지 않고 경고 + 파일 내보내기 대안). - **2.9.22** — stale-read 방어(크롬 탭 백그라운드): 탭 throttle 로 getChatFromIndex 가 최신 메시지를 빠뜨린 비권위적 read 를 같은 세션 윈도우 이상 급감 시(hidden·첫 급감) 파괴적 diff 보류 후 다음 권위 sync 재검증(evaluateShrinkRead 순수함수, 9 케이스) — '삭제' 오탐 차단, 진짜 삭제는 포그라운드 2회 확정으로 정상 발화. + 대량 삭제 모달에 '새로고침 후 재시도' 안내. + 개요 탭 [지금 확인](강제 버전 확인)·[변경점 보기](최신이어도 항상 노출). - **2.9.30** — (2.9.22~2.9.23 개발분 묶음 배포) 거대 챗 OOM 집중 대응. ① 맥따 부분 재개 — 미완료(running/partial/error) 상태도 새 jobId 에서 처음부터가 아니라 기존 진행(nextChunk)부터 증분 재개(전체 재처리 루프 차단) + narrativeTime 리셋 가드(확립된 timeline/episodic 있으면 0 리셋 안 함) — 보존 unit 연령이 0(방금)으로 무너지던 붕괴 차단. ② per-run 청크 예산(device-budget) — 모바일/저사양은 한 턴 처리 청크를 hardwareConcurrency·UA 로 제한(데스크탑 무제한 유지), crash ratchet — 직전 heavy run 이 도중 죽으면(run-active 마커 잔존) 다음 부팅 reconcile 가 strike++ → 예산 하향, status done 시 리셋. ③ crash breadcrumb — 부팅/맥따 진입 스냅샷을 wl.diag.* 에 영속(순수 setItem, getItem clone 0)해 OOM 재시작 후 로그이력 [내보내기]/'직전 진단' 카드로 회수(telemetry ring 은 메모리 전용이라 튕기면 소멸). ④ canon content persist-strip — 단일파트 canonical content 를 persist 사본(_persistShardedImpl split.units)에서만 비우고(serialize/export/merge/rollback 은 full 불변, canonicalSource.hash 보존) ingestCanonical unchanged/cbs 분기 + 패널 mount(ensureCanonHydrated)에서 복원, episodic 절대 미strip, opt-out canonPersistStrip. 회귀 4종(coldstart partial-resume·budget-ratchet·crash-breadcrumb·canon-strip) 추가, 전체 1,901 통과. ※ read-side getItem 전체-db clone 은 본체 한계 — 기존 값 캐시(2.9 이전)로 per-turn 반복은 이미 회피, 본체 패치는 미채택.