v2.2.292-296: 메모리·발열 최적화 + Pixel Office 완전 제거 + 소형 모델 추론 강화(calculate/run_code/지식 스코프)

- v2.2.292 메모리·발열: 헬스체크 워크스페이스 쓰기→fs.access(워처 연쇄 제거)·git 검사 비동기 30분 주기,
  웹뷰 retainContextWhenHidden 정리(채팅만 유지), 브레인 인덱스 유휴 30분 TTL 해제,
  채팅 DOM 200개 상한, @lmstudio/sdk 지연 로드
- v2.2.293 Pixel Office 시각화 폐기: astraOffice 모듈·사이드바 매니저 3종·스프라이트 17MB 삭제,
  sidebarProvider collector 섹션 통삭제 (기업 모드 판단 로직 무변경, vsix 12.2MB→1.3MB)
- v2.2.294 도구 메뉴 'NotebookLM 백엔드 실행/종료' 버튼: OS 자동 감지, 프로젝트 자동 탐색+폴더 선택 저장,
  포트 정리 폴백 (터미널 없이 Research 백엔드 켜고 끄기)
- v2.2.295 추론 강화 1탄: [ACTION 16] <calculate> Python 계산 위임(결과 재주입·자가수정 루프),
  단계별 지식 스코프(General+Specialty, 결정적 도메인 분류, 설정 지식·기억 탭 UI)
- v2.2.296 추론 강화 2탄: [ACTION 17] <run_code> 실행 확인(stdout 회수→수정→재실행 루프),
  문법 오류 재주입 자가수정, 도구 라우팅 힌트(dynamicBlocks), Grounding rescue 도메인 스코프 확장
- 검증: jest 818 통과(신규 29개), tsc 무오류, esbuild 정상

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-05 18:59:47 +09:00
parent fa397d7fa1
commit bb7cd6b879
466 changed files with 1285 additions and 6588 deletions
+19 -3
View File
@@ -10,6 +10,7 @@ import { embedQuery, embedTexts } from '../../retrieval/embeddings';
import { backfillBrainEmbeddings, backfillBrainChunkEmbeddings } from '../../retrieval/brainIndex';
import { loadWeaknessProfile, buildSelfReviewBlock, registerKnowledgeGap } from '../../intelligence/correctionLoop';
import { resolveScopeForAgent } from '../../skills/agentKnowledgeMap';
import { resolveDomainScope, classifyKnowledgeDomain, buildDomainRoutingHint } from '../../retrieval/domainRouter';
import {
resolveKnowledgeMix,
mapWeightToBrainFileLimit,
@@ -154,6 +155,15 @@ export async function buildMemoryContext(deps: MemoryContextDeps): Promise<strin
// Agent ↔ knowledge map. 매핑 없으면 folders=[] → orchestrator 가 whole-brain 사용 (legacy).
const scope = resolveScopeForAgent(deps.agentSkillFile, deps.activeBrain.localBrainPath);
// [단계별 지식 스코프] 에이전트 매핑이 없을 때만, 질문 도메인(수학/코딩/팩트)이 분류되고
// 해당 Specialty 폴더가 설정돼 있으면 General+Specialty 로 검색 범위를 좁힌다.
// 소형 모델 컨텍스트에서 무관 청크를 배제하는 정밀도 최적화 — 분류 실패·미설정 시 기존 전체 검색.
// (에이전트 스코프가 이미 있으면 그쪽 우선 — 기존 제한을 느슨하게 만들지 않는다.)
let effectiveScopeFolders = scope.folders;
if (effectiveScopeFolders.length === 0 && deps.activeBrain.localBrainPath) {
const domainScope = resolveDomainScope(deps.currentPrompt, deps.activeBrain.localBrainPath);
if (domainScope.folders.length > 0) effectiveScopeFolders = domainScope.folders;
}
// Context 윈도우 비례 retrieval 예산. 32K → 8K, 230K → 57K, 80K cap (scoring 속도).
const scaledTotalBudget = Math.min(
@@ -207,7 +217,7 @@ export async function buildMemoryContext(deps: MemoryContextDeps): Promise<strin
retrievalRatio: mixedRetrievalRatio,
},
brainFileLimit: mixedBrainFileLimit,
scopeFolders: scope.folders,
scopeFolders: effectiveScopeFolders,
recentSessions,
mediumTermLimit: config.memoryMediumTermSessions ?? 0,
queryEmbedding,
@@ -222,7 +232,8 @@ export async function buildMemoryContext(deps: MemoryContextDeps): Promise<strin
// [Correction Loop ③-a] 근거 약함 + agent scope 적용 중이면 전체 두뇌로 1회
// 재검색 — scope 가 정답 문서를 가리는 경우를 구제. 더 강한 근거가 나올 때만 채택.
if (scope.folders.length > 0 && assessGrounding(result).level === 'weak') {
// (도메인 스코프도 포함 — Specialty 폴더가 정답 문서를 가리는 경우 같은 방식으로 구제)
if (effectiveScopeFolders.length > 0 && assessGrounding(result).level === 'weak') {
try {
const retry = deps.retrievalOrchestrator.retrieve(deps.currentPrompt, { ...retrieveOpts, scopeFolders: [] });
if (assessGrounding(retry).level !== 'weak') {
@@ -412,7 +423,12 @@ export async function buildMemoryContext(deps: MemoryContextDeps): Promise<strin
// [CONTEXT] *밖* 보호 구역에 주입되어 context-overflow truncation 에서도 살아남는다.
// 옛 구현은 이 블록들을 RAG 본문과 같은 문자열에 합쳐 [CONTEXT] 안에 넣었는데,
// "실패 방지 제약"이 토큰 압박에서 배경 지식과 함께 잘려나가는 모순이 있었다.
const constraintBlock = [selfReviewBlock, groundingBlock, lessonBlock].filter(Boolean).join('\n\n');
// [도구 라우팅 힌트] 도메인 분류(수학/코딩/팩트)가 그 턴의 도구 사용을 직접 지시한다 —
// 수학→<calculate> 위임, 코딩→<run_code> 실행 확인, 팩트→근거 없으면 확인 불가.
// 지식 스코프와 무관하게(에이전트 스코프가 있어도) 행동 제약으로 항상 주입.
const routingHint = buildDomainRoutingHint(classifyKnowledgeDomain(deps.currentPrompt));
const constraintBlock = [routingHint, selfReviewBlock, groundingBlock, lessonBlock].filter(Boolean).join('\n\n');
if (constraintBlock) blocks.set('behavior-constraints', constraintBlock);
return memoryBlock;
}