refactor: v2.2.195-201 — slashRouter god-file 해체 (–95%) + 인프라 5개 추출

아키텍처 감사 결과 HIGH 2건 + MED 2건 + LOW 1건 — 7 라운드 정리 시리즈.
기능 변경 없음, 순수 구조 정리.

**slashRouter.ts: 4,174 → 201줄 (–3,973, –95%)**
**agent.ts: 1,617 → 1,551줄 (–66, –4%)**

v2.2.195: eventSourcedStore + SystemPromptBlock registry
  - createEventStore<E>(opts) — 4 store (customers/hire/runway/feedback) I/O 240줄 중복 제거
  - _turnCtx 5 named string field → 1 Map<string, string> (새 verification block 추가 25곳→1곳)
  - buildAstraModeSystemPrompt: 5 ternary gate + 5 위치 → 1 for-loop join

v2.2.196: trackers cluster split
  - src/features/teamops/handlers/_shared.ts (fmtKrw/parseAmount/daysUntil/parseTaskOwner/stageEmoji/STAGE_ORDER/TERMINAL_STAGES)
  - src/features/teamops/handlers/trackers.ts (runway/customers/hire)
  - src/features/teamops/handlers/index.ts (barrel)
  - extension.ts 에 side-effect import (순환 import 회피)

v2.2.197: mtimeFileCache + PostAnswerHook registry
  - src/lib/mtimeFileCache.ts — createMtimeFileCache<T>(name, parse) (terminologyBlock + termValidator 2-cache invariant 자동화)
  - src/agent/postAnswerHooks/{types,index}.ts — Devil/SelfCheck/TermValidator 3 _maybeX method → 1 runPostAnswerHooks(ctx) loop
  - agent.ts –66줄

v2.2.198: dashboards cluster split
  - src/features/teamops/handlers/dashboards.ts (morning/evening/cohort/weekly)

v2.2.199: coordination + communication clusters split
  - src/features/teamops/handlers/coordination.ts (task/decisions/onesie/blocked/standup)
  - src/features/teamops/handlers/communication.ts (draft/feedback)
  - callLmSynthesis export 노출 (communication 이 사용)
  - 옛 parseTaskOwner local 정의 삭제 (_shared.ts 사용)

v2.2.200: system cluster split
  - src/features/system/handlers.ts (memory/glossary/help)

v2.2.201: datacollect cluster split + LLM 인프라 추출
  - src/features/datacollect/handlers.ts (research/benchmark/youtube/blog/wikify/meet)
  - src/features/datacollect/llm.ts (callLmSynthesis + repairKoreanGlitches + bridgeErrorRemedy)
  - slashRouter import 4개로 축소: vscode/logInfo/getBridgeBaseUrl/bridgeErrorRemedy

**최종 slashRouter (201줄):**
- REGISTRY Map + registerSlashCommand/listSlashCommands/isSlashCommand
- handleSlashCommand (dispatcher + 에러 처리)
- Webview interface + chunk helper
- getRecentSlashCommands ring buffer (actionability scoring 용)

**미래 부담 감소 metrics:**
- 새 슬래시 명령: god-file 끝에 함수 + register → 1 파일 + 1 register call
- 새 verification block: 5곳 편집 → 1 set call
- 새 event store: 60줄 boilerplate → createEventStore 한 줄
- 새 post-answer hook: 3 step → 1 push
- 새 mtime cache: Map + invariant 관리 → createMtimeFileCache 한 줄

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 11:55:22 +09:00
parent 15a34e0889
commit 7bec20620a
40 changed files with 4784 additions and 4545 deletions
@@ -23,27 +23,12 @@ export interface BuildAstraModeSystemPromptInput {
/** From this._turnCtx.knowledgeMix — pass null when absent. */
knowledgeMix: any;
/**
* [CONFLICT WARNINGS] 블록 — buildConflictWarningsBlock 산출. 빈 문자열이면 충돌 없음 → 주입 안 함.
* v4 정책 텍스트의 "[CONFLICT WARNING] 플래그" 참조를 실제 데이터로 뒷받침.
* 동적 시스템 프롬프트 블록 Map (id → 본문). memoryContext 가 채움.
* 옛 named param 5개 (conflictWarningsCtx/coveChecklistCtx/intentClarificationCtx/
* citationTraceCtx/terminologyCtx) 를 통합. casual 모드는 자동 skip.
* 등록 순서대로 [CONTEXT] *밖* 에 join 되어 주입.
*/
conflictWarningsCtx?: string;
/**
* [VERIFICATION CHECKLIST] CoVe 블록 — buildCoveChecklistBlock 산출. 답변 *작성 전*
* 그라운딩 체크리스트로 모델 self-verify 지시. 빈 문자열이면 비활성.
*/
coveChecklistCtx?: string;
/**
* [INTENT CLARIFICATION GUIDANCE] — 모호 질의 감지 시 *역질문 우선* 지시. 모호 아닐 때 빈 문자열.
*/
intentClarificationCtx?: string;
/**
* [CITATION TRACE] — 답변 끝에 사용 출처 한 줄 정리 지시. 검색 결과 있을 때 채워짐.
*/
citationTraceCtx?: string;
/**
* [TERMINOLOGY DICTIONARY] — 사용자 편집 글로서리 + Term Check 지침. 파일 있을 때만.
*/
terminologyCtx?: string;
dynamicBlocks?: Map<string, string>;
}
export function buildAstraModeSystemPrompt(input: BuildAstraModeSystemPromptInput): string {
@@ -62,11 +47,7 @@ export function buildAstraModeSystemPrompt(input: BuildAstraModeSystemPromptInpu
isCasualConversation,
localPathContext,
knowledgeMix,
conflictWarningsCtx,
coveChecklistCtx,
intentClarificationCtx,
citationTraceCtx,
terminologyCtx,
dynamicBlocks,
} = input;
// 기존 Astra 모드 (에이전트 미선택)
@@ -105,29 +86,15 @@ export function buildAstraModeSystemPrompt(input: BuildAstraModeSystemPromptInpu
// priorConclusionCtx 는 modeBridgeCtx 와 같은 위치 (base systemPrompt 직후) — 모델이
// 자기 직전 결론을 anchor 로 잡고 사용자의 follow-up 을 그 결론에 대한 정정으로 해석하게.
const priorConclusionBlock = priorConclusionCtx ? '\n\n' + priorConclusionCtx : '';
// [CONFLICT WARNINGS] 는 [CONTEXT] 밖에 — token-truncation 시 보호. v4 정책이
// 충돌 처리 *방법* 을 명시하고, 이 블록이 *어느 출처가 충돌* 인지 데이터 제공.
// Casual conversation 모드에서는 RAG context 자체를 안 쓰므로 충돌 경고도 무의미 — 생략.
const conflictWarningsBlock = (!isCasualConversation && conflictWarningsCtx && conflictWarningsCtx.trim())
? '\n\n' + conflictWarningsCtx
: '';
// [VERIFICATION CHECKLIST] CoVe — 답변 작성 전 self-verify 지시. Conflict 와 마찬가지로
// [CONTEXT] 밖, casual 모드 비활성. CoVe 가 강하면 단정적 답변이 줄고 근거 인용 늘어남.
const coveBlock = (!isCasualConversation && coveChecklistCtx && coveChecklistCtx.trim())
? '\n\n' + coveChecklistCtx
: '';
// [INTENT CLARIFICATION GUIDANCE] — 모호 차원 감지 시 *역질문 우선*. Casual 모드는 제외.
// 위치: 다른 verification block 보다 *앞* — 모호하면 답변 자체를 안 만들어야 하므로.
const intentBlock = (!isCasualConversation && intentClarificationCtx && intentClarificationCtx.trim())
? '\n\n' + intentClarificationCtx
: '';
// [CITATION TRACE] — 답변 끝에 출처 한 줄. CoVe 와 함께 동작 — CoVe 가 라벨, Citation 이 정리.
const citationBlock = (!isCasualConversation && citationTraceCtx && citationTraceCtx.trim())
? '\n\n' + citationTraceCtx
: '';
// [TERMINOLOGY DICTIONARY] — 사용자 편집 글로서리. casual 모드 비활성 (greeting 에 용어 강제 의미 없음).
const terminologyBlock = (!isCasualConversation && terminologyCtx && terminologyCtx.trim())
? '\n\n' + terminologyCtx
: '';
return `${systemPrompt}${modeBridgeCtx ? '\n\n' + modeBridgeCtx : ''}${priorConclusionBlock}${designerCtx}${projectArchitectureCtx}${localProjectKnowledgeCtx}${thinkingPartnerCtx}${astraStanceCtx}${secondBrainTraceCtx}${v4PolicyCtx}${knowledgeMixCtx}${casualCtx}${intentBlock}${terminologyBlock}${conflictWarningsBlock}${coveBlock}${citationBlock}\n\n[CONTEXT]\n${memoryCtx}\n${knowledgeContextForPrompt}\n${contextBlock}\n[/CONTEXT]\n${negativeCtx}`;
// 동적 블록 join — [CONTEXT] *밖* 에 주입돼 token-truncation 시 보호. Casual 모드면
// RAG context 자체를 안 쓰므로 동적 블록도 의미 없음 → 일괄 skip.
// 등록 순서대로 join (memoryContext 가 메모리 호출 순으로 set — 현재: intent →
// terminology → conflict → cove → citation). 빈 본문 entry 는 자동 제외.
let dynamicBlocksJoined = '';
if (!isCasualConversation && dynamicBlocks && dynamicBlocks.size > 0) {
for (const body of dynamicBlocks.values()) {
if (body && body.trim()) dynamicBlocksJoined += '\n\n' + body;
}
}
return `${systemPrompt}${modeBridgeCtx ? '\n\n' + modeBridgeCtx : ''}${priorConclusionBlock}${designerCtx}${projectArchitectureCtx}${localProjectKnowledgeCtx}${thinkingPartnerCtx}${astraStanceCtx}${secondBrainTraceCtx}${v4PolicyCtx}${knowledgeMixCtx}${casualCtx}${dynamicBlocksJoined}\n\n[CONTEXT]\n${memoryCtx}\n${knowledgeContextForPrompt}\n${contextBlock}\n[/CONTEXT]\n${negativeCtx}`;
}