# HANDOFF — understatus (+ lterm statusline 통합)
> 다음 세션/에이전트용 핸드오프. 제품은 원래 **statusticon** 코드네임이었다가 출시 시 **understatus**로 개명. 온디스크 디렉터리는 여전히 `statusticon/`이지만 제품/크레이트/레포/바이너리는 전부 **understatus**.
>
> **최신 세션 = §0·NOW (2026-06-13): walk-up 블로커 해소 — lterm 조사로 verdict 확정 = cwd-only(walk-up No-go). ← 여기부터 읽기.** 그 전(06-12, git pill 아이콘 SF Symbol 수정 PR #21 + 잔여 backlog Goal 3건 PR #22/#23/#24)은 §0·NOW-1, 06-11(v0.5.0/v0.6.0 릴리스 + 설치 하위호환 + ctx 튜닝 + node24)은 §0·PREV, 06-10(lterm 경로 git branch pill 구현·머지)은 §0(릴리스 상세 블록쿼트 포함), 06-09(cmux 네이티브 status pills 실렌더)는 §0A, 06-08(ctx 소멸 fix + 라우팅 인프라)은 §0B, 06-07은 §0C, 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·NOW. 최신 세션 (2026-06-13) — walk-up 블로커 해소 + P1 FP-free walk-up 구현 (PR #25) ← **여기부터 읽기**
> **Goal**: 06-12 세션이 남긴 유일한 블로킹 backlog(walk-up branch 도출)의 선결 블로커 — "lterm은 `git_worktree`를 무엇으로 도출하며 셸 `cd`를 추적하는가?" — 를 lterm 레포 조사로 해소하고, 그에 따른 올바른 트랙(P1 walk-up)을 **구현**한다.
>
> **현재 상태: 블로커 해소 + P1 FP-free walk-up 구현 + quad-review-loop 2라운드 수렴 + PR #25 MERGED(rebase). main `d666aec`** — walk-up 4커밋 rebase 반영(`dc00c69` W-B 가드 → `f79883f` walk-up feat → `3f1e472` R1 fix(to_string_lossy &Path화+테스트) → `d666aec` R2 하드닝(depth 경계+symlink 외부repo 계약)). **머지 후 main 게이트 그린(341 lib + 15 oneline = 356, 0 failed), 버전 0.6.0 불변(미릴리스 — 출하 시 v0.7.0).** 블로커 답 = lterm은 cd 미추적·git 미인지 → **W-B 기각**. 정정: 원래 문제는 **P1(repo 하위 dir 시작)**이고 정답은 **understatus FP-free walk-up(W-A v2)** → **구현·검증·리뷰·머지 완료(always-on, depth 64)**.
### 결론 — 블로커 해소 + verdict 정정 (P1/P2 구분), confidence high
**블로커 답(adversarial 검증 완료):** lterm은 셸 `cd`를 추적하지 않으며 `git_worktree`를 전혀 도출하지 않는다.
- `Session.cwd`는 **비-Mutex 불변 String**(server.rs:274) — `create_session`(server.rs:1800-1807)에서 `-c`/데몬 current_dir로 **1회 캡처 후 영구 고정**. OSC 7/1337 파싱·`/proc`·`proc_pidinfo(PROC_PIDVNODEPATHINFO)` cwd 폴링·cwd 갱신 RPC **모두 production 전무**. `info()`는 매 tick `self.cwd.clone()`(server.rs:408)로 frozen 값 복제. lterm에 git 인지 0건.
- **W-B(payload에 git_worktree 추가) 기각(확정)**: frozen 시작-dir cwd와 동일 부정확성 공유 → FP를 빈 pill(관측 가능) 대신 외부 repo 틀린 branch(관측 불가)로 **displace**할 뿐. → `claude.rs` 주석 가드(PR #25).
- ⚠️ **synthesis verdict 정정 — 문제는 둘로 갈린다**:
- **P1(높은 빈도, 원래 명시된 문제) → ✅ 구현 완료(PR #25)**: codex가 **repo 하위 dir에서 시작** → `<cwd>/.git` 없음 → branch 미탐. cwd는 **시작 시점엔 정확**하므로 그 위 walk-up은 stale 문제 없이 repo 루트를 올바르게 도출 → **understatus FP-free 디렉터리 체인 walk-up(W-A v2) 구현**. synthesis가 "stale cwd"를 이유로 W-A를 기각한 건 P2 논거를 P1에 잘못 적용한 over-reject였음. W-A의 진짜 비용(FP-free 부모 체인 canonicalize 보안 가드)은 3대 불변식 + 적대검증으로 해소. understatus 단독·lterm 무변경.
- **P2(낮은 빈도, 미구현)**: 세션 중 codex/셸이 **cd로 이동** → frozen cwd stale → 틀린 branch. 해결 = lterm live cwd(W-B-conditional). codex는 자기 프로세스를 chdir 안 해 드묾. P1 walk-up과 합성 가능(lterm이 live cwd 주면 walk-up이 그 위에서 수혜).
- **W-B-conditional(P2) = 미래 옵션**: lterm이 `proc_pidinfo(PROC_PIDVNODEPATHINFO)` leader-PID live cwd 도출을 **먼저 구현**(cost=medium, lterm 측 별도 OS 종속 작업)해야 진입. M-2(절대경로 가드)는 PR #23으로 이미 충족.
### ✅ 이번 세션 산출물
1. **조사 워크플로(ultracode)**: lterm 4각도 병렬 조사(cwd 생애주기 / cd 추적 feasibility / payload 스키마+git 인지 / understatus 소비측) → 중심 주장 3렌즈 적대적 반증(escape-sequence=confirmed, data-flow=confirmed, proc-syscall=uncertain\*) → synthesis verdict. 8 에이전트, 전부 file:line 증거 기반.
- \*proc-syscall uncertain은 "lterm이 live cwd를 *줄 수 없다*"는 강한 추론만 반증 — 그건 lterm 측 medium 신규 작업이지 무변경 W-B를 구제하지 않음. cwd-only 우위 불변.
2. **`claude.rs` 주석 가드**(`parse_lterm_input`, behavior 0): "W-B 미채택" 근거를 코드에 박아 후속 기여자가 `RawLtermInput`에 `git_worktree`를 무심코 추가하는 회귀 차단. 기존 W-A 배제 경고(`claude.rs:442-453`)와 동일 패턴.
3. **계획 문서 종결**: `.omc/plans/open-questions.md` 블로커 `[x]` + M-2 `[x]`(PR #23 해결 확인) 기록(gitignored 로컬).
4. **M-2 종결 확인**: `derive_git_branch` ↔ `derive_git_branch_from_cwd` 절대성 가드 대칭, 회귀 테스트 `git_worktree_relative_path_rejected` 고정. 추가 작업 불필요.
5. **P1 walk-up 설계 합의(ultracode)**: 3 설계안(재사용/보안/엣지케이스 우선) → Architect+Critic 적대검토 → 합의 플랜. **Critic의 FP 공격(symlink cwd / linked-worktree gitfile / depth / TOCTOU) 전부 차단·임의 read 0·블로킹 0**. 핵심 footgun 적발: 정지 분기에 `lstat.is_dir()` 쓰면 심볼릭 `.git` 디렉터리(표준 git)가 회귀 → **무분기 reader 위임**으로 차단.
6. **P1 walk-up 구현(PR #25 커밋 `786271b`, feat)**: `derive_git_branch_from_cwd` cwd-only → walk-up. 신규 `find_git_root_dir`/`find_git_root_dir_capped` + `MAX_WALK_UP_DEPTH=64`. **3대 불변식**: ①canonicalize 1회(루프 前) ②probe-then-read 무분기(첫 `.git` 정지) ③depth cap. `read_branch_from_git_dir` 등 무수정 재사용, `derive_git_branch`(Claude 경로) 무변경, Task3 gitfile FN 보존. always-on(의미변화=git-consistent 정탐, 문서화). 주석 5곳 개정("부모 상승 금지"→"3 불변식 유지").
7. **구현 리뷰(독립, author/review 분리)**: correctness/security/test-adequacy 3관점 → verdict **ship**. test-adequacy가 잡은 medium(symlink 테스트 vacuous) 반영 → 테스트를 mutation-저항형으로 재작성(lexical 부모에 함정 repo). **canonicalize 임시 제거 mutation으로 `Some("leaked")` 실패 실증 후 복원** → 불변식① 실제 고정 증명. 신규 8 유닛 + 1 e2e, 기존 회귀 11종 무수정 통과.
### ⏭ Next Steps
> **P1 walk-up = 구현·리뷰·머지 완료(PR #25 MERGED, main `d666aec`).** understatus 이 레포 backlog 사실상 소진.
1. ~~PR #25 머지~~ ✅ **완료**(rebase-merge). **(선택) v0.7.0 릴리스**: walk-up은 사용자-대면 feature(repo 하위 dir에서 git branch 표시)라 출하하려면 minor bump 권장 — §C 절차(3종 버전 범프→태그→release.yml→crates.io→Homebrew prebuilt→npm passkey). 미릴리스 시 main에만 존재.
2. **[선택·부 트랙] P2 = lterm live-cwd(W-B-conditional)**: 세션 중 cd 추적. `Session::info()`(server.rs:408)에서 `self.process_id`로 `proc_pidinfo(PROC_PIDVNODEPATHINFO)` 호출해 cwd live화(payload 스키마 변경 0). codex는 chdir 안 해 빈도 낮음 — value 먼저 ralplan 권장. **lterm이 live cwd를 주면 understatus walk-up이 그 위에서 자동 수혜**(P1+P2 합성).
3. **lterm 최대 가치(불변)**: iTerm OSC1337 백엔드(NativeChrome) 실렌더(대, 미구현). 그 외 TOML `[status]` config, 다중 에이전트 세그먼트, lterm 잔여 LOW(§0·PREV 이하).
---
## §0·NOW-1. 직전 세션 (2026-06-12) — git pill 아이콘 수정 + 잔여 backlog Goal 완주
> **Goal**: git pill 아이콘 글리프 미표시 수정 후, understatus 잔여 backlog를 `/goal`로 연속 처리(각 Task: **ralplan 합의 → executor 구현 → quad-review-loop → rebase-merge**). 4개 PR 전부 머지.
>
> **현재 상태: 전부 완료·머지, 열린 PR 0, main `558aafb`(+이후 HANDOFF 갱신), test 342(328 lib + 14 oneline) 그린, 버전 0.6.0 불변(내부 hardening·테스트라 범프 불요).** understatus 이 레포 내 "지금 가능한" backlog는 **사실상 소진** — 남은 건 walk-up 하나뿐이고 그건 lterm 조사 선결로 블로킹.
### ✅ Current Progress (이번 세션 머지분, 시간순)
1. **git pill 아이콘 SF Symbol 수정** (PR #21 `fix(render)`, 머지 `7511a74`): 06-10에 추가된 git pill의 `icon: Some("git-branch")`가 cmux 사이드바에 **글리프 없이 주황 텍스트만** 뜨던 문제. **근본 원인 = cmux `--icon`은 SF Symbol 이름을 직접 렌더**한다(cmux 바이너리 `/Applications/cmux.app/Contents/Resources/bin/cmux` 내 `toolIcon` 함수 주석 `// SF Symbol names rendered inside the cmux status badge`, 매핑값 eye/pencil/terminal/sparkles/globe/checklist 전부 SF Symbol — `strings` 추출로 확정). `git-branch`(Lucide/nerd-font명)는 SF Symbol이 아니라 drop된 것. → **`arrow.triangle.branch`**(git 브랜치 표준 SF Symbol)로 교체. `render.rs:337` + 테스트 단언 + 주석. **라이브 cmux 사이드바 글리프 육안 확인**(사용자). model pill의 `sparkles`(✨)가 known-good 대조군.
2. **Task 1 — git-branch pill 견고화** (PR #22, 머지 `d90d031`/`70684ab`/`42a9cb1`/`13dac4c`): quad-review 잔여 LOW 묶음 + 리뷰 LOW.
- **branch byte cap** `MAX_BRANCH_LEN=256`(claude.rs `read_branch_from_git_dir` chokepoint, byte `.len()`): 256B 초과=손상/조작 `.git/HEAD` 신호 → None(FP<FN). NAME_MAX=255라 정상 branch는 초과 불가.
- **테스트 RAII guard**: `unique_test_dir`를 `TestDir`(`Drop`=remove_dir_all + `Deref<Path>` + `AsRef<Path>`) 반환형으로 승격 → panic 시 temp 누수 0. 구식 PID-only 3곳(collision 위험) 통일. `catch_unwind` panic-safe 증명 테스트.
- **교차-pill SF Symbol 계약 테스트** `cmux_pill_icons_contain_no_hyphen`: 모든 pill icon에 하이픈 부재(SF Symbol은 점·소문자, 하이픈=Lucide=cmux drop) → `git-branch` 회귀 영구 차단. + vacuous-pass 가드(pill 비어있음·icon 전부 None 차단).
- symlink `.git` 추종 의도 테스트 + 동기 fs read 트레이드오프 doc(비파괴).
3. **Task 2 — M-2 절대경로 가드 대칭화** (PR #23, 머지 `c9241fc`): `derive_git_branch`(Claude workspace `git_worktree`/`repo` 경로)에 `is_absolute()` 가드가 **없어** 상대경로(`"repo"`/`"."`)가 프로세스 cwd 기준 해석돼 엉뚱한 repo branch FP였음(canonicalize cwd-상대). `derive_git_branch_from_cwd`(lterm cwd)는 이미 가드 보유 → **대칭화**. **ralplan: Planner=B(공유 헬퍼에 흡수) vs Architect/Critic=A(개별 추가)** — B는 `is_safe_base_path` 공개 계약(doc "절대 허용") 반전 + SRP 위반이라 A 채택, 공유 헬퍼 불변. host-독립 단위 테스트(`derive_git_branch` 직접 호출).
4. **Task 3 — linked worktree gitfile = No-go 확정 + FN 회귀 가드** (PR #24, 머지 `1527275`/`558aafb`): linked worktree·서브모듈은 `<base>/.git`가 `gitdir:` **정규 파일**(현재 `<base>/.git/HEAD` ENOTDIR → None = 안전 FN). **ralplan 합의 = No-go**(구현 안 함). **근거 = feasibility**(value 미측정 아님): Architect가 `git worktree add` **실증** → 표준 worktree·서브모듈의 실제 HEAD는 **항상 `<base>` 밖**(main repo 하위) → 보수적 추종(C: `<base>` 경계)은 **0% 커버** = value 0 + 새 공격면 = 순손실; 전체 추종(A)은 임의 위치 파일 read primitive 개방. **산출물 = 프로덕션 로직 0**, 현 안전 FN을 **mutation-resistant 회귀 테스트**로 고정(gitdir 타깃 실재화 + sentinel HEAD → 추종 구현 시 `Some(sentinel)`로 None 단언이 깨져 회귀 포착) + doc 강화(ENOTDIR·서브모듈 명시).
### ✅ What Worked
- **`/goal` × (ralplan → executor → quad-review-loop → 머지) 사이클** 4회 반복 — 안정적. 각 Task가 독립 PR·CI 그린·atomic 커밋.
- **멀티에이전트가 실재 결함을 잡음**: Task1 Critic이 약한 단언(C1)·site 오기(C2) 적발; Task2 Architect/Critic이 Planner의 B를 "공개 계약 반전 비용"으로 뒤집고 A 확정; Task3 Architect가 `git worktree` **실증**으로 (C) 0% 커버 증명; **Task3 quad-review-loop가 round 1에서 3트랙 합의 blocker**(테스트 mutation 저항 없음 — gitdir 타깃 비존재) 적발 → round 2 sentinel 실재화로 해소·수렴.
- **cmux 아이콘 어휘를 코드로 확정**: 라이브 시행착오 프로빙 대신 cmux 바이너리 `strings`에서 `toolIcon`(SF Symbol 매핑) 발견 → 단일 후보로 수렴. 블랙박스를 코드 증거로 깸.
- **매 executor 산출물을 rustup 게이트로 독립 재검증**(author/review 분리). IDE phantom 진단(`fs.rs` E0277 등)을 `cargo test` 통과로 반증.
### ⚠️ What Didn't Work / 주의 (반복 회피)
- **executor가 커밋을 누락한 사례**(Task3 blocker fix): 보고가 cut off되며 working tree만 수정하고 커밋 안 함 → 오케스트레이터가 직접 커밋. **executor 자기보고 비신뢰 — 매 단계 `git log`/게이트로 실제 상태 확인.**
- **agy(Antigravity)는 review 프롬프트에서 4라운드 연속 hang**(타임아웃 래퍼 없이 띄우면 프로세스 방치 → pkill 필요). 핸드오프 known issue. **Forge는 라운드별 가변**(PR#21 token-mismatch 폐기, PR#23/#24 정상). → Claude+Codex 안정 듀얼 + Forge 보조로 합의.
- **quad-review-loop blocker 기준** = severity HIGH+ AND consensus(≥2 트랙). Task3에서 Codex HIGH + Forge Major + Claude MEDIUM = 합의 blocker로 정확히 정지·수정.
- IDE/rust-analyzer phantom: `TestDir`의 `Deref`-not-`AsRef`에 막혀 `fs.rs` create_dir_all/remove_dir_all 가짜 진단 → rustup clippy 클린으로 반증(메모리 `rust-toolchain-broken`).
### ⏭ Next Steps — 남은 로드맵 (understatus 이 레포)
> **이 레포 "지금 가능한" backlog는 소진.** 아래 1개만 남았고 블로킹.
1. ~~**walk-up branch 도출**(중, 블로킹)~~ ✅ **§0·NOW(06-13)에서 해소**: lterm 조사로 블로커 답 확정(lterm은 cd 미추적·git_worktree 미도출) → verdict = **cwd-only(walk-up No-go)**. W-B/W-A 모두 기각, W-B-conditional은 lterm 측 live cwd 구현 선결. 상세는 §0·NOW.
2. ~~git pill 아이콘~~ ✅ PR#21. ~~M-2 가드~~ ✅ PR#23. ~~linked worktree gitfile~~ ✅ PR#24(No-go+가드). ~~quad-review 잔여 LOW·하이픈 가드~~ ✅ PR#22.
**lterm (`/Users/jinhongan/Desktop/light_terminal`, 별도 레포 · Phase 2 — spec §15):** 변동 없음. 최대 가치 = **iTerm OSC1337 백엔드(NativeChrome) 실렌더**(대, 미구현). 그 외 TOML `[status]` config, 다중 에이전트 세그먼트, lterm 잔여 LOW. 상세는 §0·PREV 이하 참조.
---
## §0·PREV. 직전 세션 (2026-06-11) — 릴리스 + 설치 하위호환 + ctx 튜닝 + node24
> **Goal**: understatus(+lterm) statusline 제품을 출하·유지보수. 이번 세션은 누적분 릴리스 + 설치 진입장벽 제거 + ctx 정확도 튜닝.
>
> **현재 상태: 전부 완료·라이브, 블로킹 0, 열린 PR 0, main `d499ad8` + 이후 HANDOFF 갱신.** understatus **v0.6.0가 4채널(crates.io·GitHub Release·Homebrew·npm) 전부 라이브**.
### ✅ Current Progress (이번 세션 처리분, 전부 머지·배포)
1. **v0.5.0 릴리스**(4채널) — 06-10 git pill + cmux pills 누적분. PR #15/#16, 태그 v0.5.0(`29ca989`). 상세는 아래 §0 블록쿼트.
2. **GHA Node20 deprecation 대응**(PR #17 `2587ce7`): `actions/checkout@v4→v6`, `softprops/action-gh-release@v2→v3`(둘 다 node24). `dtolnay/rust-toolchain`은 composite라 무변경. ci.yml이 PR CI에서 checkout@v6 실검증.
3. **설치 CLT 26.3 요구 제거 = Homebrew formula prebuilt 전환**(PR #18 `f912aea` + tap `c839a47`→`99b2fb6`): `depends_on "rust"`+`cargo install`(소스 컴파일) → `on_arm`/`on_intel` url+sha256+`bin.install`(다운로드만). **컴파일 없어 CLT 불필요**(공식문서 확인). 배포 바이너리 `minos 11.0`→macOS 11+ 실행. `brew install` 2초·컴파일0 실측. `cargo install`만 본질상 소스라 CLT 필요(README가 brew/npm을 CLT-free로 안내).
4. **ctx 튜닝 = hold 상수 2개 `[context]` config 노출**(PR #19 feat `10d8ecc`+bump `ce298e0`): `hold_ttl_seconds`(기본 **600→180**, 반응성↑/stale↓, 0=비활성) + `drop_tolerance`(기본 **12.0 불변**, 12 미만은 86↔98 깜빡임 위험). 배선 `resolve_claude_context(&cfg.context)`→`read_held_native_ctx(ttl)`/`resolve_context_percent(drop_tolerance)`, 기본값 `DEFAULT_CONTEXT_*` pub 상수 단일출처. config.rs/claude.rs/main.rs, 동작은 TTL 외 동일. executor(opus) 구현, rustup 실측 **321+14=335 테스트** 그린.
5. **v0.6.0 릴리스**(4채널) — 태그 v0.6.0(`ce298e0`). crates.io v0.6.0 · GitHub Release(arm64 `c9116944…`/x64 `febcd0f1…`) · Homebrew prebuilt v0.6.0(`99b2fb6`, 사본 PR #20 `d499ad8`) · npm `understatus@0.6.0`(latest, 레지스트리 클린설치 E2E 통과). **릴리스 절차는 §C(prebuilt 방식으로 갱신됨) 참조.**
### ✅ What Worked
- **릴리스 스킬 + §C 절차 + PR rebase-merge 파이프라인** 반복 — 안정적. 각 단계 **E2E 실측**(brew install "2초", npm registry 클린설치, otool `minos 11.0`, cargo dry-run)으로 자기보고 대신 증거 확보.
- **prebuilt formula 전환**이 CLT 요구를 근본 제거(소스 컴파일 제거) — document-specialist로 Homebrew 공식문서 사실관계 확인 후 적용.
- **executor(opus)에 정밀 스펙 위임 → rustup 실측 4게이트로 독립 검증**(author/review 분리). IDE phantom 진단을 cargo test 통과로 반증.
### ⚠️ What Didn't Work / 주의 (반복 회피)
- **gh GraphQL 세션 중 간헐 401 / connection reset** → **재시도 루프**로 우회(`gh pr create/merge`, `gh pr checks --watch`도 영향). REST `gh run view` 폴링이 더 안정적. **git push는 osxkeychain이라 무영향.** 만성화 시 `gh auth refresh -h github.com`(브라우저=사용자).
- **IDE/rust-analyzer 인자불일치(E0107/E0061) phantom 진단** — 깨진 Homebrew 툴체인 탓. **오직 rustup `cargo test/clippy`만 신뢰**(메모리 `rust-toolchain-broken`).
- **`cargo install`(crates.io)은 본질상 소스 컴파일** → CLT 계속 필요. brew/npm만 CLT-free.
- **npm publish는 항상 사용자 passkey(EOTP)** — 에이전트 불가. 매 릴리스 마지막 수동 단계.
- **`brew style` advisory**: 과거 desc 82자(>80) — prebuilt 재작성 때 71자로 트림해 해소. `depends_on`은 `on_macos`보다 앞.
### ⏭ Next Steps — 남은 로드맵 (전부 **선택**, 블로킹 0)
> understatus 열린 이슈 0, v0.6.0 라이브. lterm도 현재(v1.0.23). 아래는 "있으면 좋은" 폴리시·확장.
**understatus (이 레포):**
1. **git pill 아이콘**(소): cmux 지원 아이콘명 조사 → git pill 아이콘 부착(현재 주황 텍스트만, cmux가 `git-branch` 미지원해 drop). model의 `sparkles`(✨)는 지원됨.
2. **v2 false-positive-free walk-up**(중): codex가 repo 하위 dir 시작 시 branch 도출(현재 cwd-only). 안전한 walk-up(`base_path` 디렉터리 canonicalize로 repo 경계 확인) 또는 lterm payload `git_worktree` 추가. — §0 이월 #3 참조.
3. **quad-review 잔여 LOW**(소, 비차단): (a) branch명 길이 cap (b) symlinked `<cwd>/.git`→other-repo HEAD 누출 의도 테스트/문서화 (c) 동기 fs read 지연(느린 마운트) (d) 테스트 dir RAII cleanup. — §0 이월 #4.
4. **linked worktree gitfile**(소): `.git`이 파일(워크트리)인 경우 지원(현재 표준 워크트리만).
5. ~~cost pill~~ — **구조적 불가**(codex rollout JSONL에 cost 필드 없음). 로드맵 제외 확정.
**lterm (`/Users/jinhongan/Desktop/light_terminal`, Phase 2 — spec §15):**
6. **iTerm OSC1337 백엔드(NativeChrome)**(대): cmux 없는 iTerm 사용자용 status. 라우팅 PoC 머지됨, 실렌더 미구현. base64 인코딩 필수(`protocol.rs:309` pub 승격), `detect_is_iterm` 이미 존재. `.poc/poc2-iterm-status.sh`가 검증법. **남은 것 중 최대 기능 가치.**
7. **TOML `[status]` config + `lterm attach --status-command` CLI 플래그**(중): 현재 env-only. lterm에 config 로더·`toml` 의존 신설 필요.
8. **다중 에이전트 세그먼트**(중): Gemini/OpenCode 등 전용 표시.
9. **lterm 잔여 LOW**(소): `build_status_payload`가 daemon `info.agent_name` 우선 사용, reader 스레드 group-kill(`kill(-pgid)`, libc 의존), status row 테마 bg 옵션화 등. — §B-6.
---
## §0. 직전 세션 (2026-06-10) — lterm 경로 git branch pill (구현·검증·라이브·quad-review-loop·**머지 완료**) + v0.5.0/v0.6.0 릴리스 상세
> 이번 세션: cmux pills 후속 트랙(§0A 이월 #3(b) "cost·git payload 확장")을 ralplan 합의로 **스코프 재정의**해 구현 → 라이브 검증 → **quad-review-loop**로 실재 보안 blocker 1건 수정 → **PR #14 머지**. lterm 경로(`--source lterm --surface-format cmux-status`)의 cmux 사이드바에 **git branch pill 추가**. **understatus 단독 변경**(lterm 무변경).
>
> **현재 상태: PR #14 MERGED(main `4baf1c5` feat + `21f83e8` fix, rebase), 열린 PR 0, CI 그린, 라이브 cmux 검증 통과, feature 브랜치 정리됨.**
>
> **✅ 릴리스 완료 (2026-06-11): understatus v0.5.0 4채널 전부 라이브.** PR #15(버전 범프, rebase-merge `29ca989`) + PR #16(homebrew 사본 동기화 `1569466`). 태그 v0.5.0(`29ca989`). 채널: **crates.io v0.5.0** · **GitHub Release v0.5.0**(arm64+x64 tar.gz+sha256) · **Homebrew tap `ictechgy/homebrew-understatus`**(commit `ffc292a`, 소스 아카이브 sha256 `4fe6384c…`, `brew info`가 stable 0.5.0 인식) · **npm `understatus@0.5.0`**(latest 태그, 사용자가 passkey로 publish; 레지스트리 클린설치 E2E 통과 — install.js가 v0.5.0 바이너리 SHA-256 검증·수신·`understatus 0.5.0` 실행 확인). 4게이트 그린(318+14=332 테스트). gh GraphQL이 세션 중 간헐 401(토큰 flaky) → 재시도로 통과, git push는 osxkeychain으로 무영향.
>
> **✅ 후속 세션 (2026-06-11, 같은 날): v0.6.0 릴리스 + 설치 하위호환 + Node24 액션 + ctx 튜닝.** 4건:
> 1. **GHA Node20 deprecation 대응**(PR #17, `2587ce7`): `actions/checkout@v4→v6`, `softprops/action-gh-release@v2→v3`(둘 다 node24). `dtolnay/rust-toolchain`은 composite라 무변경. ci.yml이 PR에서 checkout@v6 실검증.
> 2. **설치 CLT 26.3 요구 제거 = Homebrew formula를 prebuilt 바이너리로 전환**(PR #18 `f912aea` + tap `c839a47`→이후 `99b2fb6`): `depends_on "rust"`+`cargo install`(소스 컴파일) → `on_arm`/`on_intel` url+sha256+`bin.install`(다운로드만). **컴파일 없어 CLT 불필요**(공식 문서 확인). 배포 바이너리는 `minos 11.0`이라 macOS 11+ 실행(otool). `brew install` 2초·컴파일0 실측. **`cargo install`만 본질상 소스 컴파일이라 CLT 필요**(README에 명시, brew/npm을 CLT-free 경로로 안내). README Install 섹션 갱신.
> 3. **ctx 튜닝 = hold 상수 2개를 `[context]` config로 노출**(PR #19 feat `10d8ecc`+bump `ce298e0`): `hold_ttl_seconds`(기본 **600→180**, 반응성↑/stale↓, native 누락 시 직전값 유지 시간, 0=비활성) + `drop_tolerance`(기본 **12.0 불변**, hold 해제 하강 임계치 %p, 12 미만은 86↔98 깜빡임 위험). 배선: `resolve_claude_context(&cfg.context)`→`read_held_native_ctx(ttl)`/`resolve_context_percent(drop_tolerance)`, 기본값 `DEFAULT_CONTEXT_*` pub 상수 단일출처. config.rs/claude.rs/main.rs, **동작은 TTL 기본 600→180 외 동일**. executor(opus) 구현, rustup 실측 4게이트 그린(**321+14=335 테스트**). ⚠️ IDE가 표시한 인자불일치(claude.rs/main.rs)는 **깨진 Homebrew 툴체인의 phantom** — rustup `cargo test` 통과로 반증(메모리 `rust-toolchain-broken` 재확인).
> 4. **v0.6.0 4채널 릴리스 — 전부 라이브 ✅**: 태그 v0.6.0(`ce298e0`). **crates.io v0.6.0** · **GitHub Release v0.6.0**(arm64 sha256 `c9116944…`, x64 `febcd0f1…`) · **Homebrew tap prebuilt v0.6.0**(`99b2fb6`, repo 사본 PR #20 `d499ad8`, `brew info`=stable 0.6.0, 2초 설치 실측) · **npm `understatus@0.6.0`**(latest 태그, 사용자가 passkey로 publish; 레지스트리 클린설치 E2E 통과 — v0.6.0 바이너리 SHA-256 수신·`understatus 0.6.0` 실행 확인).
### quad-review-loop 결과 (2라운드 수렴)
- **R1 blocker(2/3 합의, 수정됨)**: `read_branch_from_git_dir`이 신뢰 불가 `.git/HEAD` 내용(악성 repo의 `ref: refs/heads/main␛[31m…`)을 검증 없이 반환 → oneline SGR/cmux pill 터미널 인젝션. **`char::is_control` 거부**로 source chokepoint에서 차단(lterm+Claude 경로 동시). 동반: 상대경로 cwd 거부(절대경로 요구), 고정경로 테스트 hermetic화. commit `21f83e8`.
- **R2 수렴**: Codex APPROVE. Claude 유일 HIGH(pill value 셸 메타문자 인젝션)는 **lterm sink가 `cmd.arg(value)` 셸 미경유(tmux_compat.rs)임을 코드로 확인 → false-positive 확정**(기존 model/cpu/mem pill과 동일 sink, 이 PR 도입 아님). consensus blocker 0.
- **교훈**: ralplan은 path traversal만 봤고 **content 살균(제어문자)을 놓침** → quad-review가 실재 보안 갭을 메움. 반대로 단일트랙 HIGH는 교차레포 코드 검증으로 false-positive를 걸러 불필요 수정 회피. Forge는 R2에서 reasoning-only 출력으로 폐기(flaky), Antigravity는 21~28KB 프롬프트 hang으로 양 라운드 SKIP → 사실상 Claude+Codex 듀얼.
### 핵심 발견 / 결정 (다음 세션이 알아야 할 것)
- **cost 영구 제외(데이터 소스 부재)**: codex rollout JSONL에 **cost 필드 자체가 없음**(understatus `codex.rs` CodexExtras/TokenSnapshot은 rate-limit %·plan·effort만). lterm은 PTY 래퍼라 자식(codex) 내부 cost 미접근. → "cost·git payload 확장"의 **cost는 구조적 불가**. git만 진행.
- **git은 understatus 단독으로 실현(lterm payload 확장 불필요)**: lterm이 이미 보내는 `cwd`로 understatus가 직접 `.git/HEAD`를 읽으면 됨. lterm `SessionInfo.cwd`는 세션 시작 dir(셸 cd 추적 안 됨)이나 codex는 보통 repo 루트 고정이라 실용상 OK(수용 한계).
- **cwd-only 채택, 부모 walk-up 기각(Architect 적발)**: walk-up은 `read_branch_from_git_dir`의 canonicalize가 `<base>/.git/HEAD` **파일만** 보호하고 디렉터리 체인은 검증 못 해, 심볼릭 cwd에서 **타 repo branch를 확신 표시하는 false-positive(오정보)** 위험. status 표면에선 빈 pill(false-negative) ≪ 틀린 pill. → cwd-only(`<cwd>/.git/HEAD` 1회)만, 정탐률 보완은 v2 이월.
- **Q4 코드 확정**: lterm `is_valid_pill_key("git")`==true(`tmux_compat.rs:1673` ref-segment `[A-Za-z0-9_-]` + `:3999` len≤64). lterm sink가 "git" 키를 제네릭 set-status → **lterm 변경 불필요 전제 성립**.
- **cmux 네이티브 branch 표시 발견(라이브)**: cmux가 워크스페이스마다 `branch • cwd` 줄을 **자체 표시**(우리 pill엔 cwd 없음). 단 **다른 세션에선 누락되기도 함**(불안정) → 우리 pill이 일관된 폴백으로 별개 가치. 사용자가 유지 결정.
- **git-branch 아이콘 drop(R4 예측대로)**: cmux가 `git-branch` 아이콘명 미지원 → 아이콘 누락(주황 텍스트는 정상 렌더). model의 `sparkles`(✨)는 지원. 아이콘 띄우려면 cmux 지원 아이콘명 조사 필요(폴리시 follow-up).
### ✅ 완료 (feature 브랜치, PR #14)
- **claude.rs**: `derive_git_branch_from_cwd(cwd: &str) -> Option<String>` 신규(cwd-only, `is_safe_base_path`+`read_branch_from_git_dir` 재사용, **부모 walk-up 없음** — doc에 v2 이월 명시). `parse_lterm_input`이 `cwd.as_deref().and_then(derive_git_branch_from_cwd)`로 도출(기존 영구 None 제거). 거짓 "항상 None" 주석 정정.
- **render.rs**: git 세그먼트 pill화(`key=git`, `value=branch`, `color=#F1502F` `pill_git_color()`, `icon=git-branch`, `priority=40`). `label_value_segment` 시그니처 불변 → oneline 바이트 보존.
- **회귀 0**: 기존 4 pill 키(model/ctx/cpu/mem) 불변, oneline 불변, Claude 경로 무영향, version bump 없음, 신규 의존성 없음.
- **검증**: 4게이트 그린(fmt/clippy -D warnings/test/release --locked). **lib 316 + oneline 14 통과**. AC1-AC9 테스트 실증, Guardrail 위반 0(독립 verifier 재실행). 보안: traversal/외부향 심볼릭 HEAD/detached/.git 부재 → 전부 None(패닉 0).
- **라이브 cmux 검증 통과**: 사이드바 `더 보기` 펼치면 `feature/lterm-git-branch-pill` git pill 주황(#F1502F) 렌더 확인(사용자 육안). 아이콘만 drop(무해).
### 워크플로 / 교훈
- brainstorming 없이 바로 ralplan(후속 트랙 택1) → explore×2(양 레포 payload 파이프라인) → ralplan 합의(Planner→Architect→Critic **3라운드**, APPROVE) → executor(opus) 구현 → verifier(sonnet) **독립 게이트 재실행** → 라이브 육안.
- **멀티에이전트가 단일 리뷰 사각을 메움**: ① Architect가 walk-up의 보안 false-positive(심볼릭 cwd→타 repo) 적발 → Option 1로 전환. ② Critic 라운드2가 `sample_input`(render.rs:799 `git_branch:Some("main")`) 기반 **render.rs 테스트 3개 깨짐** + claude.rs lterm 테스트 4개 **거짓 계약화**(주석 "항상 None"이 T2 후 거짓) 적발 → T4-a/T4-e로 처리. Planner 단독으론 전부 누락.
- **"cost·git payload 확장" 프레이밍이 코드와 불일치**: explore가 cost 데이터 소스 부재 + git은 lterm 변경 불필요를 밝혀 스코프를 git-only·understatus-only로 재정의. **HANDOFF 이월 항목도 코드로 재검증 필요**.
### ⏭ 다음 세션 이월
1. ~~**understatus 릴리스**~~ ✅ **완료(2026-06-11, v0.5.0)** — crates.io·GitHub Release·Homebrew tap·npm 4채널 전부 라이브. 상세는 위 §0 "릴리스 완료" 줄.
2. **git-branch 아이콘 폴리시**(선택): cmux 지원 아이콘명 조사해 git pill에 아이콘 부착(현재 주황 텍스트만 — cmux가 `git-branch` 미지원해 drop, R4).
3. **v2 false-positive-free walk-up**(선택): `base_path` 디렉터리를 canonicalize해 repo 경계 확인하는 안전한 walk-up → codex가 repo 하위 dir 시작 시도 branch 도출. 또는 lterm payload에 `git_worktree` 추가.
4. **quad-review 잔여 MEDIUM/LOW**(비차단, 추적): (a) branch명 길이 cap(source defense-in-depth — 단 lterm `cap_field`가 다운스트림 절단). (b) symlinked `<cwd>/.git`→other-repo HEAD 누출(`.git` 심볼릭 추종은 표준 git 동작이라 과수정 위험 — 문서화/의도 테스트 권장). (c) 동기 fs read 지연(느린 마운트 cwd). (d) `unique_test_dir` 교차-run cleanup(RAII).
5. **linked worktree gitfile**(`.git`이 파일) 지원(현재 표준 워크트리만).
6. 설계/계획 문서: `.omc/plans/lterm-git-branch-pill.md`(ralplan 합의 확정본, ADR 포함 — **단 `.omc`는 gitignored 로컬**). quad-review-loop 레저: `~/.claude/logs/quad-review-loop/ictechgy-understatus-14-*.md`.
### 검증 수치
- understatus main(머지 후): clippy `-D warnings` 클린, **318(lib) + 14(oneline) = 332 테스트** 통과, release `--locked` 빌드 클린, CI 그린. (구현 시점 316 → quad-review 보안수정으로 신규 테스트 +2 = 318.)
---
## §0A. 직전 세션 (2026-06-09) — cmux 네이티브 status pills 실렌더 (완료/머지)
> 이번 세션: lterm-in-cmux의 codex status를 **DECSTBM 인라인 행 대신 cmux 네이티브 사이드바 pill(`set-status`)**로 렌더하는 실렌더 트랙. §0A(06-08)의 "다음 세션 이월 = lterm 실렌더 트랙"을 완수. understatus **PR #13** + lterm **PR #123** 둘 다 머지.
>
> **현재 상태: 열린 PR 0, 양 레포 main 머지·CI 그린, 라이브 cmux 검증 통과.** 양쪽 **미릴리스**(understatus v0.4.0 / lterm v1.0.22 이후 누적 — 릴리스하려면 §C 절차).
### 핵심 발견 (다음 세션이 알아야 할 것)
- **cmux 네이티브 status API 존재**: `cmux set-status <key> <value> [--icon][--color #hex][--priority]` → 좌측 사이드바 워크스페이스 항목에 pill 렌더. `clear-status`/`list-status` 동작. HANDOFF가 몰랐던 경로(과거 "write 핸들 없음"으로 오판). **`cmux send`는 키보드 입력 주입이지 화면 페인트 아님** → split 렌더러 대신 set-status 채택.
- **`set-progress`는 워크스페이스 전역**(pane-keyed 아님) + `list-progress` 부재 → SIGKILL 시 stale progress 청소 불가(누수). **진행바 채택했다가 quad-review에서 제거, ctx는 pill만.**
- **워크스페이스 식별 함정**: `$CMUX_WORKSPACE_ID` env는 lterm 세션에서 stale(죽은 ws). runtime `cmux identify` focused는 포커스 드리프트 → **attach 시점 `cmux identify --id-format uuids`로 UUID 캡처**(stored split-time 컨텍스트 우선, `tmux_compat::cmux_status_identity`).
- **codex는 RowOff**(`show_status:false`, attach 경로 `likely_agent_session→RowOff` `main.rs:2258`)라 `requests_row()==false`. cmux pill은 off-grid라 **`sink_enabled`를 `requests_row()`에 묶으면 1차 표적 codex에서 영구 OFF**(Architect R3 BLOCKER). 정답: `sink_enabled = matches(Cmux) && LTERM_STATUS_COMMAND set && !--no-status`; `in_grid = !sink_enabled && backend!=Disabled && requests_row()`(pill 미사용 cmux 셸은 기존 DECSTBM 보존, 회귀 0).
### ✅ 완료 (양쪽 main 머지)
- **understatus #13**(rebase): `--surface-format cmux-status` 출력 모드 — oneline과 동일 `collect_segments` 재사용해 `model·ctx·cpu·mem` pill JSON 방출. `Segment`에 additive `pill: Option<PillMeta>`(oneline 바이트 불변). 색 신규 매핑(cpu만 `band_tint` 재사용). ctx 0..=100 클램프+정수% 양자화. cost·git은 lterm 파서 영구 None(`claude.rs:288-289`)이라 제외. 핵심: `src/render.rs`(to_cmux_pills/PillMeta/color_to_hex), `src/main.rs`(SurfaceFormat/--surface-format). 설계/계획: `docs/superpowers/specs/2026-06-08-cmux-native-status-pills-design.md`, `.../plans/...-plan.md`.
- **lterm #123**(merge): `CmuxStatusSink`(`src/tmux_compat.rs` cmux_status 모듈) — pill JSON diff→`cmux set-status/clear-status` 변경분만. 라우팅 `in_grid`/`sink_enabled` 분리(`client.rs:3096`), 소비점 `client.rs:3421` 분기(StatusBar 미진입, in_grid 경로 바이트 불변), `cmux_status_identity`(UUID), 고아 재조정(attach 시 list-status, 실패 시 best-effort), Drop 청소, 서킷브레이커(3연속 실패→blackout), cmux 호출 **3s 타임아웃**(`run_cmux_command` `wait_with_timeout`), pill key 검증(`is_valid_pill_key`)+value/color/icon cap.
- **라이브 검증 통과**: 실제 `lterm codex`에서 사이드바 pill(cpu/mem/✨codex) 렌더 + **codex 입력칸 무손상**(DECSTBM 제거 = 본 트랙 수용기준) + detach 청소(사용자 육안 확인).
### 워크플로 / 교훈 (반복 회피)
- brainstorming → **cmux API 라이브 탐침**(set-status 발견) → ralplan 합의(Planner×2/Architect×3/Critic×2) → 청크 구현(executor) → **라이브 PTY 검증** → quad-review-loop.
- **Architect R2가 lterm 레포 안 읽고 "앵커 0 hit → UNSOUND" 오발** → 메인 에이전트가 직접 grep해 반증(앵커 전부 실재) 후 R3 재실행. **교차레포 리뷰 시 에이전트에 레포 절대경로 명시 + "신규 식별자는 작성 대상" 프레이밍 필수.**
- **quad-review-loop가 결정적 값**: Claude code-reviewer는 양쪽 APPROVE였으나 **Codex(gpt-5.5)가 lterm HIGH 3건**(① `run_cmux_command` 무한 대기→프리즈 ② pill key 미검증 ③ set-progress 전역 누수) 적발 → 전부 수정. **단일 리뷰 사각을 멀티모델이 메움.**
- **agy는 8KB+ 프롬프트 hang**(92KB diff라 SKIP), **forge는 `forge info`부터 flaky** → quad가 사실상 Claude+Codex 듀얼. 정상 폴백.
- ralplan/quad-review가 코드 사실 불일치를 잡음: "핵심 4 pill(cost·git)"이 codex 경로 구조적 None → model·ctx·cpu·mem로 재결정.
### ⏭ 다음 세션 이월 (전부 선택)
1. **understatus 릴리스**: v0.4.0 이후 cmux pills 누적분 미릴리스. §C 절차(3종 버전 범프→태그→`release.yml` 그린 대기→`cargo publish`→Homebrew tap→npm은 사용자 passkey).
2. **lterm 릴리스**: v1.0.22 이후 미릴리스.
3. **cmux pills 후속**: (a) cmux `rpc` 배치 set으로 `sink.apply` 동기 spawn을 비동기 worker로(현재 3s 타임아웃으로 프리즈만 차단, diff 게이트로 호출 드묾). (b) cost·git용 lterm payload 확장(현재 codex 경로 None). (c) NativeChrome(iTerm OSC1337)·DelegatedSurface(Tmux) 백엔드. (d) 동일 pane 동시 attach 시 짧은 pill 깜빡임(수용 한계, instance-id는 SIGKILL 재조정과 상충해 미도입).
### 검증 수치
- understatus main: clippy 클린, **310+13 테스트**, CI(ci) 그린.
- lterm main: **1.96** clippy 클린, unit **417** + cli_smoke 201, release `--locked`, CI 7체크 그린.
---
## §0B. 직전 세션 (2026-06-08) — 완료(배경)
> 이번 세션: ① understatus **ctx 소멸 버그 수정**(#9) + ② lterm **status 라우팅 인프라 배선**(#122) + ③ **진짜 ctx 소멸 원인 = `workspace.repo` 객체화 파싱 실패 수정**(#10) + ④ **understatus v0.4.0 4채널 배포 완료**. 직전 세션(06-07)은 §0C, 배경은 §A~E.
>
> **현재 상태: 열린 PR 0, understatus v0.4.0 라이브(crates.io·npm·Homebrew·GitHub Release), 화면 ctx 정상.** 다음 작업은 lterm 실렌더 트랙(아래 이월).
### ✅ 완료 (양쪽 main 머지됨)
1. **understatus ctx 소멸 버그 수정** — Claude Code statusline JSON의 `context_window.used_percentage`가 **간헐 누락**되면 understatus가 ctx 세그먼트를 생략하면서 동시에 체인된 omc HUD ctx도 strip(§0C-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 백엔드 라우팅 인프라 배선** — §0C 이월의 "라우팅 실제 배선" **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 잔여 LOW**(알려진 한계): display=None 내는 극단 프레임(양수 native 부재 + 600s TTL 초과 + 토큰 fallback 부재 = 사실상 cold-start)엔 omc strip과 겹쳐 ctx 잠깐 빔. 빈도 낮고 cold-start는 빈 게 맞아 미수정.
3. **lterm 릴리스**(선택): lterm 라우팅 인프라 배선(#122)은 main에 있으나 v1.0.22 이후 **미릴리스**. 동작 불변(behavior-preserving)이라 급하지 않음. 실렌더 트랙 완료 시 함께 릴리스 권장.
### 검증 수치(이번 세션)
- understatus main(v0.4.0): clippy 클린, **293 테스트**, release `--locked` 빌드 클린, 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 상태 (전부 머지, 열린 PR 0)
- understatus: **#9**(ctx fix) · **#10**(repo drift fix) · **#11**(v0.4.0 범프) · **#12**(homebrew 사본 동기화) 전부 merged.
- lterm: **#122**(라우팅 인프라 배선) merged.
### 릴리스 (understatus v0.4.0 — 4채널 라이브 ✅)
v0.3.0 이후 누적분(lterm statusline 통합·codex 심층판독·strip_chain_ctx·ctx fallback/hold·repo drift fix)을 minor bump로 배포 완료:
- **crates.io**: v0.4.0 published(sparse index 확정). **npm**: `understatus@0.4.0`. **GitHub Release**: v0.4.0(arm64+x64 tar.gz+sha256). **Homebrew**: tap `ictechgy/homebrew-understatus` Formula v0.4.0(소스 빌드, 소스 아카이브 sha256 `483672d2…`) + repo 사본 동기화.
- 절차 메모(§C 보강): 태그 push→`release.yml`(macos-14 arm64+x64)→`cargo publish --allow-dirty`(IRREVERSIBLE, credentials.toml 보유)→Homebrew tap 직접 push(별도 PR 불요, formula는 **소스 아카이브** sha256 사용)→npm은 **사용자가 passkey**로 `npm publish ./npm --access public`(에이전트 불가). npm postinstall E2E로 v0.4.0 release 바이너리 수신·ctx 표시 확인.
---
## §0C. 직전 세션 (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` 갱신 — **⚠️ v0.6.0부터 prebuilt 바이너리 방식**(소스빌드 아님): `version "X.Y.Z"` + `on_arm`/`on_intel` 각 `url`(GitHub Release **바이너리** tarball)·`sha256`을 갱신. sha256은 릴리스의 `.sha256` 에셋에서 받음(`curl -sL <release>/understatus-X.Y.Z-<triple>.tar.gz.sha256 | awk '{print $1}'`, **소스 아카이브 아님**). `depends_on "rust"`/`cargo install` 없음 → 설치에 CLT 불필요. `brew style` 클린 + `brew install`로 "built in N seconds"(컴파일0) 실설치 검증. tap 직접 push, repo `homebrew/understatus.rb` 사본 동기화(별도 PR).
4. npm: 로컬 `npm install ./npm --prefix /tmp/test --foreground-scripts` E2E(install.js가 vX.Y.Z 바이너리 SHA-256 수신 확인) 후 **사용자**가 `npm publish ./npm --access public`(EOTP passkey).
---
## §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 -8 # main `558aafb`: gitfile FN 가드(#24) + M-2(#23) + git pill 견고화(#22) + 아이콘 SF Symbol(#21) ...
cargo test # 328(lib)+14(oneline)=342 통과 (rustup: ~/.cargo/bin/cargo)
grep '^version' Cargo.toml # 0.6.0 (4채널 라이브 — 이번 세션 내부 hardening이라 범프 불요)
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: Merge #123(af59ab9, cmux pills 실렌더) + 라우팅 배선 #122
cargo test --bin lterm # 417 통과. 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 창 전환→복귀
```