fix(tag-vocab): T1 review minor/nit 4건 일괄 (#3 v0.2.3)

- M1: getTopUsedTags 의 LIMIT-then-filter 의미 docstring 명시
- M2: AI+user source 통합 테스트 강화 — 카운트 차이로 정렬 검증 (toContain 만으론 약함)
  updateUserAiFields 는 tags REPLACE 방식 (DELETE+reinsert) 이므로
  fallback 패턴 사용: 3개 노트 각 1태그, AI/user 혼합으로 design=2 > meeting=1 검증
- N1: SQL "COUNT(*) c" → "COUNT(*) AS c" (countFailed 패턴과 일관)
- N2: kebab-case regex 모듈 상수 KEBAB_CASE_RE 로 hoist

skip: N3 (test 헬퍼 — verbosity 경미), N4 (it 블록 분리 — 코드베이스 패턴 유지)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
altair823
2026-05-02 12:14:53 +09:00
parent df8a53aec1
commit e2b16d44d7
2 changed files with 16 additions and 4 deletions

View File

@@ -681,11 +681,17 @@ describe('NoteRepository — failed retry helpers', () => {
it('getTopUsedTags counts AI + user sources together', () => {
const a = repo.create({ rawText: 'a' }).id;
const b = repo.create({ rawText: 'b' }).id;
const c = repo.create({ rawText: 'c' }).id;
// design: 1 AI (a) + 1 user (b) = 2 total; meeting: 1 AI (c) = 1 total
// → design must rank first (proves source merging, not AI-only count)
// Note: updateUserAiFields REPLACES tags (DELETE+reinsert), so each note
// gets exactly the tags passed in the call.
repo.updateAiResult(a, { title: 't', summary: 'x\ny\nz', tags: ['design'], provider: 'p' });
repo.updateUserAiFields(b, { tags: ['design'] });
// design count 는 AI 1 + user 1 = 2
repo.updateAiResult(c, { title: 't', summary: 'x\ny\nz', tags: ['meeting'], provider: 'p' });
const top = repo.getTopUsedTags();
expect(top).toContain('design');
expect(top[0]).toBe('design'); // 2 (AI+user) > 1 (AI only)
expect(top.indexOf('meeting')).toBeGreaterThan(0);
});
it('getTopUsedTags excludes tags from deleted notes', () => {