47b3b9f93a
- v2.2.299 아키텍처 수렴: coreChat 통일(엔진 휴리스틱 3벌 제거), 기업 모드 검색 오케스트레이터 승격, lib/execUtil(실행 래퍼 6곳·Python 탐지 3벌 단일화), lib/kstSchedule(워처 4개 nowInKst 통합), estimateTokens 통합, 설정 접근 규칙 명문화 - v2.2.300 채팅 화면 정리: LiveReasoningFilter(스트리밍 중 <think>/Harmony 추론 토큰 단위 차단), 확신도·검토요청 footer 기본 숨김(계산·Reflection 은 유지) - v2.2.301 문맥·의도 이해: [답변 전 이해 원칙] 상시 주입, 워크플로우 의도 브리핑, Report QA 루프(규칙 레지스트리+실측치+회귀 게이트, 블로그_v3 개념 이식) - v2.2.302 /benchmark 비즈니스 렌즈(가격·수익·운영)+빌드 프롬프트 모드+QA 연계 - v2.2.303 handoff 모드(측정치 무손실 인수인계 문서)+/claude(Claude Code 터미널 위임) - v2.2.304 이식성: 지식 경로 두뇌-상대 규약(pickWikiDir 상대 해석), 이사 체크리스트 - v2.2.305 Claude 구독 엔진: claude: 프로바이더(CLI 위임, 모델 드롭다운 자동 노출, coreChat 지원 — 워크플로우·QA도 구독 모델 가능) - v2.2.306 Tone Guard: AI 상투어 금지 레지스트리(상담사 화법 실사례 8종+대조 예시) - v2.2.307 /benchmark 레이아웃 골격(sectionRoles 결정론 분석, 롤링 배너 즉답), 파트별 실패 격리, 합성 타임아웃 120→300초 검증: tsc 무오류 + jest 888 통과 + esbuild 정상 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
86 lines
4.3 KiB
TypeScript
86 lines
4.3 KiB
TypeScript
import { buildHandoffDoc } from '../src/features/datacollect/prompts/handoffDoc';
|
||
import { buildClaudeCommand } from '../src/features/claude/claudeLauncher';
|
||
import { parseBenchmarkArgs, BENCHMARK_MODE_PARTS } from '../src/features/datacollect/handlers';
|
||
|
||
const SCAN = {
|
||
meta: { title: 'InteriorAI', description: 'Fire your interior designer', lang: 'en' },
|
||
design: {
|
||
colors: {
|
||
palette: [{ value: 'rgb(10,10,10)', count: 40 }, { value: 'rgb(255,87,51)', count: 12 }],
|
||
background: 'rgb(255,255,255)', primaryText: 'rgb(10,10,10)',
|
||
buttonBackground: 'rgb(255,87,51)', buttonText: 'rgb(255,255,255)',
|
||
},
|
||
typography: { primaryFont: 'Inter', h1: { size: '48px', weight: 700 }, body: { size: '16px' } },
|
||
layout: { bodyMaxWidth: '1200px', sectionSpacing: '96px', borderRadiusScale: ['8px', '16px'] },
|
||
},
|
||
interactions: { hoverRules: ['button: background 0.2s ease'] },
|
||
microcopy: { headline: 'Fire your interior designer', ctaSamples: ['Get started $29/mo'] },
|
||
structure: { h1: 'Fire your interior designer' },
|
||
sitemap: {
|
||
totalPages: 2, crawlDepth: 1, ascii: '/\n└── /pricing',
|
||
pages: [
|
||
{ url: '/', role: 'landing', h1: 'Fire your interior designer', primaryContentType: 'hero', imageCount: 6, ctaSamples: ['Get started'] },
|
||
{ url: '/pricing', role: 'pricing', title: 'Pricing', primaryContentType: 'table', imageCount: 0, formFields: [{ name: 'email', type: 'email' }] },
|
||
],
|
||
},
|
||
};
|
||
|
||
describe('buildHandoffDoc — 측정치 무손실 인수인계 문서', () => {
|
||
const doc = buildHandoffDoc(SCAN, 'https://interiorai.com', { crawlDepth: 1, maxPages: 8, userContent: '' });
|
||
|
||
test('측정된 원시 값이 그대로 들어간다 (rgb·px·카피 원문)', () => {
|
||
expect(doc).toContain('rgb(255,87,51)(×12)');
|
||
expect(doc).toContain('1200px');
|
||
expect(doc).toContain('Fire your interior designer');
|
||
expect(doc).toContain('Get started $29/mo');
|
||
});
|
||
|
||
test('클라우드 모델용 지시문과 임의 대체 금지 규칙을 포함한다', () => {
|
||
expect(doc).toContain('클라우드 모델용 지시문');
|
||
expect(doc).toContain('측정치를 그대로 사용하라');
|
||
expect(doc).toContain('추측하지 말고');
|
||
});
|
||
|
||
test('요구사항 미입력 시 채울 체크리스트를 제공한다', () => {
|
||
expect(doc).toContain('- [ ] 서비스 이름');
|
||
expect(doc).toContain('- [ ] 뺄 기능');
|
||
});
|
||
|
||
test('사용자 변형 지시가 있으면 요구사항 우선 원칙과 함께 삽입된다', () => {
|
||
const d2 = buildHandoffDoc(SCAN, 'https://interiorai.com', { crawlDepth: 1, maxPages: 8, userContent: '부동산 중개용으로 변형' });
|
||
expect(d2).toContain('부동산 중개용으로 변형');
|
||
expect(d2).toContain('요구사항이 우선한다');
|
||
});
|
||
|
||
test('페이지 인벤토리 표와 원시 JSON 부록을 포함한다', () => {
|
||
expect(doc).toContain('| /pricing | pricing |');
|
||
expect(doc).toContain('원시 스캔 데이터 부록');
|
||
expect(doc).toContain('"primaryFont": "Inter"');
|
||
});
|
||
|
||
test('빈 스캔에도 문서가 깨지지 않는다', () => {
|
||
const d = buildHandoffDoc({}, 'https://x.com', { crawlDepth: 0, maxPages: 1, userContent: '' });
|
||
expect(d).toContain('(스캔 데이터 없음)');
|
||
});
|
||
});
|
||
|
||
describe('handoff 모드 파싱·구성', () => {
|
||
test('handoff 는 bare/mode= 모두 인식되고 합성 파트가 없다', () => {
|
||
expect(parseBenchmarkArgs('https://a.com handoff').mode).toBe('handoff');
|
||
expect(parseBenchmarkArgs('https://a.com mode=handoff').mode).toBe('handoff');
|
||
expect(BENCHMARK_MODE_PARTS.handoff).toEqual([]);
|
||
});
|
||
});
|
||
|
||
describe('buildClaudeCommand — 셸 안전 정규화', () => {
|
||
test('지시문을 큰따옴표 한 줄 인자로 만든다', () => {
|
||
expect(buildClaudeCommand('파일 읽고 개발해줘')).toBe('claude "파일 읽고 개발해줘"');
|
||
});
|
||
test('따옴표·POSIX 확장 문자를 무해화한다', () => {
|
||
expect(buildClaudeCommand('say "hi" and $HOME `ls`')).toBe(`claude "say 'hi' and HOME ls"`);
|
||
});
|
||
test('빈 지시문이면 대화형 실행', () => {
|
||
expect(buildClaudeCommand(' ')).toBe('claude');
|
||
});
|
||
});
|