poin-agent — 작업 규칙 (rules)
이 파일 = note20 폰·카톡 조작 작업 규칙의 단일 출처. 상태·진행·구현이력은
handoff.md, 여긴 규칙만. 갱신 지침(필수): 새 규칙·교훈·함정이 나오면 그 답변에서 바로 아래🆕 신규에 1줄 append(날짜 + 규칙 한 줄 + 근거 포인터). 다음 세션으로 미루지 않는다. 신규가 쌓이거나 안정화되면확립 규칙의 해당 §로 원문 이관(삭제 금지, cut&paste).
📑 인덱스 (필요한 항목만 열어 읽는다)
| § | 내용 | 언제 |
|---|---|---|
| §1 | 연결·환경 (유선 기본·adb·python) | 세션 시작·연결 실패 시 |
| §2 | 화면·좌표 (세로고정·재잠금·팝업) | 모든 UI 조작 전 필수 |
| §3 | 봇탐지 회피 (지터·타이밍·레드라인) | 카톡 조작 전 필수 |
| §4 | 카톡 조작 (IME·친구추가·발송·노드맵) | 카톡 기능 구현·실행 시 |
| §5 | 검증·마무리 (단정 금지·화면끄기·경로함정) | 작업 끝낼 때 |
🆕 신규 (미편입 · 최신 위)
- 🏷(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(월)(전역 기본규칙, 상세user_brief/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).