# HANDOFF — understatus (+ lterm statusline 통합)
> 다음 세션/에이전트용 핸드오프. 제품은 원래 **statusticon** 코드네임이었다가 출시 시 **understatus**로 개명. 온디스크 디렉터리는 여전히 `statusticon/`이지만 제품/크레이트/레포/바이너리는 전부 **understatus**.
>
> **최신 세션 작업 = §0 (understatus ctx 소멸 버그 fix [PR #9] + lterm status 라우팅 인프라 배선 [PR #122] — 둘 다 머지).** 직전 세션(06-07)은 §0B, Phase 1 배경은 §A, v0.3.0 릴리스 배경은 §C.
---
## ⚠️ 먼저 읽기 — 로컬 툴체인 깨짐 (양쪽 레포 공통)
**Homebrew `rustc`/`cargo`가 깨져 있다.** `/opt/homebrew/bin/rustc`가 없는 `libLLVM.dylib`를 참조 → bare `cargo`/`rustc`/`clippy`/`rust-analyzer` 실패(dyld 에러, 가끔 오해의 exit 0). `/opt/homebrew/bin`이 `~/.cargo/bin`보다 PATH 앞이라 **bare `cargo`는 깨진 쪽으로 resolve됨.**
**항상 rustup 툴체인 사용** (understatus·lterm **둘 다**):
```bash
export PATH="$HOME/.cargo/bin:$PATH" # ~/.cargo/bin/cargo = stable-aarch64, 정상
```
- **rust-analyzer/IDE 진단은 가짜다**(phantom E0308, 실제 사용 중인 항목에 dead_code 등). **IDE 진단 무시, rustup `cargo`/`clippy` 출력만 신뢰.** (이번 세션에도 IDE가 `parse_lterm_input` 등을 dead로 표시했으나 rustup clippy는 클린.)
- `gtimeout` 없음 → 타임아웃은 background+polling kill 패턴으로.
- x86_64 크로스빌드는 로컬 실패 → CI(macos-14). 네이티브 arm64 빌드/테스트는 rustup으로 정상.
---
## §0. 최신 세션 (2026-06-08) — 완료 / 다음 세션 이월 ← **여기부터 읽기**
> 이번 세션: ① understatus **ctx 소멸 버그 수정** + ② lterm **status 백엔드 라우팅 인프라 배선**(둘 다 머지). 직전 세션(06-07)은 §0B, 배경은 §A~E.
### ✅ 완료 (양쪽 main 머지됨)
1. **understatus ctx 소멸 버그 수정** — Claude Code statusline JSON의 `context_window.used_percentage`가 **간헐 누락**되면 understatus가 ctx 세그먼트를 생략하면서 동시에 체인된 omc HUD ctx도 strip(§0B-2)해 **ctx가 화면에서 완전히 사라지던** 버그(스크린샷 증상). 체인된 omc HUD의 자체 안정화는 매 refresh마다 새 프로세스로 떠 인메모리 상태가 초기화돼 86↔98로 튀던 게 strip의 원인. 수정:
- **토큰 fallback**: `context_window`의 `current_usage` 토큰합/`total_input_tokens` ÷ `context_window_size`(omc HUD `getContextPercent`와 동일 우선순위).
- **resolve_context_percent**: 양수 native > TTL(30s) 내 직전 native 유지(hold, 세션 캐시 `ctx_native`) > 토큰 fallback > 생략.
- **비대칭 하강 가드**: 상승 노이즈(86↔98)는 hold로 차단하되, fallback이 직전 native보다 12%p↓이면(`/compact` 등 실감소) hold 해제·즉시 반영. omc 대칭 tolerance가 86↔98 상승에도 튀던 회귀 회피.
- **held 캐시 신뢰경계**: `interpret_held_native_ctx`가 `0<v≤100` 유한값만 인정(변조 캐시 거부→fallback 저하). **lenient f64 역직렬화**: 토큰 필드 타입 드리프트가 statusline 전체를 무력화하지 않게 격리.
- → **understatus PR #9 머지**(main `a9368bf`, 커밋 4개). **quad-review-loop 2라운드**(Codex+Forge 2트랙 합의 MEDIUM=held 검증 반영). **297 테스트**.
- 핵심 파일: `src/claude.rs`(compute_context_fallback/percent_of/clamp_percent/resolve_context_percent/ContextResolution/deserialize_lenient_f64), `src/main.rs`(resolve_claude_context/interpret_held_native_ctx, `CONTEXT_HOLD_TTL_SECONDS=30`/`CONTEXT_HOLD_DROP_TOLERANCE=12`/`CONTEXT_NATIVE_CACHE`).
2. **lterm status 백엔드 라우팅 인프라 배선** — §0B 이월의 "라우팅 실제 배선" **1단계 완료(behavior-preserving)**. PoC `select_status_backend`(이전 `#[allow(dead_code)]`)를 attach 진입부에 실배선:
- `status_enabled = select_status_backend(policy, &gather()) != Disabled && requests_row()` — 기존 `status_bar_supported(requests_row())`와 **정확히 동치**(backend≠Disabled ⟺ !forced_off && terminal_capable). 미사용된 `status_bar_supported` 제거.
- `gather_status_env_snapshot` 신설(실 env→StatusEnvSnapshot).
- **지뢰 처리(이월 항목)**: `tmux_compat::inside_cmux` `pub(crate)` 승격, `detect_real_tmux`+순수 `is_self_provided_tmux`로 lterm self-TMUX(`server::fake_tmux_value`=`{lterm_socket},{pid},0` + `LTERM_SOCKET` export) 식별 → **real_tmux 오분류 방지**. `detect_is_iterm`. `#[allow(dead_code)]` 4개 제거.
- → **lterm PR #122 머지**(main `fbeade0`). code-reviewer APPROVE(동작 동치 검증). 미구현 백엔드(NativeChrome/DelegatedSurface/TitleCueDelegation)는 `status_enabled`(bool)로 환원돼 기존 DECSTBM 경로 그대로(동작 불변) → **라이브 검증 불필요**.
3. **understatus `workspace.repo` 타입 드리프트 수정 (진짜 ctx 소멸 원인)** — 사용자가 "여전히 ctx 안 보임" 보고 → **statusLine stdin 라이브 캡처**로 진단: Claude Code가 `workspace.repo`를 문자열→`{"host","owner","name"}` **객체**로 바꿨는데 understatus `RawWorkspace.repo: Option<String>`이 거부 → `RawClaudeInput` **전체 파싱 실패** → model/ctx/cost/git이 통째 사라지고 시스템 지표만 남음. (`used_percentage` 60%는 정상 전달됐고 파싱만 실패 — §0-1 ctx 수정과 무관한 별개 회귀.) 실제 payload에서 repo만 문자열로 바꾸면 ctx 즉시 복구로 확정.
- **수정**: `deserialize_lenient_string`(Value로 받아 문자열만 추출, 객체/숫자/배열/bool/null→None) 추가. `RawWorkspace`(4필드)·`RawModel`(2필드)·`RawClaudeInput` 최상위(session_id/cwd) String 필드에 적용 → 표시·캐시키 String 필드 **일반화 방어**(향후 다른 필드 객체화도 안전). git_worktree 우선 폴백 보존. **(별개)** hold TTL 30s→**600s** 상향(긴 used_percentage 누락 대비).
- → **understatus PR #10 머지**(main `930d6be`). code-reviewer APPROVE. **293 테스트**(repo 객체 드리프트 보존 등 +5). 라이브 화면 ctx 복귀 사용자 확인.
- **진단 교훈**: 증상을 추측(TTL)하지 말고 **statusLine stdin을 캡처**해 측정하라. 캡처 래퍼는 `tee`(부분쓰기 race) 대신 stdin 전체를 변수로 받아 원자적 append. 두 Claude 세션이 동시 활성이면 전역 캡처 파일에 섞이니 `session_id`/`cwd`로 구분.
### ⏭ 다음 세션 이월
1. **lterm status 실렌더 트랙**(가장 큰 가치, 미구현). 라우팅은 라이브지만 비-DECSTBM 백엔드는 아직 DECSTBM로 환원됨. 트랙별:
- **DelegatedSurface(Cmux)** — ⚠️ **선결 조사 필요**: cmux split은 surface **ref 문자열만** 주고(`open_cmux_split`/`send_cmux_attach`는 attach 명령 **1회** 주입), lterm은 그 surface에 status 바이트를 **주기적으로 쓸 write 핸들이 없음**. `cmux send --surface <ref> <raw SGR>`가 지원되는지 **cmux CLI 계약을 document-specialist로 조사**해야 실현 가능 판정(lterm 레포엔 cmux 구현 없음).
- **NativeChrome(iTerm OSC1337)** — from-scratch(코드 전무). `.poc/poc2-iterm-status.sh`가 검증법 제시(SetUserVar base64 plain text, truecolor/멀티라인 불가). base64 `protocol.rs:309`(pub 승격 필요), iTerm 식별 `detect_is_iterm` 이미 있음.
- 배선점: `attach_pty_rows`(client.rs ~3595)가 "본문 1행 양보 여부" 단일 결정점 — 비-DECSTBM 백엔드는 full `rows` 전달해야 함. 콘텐츠 계약(`LTERM_STATUS_COMMAND`→`command_line`)은 backend-무관 재사용 가능(소비점은 `build_draw_body` 1곳).
- 실렌더는 동작을 바꾸므로 **라이브 PTY attach 육안 검증 필수**(자동 테스트로 색·입력칸 회귀 못 잡음 — HANDOFF 반복 교훈).
2. ~~**understatus 새 버전 릴리스**~~ → **v0.4.0 배포 진행 중**(이번 세션): v0.3.0 이후 누적분(lterm statusline 통합·codex 심층판독·strip_chain_ctx·ctx fallback/hold·repo drift fix)을 minor bump로. PR #11(버전 3종+Cargo.lock) → 태그 `v0.4.0` → release.yml(arm64+x64) → `cargo publish` → Homebrew tap(`ictechgy/homebrew-tap`) → **npm은 passkey라 사용자 직접** `npm publish ./npm --access public`. (§C 절차)
3. **understatus 잔여 LOW**(알려진 한계): display=None 내는 극단 프레임(양수 native 부재 + 30s TTL 초과 + 토큰 fallback 부재 = 사실상 cold-start)엔 omc strip과 겹쳐 ctx 잠깐 빔. 빈도 낮고 cold-start는 빈 게 맞아 미수정.
### 검증 수치(이번 세션)
- understatus main: clippy 클린, **297 테스트**, release 빌드 클린, CI 그린.
- lterm main: **1.96** clippy `-D warnings` 클린, unit **377**, release 클린, CI 7체크 SUCCESS.
- ⚠️ **lterm CI는 stable 1.96**(2026-05-28~). 로컬 rustup stable이 1.94면 `manual_option_zip` 등 신규 lint를 못 잡음 → `rustup toolchain install 1.96.0` 후 `cargo +1.96.0 clippy`로 CI 일치 검증(이번 세션 그 lint로 CI 1차 실패→로컬 1.96으로 재현·수정).
- lterm cli_smoke `notify_*cmux*`는 병렬 `CMUX_*` env 경합 flaky → `--test-threads=1` 또는 단독 실행(본 변경 무관).
### PR 상태
- understatus: **#9**(ctx fix) merged · **#10**(repo drift fix) merged · **#11**(v0.4.0 범프) 릴리스 진행 중.
- lterm: **#122**(라우팅 인프라 배선) merged.
---
## §0B. 직전 세션 (2026-06-07) — 완료/배경
> 직전 세션의 활성 작업은 §A(Phase 1)가 아니라 아래였다. §A~E는 배경/참고로 보존. 상세 상태는 자동메모리 `lterm-status-default-on`에 누적.
### ✅ 완료 (전부 양쪽 main 머지됨)
1. **Codex 세션 심층판독 (Phase 2-1)** — understatus가 `~/.codex/sessions/**/rollout-*.jsonl` 파싱해 model/ctx%/rate-limit/plan/effort 표시(`--source lterm` + agent=codex). `src/codex.rs`, `[codex]` config(enabled/freshness_minutes/scan_days), `src/claude.rs` 세션/페인 라벨. → **understatus PR #6 머지** (§B-1 완료).
2. **omc ctx 튐 진단·수정** — statusLine(understatus)은 기존 statusLine(omc HUD)을 `[chain]`으로 자식 실행해 합성하는데, 그 **체인된 omc HUD**가 Claude payload `used_percentage` 누락 시 토큰비율로 ctx를 발명해 86↔98로 튐(understatus 자체는 순수통과=무죄, 통제 재현으로 증명). understatus가 체인 출력에서 omc의 ctx 표시만 외과 제거(`[chain] strip_chain_ctx`, 기본 on). `src/chain.rs::strip_chained_context`(ANSI-aware·UTF-8 안전·bar/색/경고줄 처리)+13테스트. → **understatus PR #8 머지**(원래 #7; 스택 머지 중 base 삭제로 auto-close되어 #8 재생성). code-review APPROVE.
3. **lterm status-row 안정화** — content-only 백스톱(`force_content_redraw`): 주기 백스톱이 reserve(DECSTBM)를 재방출→codex scroll-region 침범→입력칸 증식하던 회귀 제거. + self-heal/dedup/cursor-hide. → **lterm PR #121 머지**. **라이브 시각검증 PASS**(다른 cmux 창 갔다 와도 입력칸 깔끔 — 사용자 확인).
4. **cross-env status 백엔드 라우팅 PoC** (lterm #121, **미배선**) — `select_status_backend(policy, &StatusEnvSnapshot) -> StatusBackend`(Disabled/DecstbmOverlay/NativeChrome/DelegatedSurface(Cmux|Tmux)/TitleCueDelegation) 순수 결정함수 + 8 라우팅 테스트. `#[allow(dead_code)]`라 런타임 영향 0.
5. lterm 바이너리: `~/.local/bin/lterm`은 `target/release/lterm` **심볼릭 링크** → 새 빌드가 곧 설치본(새 `lterm a`부터 #121). 데몬 핫스왑 안 됨, 새 attach 필요. status는 **client(attach) 측 렌더**라 데몬 재시작 불필요.
**연구 결론(핵심)**: 일반 터미널 + 메인버퍼 에이전트(codex)에서 **분리형 status 한 줄의 무손상 공존은 원리적으로 불가능**(DECSTBM 단일 전역 자원, host가 에이전트 scroll-region 질의 불가, alt-screen 게이트는 메인버퍼라 무력). best-effort=~50ms 수렴. 안전은 host=터미널(tmux/cmux) 또는 셀 그리드 밖 네이티브(iTerm OSC1337/탭)일 때만 성립.
### ⏭ 다음 세션 이월 — 라우팅 **실제 배선** (PoC만 머지됨)
`select_status_backend`는 결정만, 렌더 배선 미구현. 단계:
- `client.rs` `status_enabled`(~3089) 직후 `select_status_backend` 호출로 분기. PTY rows-1 clamp/reserve는 `DecstbmOverlay`일 때만.
- `StatusBackend` trait(reserve/draw/teardown 3메서드) — 공통 콘텐츠 계약은 기존 `LTERM_STATUS_COMMAND`+stdin JSON(`build_status_payload` v1)+stdout SGR passthrough 재사용(테마/펄스/세션라벨 N분기 방지).
- cmux 배선: attach 경로에서 `open_cmux_split`/`send_cmux_attach`(현재 tmux-compat split 핸들러에서만 호출) 신규 호출.
- **배선 지뢰(반드시 처리)**: ① `real_tmux`는 lterm이 자식에 TMUX를 **스스로 export**하므로 순진한 `$TMUX` 판정 시 오분류 → lterm-injected TMUX 식별해 `real_tmux=false`. ② `tmux_compat::inside_cmux`는 **private** → `pub(crate)` 승격. ③ NativeChrome OSC1337 값은 **base64 인코딩 필수**(`.poc/poc2`처럼) — OSC 인젝션 차단. ④ 멀티라인은 DelegatedSurface(cmux/tmux)에서만, DECSTBM/NativeChrome은 단일라인 격하.
- 배선 후 `.poc/poc2-iterm-status.sh`(iTerm), `.poc/poc3-convergence.md`(수렴+입력칸) 라이브 검증.
### 검증 수치(이번 세션 최종)
- understatus main: 빌드 클린 + **258 테스트**(250+8) 통과.
- lterm main: **581 테스트**(373 unit + 201 cli_smoke + 7 lifecycle) 통과, release 무경고.
- lterm #121 **quad-review-loop**: 4렌즈(정확성/보안/적대적/테스트) + round-2 델타 재검토, **CRITICAL/HIGH/확정블로커 0**, critic ACCEPT.
### PR 상태 (전부 머지/정리됨, 열린 PR 0)
- understatus: **#6**(codex) merged · **#8**(strip, =구 #7) merged.
- lterm: **#121**(status-row 안정화 + 라우팅 PoC) merged · **#120**(self-heal, #121이 supersede) closed.
---
## §A. 배경(Phase 1, 완료) — lterm × understatus statusline 통합
### 목표
Codex CLI는 Claude Code식 **command-backed statusline**(스크립트가 stdin JSON 받고 포맷 텍스트 반환 → 하단 렌더)을 미지원(공식 FR `openai/codex#17827`). 그래서 사용자의 터미널 세션 데몬 **lterm**(tmux 유사, 화면을 소유, `lterm codex` 등 에이전트 래핑 내장)의 하단 status row를 **command-backed로 확장**해, lterm 안에서 도는 모든 에이전트(Codex·Gemini·Claude…)가 에이전트 자체 지원과 무관하게 understatus statusline을 얻게 한다.
**사용법 (양쪽 main에 머지 완료):**
```bash
LTERM_STATUS_COMMAND="understatus render --source lterm --oneline" lterm codex
```
### 현재 상태 = Phase 1 완료, 양쪽 레포 main 머지됨 ✅
- **understatus** (이 레포): **PR #5 머지** → main. `render --source lterm` + `--oneline` 추가.
- `src/claude.rs::parse_lterm_input`(lenient, git 비활성, cwd 표시용, session_key 합성), `src/main.rs` `render --source <claude|lterm>`/`--oneline` 파서 + `run_render_pipeline(source, oneline)`, `tests/oneline.rs`.
- 설계/합의 문서: `docs/superpowers/specs/2026-06-05-lterm-statusline-integration-design.md` (ralplan 합의 APPROVE본 — **Phase 2 백로그는 이 문서 §15**).
- **lterm** (`/Users/jinhongan/Desktop/light_terminal`, 제품=lterm): **PR #119 머지** → main (6커밋 `980c4b5..6a66a33`).
- `src/sanitize.rs`: `sanitize_status_command_line`(신뢰 불가 stdout → **SGR-only 화이트리스트**, C1 CSI 차단, OSC/DCS/미완결 ESC 폐기, 단일행 강제, param `[0-9;:]`만+길이64/개수16 상한) + `truncate_status_line_ansi`(SGR 원자 보존+grapheme/CJK 폭 절단+끝 `\x1b[0m`).
- `src/client.rs`: `StatusCommandConfig`(env), `agent_name_from_command`, `build_status_payload`(serde JSON, 필드 길이 cap), `run_status_command`(셸 미경유 argv spawn, stdin→EOF, **reader 스레드+deadline로 status 스레드 무블로킹**, kill/wait 좀비 회수, 64KB 상한, process_group(0)), `spawn_status_command_thread`/`apply_pending_status_command`(metadata 동형), `StatusBar.command_line`+`draw_at_size` 통합(ANSI=1이면 테마 bg off+understatus 색), `attach` 배선, interruptible sleep, alt-screen pause.
### env/flag (lterm)
| 키 | 기본 | 의미 |
|---|---|---|
| `LTERM_STATUS_COMMAND` | (없음) | 설정 시 status row를 이 명령 출력으로. 미설정 시 기존 동작(세션+페인) **바이트 동일**. |
| `LTERM_STATUS_INTERVAL` | `2` | 초, `1..=3600` 클램프 |
| `LTERM_STATUS_ANSI` | `1` | 색 통과(SGR-only). `0`=strip(plain, 테마 bg 유지). **사용자가 =1 확정**(understatus 색 위주). |
| `LTERM_STATUS_DEBUG` | `0` | `1`이면 명령 실패/타임아웃 stderr 1줄 |
### stdin JSON 계약 (lterm → understatus)
```json
{"source":"lterm","version":1,"session":"codex","pane":"%3",
"session_key":"codex/%3","agent":"codex","cwd":"...","cols":120,"rows":40}
```
- understatus는 lenient: 미상 필드 무시, 빈 `{}` 무패닉. `version`은 읽되 무시(forward-compat). ignored 필드(version/cols/rows/source)는 `serde_json::Value`로 관대 — 타입 드리프트가 전체 파싱을 안 깸.
- **Phase 1에서 git branch 비활성**: understatus git 도출은 `workspace.git_worktree|repo`(워크트리 루트)를 요구하는데 lterm `SessionInfo.cwd`는 세션 시작 dir라 보장 안 됨 → cwd→branch 안 함(`$PWD` 폴백 코드 없음). git은 Phase 2(walk-up).
### 검증 (이번 세션, 양쪽 독립 확인)
- understatus: clippy `-D warnings` 클린, fmt 클린, 테스트 **205**, E2E OK.
- lterm: clippy 클린, fmt 클린, 단위 **352**, release 빌드, **라이브 PTY E2E PASS**(3회 — 실제 attach 화면 status row에 understatus truecolor 출력 `· mem 48% · disk 77% …`).
- 양쪽 **quad-review-loop SUCCESS**(4모델 교차검증). lterm R1에서 **실제 subprocess HIGH blocker**(stdin write/stdout read_to_end 무한 블로킹)를 적발·수정한 게 핵심 성과.
---
## §B. Phase 2 (다음 세션 — 선택, 우선순위순)
spec `docs/superpowers/specs/2026-06-05-lterm-statusline-integration-design.md` §15 참조.
1. ~~**Codex 세션 심층판독**~~ ✅ **완료**(§0-1, understatus #6 머지). `src/codex.rs`로 `~/.codex/sessions/**/rollout-*.jsonl` 파싱→model/ctx%/rate-limit/plan/effort.
2. **git branch**: `--source lterm`에서 cwd→`.git` walk-up(워크트리 루트 도출) 또는 payload에 `git_worktree` 추가.
3. **`mode=pane`** (split, full truecolor 다행): **연구 완료**(§0 연구결론, 메모리 §A). cmux=ghostty 기반 GUI 멀티플렉서, 별도 surface=ghostty PTY라 scroll-region 충돌 **구조적 부재**, lterm 이미 cmux 통합(`open_cmux_split`/`send_cmux_attach`) 보유 → 라우팅 배선(§0 이월)의 `DelegatedSurface(Cmux)` 트랙으로 구현. "OMX HUD-watch 재사용"은 실체 없음(omx HUD엔 ctx 요소 자체 없음).
4. **TOML `[status]` config** + `lterm attach --status-command` CLI 플래그(현재 env-only). lterm에 config 로더·`toml` 의존 없음 → 신설 필요.
5. **다중 에이전트 세그먼트**(Gemini/OpenCode 등 전용 표시).
6. **lterm 잔여 LOW**(비차단, quad-review 문서화됨):
- `build_status_payload`가 daemon의 `info.agent_name`(protocol.rs/server.rs) 대신 `info.command` 재파싱 → daemon값 우선 사용.
- reader 스레드 detach가 자손-stdout-점유 시 leak 가능 → 완전 해결은 process **group-kill**(`kill(-pgid)`, libc/nix 의존 필요) = Phase 2.
- `split_sgr_and_text`는 살균 출력 전제(docstring 명시) — pub/재사용 시 주의.
- status row 테마 bg 옵션화(ANSI=1에서도 bg 유지 선택), spawn 실패 백오프.
---
## §C. 배경 — understatus v0.3.0 (이미 출시됨)
> 제품은 **v0.3.0가 4채널 모두 라이브**. 위 statusline 작업은 그 위에 얹은 미릴리스 기능(아직 새 버전 안 냄 — 릴리스하려면 §C 릴리스 절차).
- **GitHub(공개):** https://github.com/ictechgy/understatus (default `main`).
- **lterm GitHub:** https://github.com/ictechgy/light_terminal (default `main`). Homebrew: `brew install ictechgy/tap/lterm`.
- **understatus 채널(전부 v0.3.0 라이브):** crates.io(`cargo install understatus`), Homebrew(`ictechgy/understatus/understatus`), npm(`understatus`), GitHub Release.
- **언어/플랫폼:** Rust 2021, **macOS only**(arm64+Intel). understatus build.rs는 IOKit+CoreFoundation 링크.
### ⚠️ Auth (지난 세션에 물림)
- **`gh` 토큰 만료 가능**. `gh auth status`가 invalid여도 `git push`(osxkeychain)·일부 `gh` API는 동작할 수 있음. `gh` 실패 시 `gh auth refresh -h github.com`(브라우저 — 에이전트 불가, 사용자에게). **이번 세션엔 gh 정상**이었음(PR #5/#119 생성·머지 성공).
- **npm publish/deprecate는 브라우저 passkey(EOTP) 필요** — 에이전트 일반적으로 불가.
### understatus 릴리스 절차 (v0.3.x+, 새 버전 낼 때)
1. **3종 버전 범프**: `Cargo.toml`, `npm/package.json`, `npm/install.js`(`const VERSION`) + `cargo build`로 `Cargo.lock` 갱신. 브랜치→PR→**rebase-merge**.
2. `git tag -a vX.Y.Z && git push origin vX.Y.Z` → `release.yml`(macos-14, arm64+x64) 그린 **대기 후** `cargo publish --allow-dirty`(IRREVERSIBLE).
3. Homebrew tap `Formula/understatus.rb` url+sha256 갱신(`curl -L <archive> | shasum -a 256`), repo `homebrew/understatus.rb` 사본 동기화(별도 PR).
4. npm: 로컬 `npm install ./npm --prefix /tmp/test` E2E 후 **사용자**가 `npm publish ./npm --access public`.
---
## §D. 이번 세션에서 배운 것 (반복 회피)
- **워크플로**: brainstorming → ralplan(합의) → spec → 청크 단위 구현(executor) → quad-review-loop → 머지. 효과적이었음. ralplan/quad-review가 **코드 사실 불일치·실제 보안 blocker를 잡음**(예: understatus가 cwd로 git 도출 안 함; lterm subprocess 타임아웃이 전체를 못 막음).
- **agy(Antigravity)**: 리뷰형 프롬프트 **~8KB 초과 시 hang** → 큰 diff에선 매번 SKIP(정상). 가용 3트랙(Claude+Codex+Forge)으로 합의.
- **Forge(forgecode)**: 큰 프롬프트에서 **구조화 출력 없이 reasoning 스트림만** 내는 경우 많음 → verdict/JSONL 없으면 **폐기**(합의에서 제외). flaky.
- **executor 장시간 태스크**: 매우 긴 단일 태스크에서 **API 소켓 에러로 중단**된 사례 있음 → 큰 작업은 **청크로 분할**(lterm은 3청크: 게이트→플러밍→draw통합)하면 안정적. 중단 시 부분 변경 확인 후 직접 마무리 가능.
- **lterm status bar는 attach 클라이언트가 그리는 chrome** → `lterm logs`/`capture`(scrollback)엔 안 나옴. 관측하려면 **실제 PTY attach** 필요(python `pty.fork` 하니스로 캡처 → 출력에 `mem`/`disk`+`\x1b[38;2;` 있으면 렌더 성공).
- **lterm AGENTS.md/HANDOFF.md는 gitignored**(로컬). 검증 스위트: `cargo fmt -- --check`/`cargo clippy --all-targets -- -D warnings`/`cargo test`/`cargo build --release --locked`/`cargo audit`. **의존성 추가는 정당화 필요**(group-kill용 libc 등은 신중히).
- **quad-review-loop blocker 기준** = severity HIGH+ AND consensus(≥2 트랙). MEDIUM/LOW는 루프를 안 멈추지만, 사용자는 실제 MEDIUM도 고치는 걸 선호(이번에 다 반영).
---
## §E. 빠른 상태 확인
```bash
# understatus (이 레포)
cd /Users/jinhongan/Desktop/status_ticon/statusticon
export PATH="$HOME/.cargo/bin:$PATH"
git log --oneline -6 # main: ctx fix #9(b5df2ad..a9368bf) + Merge #8(strip)·#6(codex)
cargo test # 297 통과
echo '{"source":"lterm","session":"codex","pane":"%3","cwd":"'$PWD'"}' \
| COLORTERM=truecolor ./target/release/understatus render --source lterm --oneline | cat -v
# lterm
cd /Users/jinhongan/Desktop/light_terminal
export PATH="$HOME/.cargo/bin:$PATH"
git log --oneline -5 # main: 라우팅 배선 #122(fbeade0) + Merge #121(status-row + 라우팅 PoC)
cargo test --bin lterm # 377 통과. cli_smoke는 cmux env 경합 flaky → --test-threads=1
# CI는 stable 1.96: 로컬은 `rustup toolchain install 1.96.0` 후 `cargo +1.96.0 clippy --all-targets -- -D warnings`로 일치 검증
# 라이브 E2E: LTERM_STATUS_COMMAND="<understatus 절대경로> render --source lterm --oneline" lterm codex
# 입력칸 fix 시각검증: ~/.local/bin/lterm(=target/release 심볼릭) 새 attach로 codex 띄우고 cmux 창 전환→복귀
```