feat: v2.2.194 — Post-gen Term Validator (결정론적 글로서리 검증)

v2.2.192 Terminology Dictionary 가 *instructional* 지시 (LLM 에게 표준 표기 사용 권유)
였다면, 이번엔 *deterministic* 검증 — LLM 이 지시를 안 따랐을 때 결정론적 정규식 스캔.

신규 모듈: src/agent/termValidator.ts
- parseGlossary() — .astra/glossary.md 정규식 파싱 (mtime 캐시)
  Pattern 1: **Canonical** (X: typo1, typo2, ...) — typo 등장 시 "→ Canonical 권장"
  Pattern 2: H2/H3 "금지/비추/forbidden/avoid/don't" 섹션의 -  "phrase"
- validateTermUsage() — 정규식 스캔 + 발견 횟수
- formatTermValidatorFooter() — markdown 한 줄 footer

False-positive 필터:
- 한글 1음절·영문 1자·공백 포함 토큰 제외
- 영문 단어 경계 매치, 한글 substring

Wiring:
- agent.ts _maybeRunTermValidator — Self-Check 직후, swallow 패턴
- /glossary reload — Term Validator 캐시도 함께 비움

신규 설정: g1nation.termValidatorEnabled (기본 true)

Footer 누적:
- v2.2.191 🔍 Self-check (LLM 호출, opt-in)
- v2.2.194 🔤 Term validator (정규식, on by default)

시너지: Terminology Dictionary(instructional, 작성 중) + Term Validator(deterministic,
작성 후) → 사용자가 .astra/glossary.md 한 곳만 관리하면 2단 자동 동작.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-29 16:38:56 +09:00
parent 990ea0ae5f
commit 15a34e0889
21 changed files with 433 additions and 55 deletions
+7
View File
@@ -167,6 +167,12 @@ export interface IAgentConfig {
glossaryPath: string;
/** Glossary 본문 시스템 프롬프트 cap (chars). 너무 크면 토큰 비용↑. 기본 4000. */
glossaryMaxBodyLength: number;
/**
* Post-gen Term Validator — 답변 완료 후 글로서리 forbidden 단어 결정론적 스캔.
* Terminology Dictionary (v2.2.192) 의 *instructional* 지시를 *deterministic* 검증으로 보완.
* LLM 호출 없음 (정규식), 매 turn 안전 실행. footer 한 줄 표시. 기본 true.
*/
termValidatorEnabled: boolean;
/**
* Global Knowledge Mix weight (0100). Controls how much the assistant leans on
* Second Brain evidence vs. model general knowledge when answering.
@@ -439,6 +445,7 @@ export function getConfig(): IAgentConfig {
glossaryEnabled: cfg.get<boolean>('glossaryEnabled', true),
glossaryPath: cfg.get<string>('glossaryPath', '.astra/glossary.md') || '.astra/glossary.md',
glossaryMaxBodyLength: Math.max(500, Math.min(20000, cfg.get<number>('glossaryMaxBodyLength', 4000))),
termValidatorEnabled: cfg.get<boolean>('termValidatorEnabled', true),
knowledgeMixSecondBrainWeight: Math.max(0, Math.min(100, Math.round(
cfg.get<number>('knowledgeMix.secondBrainWeight', 50)
))),