플러그인 만들기 전에 터미널부터 좀 손봤다. OSC 133/7을 받아서 명령 경계를 인식하게 하고 상태바를 붙였는데, 이거 하다가 xterm addon-webgl 버전이 안 맞아서 페인이 통째로 크래시나는 걸 발견했다. 근본 원인 찾는 데 커밋 4개 썼다. 에러가 setTimeout 안에서 터지면 React 경계가 못 잡는다는 것도 이때 알았다.
아무튼, 앱을 안 켜도 기록이 남아야 한다는 생각을 계속 하고 있었다. Ocul-PM의 진짜 알맹이는 화면이 아니라 “작업 끝나면 일지 쓰고 계획 갱신한다”는 규칙인데, 그게 앱 안에 갇혀 있으면 앱을 켠 사람만 쓴다. 그래서 이번 라운드는 그 규칙을 Claude Code 플러그인으로 뽑아내는 거였다.
마켓플레이스 구성 붙이고 스킬 4종을 동봉했다. 커맨드도 만들었다. /oculpm:project_init으로 추적 시작, /oculpm:standup으로 오늘 뭐 했는지 뽑기, /oculpm:inception으로 새 영역 설계, /oculpm:next로 다음 할 일 잡아서 한 사이클 돌기. 여기서 신경 쓴 게 always-on 토큰인데, 플러그인 설명이 항상 컨텍스트에 실리니까 실측해보고 407토큰에 상한을 걸어놨다. 테스트로 고정. 이거 안 해놓으면 슬금슬금 는다.
플래너는 3단 계층으로 확장했다. 부모 항목은 자식 롤업으로 상태가 정해지고(dropped는 모수에서 빼고, blocked가 최우선, 섞이면 진행 중), 진척률 집계는 리프 기준. 부모를 직접 체크하는 건 막았다. 이거 적대적 검증 워크플로 돌렸더니 HIGH 3건 나왔는데, 그중 하나가 부모를 지우면 자식들이 엉뚱한 부모한테 입양되는 거였다. 최상위로 승격시키는 걸로 고쳤다.
제일 재밌었던 건 디스패치다. 플래너 항목 옆 ▶ 버튼을 누르면 그 항목이랑 하위 체크리스트, 연결된 일지 발췌, 게이트 지시까지 조립해서 터미널의 Claude Code에 프리필된다. Enter는 내가 친다. 그동안 플래너가 “뭘 했는지 보는 백미러”였는데 이걸로 “뭘 할지 미는 핸들”이 됐다. 자동으로 Enter까지 치게 할까 하다가 관뒀다. 그건 좀 무섭다.
그 뒤로 스킬 카탈로그를 25종 벤더링해서 스킬 샵 탭으로 올리고, 스택 감지해서 추천해주는 것까지. 에이전틱 A/B 벤치마크도 24세션 돌려봤는데, 결과가 좀 뼈아팠다. 헤드리스 환경에서 기록 규칙 준수가 0/12. 아무도 안 지킨다. 그래서 미기록 세션 신호를 만들어서 앱이 “이 세션 기록 없는데?” 하고 알려주게 했다.
8월엔 영어화를 했다. 라이브러리 안 쓰고 직접 짰는데, 언어를 React 컨텍스트가 아니라 모듈 레벨 스토어에 뒀다. 번역할 문자열 상당수가 컴포넌트가 아니라 순수 모듈(toast, planList 같은 거)에 있어서 컨텍스트로는 안 닿는다. en을 Record<keyof typeof ko, string>으로 묶어놔서 키 하나 빠지면 타입 에러가 난다.
한글 하드코딩 검사 스크립트를 만들었는데, allowlist를 거꾸로 썼다. 지금 한글 있는 파일을 전부 등재해놓고 번역할 때마다 빼는 식. 그러면 새 파일은 처음부터 한글을 못 넣고, 진척이 목록 크기로 측정된다. 130에서 시작해서 88, 66, 47… 결국 0. 탐지는 정규식 말고 문자 단위 상태 기계로 짰다. https:// 의 //를 주석으로 오독해서 뒤에 한글을 놓치는 걸 한 번 겪어서.
여기서 제일 고민한 건 UI 언어랑 AI 작성 언어를 나눌지였다. 원래는 하나로 가려고 했는데, 둘은 되돌릴 수 있느냐가 다르다. UI야 다시 한국어로 바꾸면 그만인데, AI 작성 언어는 .oculpm/journal/*.md처럼 디스크에 영구히 남는 문서를 정한다. UI 영어로 바꿨다고 일지가 조용히 영어로 넘어가면 되돌릴 수 없는 혼종 이력이 남는다. 그래서 content_language를 따로 뒀고, UI 바꿀 때 “AI도 맞출까요?”를 차단 모달 말고 액션 토스트로 물어본다.
Rust 에러 메시지 114곳이 제일 노가다였다. 그리고 UI를 영어로 바꿔놨는데 AI가 뽑아주는 산출물은 여전히 한국어로 나오는 구멍이 있었다. LLM한테 영어로 쓰라고 시켜도, 코드가 직접 조립하는 뼈대(스탠드업 제목, 헤더, 빈 상태 문구)는 모델이 손댈 수 없는 자리다. 키가 없어서 LLM을 못 부르면 그게 최종 산출물이 되는데 그게 통째로 한국어. 이런 건 진짜 양쪽 언어로 다 켜보기 전엔 모른다.
끝나고 나니 v2.8.5. 다음 날엔 창 하나에 프로젝트 여러 개를 탭으로 물리는 v2.9.0을 냈다. 프로젝트 바꾸면 보던 게 사라지는 게 계속 거슬렸는데 드디어 해결. ⌘W를 macOS 기본 메뉴가 웹뷰보다 먼저 가져가버려서 앱 메뉴를 직접 구성해 되찾아 와야 했다. 이때 Edit 서브메뉴를 빼면 ⌘C/⌘V가 같이 죽는다는 걸 몸으로 배웠다.