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
+341
View File
@@ -1,5 +1,346 @@
# Astra Patch Notes
## v2.2.201 (2026-05-29) 🎯
### 🏗️ 리팩터링 라운드 7 — datacollect cluster split (god-file 완전 해체)
slashRouter god-file 의 마지막 클러스터 — 6 datacollect 핸들러 (research/benchmark/youtube/blog/wikify/meet) 도메인 파일로. 더불어 LLM 호출 인프라(callLmSynthesis/repairKoreanGlitches/bridgeErrorRemedy) 도 별도 모듈로.
**slashRouter.ts: 1,229 → 201줄 (1,028, 84%)**
**누적 (v2.2.195 부터): 4,174 → 201 (3,973, 95%) ⭐ 95% 축소**
**신규 파일 2개:**
- `src/features/datacollect/handlers.ts`:
- runResearch (NotebookLM Deep Research)
- runBenchmark (Playwright + 4-렌즈 LLM)
- runYoutube + helpers (`_looksLikeYoutubeChannelUrl`, `_normalizeYoutubeUrl`, YOUTUBE_BATCH_MAX)
- runBlog (Blog Pipeline 안내)
- runWikify + `wikifyOne` (P-Reinforce v3.0 위키 합성)
- runMeet (회의록 transcript → 합성 + Tasks/Calendar 자동 등록)
- `src/features/datacollect/llm.ts`:
- `callLmSynthesis` (bridge /api/lm 호출 — datacollect handlers + teamops/communication 양쪽 사용)
- `repairKoreanGlitches` (한·영 토큰 깨짐 자동 교정)
- `bridgeErrorRemedy` (환경 의존성 에러 → 사용자 해결 가이드 생성, slashRouter catch 블록이 사용)
**Wiring:**
- extension.ts — `import './features/datacollect/handlers'` 추가
- communication.ts — `callLmSynthesis` import 를 `./slashRouter``./llm` 로 변경
- slashRouter.ts — 모든 import 정리, vscode/logInfo/getBridgeBaseUrl/bridgeErrorRemedy 4개만 남음
**slashRouter.ts 최종 (201줄):**
- REGISTRY Map + registerSlashCommand + listSlashCommands + isSlashCommand
- handleSlashCommand (dispatcher + 에러 처리 + bridgeErrorRemedy 적용)
- Webview interface + chunk helper
- getRecentSlashCommands ring buffer
**아키텍처 감사 HIGH 1번 완전 해결 ✅**
god-file 해체 완료. 모든 슬래시 핸들러 도메인별 파일 분리, slashRouter 는 순수 dispatcher.
**전체 리팩터링 시리즈 (v2.2.195~201, 7 builds):**
- 신규 utility 5개 (eventSourcedStore, mtimeFileCache, postAnswerHooks, SystemPromptBlock Map, datacollect/llm)
- 신규 도메인 핸들러 모듈 7개 (teamops trackers/dashboards/coordination/communication + system handlers + datacollect handlers)
- slashRouter: 4,174 → 201 (3,973, 95%)
- agent.ts: 1,617 → 1,551 (66, 4%)
- 새 슬래시 명령 추가 = 1 파일 + 1 register call (옛 god-file 와 비교 불가능)
- 새 verification block / event store / post-answer hook = 1곳 변경
**기능 변경 없음.**
**신규 패키징:** `astra-2.2.201.vsix`.
---
## v2.2.200 (2026-05-29) 🎉
### 🏗️ 리팩터링 라운드 6 — system cluster split (마무리)
slashRouter 분리 4단계 (마지막 TeamOps 영역) — system cluster (memory/glossary/help). 4인 팀 운영 모든 핸들러 도메인 분리 완료.
**slashRouter.ts: 1,615 → 1,229줄 (386, 24%)**
**누적 (v2.2.195 부터): 4,174 → 1,229 (2,945, 71%)**
**신규 파일: `src/features/system/handlers.ts`**
- runMemory + _memoryOverview + _formatDate (Temporal + Distillation 진입점)
- runGlossary (Terminology Dictionary CRUD)
- runHelp + HelpCategory + HELP_CATEGORIES (카테고리별 명령 브라우저 + 엔진 상태)
**Wiring:**
- `extension.ts``import './features/system/handlers'` side-effect (extension.ts 가 entry point)
**전체 슬래시 분리 현황:**
```
src/features/teamops/handlers/
├── _shared.ts (헬퍼)
├── trackers.ts (3) v2.2.196
├── dashboards.ts (4) v2.2.198
├── coordination.ts (5) v2.2.199
├── communication.ts (2) v2.2.199
└── index.ts (barrel)
src/features/system/
└── handlers.ts (3) v2.2.200
```
**slashRouter 잔여 (~1,229줄):**
- 인프라: REGISTRY / registerSlashCommand / chunk / Webview / isSlashCommand / handleSlashCommand / parseTaskOwner / callLmSynthesis / getRecentSlashCommands (~200줄)
- datacollect: research / benchmark / youtube / blog / wikify / meet (~1,000줄) — 다른 도메인 영역, 추후 라운드
**아키텍처 감사 5건 최종 상태:**
| Sev | 항목 | 결과 |
|---|---|---|
| HIGH | slashRouter god-file | 🟢 71% 축소 (teamops + system 완료, datacollect 만 잔여) |
| HIGH | 5-block 체인 | ✅ v2.2.195 |
| MED | 4 store 중복 | ✅ v2.2.195 |
| MED | 2-cache invariant | ✅ v2.2.197 |
| LOW | `_maybe*` hook 패턴 | ✅ v2.2.197 |
**전체 정리 시리즈 (v2.2.195~200, 6 builds):**
- 신규 utility 4개 (eventSourcedStore, mtimeFileCache, postAnswerHooks, SystemPromptBlock Map)
- 신규 도메인별 핸들러 모듈 5개 (teamops trackers/dashboards/coordination/communication + system)
- slashRouter.ts: 4,174 → 1,229 (2,945, 71%)
- agent.ts: 1,617 → 1,551 (66, 4%)
- 향후 새 verification block / store / hook / 슬래시 명령 추가 패턴 모두 *1곳 변경* 으로 완료
**기능 변경 없음 — 순수 구조 정리.**
**신규 패키징:** `astra-2.2.200.vsix`. 🎉 v2.2.200 통과!
---
## v2.2.199 (2026-05-29)
### 🏗️ 리팩터링 라운드 5 — coordination + communication clusters
slashRouter 분리 3단계 — coordination (5 handlers) + communication (2 handlers) 도메인 파일로. 원래 v2.2.200 예정이던 communication 도 같이 묶음 (sed 범위에 함께 잡혀 자연스러운 통합).
**slashRouter.ts: 2,537 → 1,615줄 (922, 36%)**
**누적 (v2.2.195 부터): 4,174 → 1,615 (2,559, 61%)**
**신규 파일 2개:**
- `src/features/teamops/handlers/coordination.ts`:
- runTask + parseFlexibleDate (Google Tasks + Calendar 동시 등록)
- runDecisions (Chronicle ADR 검색)
- runOnesie (1:1 미팅 카드)
- runBlocked (전사 지연·블로커 뷰)
- runStandup (팀 스탠드업 카드)
- `src/features/teamops/handlers/communication.ts`:
- runDraft + DRAFT_TYPES (6종 초안)
- runFeedback + feedbackSave/List/Summary/Path + 2개 LLM 프롬프트
**Wiring 변경:**
- `slashRouter.callLmSynthesis``export` 로 노출 (communication 이 LLM 호출용으로 import)
- `parseTaskOwner` 옛 local 정의 삭제 (`_shared.ts` 사용)
- 옛 ParsedTaskOwner interface 삭제 (도메인별로 분산)
- 옛 orphan 주석 블록 (deletion 후 남은 `// ─── /morning` header 등) 정리
**slashRouter 잔여 (~1,615줄):**
- system: memory / glossary / help (~480줄) — v2.2.200
- datacollect: research / benchmark / youtube / blog / wikify / meet (~1,000줄) — 다른 도메인 영역, 추후
- 인프라: registerSlashCommand / chunk / Webview / parseTaskOwner / callLmSynthesis / handleSlashCommand 등 (~130줄)
**기능 변경 없음 — 순수 구조 정리.**
**신규 패키징:** `astra-2.2.199.vsix`.
---
## v2.2.198 (2026-05-29)
### 🏗️ 리팩터링 라운드 4 — dashboards cluster split
slashRouter 분리 2단계 — dashboards 클러스터 (morning/evening/cohort/weekly) 도메인 파일로.
**slashRouter.ts: 3,448 → 2,537줄 (911, 26%)**
**누적 (v2.2.195 부터): 4,174 → 2,537 (1,637, 39%)**
**신규 파일: `src/features/teamops/handlers/dashboards.ts`**
- runMorning + _morningActions (브리핑 카드 + 액션 도출)
- runEvening (오늘 진척 + 내일 준비 + 회고)
- runCohort + _buildMonthlyBuckets + _cohortDashboard (MoM 추세)
- runWeekly + _isoWeek + _thisWeekWindow + _priorWeekWindow + _aggregateWeek + _deltaSymbol (주간 리뷰)
**Wiring:**
- `_shared.ts` 의 fmtKrw/daysUntil/parseTaskOwner/stageEmoji/STAGE_ORDER/TERMINAL_STAGES 재사용 (trackers 와 동일)
- ChronicleProjectStore 직접 import (위클리 ADR 스캔)
- `index.ts` 배럴에 한 줄 추가 (`import './dashboards'`)
**slashRouter 잔여 (~2,540줄):**
- coordination: task / decisions / onesie / blocked / standup (~700줄) — v2.2.199 예정
- communication: draft / feedback / meet (~430줄) — v2.2.200 예정
- system: memory / glossary / help (~480줄) — v2.2.200 예정
- datacollect: research / benchmark / youtube / blog / wikify (~900줄) — 추후 (별 영역)
**기능 변경 없음 — 순수 구조 정리.**
**신규 패키징:** `astra-2.2.198.vsix`.
---
## v2.2.197 (2026-05-29)
### 🏗️ 리팩터링 라운드 3 — PostAnswerHook registry + mtimeFileCache 공유 유틸
아키텍처 감사의 MED 1건 (2 cache 동일 invariant) + LOW 1건 (`_maybeX` 3개 메서드 패턴) 마무리.
**감사 5건 누적 진행도 (라운드 1~3 완료):**
| Sev | 항목 | 결과 |
|---|---|---|
| HIGH | slashRouter god-file | 🟡 v2.2.196 trackers 분리 (17%). 나머지 보류 — 패턴 입증됨 |
| HIGH | 5-block 체인 (system prompt) | ✅ v2.2.195 |
| MED | 4 store 중복 | ✅ v2.2.195 |
| **MED** | **terminology+termValidator 2캐시** | **✅ v2.2.197** |
| **LOW** | **`_maybe*` hook 패턴** | **✅ v2.2.197** |
---
**Part A — `src/lib/mtimeFileCache.ts` (신규 utility)**
배경: terminologyBlock 과 termValidator 가 *같은* 글로서리 파일에 *별도* mtime cache 보유. 무효화 invariant ("둘 다 함께 비우기") 가 사람 손으로 강제됨 — slashRouter 가 `/glossary reload` 시 양쪽 `clearXCache()` 모두 호출.
- `createMtimeFileCache<T>(name, parse)` — generic factory
- mtime 자동 체크, 캐시 hit / 자동 재read+parse
- `read(filePath)`, `invalidate(filePath)`, `clear()`, `size()`
**Refactor:**
- `terminologyBlock.ts` — raw 본문 cache 를 mtimeFileCache 인스턴스로
- `termValidator.ts` — parsed forbidden entries cache 를 mtimeFileCache 인스턴스로
- 각 모듈은 여전히 자기 `clearXCache()` export (slashRouter 가 둘 다 호출 — 동작 동일)
- 핵심 차이: boilerplate `if (cached && cached.mtime === mtime) return cached.content; ... ; cache.set(...)` 삭제. 새 캐시 추가 = 한 줄.
---
**Part B — `src/agent/postAnswerHooks/` (신규 registry)**
배경: `agent.ts``_maybeEmitDevilRebuttal` / `_maybePostHocSelfCheck` / `_maybeRunTermValidator` 3개 private method + 3개 import + 3개 call site. 새 hook 추가 시 *3곳* 편집 필요. 패턴 동일 (안전 fallback, try/catch swallow) — 레지스트리화.
```
src/agent/postAnswerHooks/
├── types.ts ← PostAnswerHook 인터페이스 + Context
└── index.ts ← 3 hooks 등록 + runPostAnswerHooks(ctx) iterator
```
**Refactor:**
- `agent.ts`: 3 method 삭제 (66줄, 1617→1551), 3개 호출 → 1개 `runPostAnswerHooks(ctx)`
- 새 hook 추가 = `postAnswerHooks/` 에 hook 객체 push (1곳)
**효과 측정:**
- 새 후처리 hook 추가: 옛 3 step → 새 1 step
- agent.ts: 66줄
---
**기능 변경 없음 — 순수 구조 정리.** DevilRebuttal/SelfCheck/TermValidator 동작 동일, 글로서리 캐시 동작 동일.
**아키텍처 정리 시리즈 (v2.2.195~197) 총평:**
- 신규 utility 모듈 3개 (eventSourcedStore, mtimeFileCache, postAnswerHooks)
- 신규 도메인별 핸들러 모듈 1개 (teamops/handlers/{_shared,trackers,index})
- 코드 라인: slashRouter 4,174→3,448 (726), agent.ts (66)
- 미래 부담 감소: 새 verification block 추가 1곳, 새 store 1곳, 새 hook 1곳
- 감사 5건 중 4건 완료, 1건 (slashRouter 나머지) 보류 — 패턴 입증 후 추후 라운드
**신규 패키징:** `astra-2.2.197.vsix`.
---
## v2.2.196 (2026-05-29)
### 🏗️ 리팩터링 라운드 2 — slashRouter handler split (trackers cluster)
아키텍처 감사의 HIGH 1번 (`slashRouter.ts` 4,174줄 god-file) 해결 시작. 첫 클러스터(트래커 3개) 를 도메인별 파일로 분리해 패턴 확립. 나머지 클러스터(coordination/communication/dashboards) 는 다음 라운드.
**slashRouter.ts: 4,174 → 3,448줄 (726, 17%)**
**신규 구조: `src/features/teamops/handlers/`**
```
src/features/teamops/handlers/
├── _shared.ts ← fmtKrw, parseAmount, daysUntil, parseTaskOwner,
│ STAGE_ORDER, TERMINAL_STAGES, stageEmoji
├── trackers.ts ← runRunway, runCustomers, runHire + 각자 helpers
│ + registerSlashCommand 3건 자기 등록
└── index.ts ← 배럴 (`import './trackers'`)
```
**Wiring:**
- `src/extension.ts``import './features/teamops/handlers'` side-effect import (entry point, 순환 import 회피)
- `src/features/datacollect/slashRouter.ts``chunk` + `Webview` 인터페이스 export, 옛 helpers 는 `_shared.ts` 에서 alias import 로 남은 인라인 핸들러(morning/evening/cohort/weekly/blocked/standup) 호환 유지
**패턴 입증 (다음 라운드 청사진):**
- `trackers.ts` 가 작동하는 한, 같은 패턴으로 다음 클러스터:
- `coordination.ts` — task / decisions / onesie / blocked / standup
- `communication.ts` — draft / feedback / meet
- `dashboards.ts` — morning / evening / cohort / weekly
- 각 클러스터 = 새 파일 + 옛 코드 sed-delete + `index.ts` 에 한 줄 추가
**Phase 1 (v2.2.195) 도 함께:** eventSourcedStore + SystemPromptBlock registry — 이미 출시. 합쳐서 감사 HIGH 2건 중 1.5건 해결, MED 1건 (4 store 중복) 해결.
**아키텍처 감사 후속 진행도:**
| Sev | 항목 | 상태 |
|---|---|---|
| HIGH | slashRouter god-file | 🟡 17% 축소 (trackers 분리). 나머지 v2.2.197+ |
| HIGH | 5-block 체인 (system prompt) | ✅ 완료 (v2.2.195) |
| MED | 4 store 중복 | ✅ 완료 (v2.2.195) |
| MED | terminology+termValidator 2캐시 | ⏳ v2.2.197 |
| LOW | _maybeEmitDevilRebuttal 류 hook 패턴 | ⏳ v2.2.197 |
**기능 변경 없음 — 순수 구조 정리.** /runway, /customers, /hire 동작 동일.
**신규 패키징:** `astra-2.2.196.vsix`.
---
## v2.2.195 (2026-05-29)
### 🏗️ 리팩터링 라운드 1 — eventSourcedStore + SystemPromptBlock registry
아키텍처 감사 결과 (HIGH 2건, MED 3건) 중 가장 효과·비용 비율 좋은 2개. 기능 변경 없음 — 순수 구조 정리.
**Phase 1 — `src/features/_shared/eventSourcedStore.ts` (신규)**
배경: customers/hire/runway/feedback 4개 store 의 `getXFilePath() + readX() + appendX()` 가 byte-for-byte 중복 (~240줄).
- `createEventStore<E>({ relPath, validate })` — generic factory
- 4개 store 가 각각 ~12줄로 축소 (event type + validator + `computeStates` 만 남음)
- BOM/인코딩 fix 같은 edge case 가 *한 곳* 에서 전파
- 도메인 로직 (`computeCustomerStates`, `computeCandidateStates`, `computeRunwayStatus`) 은 그대로 도메인 파일에 남음 — I/O 만 추상화
```typescript
// 옛 customersStore (60줄): import fs/path/vscode + getCustomersFilePath + readEvents + appendEvent
// 새 (5줄):
const _store = createEventStore<CustomerEvent>({ relPath, validate });
export const getCustomersFilePath = _store.getFilePath;
export const readEvents = _store.read;
export const appendEvent = _store.append;
```
**Phase 2 — SystemPromptBlock registry (5 필드 → 1 Map)**
배경: 새 verification 블록 추가 시 *5곳 편집 강제*`_turnCtx` 필드 + `resetTurnContext` + `buildAstraModeSystemPrompt` 인자 + casual ternary + template literal 위치. 5번 반복 (conflict/cove/intent/citation/terminology). 이 패턴이 god-file 만드는 길.
- [agent.ts](src/agent.ts) `_turnCtx`: 5 named `string` 필드 → 1 `dynamicBlocks: Map<string, string>`
- [agent.ts](src/agent.ts) `resetTurnContext()`: 5 reset → 1 `.clear()`
- [agent.ts](src/agent.ts) `buildAstraModeSystemPrompt` 호출: 5 named param → 1 `dynamicBlocks` param
- [buildAstraModeSystemPrompt.ts](src/agent/handlePrompt/buildAstraModeSystemPrompt.ts): 5 ternary gate + 5 위치 삽입 → 1 for-loop join
- [memoryContext.ts](src/lib/contextBuilders/memoryContext.ts): 5 `turnCtx.X = build...` → 5 `blocks.set('id', build...)` (한 줄씩, 새 블록은 여기서 set 한 줄만 추가)
**효과 측정:**
- 새 블록 추가 = **25 → 1** edit 지점 (5 파일 × 5 step → 1 set call)
- 옛 5 ternary `(!isCasualConversation && X && X.trim()) ? '\n\n' + X : ''` → 1 loop, casual gate 1번
- 블록 순서 변경 = memoryContext 의 set 순서 변경만 (옛: template literal 재배치)
**아키텍처 감사 후속 작업 (예정):**
- v2.2.196 — slashRouter 4,174줄 handler 도메인별 분할 (HIGH 1, 미완)
- v2.2.197 — PostAnswerHook registry (DevilRebuttal/SelfCheck/TermValidator 패턴 통합) + mtimeFileCache 공유 유틸 (terminologyBlock + termValidator 캐시 통합)
**기능 변경 없음 — 순수 구조 변화.** 모든 verification 블록 동작 동일, 모든 store 동작 동일.
**신규 패키징:** `astra-2.2.195.vsix`.
---
## v2.2.194 (2026-05-29)
### 🔤 Post-gen Term Validator — 결정론적 글로서리 검증 (엔진 변경)
v2.2.192 의 Terminology Dictionary 가 *instructional* (LLM 에게 "표준 표기 사용" 지시) 였다면, 이건 *deterministic* — LLM 이 지시를 안 따랐을 때 결정론적 정규식 스캔으로 catch.