feat(core): KeyTable T를 오토마타 상태로, 가상 단위 A/B/C 서열 유지 - #7
Conversation
신세벌식 갈마들이(오른손 ㅗ/ㅜ=겹모음 진행 vs 왼손 ㅗ=종성 갈마들이 대기)를 지원하기 위한 두 가지 확장. 1. press()의 값-식 문맥에서 T: AutomataTable이 있으면 t_state() 휴리스틱 (0/1/2) 대신 auto_state를 그대로 낸다. 날개셋 도움말의 정의(T=현재 오토마타 상태)와 일치. 표준 설정(상태 id 의미가 휴리스틱과 같은 0/1/2) 에서는 동작이 그대로다 - 기존 104개 테스트 전부 무회귀로 확인. 상태 의존 자판만 3 이상의 상태를 정의해 "겹모음 진행 중"류 진행 상태를 T로 구분할 수 있게 된다. 2. 오토마타 A/B/C에 가상 단위(VirtualUnitTable) 식별 유지: 이전에는 feed_unit이 Unit::Virtual을 풀어서 오토마타에 넘겨, 가상 단위의 정체가 사라지고 풀린 자모의 서열만 남았다. 신세벌식에서 물리적으로 다른 두 키(오른손/왼손 ㅗ)가 같은 실제 낱자(ㅗ)를 내면서도 서로 다른 진행 상태로 이어져야 하는데, 풀린 자모만으로는 구분이 불가능했다. incoming_role_seq()를 새로 두어, 가상 단위면 VIRTUAL_SEQ_BASE(1000)+id 를(실제 서열표 최댓값보다 훨씬 큰 값이라 절대 충돌하지 않음), 보통 단위면 풀린 자모의 서열을 그대로 A/B/C에 낸다. 배치(자리 배정)는 지금처럼 풀린 자모로 한다 - fresh_state/automaton_feed/apply_result에 seq를 함께 실어 나른다. 곁들여 feed_unit의 Unit→Jamo 해석을 이미 있던 resolve_jamo 헬퍼로 재사용(중복 제거 없음, 이미 PR #3에서 정리됨). 검증: 신세벌식형 합성 오토마타(가상 단위 200=오른손ㅗ/201=왼손ㅗ, T로 갈라지는 상태 의존 글쇠)로 과(겹모음)·곶(종성 갈마들이)·갓(중성 뒤 같은키 종성 갈마들이) 오라클 테스트 4개 추가. 두 수정 각각을 일부러 되돌려서 정확히 그 테스트들이 실패하는 것까지 확인(가짜 통과 아님): T 수정 되돌리면 곶 실패, 가상 단위 서열 수정 되돌리면 과·곶 둘 다 실패. 기존 104개 + 신규 4개 전부 통과, oracle/schema 테스트 무회귀. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Opus 서브에이전트 리뷰(PR #7)가 찾은 확정 버그 수정. 1. automaton_feed/apply_result/feed_jamo_tracked 가 이력에 풀린 자모 (Unit::Jamo)만 남기고 있었다. 정상 입력 때는 incoming_role_seq 가 가상 단위 서열을 A/B/C 에 정확히 냈지만, 재생(replay_history, 즉 백스페이스·BkspAttach 되살리기·도깨비불·성분 이동 등 이력 기반 편집 전부)은 이력에서 다시 feed_unit 을 태우므로, 이력이 가상 단위 원형을 잃으면 재생 때는 풀린 자모의 "진짜" 서열로 오토마타가 다시 태워져 가상 단위로만 갈 수 있는 상태 전이를 못 찾고 낱자를 통째로 잃었다 (곶 완성 후 백스페이스 한 번 → 고 여야 하는데 ㄱ까지 날아감). 세 함수 모두 원래 Unit 을 이력 기록용으로 함께 받도록 시그니처를 바꿔, 배치는 지금처럼 풀린 자모로 하되 이력은 원형을 남긴다(레거시 경로가 이미 하던 방식과 통일). 2. commit_and_clear(공백·기호·미배열 글쇠 통과 등 조합 흐름을 끊는 확정)가 auto_state 를 안 돌리고 있었다. flush()/reset() 은 이미 시작 상태로 되돌리는데 이 경로만 빠져 있어서, 확정 직후 auto_state 가 방금 끝난 음절의 상태로 남고 이제 이 값이(#4 이후) T 로 그대로 노출되므로 다음 글쇠의 값-식이 방금 끝난 음절의 상태를 잘못 읽을 수 있었다. 회귀 테스트 2개 추가(sinsebeol_backspace_unwinds_virtual_unit_one_step, sinsebeol_commit_and_clear_resets_automata_state). 각 수정을 일부러 되돌려 정확히 그 테스트만 실패하는 것까지 확인. 곁들여 리뷰가 지적한 테스트 주석 부정확성도 정정(과는 T 수정 없이도 우연히 통과함, 실제로 T=auto_state 를 요구하는 건 곶 하나뿐). 기존 108개 + 신규 2개 전부 통과, oracle/schema 무회귀, fmt/clippy 클린. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
서브에이전트(Opus) 리뷰 결과 및 수정Opus로 독립 리뷰를 받았고, 확정 버그 1개와 latent 이슈 1개를 찾아 반영했습니다(069ec18). 확정 버그: 가상 단위로 만든 음절에 백스페이스/이력 편집을 하면 낱자가 통째로 사라짐
재현: 곶( 수정: 세 함수 모두 원래 추가로 잡은 latent 이슈:
|
Closes #4
배경
teogeul 이행 1단계에서 상태 의존 자판(신세벌식 3종, 3-2015 계열)을 옮기지 못했다. 신세벌식은 반모음 진행을 물리적으로 다른 두 키로 구분한다(오른손 ㅗ=겹모음 진행 vs 왼손 ㅗ=종성 갈마들이 대기). 둘 다 놓이는 실제 낱자는 똑같이 ㅗ라서, 현재 KeyTable 값-식 변수로는 이 둘을 구분할 수 없었다.
변경
이슈에서 제안한 두 확장을 그대로 구현했다.
press()의T= 오토마타 상태:AutomataTable이 있는 항목에서는t_state()휴리스틱(0/1/2) 대신auto_state를 그대로 낸다. 날개셋 도움말의 정의(T=현재 오토마타 상태)와 일치하며, 표준 설정(상태 id 의미가 휴리스틱과 같은 0/1/2)에서는 동작이 그대로다.AutomataTable이 없으면 지금처럼 휴리스틱.오토마타 A/B/C에 가상 단위 식별 유지:
feed_unit이Unit::Virtual을 풀어서 오토마타에 넘기던 걸,incoming_role_seq()로 바꿔 가상 단위면VIRTUAL_SEQ_BASE(1000) + id(실제 서열표 최댓값보다 훨씬 큰 값이라 절대 충돌하지 않음)를, 보통 단위면 풀린 자모의 날개셋 서열을 그대로 A/B/C에 낸다. 배치(자리 배정)는 지금처럼 풀린 자모로 한다.fresh_state/automaton_feed/apply_result가 이 서열(seq)을 함께 실어 나르도록 시그니처를 조정했다.검증
이슈의 검증 계획(과/곶/갓)을 신세벌식형 합성 오토마타로 오라클 테스트화했다(가상 단위 200=오른손ㅗ/201=왼손ㅗ, T로 갈라지는 상태 의존 글쇠 f):
sinsebeol_right_hand_o_forms_compound_vowel: 과 = ㄱ+p(가상200→ㅗ)+f(T==3→중성ㅏ, UnitMix로 ㅘ)sinsebeol_left_hand_o_becomes_toggle_jong: 곶 = ㄱ+v(가상201→ㅗ)+f(T==4→종성ㅈ)sinsebeol_same_key_toggles_jong_after_jung: 갓 = ㄱ+f(중성ㅏ)+f(T==2&&E==1→종성ㅅ로 갈마듦)sinsebeol_plain_syllable: 기본 경로 무회귀 확인용 베이스라인두 수정 각각을 일부러 되돌려서 정확히 그 테스트들이 실패하는 것까지 로컬에서 확인했다(가짜 통과 방지):
sinsebeol_left_hand_o_becomes_toggle_jong(곶)만 실패 — 과는 우연히 else 분기가 같아 안 걸림.기존 104개 + 신규 4개 전부 통과,
cargo test --workspace(oracle/schema 포함) 무회귀,cargo fmt/clippy클린.🤖 Generated with Claude Code