poin-agent — 작업 규칙 (rules)
이 파일 = note20 폰·카톡 조작 작업 규칙의 단일 출처. 상태·진행·구현이력은
handoff.md, 여긴 규칙만. 갱신 지침(필수): 새 규칙·교훈·함정이 나오면 그 답변에서 바로 아래🆕 신규에 1줄 append(날짜 + 규칙 한 줄 + 근거 포인터). 다음 세션으로 미루지 않는다. 신규가 쌓이거나 안정화되면확립 규칙의 해당 §로 원문 이관(삭제 금지, cut&paste).
📑 인덱스 (필요한 항목만 열어 읽는다)
| § | 내용 | 언제 |
|---|---|---|
| §1 | 연결·환경 (유선 기본·adb·python) | 세션 시작·연결 실패 시 |
| §2 | 화면·좌표 (세로고정·재잠금·팝업) | 모든 UI 조작 전 필수 |
| §3 | 봇탐지 회피 (지터·타이밍·레드라인) | 카톡 조작 전 필수 |
| §4 | 카톡 조작 (IME·친구추가·발송·노드맵) | 카톡 기능 구현·실행 시 |
| §5 | 검증·마무리 (단정 금지·화면끄기·경로함정) | 작업 끝낼 때 |
🆕 신규 (미편입 · 최신 위)
- [코디] 🆕26.10.21 노트20 «사진 여러 장 묶어보내기» = 전용 앨범(
/sdcard/DCIM/<이름>/)에 push +touch -t로 순서 고정 → 피커 상단 앨범 드롭다운에서 그 앨범만 고른 뒤checkbox_container를 탭(썸네일 본체 탭 = 미리보기로 빠져 1장만 선택됨). ⚠선택할 때마다 위에 미리보기 줄이 생겨 격자가 밀린다 → 탭마다 다시 덤프해 k번째 체크박스. 「사진 묶어보내기」는 기본 선택. 끝나면 앨범 rm+스캔. 스크립트 =C:\Users\delix\AppData\Local\Temp\claude\c--dev\24393ff3-04dd-438f-b299-63e452376ad1\scratchpad\send_group.py(phone.py 편입 후보). PC카톡 월드방 사진은 poin3133 계정으로도 「포인-월드」 멤버라 계정전환 없이 수집됨(collect_photos.py파일명 = 메시지 시각 HHMMSS 라 텍스트 내보내기와 시각으로 매칭). - [페페] 🆕26.10.20 발주서가 2장 이상이면 카톡엔 «페이지별로 분리한 사진»을 올린다 — 한 PNG 에 세로로 붙여 보내지 마라. 남판교 3차 오엠씨 14:34 발송분이 2장(매수 1·2)이 한 이미지로 나가 [코디] 가 표 경계선(y=1137)에서 잘라 poin3133 으로 「포인-오엠씨」에 사진 2장+「DSD삼호 남판교 3차 발주서 2장 분리 발송」 재발송(15:42 KST). 산출·스크립트 =
C:\dev\_work\omc-split-1020\. 개선 후보 = orderpaper_kakao 렌더가 인쇄 페이지 수만큼 PNG 를 나눠 send_photo 를 반복. - [코디] 🆕26.10.20 발주서 카톡
open_room은 검색 1위 더블클릭이 «창이 안 뜨면» 다시 시도하지 않는다 — 남판교 3차 오엠씨 14:25 「포인-오엠씨」 검색에 엉뚱한 「포인-오엠씨(신송)」만 열려 «방 못 찾음» 실패(제목 정확일치 가드라 신송방엔 0건) → 같은 방으로 단독 job 재시도 14:34 성공. 실패 시 = 같은 이름 방 후보·최근 대화 시각을 보고 페페 확인 후 단독 재시도(다른 업체 재발송 금지). 오엠씨 방 = 「포인-오엠씨」(신송방 아님 · 페페). 작업 시작 시 PC카톡이 poin3133 이면 kakao-switch 로 delix0731 전환. 산출 =C:\dev\_work\nampangyo-3cha-1020\kakao\. 개선 후보 = open_room 창 미표시 1회 재시도. - [코디] 🆕26.10.19 PC카톡 방 사진 받기 — 서랍(
collect_photos.py)이 「서랍/사진탭 열기 실패」면 말풍선에서 직접. 단일 이미지 우클릭 메뉴 1번 = 「저장」 → 「다른 이름으로 저장」 #32770 이 뜬다(옛 기록의 「카카오톡 받은 파일」 자동저장 아님 → ComboBox 1148/Edit 1001 경로주입). 🔴사진 «묶음»(2장+) 미다운로드분은 우클릭 1번이 「답장」이라 같은 좌표로 누르면 답장 모드가 켜진다(발송은 안 됨, 입력창 위 X 로 해제). 묶음은 클릭 → 뷰어창(EVA_Window_Dblclk, 제목 「보낸이 날짜」) 최대화 → ImageGrab 으로 받는다.kakao_grab_room.py <이름>은 1:1 방이 먼저 걸리니 단톡방은 정확한 방제목(「아이비젼-포인」)으로. pythonw 래퍼에서collect_photos는 stdout 을 재포장해 로그가 사라진다 → subprocess 로 돌린다. 산출 예 =C:\dev\_work\ivg-riverforet2\. - [코디] 🆕26.10.15 PC카톡 «로그인 창이 안 뜬다·계정 전환 실패» = 업데이트 승인창(UAC, consent.exe) → 2~3분 뒤 「업데이트에 문제가 발생했습니다」 창 순서로 막힌 것. 그동안 숨은 메인창만 있어 상태가 «로그인됨(on)»으로 읽히지만 서버 연결 0. 오류창을 WM_COMMAND 로 닫아야 로그인 창이 뜬다(BM_CLICK 은 무효 — auto-register
dismiss_kakao_update()아직 BM_CLICK). 처방 =C:\dev\poin-agent\kakao_pc_login.py2ac2314(대기 240초·매초 오류창 닫기) ·C:\dev\tools\kakao-switch\tray.pya97c097(오류창 = 로그인 필요 판정). 상태 'on' 을 믿지 말고 consent.exe·오류창부터 본다. 30분마다--click cody=C:\dev\auto-register\capture\capture_client.pyensure_resident()(사무실PC 에 delix0731 붙어 있을 때만). - 🔴(2026-10-15) [페페] 게시글 「간략」 = 경과·이력을 빼라는 뜻이지 세부를 빼라는 뜻이 아니다. 26.10.1 개편(본문 2줄·「대체된 옛 값도 지운다」)이 진행 중 항목의 사양·코드·치수까지 깎아 「세부내용이 안 들어간다」. 강제 =
sgc/watcher.pyPROMPT 4-5·4-6 / REBUILD 4-1·4-2: 규격·자재명·색상/유리/자재 코드·두께·치수·수량·위치·담당/기한은 대화 표기 그대로 · 사양 변경은 「옛 값 → 새 값」 · 본문 최대 4줄(+꼬리) · 사진은 「사진 공유(MM/DD)」만 · 돈 얘기(단가·시공비·정산·월마감 구분) 금지, 「■ 견적」 한 줄 금액만 예외 — ✅[페페] 결정 26.10.15 확정 · 「옛 값 → 새 값」은 그 항목이 끝날 때까지 유지(✅[페페] 결정 26.10.15, PROMPT 4-5 · REBUILD 4-1, 커밋2f12504). 회귀 =sgc/test_watcher_rules.py「26.10.15 세부 보존」 블록. 커밋c80c0a6· 전 방 재작성 스펙 =C:\dev\poin-agent\_backup\2026-10-15_board_detail\SPEC.md(검사기tools\chk.py). - 🔴(2026-10-15) [코디] 새 방 첫 대화가 새는 자리 3곳 — ①
handle_no_room이 unrouted 원문을[:300]로 잘랐다(SLS 첫 공지 416자의 출고일·자재 유실) → 전문 저장(알림 미리보기만 자름). ②resolve_unrouted는 그 id 의 «마지막» 메시지를 채팅목록 미리보기와 대조하는데 마지막이 사진이면 미리보기 = 「사진」이라 영영 못 맞추고 30분 간격이었다 → 사진·이모티콘이 마지막인 id 는 스캔 제외 · 새 글이 왔을 때만 재시도 · 간격 300초. ③room_id 학습 뒤 ~ 페페 수집 체크 전 사이에 온 메시지를 리스너cb가 「새 방」만 적고 버렸다(소요 한남 10:03~10:07 6건 — 폰 화면 판독으로 inbox 되넣음routed_by=phone_backfill). ✅[페페] 결정 26.10.15(추천안 A) = kakao-rules 에 없는(미결정) 새 방만keep_pending()이 원문을_unrouted.jsonl에pending:true+방 이름으로 보관(방당 최근PENDING_MAX=300건 ·PENDING_DAYS=7일), 체크해 inbox 가 생기면resolve_unrouted()가 되넣는다(routed_by=pending_replay). kakao-rules 에 있는 방(watch:false = 페이북·칼리 등)은 그대로 버린다(fail-closed 유지)._unrouted.jsonl은_UNROUTED_LOCK안에서만 쓰고, 되넣기는 락 안에서 다시 읽어 고친다(스캔 중 리스너가 덧붙인 줄을 옛 목록으로 덮어 지우던 구멍). 커밋c80c0a6·2f12504. - 🔑(2026-10-15) [코디] 빈 틀 최초 게시 = 쌓인 대화로 먼저 채운다 —
first_post()가 board.md 가 빈 스켈레톤이고 백로그가 있으면 REBUILD 경로로 채워 v1 을 올린다(실패·한도면 옛 동작 = 빈 틀 + 백로그 보존, halt 안 부름). 소요 한남은 옛 동작으로 10:32 빈 공지 → 11:05 v2 까지 33분 빈 글이었다. ⚠손으로 최초 게시해야 하면board_post.py가 아니라import watcher; watcher.notify=무음; watcher.first_post(room, proj, st, perms)— 데몬과 같은 경로라 posted_at·board_hash·processed_lines 가 같이 찍히고, 다음 슬롯 전에 끝내면 중복 게시가 없다(실물C:\dev\poin-agent\_backup\2026-10-15_board_detail\tools\sls_post.py). - ⚠(2026-10-15) [코디]
phone.roomid_map()은 프로세스 메모리 캐시다 — 밖에서_roomid_map.json에 써도 상주 watcher 는 재기동 전까지 모르고, 그 사이 watcher 가 다른 방을 배우면 자기 캐시로 파일을 통째로 덮어 바깥 항목을 지운다. 외부 학습(learn_roomid)은 watcher 를 죽인 틈에만(tools\restart_wd.py= 폰 락 잡고 사살 → 학습 →\Cody\Cody-PoinBoardWatch-Restart). - 🔴(2026-10-14) [코디] 게시글 halt(
C:\dev\poin-agent\halt.json)는watcher.py resume을 불러야만 풀린다 — 장애를 «고쳤다/무관하다»고 넘긴 세션도 resume 여부를 꼭 확인해 보고에 적는다. INC-004 = 10/8 14:05 일시 화면 장애(잠금/AOD·포커스 null)로 halt → 그날 다른 세션이 「resume 안 함」으로 남겨 전 방 6일 게시 0(첫 알림 1번뿐이라 아무도 몰랐다). 장치 = watcher 가 halt 24시간+ 이면 게시 시간대에 하루 1번 텔레그램 재알림(remind_halt) +phone.open_room목록 탐색 실패 시force_chat_list후 1회 재시도. 커밋58025cc·198dfac, 기록 =C:\dev\poin-agent\incidents\INC-004.md「## 해결」. ⚠phone.py selftest는_fail_openroom.txt를 덮어쓴다 → 실패 증거는 selftest 전에 옮겨 적는다. - 🔑[페페] 26.10.14 카톡 발송·수집 전 계정이 delix0731 로 안 붙어 있으면(목록 0·로그인 창·다른 계정) 묻지 말고 kakao-switch 엔진으로 자동 전환(강제 로그인 포함) 후 진행 — 판정 = Session 1 에서
C:\dev\tools\kakao-switch\tray.py의kakao_state()(on/login/off) +current_account()(last_pc_login.dat 메일만) · 전환 =tray.py --switch pepe(=kakao_pc_login.login_with→restart_to_login·dismiss_popups「로그아웃되었습니다」 닫기·「다른 기기 로그인 중」 강제 로그인). 첫 적용 26.10.14 13:52 KST: 상태login(계정 파일은 delix0731 그대로 = 다른 기기에 튕김, 메인창은 빈 목록 「채팅을 시작해보세요」) → 전환 8초 →on→ 롯데 이천 안흥 발주서 3/3 발송. ⚠current_account()만 보면 «붙어 있다»로 오판한다(튕겨도 ID 는 남는다) → 반드시kakao_state()같이. ⚠전환의 합성 마우스가 유휴시간을 0 으로 만든다 → 발송 래퍼 유휴 가드(60초)는 전환 뒤 1분 기다려 통과. ✅도구 반영됨(poin-agentcfbb41f· 기준점ed4e68b):kakao_pc_send.ensure_account()(트레이 kakao_state·current_account·need_login·switch 재사용 · 전환 뒤quiet_ok로 전환 합성 입력 vs 사람 입력 구분 · Session 0 = 판정 불가) →orderpaper_kakao.run_local사전 점검 뒤 호출 + 방 확인이 전부 「열어본 방=[]」(목록 0)이면 재로그인 후 1회 재확인 ·--check·직접--send(실패 텔레그램)·--dry(판정만) · 자체검사test_account_switch.py26. 반영 전엔 방 확인 실패 = 「대상 방을 못 찾았다(열어본 방=[])」 0건 중단(26.10.14 07:00 피앤알·08:30 2건). ⚠핑퐁: 13:52 강제 로그인 뒤 14:02 다시login(다른 기기가 되찾음) — 다른 PC 에서 같은 계정을 쓰는 중이면 발송마다 서로 밀어낸다. - 🆕(2026-10-14) [코디] 스킬 신설
C:\Users\delix\.claude\skills\orderpaper-dispatch\SKILL.md— 「발주서 발주 진행·원부자재발주서 출력/발송·발주서 기준 PFS 수정」 전 과정(정본 대조 → PFS amend/remove → 엑셀 zip 치환 → 사무실 복합기 출력 → 카톡 일괄 예약 발송 → 사후). 기준 사례·스크립트 =C:\dev\_work\daejeon-order-send-1014\. 이 파일의 발주서 카톡 함정은 그 스킬이 포인터로 묶는다. - 🔴(2026-10-14) [코디]
orderpaper_kakao.render()는 Excel 이 «응답 없는 기본 프린터»(미니PC = 집 Samsung WiFi)로 열면 100초+ 멈추거나 PDF 내보내기가 「이 프린터를 사용할 수 없습니다」로 죽는다 — 처방 = 파일을 열기 전에 인스턴스ActivePrinter를Microsoft Print to PDF(없으면 SINDOH) 로 돌린다. ★열린 통합문서가 0개면 설정이 거부된다 →Workbooks.Add()빈 문서 먼저 →_set_printer→ 진짜 파일 Open → 빈 문서 Close(실측 6탭 렌더 4초). Windows 기본 프린터는 안 바꾼다.render_retry(3회·150초 타임아웃·이번에 뜬 EXCEL.EXE 만 taskkill) 가 간헐 실패를 받는다. 출력 쪽print_tabs.py는 빈 문서 없이 set 해서 None 이 나와도 Excel 의 ActivePrinter 가 이미 SINDOH 일 때만 통과했다 → 같은 처방을 적용할 것. - 🔴(2026-10-14) [코디]
orderpaper_kakao.py --job의local: true경로(run_local)는 첫 실발송이 07:00 예약이라 «실전 최초 실행»이다 — 모의(kakao\_test_run_local.py: 정상/시각 지남/화면 잠김/방 이미 열림)와--dry만 검증됐다. 순서 = 시각 지남(30분↑ 중단) → 화면 잠금(desktop_locked) → 대상 방 창 이미 열림 → 방 확인(발송 0) → at 대기 → 잠금 재확인 →~$경고 → NAS 재렌더 → 발송.--dry는 send/auto/local 을 꺼서 발송 0건. jobrooms/msgs키가 대상 탭에 없으면 중단(오타 방지). 첫 실행 결과(run.log·텔레그램)로 확정하고, 틀어지면 이 줄을 고친다. - 🆕(2026-10-08) [코디] claude 호출 =
C:\dev\tools\cody_ask.py경유(API 크레딧 우선·구독 폴백) — 테스트 대역도 바뀌었다.sgc/test_watcher_rules.py는w.cody_ask = type("m", (), {"ask": staticmethod(lambda prompt, **k: {...dict})})()로 흉내 낸다(옛w.subprocess·w.oauth_env대역은 없다). 한도 판정 =r["limit"]또는_LIMIT_MSG(어댑터가 한도 문구를err에 싣는다). ⛒이관·재기동 같은 정비 중halt.json이 이미 다른 장애(INC-###)로 열려 있으면resume하지 마라 — resume 은 그 티켓을 닫는다(26.10.8 INC-004 열린 채 재기동만 함). - 🆕(2026-10-08) 사무실PC(poinimos01) = Win10 Home 19045 다 — Win11 트레이 꺼내기(
HKCU\Control Panel\NotifyIconSettings\…\IsPromoted=1)가 없다. 키 자체가 없음(실측). Win10 은TrayNotify\IconStreams이진값+explorer 재시작이라 비침습 원칙에 걸린다 → 아이콘은 숨김 영역(^)에서 사람이 1회 끌어낸다. 같은 PC 의 broker 알림(notify.py)도 안 된다(broker = 미니PC 127.0.0.1:7777 전용). - 🆕(2026-10-01) [페페] 카톡 게시글 = «당장 해야 할 과제만, 간략하게». 「■ 변동 반영 이력」·「■ 출고 완료」 섹션 폐지(끝난·취소·대체된 옛 값·지난 일정·경과 서술은 지운다). 항목 =
N. 항목명 — 현재 결론 · 다음 할 일(누가/언제)본문 2줄 이내 + 화자 꼬리 1줄(이름 직책 MM/DD)최신 결정자 1명, 변동은 덧붙이지 말고 바꿔 쓴다. 그 밖 섹션은 0건이어도 제목 유지 · 견적 한 줄 규칙(26.8.14) 유지. 강제 =sgc/watcher.pyPROMPT 4·6 / REBUILD 3·4 +interpret()가 폐지 섹션을 걷고(누락 계산 제외) 하한 300자 대신 구조 검사(첫 줄·수정줄·안내문 잘림·섹션누락 — 짧은 정상 글이 FAIL_LIMIT 로 전 방 halt 되던 자리) +first_post()스켈레톤 거름 + devplan_KBOARD_SKEL에서 두 섹션 삭제. 커밋9448a53· 원문 =handoff.md26.10.1 절. - 🆕(2026-09-28) [페페] PC카톡 수집은 계정 전환·강제 로그인까지 기본 자동화다.
C:\dev\_work\ax-biz\kakao_grab_room.py가 시작 때ensure_pepe()로 delix0731 을 확인하고, 아니면kakao-switch\tray.py의switch('pepe')로 로그인한다(--no-switch로 끔).kakao_pc_login.login_with()는dismiss_popups()로 「다른 기기에서 로그인 중 → 강제 로그인?」(262x186, 확인=왼쪽 절반)과 「로그아웃되었습니다」(262x165)를 실제 마우스 클릭으로 넘긴다 — 광고 팝업(388x91)도 같은EVA_Window_Dblclk·무제목이라 크기로만 가른다. ⛒튕겨난 카톡은last_pc_login.dat가 그대로 delix0731 이고 메인창도 있는데 채팅·친구 목록만 텅 빈다(숨은 로그인 창 존재) → 계정 판정에find_login_window2()유무를 같이 본다(26.9.28 실측: 검색 3회 전부 0건). ⚠강제 로그인 = 페페가 다른 PC에서 쓰던 delix0731 카톡이 로그아웃된다. - 🆕(2026-09-23) [페페] 노트20 카톡 미읽음은 쌓아두지 않는다 — 매일 05:30 자동으로 0으로 만든다. 도구 =
C:\dev\tools\kakao-unread\clear_unread.py(예약작업\Cody\kakao-unread-clear· 숨김 vbs · 로그clear.log), 경로 = 채팅 탭 → 「안읽음」 필터칩 → 맨 위 미읽음 행 탭(=읽음) → BACK 반복 → 「전체」 원복. 판정은 진입 성공이 아니라 «그 방이 미읽음 목록에서 사라졌나» 로 한다(오픈 실패는 건너뛰고 다음 방). 성공 = 미읽음 행 0 그리고채팅 탭desc 에 숫자 없음. ⛔길게누르기·「채팅방 관리」 편집모드 금지(옆이 「나가기」) — ⋮ 메뉴엔 일괄 읽음 자체가 없다(실측: 채팅방 관리·정렬·폴더 관리·전체 설정 4개). 광고 배너 행은 폭(x 45~1035, 방 행은0~1080)으로 거른다. 첫 실행 133 → 0개 · 7방 · 113초 · 잔여 카톡 알림 0. 왜 = 미읽음이 쌓이면 탭 desc 가채팅 탭 N개의 새로운 업데이트로 바뀌어 폰 도구가 죽는다(26.8.12 46개에서 전량room not found). devplan =/note20-agent.html#unread-clear. - 🔴(2026-09-23) [코디] 카톡 게시글은 「10,000자 / 250줄」이 하드 상한 — 넘으면 카톡이 모달을 띄우고 저장을 거부한다. 실측 = 향남 17:19 새 본문 10,003자(3자 초과). 모달이
content_edit노드를 덮어 덤프에서 지우는 바람에 오류가 「새 본문 입력 실패 (ADBKeyboard=…)」로 둔갑했다 — 입력기·adb 길이 문제로 오진하기 딱 좋다(같은 room 이 18,817바이트 게시글을 9.17 에 멀쩡히 올렸다 = 길이 단위를 바이트로 보면 원인을 못 찾는다). 화면 증거 =C:\dev\poin-agent\_fail_edit.png(cody-vision 으로 모달 문구를 읽었다). 처방 =watcher._fit_kakao()가 「■ 변동 반영 이력」 오래된 줄부터 버려 상한을 맞추고, 이력을 다 줄여도 안 맞으면 폰에 끌고 가지 않고 거부한다(잘린 글 게시 금지). ⛒순서 = 폭주 가드(직전×2) 통과 뒤에 줄인다 — 먼저 줄이면 폭주가 이력 줄에 숨는다. 커밋7ccfcbe. - 🔴(2026-09-23) [코디]
claude -p는 한도 소진을 stdout 에 적고 stderr 는 비운다 — stderr 만 실으면claude rc=1:만 남는다. INC-003 원인 = 26.9.21 11:00·11:30 「You've hit your weekly limit · resets 10pm」(transcript%TEMP%\poin-agent-claude\*.jsonl의isApiErrorMessage:true). 자동분석 claude 도 같은 한도에 막혀 빈 소견을 내서 원인 미상으로 2일 방치됐고, 한도는 그날 22:00 에 이미 풀려 있었다. 처방 =watcher.run_claude()단일 경로가 stdout·stderr 를 둘 다 실어 던지고,UsageLimit로 분류된 실패는 실패 카운트·halt 대상에서 뺀다(다음 슬롯 재시도 · 알림 1회). ⛒「context limit」류는 일부러 한도로 안 본다 — 시간이 지나도 안 나으니 영원히 재시도만 하고 티켓이 안 열린다. 곁다리로pfs_done은 판정이 터진 방의 자재를seen에서 빼 다음 회차에 다시 본다(안 빼면 완료 반영이 조용히 증발한다). 커밋8ce550e· 티켓C:\dev\poin-agent\incidents\INC-003.md「해결」 절. - 🔑(2026-09-23) [코디]
pfs_done의 Jevnoul은 «거르기 전용»이다 — 확실 판정을 Jev 에 맡기지 마라. 정답셋 12행(C:\dev\_work\jev\d4_labeled.py) = 종결 0.55~0.86 · 비종결 0.08~0.58 로 겹친다(「입고 뒤 도장·출고 남음」 행이 0.58로 진짜 종결보다 높다). 그래서JEV_LO=0.2미만 행만 버리고 남은 행을claude -p가 확정한다(하이브리드 종결 5/5·비종결 0/7). 자재에 거래처명 추가·choice3지선다는 분리 개선 없음(choice 는 전부 「일부」로 쏠림). 임계 = envPFS_DONE_JEV_LO. - 🔴(2026-09-20) [코디]
Phone._sh()는 이미shell을 붙인다 — 또 붙이면 «조용히 빈 결과»다.P._sh('shell','uiautomator','dump',…)는 폰에서/system/bin/sh: shell: inaccessible or not found(rc 127)로 죽는데, 반환이 튜플(stdout, stderr, rc)라xml[0]만 읽으면 빈 문자열이 온다 → UI 덤프가 0건이고 「그 버튼이 화면에 없다」로 오판한다(실측:_ui.xml0바이트로 저장돼 있었다). 정답 =P._sh('uiautomator','dump','/sdcard/_ui.xml')+P._sh('cat','/sdcard/_ui.xml'). ⚠덤프를 여러 번 나눠 찍을 땐 매 호출마다P.unlock()— 사이에 화면이 잠기면 잠금화면(시계·날짜)만 덤프된다. - 🔴(2026-09-18) [코디]
phone.open_room()이 「툴바 제목 불일치」로 죽으면 방 이름이 아니라 «행이 화면 맨 아래 경계»가 범인이다 — 탭이 조용히 무효가 된다. 실측 = 신동승 방이cy 2116 / h 2400(0.88h)일 때 3회 연속 실패, 같은 행을cy 1246으로 올리자 1회에 진입. 탐색 루프가 「보이기만 하면」 통과시키고,open_room이 시작할 때 「전체」 필터를 눌러 목록을 맨 위로 되돌리므로 목록 아래쪽 방은 매번 이 자리로 온다. ⛒처방(적용 완료) = 탭 직전row["cy"] > h*0.78이면 한 번 스와이프하고 재탐색(phone.pyopen_room). ⚠미니PC 의 PC 카톡은 빈 계정이다(채팅·친구 0,last_pc_login.dat의 메일주소는 마지막 «시도» 계정일 뿐) → 파일 전송은 PC 카톡 경로를 보지 말고 노트20phone.py sendfile로 간다. 화면이 잠겨 있으면awake()가 «타임아웃만» 늘리고 잠금은 안 푼다 → 호출 전에wake()+unlock(). - 🔴(2026-09-18) [코디] 고객 방 게시글엔 «돈 얘기»를 넣지 않는다 — 통화 전사에서 자동으로 딸려 온다. 26.9.18 나진상가 2차 갱신에서 김영민 부장 통화 10건을 전사했더니 시공비 단가 조율(30~33만원)·시공팀 견적 230만원·계산서/월마감 프로세스가 요약에 그대로 잡혔다. 게시글은 한샘·넥서스가 보는 글이라 전부 뺐고, 담은 건 일정·반입조건·업체분담·확정사양뿐이다. 같은 이유로 내부 검증 산출물(네스팅↔사양서 컬러 불일치 등 [페페] 조치 판단 전인 것)도 안 올린다 — 올리면 코디가 고객에게 질문을 던지는 셈이 된다. ⚠카톡 게시글은 마크다운을 렌더하지 않는다 —
**강조**가 글자 그대로 나간다(저장 직후 걷어내 폰 반영 전 수습). - 🔑(2026-09-18) [코디] 현장 협의 이력을 모을 땐 «통화»가 카톡보다 밀도가 높다 — 미전사분을 먼저 센다. 나진상가는 카톡(1:1 넥서스 김영민 부장)에 없는 확정이 통화에만 있었다(업체 분담·몸통 18T/선반 25T·양중 동선·검토기준 사양서 단일). 세는 법 =
ls C:\dev\talklog\data\calls | grep <이름>로 원본 전량 → 이미 전사된 건C:\dev\poin-agent\calls\에 날짜명으로 있다(차집합이 미전사분). 배치 =stt.py run <m4a> --peer "<상대>" --subject "<현장>" --groq --no-kakao(--no-kakao필수 — 없으면 건마다 페페 카톡으로 HTML 이 날아간다). Groq 는 통화 1건당 20~90초라 10건도 10분 안에 끝난다. 읽을 땐sed -n '/■ 요약/,/■ 확인 필요/p'로 정리본만 — 전문까지 읽으면 컨텍스트가 샌다. - 🔑(2026-09-18) [코디] 최초 게시 «시각»을 지정받으면
kakao-rules.json등록 시각으로 맞춘다 — watcher 는 등록된 «다음» 정각/반각에first_post()를 돈다. 루프가added방에last.setdefault(room, 현재슬롯)을 박아 붙은 슬롯을 건너뛰고(페페 지시 26.8.5 「게시글은 다음 주기때 시작」), 주간 슬롯은 30분(DAY_IVL)이다. ⛒「1시 업로드」 = 12:31~12:59 사이에 rules 등록(예약작업 1회면 된다 — 26.9.18 나진상가는 12:45\Cody\NajinEnable). 폴더·state.json·board.md는 먼저 만들어도 안전하다 —load_rules가 fail-closed(rules 에 없는 방은board_edit=False)라 등록 전엔paused로만 돈다.board_post.py를 손으로 돌리는 건 여전히 금지(중복게시). - ⚠(2026-09-18) [코디] PC카톡 검색 0건 = 「방이 없다」가 아니라 «오늘 만든 방일 수 있다» — 방 개설 시각부터 확인한다. 26.9.18 나진상가는 미니PC PC카톡에서 「나진」 검색이 0건이라 라인VIP 와 같은 「페페 대화 내보내기」 경로를 떠올렸지만, 실제로는 그 방이 11:01 에 개설된 신규방이라 어디에도 이력이 없었다(코디폰 방 화면 4줄이 전부). 판정 =
data/rooms/_unrouted.jsonl의 그room_id첫 줄 시각 · 폰 방 상단의 「…님이 …님을 초대했습니다」. 🔑현장 협의 본체는 다른 방에 있다 — 발주처 1:1 방(나진상가 = 「넥서스 김영민 부장」C:\dev\_work\najin\nexus_kym.txt)과 PFS 시드(네스팅·발주서·도면)를 합쳐야 최초 정리 게시글이 나온다. - ⚠(2026-09-18) [코디]
kakao_grab_runner.py는 사무실PC 사본 전제라 미니PC 에서ModuleNotFoundError: kakao_pc_send로 죽는다 — 사무실PC 는C:\poin-orderpaper\에 모듈 사본을 같이 두지만 미니PC 는 리포(C:\dev\poin-agent·C:\dev\talklog\collector)에 원본만 있다. 처방 =sys.path조건부 추가(os.path.isdir로 양쪽 PC 호환). 덤 = 예약작업/tr에pythonw만 쓰면0x80070002(파일 없음) 로 조용히 실패한다 → 전체 경로(C:\Users\delix\AppData\Local\Programs\Python\Python312\pythonw.exe)로 쓴다. - ⚠(2026-09-16) [코디]
board.md를 고쳐 watcher 에 맡길 땐 한 번만 고치고 손을 뗀다 — watcher 가 폰에 민 뒤commit_board()로board.md를 자기 텍스트로 되쓰기 때문에, 그 사이에 넣은 수정은 조용히 사라진다. 26.9.16 실측 = 문구 정합 수정(①)과 둘째 줄 「수정: 시각」 갱신(②)을 몇 분 간격으로 넣었더니, watcher 가 ①만 담긴 판을 읽어 폰에 밀고 그 텍스트로 파일을 덮어써 ②가 없어졌다(v2edited16:14:21). 게시글 갱신은 board.md 1회 저장 → 5분 대기 →runs.jsonl의edited확인 순서로 본다. 참고로push_web_edits는 「수정:」 시각을 갱신하지 않는다(웹 행편집 반영 경로라 그렇다) — 시각까지 맞추려면 그 한 번에 같이 써 넣어야 한다. - 🔴🔑(2026-09-16) [코디] 새 방을 편입할 때
board_post.py로 손수 최초 게시하면 게시글이 2건 올라간다 — 최초 게시는 watcher 몫이다.sgc/README.md「새 방 추가 절차」 3번이board_post.py1회 게시를 시키는데, 그건 watcher 에first_post()(=posted_at이 비면 자기가 게시+공지 등록)가 들어간 26.7.27 이전 절차다. 26.9.16 라인VIP 편입 실측 = 내가 15:59 에 올리고kakao-rules.json에 방을 등록했더니 watcher 가 「감시 대상 갱신」 후posted_at=null을 보고 16:02 에 같은 글을 또 게시했다(그쪽이 공지로 등록됨). ⛒순서 = 폴더+state.json(posted_at=null)+board.md만 두고 손 떼면 10분 내 watcher 가 게시·공지까지 한다. 직접 올려야 하면 게시 직후posted_at·board_hash를 먼저 채우고 그 다음에 rules 등록(등록이 먼저면 그 틈에 끼어든다). 수습 = 게시판 카드 중 공지 배지 없는 쪽만 ⋮→삭제하기(공지 쪽을 지우면 배너까지 날아간다) · 절차 원문은sgc/README.md3번에 박아 두었다. - ⚠(2026-09-16) [코디] 미니PC(POIN-MINI) PC 카톡 계정이
delix0731(페페 계정)로 와 있다 — 26.9.15 기록(「지금은 사무실PC」)은 하루 만에 뒤집혔다. 카톡 계정은 PC 한 대에만 붙으니 수집·발송기를 돌릴 PC 는 그날그날last_pc_login.dat로 판정하고 시작한다(고정 가정 금지). - ⚠(2026-09-16) [코디]
kakao_pc_send._tops()의EnumWindows콜백이 falsy 를 돌려줘 간헐적으로pywintypes.error: (183, 'EnumWindows', ...)로 죽었다. 콜백이None이면 열거가 중단되고 잔류GetLastError가 예외로 올라온다(같은 코드가 앞선 호출에선 통과 = 재현이 들쭉날쭉). 처방 =lambda h, _: out.append(h) or True. 이 함수는main_win·room_wins공용이라 카톡 GUI 도구 전체가 이걸 탄다. - 🔴🔑(2026-09-15) [코디] PC 카톡에서 방을 열 때 「신규창 차집합」만 보면, 방이 이미 열려 있을 때 영영 헛돈다.
kakao_grab_room.find_room은 검색 → 행 더블클릭 →room_wins()차집합으로 새 창을 기다리는데, 그 방 창이 처음부터 떠 있으면 더블클릭은 포커스만 옮기고 새 창을 안 만든다 →열어본방=[]로 3개 검색어 전부 miss(26.9.15 사무실PC 실측, 스크린샷엔 검색결과 「넥서스 김영민 부장」이 멀쩡히 떠 있었다). ⛒검색 전에room_wins()를 먼저 훑어 제목이 맞는 창을 집는다. ⚠이미 열려 있던 창은 옮기지도 닫지도 않는다 — 페페가 열어 둔 창일 수 있다(무간섭). 실물 =C:\poin-orderpaper\kakao_grab_runner.py(사무실PC ·/IT예약작업\Cody\KakaoGrab· 대상은grab_job.json). - ⚠(2026-09-15) [코디] 사무실PC(poinimos01) PC 카톡 계정이
delix0731(= 페페·S25 계정)로 바뀌어 있다. 26.8.27 기록(「사무실PC = 채팅방 0개인 다른 계정」)은 낡았다 — 카톡 계정은 PC 한 대에만 붙으므로 거래처 1:1 방 수집·발송기는 지금 사무실PC 다. 판정 한 줄 =%LOCALAPPDATA%\Kakao\KakaoTalk\users\last_pc_login.dat에서 메일주소만 정규식으로 뽑기(토큰이 같이 들어 있어 통째로 찍으면 안 된다). - 🔴🔴(2026-09-15) [코디] 0순위(카톡 워커)에 폰을 양보했다 돌아오면 «화면이 꺼져 잠겨 있다» — 되찾은 즉시 다시 깨워야 한다. 원인 = 0순위가 자기
awake()블록을 닫으며finally에서screen_off_timeout을 되돌리고sleep()을 때린다._awake_depth재진입 가드는 프로세스 안에서만 듣기 때문에 남의 프로세스 sleep 을 못 막는다. 실측 = 당근 팁 t006 게시가 11:03 양보 → 복귀 후 사진 6/8 에서 「사진 피커가 안 열린다」(덤프 루트에 잠금화면 시계오전11:03 · 9월 15일 화요일)로 죽었다. ⛒처방 =phone.Phone._sh()에서phonegate.checkpoint()가 True(=실제 양보) 면screen_off_timeout을self._awake_ms로 다시 걸고self.unlock()(신설 필드_awake_ms·재진입 금지_resuming). 폰 모는 코드는 전부_sh를 지나므로 도구마다 안 넣어도 된다. 자체검사 =python phone.py selftest(양보 True→잠금해제 1회 · 양보 없음→0회 ·awake블록 밖→0회). ⚠_sh안에서unlock()을 부르면 다시_sh로 들어온다 →_resuming가드 없으면 무한재귀. - ⚠(2026-09-14) [코디] watcher 데몬 재기동 스크립트는 «파일명 자체»가
watcher.py를 포함하면 안 된다. 「python -c로 쓰지 말고 파일로 분리」(26.8.14 규칙)를 지켜restart_watcher.py로 만들었는데,'watcher.py' in cmdline이restart_watcher.py에도 걸려 그 스크립트를 띄운 부모 bash 를 죽였다(Claude Bash 도구가 exit 15 로 실패 보고 — 정작 재기동 자체는 성공). ⛒대상 선별은cmdlinesubstr 말고sgc\watcher.py처럼 경로째로 보거나, 자기 pid + 조상 사슬을 후보에서 뺀다(tooling.md「--skip-if-running가드」와 같은 뿌리). 🔑겸사 확립 = 재기동 전에data/phone.lock이 풀렸는지 확인하고 죽인다(폰 UI 조작 중에 죽이면 카톡이 어중간한 화면에 남아 다음open_room이 죽는다). - 🔴(2026-09-14) [코디] 장애 티켓의 「실패 시점 폰 화면」은 실패 시점이 아니다 —
awake()가 끝나며 폰을 재운 뒤 덤프라 항상 잠금화면이다. INC-002 가 그 잠금화면 라벨(오후5:31, 5, :, 31, 9월 9일 수요일)을 근거로 「방 이름이 바뀌었다/봇이 나갔다」로 자동분석했고, 실제로는 방이 그대로 있었다(9/9 16:34 채팅목록 스냅샷에도 있고 지금open_room도 성공) — 오진 하나로 5일 무갱신. ⛒실패 화면은 화면이 켜져 있는 실패 지점에서 찍는다 =phone.open_room이room not found직전에_fail_openroom.png/.txt(activity·focused pkg·노드 라벨) 저장(26.9.14 추가). ⚠진단 산출물은 신선도 검사 필수 — INC-002 는 3주 묵은_fail_edit.png(8/24)를 「남은 진단 산출물」로 달아 놨다 →watcher.open_incident가 이제 10분 이내 파일만 싣는다. ⚠파일을 열고 나서 내용을 모으면 중간에 adb 가 죽을 때 0바이트가 남아 직전 증거까지 지운다(셀프테스트가 잡았다) → 본문 먼저 만들고 연다. - (2026-09-14) [코디] 🔴
phone.py의phone_lock은 재진입 불가 —Phone.send/send_long/send_file이awake()안에서 스스로 잡는다. 호출 스크립트가 바깥에서with phone_lock(...)로 한 번 더 감싸면 자기 자신을 420초 기다리다 「폰이 다른 작업에 잡혀 있다」로 죽는다(26.9.14 실측). ⛒호출부는 락 없이P = Phone(); P.connect(); P.send_long(...)만. 재사용 예 =C:\dev\_work\upseong\send_kakao.py(텍스트 + 파일 발송, 파일은send_file(room, path, caption)). - 🔑(2026-09-14) PC 카톡에서 «페페 카톡에 온 파일» 회수 = 미니PC PC 카톡(delix0731 세션 · Bash 가 Session 1 콘솔이라 GUI 직접 조작 가능) · [코디]: ①
kakao_pc_send.main_win()(win32 · 트레이 숨김도 잡음 —collect_all.main_win()UIA 는 「메인창 없음」으로 죽는다) → 검색 → 행 열어 제목에 이름이 들어가면 채택(1:1 방 제목은 저장된 이름 그대로 = 「당근Ai 조수은(해달)」) ②본문 =collect_all.export_text(auto.ControlFromHandle(h), txt)③파일 = 말풍선 「다른 이름으로 저장」 링크를kps.click→#32770저장 대화상자를 export_text 와 같은 UIA 로 경로 주입(성공 4.1MB). ⚠방 내 검색(돋보기)은 WM_CHAR/WM_KEYDOWN Enter 로 점프가 안 된다(검색어만 들어감) ·mouse_event휠도 무시 → 옛 메시지는 서랍(파일 탭) 경로로 가야 한다(미구현). 도구 =C:\dev\_work\ax-biz\kakao_grab_room.py·kakao_get_files.py(shot/click/find). - 🔴(2026-09-08) 한 번도 말 안 한 1:1 방은 채팅목록에 없다 →
P.open_room이 영영 못 찾는다. 친구는 있고 대화 이력만 없는 상대(예: 「라크리스(알피) 심재봉 대표」)는 방이 첫 발송 뒤에야 목록에 등재된다. 프로필에서 「1:1 채팅」으로 방을 열어만 놔도 안 뜬다(실측 = 열고 나온 뒤open_room재실패). ⛒첫 발송 경로 = 검색 → 친구행 → 프로필 → 「1:1 채팅」 →P._send_in_room(text)._send_in_room은P.send가 쓰는 그 검증 경로(입력칸이 비었는지까지 확인)라 그대로 재사용한다. 구현 =C:\dev\tools\reminders\simjaebong.py_open_via_profile()— 빠른 길(open_room) 먼저, 실패하면 프로필. - 🔴(2026-09-08) uiautomator 덤프는 화면보다 늦다 — 한 번 뜨고 「없다」고 단정하면 그날 작업이 죽는다.
카톡 검색 결과가 스크린샷에는 멀쩡히 보이는데 같은 시점 덤프엔
input_focus(0폭 더미 EditText) 하나뿐이었다 (같은 코드가 앞선 실행에선 성공 = 재현성 없는 레이스). ⛒노드 조회는 재시도 루프로 감싼다 (_wait_node(pred, tries=6, gap=1.5)). 카톡 검색 입력칸도 노드로는 못 고른다 — 상단 검색바를 좌표(350,168) 직접 탭. - ⚠(2026-09-08) 노트20 카톡 = poin3133(공용) 계정, 방 17개뿐이다. 페페 계정(delix0731)의 거래처 1:1 방은
여기 없다 —
talklog\data\mobile\kakao_dirty.json에 이름이 보인다고 노트20에 있는 게 아니다(그건 페페 S25 수집분). 발송 전python rooms.py list --device note20으로 실제 목록을 확인한다. 미니PC PC카톡도 같은 poin3133 계정이다. - ⚠(2026-09-08) adb
am start인자에 괄호가 들어가면 기기 셸이 죽는다 —syntax error: unexpected '('. 한글·공백·괄호가 든 값은 작은따옴표로 감싸서 한 인자로 넘긴다("'%s'" % NAME). 연락처 중복 확인은 저장형식이 제각각이라(010-4002-3200vs01040023200) 하이픈 유무 둘 다 훑어야 한다 — 안 그러면 중복을 만든다(실측 1건, 삭제함). - 🔴(2026-09-08)
phone.py를 스크립트로 부를 땐phone_lock을 직접 잡지 마라 — 자기 락에 걸려 교착한다.P.awake()가 이미phone_lock을 잡는다. 바깥에서 한 번 더 잡으면 같은 프로세스인데도msvcrt.locking이 핸들 단위라 자기 자신을 막는다 → 420초 대기 후 예외(출력은 파이프 버퍼에 갇혀 아무것도 안 보인다, 「멈춘 것처럼」 보이는 게 증상). 처방 = 스크립트는with P.awake():만 쓴다. - ⚠(2026-09-08) 카톡 파일 첨부 내려받기 = 말풍선 「길게 누르기 → 내 파일에 저장」. 그냥 탭하면 zip 은
열 앱이 없어 아무 일도 안 일어난다. 저장 위치 =
/sdcard/Download/KakaoTalk/<원본파일명>(147MB 가 약 1분). PC 로 가져오기 =adb pull(한글 경로라MSYS_NO_PATHCONV=1필요). 발송은phone.py sendfile "신동승" <path> "캡션". - 🔴(2026-09-07) 게시글 길이 상한은 고정값이면 안 된다 — 자라는 방을 차례로 죽인다(INC-001, 4일 정지).
watcher.interpret의300 < len(out) < 6000에서 상한 6,000자가 범인이었다. 향남 방이 6,071→6,371자를 찍자 「형식 불량」으로 2회 연속 실패 → 전 방 게시 정지(26.9.3 15:35 ~ 26.9.7 10:10). 🔑로그가 이미 답을 말하고 있었다 —섹션누락=[]+ 첫 줄 정상 = 구조는 멀쩡, 길다는 이유 하나. 🔴향남만의 문제가 아니었다(실측): 게시글 최대 길이 = ivision 5,781자 · 향남 5,671 · 금강에코 4,923 — 큰 방 3개가 전부 상한 턱밑이었다. 향남이 먼저 걸렸을 뿐 나머지도 며칠 뒤 순서였다. ⛒처방 = 상한을 「직전 게시글 × 2」(하한 6,000) 로. 게시글이 자라면 상한도 자라고, 폭주(2배 초과)는 그대로 잡는다. ⚠하한 300 은 건드리지 않는다 — 61·171·288자 잘림을 실제로 잡은 값이다(형식불량 이력의 태반이 짧은 쪽). 회귀 =test_watcher_rules.py「길이상한 동적(직전×2)」(6,000자 넘긴 방을 재현해 성장 통과·폭주 거부 양방향). ⚠고친 뒤resume만으론 안 산다 — 상주(HKCU RunPoinAgent-BoardWatch, pythonw)를 재시작해야 새 코드가 먹는다. ⚠스테이징(pfs 8002, 26.9.4 신설)은 무관하다 — 사고가 그보다 하루 먼저(9.3) 났고,pfs_login.env의PFS_PROD_URL=https://pfs.poin.co.kr/PFS_TEST_URL=…:8001둘 다 8002 를 안 본다(실측). - 🆕(2026-09-02) 카톡 계정 전환은 트레이 아이콘으로 한다 —
C:\dev\tools\kakao-switch\tray.py(pystray, pythonw 상주, HKCU RunKakaoSwitchTray자동시작). 우클릭 →delix0731/poin3133라디오 선택. 엔진은 새로 안 짰다 —poin-agent\kakao_pc_login.py의restart_to_login()+login_with()를 그대로 부른다. 🔑현재 로그인 계정 판별 =%LOCALAPPDATA%\Kakao\KakaoTalk\users\last_pc_login.dat(형식1|<id>|<토큰>— 3번째가 인증 토큰이라 통째로 로그·화면에 내보내지 말고 메일주소만 정규식으로 뽑는다). 옆 파일login_list.dat는 MRU 목록이라 순서가 뒤집혀 현재 계정과 어긋난다(26.9.2 실측). ⛒taskkill /F뒤 고정 3초 sleep 은 부족하다 — 아직 정리 중인 이전 인스턴스와 겹치면 새로 띄운 카톡이 조용히 자살해 「로그인 창이 안 떴다」로 40초 만에 실패한다(프로세스 0개가 증거). 처방 =_kakao_pids()로 소멸을 폴링(최대 20초)+1.5초 여유, 그래도 안 뜨면 Popen 1회 재시도 —kakao_pc_login.py에 반영 완료. ⚠tasklist출력은 cp949 라text=True면 UnicodeDecodeError. 실측 = 로그인된 상태에서 반대 계정으로 왕복 전환 10초, 2단계 인증 안 뜸. - 🆕(2026-08-31) PFS 완료 → 게시글 자동 반영은 배관을 새로 깔지 않는다. 판정부(
pfs_done.py)만 만들고 반영은 기존kakao_board_op큐를 탄다. 애매 건 =state='제안'— 데몬이 가져가는 건'대기'뿐이라 승인 전엔 고객 글 무접촉이고 스키마 변경도 0이다. 함정 둘 = ⛒원장(pfs_done_seen)은 PFS 호스트별로 갈라야 한다 — 운영·테스트가 한 파일을 쓰면 테스트로 한 번 돌린 순간 다음 운영 회차에 완료분 전량이 신규로 잡힌다(26.8.31 실측 51건, 「최초 1회 마킹」 방어가 통째로 무력화). ⛒「확실」이어도 자재명이 행 본문에 없으면 자동 실행 금지 — LLM 확신만 믿으면 별칭·복수품목에서 오탐이 나고, 오탐 = 고객 글에서 줄이 조용히 사라지는 사고다. 섀도 스위치 =pfs_done_auto.on파일(데몬 상주라 env 는 재시작해야 먹는다). 현장 완료(30)·완료 취소는 알림만. - 🔴(2026-08-31) 카톡 알림에 방 이름이 더는 없다 — 26.8.14 이후 만든 방은 전부 무음 유실이었다. 실측(
adb shell dumpsys notification --noredact) =android.subText=null이고android.conversationTitle은 키 자체가 없다(있는 건android.isGroupConversation뿐).phone.route()는 sub 가 살아 있던 이벤트로 배운_roomid_map.json에만 기대므로 새 방은 배울 기회가 영영 없다(「에넥스포인 금호 구미」 26.8.31 대화 10건 · 「에넥스-포인 대우 용인」 은 8/14 이후 귀머거리). ⛒처방 =watcher.resolve_unrouted()— 못 받은 메시지 원문을 폰 채팅목록 행의 마지막 메시지 미리보기(rooms.py스냅샷desc) 와 대조해 채팅방 id↔이름을 확정한다. 후보가 1개일 때만 묶는다(0개·2개 이상은unrouted_ambiguous로 남기고 건너뛴다 — 잘못 묶으면 남의 현장 게시글에 섞인다). 스냅샷은 30분에 1회만(매 루프 훑으면 폰이 종일 스크롤). 겸사겸사 스냅샷이 새로 떠서 devplan 카톡관리 목록에도 그 방이 올라온다. 🔑리스너 APK 는 못 고친다 — 알림에 이름이 아예 없어서 소스를 고칠 대상이 없다.* - 🔴(2026-08-31) 「그 이름의 방이 폰 목록에 있다」로 1:1 이라 단정하지 마라. 방 이름이 없는 알림은
room칸에 발신자가 들어오는데, 그게 마침 1:1 방도 가진 사람이면(신동승) 단톡 대화가 그 사람 폴더로 조용히 샌다(실측 = 금호 구미 4건이_collect/신동승으로, 8/12 아이비젼 8건도 같은 자리). ⛒cb()는sub가 있거나 채팅방 id 로 되찾은 이벤트만 방 폴더에 적재하고,handle_no_room의 캡처 전달(queue_dm)도 id 가 1:1 로 확인된 것만 한다. 나머지는_unrouted.jsonl로 → 다음 루프가 되찾는다. - 🔑(2026-08-31)
first_post는 board.md 가 빈 스켈레톤이면 백로그를 소비하면 안 된다. 원래 「초안은 이미 그 대화를 반영해 쓴 것」이라는 전제로 inbox 를 통째로processed_lines처리하는데, devplan 카톡관리에서 「게시글 수정」을 켜 자동 생성된 초안은 빈 스켈레톤이라 그때까지 쌓인 대화가 한 줄도 안 올라간 채 사라진다. ⛒board_rows.parse(board)가 0행이면 백로그 유지 → v1(스켈레톤) 게시 뒤 다음 슬롯이 v2 로 반영한다. - 🔑(2026-08-31) 수집만 켠 방도 PFS 카톡관리에 올린다(읽기전용). 전엔
state.json+board.md있는 방만 미러돼서, 새 현장 단톡방을 PFS 현장에 이어 두려면 「게시글 수정」을 켤 수밖에 없었고 그러면 고객 방에 출고일정 글이 실제로 올라갔다.pfs_board_sync.collect_rooms()가kakao-rules의watch켜진 방을editable=False·_dir=None으로 같이 보낸다(_proj_of가 None 을 걸러 행 편집 명령 대상에서 빠진다). 연결과 게시를 갈랐다. - 🔴(2026-08-27) 「예정시각까지 대기」 함수에 「이미 지났으면 즉시 통과」를 넣지 마라 — 한밤중에 거래처로 나갈 뻔했다.
--at=08:00을 23:08 에 실수로 실행했더니 「오늘 08:00 은 지났다」로 대기 0초가 돼 곧바로 발송 경로로 들어갔다(사무실PC 방확인 단계에서 손으로 죽여 실발송 0건). 처방 =LATE_GRACE_MIN=30— 예약작업이 밀린 정도(30분)까지만 즉시 진행하고 그 이상 지났으면 발송하지 않고 예외. 🔑같은 함정이 「지난 시각 크론」·「밀린 배치」 전부에 있다. 회귀 =_wait_until('08:00')이 낮/밤에 각각 통과·예외. - 🔴(2026-08-27) 자격증명을 담은 job/설정 dict 를 로그에 통째로 찍지 마라.
orderpaper_runner가log("start job=%s" % json.dumps(job))로 카톡 비밀번호를 사무실PCrunner.log에 평문으로 남겼다. 처방 = 로깅 전에pw|password|token키를***로 치환 + 이미 찍힌 줄은 즉시 세척(정규식 치환 후findstr로 잔존 0 확인). 자격증명은 일회성 job.json 으로 넘기고 읽자마자 파일을 덮어쓴다(~~사무실PC 에kakao_login.env사본을 두지 않는다 — 비밀 단일출처 = 미니PCC:\dev\.secrets~~). - 🆕26.10.8 [페페] 결정 A — 카톡 전환 트레이용으로 사무실PC 사본 허용(ACL 제한): 사무실PC
C:\dev\.secrets\kakao_login.env= poinpc·Administrators·SYSTEM 만(icacls /inheritance:r). 정본은 여전히 미니PC — 비번이 바뀌면 사무실 사본도 같이 갱신(MD5 대조). 로그 세척 규칙(위)은 그대로. - ⚠(2026-08-27)
should_prevent_auto_login_once=yes로 카톡 계정 전환은 사무실PC에선 안 먹는다. 미니PC(카톡 구버전)에선 되는데 사무실PC(settings_version 25.4.0)는 플래그를 무시하고 그대로 자동 로그인한다. 게다가 자동시작이라 창이 트레이로 숨어서 뜨므로IsWindowVisible을 조건에 넣은 로그인창 탐색은 영영 실패한다(「로그인 창이 안 떴다」). 로그인 창 판별은OnlineMainView_*자식 유무로 한다(메인 창엔 있고 로그인 창엔 없다 — 둘 다 제목이 「카카오톡」이고 Edit 를 갖는다). 결론 = 사무실PC 카톡 계정 전환은 사람이 1회 수동 로그인해야 한다(코디 자동화 불가). - ⚠(2026-08-27) 같은 발주서 파일 안에서도 양식이 다르다 — 셀 주소를 박으면 깨진다. 현장명이 발주서 탭(데코밸리·피앤알)은 B27, 오엠씨(원자재) 탭은 B29. →
by_label()로 A열 라벨(「수 신」·「참 조」·「현장명」, 공백 제거 비교)을 찾아 그 행에서 읽는다. 인쇄범위도 마지막 값 있는 행으로 계산(오엠씨=31행, 발주서=29행). - 📤(2026-08-27) 발주서 카톡 발송 도구 신설 — PC 카톡 조작 함정 4개는
kakao_pc_send.py가 단일 출처다. 원부자재발주서 xlsx 업체 탭 → PNG → 담당자 방에 사진+문구(orderpaper_kakao.py). ①비활성 창에 더블클릭하면 첫 클릭이 활성화에 먹혀 남은 한 번이 단일 클릭이 된다 → 첫 방만 열리고 두 번째부터 계속 「방을 못 찾았다」(검색 결과는 화면에 멀쩡히 보여서 더 헷갈린다). 처방 =front()가 제목표시줄 빈 곳(150,10)을 실제로 클릭해 활성화까지 끝낸 뒤 더블클릭. ②트레이에 숨은 창은SW_RESTORE로 안 나온다 →SW_SHOW먼저(검색어 입력은 PostMessage 라 숨은 창에도 들어가서 「되는 것처럼」 보인다 — 사무실PC 에서만 재현). ③Enter 는 방 창이 진짜 포그라운드일 때만 먹는다, 그리고 화면의 「전송」 버튼 자리는RICHEDIT50W가 덮고 있어 클릭이 리치에디트로 간다 → 입력칸을 실제로 클릭한 직후에만 Enter. ④검색 1위가 대상이라는 보장이 없다 — 카톡은 대화 내용·멤버 이름으로도 매칭한다(실측: 「신동승」 1위가 「포인-월드」 단톡방) → 정확한 방 이름으로 검색하고 열린 창 제목이 다르면 닫고 중단. 사진은Ctrl+V→ 제목 없는 「클립보드 이미지 전송」 창(방 창과 구분이 안 되니 붙여넣기 직전 창 스냅샷과의 차집합으로 찾는다) → 캡션 비우고(50자·줄바꿈 불가) 하단 「전송」. 방 이름 규칙 =업체 이름 직책(발주서 C2·C3·B27 에서 추출, 실측 「데코밸리 김남부 차장」·「피앤알 남태욱 상무」와 일치). 계획 = devplanorderpaper-kakao.html. - 🔴(2026-08-27) 사무실PC(POINIMOS01)에서 Excel COM 이 안 돈다 — Office 제품 인증 실패다.
Workbooks접근이RPC_E_CALL_REJECTED(피호출자가 호출을 거부했습니다)로 계속 거부되고, 원인은 화면에 떠 있는Microsoft Office 인증 마법사모달(Excel 창 제목 =월드 스티커 출력.xlsm - Excel (제품 인증 실패)). 좀비 EXCEL 프로세스 2개(09:25·10:52 기동, 창 없음)도 같은 원인. 🔑진단은 Session 1 예약작업에서 창을 전부 캡처해야 보인다 —Visible=False라 모달이 안 보이고, SSH(Session 0)에선 애초에 그 데스크톱을 못 본다. 처방(현재) = 렌더는 미니PC, 발송만 사무실PC로 쪼갠다. ⚠Excel 은DispatchEx로 연다 —Dispatch면 페페가 열어둔 Excel 에 붙어Visible=False로 그 창을 숨기려 들고 예외까지 난다. - 🔑(2026-08-27) PC 카톡은 계정 하나가 PC 한 대에만 붙는다 — 어디에 로그인하느냐가 곧 「어느 PC 가 발송기냐」다. 실측 = 미니PC = delix0731(페페) 로 로그인돼 있고 거래처 1:1 방(「데코밸리 김남부 차장」·「피앤알 남태욱 상무」)이 다 있다. 사무실PC = 채팅방 0개인 다른 계정(등록 이력
delix0731+4220339@naver.com) → 그 상태로는 방 탐색이 무조건 실패한다. 즉 지금 당장 거래처 실발송이 가능한 건 미니PC 뿐이고, 사무실PC 를 주 발송기로 쓰려면 거기서 delix0731 로 로그인해야 하는데 그러면 미니PC 세션이 밀려난다(26.8.12 항목의 반대 방향). 코디 SSH 는 Session 0 라 사무실PC GUI 를 못 만지므로/IT예약작업\Cody\OrderpaperKakao+job.json이 유일한 통로다(인자를 못 넘긴다). 발송 중엔 그 PC 의 마우스·포그라운드를 수십 초 점유한다. - 🏷(2026-08-25) 거래처 「넥서스」 → 「한샘」 개명. 단 카톡방 이름·과거 게시글은 안 바꾼다.
kakao_room.room_name·kakao_board_op.room_name(예: 「넥서스포인 SGC 용두동」)은 실제 방 이름이라 게시글 자동갱신의 매칭키다 — 바꾸면 갱신이 끊긴다. 게시글 본문의 과거 발화 기록(「넥서스 김선정 과장」 등)도 그 시점 사실이라 유지. 새로 쓰는 글에서만 「한샘」*. 규칙 원문 =projects/pfs/rules.md🆕 「거래처 개명」. - (2026-08-24) 🔴 게시글 갱신이 연속 2회 실패하면 데몬이 스스로 멈추고 CLI 코디가 원인·해결안만 뽑아 텔레그램으로 보낸다 — 자동 복구는 안 한다(페페 지시). 흐름 =
process()예외 연속 2회(1회는 덤프충돌 같은 단발이 흔해 재시도) →halt.json먼저 쓰고(분석에 수 분 걸리는 사이 다음 주기가 돌면 안 된다) →claude -p로 원인 1줄+해결안 →incidents/INC-###.md저장 → 텔레그램에 번호. 페페는 새 세션에INC-042번호만 주고, 그 파일에 오류·traceback·폰 화면·runs·소스조각·재개방법이 다 들어 있다. 재개는 사람이 고친 뒤watcher.py resume— 자동 재개 없다. ⚠중단은 방별이 아니라 전 방(페페 결정) — 이번처럼 원인이phone.py공통 경로면 방마다 걸려 텔레그램이 6통 오고 같은 실패를 6번 반복한다. ⚠멈추는 건 폰 게시만 — 수집(listener)·PFS 미러·화면끄기는 계속 돌아 백로그가 쌓이고 재개하면 한 번에 반영된다. ⚠분석 claude 는 리포 밖(%TEMP%) 에서 돌린다(CLAUDE.md 꼬리표 혼입 차단, 26.8.14 교훈) → 소스를 못 읽으므로 traceback 이 가리키는 파일의 그 줄 ±15줄만 프롬프트로 넘긴다(_src_around). ⚠테스트에서HALT/INCIDENTS/AGENT_ROOT를 임시폴더로 갈아끼우지 않으면 자체검사가 운영 데몬을 멈춘다. 전역 진입 =C:\dev\CLAUDE.md§3 「INC-### 만 오면」 1줄. 회귀 =test_watcher_rules.py「장애 티켓·중단·재개」. - (2026-08-24) ✅ 위 고착의 조치 = 「탈출」을 화면마다 두지 않고
P.force_chat_list()한 곳에 모았다 — 런처 인텐트 +--activity-clear-top. 확인창 라벨(「글 수정을 취소하시겠습니까?」/아니요·예)을 실측했지만 '예'를 누르는 방식은 안 쓴다 — 같은 코드가 언젠가 「방 나가기」·「삭제」 확인창을 누른다(board_edit 블랙리스트와 같은 이유).am start -a MAIN -c LAUNCHER -p com.kakao.talk --activity-clear-top은 어떤 화면이 떠 있든 위 액티비티를 통째로 끝낸다(실측: PostEditActivity+확인창 → 채팅목록 1회). ⚠-n com.kakao.talk/.activity.main.MainActivity직접 지정은 not exported 라 SecurityException — 런처 인텐트로만 간다. 부착 지점 2곳 =to_chat_list()BACK 루프 실패 시 반환값,open_room()이 채팅탭을 못 찾았을 때(=앞 실행이 고착시켜 놓고 넘어온 경우 다음 실행이 스스로 푼다). 회귀 =phone.py selftest「BACK 핑퐁」. - (2026-08-24) 🔴🔴 진범 = uiautomator 덤프 파서다 — 값에 큰따옴표가 하나라도 있으면 그 속성만 작은따옴표로 감싸는데,
_nodes()는 큰따옴표만 봤다. 카톡 대화의발주코드 "다솜 60-32"가 게시글 본문에 실린 순간부터 갱신이 4주기 연속새 본문 입력 실패로 죽었다. 본문은 매번 정상적으로 다 들어가 있었다(실패 스크린샷 4,668자 확인) —text=매치가 실패해 빈 문자열이 되고 호출부가 「글자가 안 들어갔다」로 오진한 것뿐이다. 기전 =KXmlSerializer.attribute()의value.indexOf('"') == -1 ? '"' : '\''(덤프에"0개,text='…"다솜 60-32"…'). 조치 =_nodes()의a()에 작은따옴표 폴백 1줄(re.search(name+'="([^"]*)"') or re.search(name+"='([^']*)'")). ⚠노드 경계<node[^>]*>는 안전 —<·>·&는 실제로 엔티티 이스케이프된다(따옴표만 예외). 🔑_nodes()는 모든 카톡 화면 읽기의 공통 관문이라 방 목록 행·메시지 본문·툴바 제목도 같은 오진이 나고 있었다 — 한 곳을 고치면 전부 낫는다. 검증 = 실패했던 덤프 원본 재파싱 4,668자(시도 본문과 일치) +phone.py selftest회귀. ⚠폐기된 가설 4개(같은 길 두 번 가지 마라) = 길이 절벽(b64 31,072까지 OK·실패본이 성공본보다 작았다) · 클리어 직후 commitText 무효 · 클리어와 입력 사이 덤프 · pythonw 환경(콘솔 python 에서도 동일 재현). - (2026-08-24) 🟡
adb_ime()의prev가 ADBKeyboard 면 그대로 되돌리면 안 된다 — 한 번 어긋나면 영구 고착이다(위 입력 실패의 원인은 아니었다 — 부수 피해였다). 앞 실행이 복구 못 하고 죽으면 다음 실행의settings get default_input_method가 이미 ADBKeyboard → finally 가 그걸 되돌려 계속 ADBKeyboard(페페가 폰 들면 한글 못 침 — 26.8.24 실제로 40분 넘게 그 상태였다). 조치 =prev == ADB_IME면SAMSUNG_IME로 강제(+삼성으로 한 번 내렸다 올려 재바인딩) + 복구 후 읽어서 확인·1회 재시도.awake()의screen_off_timeout상한과 완전히 같은 함정·같은 처방 — 「이전 값 복원」 패턴은 항상 이전 실행이 죽은 경우를 가정한다. 회귀 =phone.py selftest「IME 복구」(시작값 ADB/삼성 둘 다). - (2026-08-24) 🔴 실패 문구가 원인을 못 가리키면 다음 사고 때 또 몇 시간 태운다 — 검사에
if node and …를 쓰면 「노드가 없다」가 조용히 통과한다.board_edit의 클리어 검사가if edit_box and …라 content_edit 이 덤프에서 사라진 경우를 클리어 성공으로 넘겼고, 바로 다음 검사에서 같은 None 이 「새 본문 입력 실패」로 튀었다 → 화면 문제인지 입력 문제인지 구분 불가. 조치 = 노드 없음을 별도 예외로 분리 +type_text()의 브로드캐스트 결과를 실패 메시지에 싣는다(이 한 줄이result=0를 드러내 진단을 열었다). - (2026-08-24) 🔴 폰 UI 작업은 실패 경로에 「탈출」이 없으면 1회 실패가 영구 실패가 된다 — 금강 에코 게시글 갱신이 그렇게 43분+ 고착됐다.
board_edit.edit()은 성공 경로에서만 BACK×3+home 을 하고 예외는 편집기(PostEditActivity)를 열어둔 채 올라간다. 뒤이은awake()→to_chat_list()는 BACK 만 4번 누르는데 편집기 BACK 은 「나가기 확인」 대화상자를 띄우고 다음 BACK 이 그 대화상자를 닫는 핑퐁이라 목록에 영영 못 간다 → 다음 주기open_room()도 같은 이유로room not found in chat list. 화면을 여는 함수는 예외 경로에도 닫는 코드를 둔다(try/finally), BACK 만으로 화면을 벗어난다고 가정하지 않는다(확인 대화상자 라벨을 눌러야 하는 화면이 있다). 부수 = 실패 시 스크린샷이 없어 사후 진단이 불가했고(type_text()는 브로드캐스트 결과도 버린다), IME 가 ADBKeyboard 로 남아 페페가 폰을 잡으면 한글을 못 친다. 근거 =projects/poin-agent/handoff.md26.8.24 16:50 NOW. 🔧정정(같은 날 17:40): 이 건의 1차 도미노는 입력 실패가 아니라 덤프 파서 오진이었다 — uiautomator 는 값에"가 들어간 속성만 작은따옴표로 감싸는데_nodes()가 큰따옴표만 봐서text=""로 읽었다(수정 = 작은따옴표 폴백, dev-0a). 같은 사본이collect_cartypes.py:24·freight_app.py:70·s25.py:33에 미수정으로 남아 있다. 위 「탈출 부재」 규칙 자체는 별개 결함이라 그대로 유효. - (2026-08-23) 🔴 카톡 첨부 메뉴는 세로 스크롤 리스트다 — 「파일」은 접힌 시트 아래라 제자리 재덤프로는 영영 안 나온다. 실측(카톡 26.8 · note20 1080×2400) =
media_send_layout을 눌러도 보이는 건 사진·통화·선물하기·송금까지고, 지도·친구위치는 노드가(0,0)으로만 뜬다(레이아웃 안 됨).파일은 스와이프 1회 뒤(540,1868)에 나온다 — 그 뒤로 연락처·음성메시지·예약메시지·캡처가 더 있다._tap_label()이 6회 재덤프만 하고 스크롤을 안 해서send_file이RuntimeError: 화면에 '파일' 없음으로 죽었다(fresh 재시도 2회 다 실패 = 좌표캐시 문제가 아니다). ⚠전체화면 보기(handle_container) 탭은 효과 없다 — 눌러도 덤프가 한 글자도 안 바뀐다(시도했다가 버림). 조치 =_tap_label실패 회차마다swipe(w/2, h*0.88 → h*0.62, 400ms)+sleep(1.0)(스크롤이 멈춰야 다음 덤프가 갱신된다). 첨부 경로 5개 라벨(파일·파일에서 선택·내 파일·다운로드·완료)이 전부 이 한 함수를 지나므로 어느 화면이 잘려도 같이 낫는다. 검증 =phone.py sendfile 신동승 <mp4>→ 52.5초 성공. ⚠캡션은 첨부 전에 나가므로, 첨부에서 죽으면 페페 폰엔 캡션만 남는다 → 재시도 땐 캡션을 빼야 중복이 안 생긴다. - (2026-08-21) 🔴 게시글 행 id 에 「바뀌는 값」을 넣지 마라 — 섹션 건수가 들어 있어서 일괄 숨김이 섹션당 첫 건만 반영됐다.
board_rows._ids가sha1(섹션헤더 \x00 첫줄 \x00 등장순번)인데 섹션헤더가■ 미출고 (8건)통째였다. 행 하나를 숨기면_recount가 건수를 다시 쓰므로 같은 섹션 나머지 행의 id 가 전부 바뀐다 → PFS 카톡관리에서 여러 줄 체크 후 「저장」하면 데몬이 첫 건만 적용하고 나머지는KeyError= 화면엔 「반영 실패」로만 뜬다. 운영 실측 33건(SGC 28·오엠씨 4·향남 1), 전부완료·취소였다. 🔑단서 = 「삭제」는 100% 성공했다 — 소프트딜리트 대상인■ 변동 반영 이력·■ 일정 · 공지는 헤더에(N건)이 없어 id 가 안 흔들린다. 조치 = 섹션은 제목만 해싱(_title(sec)), 회귀검사 = 같은 섹션 3행 연속 숨김(board_rows.py자체검사, 옛 코드면 KeyError 로 잡힌다). 커밋87f01e4. ⚠고치면 전 행 id 가 한 번 바뀐다 → 데몬board_rows.py수정 → watcher 재시작(상주 import) →pfs_board_sync.py로 미러 먼저 밀고 나서 명령을 등록한다. ⚠실패한 옛 명령은 row_id 가 이미 죽어 재시도가 불가능하다 →(N건)만 0~99 로 갈아끼우며 현재 board.md 행과 sha1 대조하면 옛 id→현재 행으로 역매핑된다(33건 중 32건 복구, 1건은 이미 숨김 처리됨). 해소한 실패행은 지우지 말고kakao_board_op.state='재등록'으로 내린다(select_failed_ops가'실패'만 보므로 카드가 걷히고 이력은 남는다). - (2026-08-19) 🔴 코디는 고객 게시글에 존재하지 않는다 — 이름도, 코디가 한 작업도 안 적는다(페페 지시). 코디의 존재를 나타낼 자리는 둘째 줄
수정: … (포인 공용폰)과 맨 아래 안내문 두 곳뿐이고, 그 밖에는 「코디」라는 말도 「게시글 정리·개설·구조 재작성」 같은 코디의 작업 내용도 게시글 어디에도 못 쓴다(특히■ 변동 반영 이력). 이력은 방 대화에서 사람이 말한 변동만 적는다. 실측 = 6개 방 게시글 전부에· 08/14 11:50 [코디] 게시글 정리 — …7줄이 고객 방 톡게시판에 게시돼 있었다(향남 방에서 페페가 발견). 원인 2개 = ①REBUILD_PROMPT3번이 대놓고"· MM/DD HH:MM [코디] 게시글 구조 재작성 → 반영" 한 줄을 남긴다고 시켰다 ②갱신 프롬프트엔 금지 규칙이 없어 모델이 자기 작업을 이력에 적는 걸 안 막았다. 조치 = 두 프롬프트에 금지 규칙(4-4·7-1) + 마지막 관문_strip_agent()= 이력 줄의 화자 태그가 사람이 아니면(코디|클로드|Claude|AI|에이전트|봇|포인 공용폰) 그 줄을 통째로 버린다(_strip_report와 같은 자리·같은 교훈 — 프롬프트 규칙만으론 안 막힌다). 화자 태그만 보므로 본문 사실은 안 지운다. 데이터는 6방 board.md 에서 7줄 제거 후 데몬push_web_edits로 폰 게시글 전량 재게시(v31/v45/v19/v17/v10/v3) + PFS 미러 재동기화. 회귀 =sgc/test_watcher_rules.py「코디 흔적 제거」. 🔑발생원은 watcher 말고 하나 더 있었다 =devplan/app.py의_KBOARD_SKEL(새 방 「게시글 수정」을 켜면 만드는 스켈레톤)이· MM/DD HH:MM [코디] 게시글 개설 — …을 박아 넣어 새 방마다 위반이 태어났다(에넥스 대우 용인 v1 이 그 산물). 이력 줄 삭제 +test_kakao_newproject.py에"코디" not in board회귀 + devplan 재시작. ⚠게시글 문구는 두 리포에 흩어져 있다(poin-agent 프롬프트 · devplan 스켈레톤) — 게시글 규칙을 고칠 땐 양쪽 다 본다. ⚠history/*.md는 당시 게시된 원문 그대로 두었다(로컬 감사기록 · 재게시 경로 없음). - (2026-08-14) 🔴 헤드리스
claude -p를C:\dev안에서 돌리면C:\dev\CLAUDE.md(코디 전역 지침)가 딸려 들어가 「답변 꼬리표」가 고객 게시글에 그대로 실린다. 실측 = 아이비젼 v37~v39·오엠씨 v17 게시글 끝에---+시드: 갱신 없음 · 컨텍스트: … · 텔레그램: 발송함이 붙어 고객 방 톡게시판에 게시됐다(형식검사가 첫 줄·섹션·길이만 봐서 통과). 원인 =interpret()의cwd=proj_dir. 🔑게시글 재료는 전부 프롬프트로 주므로 작업폴더는 리포 밖이면 된다 →CLAUDE_CWD = %TEMP%/poin-agent-claude. 마지막 관문으로_strip_report()(안내문 「※ 이 게시글은」 뒤 전부 절단 +시드|컨텍스트|텔레그램|검증|다음|요약:줄부터 절단)를 둔다. ⚠리포 안에서 LLM 을 돌리는 모든 자리에 같은 함정 — 프롬프트에 「보고 문구 금지」를 적는 것만으로는 안 막힌다(지침 파일이 더 세다). - (2026-08-14) 게시글 구분선은 저장물이 아니라 렌더 결과다 —
board_rows.render()가 매번 전부 지우고 다시 그린다. 그룹(■ 섹션) 앞━×15, 그룹 안 현장 사이─×10(페페 지시 "그룹별 현장별 분리가 잘 안보인다"). 🔑저장하면 행을 지웠을 때 구분선만 남아 고아가 된다 → 위치를 계산으로 정하면 그런 상태가 아예 없다. 규칙 2개 = ①■ 변동 반영 이력엔 가는 선을 안 긋는다 ②여러 줄짜리 행의 앞뒤에만 긋는다(한 줄 목록까지 줄줄이 그으면 되레 안 보인다). ⚠_is_head()에서 구분선을 행에서 빼는 게 필수 — 안 빼면 devplan·PFS 카톡관리 목록에 구분선이 「행」으로 뜨고(N건)도 부풀고 편집 대상이 된다. claude 갱신본도render()를 한 번 통과시켜 규격을 맞춘다. - (2026-08-14) 「■ 견적」 = 한 건당 한 줄 · 핵심 3가지(현장명 — 견적 발송여부 / 금액)만. 페페 지시. 사양·품목·협의 경과는 견적에 안 쓴다 → 그 현장의 상세는 진행 상태에 맞는 섹션 한 곳에만 둔다(같은 현장이 미출고·견적 양쪽에 통째로 있던 게 「요약 충돌」의 정체였다 — 아이비젼 포항 환호공원). 금액 미확정도 행은 남기고
금액 미정. 같이 확립 = 이력에서 항목을 가리킬 땐 번호가 아니라 현장·품목명으로(항목이 다른 섹션으로 이관되면 번호가 밀려 옛 이력이 엉뚱한 항목을 가리킨다 — 오엠씨 실측). - (2026-08-14) 🔴 sub 결손 메시지는
_unrouted.jsonl에만 쌓이는 게 아니다 — 발신자에게 1:1 방이 있으면 그 방 inbox 로 조용히 샌다. 실측: 「롯데건설 화성 향남(포인)」(채팅방 id474079857497831) 대화가 서예진 사원 발 6건은_unrouted, 신동승 발 8건은_collect/신동승/inbox.jsonl로 갈라져 들어갔다(같은 대화가 두 곳에 반쪽씩 = unrouted 만 보면 절반을 놓친다). 🔑복구·점검은 언제나 알림 key 4번째 칸(채팅방 id)으로 전 inbox 전수 스캔 —glob('*/inbox.jsonl') + glob('_collect/*/inbox.jsonl')에서 rid 일치 줄을 뽑아 제 방으로 ts 순 병합하고(회수 줄은room·sub를 진짜 방 이름으로 교정해야phone.py roomids재학습에도 살아난다) 원본은.bak남기고 제거. 재발 방지 =data/rooms/_roomid_map.json에 id→방 매핑 1줄(이 방은 sub 가 온 적이 없어 자동 학습이 불가능했다 = 페페가 방 이름을 알려줘야 하는 유일한 경우). ⚠매핑 파일만 고치면 안 먹는다 —phone.roomid_map()은_ridmap전역 캐시라 watcher(pythonw 상시) 재시작까지가 한 작업. ⚠함정 = 데몬 죽이는 코드를python -c로 쓰면 자기 cmdline 에watcher.py문자열이 들어가 스스로 terminate 한다(exit 15, 출력 0) → 킬 스크립트는 파일로 분리하고p.info['pid'] == os.getpid()를 건너뛴다. - (2026-08-13) 통화 녹음 → 게시글 반영 경로 = 전사(ytmine STT) →
board.md한 번 쓰기 → watcher 30초 루프가 폰에 민다(코디가 폰을 직접 만지지 않는다). 실측 26.8.13 은지호 팀장 통화 5분31초 → 아이비젼 게시글 v36(push_web_edits→runs.jsonl {"action":"edited","note":"웹 행편집 반영"}+history/2026-08-13_1529_v36.md). 검증은 state.jsonversion·board_hash(=파일 raw 바이트 sha1, strip 후 해시와 다르다) + history 스냅샷 diff로 하고 폰을 다시 열어보지 마라(데몬과 경합). 전사 원문은<proj>/calls/<날짜>_<시각>_<상대>_<건명>.txt로 접어 보관하고 게시글엔 명사형 요약만(26.7.24 규칙). ⚠STT가 가구 용어를 흘린다(실측: 「지판스라」·「메리 푸시」·「걸레바지」) → 치수·자재명은 그대로 옮기지 말고 페페 확인 항목으로 표기. - (2026-08-12) 예약작업으로 돌리는
.cmd에 한글을 넣지 마라 — cp949로 깨져 「마지막 결과 0」인데 아무 일도 안 일어난다. 실측:echo === 상태 확인같은 한글 echo 한 줄 때문에 스크립트 전체가 죽어 로그 파일조차 안 생겼다(성공/실패 구분이 안 돼 20분 태웠다). 래퍼.cmd는 ASCII만, 한글 출력은 파이썬 쪽에서 한다(PYTHONUTF8=1). 같이: 작업 액션에.cmd를 직접 넣으면 결과 1로 실패(경로에/와\가 섞이면 특히) → 검증된 형태 =wscript.exe "run_hidden.vbs" "<abs.cmd>". - (2026-08-12) 미니PC 카톡 계정 되돌리기 =
kakao_pc_login.py --who cody(poin3133) 로 끝난다 — 잠금 상태여도 된다. 페페가 사무실에서 delix0731 로 로그인하면 미니PC 는 자동으로 밀려나 로그인 창만 남는다(메인창 hidden). 그 창은 PostMessage 로 조작되므로 잠금 무관. 성공 판정 3종 = ①로그인 창 핸들 소멸(그때shot()이 1400 에러로 죽는 건 정상) ②메인창EVA_Window_Dblclk '카카오톡'visible ③netstat :995ESTABLISHED. 계정 확인은 메인창 캡처의 프로필 이름(코디=「포인」 / 페페=「신동승」). - (2026-08-12) 🔴잠긴 윈도 세션은 코디가 못 푼다 — 관리자여도 못 푼다(윈도 보안 설계). 실측(POIN-MINI, 관리자 셸):
tscon 1 /dest:console(SYSTEM) 무효 ·LockApp.exe+LogonUI.exe강제종료 → LogonUI가 새 PID로 즉시 재생성. Winlogon 보안 데스크톱은 자격증명 입력 외엔 안 열린다.AutoAdminLogon=1은 「부팅 시 자동 로그인」이라 이미 잠긴 세션엔 무효. → 지금 풀 방법 = CRD 접속 1회 또는 재부팅(자동 로그인)뿐, 둘 다 페페 몫. - (2026-08-12) 잠금 재발 방지는 걸리기 전에 꺼 둔다(설정 완료 · POIN-MINI).
CONSOLELOCK=0(절전 복귀 시 암호 요구 없음,powercfg /attributes SUB_NONE 0e796bdb-… -ATTRIB_HIDE로 숨김 해제해야 설정된다) ·HKLM\…\Policies\System\InactivityTimeoutSecs=0· 화면보호기 off(ScreenSaveActive=0,ScreenSaverIsSecure는 원래 0). ⚠Chrome 원격 데스크톱은 연결을 끊으면 세션을 잠근다 — 이건 위 설정으로 못 막는다(이번 잠금의 유력 원인). - (2026-08-12) ⚠진단 순서를 건너뛰면 오진한다(이번에 그랬다).
LogonUI존재만 보고 「잠금」이라 단정했는데, 규정 순서는 talklog rules 26.8.10 = ①포그라운드 프로세스명 → ②BlockInput(False)err=5 → ③Session1에서ImageGrab.grab(all_screens=True)캡처다. 이번 실측 = fg=0 · BlockInput err=5 · 캡처에 PIN 화면 → 잠금 확정(결론은 맞았지만 근거가 없었다). 🔑「막힌 것」에 적을 땐 무엇이 되고 무엇이 안 됐는지 갈라 적는다 — 이번엔 로그인·수집은 됐는데 「PC 잠금」만 크게 적어 ④ 전체가 실패한 것처럼 읽혔다(페페 지적). - (2026-08-12) 코디가 도는 이 PC =
POIN-MINI\delix(미니PC)이고 셸은 관리자 권한이다.schtasks /RU SYSTEM /RL HIGHEST생성이 된다 = SYSTEM 작업을 만들 수 있다(잠금 해제는 그래도 안 되지만, 다른 상승권한 작업은 가능). 잠금 무관하게 되는 것 = SSH·파일·DB·HTTP·adb(폰) → 여태 「잠금이어도 잘 되던」 이유. 막히는 건 GUI 좌표제어 하나뿐이다. - (2026-08-12) 🔴PC가 잠겨 있으면(LogonUI 떠 있음) 물리 입력이 OS 차원에서 막힌다 —
SetCursorPos·keybd_event가 에러 0으로 죽고SetForegroundWindow도 실패. 그래서collect_all의 마우스·Ctrl+S 경로(=정식 「대화 내보내기」)는 잠금 상태에서 못 쓴다. 반면 PostMessage 계열은 전부 먹는다 — 방 열기(리스트 컨트롤에WM_LBUTTONDBLCLK), 화면 스크롤(WM_MOUSEWHEEL), 캡처(PrintWindow)로 대화를 이미지로 수집하는 우회는 가능하다(실측 26.8.12 롯데 향남 방 = 4화면). 판별 =Get-Process LogonUI(Session1에 있으면 잠금). 전체 내보내기가 필요하면 페페가 PC 잠금을 풀어야 한다. - (2026-08-12) 코디 Bash는 Session 0, 카톡/익스플로러는 Session 1 — 창이 아예 안 보인다.
EnumWindows가 카톡 창 0개면 로그아웃이 아니라 세션이 다른 것이다((Get-Process -Id $PID).SessionIdvsexplorer). 해결 =schtasks /Create … /IT+/Run으로 Session 1에서 실행(콘솔은 wscript.vbs로 숨김, 규칙 2). ⚠Git Bash에서schtasks /Create는MSYS_NO_PATHCONV=1없으면/Create를 경로로 바꿔 죽는다. - (2026-08-12) PC 카톡 좌측 레일(친구/채팅/더보기) 클릭은 최상위창이 아니라
OnlineMainView(EVA_ChildWindow) 자식에 PostMessage 해야 먹는다. 최상위창에 보내면 무반응. 성공 판정 =ChatRoomListView_0x…자식이 visible 로 바뀌는가(캡처보다 확실). 방 목록 컨트롤 =ChatRoomListCtrl_0x…, 방창 메시지 영역 =EVA_VH_ListControl_Dblclk. - (2026-08-12) ⛔톡클라우드 이전 대화 수집 = 항목 폐기(페페 지시 26.8.12). 다시 제안하지 마라. (참고로 막혔던 이유 = 「이전 대화 불러오기」가 My 비밀번호 6자리 + 보안키패드를 요구한다. 실수로 열었으면 프롬프트는 WM_CLOSE로 닫고 끝낸다.) 수집 범위 = PC 카톡 로컬 보유분까지가 전량이다.
- (2026-08-12) kakao-ops §1 방 목록은
members가 없으면 화면에 「1:1」로 표기된다 — 스냅샷에 없는 수동 등록 방(PC 카톡 방 등)이 단톡인데 1:1로 보인다._listener_seen.json항목에members를 넣고devplan/app.py::_kakao_rooms가 그걸 쓰도록 고쳤다(2026-08-12). ⚠8799 서버는 상승권한이라 코디가 재시작 못 한다 → 다음 재시작 전까지는 화면에 계속 1:1로 보인다(정적 html 수정은 즉시 반영). - (2026-08-12) 🔴카톡 알림에서
sub(방 이름)가 통째로 빠지는 날이 있다 — 그날 단톡방 수집이 전부 무음으로 샌다. 실측 26.8.12 08:00 이후 그날 온 알림 전량이sub=''.phone.route()가 발신자를 방으로 삼아 ①발신자에게 1:1 방이 있으면 그 폴더로 조용히 적재(아이비젼 대화 8건 →_collect/신동승, 금강에코 4건 →_collect/포인_신동혁_대리= 게시글이 어제에서 멈춤) ②없으면 「새 방」으로 등재(「글로벌아이비젼 은지호」·「넥서스 김선정 과장」 = 채팅목록 14개 어디에도 없는 가짜 방). 🔑복구 키 = 알림 key의 4번째 칸 = 카톡 채팅방 id(0|com.kakao.talk|2|474342527906766|10337, 방마다 고정).sub살아 있던 과거 이벤트로 이름표를 학습해 두면 sub가 없어도 방을 되찾는다 →data/rooms/_roomid_map.json(PYTHONUTF8=1 python phone.py roomids로 과거 inbox 전량에서 재작성, 폰 안 건드림). 학습은 sub 우선 — sub 없이 잘못 적재된 이벤트의room은 발신자 이름이라 그걸 배우면 오염이 굳는다.route()가 되찾으면ev["group"]을 채우고watcher.is_group()이 그걸 본다. - (2026-08-12) 🔴하단 「채팅 탭」 desc는 미읽음이 쌓이면 "채팅 탭 46개의 새로운 업데이트"로 바뀐다 — 정확일치로 보면 그날부터 방을 하나도 못 연다. 증상 =
room not found in chat list가 모든 방에서(게시글 갱신·발송·스냅샷 전멸). 원인은 방 목록이 아니라 친구/소식 탭에 눌러앉은 것(탭을 못 찾아 안 누름). 같은 이유로 쇼핑·더보기도 "… 업데이트 됨"이 붙는다 →phone.is_chat_tab(n)(startswith) 하나로 보고phone.open_room/to_chat_list·rooms._chat_list·sgc/find_room.py가 전부 그걸 쓴다. 회귀 =phone.py selftest(미읽음 접미 fixture 추가). - (2026-08-12) 방 이름 없는 알림 처리 = 폰 채팅목록에 있으면 진짜 1:1, 없으면 발신자 이름이다(페페 지시). 새 방 목록(devplan 카톡관리 §2)에는 신동승 차장이 낀 단톡방만 올린다. ①진짜 1:1 = 공용폰에만 오고 페페 폰엔 안 뜬다 → 방을 열어 캡처해서 「신동승」 방으로 보낸다(
watcher.queue_dm→ 메인 루프drain_dms, ⛔리스너 스레드에서 폰 만지면 게시글 편집 화면에 끼어든다). ②목록에 없는 이름 = 발신자 →data/rooms/_unrouted.jsonl에 원문 남기고 텔레그램(같은 발신자 1시간 1회). 알림톡 채널은DM_SKIP(카카오톡·카카오계정·페이북). - (2026-08-12) 게시글 프롬프트 규칙은 한 줄로 — 지시문 톤으로 길게 쓰면 claude가 게시글 대신 「3단계 보고」를 뱉는다.
claude -p가cwd=proj_dir라C:\dev\CLAUDE.md(답변 형식 지침)를 같이 읽는다 → 규칙문이 장황하면 그쪽으로 끌려간다. 실측 26.8.12: 볼드·다단 4줄로 넣은 「견적 금액」 규칙에서 출력이 「3단계 보고 / - 무엇: …」(섹션검사가 잡아 게시 차단, 1주기 손실) → 한 줄로 줄이니 정상. 섹션 누락 검사가 마지막 관문이니 없애지 마라. - (2026-08-12) 금액이 나온 견적은 「■ 견적」에 금액을 적는다(페페 지시) — 다른 섹션으로 옮겨가도 견적에 금액 한 줄은 남긴다. 미출고 항목 본문 안에만 묻으면 안 된다(실측: 포항 환호공원 200만원이 미출고2 안에만 있었다 → 견적3 신설).
watcher.PROMPT규칙7·REBUILD_PROMPT규칙8, 회귀는test_watcher_rules.py가 두 프롬프트에 규칙이 살아 있는지 본다. - (2026-08-12)
board.md수동 편집은 데몬 30초 push 루프와 경합한다 — 여러 곳 고칠 땐 파일 쓰기 한 번으로 끝내라.push_web_edits가 해시 변화를 보고 폰에 밀고commit_board가 board.md를 자기가 민 텍스트로 덮어쓴다 → 편집 도중이면 뒤늦은 수정분이 조용히 사라진다(실측: 이력 2줄 유실 후 재작성). - (2026-08-11) 📼 카톡으로 받은 「파일」(음성 녹음 등)은 S25(페페 개인폰) 캐시에 있다 — 노트20엔 없다. 페페가 「신동승」 방에 84분 미팅 녹음을 보냈는데 노트20(SM-N981N) 캐시·PC 카톡·다운로드 폴더 전부 0건이었다. 실제 위치 = S25(
adb connect 100.106.4.88:5555)/sdcard/Android/data/com.kakao.talk/contents/MTg=/474941031084587/<앞2>/<sha256>(확장자 없음,MTg=="18"=파일 ·474941031084587=「신동승」 방). 🔑두 폰이 서로 다른 계정이라 캐시도 갈린다 — 노트20 = 코디/업무 계정, S25 = 페페 개인 계정. 페페가 보낸 것은 S25, 페페에게 온 것은 노트20에서 찾는다. 타입 폴더도 폰마다 다르다(노트20 =Mg==·MTg=만 / S25 =Mw==(동영상)·NQ==·drive포함). 파일은 확장자가 없으니ffprobe로 판별(이번 건 = 3gp4/AAC 48kHz mono 156MB). 사진 편 = 2026-08-05 항목(방 열어야 원본이 떨어진다)과 같은 계열이나, 파일은 방을 안 열어도 이미 캐시에 있었다. - (2026-08-11) 🎙️ 긴 녹음 전사 = ytmine STT 어댑터를 그대로 재사용한다(새 코드 금지).
sys.path.insert(0, r"C:\dev\ytmine")→from ytmine import transcribe_audio→transcribe_audio(path, backend="groq"). 24MB 초과면 어댑터가 알아서 16kHz opus 20kbps로 줄여 Groq 25MB 한도를 피한다(84분 156MB → 한 방에 1,793 세그먼트). 🔴인터프리터를 틀리면 조용히 로컬 폴백으로 샌다 — 시스템 python312엔groq·faster_whisper가 없어서 "groq 실패 → local 폴백" 찍고ModuleNotFoundError로 죽는다. 전사용 venv =C:\dev\talklog\live\.venv\Scripts\python.exe(ytmineweb.py의VENV상수가 단일 출처,C:\dev\ytmine\.venv는 없다). - (2026-08-10) 🔴kakao-ops 「방 목록」은
rooms.py스냅샷이다 — 그 스냅샷이 방을 빠뜨려포인 신동혁 대리가 화면에 없었다. 목록 출처 = 최신data/rooms/note20_*.json+_listener_seen.json(알림으로 처음 본 방). 두 경로 다 새 방을 못 올린 원인: - ①🔑
list_rooms가 아래로만 훑었다 — 목록이 이미 내려가 있으면 위쪽 방을 통째로 못 본다(8/5 스냅샷에 신동혁 방 없음). → 훑기 전에 맨 위로 복귀(open_room·people_map과 같은 처방). ②_chat_list에 잠금해제가 없어 화면이 꺼져 있으면focus=''로 방 0개 예외(awake()는 화면만 켜지 키가드를 못 넘는다) →p.unlock()선행. ③스냅샷을 아무도 주기 실행 안 했다(마지막 8/5) →intake-check16:30 예약작업(run_1630.py)이 본작업 전에rooms.py list를 돌린다(폰을 어차피 쓰므로 예약작업을 늘리지 않는다, 실패해도 본작업 진행). - 🆕「자재입고 발송」 체크칸 신설(페페 지시) =
kakao-rules.json의intake_msg. 발송 대상의 단일 출처다 —intake_check.py가 이 체크를 읽고, 체크 0건이면 아무 데도 안 보낸다(fail-closed). 규칙 파일을 못 읽을 때만 코드 상수로 폴백. 체크칸 아래 = 마지막 발송 시각(runs/run_*.json의 kakao 결과). - ⚠플래그를 추가하면 옛 화면이 그걸 지운다 — 캐시된 탭이 저장하면
KPERMS전량 덮어쓰기라 신규 플래그가 꺼진다. →/api/kakao/rules를 보낸 키만 반영(k in pm) + 방 단위 통째 교체 대신setdefault().update()로 바꿔 놓았다. - 🔑devplan 8799 재시작은 상승권한 없이도 된다(2026-08-10 실측 —
taskkill /PID /F2개 +pythonw(Python39) app.py재기동, API·화면 정상). 「재시작은 페페 몫」은 낡은 기록이다. - (2026-08-10) 🔴리스너 「파손」 경보는 워치독 프로브가 낸 오보였다 — 감시 프로브는 자기 비용을 재고 만들어라. 카톡 26.6.1→26.6.3 자동감지 후
kakao-listener/version_check.py가 「리스너 바인딩 실패」로 2주 연속 경보. 실제 리스너는 멀쩡(dumpsysLive notification listeners에 바인딩 + 당일 실메시지 room/sender/text·reply:true정상 파싱). 프로브 결함 3개 전부 수정: - ①🔑
adb logcat -d -s KAKAO_MSG= 11.3초인데 타임아웃이 6초(3회 실측 11.2~11.4s). 태그 필터라도 5MiB 링버퍼를 전량 훑는다 →TimeoutExpired를("", "timeout", 1)로 삼켜 빈 문자열에서listener_connected를 찾다 항상 실패. ⚠-t N으로 못 줄인다 — 필터 전에 잘라서 최근 N줄엔 우리 태그가 0줄(실측). 주 1회니 타임아웃 60초로 올리는 게 답. - ②바인딩 판정은 logcat이 아니라
dumpsys notification. 「Live notification listeners」 섹션 = 0.4초·현재상태. 🔑그 위 「Allowed」 섹션엔 unbound여도 우리 이름이 있다 → 반드시 Live 구간만 잘라 본다. logcat 방식은 며칠 전listener_connected잔재를 집어 거짓 정상도 낸다. - ③
dumpsys notification은 "RemoteInput" 문자열을 절대 안 찍는다(actions=1·actions={까지만) → 답장액션 프로브가 원리적으로 항상 「못찾음」. 정답 = 우리 리스너가 이미 뱉는"reply":true를 읽는 것(추측 말고 자기 산출물을 본다). 본문파싱도 같은 소스로 통합. - ④멀쩡한데도
install -r을 무조건 돌렸다 → 프로세스가 죽고 재바인딩까지 11초 무음(10:00:01 재설치 → 10:00:12 connected, 실측). 감시가 감시대상을 깨뜨린 셈. 바인딩 실패일 때만 보수로 좁힘 + 재바인딩 대기 2초→30초 폴링. - ⑤증거 없으면 경보 금지 — 최근 7일 수신 0건이면 파싱·답장은 「판정보류」로 두고 baseline은 전진시킨다(조용한 폰에 매주 오보를 쏘면 워치독이 무시당한다). 회귀 =
version_check.py --selftest7항목(권한만/unbound·live·msg추출·정상·파싱사망·수신없음·unbound). - (2026-08-05) 📷 카톡으로 받은 사진은 폰 갤러리에 없다 — 「방을 열어야」 캐시에 원본이 떨어진다. [페페] 지시로 검증. 페페가 카톡 「신동승」 방에 사진을 넣었는데 코디가 DCIM/Camera · /sdcard/Download · /sdcard/Pictures · MediaStore(
content query content://media/external/images/media) · PC 다운로드/문서 전부에서 0건을 보고 "사진이 없다"고 오판했다. 실제 위치 =/sdcard/Android/data/com.kakao.talk/contents/<타입>/<채팅ID>/<앞2글자>/<sha256>(확장자 없음, adb shell로 읽힌다). - 타입 폴더 = base64 숫자 —
Mg==(="2") 사진 ·MTg=(="18") 파일. 🔑채팅ID는 코디가 보낸 파일 크기로 역추적한다(sendfile로 보낸 HTML 180,970바이트가MTg=/474941031084587/에 있으면 그 ID가 「신동승」 방). - 🔴방을 열기 전에는 썸네일뿐이다. 실측 = 열기 전 그 방 폴더의 최신 파일이 7/26(원본 0) →
phone.py readlong "신동승"으로 방을 여는 순간 4000×1848 원본 19장이 한꺼번에 떨어졌다. 즉 "캐시에 없다 = 안 왔다"가 아니다. 스크롤로 더 위까지 올려도 같은 44개면 그게 전량(위로 8번 스와이프 후 재확인 = 증가 0). - 썸네일 vs 원본 구분 = 세로 원본 1848×4000 ↔ 썸네일 555×1201 / 가로 원본 4000×1848 ↔ 썸네일 731×338. 긴 변 3000 미만은 버린다.
- ⚠캐시 원본은 EXIF 회전이 안 적용된 상태(세로 사진이
orientation=6으로 누워 있다). PILImage.open은 이걸 자동 적용하지 않아 세로 사진 13장을 전부 가로로 오독했다 →ImageOps.exif_transpose()필수. - ⚠Bash 도구에서
adb pull /sdcard/...는 MSYS 경로변환에 먹힌다(C:/Program Files/Git/sdcard/...로 바뀌어 "failed to stat remote object") →export MSYS_NO_PATHCONV=1. - 정식 경로(갤러리에 넣기)는 폰에서 사람이 「저장」을 눌러야 하지만, 읽기만 할 거면 방 열고 캐시 pull이 빠르다(19장 35MB 0.5초).
- (2026-08-05) 「게시글 수정」을 새로 켜고 저장하면 그 자리에서 게시글 프로젝트가 생긴다 — 첫 게시는 다음 슬롯. 페페 지시. devplan
/api/kakao/rules저장 핸들러가_kboard_turned_on()(꺼짐→켜짐인 방만) →_ensure_kproject()로<slug>/state.json+board.md스켈레톤 생성. 🔴이미 켜져 있던 방은 제외해야 한다 —포인 발주방처럼 게시글 없이 board_edit만 켜둔 방이 실재해서, 저장할 때마다 전수 생성하면 고객 방에 안 시킨 글이 올라간다(설계 중 발견·차단). 현장명 = 별칭 우선, 없으면 방 이름에서*포인/-포인표기만 제거(에넥스-포인 대우 용인→에넥스 대우 용인) → 게시글 제목에 그대로 나가니 어색하면state.jsonsite수정.change_msg는 빈 값으로 생성(승인 전 방 발신 금지). 폰은 안 만진다 — 게시는 데몬 몫(행 편집과 같은 원칙). PFS 노출 =pfs_board_sync가 state.json+board.md 있는 방만 미러하므로 생성 즉시 대상이 되고 1분 예약 동기화로field/worklog카톡관리 탭에 뜬다. - (2026-08-05) 데몬 재열거 = 600초 → 매 루프(30초), 단 도중에 붙은 방은 이번 슬롯 게시를 건너뛴다. 저장하고 10분간 아무 일도 안 일어나던 문제. 수집은 즉시(≤30초) 시작하고 게시만 다음 정각/반각부터(페페 지시 "게시글은 다음 주기때"). 구현 =
main()에서 새로 붙은 방에last.setdefault(room, 현재슬롯). 기동 직후(last비어 있음)는 예외 — 재시작하면 곧바로 한 바퀴 도는 기존 동작을 유지한다. - (2026-08-05) 🔴
_dump()는uiautomator dump실패를 안 보고 「빈 화면」으로 넘긴다 — 게시글 갱신 실패 4건의 진짜 원인. 다른 폰 작업(카톡 발송·실측)이 겹치면 dump가IllegalStateException: UiAutomationService already registered로 SIGKILL(rc=137) 되고/sdcard/_ui.xml이 0바이트가 된다._dump()는 returncode·길이를 안 보고 빈 문자열을 반환 →_nodes()=[] → ①목록 덤프가 빈 회차 =room not found in chat list②방 진입 뒤 빈 회차 =메뉴 더보기StopIteration. 같은 원인인데 오류 문구가 둘로 갈려 방/카톡 UI 문제로 오진된다. 실측 실패율 = 짧은 간격 8회 중 3회(37.5%). 연쇄까지: 빈 덤프 한 번이면open_room의 BACK 탈출 루프가 「채팅 탭」을 못 찾아 BACK을 계속 쏴 카톡 밖으로 나가고,app()복귀는 마지막 방을 다시 열어 목록에 영영 못 간다(실측 = 방 안에서 시작 76초 FAIL → BACK 1회로 목록에 세워두고 재시도하면 성공). 규칙 = ①_dump()는 rc/길이 검사 후 재시도(빈 XML을 화면으로 쓰지 말 것) ②폰 작업은 서로 겹치지 말 것(데몬 30초·30분 슬롯을 피하거나 락) ③끝낼 때 카톡을 채팅 목록에 세워두고 나온다 → 2026-08-05 전부 코드로 강제됨: ①_dump(tries=4)가 rc·<hierarchy검사 후 재시도하고 끝내 못 뜨면 예외(빈 화면인 척 금지) ②phone_lock()파일 락(data/phone.lock)을awake()가 잡는다 — 폰을 모는 경로는 전부 awake로 들어오므로 락 1개면 전부 직렬화된다(프로세스가 죽으면 OS가 핸들을 닫아 stale 락 없음, 대기 420초 초과면 예외) ③to_chat_list()가 awake 종료마다 카톡을 채팅 목록에 세운다. 회귀 =phone.py selftest(덤프 재시도·실패 예외·목록 복귀 2·락 상호배제). - (2026-08-05) 🆕 신규 카톡방 = 리스너가 첫 메시지에서 자동으로 목록에 올린다(수집은 여전히 페페 체크). 페페 지시로 신설:
watcher.listener_loop의 cb가 미등록 방이면note_new_room()으로data/rooms/_listener_seen.json에 이름+first_seen만 적고(수집은 안 함 = fail-closed 유지)runs.jsonl에new_room+ 텔레그램 1회 알림. devplan_kakao_rooms()가 스냅샷 ∪ 이 파일을 보여주므로 폰 스냅샷을 안 돌려도 카톡관리 §2에 「🆕 새 방」으로 뜬다(멤버수는 비어 있다 →rooms.py list돌리면 채워지고 배지도 자동으로 사라진다). ⚠한계 = 메시지가 와야 보인다(방만 만들고 조용하면 안 잡힘) + 알림 스트림이 끊긴 동안 온 첫 메시지는 놓친다(아래 항목). 전(前)이력: 이 기능 전엔 미등록 방 이벤트를if not proj: return으로 조용히 버렸고 목록 유일 출처가 수동rooms.py list(예약작업 0, 스냅샷 26.7.27)라 9일간 신규방 무인지였다. 데몬 rescan 600초는 등록된 뒤에만 의미(체크하면 ≤10분에 수집 시작, 재시작 불요). - (2026-08-05) ⚠ 죽은 무선IP는 watcher의 알림 스트림도 갉아먹는다(메시지 유실).
listener_loop가 재접속할 때마다connect()가adb tcpip 5555를 때려 자기 logcat을 끊는다 →watcher.log에listener_restart "watch stream ended"가 반복(26.8.5 10~11시 6회).logcat -T 1이라 끊긴 20초 동안 도착한 메시지는 영구 유실(등록된 방도 해당). 근본대응 = 무선IP를 살리거나 데몬이 USB 시리얼을 고정으로 쓰게 하는 것. - (2026-08-05) 📎 카톡 파일전송 =
phone.py sendfile신설 + 노트20은 USB 전용 — 🆕페페 지시: 노트20 작업은 전부 USB 케이블(폰은 상시 미니PC에 꽂혀 있다), 무선 adb는 특별한 경우만. →connect()에서adb tcpip재무장을 아예 제거했다. 그게 adbd를 재시작해 USB를 몇 초씩 떨어뜨렸고, 바로 뒤unlock()안의 두 번째connect()가 "no device reachable"로 죽어 스크립트 3개를 연달아 날려먹은 범인이었다. - 사용법 =
python phone.py sendfile "방이름" <파일경로> ["캡션"]또는P.send_file(room, path, caption). 파일 종류 무관. - UI 경로(실측 확정) = 미디어키보드 → 파일 → 파일에서 선택(SAF) → 루트 「내 파일」 → 삼성
myfiles.PickerActivity→ 다운로드 → 파일 탭 → 🔑「완료」. 삼성 선택기는 다중선택이라 파일 탭은 체크만 되고 완료를 눌러야 카톡으로 돌아간다 — 이걸 빼면 선택기에 그대로 앉아 있는다. - ⚠SAF 「최근」에는 adb push한 .html이 안 뜬다 — MediaStore 색인 대상이 아니라 미디어스캔 브로드캐스트도 소용없다(
send_image의 갤러리 방식이 안 통하는 이유). 같은 이유로 공유 인텐트 우회도 불가(content URI 자체가 안 생긴다) — 재조사 금지. - 🔴속도의 정체 = UI 덤프 횟수.
uiautomator dump1회 = 3.08초(adb shell 왕복 0.08초·focused_pkg0.14초와 비교). 그래서 ①화면 전환 대기는 덤프가 아니라focused_pkg폴링 ②고정 다이얼로그 좌표는_ui_coords.json에 캐시 ③채팅탭·전체필터는 한 덤프에서 같이 누른다. 실측 = 종단 77초(캐시 없음) / 68초(적중) / 50초(캡션 없음), 개선 전 120~140초. - 캐시 규칙 2개(자체검사에 박아둠) = ⓐ폴백으로 찾은 좌표도 캐시에 써야 낡은 값이 자가복구된다(안 쓰면 오염된 캐시가 남아 매 실행 130초 폴백 고착 — 실측) ⓑ단 「파일」 버튼은 캐시 금지(미디어 키보드 높이가 직전 소프트키보드 여부로 달라져 y=1945/2131 둘 다 관측 → 낡은 좌표는 대화 말풍선을 눌러 엉뚱한 파일을 연다).
- 🔴검증은 방 안이 아니라 「채팅 목록 행」에서 한다(미리보기가
파일: <이름>으로 바뀐다). 방 안 말풍선으로 검증하다 멀쩡히 간 파일을 6번 "전송 실패"로 오판했다 — ①덤프엔 보이는 노드만 담기는데 첨부 후 방은 화면이 위에 머물러 새 말풍선이 화면 밖 ②그래서 스크롤을 넣으면 창이 안 멈춰uiautomator dump가 이전 xml을 그대로 남긴다(빠른 플링은 방까지 빠져나갔다) ③같은 파일을 전에 보냈으면 말풍선이 여러 개라 "있다"로는 이번 것을 못 가린다. - 잠금 함정 = 화면이 켜지는 중엔
mCurrentFocus=null이라is_locked()가 False → "안 잠겼다"로 오판하고 잠금화면 위에서 작업을 계속한다. 포커스가 잡힐 때까지 기다린 뒤 판단 + PIN 3회 재시도 + 실패 시 즉시 중단. - 조용한 실패 하나 더 =
send()의 "입력칸이 비었다"는 성공 증거가 아니다(ADBKeyboard 브로드캐스트가 씹히면 애초에 안 쳐진 것도 빈칸) → 타이핑 직후 입력칸 내용을 먼저 확인한다. - 실패는 반드시 홈으로 되돌린다 — 선택기를 띄운 채 끝나면 카톡 태스크에 얹혀 있어서
app()재실행으로도 안 걷히고, 이후 모든 실행이room not found in chat list로 죽는다(방 목록 문제로 보이지만 원인은 이것). - (2026-08-04) 🚫 게시글 호칭 = 「신동승 차장」, 「페페」 금지 — 규칙 원문은
C:\dev\CLAUDE.md§3-8(단일 출처). 여긴 강제 지점만: ①sgc/watcher.py지시 블록 머리말[신동승 차장 지시 — devplan 댓글](모델이 화자를 그대로 받아쓴다 — 여기가 유출 진원지였다) ②PROMPT 4-3/REBUILD_PROMPT 7금지 문구 ③kakao-rules.jsonalias(gitignore=로컬 상태). 실유출 1건 =ivision/board.md이력[페페 지시]→ 수정 후 데몬이 v16으로 카톡 실반영. ⚠데몬은 상승권한이라 코디가 재시작 못 해 프롬프트 수정분은 다음 재시작부터 적용된다. 근거 =projects/pfs/session-2026-08-04-kakao-board-batch-save.md. - (2026-08-03) 🌑 화면 꺼짐은 「끄기」가 아니라 「켜둔 설정을 되돌리기」다 — 폰이 며칠째 켜져 있던 진짜 원인은
KEYCODE_SLEEP누락이 아니라 되돌리지 않은 안드로이드 설정 2개였다(실측:stay_on_while_plugged_in=7= 충전 중 화면 항상 켜짐 +screen_off_timeout=1800000= 30분).freight_app.open()·collect_cartypes.open_form()이 7을 박고 복구를 안 했고(제거 완료),awake()는 이미 부풀려진 값을 「원래 값」으로 읽어 다시 저장해 30분이 영구히 눌러앉았다. → ①P.sleep()이 매번 두 설정을 정상값으로 되돌린다(stay_on=0, 타임아웃 상한IDLE_TIMEOUT_MS=60000) ②awake()복구값에 상한(min(prev, 60000)) — 누출돼도 다음 작업에서 수렴 ③P.sleep_if_idle()(=화면 ON + 잠금화면일 때만 끔, 잠금 풀려 있으면 작업/사용 중이라 안 건드림)을 watcher 30초 루프에 배치 = 알림 등 우리 작업 밖의 이유로 켜진 화면도 30초 내 꺼진다. CLI =phone.py idle. 교훈: 전역 설정을 바꾸는 코드는 복구를 같은 함수에 쓰지 말고 되돌리는 쪽(sleep)에 몰아라 — 스크립트가 죽어도 복구된다. - (2026-08-03) 🪆
awake()는 재진입 가능해야 한다 — 중첩되면 안쪽 블록이 끝날 때finally가 화면을 꺼서 바깥 작업이 캄캄한 화면에서 계속된다(send()가 자기 awake를 쓰므로 실제로 발생하는 조합). depth 카운터로 안쪽은 no-op. - (2026-07-31) ♻ 데몬 재시작 = 「승격 킬 + 일반권한 재기동」이 정답(26.7.31 실행 완료 — 이후 devplan 8880·watcher 2068은 세션1·일반권한이라 코디가 그냥 재시작 가능, 아래 07-28 "코디가 재시작 못 한다" 항목은 그 시점 프로세스 얘기다). 막혔을 때 =
Stop-Process거부 +schtasks /Create /RL HIGHEST거부(우회 없음) →Start-Process -Verb RunAs로 UAC 요청이 유일 경로, 페페가 화면에서 눌러야 진행된다(consent.exe로 대기 확인 가능). 승인이 늦을 수 있으니 승격 스크립트는 ①킬 대상 PID를 못박고(늦게 눌려도 새 데몬을 안 죽인다) ②재기동까지 포함해 무인 완결시킨다. ⚠schtasks /Delete는 그 태스크가 띄운 자식 프로세스까지 죽인다 —wscript→pythonw2단 런처는 삭제에 딸려 죽으니 태스크를 남기거나 충분히 기다린다(pythonw 직접 실행은 무사). - (2026-07-31) 🧱 claude 출력 검사는 「감싼 것」을 먼저 벗기고 한다 — 프롬프트에 "코드펜스 금지"를 써도 가끔
``로 감싸 온다(26.7.31 아이비젼 실패의 전부. 섹션·길이는 정상이었고 첫 줄 3글자 때문에 turn 하나가 통째로 버려졌다).watcher._unfence()`로 감싼 경우에만 벗긴다(본문 중간 펜스는 안 건드린다). 형식 검사는 모델을 못 고치니 파서가 흡수한다. - (2026-07-31) 🔁 실패는 사람 선택지를 화면에 같이 내야 한다 — 갱신 실패를 알림으로만 흘리면 페페가 할 수 있는 게 없다(59.2% 사고와 같은 계열). kakao-ops 방 카드에 실패 이력(runs.jsonl 전량에서
error·op_*·*_fail만 별도 수집 = 최근 15줄에서 밀려나도 남는다) + 처리 버튼 2개: ⏸보류(=board_editoff 재사용, 새 상태값 안 만든다) · ♻구조 재작성(=<proj>/pending_op.json). 선택도runs.jsonl에op_hold/op_rebuild로 적어 실패와 처리가 한 줄기로 읽히게 한다. - (2026-07-31) 📮 웹→데몬 1회성 지시는 파일 하나 + 「성공해야 소비」 —
pending_op.json은 읽기만으로 지워지지 않는다(권한 off·야간이면 그대로 두고 다음 턴 재시도, 실행 성공 후에만clear_op). 폰 조작 주체는 여전히 데몬 하나라는 원칙 유지 — 웹은 파일만 쓴다. - (2026-07-28) 🌐 PFS는 이 PC로 못 들어온다 — 동기화는 항상 「이쪽에서 왕복」. EC2가 사무실 PC(NAT 뒤)를 호출할 수 없으므로 방향을 뒤집는다:
pfs_board_sync.run_once()가 ①미러 push(/api/kakao-board/sync) ②대기 명령 pull ③board_rows로 board.md 적용 ④ack 회신(무상태 — 저장할 것 없음). 웹은 파일을 못 고치니 「의도(명령)」를 큐로 넘긴다. 폰 반영은 손대지 않는다 →watcher.push_web_edits()가 board_hash 변화를 보고 가져간다. 폰 조작 주체는 여전히 데몬 하나. - (2026-07-28) 🚫 미러를 웹에서 낙관적으로 고치지 않는다. 원본은 로컬이고 되돌아오는 sync가 진실이다. 대신 화면에 「반영 대기 n건」과 실패 사유 배너를 노출한다(조용한 미반영 금지 = 59.2% 사고 교훈). 사라진 행에 대한 명령은
KeyError로 실패 회신돼 화면에 뜬다. - (2026-07-28) 🔒 감시 데몬은 상승권한이라 코디가 재시작 못 한다(
Stop-Process액세스 거부, PID=pythonw /CommandLine도 안 읽힘 — 찾을 땐Get-NetTCPConnection -LocalPort 47311로 락 소유 PID를 본다. 데몬이 bind만 하고 listen을 안 해netstatLISTEN에는 안 나온다). → 코드 변경분이 즉시 살아나지 않는다. 예비 경로를 같이 깔 것: 숨김 vbs + 예약작업(PFS-KakaoBoard-Sync1분). 데몬 안 호출과 겹치면 같은 명령을 두 번 적용하므로 싱글턴 락(47312) 필수. - (2026-07-28) 🤫 1분 주기 예약작업은
--quiet— 무사한 회차는 로그를 남기지 않는다(로그 무한증식 방지). 실패는 트레이스백으로 남고, "언제 동기화됐나"는 PFS 화면의 방별 동기화 시각이 보여준다. - (2026-07-28) 🧰 git-bash에서
schtasks호출 시MSYS_NO_PATHCONV=1접두 — 안 붙이면/Create가C:/Program Files/Git/Create경로로 변환돼 "잘못된 인수" 로 죽는다. - (2026-07-28) 🗂 완료·취소 체크 = 「숨김」이다 — 게시글에서 잘라내
hidden.jsonl로 이관(페페 지시, 앞선 "상태 표기+종결 섹션 이관"을 대체). 카톡 게시글·웹 양쪽에서 사라지고, 이력은<slug>/hidden.jsonl(1줄 ={ts,status,section,text})에 완료/취소 사유 라벨과 함께 남는다(페페: "종료된 명목의 의미가 다르다, 추후 이력에서 확인 필요"). 보기는 카톡관리 페이지에서만 — 모달 맨 아래<details>숨김그룹, 기본 접힘(창을 새로 열면 다시 접힌다), 최신이 위,↩로 원래 섹션 끝에 복원(그 섹션이 사라졌으면 409). 폐기 =set_status()·sort_statuses()·[완료]표기·GET이 파일을 되쓰던 정렬. 신규 =hide()·restore()·load_hidden()/save_hidden(), APIaction: hide|restore. 「■ 변동 반영 이력」 섹션 행에는 완료·취소 버튼을 안 붙인다(로그지 관리 항목이 아니다 — 수정·삭제는 유지). - (2026-07-28) 🧟 숨긴 항목은 claude가 되살린다 — 프롬프트에 종결 목록을 넣어야 한다. 데몬은 게시글 전문을 재작성하므로, 대화에 그 품목이 또 언급되면 표에 다시 만든다(숨김이 원위치).
watcher.hidden_block()이 최근 30건을[종결 항목 — 되살리지 마라]로 주입 + PROMPT 규칙 4-2. 새 변동 사실이면 이력 줄로만 남긴다. - (2026-07-28) ✍️ 게시글 「행」 편집 =
board_rows.py단일 출처(페페 지시). 행 = ■ 섹션 안의 들여쓰지 않은 줄 + 뒤따르는 들여쓴 연속 줄(머리말·「※ 이 게시글은…」 안내문은 행이 아니다). 행 id = 표기 접두사([완료]·※추가)를 뺀 본문 + 섹션 + 등장순번 해시라 토글해도 안 바뀐다. 삭제 시(N건)자동 갱신. devplanapp.py는 이 모듈을 importlib로 그대로 불러 쓴다 — 파싱 규칙 양쪽 중복 구현 금지. 자체검사 =PYTHONUTF8=1 python board_rows.py. - (2026-07-28) 📱 웹은 파일만 고치고 폰은 데몬만 만진다. kakao-ops 행 편집 →
board.md만 저장 → watcherpush_web_edits()가 board_hash 불일치를 보고 30초 루프에서 폰에 반영. 웹이 직접 폰을 조작하면 데몬 턴과 이중 수정이 난다.board_hash가 없는 state는 최초 1회 기준선만 기록(구 state 마이그레이션 시 불필요한 재게시 방지). 검증법 = board_hash를 일부러 어긋내면 같은 본문이 재푸시된다(방에는 변화 없음). - (2026-07-28) 🧷 편집 세션 중에는 행이 절대 안 움직인다(페페 교정 — "토글하자마자 그룹으로 넘어가면 인지가 어렵다").
set_status()는[완료]/[취소]표기만 바꾸고 제자리에 둔다. 종결 섹션 이관은sort_statuses()가 모달을 새로 열 때(devplanGET /api/kakao/board) 한 번에 한다 — 그 GET은 정렬 결과를 파일에 되쓴다(읽기 엔드포인트지만 "다음 로드에 반영" 규칙의 유일한 시점). 재렌더 시 모달 스크롤 위치도 보존한다. - (2026-07-28) 🥇 페페 편집 > claude. claude가 도는 몇 분 사이 board.md가 바뀌면 그 턴 결과를 버린다(
action: superseded, 백로그 유지 → 다음 턴 재판단). 상태 해제(–)는 접두사만 지우고 원래 섹션으로는 안 돌아간다(원위치 정보 없음 — 합의된 한계). - (2026-07-28) 🚨 카톡 알림의 방 이름은
sub(EXTRA_SUB_TEXT)다 —title은 발신자. 관측된 모든 이벤트에서room(title) == sender였고, title로 라우팅하던 탓에 단톡방 메시지가 전부 발신자 이름 폴더로 새서 관리 4방 inbox가 5시간 동안 0건(게시글 갱신 무음 정지, 프로세스는 살아 있어 로그도 안 남는다). 정규화는 공유 진입점phone.route(ev)한 곳 —ev["title"]=title; room=sub or title. 1:1은 sub가 비어 title이 곧 방이다. ⚠APK의 reply 캐시는 아직 title 키(P.reply쓸 때 같이 고칠 것). 커밋7f4deb6, 검사sgc/test_watcher_rules.py. - (2026-07-28) 🧭 "데몬 살아있음 ≠ 동작중" — 진단은 프로세스 유무가 아니라 inbox.jsonl mtime으로 한다. 관리 방 inbox가 다 같은 시각에 멈춰 있으면 수집 경로가 끊긴 것이다(위 라우팅 사고를 이걸로 잡았다).
runs.jsonl은idle을 안 남기므로 무증상이다. - (2026-07-28) 🕧 판정 주기 = 30분, 벽시계 :00/:30 슬롯(페페 지시, 이전 5분).
slot = int(time.time() // ivl)로 방마다 슬롯당 1회 — 데몬을 언제 재기동해도 다음 턴이 정각/반각이라 예측 가능하다. 야간은 그대로 1시간. - (2026-07-28) ※표기 = 최신 갱신분만(페페 지시): 새 행은 줄 맨 앞
※추가, 바뀐 행은※수정. 이전 갱신 표기 중 이번에 안 바뀐 행은 지운다. 이력 섹션·안내문엔 안 붙이고, 여러 줄로 이어지는 항목은 첫 줄에만(연속 줄은 들여쓰기로 판별해 위로 올린다). PROMPT 규칙 4-1. - (2026-07-28) 🔕 게시글 수정 안내 메시지 중단(페페 지시) —
kakao-rules.json전 방change_msg=false. 자기가 보낸 "게시글이 수정 되었습니다"를collect_room이 도로 주워 claude를 한 번 더 돌리는 자기참조도 같이 차단(SKIP_FEED 등재). - (2026-07-28) 🧱 게시글 구조는 방마다 다르다 → 출력검사에 섹션명 하드코딩 금지.
watcher.interpret()이"■ 미출고" not in out을 요구해, 출고목록이 아니라 시공일정·사양 구조인 금강 부산 에코 게시글은 claude 출력이 매번 반려됐다(08:09~08:14 전량 실패,processed_lines미전진 → 5분마다 같은 실패 무한 반복 = claude 호출 낭비). 검사는 "현재 board.md의 ■ 섹션이 전부 살아있는가"(_sections(), 추가 허용·누락 거부,(4건)건수는 괄호 앞까지만 비교)로 대체. PROMPT도 "없는 섹션 신설 금지" + 미출고→출고완료 이동은 두 섹션 다 있을 때만. 자체검사=sgc/test_watcher_rules.py. 커밋058edf6. - (2026-07-28) 📌 이미 공지인지 판정 라벨 = 「공지 내리기」(「공지 해제」 아님).
notice.ensure_notice()가 해제 라벨만 봐서 이미 공지인 방마다notice_fail을 뱉었다(글은 정상). 두 라벨 다 인정. 검증 스샷도sgc-yongdu/_notice.png→ 방 무관poin-agent/_notice.png(다른 방 디버깅 시 오인 유발). - (2026-07-28) ♻️ watcher는 코드 고쳐도 자동 반영 안 된다 —
pythonw상주 데몬이라 kill 후 재기동 필수(Stop-Process→Start-Process pythonw sgc/watcher.py, 자동시작 예약작업 없음·싱글턴 락 47311). 재기동하면last={}라 즉시 1회차를 돈다. - (2026-07-28) 📥 알림 스트림은 소급이 안 된다 → 백필 수집기
collect_room.py(페페 지시). 방에 직접 들어가 위로 스크롤하며 말풍선을 읽어 같은inbox.jsonl에 append(게시글 방=프로젝트 폴더, 그 외=_collect/<슬러그>/).--all은 watch 켠 방 전부. 장문은 「전체보기」(id=excute_message)를 눌러message_text전문으로 교체 — 알림 500자 캡 우회. 자체검사 =test_collect_room.py. - (2026-07-28) ⛔ 방 진입 검증 없으면 「방 목록 미리보기」를 대화로 수집한다(실측 사고: 포인01 방에서 목록 텍스트 11건이 그대로 들어감 → 폐기). 판별은 툴바 제목이 아니라 액티비티(
P.activity()에ChatRoom포함,List아님) — 이름을 안 지은 방은 툴바가그룹채팅8명이고 긴 이름은 말줄임되므로 제목 매칭은 못 믿는다. 수집 루프 매 회차마다 재검증하고, 벗어나면 즉시 중단. - (2026-07-28) 🔁 수집 중복키는 「본문」만(발신자·y 제외). 화면 상단이 잘려 발신자를 못 읽은 같은 메시지가 다음 화면에서 실명과 함께 다시 잡히면, 발신자를 키에 넣은 순간 같은 말이 두 번 들어간다(실측 26건 중 6건 중복). 본문으로 묶고 발신자만
?→실명으로 승격한다. 미상률 12%→3%. - (2026-07-28) 📜 방 진입 시 최하단 보장: 미읽음이 있으면 카톡은 「여기까지 읽으셨습니다」 지점에서 열려 그 아래(최신)를 놓친다 →
new_message_indicator탭 + 위로 스와이프 2회로 바닥을 잡고 나서 과거로 올라간다. 시간순 복원 =(-화면순번, y)오름차순(위로 스크롤할수록 과거). - (2026-07-28) 🕐 카톡 말풍선 시각은 접근성 트리에 없다 — 수집은 날짜(구분선)까지만 기록한다. 발신 시각이 필요하면 알림 스트림(ts 포함) 쪽을 써야 한다.
- (2026-07-27) 📊 대시보드(§1)는 「바뀐 것」만 등재(페페 규칙):
off_hours·paused(대기),nochange·idle(수정 없음)은 표에 넣지 않는다. 등재 =first_post·edited·오류류뿐이며 최신순, 열은 시각+수정 내용 2개로 압축. 필터는 프론트SHOW맵(runs.jsonl 원본은 그대로 남긴다 — 진단용). - (2026-07-27) 📅 날짜 표기 =
26.7.27(월)(전역 기본규칙, 상세seedchain/rules/tooling.md"날짜 표기"). 게시글 갱신 프롬프트에도 규칙 3-1로 박아뒀고, watcherkdate()가 "수정:" 줄을 이 형식으로 쓴다. state.json·로그 등 기계값은YYYY-MM-DD유지. - (2026-07-27) 📝 방 정리내용 = 단일 규칙: 게시글 방이면
<proj>/board.md(카톡에 올라간 글 그 자체), 게시 권한 없는 방이면summaries/<슬러그>.md. devplankakao-ops.html에서 방 이름 클릭 → 모달로 본문 표시(/api/kakao/summary?room=). 게시 권한 없는 방의 정리내용은 절대 카톡에 올리지 않는다(페이지 전용). - (2026-07-27) 🏷 방 표시명(별칭): 폰에 뜨는 원본 방 이름은 길고 사람이름이라 알아보기 어렵다 →
kakao-rules.json의alias{원본:표시명}으로 표시만 바꾼다(원본 이름은 어디서도 변경 금지 — 방 매칭 키). 편집 = 모달 하단 입력, 비우면 해제. API =POST /api/kakao/alias. - (2026-07-27) 🆕 최초 게시 경로:
state.json에posted_at이 비어 있으면 게시글이 아직 없는 방 →watcher.first_post()가board_post.post()로 최초 1회 게시 + 공지 등록, 이후부터board_edit.edit()수정. 최초 게시도 08~20시 게이트를 따른다(off_hours_first_post). 새 방 추가 절차 = 폴더 만들고board.md+state.json(posted_at=null) 두면 끝,_collect/에 쌓인 inbox는 프로젝트 폴더로 이관. - (2026-07-27) ⏰ 게시글 게시는 오전 8시~오후 8시에만(페페 규칙).
watcher.can_post()=POST_WINDOW = range(8, 20). 금지 시간엔 claude 판단조차 돌리지 않고 백로그를 유지(action: off_hours) → 아침 8시에 밤새 메시지를 일괄 반영. 수집(inbox 적재)은 24시간 계속. 검사 =PYTHONUTF8=1 python sgc/test_watcher_rules.py. - (2026-07-27) 📥 watch만 켠 방 = 수집 전용(게시글 프로젝트 없음) →
_collect/<방슬러그>/inbox.jsonl에 적재. 체크했는데 아무 일도 안 일어나는 상태를 없애기 위함. 게시글 관리 대상은 여전히<proj>/state.json+board.md가 있는 방만(그 방에 새 게시글을 만드는 건 카톡에 글을 쓰는 행위 = 페페 지시 필요). 방 이름의*·,·공백은 폴더명에 못 쓰므로_slug()로 정규화. - (2026-07-27) 🔐 카톡 권한은 전역이 아니라 「방 × 작업」 매트릭스(페페 지시) —
kakao-rules.json의 구 전역perms폐기,rooms{방이름:{watch,board_edit,notice,change_msg}}로 교체. 등록 안 된 방 = 전부 차단(fail-closed),watcher.load_rules(room)가 방별로 조회. UI =kakao-ops.html§2 표(헤더 체크박스=열 일괄 허용, 셀=개별). 방 목록은 별도 등록 파일 없이rooms.py list --device note20최신 스냅샷(data/rooms/note20_*.json)을 devplan API가 읽는다 — 방이 늘면 스냅샷만 다시 뜨면 표에 자동 등록(시스템 채널 카카오톡·카카오계정은 제외). 2026-07-27 실측 = 참여방 11개(그룹 7·1:1 2·시스템 2). - (2026-07-27) 📂 프로젝트 워크스페이스 =
C:\dev\poin-agent독립 이전(페페 지시 — tools 하위 아님). 코드+데이터 전부 이전, tools 리포에서 제거 커밋(ff62f37), 로컬 전용 git 리포 신규(.gitignore로 대화원본·수집데이터 제외 — GitHub 원격 없음). adb는C:\dev\tools\platform-tools\adb.exe절대경로(상대경로는 이전으로 깨짐). 자동시작 HKCU Run도 새 경로. ⚠이전 중 heredoc 이중디코드 함정 재발(\t·\a오염) — Windows 경로 문자열 치환은 Edit 도구로 할 것(기존 규칙 재확인). - (2026-07-27) 🎛 코디 카톡 작업 권한 단일 출처 =
C:\dev\poin-agent\kakao-rules.json— devplankakao-ops.html(poin-agent.html에서 연결)의 체크박스(감시·게시글수정·공지유지·변동알림)가 이 파일 perms를 쓰고, watcher가 매 주기 로드해 준수(꺼진 동안 백로그는 소비 안 함 = 켜면 일괄 반영). 운영 지시 = 같은 파일 comments(페페 댓글) 최근 8건을 갱신 판단 프롬프트에 주입. 방 자유발언·확약성 발언은 체크박스 없음(영구 하드락). API = devplanapp.py/api/kakao/status|rules|comment. - (2026-07-27) 📢 게시판 운영 기본 규칙(페페 확정): ①관리 게시글은 항상 방 공지로 등록 유지(수정 후
notice.ensure_notice()— 「공지 해제하기」 보이면 이미 등록 = 스킵, '해제/삭제' 라벨 탭 금지) ②수정된 경우에만 방에 알림 메시지 1회 — 문구 고정 "게시글이 수정 되었습니다."(존댓말, 요약·핵심내용 미포함, 공용폰 언급 금지. 페페 승인 문구 2026-07-27, state.jsonchange_msg로 게이트) ③향후 출고일정 외 생산현황 등 비서역할 항목을 게시글로 통합 관리 예정 — 문구가 범용인 이유. 첫 공지 등록 실측: 등록 시 방에 "공지가 등록되었습니다" 카드가 자동으로 뜬다(코디 발언 아님). - (2026-07-27) 📌 톡게시판 조작 실측 = 방→「메뉴 더보기」→서랍 「게시판」→「글쓰기」 / 글 카드 ⋮→「수정하기」(라벨은 '수정'이 아니라 '수정하기'). 본문칸
id=content_edit(placeholder "멤버들과 공유하고 싶은 소식을 남겨보세요."), 확정 = 우상단 「완료」. 카드 ⋮ 메뉴 = 공유하기/공지 등록하기/수정하기/삭제하기 → 자동화는 '삭제'가 든 라벨 탭 금지(블랙리스트). 수정 시 기존 본문 클리어 = ADB_CLEAR_TEXT 브로드캐스트(필드 포커스 상태), 클리어 검증 후 재입력(중복 입력 방지). 글 수정은 방에 알림이 안 간다 → 고빈도 갱신에 적합(공지·메시지 재전송 대비). 구현 =sgc/board_post.py·board_edit.py. - (2026-07-27) 🐛 pythonw 데몬은 stdout=None — 모듈 최상단
sys.stdout.reconfigure()가 AttributeError로 즉사해 "등록했는데 안 뜨는" 무음 실패가 된다(watcher 첫 기동 실측). 데몬 진입부에서 stdout/stderr를 로그파일로 리다이렉트하고, import되는 모듈의 reconfigure는if sys.stdout:가드. - (2026-07-27) 🔍 bind-only 소켓(싱글턴 락)은 netstat에 안 뜬다(listen 안 하므로) — 락 검증은 이중기동 시도("이미 실행 중" 확인)로. 부수: Bash
timeout N … phone.py watch는 자식 adb logcat을 같이 죽여 "stream ended"처럼 보인다(스트림 죽음 오탐 주의). - (2026-07-27) ✅ 서버측 이름이 있는 방(생성 시 명명)은 양폰 표시명이 같다 — 「넥서스포인 SGC 용두동」 실증. 인원수+초대시각 매핑은 자동 기본명 방에만* 필요.
- (2026-07-26) 📷 카톡 사진 전송은 「원본 화질」 확인창까지 눌러야 간다 — 안 누르면 글만 가고 사진은 조용히 안 간다(실측). 경로 = 방 →
media_send_layout→ desc사진→ 최신 썸네일(desc7월 26일 오전 1:42, 사진) →send_button→ 텍스트전송하기확인창. 검증은 "선택 화면이 닫혔다"로 하면 안 되고(확인창이 떠도 닫혀 보인다) 방에id=image말풍선이 생겼는지로 한다. 썸네일 격자는 늦게 그려지니 8회까지 재시도, 최신 썸네일 시각이 푸시 시각과 5분 이상 벌어지면 엉뚱한 사진이므로 전송 중단. 구현 =phone.send_image(). - (2026-07-26) 🔎 화물앱 주소검색 팝업은 지명 「한 토큰」만 받는다 — "시흥시 계수동"은 0건, "계수동"은 2건(실측). 자동화는 주소에서 동/읍/면/리 토큰(없으면 로/길)만 뽑아 검색하고, 결과행은 시·군 이름(경기도 시흥시 →
시흥)으로 고른다. 못 고르면 추측하지 말고 실패로 보고(잘못 고른 주소로 배차가 나가는 게 더 나쁘다). 결과행을 탭하면 시도·시군구·읍면동이 자동으로 채워지고 나머지 주소는 비어 있다(= 페페 규칙과 일치). - (2026-07-26) ⌨ 앱 입력칸 검증은 「값 비교」가 아니라 「placeholder가 사라졌는가」로 한다 — 이 WebView는 채워진 EditText의 값을 a11y에 안 싣고(text=''), 조작이 길어지면 트리가 무너져 좌표까지 뭉개진다. 값으로 비교하면 멀쩡한 입력을 실패로 오판하고, 재입력하다 값이 겹친다. 또 ADBKeyboard 전환은 필드마다 하지 말고 한 번만(전환할 때마다 포커스가 날아가 입력이 씹힌다 — 운송료 미입력 실측). 스크롤 스와이프는 위젯 없는 왼쪽 여백(x≈40)에서 — 필드 위에서 쓸면 탭으로 먹혀 모달이 열린다(실측).
- (2026-07-26) 📸 사진을 안 보면 업무 사실을 놓친다 — 텍스트만 읽고 방을 파악했다고 하지 마라(실증). 아이비젼 방 대화 텍스트 5개 파일 전부에
윅스가 0건인데, 사진에 사업자등록증 실물이 있어 거래처 법인명이 ㈜윅스솔루션(대표 은지호, 표시 상호 "글로벌아이비젼"과 다름)임이 나왔다. 계산서 발행처가 건별로 법인/개인 갈리는 방이라 이건 실무 직결 정보다. → 방 파악·현안 추출 시 사진을 실제로 열어볼 것(자재표·재고표·도면·불량사진·증빙이 대부분이고 텍스트엔 "사진"이라고만 남는다). - (2026-07-26) ⚠ 카톡 삭제 메시지 문구는 정확히
메시지가 삭제되었습니다.—삭제된 메시지·삭제하였습니다같은 변형으로 grep하면 0건이 나와 "삭제 없음"으로 오판한다(내가 그렇게 오판했다). 삭제된 자리는 내보내기에 이 한 줄만 남고 원문은 복구 불가 → 대화 흐름에 구멍이 생긴 지점이므로 후속 결과 확인이 필요한 항목으로 플래그해야 한다(실측: 아이비젼 방 롯데논현 경첩 교체 수량 문답 직후가 삭제됨). - (2026-07-26) 🔒 수집 원본은 git에 올리지 마라 —
tools리포는 GitHub 원격이 있다. 방 목록 스냅샷(거래처명 포함)이 이미 추적돼 커밋된 걸 push 전에 잡았다..gitignore에poin-agent/data/kakaopc/·poin-agent/data/rooms/·data/*.log추가 +git rm --cached로 추적 해제. 원칙 = 대화 원문·사진·방이름·계정 캡처는 로컬만(3자 회의 확정 "외부 전송 없음, 로컬+페페 텔레그램만"). ⚠poin-agent/data/freight/(차주 이름·연락처·운임)는 여전히 추적 중 — 페페 판단 필요. 문서·페이지에 쓸 때도 전화번호·사업자번호는 마스킹한다. - (2026-07-26) ✅ 방 매핑은 「인원수 + 초대 시각」이면 끝난다 — 본래이름 판독까지 안 가도 된다(실증). 페페가 5방에 코디를 초대하며 각 방에
.를 1건씩 보냈고(00:36~00:38), 그 시각이 양쪽 목록에 동일하게 찍혀 1:1 대응이 확정됐다. 인원수(5·10·8·4·8)도 양쪽 일치, 8명 방 2개는 시각(00:37 vs 00:36)으로 갈렸다. 실증: 5방 중 4방이 이름이 다르다 — 페페폰포인-월드/프린테크-포인 발주방/아이비젼-포인/포인01↔ 코디폰팀채팅, 포인-월드/포인 발주방/생산 소물량 업체 포인 신동승 차장님/아빠, 갈랑 포인, …. 매핑표 =tools/poin-agent/data/rooms/mapping.json. 위험한 이름편집 화면(origname)은 애매한 방에만 쓴다. - (2026-07-26) 🖥 카톡 PC 지정방 수집 =
tools/poin-agent/kakao_pc_grab.py(페페 지시 "다중 방 순회 사용하면 안된다. 해당 단톡방만").collect_full.py(967방 전량 순회)는 쓰지 않는다. 검증된 하위 함수만 재사용 =collect_all.export_text(Ctrl+S→#32770 UIA 저장)·collect_photos.collect(서랍 사진). 방 특정 = 목록 캡처에서 y픽셀을 읽어 더블클릭 → 창 제목으로 검증, 제목이 대상이 아니면 즉시 닫고 넘어간다. ⚠행 인덱스 산술 금지 — 그룹방은 아바타 격자라 행 높이가 1:1방보다 크다(실측 pitch 68 vs 78). UIA로는 목록 항목이 안 보이니(EVA GDI) 캡처로 이름을 읽는 게 유일하게 방을 안 열고 특정하는 방법이다. - (2026-07-26) 🐛 카톡 ≡ 메뉴: 고정 sleep 후 1회 확인 → 빈 결과면 재클릭 = 이미 열린 메뉴를 닫는다(토글).
collect_photos.open_drawer_photo가 이 구조라 서랍 열기가 조용히 전부 실패했다. 근본수정 = 뜰 때까지 폴링(0.3초×12) 후 정말 없을 때만 1회 재시도. 추가로 서브메뉴 캐스케이드는 0.4초로는 못 잡는다(실측 ~1초) → 호버 대기 0.9초 + 클릭 폴백. 메뉴 구성 실측(2026-07 카톡) = 초대하기/다시만들기/채팅방 서랍▶(top+83)/톡캘린더/톡게시판/브리핑보드/챗봇/대화내용▶/나가기. - (2026-07-26) 🔐 카톡 PC 로그인 자동화 = Edit 컨트롤에 WM_CHAR 직접 주입. 로그인 창(EVA_Window)엔 진짜
Edit자식이 2개(ID 보임/PW 숨김) 있어WM_GETTEXT로 읽고WM_CHAR로 쓸 수 있다. ⚠크로스프로세스SetFocus는 액세스 거부(5) → 포커스는 그 컨트롤을PostMessage(WM_LBUTTONDOWN/UP)로 직접 클릭해 잡는다. 로그인 성공 신호 = 로그인 창 핸들이 무효가 된다(GetWindowRect 1400). 비밀번호는 길이만 검증하고 값은 절대 출력·로그·커밋 금지. 도구 =tools/poin-agent/kakao_pc_login.py --who pepe|cody. - (2026-07-26) 🔑 단톡방 이름은 기기마다 다르다 — 두 폰 매핑에 공통 키가 필요하다(페페 지시). 카톡 방 이름 변경은 로컬이라 페페 S25에서 바꾼 이름이 코디 Note20엔 원래 이름으로 뜬다. 공통 키 = 본래 방 이름, 판독 경로 =
방 > 우측상단 옵션 > 우측상단 설정 > 우측상단 편집 > 방이름 터치 > 우측 X 터치→ 기존 이름이 지워지고 본래 이름이 placeholder로 흐리게 뜬다. ⛔ 저장 금지 하드락 필수(확인/저장/완료/적용/변경 라벨 탭 블랙리스트 + 이름칸에 텍스트 입력 금지 + BACK으로만 탈출 + 끝나고 방 목록에서 이름 불변 재확인, 불일치면 자동복구 말고 중단·보고). 도구 =tools/poin-agent/rooms.py. 추후 추가되는 방도 매번 같은 작업 필요. - (2026-07-26) 📋 카톡 방 행 판별자 =
class=android.widget.Button— 날짜 형식 열거 금지. 실측 사고: 마지막 칸(시각) 정규식에"7월 23일"형식을 안 넣어 방 2개가 조용히 사라졌다(9개인데 7개로 보고). 카톡 시각 표기는오전/오후 H:MM·어제·N월 N일·YYYY.M.D· 요일로 갈린다. → class로 거르고, 형식을 못 맞춘 Button 행은 버리지 말고unparsed로 올려 보고한다(조용한 누락 금지). 방 아닌 Button(새로운 항목, 채팅방 폴더 관리)은 desc 접두로 배제. - (2026-07-26) ⚠ 방 이름에 쉼표가 흔하다 — 첫 쉼표로 자르면 안 된다. content-desc 포맷 =
{방이름}[, N명], [새로운 메시지 N개, ]{미리보기}, {시각}. 참여자 나열형 자동 방이름(아빠, 갈랑 포인, 신동승, 포인 신동혁 대리, 김성수 이사님, 8명, …)이 실재한다., N명앵커 →, 새로운 메시지 N개앵커 → 첫 쉼표 순으로 자른다., N명을 비탐욕 매칭하면 이름 안의 "5명"(포인 5명 작업방, 8명, …)에도 안 속는다. 인원수는 두 폰에서 같으니 본래이름과 함께 보조 매핑 키로 쓴다. - (2026-07-26) 🔴 카톡 앱 진입 루프가 렌더 전 덤프를 보고 앱 밖으로 나간다 —
wait_app+ 포커스 가드 필수.open_room()/_chat_list()의 "채팅 탭 없으면 BACK" 루프가 아직 안 그려진 덤프를 '화면이 틀렸다'로 오독해 BACK 4번 → 런처로 나가버린다(실측 2회 연속 방 0개 수집). 근본수정 =Phone.wait_app(pkg)— 포커스가 그 패키지이고 노드 수가 임계 이상일 때까지 대기 후 그 덤프를 반환, 그리고 BACK은focused_pkg()==대상일 때만 누른다(아니면 앱 재실행).Phone.focused_pkg()는dumpsys window의mCurrentFocus=Window{... pkg/Activity}에서 뽑는다. 부수: 방 0개면 예외를 던져 조용히 빈 결과를 저장하지 않게 한다. - (2026-07-26) 🔑
C:\dev\.secrets\kakao_login.env는 ID/PW 키가 2번씩 나온다 — 계정 구분이 주석 헤더(# 사용자(신동승,…)/# 사용자(코디,…))로만 돼 있어 일반 dotenv 파서로 읽으면 마지막 값만 남아 조용히 코디 계정으로 붙는다. 순서대로 파싱하거나 헤더로 구분할 것. 매핑 = delix0731@gmail.com = 페페(S25) / poin3133@gmail.com = 코디(Note20). ⚠ 카톡 PC는 현재 미로그인(로그인 화면에 poin3133 프리필). 페페 방 대화 내려받기는 delix0731로 로그인해야 하고, 이는 로그인 위험항목이라 착수 전 페페 승인(코디 메모리login-credential-autofill-risk). - (2026-07-26) 🔄 배차 판정 변경 — "코디가 원천적으로 못 한다"는 틀렸다(페페 통보). 화물 앱으로 코디가 실제 배차를 낼 수 있다(같은 계정 실배차 15건 실증·화주 정식가입 불필요).
poin-agent.html판정표 11행 C(불가) → B(초안). A가 아닌 이유 =devplan/freight-dispatch.html(단일 출처)이 제출 버튼 = 사람 하드락을 아직 유지. ⚠다른 C행에 유추 적용 금지 — 위임은 항목 단위다("배차를 위임했으니 발주도 된다"는 성립 안 함). 원칙 자체는 유효: 되돌릴 수 없는 행위의 기본값은 C, 페페가 항목을 지목해 위임할 때만 올라간다. - (2026-07-25) 📋 devplan(8799) 페이지에서
navigator.clipboard는 없다 — 복사 버튼은 반드시 폴백 2단계:http://<ip>:8799는 secure context가 아니라(localhost만 예외) 클립보드 API가 정의조차 안 된다.navigator.clipboard?.writeText()로 쓰면 옵셔널체이닝이 삼켜 조용히 아무 일도 안 일어남(alert로 텍스트를 보여주면 성공처럼 보여 오진 유발). 표준 = ①clipboard 있으면 사용 ②없거나 reject면document.execCommand('copy')(선택된 textarea 필요) ③그래도 실패면 텍스트 상자를 화면에 띄워 Ctrl+C. 참고 구현 =devplan/freight-dispatch.htmlexportMemo()/execCopy(), 선례devplan/mockup-common.jsfallbackCopy(). - (2026-07-25) 📤 페페에게 보고를 카톡으로 보내라 = 노트20에서 카톡 「신동승」 방으로 발송이 기본(페페 교정: "폰을 활용해서 카톡으로 나(신동승)에게 보내는 게 카톡 사용 기본 방식"). 코디가 PC 카카오톡 GUI를 조작해 보내려 한 것은 경로 오판. 구현 =
tools/poin-agent/phone.pyP.send("신동승", text)그대로 재사용(ADBKeyboard b64 입력 → 전송 → 입력창 비었는지 검증). 개행 포함 872자 1건이 한 말풍선으로 정상 전송 실측(전체보기 달림) → 장문도 쪼갤 필요 없다. 발신 하드락(§3 레드라인)은 거래처·단톡방 대상이고, 페페 본인 1:1 방은 페페 지시로 발송한다. - (2026-07-25) 🖱 PC 카카오톡은 합성 입력(SendInput·mouse_event·keybd_event 단축키)을 전부 무시한다 —
PostMessage(WM_LBUTTONDOWN/UP)만 먹는다(실측). 좌표·DPI·포커스를 다 맞춰도 클릭이 조용히 씹혀 "좌표가 틀렸나"로 시간을 버림(Ctrl+1 같은 단축키도 동일하게 무시). 대상 창은WindowFromPoint로 자식(EVA_ChildWindow)을 잡고ScreenToClient로 변환한 lParam을 보낼 것. UIA(uiautomation)로는 카톡 내부가 안 보인다(EVA 커스텀 렌더라ChatRoomListCtrl같은 컨테이너까지만 노출) → 결국 좌표+PostMessage 조합. ※그래도 보고 발송은 PC 말고 노트20(위 항목). - (2026-07-25) 📥
adb pull은 한글 파일명 소스를 못 받는다 — Windows adb.exe에 UTF-8 인자가 넘어가면 basename 추출이 깨져cannot create '...\.': No such file or directory로 실패(dest 끝에\나/를 붙여도 동일). 우회 = 폰에서 ASCII 이름으로 복사 후 디렉토리째 pull, 로컬에서 파이썬으로 rename(for f in <패턴>; do cp "$f" /sdcard/_tmp/x_${f##*_}; done→adb pull /sdcard/_tmp). 패턴 매칭은 한글 대신 전화번호·날짜를 쓰면 인자에 한글이 안 들어간다. - (2026-07-28) ☎ 노트20 착신전환 대상 번호는 1개로 고정(페페 결정). 배차 담당 직원별로 번호를 바꾸는 동적 스위치는 하지 않는다 — 착신전환은 발신자 구분이 안 되고 시점당 대상이 1개라 복잡도만 늘고 실익이 없다. 노트20으로 배차 등록을 넘기려면 차주 전화 경로 확보가 선행이다(010-2841-1731 KT, 아무도 안 받는 번호). 실행 = KT 「착신전환(모바일,통화만)」 월 770원 가입(명의자 몫) 후
*88+번호+*/ 해제#88*, 코드 불발 시 전화앱>설정>부가서비스 UI 폴백. 계획 =devplan/freight-dispatch.htmlP6. - (2026-07-25) 🚛 화물 앱 차량종류 목록은 톤수에 종속(S25 실적으로 발각). 1톤 선택 후 뜬 34종에 다마스·라보가 없는데 실제 배차엔 다마스4·라보1이 있다 → 톤수를 바꾸면 차종 목록이 바뀐다. 모달 옵션을 한 번 떠 놓고 전체라고 단정하지 말 것 — 상위 선택지별로 각각 떠야 한다. 실측 차종 = 카고·다마스·윙바디·호루·라보.
- (2026-07-25) 📵 화물 앱은 조회기간 1개월 제한 + 그 이전 이력 조회 불가(페페 확인). 이 앱에서 얻는 데이터는 최근 1개월이 전부 → 장기 이력이 필요하면 주기 수집 배치로 쌓는 것 말고 방법이 없다. 과거월 수집 시도는 낭비.
- (2026-07-25) ⚠ 이 앱은 조작을 이어가면 WebView 접근성 트리가 죽는다 —
uiautomator dump가 타이틀 1~2줄만 반환(스크린샷은 정상). 복구는 앱 강제종료·재시작뿐. 그래서 장시간 수집 루프는 건마다 트리 생존 확인 + 죽으면 재시작·화면 복구를 넣어야 한다. 부수 실측 = ①날짜 입력칸(EditText) 탭으로는 달력이 안 열리고 옆 달력 아이콘(list_date01)을 눌러야 한다 ②앱 재시작 직후의 탭은 씹힌다(메인 텍스트 확인 후 탭) ③미래 날짜는 달력에서 못 고른다(종료일은 오늘로 클램프) ④행 매칭에 raw 전체 문자열을 쓰지 말 것 — 접근성 트리가 늦게 차면 상태문구('배차')가 붙었다 말았다 해 같은 행이 다른 문자열이 된다 → 날짜+운임 키로 매칭. - (2026-07-25) 📱 기기 2대 구분 = Note20
R3CR103JBBY(테스트·조작용) / S25R5CY831RHVH(페페 데일리폰, SM-S937N 1080x2340). 실제 업무 데이터(배차 실적·카톡·통화)는 S25에 있다. S25는 개인폰이므로 설정 변경 금지·읽기 위주(회전잠금/절전 설정 건드리지 않음), 드라이버는tools/poin-agent/s25.py(노드 라벨 기준, 최소 조작). USB 연결이 도중에 끊기면uiautomator dump가 빈 문자열을 반환해 조용히 실패하니 각 단계에서 값 검증 필수. - (2026-07-25) ⚠ 앱 조회기간 변경은 「조용히 실패」한다 — 결과 날짜를 반드시 검증. 화물등록내역 월별 수집 시 달력 조작이 실패해도 앱은 직전 기간의 결과를 그대로 보여준다(실측: 6월·5월 조회가 7월과 완전히 동일한 15건 반환 → 45건 중 30건이 중복 허수). 탐지·방지 = ①날짜 선택 후 입력칸(EditText) 값이 기대값과 같은지 확인 ②조회 결과 행의 날짜가 요청한 달과 일치하는지 검사, 불일치면 무효 처리. 화면이 바뀌었다고 데이터가 바뀐 게 아니다.
- (2026-07-25) ⚠
enabled=false하나로 "선택 불가" 단정 금지 — 웹뷰는<select>를 일부러 죽이고 오버레이 버튼으로 커스텀 모달을 연다(페페 지적으로 정정, 실측). 화물 앱 차량톤수·차량종류가 그 케이스: a11y엔click,DISABLED로 보이지만 같은 좌표에blank_btn01이미지 노드가 겹쳐 있고 그걸 탭하면 격자 모달이 정상으로 뜬다(옵션 15종/34종 전부 노드로 읽힘). 판정 전에 반드시 ①탭 ②스크린샷 ③덤프 전체(head로 자르지 말 것 — 모달 노드는 폼 노드 뒤에 붙는다) 를 보고, 그래도 반응 없을 때만 비활성으로 적는다. 겹친 노드가 있으면 가장 위(나중에 나오는) Image/오버레이가 실제 클릭 타깃이다. - (2026-07-25) 화물 앱 입력 사슬 = 차량톤수 → 차량종류 → 화물중량(실측). 톤수 없이 중량 입력 시 "화물중량은 차량톤수의 110%를 초과할 수 없습니다" 알림으로 차단, 차량종류는 톤수 선택 후 열리고 「전체」를 고르면 미완료(페페 확인) → 자동화는 이 순서를 하드코딩하고 차종에 「전체」를 절대 넣지 않는다. 톤수 15종 = 0.3·0.5·1·1.4·2.5·3.5·4·5·8·9.5·11·14·15·18·25(오토바이·9T 없음 → PFS
vehicle_type대응표는 페페 확정 필요). - (2026-07-25) 🔴 통화 파이프라인 PFS 적재가 절반 넘게 조용히 실패하고 있었다 — 실측
load267회 중 158회 실패(59.2%). 3자 회의 5회차 '코디' 렌즈가 발견,talklog/data/_pipeline_log.jsonl직접 집계로 확인({"stage":"load","ok":false}158건,classify_err72건도 별도). 아무도 몰랐던 이유 = 실패해도 알림이 없고 성공/실패 비율을 보는 화면이 없다. 재시도·경보 없이 로그에만 남는다. → 새 배치 파이프라인은 성공률을 집계해 보고하는 경로를 처음부터 넣을 것(단순 로그 append는 관측이 아니다). 갭㉓으로 등재. - (2026-07-25) ⚠ "가동중"이라 쓰기 전에 ①docstring 말고 SQL/코드를 보고 ②스케줄러 존재를 확인하라(3자 회의 적대검증이 잡아낸 실측 오류 2건). 실측:
talklog/server/pipeline_worker.pydocstring엔 "worklog '미검수' 적재"라 적혀 있는데 실제 INSERT는review_status='확정'(_pipeline_load.py도 동일) — 검수 단계 없이 바로 확정으로 들어간다. 또 통화 파이프라인은 등록된 예약작업이 없다(talklog_room_sync만 존재) → 상시 자동이 아니라 수동 배치. 내가 문서·주석을 근거로 "가동중/미검수"라 적었다가 둘 다 틀렸다. 문서·주석은 근거가 아니다. 실행 경로(SQL 문자열·schtasks 목록)를 직접 확인하고 쓸 것. - (2026-07-25) 계획 문서에 "현 상태" 칸을 반드시 두고 계획/현실을 섞지 마라(3자 회의 반복 지적). 같은 표에 "코디가 할 수 있다"(설계 판정)와 "지금 되고 있다"(구현 상태)를 한 칸으로 합치면 페페가 미구현을 가동중으로 오독한다. 판정 등급(A/B/C/K)과 구현 상태 배지(가동중/미구현/사람 전속)를 항상 분리 병기하고, 검증 안 된 판정은 "잠정"을 붙인다(예: 카톡 접수 A → 카톡 텍스트로 실측 전까지 B잠정).
- (2026-07-25) 수집 대상(거래처)의 이익·고지·이의제기를 설계에 넣어라(3자 회의 '거래처' 렌즈 산출). 통화·카톡 수집은 상대가 동의한 적 없는 기록이다. 최소 4항목을 갭으로 관리 = 고지(통화 시작 구두 안내·단톡방 참여자 전원 고지)·보존기한·정정/파기 창구·이의제기 경로. 페이지·랭킹표의 실명은 기본 마스킹(초성), 협상 내용은 대분류로 순화. 카톡 수집 개시(P3) 게이트에 봇탐지 회피(코디 리스크)뿐 아니라 거래처 보호절차도 선행조건으로 넣는다.
- (2026-07-25) ⛔ 화물 앱
[화물등록]버튼은 코디 영구 금지(하드락). 전국24시콜화물 앱(kr.co.call24.everyonefreight2)의 화물등록 = 화물망에 콜이 실제로 뿌려지는 행위(기사가 잡으면 차가 온다) = C등급 사람 전속. 코디 상한 = 폼을 다 채워놓는 것까지. 구현 시 탭 함수에 제출버튼 라벨 블랙리스트(히트 시 예외) + 1회 1건 + 완료 후 스크린샷·값요약 보고 + 앱 내 전화걸기 금지. 근거·계획 =devplan/freight-dispatch.html. - (2026-07-25) WebView 앱은 좌표 말고 접근성 노드 라벨로 조작(화물 앱 실측).
EF_Cargowlist는 WebView지만 uiautomator에 라벨·bounds·enabled가 그대로 노출 → OCR 불필요, 좌표 하드코딩 불필요. 단 WebView 디버깅 소켓은 닫혀 있어(/proc/net/unix에 devtools 없음) DOM 직접 접근은 불가. ⚠ 스크롤 위치가 바뀌면 같은 좌표가 다른 항목을 누른다 — 실측 사고: 좌표 재사용으로 메인메뉴의 센터전화연결·사용법까지 들어갔다. 매 조작 전 노드 재조회, 그리고 BACK 누르기 전 focus(액티비티) 확인(팝업인 줄 알고 BACK 하면 화면을 벗어난다). - (2026-07-25) 외부 앱 조사 후엔 흔적 원복이 작업의 일부. 탐색 중 들어간 임시 입력 삭제 + 한글 IME 삼성 복구 + 홈 + 화면끄기 + "등록 0건"을 앱 내역 화면으로 확인하고 보고한다(내가 안 했다는 주장 대신 앱이 말하게 한다).
- (2026-07-25) 📛 프로젝트명 =
poin-agent(구 note20-agent, 페페 지시). 정체 = PFS 보조 에이전트(통화·카톡 수집 → 정리·보고·PFS 게시 + 가구 KB 축적). 폰 제어는 수단. 하위 통합 = call-mapping·worklog-triage·kakao-role(별개 프로젝트 아님, 한 파이프라인의 구간). 경로 =projects/poin-agent/·C:\dev\tools\poin-agent· devplan 허브poin-agent.html. - (2026-07-25) ⭐ 업무 판정 원칙 = 「정보」와 「행위」의 경계(페페 지시 "할 수 있는 것과 없는 것 정확히 구별"). 코디 = 정보를 다루는 일(읽기·내부시스템 쓰기·보고 — 되돌릴 수 있음). 사람 = 바깥세상 행위(통화 주문·금액/납기 확약·거래처 방 발언·물리 확인 — 되돌릴 수 없고 돈·관계에 닿음). ★"등록"과 "실행"을 절대 같은 것으로 적지 말 것:
dispatch행을 만들어도 차는 오지 않는다(실제 배차 = 화물 콜 전화 주문). 산출물은 배차 기록이지 배차가 아니다. 같은 함정이 발주·입고일정·견적에 전부 있다. 등급 = A완결/B초안/C불가/K승인 4단, 실측 분포 A254(63.5%)·B31·C90(22.5%)·K25. - (2026-07-25) 🚫 PFS에 worklog 생성 API가 없다(조사 확정).
/api/worklog/*는 기존 행 큐레이션 전용이고INSERT INTO worklog가 DAO에 0건 — 현재는 외부 프로세스가 MySQL에 직접 INSERT. 그래서 스키마 계약이 조용히 깨질 수 있고 감사로그·되돌리기 경로가 없다. pfs 게시를 늘리기 전에POST /api/worklog신설이 선행. 인증은 Flask 세션 쿠키뿐(토큰 없음) → 스크립트는POST /api/auth/login후 쿠키 유지.kakao_room도 동일(생성 엔드포인트 없음). - (2026-07-25) 카톡 수집 개시 순서 = 하드락 → 초대 → 수집. 페페가 방에 초대하는 것이 병목이지만, 발신 fail-closed 하드락이 코드에 먼저 들어가야 한다. 거래처 방에서 코디가 말할 수 있는 경로가 존재하지 않는 것이 카카오 제재 회피의 1순위 조건이라 순서를 바꾸면 안 된다.
- (2026-07-25) devplan 정밀 도표는 손으로 쓴 인라인 SVG로, imagegen은 개념 일러스트에만. 나노바나나는 이미지 안 한글 텍스트를 신뢰성 있게 못 그린다 → 수치·라벨이 들어가는 도표·관계도·파이프라인은 인라인 SVG(테마 토큰 재사용·검색 가능·정확), imagegen은 텍스트 없는 개념 일러스트(히어로·은유)만. 선례 =
devplan/poin-agent.html+devplan/img/pa-*.png. ⚠imagegen은 Python312 절대경로로 실행(구 사유였던 "PATHpython=hermes venv"는 2026-07-27 hermes 폐기로 무효, 절대경로 관례는 유지). 또 gemini 웹UI가 동의 다이얼로그(mat-dialog-container)를 띄우면 클릭이 막히므로 "나중에" 버튼으로 닫고 재시도. - (2026-07-25) ⚠ 배치 에이전트가 파일↔내용을 뒤바꾼다 — 산출물은 반드시 원문 유사도로 전수 검증. 실측: 153통 교정 중 3개 파일이 A→B→C→A 순환 스왑(메타데이터 who/room/date는 정상인데
corrected/facts/field_guess만 남의 통화 것). 육안·스팟체크로는 절대 못 잡는다(각 파일 내용은 그럴듯함). 탐지법 =difflib.SequenceMatcher(원문, 교정본).ratio()전수 스캔 — 정상은 0.93~1.00, 스왑된 것만 0.03~0.04로 확연한 이상치. 적대 검증 렌즈 2개가 독립적으로 같은 버그를 잡아냈다(단일 렌즈였으면 놓쳤을 것). 배치 fan-out 산출물은 기계적 대조 지표를 하나 반드시 넣을 것. - (2026-07-25) 사전 매칭이 발화 사실을 덮어쓰지 않게 할 것. 실측 오류: 원문 "진영 생상무님" → dict의
미림 시트 진영생이사에 맞춰 직함까지 "이사"로 변조. 이름 경계 교정(진영+생상무님→진영생+상무님)은 타당하나 상무↔이사는 발음 무관 — 사전에 그렇게 적혀 있다는 이유로 화자가 실제로 말한 직함을 바꾸면 안 된다. 교정 허용 근거 = 발음 유사성이며, DB 레코드 일치는 그 자체로 근거가 아니다. - (2026-07-25) 현장
conf=confirmed는 "원문에 그 이름이 실제로 등장"할 때만. 실측 과신: 원문에 "의정부"+"LH"만 있는데 dict에LH 의정부 우정이 유일해서 confirmed로 찍힘 → likely가 맞다. 사전에 후보가 하나뿐인 것은 추론 근거지 확증이 아니다. - (2026-07-25) 🚫 pfs
field마스터에 현장 아닌 것이 섞여 있다 — 현장 추론 전 블랙리스트 필수(페페 확정).강동식 차장류는 거래처 담당자 이름+직급이지 현장이 아니다. 실측 = 현장 1420건 중 21건 오염(사람 이름+직급 18 =^[가-힣]{2,4}\s?(차장|부장|과장|대리|이사|상무|전무|소장|팀장|사장)+사장님*/ 거래처명이 현장으로 등록 3 =fields ∩ companies= 넥서스·우아금속·유로글라스). 블랙리스트 =talklog/data/calls/_correct/field_blacklist.json, 정제 사전 = 같은 폴더dict_raw.json(_excluded_fields보존). ⚠단순 직급어 정규식은 오탐 다발 —욕실장·화장대 하부장·개발팀 상부장은 가구,GS 상무 센트럴은 지역(광주 상무지구),현대리바트는 "대리" 오매칭. 반드시 이름(한글2~4자)+직급 앵커로 잡을 것. - (2026-07-24) 자동 반영 범위 = worklog(현장기록)까지만(페페 결정, D5 확정). 자재·배송 사실은 승인 없이 worklog에 자동 기록하고 되돌리기로 커버. 발주·배차·입고일정·견적 등 실제 업무 데이터는 초안까지만(사람이 반영). 금액·확약은 손대지 않음. 확대는 자율성 루프가 정확도 실적으로 승격 제안 → 페페 승인 시에만.
- (2026-07-24) ⛔ 전건 승인 UI 금지 = 승인은 노동(페페 교정). 100건 넘는 항목을 사람이 하나씩 승인하는 화면은 일을 줄이는 게 아니라 새 일을 추가하는 것. 설계 기본값 = 분야별 자율 처리 + 예외만 사람. 승인 게이트는 되돌릴 수 없는 것(금액·확약·외부 발신)에만 남긴다. → 목업
devplan/worklog-triage.html의 129건 카드 승인 방식은 폐기 대상. - (2026-07-24) 판단 단위 = 통화 1건(페페 지시). 문장 단위로 쪼개면 맥락이 끊긴다.
room+reg로 묶어 1통화=1판단(실측 129항목→48통). 개별 사실 분해는 에이전트 몫. - (2026-07-24) 현장 추론 = 상대(연락처) 배경으로(페페 지시). 대화에 현장명이 없어도 통화 상대의 이력(과거 통화·카톡·pfs 발주/배차 진행건)으로 추론한다. 실측 근거 = 상대 상위 5명이 전체 86%(단골 소수) → 상대 프로필만 잡으면 대부분 해결. 확정 추정 가능한 건은 사람에게 묻지 말고 에이전트가 바로 매칭.
- (2026-07-24) 원문 녹음 재생 = 보류(페페 판단). 사람이 다시 듣는 전제면 자동화 가치 불명.
- (2026-07-24) 대화 요약 = 전사 원문 복사 금지(페페 지시). 통화·카톡 전사를 그대로 옮기지 말고 문맥을 읽어 핵심만 명사형으로 정리한다. 대화체 금지(“~할게요/~인가요” 등 종결어미·구어 그대로 두지 않음). 원문은 근거용으로 접어서 보관(승인 판단 시 펼쳐 확인). 적용 선례 =
devplan/worklog-triage.html. - (2026-07-24) 대화 분류 축 = 현장(field) + 거래처(company) 2축(페페 교정). site_name 자동추정값은 업체명이 섞여 있어 현장 분류로 쓰면 안 된다(실측: 최근 2주 129건 중 현장 특정 14건뿐, 나머지 115건은 자재·물류 통화라 현장이 애초에 없음). 현장 기준으로 묶되 현장 미지정 건은 거래처 단위로 묶고 거래처 필터를 유지한다. worklog
field_noNULL = PFS 현장 미연결. - (2026-07-24) ⛔ 단톡방 발언 정책 = 기본 읽기 전용(페페 결정). 방 대부분이 거래처 방이라 코디는 발언하지 않는다. 자사 직원 방에 한해 페페가 필요시 특별 허용할 때만 답변. 발신은 fail-closed(허용 목록에 없으면 차단)로 구현하고, staff 방이어도 건별 페페 승인을 거친다. → §3 레드라인 확장 / 계획 =
devplan/kakao-role.html - (2026-07-24) 금액·납기·하자 책임 등 확약성 발언은 코디가 절대 하지 않는다(자사방 포함 — 캡처되어 밖으로 나갈 수 있음). 모르면 "확인 필요"로 답하고 페페 에스컬레이션. → §3
- (2026-07-24) 연결 기본 = 유선 USB(
R3CR103JBBY). 무선ADB는 보류(공유기 AP 단말간 차단, 필요 시 페페가 해제). → §1 - (2026-07-24) 케이블 뺐다 다시 꽂아도 디버깅 인가 유지(
adb devices=device).unauthorized면 그때만 폰에서 재승인. → §1
확립 규칙
§1 연결·환경
- 연결 = 유선 USB 기본. ADB=
C:\dev\tools\platform-tools\adb.exe, 시리얼R3CR103JBBY. 무선(192.168.45.66:5555)은 보류. - 무선 불통 = 코드 버그 아님: IP·adbd 정상인데 PC↔폰 ping 양방향 실패 + 게이트웨이는 성공 → AP 단말간 차단(client isolation) 확정. 코드로 해결 불가(
connect()예외 메시지에 진단 박아둠). 다시 헤매지 말 것. connect()는 죽은 무선IP에서 hang →_adb가 TimeoutExpired 삼키고 usb fallback(필수 동작).- ⚠
python실행: ~~PATH의python이 hermes venv를 먼저 잡는다(uv trampoline 에러=junction 깨짐)~~ = 2026-07-27 hermes 전면폐기로 무효. 이제 PATHpython= Python312. playwright·CDP 스크립트는 여전히 Python312 절대경로 권장. - python 실행은 항상
PYTHONUTF8=1prefix(전역 규칙,rules/tooling.md).
§2 화면·좌표 — 세로화면 고정 = 필수 전제 (2026-07-23 페페 지시, 근본수정 완료)
adb 작업 중 폰 자동회전이 켜져 가로화면이 되는 이슈가 실재. 가로가 되면 좌표계 전체가 뒤집혀(1080x2400 ↔ 2400x1080) 모든 하드코딩 좌표·스와이프가 엉뚱한 데로 가고, 화면 밖 스와이프는 조용히 무시된다 → "메뉴 항목이 없다"는 유령 오진을 낳음(실제로 이 버그로 공지 메뉴를 "없다"고 오판했다).
- 고정 방법: P.portrait() = accelerometer_rotation 0(자동회전 끔) + user_rotation 0(세로). connect()마다 자동 실행(프로세스당 1회) + app() 실행 직후 force=True 재적용.
- ⚠ 카톡은 실행 시 화면을 가로로 뒤집는다(회전잠금 걸려 있어도). 그래서 connect 시점 1회로는 부족 → 앱 실행 후 재적용이 필수. 실측: 재적용 전 in room: (2400,1080) → 재적용 후 (1080,2400) 유지.
- ⚠ wm size로 방향 판정 금지 — 물리 패널 크기(항상 1080x2400)라 회전해도 안 변함(내가 이걸로 오판했다). dumpsys window displays의 cur=WxH(회전 반영)를 봐야 한다. P.size()/P.is_portrait()가 이걸 쓴다.
- 좌표는 화면크기 계산 대신 노드 bounds에서 유도하는 게 근본적으로 안전 → 리스트 스크롤은 _find_in_list()가 scrollable 컨테이너 자체 bounds 안에서 스와이프(회전 무관).
- 재잠금 대비: unlock 성공해도 조작 중 잠금화면 복귀함(실측). 매 조작 전 잠금상태 재확인 + 필요시 재unlock. P.awake() 컨텍스트매니저가 이걸 담당(finally에서 화면 끔).
- is_locked()는 포커스 라인만 판정(Bouncer/Keyguard/StatusBar/NotificationShade). dumpsys 전체에서 "Keyguard" 문자열 찾으면 잠금 아닌데 True → 켜진 화면에 스와이프 → 알림셰이드가 앱을 덮어 작업 전부 실패(수정 완료, 재발 주의). 스와이프 시작 y=1800(2000은 제스처바라 home 제스처로 먹힘).
- unlock 직후 팝업이 화면을 덮는 케이스: MtpPopupActivity(USB연결)·CellBroadcastAlertDialog(재난문자) → BACK으로 대개 닫히나 재난문자는 확인버튼 좌표탭 필요. 조작 전 focus가 com.kakao.talk인지 확인 필수.
§3 봇탐지 회피 (최우선 원칙)
- ⚠ 최우선 = 봇 탐지 회피: 카카오가 봇으로 잡으면 안 됨(제재). 불법 아님(카카오 봇 API 미제공에 대한 개인 커스텀). UI 터치로만(패킷/프로토콜 조작 금지), 랜덤 딜레이·상한 준수·급증 회피. 카카오 탐지신호 5 = 단기 대량 친구추가/방생성, 어뷰징 유사 기기·IP, PC에뮬레이터 감지, 신고. 실물폰+adb가 유리(에뮬 아님). 친구추가 하루 소수·간격분산. poin3133=친구0 신규계정이라 워밍업 필요. 정량 상한 비공개.
- 좌표 지터: 균등분포 금지 → 가우시안(타겟 박스 중심=μ, σ=박스 크기의 15~20%), 가장자리 인셋 8~10%. 특허 명시: "오차범위 내 반복"(항상 중심±3px 같은 좁은 흔들림)도 패턴으로 걸림 — σ가 박스 대비 충분히 커야 함.
- 타이밍: 액션간 300~1500ms 로그정규분포(순수 uniform도 매끈해서 패턴 될 수 있음). 5~15% 확률로 2~5초 "딴짓" 정지 삽입.
- 탭 방식:
input tap대신input swipe x y x y D(동일좌표, D=80~180ms 랜덤)로 통일 — 손가락 dwell 흉내. 스크롤도 거리·속도(duration) 매번 다르게. - 뒤로가기: 좌표탭 대신
KEYCODE_BACK논리키(좌표편차 이슈 자체가 없음). - sendevent/저수준주입 금지: 비루팅 확정 불가(root 필요).
input이 유일 경로 — 고민 불필요. ADB injected touch는 API 레벨(getSource()=SOURCE_TOUCHSCREEN,getToolType()=FINGER)에서 실터치와 구분 불가. - 화면ON 최소화: uiautomator/tap은 화면ON+언락 필수 → 저빈도 트리거(예: 장문읽기는 500자 초과 확정時만, 즉시반응 아닌 약간 지연).
- 🚫 레드라인: ①발신 자동화와 읽기 자동화 결합 금지(정책이 명시하는 밴 사유 그 자체) ②동일좌표·동일duration 하드코딩 금지 ③에뮬레이터·화면미러링(scrcpy 등) 경유 금지 ④연속장시간 화면ON 금지.
- 정책 근거(talksafety.kakao.com): 카카오 자동감지축 = 단기 대량행위 + 비정상환경 + 연속장시간(특허 KR101915802B1 = 24~48h). 읽기전용 열람은 이 축들에 해당 없음 — 읽기 자체를 지목하는 정책 문구 없음.
§4 카톡 조작 (P3 확립)
- 한글 입력 = ADBKeyBoard(
com.android.adbkeyboard/.AdbIME) APK 설치·활성화 →ime set으로 전환 후am broadcast -a ADB_INPUT_TEXT --es msg '한글'(긴 문자열·특수문자는ADB_INPUT_B64base64). 숫자는 삼성 허니보드로도 OK. 작업 후 기본 IME 삼성 복구 필수(adb_ime()컨텍스트매니저 — 안 하면 페페가 폰 들었을 때 키보드 없음). APK=C:\dev\tools\poin-agent\ADBKeyboard.apk. - 친구추가 = 친구탭 → 친구추가(person+) → "연락처로 추가"(전화번호+이름 개별 입력, 대량 자동추가 회피) → 확인. 카톡 통합검색은 이미 친구인 사람만 찾음.
- 문자 발송 = 친구 프로필 → 1:1채팅 → 메시지 입력필드 탭 → ADBKeyBoard 입력 → 전송(▶).
- 화면 좌표는 회전에 민감 — 세로 고정(§2), 절전방지(
stay_on_while_plugged_in 7). 조작 전 스크린샷 육안 확인. sendvsreply선택:reply=알림 캐시 필요(그 방이 리스너 기동 후 메시지를 보냈어야 함)·앱 안 염·봇탐지 최저 /send=캐시 불필요(우리가 먼저 말 거는 유일 경로)·UI 구동·전송 후 입력칸 빈 것으로 성공 검증.- ⭐ 노드 파싱 = content-desc를 본다(
.text아님) — 카톡은 접근성 노드에 텍스트를 content-desc로 실음. uiautomator가 한글 잘 읽음 → OCR 불필요. 메시지본문=resource-id "message", 발신자=nickname, 방제목=toolbar_default_title_text. - 방목록 파싱: 현 카톡 26.6.1엔
chat_room_list_item없음(talklog ID 낡음). 방 행 = class=Button, content-desc="{방이름}, 새로운 메시지 N개, {미리보기}"로 파싱. - 탭 이동은 TAP으로 — 카톡은 친구탭으로 열린다. BACK 반복으로는 채팅탭에 못 감(
open_room()이 채팅탭 탭 후 방 진입,read_long/send/notice공용). - 공지는 방당 1건만 노출 — 새로 등록하면 기존 공지 교체(다이얼로그 명시). 원본 메시지는 대화에 남아 재등록 가능. 공지 등록 = 게시판 글로도 자동 등록됨.
§5 검증·마무리
- ⚠ 덤프 한 장으로 "없다" 단정 금지 — 스크롤 컨테이너를 끝까지 훑고 캡처로 눈으로 확인한 뒤 판단. (실제 오판 사례: 1:1 방에 "공지/게시판 없다"고 보고 → 틀림. 스크롤 좌표가 화면 밖이라 스크롤이 안 먹은 것이었다.)
- 작업 후 화면끄기 필수(페페 지시):
phone.py sleep(keyevent 223 +stay_on·타임아웃 되돌리기). 실패 경로에서도awake()finally가 끔. 우리 작업 밖에서 켜진 화면은 watcher 30초 루프의sleep_if_idle()이 처리(상세 = 🆕 26.8.3). - 경로 함정: Git Bash가
/sdcard를 Windows 경로로 오염 →export MSYS_NO_PATHCONV=1필수. dump 회수는adb exec-out cat /sdcard/_ui.xml(pull은 경로오염). - watch 백그라운드: 파이썬 stdout 블록버퍼 →
print(flush=True). logcat 직접 감시는 Monitor 도구가 더 견고. - 회귀 검증:
python phone.py selftest(xml 파서 +is_locked오탐 + 스크롤 컨테이너 좌표 유도 assert). - 🆕[2026-08-04 · 현업 P0-1]
watcher.py의PROMPT/REBUILD_PROMPT를 고치면 회귀테스트가 선행이다 —PYTHONUTF8=1 python sgc/test_watcher_rules.py(8항목, 폰·claude 없이 규칙 로직만). 통과 못 하면 고치지 말고 되돌린다. 이유 = 지금까지 프롬프트 변경이 전부 사고 난 뒤 규칙을 덧붙이는 사후대응이었다(섹션 붕괴·코드펜스). 테스트는 있었는데 강제되는 자리가 없었다 →watcher.pyPROMPT 정의부 바로 위에 같은 문구를 주석으로 박아뒀다(코드 로직 변경 0). - 🆕[코디 26.10.9] 「PFS 카톡관리 동기화 실패 · 502 Bad Gateway /api/auth/login」 = 거의 항상 pfs-live 운영배포의 uWSGI 재시작 순간이다(26.10.9 09:07·09:15·11:42 실측 —
journalctl -u pfs-live.uwsgiStopping/Started 시각과 초 단위 일치, nginxrecv() failed (104)). 다음 5분 주기에 자동 회복. 판정 =runs.jsonl의pfs_sync_fail직후 회차 +python -c "import pfs_board_sync as p;print(p.run_once(True,print))"가(방수, 0)이면 정상._PFS_FAIL은 성공 시 0 리셋 → 단발 실패마다 알림이 나간다(노이즈).