# v0.2.4 — 세션 터미널 외관 (테마 / Ctrl+wheel 줌 / 글로벌 기본 폰트), 시작 구간 type-ahead 안전, npm sigstore provenance

릴리즈 일자: 2026-05-04
이전 버전: v0.2.3

## 요약 (TL;DR)

- **세션 터미널에 8개 브랜드 프리셋 + Custom 5색 테마 picker**가 추가됐습니다. 탭바의 팔레트 버튼으로 즉시 전환, 세션마다 따로 저장.
- **Ctrl/Cmd + 마우스 휠로 폰트 줌**이 가능해졌습니다. Settings → Sessions에서 **글로벌 기본 폰트 사이즈**도 지정할 수 있습니다 — 새 세션이 그 값으로 시작하고, 이미 줌해 둔 세션은 자기 사이즈를 유지.
- **세션 시작 직후 친 키가 사라지지 않습니다.** PTY가 살기 전에 입력한 키스트로크는 서버가 큐에 모아 두었다가 PTY 가 살자마자 같은 순서로 흘려줍니다. 빈 description 으로 시작했을 때 의도치 않은 엔터가 한 글자 끼던 회귀도 함께 수정.
- **폰트 사이즈를 단계적으로 키울 때 welcome banner가 두세 번씩 누적되던 문제 수정.**
- **Settings 모달 사이드바 하단에 현재 빌드 버전을 표시**합니다. 어떤 버전을 돌리고 있는지 즉시 확인 가능.
- **npm 패키지에 sigstore 빌드 provenance 활성화** — npmjs.com에 "Built and signed on GitHub Actions" 배지가 표시되고, `npm audit signatures`로 무결성 검증이 가능합니다.

## 주요 변경

### 세션 터미널 테마 picker (per-session, 8개 브랜드 프리셋 + Custom)

세션 터미널 색상이 cmd 톤에 하드코딩되어 사용자가 바꿀 수단이 없었습니다. 이번 버전부터:

- 탭바의 **팔레트 버튼**으로 portal popover 열림 — 3×3 그리드에 프리셋 카드와 Custom 카드
- 8개 브랜드 프리셋: **Default / Claude / Vercel / Supabase / Stripe / Spotify / Ferrari / NVIDIA**
- **Custom**: 5색 (background / foreground / cursor / selection / accent) native color picker로 자유 편집
- 선택은 **세션마다 따로 저장** (`localStorage` 영속화, DB 마이그레이션 없음). 한 세션 색을 바꿔도 다른 세션은 그대로

### Ctrl+wheel 폰트 줌 + 글로벌 기본 폰트 사이즈

마우스 사용자에게 익숙한 패턴(VS Code/iTerm/브라우저 동일)을 추가하고, 매 세션 같은 줌을 반복해야 했던 불편을 해결했습니다.

- **Ctrl/Cmd + 마우스 휠** → 1px 단위 줌 in/out (8-28px clamp). 비-modifier 휠은 기존대로 xterm scrollback에 그대로 통과
- 기존 ±버튼 / Ctrl+± 단축키도 그대로 동작
- **Settings → Sessions** 탭에 **터미널 기본 폰트 사이즈** range + number input 추가 — 신규 세션 + per-session 줌이 없는 active 세션에 즉시 반영 (이미 줌해 둔 세션은 자기 사이즈 유지)
- 350ms 디바운스 저장 + 라이브 브로드캐스트로 슬라이더 움직이는 동안 미리보기 가능

### 세션 시작 직후 키스트로크 안전 (server-side type-ahead 버퍼)

세션을 막 시작한 직후 빠르게 타자를 치면 입력이 silently 사라지거나, 의도치 않게 엔터로 제출되거나, 폼 description이 통째로 날아가는 회귀가 여러 결로 겹쳐 있었습니다. 이번 버전에서 다음과 같이 정리됐습니다:

- **Send/Skip 배너가 떠 있는 동안**: 클라이언트와 서버 양쪽에서 PTY 입력을 차단해 사용자가 명시적으로 Send 또는 Skip을 눌러야 description이 들어갑니다 — 자동 send 같은 destructive 동작은 없음
- **PTY 가 아직 살기 전 (`POST /start` 응답 직전 구간)**: 클라가 막는 대신 **서버가 들어오는 키를 세션별 큐에 모아 두었다가 PTY가 살자마자 같은 순서로 흘려줍니다**. 사용자 시점엔 "타자를 친 그대로 명령줄에 들어감"
- **빈 description 으로 시작했을 때 의도치 않은 엔터 한 글자 끼던 버그 수정**: 어댑터가 빈 prompt에 대해 `'\n'`을 합성해 PTY 에 한 번 enter 를 박아 type-ahead 가 엔터로 제출되던 회귀 — 빈 prompt면 `stdinPrompt` 자체를 만들지 않도록 가드

부수적으로 한글 IME helper textarea 가 mount 직후 cursor 셀로 사전 배치되어 첫 자모 입력 시 IME 후보창이 viewport 우하단에 뜨던 케이스도 함께 잡았습니다.

> 한글 IME 합성 글자가 React Ink 기반 TUI(Claude Code/Codex/Gemini)의 visual block cursor 와 한 셀 어긋나 보이는 케이스는 이번 버전에 두 차례 수정 시도 후 root cause 가 가설과 다름이 확인되어 둘 다 revert 됐습니다. 합성 중 시각 어긋남은 잔존하지만 commit 후 최종 텍스트는 CLI 입력 박스에서 정상 렌더되므로 known issue 로 둡니다 (자세한 내용은 `docs/changelog/2026-05/2026-05-04-3.md`).

### 폰트 사이즈 변경 시 welcome banner 중복 누적 수정

세션 터미널에서 Ctrl+= / Ctrl+- 로 폰트를 단계적으로 키우면 welcome banner (Claude Code 로고 + 모델 + 경로 4줄 블록) 가 xterm scrollback 에 두세 번씩 누적되던 회귀를 수정했습니다.

- `session:resize` broadcast 디바운스를 50ms → 300ms 로 연장해 빠른 +/- 연타가 단일 resize 로 합쳐짐
- ResizeObserver 의 150ms 타이머와 분리된 별도 ref 로 폰트 디바운스가 짧은 창에 덮어쓰이지 않도록
- 폰트 미세 변경으로 cell grid 가 바뀌지 않으면 redundant SIGWINCH 자체를 보내지 않음 (early-return)

### Settings 모달에 빌드 버전 표시

사용자가 어떤 CLITrigger 버전을 돌리는지 `package.json` 을 직접 열지 않고도 확인할 수 있도록 **Settings 모달 사이드바 하단**에 현재 빌드 버전을 muted footer 로 추가했습니다 (`v0.2.4` 형식). Vite define 으로 빌드 타임에 inject 되어 zero-cost.

### npm sigstore 빌드 provenance 활성화

npm 공급망 보호를 위한 sigstore 기반 빌드 provenance 를 enable 했습니다.

- npmjs.com 패키지 페이지에 **"Built and signed on GitHub Actions"** 배지가 표시됩니다
- 사용자는 `npm audit signatures` 로 특정 tarball 이 이 레포의 특정 커밋에서 빌드되었는지 검증할 수 있습니다 — 도용된 npm 토큰으로 변조된 버전을 publish 하는 공급망 공격 완화
- OIDC 토큰이 GitHub Actions per run 으로 발급되므로 **secret 회전 / 추가 등록 불필요**

### 릴리스 파이프라인: 태그가 release notes 포함 트리를 가리킴

이전엔 `chore(release)` 커밋과 태그가 먼저 박힌 뒤 release notes 커밋이 따라붙어, 태그 ref 만 체크아웃하면 `docs/release-notes/<tag>.md` 가 트리에 없는 상태였습니다. 이를 우회하던 워크플로의 별도 `origin/main` fetch 도 태그 push 와 main push 사이의 race 가 잠재해 있었습니다.

이번 버전부터:

- release skill 의 phase 가 재배치되어 `package.json` / `package-lock.json` 과 release notes 가 같은 커밋에 stage 되고, 그 뒤에 태그를 박습니다
- 워크플로는 단순한 `cp` 하나만 사용 (별도 main fetch 우회 제거)

> 사용자에겐 무관한 인프라 변경이지만, 향후 GitHub Release body 가 항상 정확히 해당 태그 시점의 노트를 반영합니다.

## 마이그레이션

별도 마이그레이션 작업 불필요. 다만:

- 기존 세션은 **글로벌 기본 폰트 사이즈** broadcast 영향을 받지 않습니다 — 한 번이라도 줌/축소를 했던 세션은 자기 사이즈를 유지하고, 줌한 적이 없는 active 세션과 신규 세션만 글로벌 기본값을 따릅니다
- 터미널 테마는 per-session localStorage 라 새 세션은 Default 로 시작합니다 — 원하는 테마는 팔레트 버튼으로 직접 선택

## 설치 / 업데이트

```bash
npm i -g clitrigger@0.2.4
```

데스크탑 앱: GitHub Release 자산의 `.exe` / `.dmg` / `.AppImage` 사용.

## 전체 커밋 목록

- 1dce977 WIP(docs): split 2026-05-04 changelog into 7 entries
- a33b596 chore(release): bundle release notes into release commit
- 543586e revert: drop ineffective IME positioning fixes
- 556890c fix(session): shift IME composition to match CLI custom block cursor
- 78f095a chore(release): enable npm provenance publishing
- 9b921dc fix(session): align Hangul IME helper textarea to actual cursor cell
- 37d71e8 fix(session): debounce font-size resizes to dedupe CLI welcome banner
- 2695764 fix(session): prevent stray Enter on type-ahead and fix Hangul IME placement
- 91fed94 fix(session): buffer type-ahead keystrokes during PTY spawn
- e6ed708 feat(session): add Ctrl+wheel zoom and global default font size
- de115cd feat(session): add per-session terminal theme picker with brand presets
- e0ad308 fix(session): block keystrokes during pendingFit/starting phases
- 73072b2 fix(session): block keystrokes while initial prompt awaits Send/Skip
- 38ab065 feat(settings): show app version in settings modal sidebar

## 관련 문서

- [상세 changelog](../changelog/) — 날짜별 기술 결정 기록 (특히 2026-05-04-2 ~ 2026-05-04-7)
