Skip to content

remove chosung field option (query-dependent hard gate breaks monotonic narrowing) #36

Description

@mundi4

배경

chosung: false 필드 옵션(멀티필드)은 초성-only 토큰을 해당 필드에서 hard filter로 gate-out한다 (matchFields.ts의 D4). 이 gate의 술어(isChosungOnlyToken)는 쿼리에 의존하므로, 타이핑 도중 모음이 붙는 순간() 술어가 뒤집혀 필드가 un-gate되고 매치 집합이 커진다.

이는 라이브러리의 핵심 계약인 "타이핑할수록 결과 단조감소(monotonic narrowing)"를 UX 층위에서 깨뜨린다:

  • → gate-out → 결과 없음
  • → un-gate → 결과 등장 (집합 증가)
  • split 모드에선 모든 한글 단어가 초성으로 시작하므로, 새 토큰을 시작하는 매 키스트로크마다 chosung:false 필드에만 매치되는 아이템이 사라졌다 되살아나는 깜빡임 발생

issue #35의 세션 가드(e943dd6)는 엔진 soundness(재사용 시 매치 누락)만 고쳤고, 이 UX 비단조성은 기능 명세 자체에 내재한다. 쿼리가 자라면서 꺼질 수 있는 hard filter는 정의상 단조일 수 없어 어떤 가드로도 제거 불가능하다.

결정

chosung 옵션을 완전 제거한다. 초성 노이즈 억제가 다시 필요해지면 단조성-안전한 score demotion(초성 매치 감점 축)으로 재도입한다 — 이 이슈의 non-goal.

부수 효과: #35 가드 전체(prevTokenChosung, hasChosungFalseField, un-gating 검사)가 불필요해져 세션 재사용 로직이 단순해진다. 후속 scan cursor 이슈의 전제이기도 하다.

변경 사항

src/types.ts

  • MatchField.chosung 제거 (~L174)
  • SearcherFieldSpec.chosung 제거 (~L325)

src/matchFields.ts

  • isChosungOnlyToken 함수 제거 (이 변경 후 사용처 0 — export 포함 삭제). isConsonantLUT import도 미사용이 되므로 제거
  • 토큰 루프의 const chosung = isChosungOnlyToken(token) (~L62) 및 if (chosung && fields[i].chosung === false) continue; (D4 hard filter, ~L67) 제거
  • JSDoc의 chosung 언급 제거 (@param fields, ~L31)

src/createSearcher.ts

  • isChosungOnlyToken import 제거
  • makeRuntime: hasChosungFalseField 파라미터, prevTokenChosung/currentTokenChosung 상태, canReuse 내 un-gating 분기 (~L177-179), 커밋 (~L227), resetSession 내 초기화, 관련 주석 (~L115-118, L153, L165-167) 제거
  • createMultiFieldSearcher: fieldBufchosung: f.chosung (~L364), hasChosungFalseField 계산 (~L398)과 makeRuntime 5번째 인자 (~L405) 제거
  • 제거 경고: 필드 spec에 chosung 키가 있으면 dev 모드(isProd가 false)에서 생성 시점에 console.warn"[fuzzly] createSearcher: field option 'chosung' was removed and is ignored". JS 소비자의 silent ignore 방지. matchFields 직접 호출 경로에는 추가하지 않는다 (searcher에선 per-entry hot path라 비용/스팸 문제)

테스트

  • test/matchFields.test.ts case 6 ("chosung 스코프") 재작성: gate가 없으므로 초성-only 토큰이 모든 필드에서 후보가 된다. ㅎㄱㄷ가 chosung 옵션 없이 매치되고 weighted argmax로 귀속되는지 검증. 기존 r2 시나리오(양쪽 chosung:false → null)는 이제 non-null 매치가 되는 것으로 대체
  • test/multiField.test.ts:
  • 마무리로 grep -ri chosung src test 0건 확인

문서

Breaking change

public 옵션 제거 (MatchField.chosung, SearcherFieldSpec.chosung). TS 소비자는 컴파일 에러로, JS 소비자는 dev 경고로 인지. 릴리스 노트에 명시할 것.

완료 기준

  • grep -ri chosung src/ test/ 0건
  • npm test green (재작성 테스트 포함)
  • npm run check:fix clean
  • CLAUDE.md 갱신

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions