altair823
d8621d55e0
fix(tag-vocab): PR review round 1 — i1 dedup + m2 test gap ( #3 v0.2.3)
...
- i1 (Important): AiWorker per-tag emit 루프에 res.tags Set dedup
AI 가 같은 태그 중복 응답 시 hit count 2번 emit 되던 통계 왜곡 수정
+ 테스트 1개 (중복 태그 1 hit + 1 miss 검증)
- m2 (Minor): NoteRepository.getTopUsedTags LIMIT-then-filter 테스트 갭
+ 테스트 1개 (limit=3 + 한글 1 + kebab 2 → 결과 length=2 lock-in)
skip: m1 (per-tag serial await — ai_succeeded 패턴 일관),
n1 (prompt 빈 줄 cosmetic), n2 (tagId positive — AUTOINCREMENT 1+)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:49:36 +09:00
altair823
ff07738b02
chore(tag-vocab): #3 closure — gates verified + roadmap mark complete
...
- typecheck 0 / 단위 384 / e2e 1
- v0.2.3 6/7 (#3 태그 vocab 머지)
- 다음: #6 리마인드 spike (마지막 항목)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:37:30 +09:00
altair823
727eeb1919
fix(tag-vocab): T7 review nit 2건 — test 코드 ergonomics ( #3 v0.2.3)
...
- nit1: tag_vocab_hit/miss 테스트 payload cast dedupe (한 번에 typed 바인딩)
- nit2: { kind: string; payload: unknown } 반복을 EmittedEvent 타입 alias 로 hoist
skip: Minor1 (serial await — ai_succeeded 와 패턴 일관), Nit3 (magic number VOCAB_TOP_N — v0.2.4 backlog), Nit4 (한국어 코멘트 — 기존 코드와 일관)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:36:16 +09:00
altair823
3e0f710c70
feat(tag-vocab): AiWorker — vocab fetch + per-tag hit/miss emit ( #3 v0.2.3)
...
- processJob 가 generate 직전 repo.getTopUsedTags(20) fetch
- provider.generate 에 vocab 전달 (LocalOllamaProvider 가 prompt 에 주입)
- ai_succeeded emit 후 per-tag 분류 → tag_vocab_hit/miss emit
- hit: vocabSet.has + getTagIdByName lookup → { tagId, vocabSize }
- miss: { vocabSize }
- AiTelemetryEmitter union 4종 (ai_succeeded/ai_failed/tag_vocab_hit/tag_vocab_miss)
- 단위 +4 cases (vocab passthrough, hit+miss, vocab=[] all miss, per-tag emit count)
- collectingTelemetry mock → AiTelemetryEmitter 타입 적용 (typecheck 통과)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:33:16 +09:00
altair823
26f1db5626
feat(tag-vocab): TelemetryService EmitInput +tag_vocab_hit/miss + 테스트 narrowing 확장 ( #3 v0.2.3)
...
- EmitInput union 13 → 15
- narrowing guards (noteId 없는 kind 분기) 에 tag_vocab_hit/miss 추가
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:29:24 +09:00
altair823
973cb1d08d
feat(tag-vocab): telemetryStats — hit/miss 누적 + summary 적중률 ( #3 v0.2.3)
...
- DailyRow +2 cols (tag_vocab_hit, tag_vocab_miss)
- accumulators + branches
- table 컬럼 +2
- summary "- 태그 vocab: hit/miss = N/M (적중률 X%)" 또는 "(데이터 없음)"
- 단위 +2 cases
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:27:22 +09:00
altair823
b81fc82621
feat(tag-vocab): telemetryEvents — tag_vocab_hit/miss zod schemas ( #3 v0.2.3)
...
- TagVocabHitPayload { tagId: int>0, vocabSize: int>=0 } .strict()
- TagVocabMissPayload { vocabSize: int>=0 } .strict()
- TelemetryEventSchema union 13 → 15
- 단위 +3 cases (hit accept, miss accept, hit extra field 거부)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:23:31 +09:00
altair823
daa8507364
feat(tag-vocab): InferenceProvider.vocab + LocalOllamaProvider 전달 ( #3 v0.2.3)
...
- GenerateInput.vocab?: string[] (optional, 미전달 시 빈 배열 처리)
- LocalOllamaProvider.generate 가 input.vocab ?? [] 를 buildPrompt 4th 인자로
- 단위 +1 case (vocab → prompt body)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:21:24 +09:00
altair823
896b374f56
fix(tag-vocab): T2 review minor/nit 2건 ( #3 v0.2.3)
...
- M1: prompt.test.ts test 4 변수명 candidateIdx → headerIdx (실제 anchor 가 'Today's date' 헤더)
- N1: prompt.ts return 직전 self-delimited block 컨벤션 1줄 코멘트
skip: N2 (PROMPT_VERSION 테스트 redundancy nit — harmless guard), N3 (vocab dedup/normalize — Task 1 caller 책임)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:19:39 +09:00
altair823
134d59ddb4
feat(tag-vocab): prompt.ts — PROMPT_VERSION 4 + vocab parameter ( #3 v0.2.3)
...
- PROMPT_VERSION 3 → 4 (marker bump, retry 트리거 X)
- buildPrompt 4번째 param vocab: string[] = []
- vocab.length > 0 시 "Existing vocabulary tags" + "Prefer reusing" 라인 추가
- vocab=[] 시 라인 자체 생략 (Q3=B 결정)
- 단위 +4 cases (신규 prompt.test.ts)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:17:17 +09:00
altair823
e2b16d44d7
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 >
2026-05-02 12:14:53 +09:00
altair823
df8a53aec1
feat(tag-vocab): NoteRepository — getTopUsedTags + getTagIdByName ( #3 v0.2.3)
...
- getTopUsedTags(limit=20): top-N (count desc, id asc) + kebab-case 필터 + deleted_at 제외
- getTagIdByName(name): COLLATE NOCASE lookup
- AI+user source 통합 카운트 (Q1=C 결정)
- 단위 +7 cases (정렬, 필터, source 통합, deleted 제외, limit, getTagIdByName)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:10:36 +09:00
altair823
853ca39c0d
docs(tag-vocab): #3 plan — 8 tasks TDD + 21 단위 cases (v0.2.3)
...
8 task TDD plan:
T1 NoteRepository (getTopUsedTags + getTagIdByName, +7 cases)
T2 prompt.ts (PROMPT_VERSION 4 + vocab param, +4 cases, 신규 prompt.test.ts)
T3 InferenceProvider + LocalOllamaProvider (vocab passthrough, +1 case)
T4 telemetryEvents (zod schemas, +3 cases)
T5 telemetryStats (누적 + summary, +2 cases)
T6 TelemetryService EmitInput + narrowing 확장
T7 AiWorker (vocab fetch + per-tag emit, +4 cases)
T8 closure (gates + roadmap)
총 신규 단위 +21 (spec budget 19 + 2 surplus). 단위 363 → 382 (±5) 예상.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:07:28 +09:00
altair823
8206462ee4
docs(tag-vocab): #3 spec — vocab pool/telemetry/prompt 강도/재처리 결정 (v0.2.3)
...
mini-brainstorm 4개 결정:
- Q1=C: vocab pool = AI+user 통합 + kebab-case 필터
- Q2=A: telemetry emit 단위 = 태그별 (per-tag hit/miss)
- Q3=B: prompt 강도 = "Prefer" (우선, MUST 아님)
- Q4=A: 기존 노트 재처리 = 자연 진화 (X)
핵심 invariant 6개 + privacy invariant + tests ≥19개 약속.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-02 12:02:06 +09:00