feat(kebab-tui): p9-fb-12 follow-up — heuristic 제거, mode-authoritative dispatch #85

Merged
altair823 merged 2 commits from feat/p9-fb-12-mode-dispatch into main 2026-05-03 07:54:37 +00:00
Owner

요약

p9-fb-12 partial (PR #84) 의 deferred 부분 finalize. spec status in_progresscompleted.

변경

  • search::is_typing_mod 함수 삭제. search Char dispatch 가 state.mode 기반:
    • Normal + plain j/k → 선택 이동
    • Insert + plain Char (chord 제외) → input.push
  • search::handle_key_searchi (chunk inspect) / g (editor jump) pre-pass 가 Normal 모드에서만 fire
  • ask::handle_key_ask input-empty heuristic 삭제. e/j/k 가 mode 분기 — Normal toggle/scroll, Insert typing
  • 테스트 fixtureapp.mode = Mode::auto_for(focus) mirror — run loop 동작 일치
  • 기존 nav 테스트 (j_k_move, g_key_enqueues, e_toggles) 에 explicit app.mode = Mode::Normal
  • 신규 4 테스트 mode-authoritative 회귀 방지

테스트

  • 113 TUI 테스트 (기존 109 + 신규 4) 통과
  • cargo test --workspace --no-fail-fast -j 1 exit 0
  • cargo clippy --workspace --all-targets -- -D warnings clean

문서

  • README kebab tui: mode-authoritative dispatch 명시
  • HANDOFF: 2026-05-03 follow-up entry
  • spec status in_progresscompleted

p9-fb-12 partial 의 HOTFIXES entry 가 이미 deferral 사유 + 해결 조건 명시했으므로 새 entry 불필요.

## 요약 p9-fb-12 partial (PR #84) 의 deferred 부분 finalize. spec status `in_progress` → `completed`. ## 변경 - **`search::is_typing_mod`** 함수 삭제. search Char dispatch 가 `state.mode` 기반: - Normal + plain `j`/`k` → 선택 이동 - Insert + plain Char (chord 제외) → input.push - **`search::handle_key_search`** 의 `i` (chunk inspect) / `g` (editor jump) pre-pass 가 Normal 모드에서만 fire - **`ask::handle_key_ask`** input-empty heuristic 삭제. e/j/k 가 mode 분기 — Normal toggle/scroll, Insert typing - **테스트 fixture** 가 `app.mode = Mode::auto_for(focus)` mirror — run loop 동작 일치 - **기존 nav 테스트** (j_k_move, g_key_enqueues, e_toggles) 에 explicit `app.mode = Mode::Normal` - **신규 4 테스트** mode-authoritative 회귀 방지 ## 테스트 - 113 TUI 테스트 (기존 109 + 신규 4) 통과 - `cargo test --workspace --no-fail-fast -j 1` exit 0 - `cargo clippy --workspace --all-targets -- -D warnings` clean ## 문서 - README `kebab tui`: mode-authoritative dispatch 명시 - HANDOFF: 2026-05-03 follow-up entry - spec status `in_progress` → `completed` p9-fb-12 partial 의 HOTFIXES entry 가 이미 deferral 사유 + 해결 조건 명시했으므로 새 entry 불필요.
altair823 added 1 commit 2026-05-03 07:50:27 +00:00
p9-fb-12 partial (PR #84) 의 deferred 부분 finalize. spec contract 의
\"기존 P9-3 ask 의 e/j/k input-empty heuristic 제거 — mode 로 명확히\"
완료. spec status `in_progress` → `completed`.

## 핵심 변경

- **`search::is_typing_mod`** (CTRL/ALT chord filter) 함수 삭제.
  search Char dispatch 가 `state.mode` 로 분기:
  - Normal + plain `j`/`k` → 선택 이동 (Char 이라도 Normal 이면
    navigation)
  - Insert + plain `j`/`k`/Char(c) (chord 제외) → input.push
  - Insert + CTRL/ALT chord → no-op (예약 — 향후 binding 위해)
  - Normal + 그 외 Char → no-op (no typing in Normal)
- **`search::handle_key_search` 의 `i` (chunk inspect) / `g` (editor
  jump) pre-pass** 가 `state.mode == Mode::Normal` 일 때만 fire.
  Insert 모드면 typed char (input 에 push). 기존 SHIFT-aware
  matches!() 가드는 Normal-mode 진입 가드로 흡수.
- **`ask::handle_key_ask`** 의 input-empty heuristic 삭제. e/j/k:
  - Normal + `e` → toggle explain
  - Normal + `j` → scroll down (saturating_add)
  - Normal + `k` → scroll up (saturating_sub)
  - Insert + 모든 plain Char (chord 제외) → input.push
- **테스트 fixture** (`tests/search.rs::fresh_app`,
  `tests/ask.rs::fresh_app`) 에 `app.mode = Mode::auto_for(focus)`
  추가 — run loop 의 auto-flip 동작을 테스트가 mirror.
- **기존 nav 테스트** (`j_k_move_selection_within_bounds`,
  `g_key_enqueues_pending_editor_request`, `e_toggles_explain_in_
  normal_mode`) 가 `app.mode = Mode::Normal` 명시.
- **신규 4 테스트** mode-authoritative 동작 회귀 방지:
  - search: `j_in_insert_types_does_not_move_selection`,
    `arbitrary_char_in_normal_mode_is_noop`
  - ask: `e_types_in_insert_mode_does_not_toggle_explain`,
    `jk_scroll_in_normal_mode_type_in_insert`

## 테스트

- 기존 109 + 신규 4 = 113 TUI 테스트 통과 (38 lib + 20 ask + 12
  inspect + 10 library + 6 mode + 25 search + 2 chat — search 23→25,
  ask 18→20)
- `cargo test --workspace --no-fail-fast -j 1` exit 0
- `cargo clippy --workspace --all-targets -- -D warnings` clean

## 문서

- README `kebab tui` 행: \"mode-authoritative dispatch — Search 의
  j/k/i/g, Ask 의 e/j/k 는 NORMAL 모드에서만 명령으로 동작, INSERT
  에서는 입력 문자로 typing\" 명시
- HANDOFF: 2026-05-03 follow-up entry
- spec status `in_progress` → `completed`

## HOTFIXES

p9-fb-12 partial PR (#84) 의 \"Deferred\" 항목이 본 PR 로 finalized
— HOTFIXES 새 entry 불필요 (기존 entry 가 이미 deferral 사유 + 해결
조건 명시).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 requested changes 2026-05-03 07:51:25 +00:00
Dismissed
claude-reviewer-01 left a comment
Member

회차 1 — heuristic 제거 + mode-authoritative 전환 깔끔. test fixture 가 run-loop 의 auto_for mirror 하는 패턴 정확. 신규 4 회귀 테스트도 Insert-types vs Normal-commands 양 방향 cover.

actionable nit 2 건 (cosmetic) — (a) j/k 두 개 arm → body-branching 으로 flatten, (b) 자리 코멘트 노이즈.

회차 1 — heuristic 제거 + mode-authoritative 전환 깔끔. test fixture 가 run-loop 의 auto_for mirror 하는 패턴 정확. 신규 4 회귀 테스트도 Insert-types vs Normal-commands 양 방향 cover. actionable nit 2 건 (cosmetic) — (a) j/k 두 개 arm → body-branching 으로 flatten, (b) 자리 코멘트 노이즈.
@@ -248,0 +249,4 @@
// `is_typing_mod` heuristic (SHIFT-aware char filter) is gone —
// mode now decides whether a Char goes to the input buffer or
// becomes a navigation command. `Tab` (mode cycle), `Enter`
// (refresh), `Backspace`, arrow keys, Esc work in both modes

j/k 가 각각 두 개 arm 으로 분기 (Insert 가드 + Normal no-guard) — 동작은 정확하지만 reader 가 "왜 두 개" 한 박자 멈춤. body-branching 으로 flatten 하면 의도가 더 명확:

(KeyCode::Char('j'), KeyModifiers::NONE) => {
    if is_normal {
        move_selection(s, 1);
        s.preview = None;
    } else {
        s.input.push('j');
        s.input_dirty_at = Some(time::OffsetDateTime::now_utc());
    }
    KeyOutcome::Continue
}
(KeyCode::Char('k'), KeyModifiers::NONE) => {
    if is_normal {
        move_selection(s, -1);
        s.preview = None;
    } else {
        s.input.push('k');
        s.input_dirty_at = Some(time::OffsetDateTime::now_utc());
    }
    KeyOutcome::Continue
}

4 arm → 2 arm. "j/k 가 mode 따라 다르다" 가 한 자리에서 보임. ask.rs 의 패턴과도 정렬.

j/k 가 각각 두 개 arm 으로 분기 (Insert 가드 + Normal no-guard) — 동작은 정확하지만 reader 가 "왜 두 개" 한 박자 멈춤. body-branching 으로 flatten 하면 의도가 더 명확: ```rust (KeyCode::Char('j'), KeyModifiers::NONE) => { if is_normal { move_selection(s, 1); s.preview = None; } else { s.input.push('j'); s.input_dirty_at = Some(time::OffsetDateTime::now_utc()); } KeyOutcome::Continue } (KeyCode::Char('k'), KeyModifiers::NONE) => { if is_normal { move_selection(s, -1); s.preview = None; } else { s.input.push('k'); s.input_dirty_at = Some(time::OffsetDateTime::now_utc()); } KeyOutcome::Continue } ``` 4 arm → 2 arm. "j/k 가 mode 따라 다르다" 가 한 자리에서 보임. ask.rs 의 패턴과도 정렬.
@@ -317,11 +341,9 @@ fn cycle_mode(m: SearchMode) -> SearchMode {
}
}

is_typing_mod 함수 자리에 "removed" 안내 코멘트 3 줄이 영구 남아있는데, 같은 정보가 매치 블록 안 "p9-fb-12 follow-up" 코멘트 + commit message 에 이미 충분히 documented 입니다. 향후 reader 한테 "여기 뭔가 있었나" 만 묻게 만드는 노이즈.

그냥 삭제하는 게 깔끔. (HOTFIXES / commit history 가 reference).

`is_typing_mod` 함수 자리에 "removed" 안내 코멘트 3 줄이 영구 남아있는데, 같은 정보가 매치 블록 안 "p9-fb-12 follow-up" 코멘트 + commit message 에 이미 충분히 documented 입니다. 향후 reader 한테 "여기 뭔가 있었나" 만 묻게 만드는 노이즈. 그냥 삭제하는 게 깔끔. (HOTFIXES / commit history 가 reference).
altair823 added 1 commit 2026-05-03 07:54:23 +00:00
- search::handle_key_search 의 j/k 두 개 arm (Insert 가드 + Normal
  no-guard) 을 single arm + body if-branch 로 flatten. 4 arm → 2 arm,
  \"j/k 가 mode 따라 다르다\" 가 한 자리에서 보임. ask.rs 패턴과 정렬.
- `is_typing_mod` 자리에 남아있던 \"removed\" placeholder 코멘트 3 줄
  삭제. commit history 와 매치 블록 안 코멘트 가 reference.

113 TUI 테스트 통과 + clippy clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-05-03 07:54:33 +00:00
claude-reviewer-01 left a comment
Member

회차 2 — nit 2 건 깔끔히 반영.

  • j/k 4 arm → 2 arm body-branching (ask.rs 패턴과 정렬)
  • is_typing_mod placeholder 코멘트 삭제

추가 지적 없음. 머지 OK.

회차 2 — nit 2 건 깔끔히 반영. - j/k 4 arm → 2 arm body-branching (ask.rs 패턴과 정렬) - is_typing_mod placeholder 코멘트 삭제 추가 지적 없음. 머지 OK.
altair823 merged commit 5cd802e42a into main 2026-05-03 07:54:37 +00:00
altair823 deleted branch feat/p9-fb-12-mode-dispatch 2026-05-03 07:54:38 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: altair823-org/kebab#85