960f43f643
[자기 지식 구식화 — 마지막 구멍 봉쇄] 인벤토리를 자동 생성해도(v2.2.225) 모델이 검색 없이 기억으로 답하면 무용 — 실사례: 답변 말미 "출처: 모델 지식 (검색 미사용)" 후 이미 있는 기능 (CoVe·멀티스텝 플래닝·노후점검 자동화)을 신규 제안. 프롬프트 규칙은 검색을 강제할 수 없으므로 scheduleContext 와 동일 패턴으로 해결: - selfAssessContext: "기능 개선/고도화/self-evolving/무슨 기능" 류 질의 감지 시 인벤토리 전문을 RAG 경쟁 없이 결정론적 주입 + "이미 있는 기능 신규 제안 금지, '현재 X 있음 — 빠진 증분 Y' 형태" 지시. 인벤토리 미생성 시 정직 안내. [충돌 해결사 — 권고까지만, 자동 결정은 안 함] - conflictScan 에 신뢰도 비교 추가: 양쪽 frontmatter(source_trust_level S~D, confidence_score) + 최신성으로 "신규/기존 우선 권고" 생성. 메타데이터 없거나 비등하면 권고 보류 (근거 없는 권고 금지). 삭제·덮어쓰기는 여전히 사람 결정. 테스트 17건 추가 (질의 감지·인벤토리 주입·신뢰 파싱·권고 분기). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
69 lines
3.3 KiB
TypeScript
69 lines
3.3 KiB
TypeScript
/**
|
|
* 자기 평가 정본 주입 + 충돌 신뢰도 비교 — 순수 로직 테스트.
|
|
*/
|
|
import * as fs from 'fs';
|
|
import * as os from 'os';
|
|
import * as path from 'path';
|
|
import { isSelfAssessRequest, buildSelfAssessContext } from '../src/lib/contextBuilders/selfAssessContext';
|
|
import { INVENTORY_FILE } from '../src/extension/featureInventory';
|
|
import { parseDocTrust, buildTrustRecommendation } from '../src/features/growth/conflictScan';
|
|
|
|
describe('isSelfAssessRequest — 자기 평가/기능 질의 감지', () => {
|
|
test.each([
|
|
'너의 기능 개선 아이디어 줘',
|
|
'self-evolving 엔진을 더 날카롭게 만들 방법은?',
|
|
'아스트라 아키텍처 분석하고 개선 방향 제안해줘',
|
|
'시스템 고도화 방안 알려줘',
|
|
'너 무슨 기능 있어?',
|
|
'아스트라가 할 수 있는 일 목록',
|
|
])('감지: %s', (p) => expect(isSelfAssessRequest(p)).toBe(true));
|
|
|
|
test.each([
|
|
'오늘 업무 목록 알려줘',
|
|
'이 회의록 요약해줘',
|
|
'삼성전자 주가 어때',
|
|
'커밋하고 푸쉬해줘',
|
|
])('비대상: %s', (p) => expect(isSelfAssessRequest(p)).toBe(false));
|
|
});
|
|
|
|
describe('buildSelfAssessContext', () => {
|
|
test('인벤토리 있으면 전문 + 대조 지시 주입', () => {
|
|
const brain = fs.mkdtempSync(path.join(os.tmpdir(), 'astra-sa-'));
|
|
fs.writeFileSync(path.join(brain, INVENTORY_FILE), '# 인벤토리 v9\n- 기능 A', 'utf8');
|
|
const block = buildSelfAssessContext(brain);
|
|
expect(block).toContain('이미 있는 기능을 신규 제안하지 마라');
|
|
expect(block).toContain('기능 A');
|
|
});
|
|
test('인벤토리 없으면 정직한 안내 (지어내기 방지)', () => {
|
|
const block = buildSelfAssessContext(fs.mkdtempSync(path.join(os.tmpdir(), 'astra-sa-')));
|
|
expect(block).toContain('생성되지 않음');
|
|
expect(block).toContain('확인 필요');
|
|
});
|
|
});
|
|
|
|
describe('충돌 신뢰도 비교', () => {
|
|
const fm = (trust: string, conf: number) => `---\nsource_trust_level: "${trust}"\nconfidence_score: ${conf}\n---\n본문`;
|
|
test('frontmatter 파싱', () => {
|
|
const t = parseDocTrust(fm('S', 0.95), 123);
|
|
expect(t).toMatchObject({ trustLevel: 'S', confidence: 0.95, mtimeMs: 123 });
|
|
expect(parseDocTrust('본문만 있음', 1).trustLevel).toBe('');
|
|
expect(parseDocTrust('본문만 있음', 1).confidence).toBe(-1);
|
|
});
|
|
test('신규 S vs 기존 C → 신규 우선', () => {
|
|
const r = buildTrustRecommendation(parseDocTrust(fm('S', 1.0), 2), parseDocTrust(fm('C', 0.5), 1));
|
|
expect(r).toContain('신규 우선');
|
|
});
|
|
test('신규 등급없음 vs 기존 S → 기존 우선 (최신이어도 신뢰가 이김)', () => {
|
|
const r = buildTrustRecommendation(parseDocTrust('본문', 2), parseDocTrust(fm('S', 1.0), 1));
|
|
expect(r).toContain('기존 우선');
|
|
});
|
|
test('양쪽 메타 없음 → 권고 보류 (근거 없는 권고 금지)', () => {
|
|
const r = buildTrustRecommendation(parseDocTrust('a', 2), parseDocTrust('b', 1));
|
|
expect(r).toContain('권고 보류');
|
|
});
|
|
test('비등 → 보류', () => {
|
|
const r = buildTrustRecommendation(parseDocTrust(fm('A', 0.8), 2), parseDocTrust(fm('A', 0.9), 1));
|
|
expect(r).toContain('권고 보류');
|
|
});
|
|
});
|