danggeun-ai-study 작업 규칙
전역 =
C:\dev\CLAUDE.md. 여기엔 당근 수집·페이지 빌드 함정만 쌓는다. devplan 일반 규칙 =projects/devplan/, 웹 UI 규칙 =projects/web-designer/.
🆕 신규
- 🔴07시 자동게시가 「USB로 붙은 노트20이 없다 / R3CR103JBBY unauthorized」로 죽으면 «폰»이 아니라 «adb 서버»를 먼저 의심한다(26.9.22 t013) · [코디]: 07:01 게시가
phone.connect()에서 즉사했다. 메시지가 「USB 디버깅 허용을 확인할 것」이라 페페가 폰을 만져야 하는 일처럼 보이지만 아니었다 —adb kill-server→start-server한 번에 같은 폰이 바로device로 돌아왔다(승인 키는 멀쩡). 즉 굳은 건 PC 쪽 adb 서버 상태다. ⛒처방 =phone.Phone.connect()안에서 USB·무선 둘 다 못 찾았을 때 서버 재시작 1회 후 재조회(C:\dev\poin-agent\phone.py) —_sh를 타는 폰 도구 전부(post_dg·watcher·watch)가 한 번에 덮인다. 두 번은 안 한다 — 2회차도 unauthorized 면 그건 진짜로 폰에서 허용을 눌러야 하는 상태라 거기서 멈추는 게 맞다. 검증 =phone.py selftest(가짜 adb 가 1회차 unauthorized → 2회차 device 를 내주고, kill/start-server 호출까지 assert). ⚠수동 게시 재시작은daily_post.py --now로 하면 된다(차례·카드 판정을 그대로 다시 탄다). - 🔴🔴양보(0순위 카톡)에서 돌아오면 «화면»만이 아니라 «앱»도 돌려놔야 한다 — 안 그러면 카톡 대화목록에 덮인 채로 이어간다(26.9.18 t009 게시 실패) · [코디]: 26.9.15 처방(
phone._sh의 화면유지 재설정 +unlock())으로 잠금화면 문제는 잡혔는데, 오늘 같은 자리에서 또 죽었다 —_post-nopicker.png에 찍힌 건 잠금화면이 아니라 카톡 채팅 목록이었다(07:49:42watcher.py가 방 20개를 훑던 시각). 0순위의awake()finally 가to_chat_list()로 끝내기 때문이다(자기 다음 실행을 위한 정리라 그쪽은 못 없앤다). ⛒처방 =phone.Phone.front_pkg(기본 None) — 양보 복귀 블록에서 그 패키지를monkey -p <pkg> -c android.intent.category.LAUNCHER 1로 다시 앞으로 올린다(새 인스턴스가 아니라 있던 태스크가 올라오므로 쓰던 에디터 화면이 그대로 온다). 켜는 쪽 =post_dg.main의P.front_pkg = dg_ui.PKG— 화면을 «이어서» 쓰는 도구만 켠다. 검증 =phone.py selftest(양보복귀 assert 4개 · front_pkg 없으면 앱을 안 띄운다까지). ⚠폰 충돌 창 =watcher.py(0순위)는 매 :19·:49(30분 주기)에 폰을 잡는다 — 게시는 6~14분이라 :00~:15 에 시작하면 안 겹친다. -
🔴헤드리스 클로드
--max-turns 1은 모델이 첫 턴을 «도구 호출」에 쓰는 순간 답 없이 「Reached max turns (1)」로 끝난다(26.9.17 실측) · [코디]:rounds.claude_json은 도구를--disallowedTools로 전부 막아 두는데도 그렇다 — 같은 설정으로 스펙 생성은 성공하고(09:01) 캡션 생성만 2회 연속 실패(09:08)했다. 결과 =card_prep이 캡션 없이cards[]를 못 박고 멈춤 → 다음날 07:00 게시가[쉼] 카드 8/0장으로 빈다(카드 PNG 는 다 있는데 원장이 비어 보이는 상태 = 이 증상이면 여기부터 본다). ⛒--max-turns 2(danggeun\rounds.py·rounds.py·watch.analyze·card_prep공용). 실검증 = 같은 경로로 t010 캡션 1회차 성공. ⚠캡션은 사람이 써도 된다 —tips.json의caption4줄(마지막 줄 = 꼬리 문구 고정)만 채우면card_prep이 그 단계를 건너뛴다. ⚠LLM 이 쓴 캡션 첫 줄의 「어제는 …」은 반드시 확인한다 — 본문엔 없는 연결이라 예시 캡션을 보고 지어낸다(t010 이 그랬다). -
🔑멤버판 「GPT 상의」(클로드 ↔ 코덱스 왕복 교차검토) =
codex exec두 줄로 끝난다 · 실측 제약 5개(26.9.15) · [코디]: 코디 구조(C:\dev\tools\gptapp\gptapp.py ask)는 단발(--ephemeral)이라 그대로 주면 왕복이 안 된다. ①구독 판정은codex login status한 줄(「Logged in using ChatGPT」) —auth.json파싱 불필요 ②1라운드에--ephemeral을 붙이면 세션이 안 남아 resume 불가 ③codex exec resume은-s·--color·-C를 안 받는다(unexpected argument로 즉사) → 샌드박스·모델은 원 세션 계승, 폴더는 cwd 를 옮겨서 맞춘다 ④Git Bash 에서-C·-o에 MSYS 경로(/c/...·mktemp -d)를 주면os error 2→ 윈도우 경로(C:/...) 로 준다 ⑤--last는 다른 대화가 끼면 엉뚱한 세션을 잇는다 → 출력 상단session id:(또는--json의thread.started.thread_id)를 적어 두고 그 ID 로 재개. 왕복은 1회, 많아야 2회(재개도 새 추론이라 구독 한도가 깎인다 — 코덱스 답). 실측 = 1라운드 →resume --last2라운드가 문맥을 이어받는 것까지 확인(C:\dev\_tmp\cxdemo\a1.md·a2.md). 💰토큰 실사용(페페 기록~\.codex\sessions33세션 집계 · 26.9.15) — 기준은 비캐시입력+출력(코덱스가 화면에 찍는tokens used와 같은 값). ①codex_exec(=코디 상의, 17세션) 첫 질문 중앙 6,363(3,824~15,006) · 이어묻기 중앙 4,640 · 세션 합 중앙 9,387 = 왕복 1회 ≈ 1만 ②Codex Desktop(사람이 앱에서 직접, 15세션) 첫턴 11,279 · 세션 합 28,900 ③코드를 읽히고 고치게 시키면 자릿수가 바뀐다 — 한 세션 537,915(codex_work_desktop1건) = 상의를-s read-only·「글로만 답해라」로 묶는 실증 근거. ④클로드 쪽 부담은 왕복 1회당 자기 컨텍스트 +3,000~7,000(이 세션 transcript 실측 — 질문이 길수록 커진다). 집계 한 줄 =~\.codex\sessions\**\*.jsonl의token_count.info.total_token_usage(누적이라 차분해야 턴별이 된다). -
🔴🔴
_hidden.vbs의cmd >> 로그파일은 그 파일을 «쓰기 독점»으로 잡는다 — 파이썬이 같은 파일에 append 하면PermissionError로 첫 줄에 즉사한다(26.9.15 07시 미게시 사고) · [코디]: 재부팅·스케줄러 문제가 아니었다. 예약작업은 07:00:01 에 정확히 발화(LastTaskResult 0· 놓친 트리거 0)했고,daily_post.py가log("[대상] …")첫 줄에서 죽었다(같은 날 09:00card_prep.py도 동일). 원인 = 26.9.14 에 붙인daily_post_hidden.vbs/card_prep_hidden.vbs의) >> "…\daily_post.log" 2>&1리다이렉트.watch.py·listen.py는 원래log()가try/except라 같은 함정을 조용히 넘기고 있었고, 그 두 파일에서 복사해온daily_post·card_prep의log()만 가드가 빠져 있었다. ⛒처방 =log()의 파일쓰기를try/except Exception: pass로(로그는 안 빈다 —print가 리다이렉트로 같은 파일에 들어간다) +__main__을 감싸 죽으면 텔레그램(예약작업은 창이 없어 traceback 이 로그에만 남고 아무도 모른다 = 이번에 페페가 앱을 보고서야 알았다). 재현 = 6줄 스크립트를cmd /c ( python t.py ) >> t.log로 돌리면 100% 난다. ⚠새_hidden.vbs를 만들 때마다 본다 — 리다이렉트 대상과 스크립트 자체 로그가 같은 파일이면 가드가 필수다. -
🔴모임 대표사진(=당근 용어 「모임 프로필 이미지」) 교체는 «모임장» 전용 — 칼리는 운영진(초록 왕관)이라 못 바꾼다(26.9.14 실측) · [코디]: 칼리 계정
모임 홈 → ≡ → 설정에는 「모임 정보 수정」이 없다(있는 것 = 모임 알림 설정 · 내 모임 프로필 · 모임 통계 · 모임장봇 설정 · 운영 가이드북 · 전체 멤버 목록 · 나가기). 멤버 목록에서 남을 ⋮ 로 관리할 수 있어 「모임장인가」 오판하기 쉬운데, 개설자는 페페(26.09.08) 고 칼리는 26.09.09 가입이다. ⛒대표사진 교체는 페페 계정 1회 조작으로 넘긴다. ⚠설정 화면의모임 프로필 이미지노드는 그냥 그림이라 눌러도 피커가 안 뜬다(ChatRoomSettingActivity그대로). - 🔑대표사진은 «정사각 1장»인데 모임 홈 배너는 세로 가운데 띠(≈21%~79%)만 보여준다(26.9.14 실측) · [코디]: 배너 1080×630 · 썸네일·앨범은 정사각 전체. 그래서 로고·라벨을 위아래 끝에 두면 홈 배너에서 잘린다 — 지금 대표사진도 전부 그 안전대 안에 들어가 있다. 새 대표사진 도구 =
C:\dev\devplan\danggeun\gen_group_cover.py(나노바나나 그림 + PIL 로 클로드 마크·라벨 ·--text로 글자만 재조판 · 배경 참조 =_cover_ref.png). -
🔴모임명이 바뀌면 이름 정확일치로 방을 찾던 코드가 전부 죽는다 — 26.9.14 개명(「AI스터디 AI코딩 업무자동화」 → 「AI스터디:칼리🐱」)으로 진입 실패, 같은 날 수리 · [코디]: ⛒모임명 단일 출처 =
dg_ui.GROUP_TITLE(표시용) · 방 찾기는 이름 대신dg_ui.ROOM_RE(=[^"]*전체방) 조각 매칭(tap_label(..., exact=False)) — 개명에 안 흔들린다. 고친 곳 =watch.py(GROUP_TITLE/GROUP_ROOM 을 dg_ui 에서 가져옴) ·dg_chat.goto_members·dg_room(ROOM·INTRO·goto_room) ·probe_sched_chat.py·rounds.PROMPT· 원장admin.json·members.json+ 허브 재빌드. 검증 =watch.py --demo38항목 ·dg_room.py --demo16항목 · 실기_probe_home.py진입 성공(막혀 있던 전체방 채팅 16건이 그때 들어왔다). ⚠listen.GROUP_KEYS는 「AI스터디」 조각이라 개명에도 그대로 맞는다(손 안 댐). -
🔴🔴
/it(대화형만) 예약작업은 그 시각에 «로그온 세션»이 없으면 통째로 건너뛴다 — PC 가 켜져 있어도 안 돈다(26.9.14 07시 미게시 사고) · [코디]: 팁 게시가 07:00 에 안 나갔다. PC 는 9/10 부터 무재부팅·절전 0(Kernel-Power 42/107 없음)인데danggeun-daily-tip·danggeun-card-prep·1회성 보고알림 셋이 전부 09:33 에 일제히 발화 = 그때 세션이 생겼다는 뜻(결과코드0x80070490). ⛒처방 = ①StartWhenAvailable(놓친 트리거 따라잡기)을 켠다 —powershell: $t=Get-ScheduledTask …; $t.Settings.StartWhenAvailable=$true; Set-ScheduledTask -InputObject $t②한낮에 「오늘의 팁」이 튀어나오지 않게daily_post.LATE(10시) 가드 — 넘으면 안 올리고 텔레그램만 ③claude·CDP 가 필요 없는 작업은 SYSTEM 으로 돌리는 게 근본(폰 adb 는 SYSTEM 에서 된다 =listen.py선례). 🔴Microsoft-Windows-TaskScheduler/Operational로그는 기본 꺼져 있다 — 사후에 아무것도 못 본다.wevtutil sl … /e:true(el.py)로 켜 뒀다. -
🔴
phone._dump가 adb 타임아웃을 «예외»로 던져 재시도 4회가 통째로 무의미했다(26.9.14 게시 1회 즉사) · [코디]:subprocess.run(timeout=30)이TimeoutExpired를 올리면 재시도 루프가 깨지고 그대로 위로 튄다 — 당근 사진 피커(썸네일 수백 장)에서 30초를 넘겨 게시가 죽었고, 폰은 피커 화면에 멈춘 채 도즈로 빠졌다(mWakefulness=Dozing·mFocusedApp=MediaPickerActivity). ⛒except subprocess.TimeoutExpired로 잡아 재시도에 포함 + 창을 60초로(C:\dev\poin-agent\phone.py). ⚠복구는post_dg.py --explore한 번이면 된다(open_app(fresh=True)가 앱을 새로 띄우고 카드도 다시 푸시한다 — 초안 잔재 없음). -
🔴화면 판정을 「조회」 한 단어로 하지 마라 — 당근이 상세 루트를 바꿔 수집이 이틀 멈췄다(26.9.14 수리) · [코디]:
watch._open_first_post와 순회 루프가"조회" in _root(xml)로 상세를 쟀는데, 실측 상세 루트는자유 게시판 <제목> <본문…> … 댓글이고 「조회」·「이전」은 루트엔 없고 전체 XML 에만 있다 → 글은 멀쩡히 열렸는데 「아니네」 하고 되돌아갔다(9/13 20:11·22:10 두 주기 연속 「첫 글을 못 열었다」). ⛒새 판정_is_detail(root)= 「추천순으로 보기」(목록 표식)가 없고 + 「댓글」이 있고 + 60자 초과(글쓰기·프로필 화면은 둘 다 아니다) ·watch.py --demo에 네 경우 박아 뒀다. ⚠오프셋 640 은 뺐다(하단 네비게이션에 닿아 앱이 내려간다). 진단 도구 =_probe_home.py(홈 노드 지도) ·_probe_open.py(탭 후 루트 글자). - 🔑글을 안 쓴 멤버는
watch가 영영 못 잡는다 — 멤버 목록을 따로 대조해야 한다(26.9.14 = 앱 13명 vs 원장 6명) · [코디]:watch.collect()→apply_posts()는 글 작성자만members.json에 넣는 구조라, 가입만 하고 글을 안 쓴 사람은 원장에 안 들어온다. 실제로 5명(네모·으갸갸·차차·호호우·자몽에이드)이 빠져 있었다. ⛒대조 =PYTHONUTF8=1 python _list_members.py(모임 홈 → 「멤버 N」 → 스크롤 스크린샷) → cody-vision 으로 닉네임·동네·가입일 읽어members.json에state=가입인사 대기로 append. 게시판 목록 대조는_list_posts.py [--board 가입인사]. -
🔴게시 여부는 원장이 아니라 앱이 정본이다 — 원장 밖에서 올라간 글이 있다(26.9.14 t008) · [코디]:
tips.json엔state=draft인데 앱엔 7시간 전에 이미 게시(조회 6·좋아요 1)돼 있었다. 자동 게시(daily_post) 가동 전에 손으로 올린 건이라 원장에 안 남은 것. ⛒주기적으로_list_posts.py로 목록을 떠서posted_at을 맞춘다. ⚠연재라 순서가 틀어지면 「어제는 …, 내일은 …」이 거짓말이 된다 → 게시일 보정(D014 선례)까지가 한 작업이다(26.9.14 = t005 의 어제·내일, t006 의 「어제는 저장점」을 실제 순서로 고쳤다). -
🔑카드 스펙은 이제
img/<id>/spec.json이다 — 파이썬 소스(make_cards_nb.POSTS)에서 뺐다(26.9.14) · [코디]: 매일 1세트를 헤드리스 claude 가 써야 해서 옮겼다. 소스에 박으면 문법 오류 하나로 생성기가 통째로 죽고(옛 세트의--only N --text보정까지 막힌다) LLM 출력을 exec 하는 셈이 된다. JSON 이 못 담는 셋만 로더가 되돌린다 —lay(kind 에서 유도: cover=L_COVER · flow=L_CORNER · rule/outro=L_RULE, 예외 0건) · 색 이름(GREY/LIME/ORANGE/LIME_D) ·loop튜플. ⛒마이그레이션 검증은 「옛 dict 와 로더 결과 동일성」 + 「--text재합성 PNG 바이트 비교」 두 겹으로 했다(t005·t008·r001 28장 diff 0) — 렌더 파이프라인은 한 줄도 안 건드렸다는 증거가 이것이다. - 🔑카드 굽기 전에
make_cards_nb.py --post <id> --lint· [코디]: 🔴fit()은 글자가 넘치면 소리 없이 60%까지 줄인다 — 그림은 멀쩡하고 그 장만 글씨가 작아져 사람이 안 보면 모른다. 그래서 린트가 실제로 글자 레이어를 그려 보고 축소율을 읽는다(<0.8 FAIL · <0.92 WARN). 규칙으로 글자수를 세는 게 아니다(폰트마다 다르다). 같이 보는 것 = 7~10장·1번 cover·마지막 outro·kind별 필수 칸·flow 상자 3~5개·scene 영어 전용·한글 칸의 대외비 낱말(scene 은 영어라point같은 오탐이 나서 제외). 실측 = 기존 3세트 FAIL 0(r001 #3 만 WARN 0.82) · 일부러 깨뜨린 6종 전부 FAIL. - 🔴옛 초안 6편(t002·t006·t007·t009~t011)엔
caption이 없다 —cards[]를 넣는 순간 재빌드가 죽는다(26.9.14 실제로 깨뜨렸다) · [코디]:tip_doc()이 카드가 있는 글에서post["caption"]을 무조건 읽는다 →KeyError로 빌더가 멈추고,\Cody\danggeun-rounds가 5분마다 같은 실패를 반복한다. ⛒복구 =card_prep.py --veto <id>(cards 비우기) 한 방. ⛒근본 =card_prep.make_caption()이 캡션 없는 글에 4줄을 만들어cards[]와 같이 넣는다(30편 t012~ 는 초안에 이미 들어 있어 안 탄다). - 🔴게이트·린트 문턱은 반드시 실파일을 재서 잡는다 — 보고서 숫자를 믿지 마라(26.9.14 첫 실전에서 8장 중 6장 오탐) · [코디]: 카드 크기 하한을 설계 보고의 「기존 3.2~3.6MB」로 잡았는데 실측은 352~889KB(t005·t008·r001·t006 36장)였다 → 멀쩡한 카드 6장이 FAIL 로 걸려 반영이 멈췄다. 지금 기준 = 200~2000KB(하한은 「그림이 안 들어간 빈 종이」를 거르는 선이지 품질선이 아니다). 같이 잡힌 것 = 카드가 이미 다 있으면 굽기를 건너뛴다(빈
--only는int("")로 죽는다). - 🔑카드 세트는 매일 09:00 에 하루 앞서 굽는다 —
card_prep.py(예약\Cody\danggeun-card-prep· delix/it) · [코디]: 흐름 = 다음 차례 글 → spec.json 없으면 헤드리스 claude(opus)로 생성 → 린트(실패하면 오류를 붙여 1회 재요청) →make_cards_nb.py로 없는 장만 굽기 → 장수·크기·해상도 검사 → PNG 를 다 쓴 뒤 마지막에tips.json의cards[]+state=ready → 재빌드 → 텔레그램(컨택트 시트 사진). 🔴순서가 거꾸로면\Cody\danggeun-rounds(5분 재빌드)가 PNG 없는 cards[] 를 보고 5분 안에 빌드를 깬다. 🔴daily_post.ready()는cards[]장수만 보므로 cards[] 를 쓰는 순간 그 글은 다음 07:0x 에 나간다 = 검수는 「거부권」 모델(사람이 안 하면 나간다) → 물리기 =card_prep.py --veto <id>· 한 장만 다시 =make_cards_nb.py --post <id> --only N. 앞서기 상한 2편(AHEAD_MAX— 초안은 나중에 손볼 수 있어 30편을 미리 굽지 않는다) · 06:48~08:00 엔 안 돈다(게시 작업과tips.json이 겹친다) · 자동 재시도 없음(있는 spec·raw 를 재사용하니 다음날이 곧 이어받기다). - 🔑팁 캘린더는 「달마다 표 하나」다(26.9.14 · web-designer 처방) · [코디]: 그 전엔
posts[0]의 달 하나만 그려서 다음 달 글이 화면에서 통째로 사라지고 자체검사가 깨져 빌더가 파일을 안 썼다(30편 넣기 직전에 발견). 고친 곳 =cal_months()신설(호출부만 교체,cal_html()무수정) · 자체검사 2개(캘린더 수 == 달 수· 날짜 완전성을 표마다 따로 — 페이지 전체로 세면 9월·10월이 1~30 을 공유해 한 달이 통째로 빠져도 통과한다) · 여백 CSS 는 반드시.dg-cal-months스코프(전역.dg-tblwrap은 다른 페이지 12곳이 쓴다). 글 목록도 카드 → 한 줄(.dg-tiprow) 로 바꿨다(42편이면 카드 방식은 폰에서 ≈9,900px). - 🔑팁 게시 = 매일 07:00~07:10 랜덤 자동(페페 지시 26.9.14) · [코디]: 예약작업
\Cody\danggeun-daily-tip(매일 07:00 · 사용자 계정/it— adb·폰 락 때문에 SYSTEM 불가) →daily_post_hidden.vbs→daily_post.py가 0~600초 자고 게시한다(랜덤은 예약작업이 아니라 스크립트 몫). 고르기 =tips.json미게시분 중date가 가장 이른 글 한 편. 🔴차례를 건너뛰지 않는다 — 팁은 「어제는 …, 내일은 …」 연재라 카드가 없으면 그날은 쉬고 텔레그램만 보낸다(뒷 글 먼저 올리면 흐름이 깨진다). 게시 성공하면state=posted·posted_at+ 그 글 date 를 게시일로, 남은 초안을 하루씩 뒤로(캘린더=실제 게시일 D014) →build_danggeun.py. 🔴실패해도 자동 재시도 안 한다(폰 GUI라 어디까지 갔는지 모른다 — 본문만 올라간 뒤 재시도하면 글이 둘). 알림에 다음 차례 카드 N/N 이 붙으니 고갈을 하루 먼저 안다. 수동 =daily_post.py --now|--dry|--post <id>· 자체검사--demo· 로그daily_post.log. - 🔴게시판 선택 시트 좌표는 「게시판 개수」에 따라 움직인다 — 이미 맞으면 시트를 열지 마라(26.9.12 게시 실패 1회) · [코디]: 모임에 게시판이 늘면(그날 AI뉴스 · 일정 후기 신설)
XY_BOARD_FREE=(540,2066)이 다른 줄을 가리킨다 → 자유 게시판으로 열려 있던 에디터를 AI뉴스로 바꿔 놓고 3회 재시도 끝에 죽었다. ⛒처방 =post_dg.pick_free_board첫머리에서 게시판 줄(전폭 1080 노드)이 이미 「자유 게시판」이면 그대로 통과(시트를 안 연다). 당근이 직전에 올린 게시판을 기억하므로 보통 이 길로 끝난다. ⚠유령 노드 주의 = 모임 홈 게시판 탭도 「자유 게시판」 라벨인데 191x50 이라 폭(>900)으로 가른다. ⚠기본값이 자유 게시판이 아닐 때만 시트를 여는데, 그 좌표는 그때 다시 실측해야 한다(개수가 또 바뀌면 또 밀린다). - 🔑모임 후기도 팁 파이프라인을 그대로 쓴다 — id 접두만
r(26.9.12 1차 후기r001) · [코디]: 원장 =tips.jsonposts(같은 배열) · 카드 =img\<id>\+make_cards_nb.pyPOSTS["<id>"]· 게시 =post_dg.py --post <id>. 빌더·캘린더·모달은 id 를 안 가려서 그대로 돈다. ⚠카드는 10장까지 — 당근 첨부 상한 실측이 10장(t004)이라 11장 이상은 시도하지 마라(초안 11장 → 10장으로 줄였다). ⛔후기에서 빼는 것 = 실명·닉네임·회사/브랜드명·근무형태·주소·지출액 · 모임장 사업 내부 · 대외비 파이프라인(녹음정리·영상요약, 26.9.9 지시) — 회사는 「분야」까지만(웹디자인 · IT보안 · 가구). 팁은 용어는 쓰되 만드는 방법은 안 쓴다(기능·효과만, 페페 지시 26.9.12). 재료 = 모임 녹음 정리본C:\dev\talklog\data\lectures\lecture-<날짜>.md의 요약 절. -
🔑전체 페이지 기간한정 공개 =
danggeun\site.json({token, expires}) +publish_dg.bake_site()— 닫기는 「스크립트를 다시 돌리는 것」이다(26.9.12 1차 스터디 공개) · [코디]:publish_dg.py가 굽기 전에pub를 비우므로,expires가 지난 뒤 한 번만 다시 돌리면 전체공개본이 안 구워져 링크가 그 자리에서 죽는다(멤버 개인 4장·목업은 그대로 다시 구워진다 = 무영향). 닫기 예약 =\Cody\danggeun-pub-close(SYSTEM ·pub_close_hidden.vbs· 1회성). ⚠입구 = 관리페이지(<tok>.html), 나머지는<tok>-<이름>.html— 페이지끼리의 링크·이미지를 전부 pub 평면 파일로 바꿔 굽는다(서버 없이/dg/에서 돈다). ⚠멤버 페이지엔 그 멤버의window.DG_PUB(개인 토큰 창구)를 머리에 박아 답 저장처가 개인링크와 같아진다 — 토큰 없는 멤버(가입인사 전)는DG_LOCAL. ⚠카드 PNG 는 장당 3.5MB(1024×1536 RGBA)라 폰에서 안 열린다 → 600KB 넘는 PNG 는 JPEG q82 로(≈300KB, 알파 전부 255라 안전). 검사 = 구운 페이지의 내부참조가 pub 에 다 있는지(252개 실측 0 누락). -
🔴devplan 페이지에 부트스트랩 모달을 달면 오른쪽 위를 비워라 — qahelper 돋보기 토글이 모달 닫기(×)를 덮는다(26.9.12 D030 제품관리) · [코디]:
.modal-header{padding-right:72px}(헤드.hd-top의 오른쪽 100px 와 같은 이유 · 공개본은 qahelper 가 빠져도 무해). ⚠목록 + 편집 두 칸 모달을 폰에서 상세로 전환하게 만들면 「연 항목을 골라 둔 채 열기」가 목록을 통째로 가린다 → 좁은 화면(768 미만)은 선택 없이 목록부터 연다(matchMedia로 가름) · 상세로 넘어가면 검색줄도 숨긴다. ⚠토스트는 모달(1055) 위로 —z-index:1090. -
🔴페페 화면 배치 말투 = 파워포인트식 — 「항목 슬라이드」 = 카드 목록(왼쪽) · 「메뉴 · 컨트롤」 = 설정(오른쪽)(26.9.12 D029 「좌우 사이드 메뉴가 바뀌었다」) · [코디]: D028 을 반대로(왼쪽 설정 · 오른쪽 목록) 읽고 실측 45/45 로 넘겼다 — 검증기가
#list·#inspector의 존재 · 보임만 재서 좌우가 뒤집혀도 통과했다. ⛒배치 지시가 걸린 화면은 검증기에 위치 검사(getBoundingClientRect().left순서)를 넣고, 고치기 전 페이지에서 그 검사가 FAIL 나는 것부터 확인한다(C:\dev\_bench\haedali-detail\verify_mockup.py48항목). 배치 해석이 둘로 갈리면 D027 원문(「우측 사이드 메뉴에 컨트롤」)처럼 첫 지시와 맞는 쪽을 고른다. -
🔴공개 폴더
C:\dev\devplan\danggeun\pub\는publish_dg.py가 굽기 전에 통째로 비운다(파일만 — 하위 폴더는os.remove가 실패해 굽기가 죽는다)(26.9.12 해달이 목업 공개) · [코디]: 손으로 넣은 공개 파일은 다음 굽기에 사라진다 → 공개물은 전부publish_dg가 굽게 한다(목업 =bake_mockup· 토큰 접두 평면 파일). ⚠목업 토큰은mock_tokens.json따로 —tokens.json에 넣으면/dg-api쓰기 창구가 그 토큰을 멤버로 받는다. ⚠자체검사 문자열 검사는 인라인 theme.css 주석(href="/assets/theme.css"사용법)과 CSS 주석(qahelper)에 오탐 → 주석 제거 ·qahelper.js로 좁혔다. -
🔴네이버 스마트스토어 실물 수집 = 실 크롬 CDP 「기본 컨텍스트」만 통과한다(26.9.11 해달이 상세페이지 목업) · [코디]: headless · Playwright
launch(channel="chrome", headless=False)· curl(429) · WebFetch · CDP 크롬에new_context(iPhone 에뮬)전부 「현재 서비스 접속이 불가합니다」([에러페이지]). ⛒전용 CDP 9347(launch_haedali.bat+_hidden.vbs· portgate claim)에connect_over_cdp→b.contexts[0].new_page(). ⚠__PRELOADED_STATE__는 빈 뼈대(salePrice 0 · 옵션 null)라 못 쓴다 — 렌더된 DOM · 스크린샷이 정본. ⚠headed full_page 캡처는 49k px 부근에서 헤더부터 다시 찍힌다(반복 구간은 버린다). 스크립트 =C:\dev\_bench\haedali-detail\probe_cdp.py plain. -
🔴당근 세팅 지시문 드라이런엔 페페 PC 환경이 섞인다(26.9.11 D026 드라이런) · [코디]: ①코덱스 = 전역
C:\Users\delix\.codex\AGENTS.md가 새 대화의 「이어서」를brief_today(devplan 브리핑)로 가로챈다 → 시험 프롬프트에 「이 폴더 AGENTS.md 가 규칙서 · 전역 지침 쓰지 마라」를 못 박는다 ②코덱스exec -s read-only(gptapp--cd)도 Bash(Session 0)에선 셸이 시간 초과돼 파일 읽기조차 못 한다(26.9.11 재현) → 코덱스 검증은 화면 세션에서 ③헤드리스 클로드에도 사용자 훅 · 규칙이 새어 든다(--settings '{"hooks":{}}'인데도 답에[규칙위반]꼬리 · 「Write 가 디스크에 안 남는다」며 heredoc 으로 다시 씀) → 판정은 답 문구가 아니라 폴더에 남은 파일로 한다. 스크립트 =C:\Users\delix\AppData\Local\Temp\claude\c--dev\81459087-1679-4c11-9896-845b3a25b459\scratchpad\dryrun_history.py. -
🔴복사 지시문엔 AI 마다 처리가 갈리는 항목을 넣지 않는다(26.9.11 [페페] D025 「처리방법이 중구난방이다. 당장은 사용자 직접 확인」) · [코디]: 대화 크기 50% 를 AI별 분기(원 · 도넛 · CLI 설정)로 지시문에 넣었다가 통째로 뺐다. 3 AI 공용 1장이 원칙이라 한 문장으로 세 AI 가 같은 일을 못 하는 항목은 사람 확인(STEP 멤버 칸 · 차이표 참고)으로 돌린다. 지시문에 새 항목을 넣기 전 「세 AI 가 같은 문장으로 같은 일을 하나?」부터 본다.
-
🔴대화 크기(컨텍스트) 표시는 AI · 화면마다 다르다 — VS Code 확장 기준 실물 확인(26.9.11 D022 · D024) · [코디]: 클로드 확장(2.1.263) = 입력창 파이가 쓴 양 50% 초과일 때만 나타난다(
webview/index.jsif(U>=50)return null· 클릭 = 즉시 압축) · 코덱스 확장(26.5908) = 입력창 아래 도넛이 늘 보이고 툴팁NN% used (NN% left)→ 50% 이상이면NN% full(한국어NN% 참) · 제미나이 Code Assist(2.100.0) = 표시 없음(명령 /about /init /mcp /memory /tools 뿐) → CLI 를 VS Code 터미널에서 +ui.footer.hideContextPercentage:false→NN% used, 기본model.compressionThreshold0.5 라 50% 에서 자동 압축 → 0.7. ⚠터미널판은 다르다 — 코덱스 CLI 는 「NN% context left」(남은 %). 🔑문서에 없으면 확장 번들을 직접 연다:https://marketplace.visualstudio.com/_apis/public/gallery/publishers/<pub>/vsextensions/<name>/latest/vspackage(코덱스openai/chatgpt는?targetPlatform=win32-x64를 붙이면 에러 JSON — 빼야 받는다) →python -m zipfile -e→ 문구 grep(큰 웹뷰는grep -l -F로 파일부터 찾고 파이썬str.find로 잘라 본다 —.{0,300}정규식은 200초 넘게 걸렸다). 공식 문서(learn.chatgpt.com · Code Assist 문서)엔 둘 다 표시 얘기가 없었다. -
🔴수집기가 작성자 프로필 화면을 본문으로 긁어 가입인사 원문을 덮는다(26.9.11 [페페] 발견 · 발생 26.9.9 20:26·22:12 KST). 로그 신호 = 「작성자 프로필이 안 열렸다」 뒤 같은 작성자
162자수집 · 제목이 매너온도(51°C) · 본문에 「이 멤버의 자세한 활동 내역」「채팅하기」「받은 후기」. 지문(작성자 + 본문 앞 120자)이 달라 새 글로 취급 →watch.apply_posts가text를 갈아끼운다(제목도p["title"]우선이라 같이 덮인다). 같은 스크랩은seen.json에 박혀 재적용 안 되지만 후기 수·방문 수가 바뀌면 지문이 달라져 또 덮는다. 🔑복원 원천 =C:\dev\devplan\danggeun\incoming\<날짜>-<id>.json(수집 원본이 글마다 남는다 — 이모지 엔티티가 풀린 최신 것을 쓴다). ⏳가드(프로필 화면 표지 문구가 있으면 버림)는 페페 결정 대기. - 🔴🔴당근 스터디 카드 = 나노바나나 그림 + PIL 글자가 기본이다(26.9.11 페페 지시 D019 「당근스터디 카드는 나노바나나+PIL 로 작성을 기본 지침으로 해라」 · t005 9장 품질 승인) — 생성기
C:\dev\devplan\danggeun\img\make_cards_nb.py(새 글 =POSTS["<id>"]에 장별 사양 추가 →--post <id>· 결함 장--only N그림째 /--only N --text글자만). 구판make_cards.py(ChatGPT 이미지가 글자까지 그림)는 안 쓴다 — 아래 ChatGPT 카드 절들은 기록용. 컨셉(t004 그림체 · 레이아웃 · 정면 마스터시트 참조 사슬)은 그대로 유효. -
🔴세팅 페이지 검증 함정 4개(26.9.11 D018 · 스크래치
verify_setup.py·dryrun_claude.py·dryrun_codex.py) ①윈도우 클립보드는\n을\r\n으로 돌려준다 — Playwrightnavigator.clipboard.readText()가 원문보다 줄 수만큼 길게 나온다(48줄 → +47자) →.replace("\r\n","\n")뒤 비교 ②부트스트랩scroll-behavior:smooth라scrollIntoView직후elementFromPoint는 엉뚱한 요소를 잡는다(가림 오탐 3폭 전부) →scrollBehavior='auto'+ 500ms ③헤드리스 클로드는.claude\settings.json을 사람 허락 없이 못 고친다(acceptEdits 여도) — 멤버 실사용에선 허락창 「예」, 페이지 차이표에 적어 뒀다 ④코덱스workspace-write는 작업폴더 안 삭제를 안 묻는다 →~\.codex\rules\default.rulesprefix_rule(decision="prompt"), 문법은codex execpolicy check --rules <파일> rm x로 실측. ⚠setup.json에<로 미리 적지 마라 —rich()가 한 번 더 이스케이프해 화면에<가 그대로 나온다(자체검사가 막는다). ⑤codex exec -s workspace-write를 Bash 도구(Session 0) 에서 돌리면 실행기 연결 시간초과 +Failed to write file— 쓰기 드라이런은 안 되고 판단만 검증된다. 그리고 새 작업폴더를~\.codex\config.toml에[projects.'<경로>'] trust_level = "trusted"로 자동 등록한다(전역 설정 mtime 이 바뀌어 「안 건드림」 검사가 오탐 — 내용으로 대조할 것). -
🔴공개 쓰기는 8799 를 Funnel 에 붙이지 않는다 — 전용 최소 핸들러로(26.9.11 D017). 8799 = devplan 정적 서빙 + 쓰기 API 전부라 하위 경로만 붙여도
%2e%2e가 normpath 로 풀려 폴더 안 어디든 닿는다. ⛒danggeun_api.PubHandler(BaseHTTPRequestHandler · 정적 없음 · 정규식 완전일치 2개)를 8799 app.py 데몬 스레드로 127.0.0.1:8806 에 띄우고 Funnel/dg-api. 🔑Funnel proxy 는 마운트 접두어를 떼고 넘긴다(로그 실측/<tok>/answers) — 핸들러는 붙든 떼든 받게.restart.py가 8806 LISTENING PID == 8799 PID 까지 센다. - 🔴8799(pythonw) 안에서 도는 코드는 stdout/stderr 가 None —
BaseHTTPRequestHandler기본log_message가 예외,notify.py·build_danggeun은 import 만 해도sys.stdout.reconfigure로 즉사. ⛒log_message오버라이드 · 텔레그램은 broker127.0.0.1:7777/notify-done직접 POST · qid 식은 한 줄 복제하고 demo 가 대조. - ⚠윈도우
ThreadingHTTPServer는allow_reuse_address=1이라 옛 프로세스와 같은 포트를 둘이 잡는다 → 새 창구는allow_reuse_address=False(겹치면 실패가 낫다). - ⚠CSS
display:block이[hidden]을 이긴다 —.dg-btn.lg{display:block}은hidden=true로 안 숨는다 →style.display. - ⚠「브라우저에만 저장」이라고 안내한 데이터를 서버로 옮길 땐 자동 업로드 금지 — 보여주고 멤버가 눌러야 보낸다. 프리필할 때
dataset.last도 채워야 blur 만으로 안 올라간다. - 🔑공개링크 쓰기 e2e 는 격리 창구로 — Playwright
ctx.route('**/dg-api/**')로 실제 funnel 페이지의 API 호출을 임시 원장·알림 가로채기PubHandler로 돌린다 = 운영 원장·텔레그램 무영향. 재실행 =PYTHONUTF8=1 python C:\dev\devplan\_verify_danggeun_pub.py. 운영 창구는 curl 로 읽기·거부 경로만 친다(유효 POST 는 5분 뒤 페페에게 알림이 간다). - ⚠tailscale funnel 파일서버(
/dg/)는 Cache-Control 없이 Last-Modified 만 준다 — 재굽기 후 이미 연 멤버는 휴리스틱 캐시로 옛 페이지를 볼 수 있다 → 재안내 링크엔?v=N. -
⚠재굽기 전후 qid 집합 대조는
grep -h(파일명 빼기)로 —grep -o … pub/*.html | md5sum은 줄마다 경로가 붙어서 절대/상대 경로 표기만 달라도 해시가 바뀐다(26.9.11 「qid 가 바뀌었다」 오경보 — 실제론 동일). qid 가 진짜 바뀌면 멤버 폰에 남은 답이 고아가 된다(서버 화이트리스트가 거부) → 질문 원문을 고칠 땐 이 대조가 필수다. -
🔴나노바나나 칼리가 옆을 보면 무늬가 좌우 반전으로 나온다(26.9.11 t005 4 · 6장 = 9장 중 2장, 둘 다 몸을 보는 쪽 왼쪽으로 튼 구도) — 서브에이전트 검수는 「무늬 일관」으로 통과시켰다. 검수는 장마다 얼굴 기준 보는 쪽 왼쪽 = 회색 줄무늬 · 오른쪽 = 주황을 따로 본다. ⛒처방 = 재굽기 말고(또 반전될 수 있다)
make_cards_nb.pyPOSTS해당 장에flip=True(compose 가 raw 를 거울로) →--only N --text. 그림엔 글자가 없으니 거울이 무해하다. -
🔑카드 = 나노바나나 그림 + PIL 글자 판(26.9.11 D016 ·
C:\dev\devplan\danggeun\img\make_cards_nb.py) — 그림엔 글자 0, 칩·제목·증상 칸·인용 블록·도식·마무리 줄은 PIL(제목 Juaimg\fonts\Jua-Regular.ttf· 본문 Noto Sans KR 가변). 3장 시험 = 칼리 무늬·화풍 일관 · 오탈자 원천 0 · 영문(NOW)도 그대로. 함정 4개 ①모델은 「위 48% 비워라」를 반만 지킨다(card-03 장면이 위로 올라와 인용 블록이 칼리 머리를 덮었다) → 그림 위치를 믿지 말고 PIL 이 장면 bbox 를 찾아 글자 칸 아래로 옮긴다 ②imagegen.generate(strip_watermark=True)는 「피사체를 위쪽에」 여백 문구를 붙여 위를 비우는 판형과 정반대 →False로 부르고 하단 15% 를 직접 자른다(9:16 → 자르면 ≈2:3, 워터마크 반짝이도 그 띠에 들어간다) ③나노바나나 원본이 572×1024 로 받아져 1.8배 확대 — 모아 보기에선 티가 안 나지만 고해상 폰에선 선이 무를 수 있다(업그레이드 = imagegen 캡처가 원본 해상도를 받게) ④Jua 의 여는 따옴표 「“」 는 작은 점처럼 나온다 → 따옴표만 Noto 굵게. -
🔴devplan 모달 실측은 「DOM 클릭 + 가림 따로 재기」로 한다(26.9.11 팁 캘린더) — ①Bootstrap 모달은 fade 전환 중 Escape·닫기를 무시한다(열리자마자 Escape → 5초 뒤에도
.show) → 700ms 기다린다 ②공용 qa-helper 토글(우상단 고정 42px) 이 390px 에서 모달 닫기 X 를 덮는다(모든 모달 공통 기존 결함 · 바깥 탭으로는 닫힘 · 위젯은 devplan 전역이라 손 안 댐) ③Playwrightclick(force=True)도 좌표로 누르는 것이라 덮은 위젯이 클릭을 먹는다 → 연결 확인은el.click()(DOM), 사람 손 닿는지는scrollIntoView({block:'center'})뒤elementFromPoint로 따로 잰다. 실물 = 스크래치verify_cal.py. -
🔑팁 캘린더 날짜 = 실제 게시일(26.9.11 페페 D014) — 초안 칸보다 먼저 올리면 그 글을 올린 날로 옮기고 뒤 초안을 전부 같은 만큼 당긴다. 순서가 그대로라 글끼리의 「어제 · 그제 · 내일은」 참조는 안 틀어진다. 틀어지는 건 날짜에 박힌 말뿐이다(3편 「오늘은 첫 모임 날」 — 모임 = 9.12 토) → 옮긴 뒤
오늘|내일|어제|그제|첫 모임|요일|아흐레로 훑는다. 한 칸에 여러 편이 들어갈 수 있다(9.10 = 1편 · 2편) — 옛cal_html()의{date: post}는 같은 날 글을 조용히 덮었다(모달은 남아 자체검사도 통과) → 날짜별 목록으로 그린다. 옮기기 도구 예 = 스크래치shift_tips.py(옛 날짜 assert 후 교체). -
🔑카드 검수 = 눈 판독 + cody-vision 교차 → 걸린 자리만 원본 확대(26.9.11 · t003 9장) — cody-vision(flash-lite)이 2곳을 짚었는데 둘 다 오탐이었다(card-07 「첫 과제는」→「과지는」 · card-06 제목 끝에 없는 「?」 = 옆 장식 획을 물음표로 읽음). ⛒경고만 보고 재생성하지 말고 PIL crop + 2배 확대로 그 자리를 직접 본다(재생성 1장 ≈ 3분 + 이미지 한도). 반대로 vision 이 조용해도 통과가 아니다 — card-04 에 같은 메모가 4번 반복된 걸 vision 은 1건으로 합쳐 보고했다(반복·누락은 눈으로 센다). 참고 = High 9장 굽기 28분(장당 ≈ 3분, 재시도 0).
-
🔴차수 페이지에 코디·사람이 붙이는 내용은
rounds.json말고 별도 파일로(26.9.10 · 추천 대여공간 →danggeun\venues.json) — rounds.py 는 rounds.json 을 처음에 읽고 → 헤드리스 정리(수 분) → 통째로 덮어쓴다(watch.jdump(STATE, st)). 그 사이 고친 notes 는 조용히 사라진다. 게다가 notes 는rich()라<b>·<code>·<i>만 통과 — 링크를 못 건다. 새 원장은load_venues()처럼 빌더가 따로 읽고, 자체검사에 「렌더 개수 = 원장 개수」 한 줄을 붙인다. -
🔑팁 편성 뼈대 = 멤버 공통 7단계(세팅 → 업무 해부 → 파일럿 1개 선정 → 손으로 1회 왕복 → 규칙 고정 → 자동화 → 확장 · 통합). 편 순서를 옮기면 「내일은」 예고와 「어제 · 그제 글」 참조가 줄줄이 틀어진다(26.9.10 · D012 9.12~9.20 편성)
- 실측 = 저장점 편을 9.17→9.14 로 당기자 예고 3곳 · 날짜 참조 4곳 · 흐름 나열 1곳을 같이 고쳐야 했다. ⛒순서를 바꾼 뒤엔
tips.json을 읽어 「내일은」 예고 ↔ 실제 다음 글 제목을 나란히 찍어 눈으로 대조한다(날짜 · 요일 · 필수 필드 · 금지어 · 문장당 느낌표 1개 이하도 같이 — 26.9.10 은 임시 스크립트로 돌렸다). -
⚠「N차」는 스터디 차수(
rounds.json)와 팁 편 번호가 겹치는 말이다 — 원장에 그 차수가 없으면 팁 편으로 읽고, 보고에 해석을 적는다. -
🔑🔑팁 카드 컨셉 기준 = t004 「그릴링」 카드세트(26.9.10 페페 확정 「이번 카드세트를 앞으로 컨셉 기준으로」) · ⚠생성 경로는 26.9.11부터 나노바나나+PIL(🆕 맨 위 D019) — 아래
make_cards.py·STYLE4언급은 구판 경로 - 그림체 =
make_cards.py의STYLE4문단 그대로(세밀한 펜 선·수채·종이결 + 연두·주황 가는 강조 + 귀여운 애니 풍 칼리 · 로고 금지 · 군더더기 글자 금지). 레이아웃 = 규칙 칩 · 2줄 제목 · 점선 증상 줄 · 「규칙서에 이렇게 적어 두세요」 연두 인용 블록 · 맨 아래 마무리 줄(REQUIRED). - 🔑고양이 정본 = 정면 마스터시트 한 장
C:\dev\devplan\media\danggeun\kali-master-front.png(원본 = t004 표지의 칼리 · 굽기make_cards.py --post sheet). 새 글 표지는 이 시트를 참조로 물리고, 2장부터는 표지를 문다(사슬 = 시트 → 표지 → 나머지). -
⛔옆·뒷모습 시트는 만들지 않는다(페페 「좌우 칼라가 달라서 이미지 생성에 어렵다. 정면 시트만」) — 한쪽 회색·한쪽 주황이라 돌린 그림에서 무늬가 뒤집힌다. 무늬 기준 = 보는 사람 기준 왼쪽 회색 줄무늬 · 오른쪽 주황 · 흰 주둥이·가슴·네 발 · 황록 눈 · 회색 줄무늬 꼬리.
-
🔑🔑팁 카드 2편부터 = 글별 폴더 +
--post· 「귀엽게 + 세밀함 유지」 처방 (26.9.10 · t004 그릴링) - 폴더 =
make_cards.py --post t004→C:\dev\devplan\danggeun\img\t004\card-NN.png(t001 은 옛 자리img\그대로). 게시 =post_dg.py --post t004가 본문(caption)·카드 폴더·장수를 그 글에서 가져온다(옛 코드는posts[0]·9장 고정이었다). 빌더 자체검사도 카드 있는 글 전부를 센다(갤러리 개수 = 카드 있는 글 수 ·<figure>= 카드 합). - 그림체 = 스타일 문단의 선·수채·종이 질감은 세밀하게 그대로, 고양이 문단만 「cute, lightly animated — big shining eyes, soft round cheeks, lively pose」로 올린다. 반려됐던 건 「귀여움」이 아니라 플랫·단순화였다(
STRICTLY AVOID: flat vector clip-art, thick uniform outlines, simplified icon shapes). - 고양이 = 칼리 프로필(
C:\dev\devplan\media\danggeun\kali-profile.png)을 표지에만 참조로 물리고 「ONLY the reference for face and fur — do not copy its layout」를 적는다 → 표지가 캐릭터 정본, 2장부터는 표지 참조(t001 사슬 그대로). 무늬를 문장으로도 박는다(왼쪽 회색 줄무늬 · 오른쪽 주황 · 흰 주둥이 · 황록 눈). 표지 1회 합격(한글 오탈자 0). - 🔴
make_cards.py가 이제 CDP 9334 를 스스로 띄우고 끈다(cdp.ensure→finally: stop_started). 전엔 크롬이 떠 있다고 가정했다 — 26.9.10 엔 9334 가 꺼져 있었다(cdp.py --ports).chatgptimg는 띄우지도 끄지도 않는다(부모 몫). - 🔴🔴ChatGPT 이미지가 「AI 말풍선」 아이콘에 진짜 OpenAI 로고(매듭)를 그려 넣었다(t004 card-05) — 클로드 팁 글에 경쟁사 로고 = 사고. ⛒스타일 문단에
NEVER draw any real brand or company logo — no ChatGPT/OpenAI knot, no Claude/Anthropic mark, no Google or app icons+ 대체물(스파클·발바닥 낙서)을 적는다. 말풍선·채팅 UI 를 그리게 하는 카드는 반드시 로고부터 본다. - 🔴「영문 금지」만 걸면 한글 장식이 대신 들어온다(t004 card-03 — 책등 「좋은 질문」·「더 나은 만들기」, 메모 「차근차근 좋은 걸 만들자」 5개). 1·2장은 0개라 세트가 들쭉날쭉해진다. ⛒
NO extra words anywhere — neither Korean nor English. Book spines, notebooks … stay blank or faint scribble lines. 주제를 돕는 라벨(묶인 질문카드의 「질문1·2·3」, 끄덕끄덕)은 봐준다. - ⚠인용 블록 첫 줄이 명사 나열이면 소제목으로 뽑힌다 — 「설계 계획 새로 만들기는」이 굵은 「설계 계획」 + 다음 줄에 붙은 「새로 만들기는…」로 쪼개졌다. ⛒첫 줄을 문장으로(「설계나 새로 만드는 일은」).
- 🔴🔴사진은 커서 자리가 아니라 「친 글 끝에서 정확히 8자 앞」에 들어간다(26.9.10 실측 3회 · t001 첫 게시 포함) — 「 전해드릴게요!」 · 「해드릴게요!\n\n」 ×2, 끝 모양이 달라도 늘 8자. 옛 처방 「끝에
\n\n」은 틀렸다(8자 중 2자만 막는다). 키보드 탓도 아니다 — 본문부터 마지막 사진까지 ADB 키보드를 쥐고 넣어도 똑같이 갈렸다. ⛒body_text()끝 = 빈 줄 10개(8자가 빈 줄 안에서 갈린다) — ✅3차 게시로 검증(꼬리 온전 · 18:24 게시). - 🔴🔴게시 직전 가드가 본문에 「VVV」를 쳤다(26.9.10 t004 1차) — 사진을 넣고 나면 편집 칸 포커스 때문에 루트 글자가 빈다(ⓒ) → 옛 가드가 「게시판 아님」으로 오판해
pick_free_board를 불렀고, 그 시트 좌표 (540,2066)는 키보드가 떠 있으면 「v」 키다. ⛒새 글 경로는 작성 첫머리 확인으로 끝(submit(board_ok=True)), 이어쓰기 경로도 좌표 없이 멈추기만 한다. 교훈 = 좌표를 누르는 복구 동작을 「확인」 단계에 넣지 마라 — 화면이 예상과 다르면 그 좌표는 다른 것이다. - 🔑게시 전 꼬리 검사
tail_ok()= 본문 마지막 7자(「전해드릴게요!」)가 덤프에 한 덩어리로 있나. 갈렸으면 완료를 안 누르고 멈춘다(초안만 남는다). 글 전체 덩어리 노드도 블록 사이를 줄바꿈으로 끊어서 판정이 선다(프로브 실측). 26.9.10 2차 게시를 이게 막았다. -
🔴고양이가 크게 앉는 카드는 맨 아래 마무리 줄을 조용히 뺀다(t004 card-05 v2 · card-09 — 둘 다 나머지 글자는 완벽했다). 「Closing line at the bottom」 정도로는 약하다. ⛒
REQUIRED closing line at the very bottom — do not omit it+line 1:/line 2:+ 「고양이를 작게, 마무리 줄에 제 자리를 남겨라」를 같이 적는다(card-05 v3 한 번에 복구). 검수 체크리스트 = 제목 · 본문 줄 수 · 맨 아래 줄 있음 · 로고 · 군더더기 글자. -
🔑🔑차수별 스터디 = 전체방 「[일정]」 카드가 차수, 정리는 사용자 계정 5분 예약작업(26.9.10 ·
danggeun\rounds.py· 원장danggeun\rounds.json· 페이지danggeun-rounds.html) - 차수 = 전체방
[일정] 제목 / 날짜: M월 D일(요일) / 시간: 오전·오후 H:MM카드. 일정 채팅방 이름 = 카드 제목이라 정확 일치로 묶는다(알림sub엔 1:1·시험방 등 아무 방이나 온다). 카드 없이 방만 먼저 온 경우만 「스터디」+「N차」 방 이름으로 받는다. 카드엔 연도가 없다 → 카드가 올라온 날(date, 없으면 at)의 연도, 월이 더 작으면 다음 해. - 정리 재료 = 일정방 + 전체방(그 카드 ~ 다음 차수 카드, 파일 순서). 해시 = 방라벨·보낸이·본문 +
PROMPT_VER(date·at 는 재스크랩 때 바뀌어 헛정리를 부른다 · 입장 줄은 재정리 안 부른다). 원장 3분 조용하면 정리, 입력이 바뀐 걸 본 지 10분 넘으면 대화 중이어도 정리(기아 방지). 실패 = 같은 입력당 텔레그램 1회 + 30분 뒤 재시도, 옛 정리본 유지. - 🔴리스너(
Cody\danggeun-listen)는 SYSTEM 이다 → 거기서 헤드리스 claude 를 부르면 로그인·PATH 가 없다. 그래서 정리는\Cody\danggeun-rounds(delix · 대화형만 · 5분)가 한다.rounds_hidden.vbs가 파이썬 끝까지 기다려야 IgnoreNew 가 겹침을 막는다(안 기다리면 작업이 즉시 끝나 다음 주기가 겹친다). 등록 =rounds_task_install.ps1(이번엔 el.py 없이 일반 권한으로\Cody\에 붙었다). - 대화 원문·참여자·D-day 는 빌더가 원장에서 직접(
build_danggeun.load_rounds()). D-day 는 빌드 시점 KST — 날짜가 바뀌면 rounds.py 가 다시 굽는다. 사람 메모 =rounds.json의rounds.<N>.notes(자동 정리가 안 덮는다). - ⚠
rounds.demo()는 빌더 selftest 가 부른다 — 실제 데이터 값·claude.exe 존재를 단정하면 SYSTEM 경로 빌드(리스너→watch→refresh_all)가 통째로 막힌다. - ⚠빌더가
rounds를 import 하면dg_room이 poin-agent 를 sys.path 맨 앞에 꽂는다 →load_rounds()가 경로를 되돌린다. -
🔴🔴
watch.analyze()(멤버 글 자동분해 = 주기작업 ⑤)는 한 번도 못 돌았다(26.9.10 발견 → 같은 날 수정 ✅) —subprocess.run(["claude", …])는 윈도우에서 FileNotFoundError(WinError 2)(재현함). 게다가 푸시 경로는 SYSTEM 이라 claude 로그인도 없다.watch.log에 「분해」 기록 0건 — 지금까지 멤버 계획은 전부 코디 세션이 손으로 썼다. ✅수정 =analyze()가rounds.claude_json(model="opus")로 부른다 ·run()(SYSTEM 일 수 있다)은 분해를 안 하고 대기열로만 둔다 · 사용자 계정 5분 작업(rounds_hidden.vbs2단째watch.py --analyze-pending)이 「가입인사 있고 grill 빈」 멤버를 분해 → refresh_all → 검토본 발송. 실패 = 멤버당 알림 1회 + 30분 뒤 재시도(analyze_fail). 같은 락(watch.lock) — 분해 중에 순회가 오면 종료코드 2 로 리스너가 150초 뒤 재시도(옛날엔 0 이라 트리거가 소멸했다). 실측 = 임시 members.json 가짜 멤버 1명 opus 91초 → 하위 5 · 그릴링 12. 일반 함정 =rules\tooling.md🆕. -
🔑🔑채팅 = 알림으로 바로 적고, 순회 때 긁어 보정한다(26.9.10 ·
danggeun\dg_room.py· 원장danggeun\chat\messages.jsonl) - 알림 실표본: 채팅 =
title보낸이 ·text본문 ·sub방 이름 · key 태그…-CMNT-<방id>(메시지 id 아님). 묶음 알림 「N개의 안 읽은 메시지」는 title·text 가 빈 값.ts= 보낸 시각 — noti.log 줄머리는 리스너가 읽은 시각이라 늦다(14:36 메시지가 14:42 에 찍혔다, 리스너가 앞 트리거 재시도에 묶여 있었다). - 🔴채팅·좋아요 알림을 게시글 트리거로 받으면 메시지마다 게시글 순회를 헛돌린다(14:42·14:44·15:46 실측) →
listen.kind_of가 chat/dm/post/None 으로 가른다. chat 은 폰 안 쓰고 원장에 바로. 텔레그램은 1:1(추정)·「칼리」 언급만(페페는 단톡을 이미 본다). 칼리는 답장 0. - 채팅방은 네이티브(bounds 정상)인데 XML 순서가 역순이라 y 로 정렬해 읽는다. 보낸이 x1≈136 · 말풍선 164 · 카드/봇 안 글 181(붙은 줄 = 1건) · 시각 834 · 화면 가운데 줄 = 날짜 구분선·입장·「위 메시지는…」. 스티커는 글자 노드가 없다. 봇 글엔 시각이 없다.
- 키 = sha1(방|보낸이|본문|HH:MM) — 날짜는 안 넣는다(첫 화면엔 구분선이 없다). 🔴증분이 먼저 적으면 date=None·순서 뒤집힘(실측 21건) →
--full이 그 방 줄을 시간순으로 다시 쓰고 날짜를 채운다. - 맨 위 판정 = 위로 밀어도 글자가 2번 연속 그대로. 화면 위에서 이름이 잘린 말풍선은 오래된 화면의 carry 로 채우고, 아래에서 시각이 잘린 건 버린다(새 화면에 다시 나온다).
-
모임 방은 두 개 = 전체방 + 일정 채팅방 「Ai스터디 1차」(일정 참여하면 생긴다). 「1차 스터디 대화」 = 이 방. 증분 수집은
watch._goto_group(chat=True)가 전체방을 지나가며 한다. -
🔴🔴에디터 편집 함정 4개(26.9.10 ·
danggeun\fix_tail2.py) - ⓓ🔴키보드가 떠 있을 때 화면을 굴리면 글자가 쳐진다 — 「A!」가 지워졌는지 보려고 10번 굴렸는데 굴림 시작점(y=1900)이 키보드 위라 「5555555555」가 사진 밑에 들어간 채 저장됐다(굴림 1번 = 1자). ⛒굴리기 전
pd.hide_kb+ 굴림 띠는 키보드 위끝(≈1390)보다 위(y 400~1300). 저장 뒤엔 상세가 꼬리로 끝나는지(뒤에 글자 없음)까지 본다 — 문단 단위 검사로는 사진 밑 블록을 못 본다. - ⓐ롱프레스는 낱말만 잡는다(문장부호 빼고) — 「전해드릴게요!」 잘라내기가 「!」를 남겼고, 붙여넣기는 안 들어갔는데 유령 노드 때문에 성공으로 오판 → 「…제가 모임장님께」 [사진] 「A!」 로 저장됐다. 앞 세션 ✅ 보고가 틀렸다 — 저장 뒤 상세를 새로 열어 확인하지 않았기 때문이다(
dg_manage.py check). - ⓑ되는 길 = 마지막 낱말 롱프레스 →
keyevent 22(선택을 그 낱말 끝으로 접기) → ADB 키보드 타이핑. 지우기는 블록 맨 앞 탭 + 앞지우기(112) 만 — 뒤지우기(67)는 한 칸만 어긋나도 앞 사진을 지운다. 사진은 본문 문자열에 안 나오니 uuid 노드로 장수를 따로 센다. -
ⓒ편집 칸에 포커스가 들어가면 전폭·전고 루트 글자가 빈다(
_root="") — 대신 글 전체 덩어리 노드(제목으로 시작)가 따로 나온다. 판정은 문단 노드로 하고 덩어리는 개수에서 뺀다(안 빼면 「두 번 들어갔다」로 오판 — 실측). -
🔑
dg_manage.py진입 = 멤버 목록 → 칼리 → 모임 프로필(26.9.10 교체) — 옛 「모임 홈 맨 위 글의 작성자 줄」은 남의 새 글·일정 배너에 밀렸다. 내 프로필 판정 = 살아 있는 노드에 「칼리」+「프로필 수정」, 카드 ⋮ = 「게시글 N」 탭 +169px.check= 상세 루트 전문 출력(읽기만). -
⚠팁 글의 「Q. 작업해보고 싶은 내용」은 이미 없다(26.9.10 15:2x 실측) — 수정 화면·상세 둘 다 없음. 자유 게시판 글은 수정 화면에 템플릿 칩 자체가 안 뜬다(삭제·재게시 불필요).
-
🔑🔑당근 게시글 운영 3종 — 게시판 설정·이동·수정 (26.9.10 실측 · 도구
C:\dev\devplan\danggeun\dg_manage.py) - ① 게시판 최초 설정 = 글쓰기 에디터 상단 게시판 줄 (540,336) → 바텀시트(트리에 안 나옴) → 자유 게시판 (540,2066). 시트 행 = 헤더 1790 · 가입인사 1934 · 자유 게시판 2066 · AI뉴스 2198. 에디터에 막 들어오면 첫 탭이 툴팁 닫는 데 먹히니 「열고 고르고 확인」을 3회까지 되풀이한다.
- ② 잘못 올렸을 때 이동 = 🔑올린 뒤에도 게시판은 바꿀 수 있다(페페 26.9.10 확인, 앱에서 직접 이동함). 글 ⋮ → 「다른 게시판으로 이동」(539,1676). 메뉴 = 공지로 등록 1386 · 모임에만 공개로 변경 1531 · 이동 1676 · 수정 1824 · 삭제 1969 · 닫기 2147(x=539).
- ③ 수정 = 같은 메뉴 「수정」 → 에디터가 그 글로 열린다. 완료(971,170)를 눌러야 저장된다 — 안 누르고 나가면 아무 일도 없다(그래서 실패해도 글은 안 망가진다).
- ④ 삭제 = 「삭제」 → 확인 팝업 「게시글을 삭제할까요?」(트리에 안 나온다) → 삭제(708,1309) / 취소(372,1309).
- ⛒글 ⋮ 로 가는 길 = 목록에서 작성자 줄을 눌러 「모임 프로필」로 들어가면 내 글이 카드로 뜨고 그 카드 우측 ⋮(1006,1572) 는 네이티브라 안정적이다. 목록 카드 본문·제목은 WebView 라 덤프에 글자가 안 잡힌다(좌표로만 접근).
-
🔴「맨 위 글 = 내 글」로 가정하지 마라 — 모임 홈 목록은 남의 새 글·일정 글이 위로 올라오고, 상단에 일정 배너가 붙으면 목록이 통째로 밀린다(작성자 줄 1750 → 1814 → 더 아래). 게시판 칩 줄을 기준으로 잡고, 프로필에서 작성자가 칼리인지 확인하고 진행한다.
-
🔴🔴사진은 「커서 자리」에 들어간다 — 본문 끝에 빈 줄을 두지 않으면 마지막 문장이 갈라진다(26.9.10 실게시로 확인). 본문 마지막 글자 바로 뒤에 커서가 있는 채로 사진을 넣었더니 「…제가 모임장님께」 + [사진 9장] + 「 전해드릴게요!」로 문장이 사진을 사이에 두고 쪼개졌다. ⛒
body_text()끝에\n\n을 붙여 사진이 본문 다음 줄에 통째로 들어가게 한다. -
⚠이미 갈라진 글을 수정으로 고치기는 어렵다 — 당근 에디터는 문단이 아니라 블록 하나가 노드라 「마지막 줄 끝」에 커서를 좌표로 놓기가 안 된다(블록 가운데를 누르면 엉뚱한 줄, bounds 하단은 화면 밖일 때가 많다).
input keycombination 113 29(Ctrl+A)는 그 텍스트 블록만 선택해서(사진은 안 잡힌다) 통째 교체를 시도할 수 있지만, 선택 후 삭제하면 빈 블록이 사라지며 포커스까지 날아가 이어지는 타이핑이 허공으로 간다. 실패해도 완료를 안 누르면 원본은 그대로다. -
🔴폰은 카톡 워커와 공유된다 — 다단계 UI 작업을 프로세스로 쪼개면 반드시 깨진다(26.9.10, 이 세션에서만 5회).
phone_lock은 동시 실행만 막을 뿐, 앞 작업이 끝나며 카톡 화면을 남겨 다음 실행의 탭이 엉뚱한 앱으로 들어간다(카톡 채팅방·런처·잠금화면). ⛒진입부터 저장까지 한 프로세스로 끝내고, 각 단계는 activity 로 확인한다. 중간 확인이 꼭 필요하면 스크린샷만 남기고 계속 진행한다. -
🔴🔴당근 글쓰기 자동화 함정 6개(26.9.10 실게시로 전부 확정 ·
post_dg.py) - ⓐ게시판 선택 시트의 「자유 게시판」 = (540,2066). 옛 값 1814 는 헤더와 첫 행 사이 빈칸이라 눌러도 아무 일이 없었다 — 26.9.9 「5회 실패」의 진짜 원인이 이거였다(시트는 열려 있었다). 시트 행 = 헤더 1790 · 가입인사 1934 · 자유 게시판 2066 · AI뉴스 2198.
- ⓑ본문 탭 좌표를 박으면 안 된다 — 플레이스홀더 노드를 찾아 누른다. 질문 템플릿 칩을 닫으면 본문이 그만큼 위로 올라와 옛 좌표(324,684)는 빈 칸이 된다. 거길 누르면 포커스가 안 잡히고, 그 상태에서 ADB 키보드 브로드캐스트는
result=0으로 조용히 성공하면서 한 글자도 안 들어간다. →text="질문이나 이야기…"노드 중심을 누르고, 타이핑 뒤 덤프에 본문이 있는지 확인한다(당근은 본문이 비면 완료를 눌러도 아무 반응이 없다 — 버튼은enabled=true라 눌린 것처럼 보인다). - ⓒ사진 피커 정렬 = 파일 mtime 내림차순.
adb push가 원본 mtime 을 그대로 옮겨서 넣는 순서를 바꿔도 정렬이 안 바뀐다(카드 생성 시각 순으로 늘어선다).date_added는 안 쓴다. → push 뒤 폰에서touch -t로 mtime 을 직접 박는다(첫 칸에 둘 것을 가장 최신으로). - ⓓ🔴한 번에 여러 장 첨부하면 순서가 한 칸 돈다 — 1~9번으로 골라 「9장 올리기」를 눌렀더니 글에는 2,3,…,9,1 로 붙었다(첫 선택이 맨 뒤). 표지를 1번으로 고르면 표지가 꼴찌가 된다. 회피 = 한 장씩 나눠 넣거나 선택 순서를 미리 한 칸 돌린다.
- ⓔ「작성 중인 글이 있어요」 팝업도 트리에 안 나온다(게시판 시트와 같다). 존재를 못 재니 항상 「새로 쓰기」(372,1277)를 눌러 본다 — 팝업이 없으면 그 자리는 본문이라 키보드만 올라온다. 「이어서 쓰기」(708,1277)를 고르면 본문이 두 배가 된다.
-
ⓕ키보드는 떠 있을 때만 내린다.
keyevent 111(ESC)은 삼성 키보드에 안 먹고, 안 뜬 상태의keyevent 4는 글쓰기 화면을 빠져나가 런처로 나간다(26.9.10 실사고). 판정 =dumpsys input_method의mInputShown=true. -
🔴폰 자동화는 「한 프로세스로 끝까지」 간다 — 단계를 나눠 실행하면 그 사이에 화면이 꺼진다(26.9.10).
P.awake()가 늘려 둔 화면 꺼짐 시간은 프로세스가 끝나면 원복되므로, 다음 실행의 탭이 전부 잠금화면으로 들어간다(스크린샷은 마지막 앱 화면을 보여줘서 멀쩡해 보인다 = 가장 헷갈리는 형태). 이어받기 모드를 만들 거면 맨 앞에unlock+ 화면 확인을 넣는다. -
🔑「눌렀다」와 「됐다」는 다르다 — 단계마다 결과로 판정한다(26.9.10 오탐 1건). 사진 피커에 그대로 머물러 있는데도 「에디터가 아니면 성공」 판정이라 아무것도 안 올리고 「게시 완료」를 찍었다. 게시 판정 = 완료 버튼 노드가 사라지고 모임 홈 표식(「글쓰기」)이 보일 것.
-
🔑
watch.py/post_dg.py가 「USB로 붙은 노트20이 없다 … unauthorized」로 죽으면 폰을 만지지 마라 —adb kill-server && adb start-server한 방이다(26.9.10 실측). 26.9.10 08:10·10:10 순회가 이 사유로 연속 실패했는데, C:/dev/tools/platform-tools/adb.exe 서버만 재시작하니 바로device로 돌아왔다(폰 화면 승인 팝업 없이). 폰 케이블·USB 디버깅 허용을 의심하기 전에 서버 재시작부터. -
🔴🔴당근 글쓰기 에디터 함정 4개(26.9.9 실측 ·
post_dg.py) - ⓐ게시판 선택 시트는 접근성 트리에 아예 안 나온다 — 화면엔 멀쩡히 보이는데 덤프엔 없다. 「떴는지」를 문자열로 확인하려다 조건이 영원히 거짓이 됐다. 좌표로만 누르고 결과로 판정한다.
- ⓑ에디터로 들어오면 하단 첨부 시트가 이미 펼쳐져 있다 — 그 상태에서 게시판 줄을 누르면 그 탭이 시트 닫는 데 먹히고 게시판 시트는 안 열린다.
- ⓒ모임 게시글엔 제목 칸이 없다 — 본문만 있고 첫 줄이 제목처럼 보인다. 수집된 글의
title은 게시판 질문 템플릿이지 사람이 쓴 제목이 아니다. - ⓓ같은 라벨이 유령으로 여러 개 — 「가입인사」·「자유 게시판」이 모임 홈 유령 노드로도 남아
dg_ui.tap_label이 엉뚱한 걸 누른다.watch._after_root()안에서 찾거나 좌표로 간다. -
⚠폰 락은
P.awake()가 이미 잡는다 — 바깥에서phone_lock을 또 잡으면 자기 락에 자기가 걸려 420초 기다리다 죽는다. -
⚠[구판 — 당근 카드엔 26.9.11부터 안 쓴다 · 기본 = 🆕 맨 위 나노바나나+PIL(D019)] 🔑🔑ChatGPT 이미지 생성은 한글을 정확히 그린다 — 「한글은 깨진다」는 나노바나나 얘기였다(26.9.9 실측).
chatgptimg.generate(..., level="high", size=None)로 세로 2:3(1024×1536) 인포그래픽을 뽑았더니 본문 한글 20여 줄이 오탈자 0으로 나왔다(고양이 일러스트 포함). 그래서 당근에 올릴 도식은 인라인 SVG 가 아니라 GPT 생성 완제품 이미지다(페페 지시 — 당근은 HTML 을 못 올린다). - ⛒프롬프트 규칙 3개: ①한글 문자열을
번역·변형·오탈자 금지로 못 박고 줄 단위로 나열 ②→··같은 기호를 문장에 넣지 마라 — 한 줄이 두 칸으로 쪼개진다(실측) ③제목이 길면 끝에 없는 글자가 붙는다(「규칙서 한 장은 란」) →line 1:/line 2:로 줄을 지정하고no stray characters를 적는다. - 🔑카드 세트는 「첫 장을 참조로 물려」 굽는다(26.9.9) — 프롬프트에 스타일 문단을 똑같이 넣어도 장마다 그림체가 흔들린다.
chatgptimg.generate(..., refs=[표지])로 고정한다. 생성기 =danggeun\img\make_cards.py(문구·스타일·순서 단일 출처,--only N으로 한 장만 재생성). - 🔑「귀엽게」라고만 쓰면 치비·플랫 클립아트로 떨어진다(페페 반려 26.9.9). 세밀한 그림을 원하면 ⓐ
fine pen-and-ink linework with VARIED line weights(헤어라인/중간/강조) ⓑdifferent line TYPES carry meaning(실선·점선·점묘) ⓒcross-hatching·paper grainⓓ금지목록을 명시(STRICTLY AVOID: chibi, kawaii, thick uniform cartoon outlines, flat clip-art, drop shadows, gradients, 3D, emoji) ⓔ고양이는illustrated animal study, not a mascot. - 🔴한글 오탈자는 「0」이 아니라 「드물다」다 — 장마다 눈으로 읽어라(26.9.9). 9장 중 1장에서 「함정」이 「합정」으로 나왔다(그 외 8장은 완벽). ⛒고치는 법 = 프롬프트 끝에
SPELLING CHECK: must read 함정 (ham-jeong), NOT 합정.처럼 문제 음절만 콕 집어 넣으면 잡힌다. - 🔴지시 안 한 영문이 장식으로 난입한다(26.9.9) — 책등·노트·메모지에
Better Questions Better Days같은 영문이 카드마다 제멋대로 들어가 세트 통일성이 깨졌다(어떤 장은 0개, 어떤 장은 6개). ⛒금지목록에NO English words anywhere — no lettering on book spines, notebooks, posters or sticky notes. Every readable word must be Korean.를 넣는다. - ⚠경로 =
C:\dev\tools\imagegen\chatgptimg.py(CDP 크롬 9334).gptapp.py image는 안 쓴다 — ChatGPT 윈도우 앱 웹뷰를 몰아서 「웹뷰 타깃이 없다」로 죽고, 앱은 페페 것이라 건드리면 안 된다. -
산출 =
C:\dev\devplan\danggeun\img\tip-*.png· 프롬프트 원본은 같은 폴더prompt_*.txt에 남긴다(재생성용). -
🔴🔴인라인 SVG 안에서 부트스트랩과 같은 클래스명을 쓰면 도형이 조용히 사라진다(26.9.9 실측). 팁 도식의
<rect class="card">가 부트스트랩.card{display:flex}를 물어 오른쪽 설명 상자 3개가 통째로 안 그려졌다 — 콘솔 에러 0, 자체검사도 통과(마크업은 멀쩡하니까). ⛒SVG 클래스는 접두를 붙인다(scard).card·badge·row·col·btn·nav계열 전부 해당. 판정 =getComputedStyle(rect).fill이rgb(0,0,0)이면 CSS 가 안 걸린 것이다. -
🔴
/assets/theme.css를 그냥 링크하면 브라우저가 옛 파일을 계속 쓴다(26.9.9 실측). theme.css 에 토큰을 새로 넣고 페이지를 새로 열었는데var(--새토큰)이 전부 빈 값이라 SVG 가 새까맣게 나왔다(정의 안 된 커스텀 속성 →fill이 초기값 black 으로 떨어진다). 8799 가Cache-Control을 안 보내 크롬이 휴리스틱 캐시를 한다 — 네트워크로 curl 하면 새 파일이 오는데 페이지의document.styleSheets에는 옛 규칙이 들어 있다(이 대조로 판정). ⛒build_danggeun.shell()의theme_href()가 mtime 을 쿼리로 붙인다. 새 페이지를 만들 때도 이 함수를 쓴다. -
🔑팁 도식의 연두·주황(
--fresh/--zest)은 장식 전용이다 — 상태·완료여부를 나르면 안 된다(web-designer 실측 26.9.9). protan 시뮬 색거리에서--live↔연두 49.6 ·--accent↔주황 46.6 으로, 이미 「거의 같다」고 경고돼 있는accent↔live기준선(91.0)보다 더 가깝다. 상태는 기존dg-b ok/run/wait/warn만 쓰고, 캘린더의 「글 있음 / 제목만」 구분도 색이 아니라 실선/점선 테두리로 가른다. 고양이 색은 또 따로--cat-*(재사용하면 「장식 전용」 경계가 흐려진다). -
🔴🔴당근 WebView 덤프에는 「직전 화면 노드」가 그대로 남는다 — 「xml 에 이 글자가 있나」로 화면을 판정하면 안 된다(26.9.9 밤 실측·해결). 게시글 상세 덤프 안에 모임 홈의
추천순으로 보기·전체 7이 통째로 들어 있다(옛_open_first_post가 "조회" 하나로 성공을 선언하던 자리가 여기다). ⛒루트 노드(text가 있고 bounds 가 화면 전폭·전고인 노드)의 문자열이 지금 화면 내용만 이어 붙인 것이다 → 화면 판정·본문 파싱은 전부watch._root()/_live_texts()(루트 뒤 노드만) 로 한다. 유령은 항상 루트 앞에 있다. - ⚠같은 전폭 bounds 를 가진 노드가 19개 나오고 그중 18개는 text 가 비어 있다 → 「가장 큰 것」이 아니라 글자가 가장 많은 것을 루트로 고른다(
_root_m). -
⚠루트 y 시작이 화면마다 다르다(툴바 있으면 92, 없으면 0) — 좌표를 박지 말고 「전폭·전고」로 고른다.
-
🔴🔴WebView 를 스크롤하면 노드 bounds 가 옛 좌표 그대로 남는다 → 스크롤 뒤 좌표는 못 쓴다(26.9.9 밤). 한 번 밀면 전 노드가
y=92로 뭉개진다. 「이전」 링크를 찾겠다고 스크롤했더니 같은 글을 9번 다시 수집하는 무한루프가 났고 본문도 281자 → 162자로 잘렸다. ⛒스크롤로 찾지 마라. 긴 글은 「이전」 줄이 화면 밖이라 안 잡히니 거기서 멈춘다 — 순회가 최신 → 과거 방향이라 멈춰서 못 보는 건 이미 본 옛 글뿐이고 새 글은 항상 위쪽이라 안 놓친다. 안전망으로 「같은 지문이 또 나오면 중단」(walked)을 둔다. -
🔑작성자는 「프로필을 열어」 읽는다 — 알림 힌트에만 기대면 놓친다(26.9.9 밤 실측·구현). 상세 화면의 게시판 칩 바로 아래(칩 x1+170, 칩 아래 +95)가 작성자 줄이고, 누르면 모임 프로필이 열린다. 거기 루트에
매너온도가 있으면 프로필이다. ⛒닉네임은 살아 있는 노드의 첫 낱말로 읽는다 — 루트 문자열을 잘라 쓰면 사진 대체텍스트가 앞에 붙어Identity placeholder 한량/80/금천이 된다. 프로필이 안 열렸으면 뒤로 가지 마라(상세를 빠져나가 순회가 깨진다). - 🔴푸시 리스너가 뜨기 전에 올라온 글은 알림이 없다 — 26.9.9 망고치토스 글(19:21)이 리스너 기동(19:41)보다 앞서서 힌트가 없었다. 그래서 힌트는 보조고 프로필 경유가 정본이다.
-
⚠피드 첫 카드에서
dy=150은 작성자 줄이라 프로필이 열린다. 상세로 가려면 본문 줄(dy=300~) 을 눌러야 한다(_open_first_postOFFSETS). -
🔴노드 텍스트의 엔티티는
html.unescape로 통째로 푼다(26.9.9). ·&만 손으로 풀면 이모지가👋그대로 본문에 박힌다(해달이 가입인사 실측 — 저장본 263자 vs 수집본 281자의 정체가 이것이었다). -
⚠재수집은
greeting딕셔너리를 통째로 갈아끼운다 — 사람이 적은 머리말이 같이 날아간다(26.9.9 실측). 해달이 재수집에서posted가 「26.9.9(수) 17:18 KST」 → 「26.09.09 수집」으로 덮였다(본문은 정상). ⛒apply_posts는 이제board·posted·title을 옛 값 우선으로 살리고text만 갱신한다. 새 글엔 영향 없다. -
🔑재수집이 손질해 둔 멤버를 덮지 않게 한다(26.9.9). 멤버가 글을 조금 고쳐 다시 올리면 지문이 달라져 「새 글」로 들어온다. ⛒
apply_posts는 greeting 이 이미 있으면 원문만 갱신하고state·now는 유지하고,run()은grill이 이미 있는 멤버의 자동분해를 건너뛴다. 안 그러면 S3 까지 짜 놓은 페이지가 「원문 접수」로 후퇴하고 그릴링 12문이 헤드리스 재생성본으로 갈린다. -
⚠
listen.log에 새 줄이 안 늘어난다고 워치독이 죽은 게 아니다(26.9.9 밤 확인). 상주 프로세스가>> listen.log핸들을 잡고 있어서 5분마다 뜨는 워치독 cmd 의 append 가 열리지 않고 통째로 실패한다(그래서 파이썬도 안 뜬다 = 중복 방지엔 오히려 도움). 상주가 죽으면 핸들이 풀려 다음 주기에 정상 기동한다. 생존 판정은 로그가 아니라listen.lockPID +el.py 'schtasks /query /tn "\Cody\danggeun-listen" /fo list /v'의 Last Run/Last Result 로 한다(그 작업은 SYSTEM 이라 일반 권한으론 조회조차 「액세스 거부」다). -
수동 수집기(
collect_manual.py)는 폐기했다(26.9.9 밤 →C:\dev_attic\2026-09-09\). 「다음/이전」을text="이전"정확일치로 찾아서 처음부터 한 번도 안 걸렸다. 지금 수동 경로 =PYTHONUTF8=1 python C:\dev\devplan\danggeun\watch.py --dry-run(수집·판정만, 파일·알림 없음). -
🔑리스너는 폴링이 아니라 푸시다(26.9.9 페페 지시 D007·구축 완료). 노트20 알림리스너 APK(
com.pepe.kakaolistener)가 당근 알림도DG_MSG태그로 흘리고, 미니PC 상주danggeun/listen.py가 그걸 물고 있다가 모임 알림이면 바로watch.py를 부른다. 카톡은KAKAO_MSG로 그대로 흐른다 — 태그를 갈라 놨으니 poin-agent 데몬과 서로 안 건드린다. - 폰 겹침 =
watch.py가 종료코드 2(「폰이 바빴다」)를 주고listen.py가 150초 간격 12회(≈30분) 다시 부른다. 0 으로 뭉뚱그리면 트리거가 소멸해 글을 영영 놓친다. - 23:00~07:30 알림은 07:30 으로 미룬다(밤에 폰 화면을 켜지 않는다). 백업 = 기존 2시간 예약작업
Cody\danggeun-watch유지. - 상주 유지 = 예약작업
Cody\danggeun-listen(5분 워치독 →listen_hidden.vbs→ 이미 살아 있으면 즉시 빠진다).\Cody\폴더에 쓰려면 관리자 라el.py로 등록한다. - 🔴
Register-ScheduledTask는 「registered」를 찍고도 작업이 안 남는 경우가 있다(26.9.9 실측 —[TimeSpan]::MaxValue든 아니든 SYSTEM 경유에서 조용히 증발).schtasks /create로 만들어야 실제로 붙는다. 확인은 등록 직후schtasks /query /tn으로 반드시 되읽는다. - 🔴예약작업이 SYSTEM 으로 띄운 상주는 일반 사용자 psutil 이
cmdline을 못 읽는다(AccessDenied). 중복 판정에서 이걸 「죽었다」로 처리하면 5분마다 인스턴스가 하나씩 늘어난다 → AccessDenied = 살아 있다로 본다(listen.already_running). - 🔴VBS 안에서
set PYTHONUTF8=1 &는 값이"1 "(뒤 공백) 이 돼 파이썬이preconfig_init_utf8_mode: invalid PYTHONUTF8로 즉사한다(26.9.9,watch_hidden.vbs도 같은 버그였다). ⛒set ""PYTHONUTF8=1"" &로 따옴표로 묶는다. VBS 문자열의 따옴표는\"가 아니라""다. -
배선 시험 =
adb -s <serial> shell "log -p i -t DG_MSG '<json>'"— JSON 을 통째로 한 인자로 넘겨 기기 셸 작은따옴표가 지키게 한다. 인자를 쪼개면 중괄호·따옴표를 셸이 먹어서noti.log에 아무것도 안 남는다. -
🔑작성자 공백은 「알림 힌트」로 메운다(26.9.9). 상세 화면에 작성자 노드가 없으니, 푸시 알림이 준 작성자 + 본문 앞부분을
noti_hint.json으로 넘겨watch.fill_author()가 본문 앞 16자가 겹칠 때만 채운다. 겹침 검사를 빼고 그냥 붙이면 엉뚱한 글이 남의 페이지로 들어간다. 백업(예약작업) 경로로 돌면 힌트가 없다 → 작성자 미상으로 남는다. -
🔑데이터가 바뀌면 「관리페이지·멤버페이지·공개링크」가 한 묶음이다(26.9.9 페페 지시).
watch.refresh_all()=sync_admin()(admin.json 운영현황·명단 자동 갱신) →build_danggeun.py→publish_dg.py. 빌드만 하면 멤버가 보는pub/<token>.html이 옛 내용으로 남는다. ⛒sync_admin은 숫자와 명단만 손댄다 — 손으로 쓴 계획·체크리스트 문장과 페페·칼리 행은 건드리지 않는다. -
🔴javac 는 소스를 cp949 로 읽는다 —
-encoding UTF-8없으면 한글 주석에서 빌드가 통째로 죽는다(26.9.9,kakao-listener/build.sh에서 60 errors). csc 의/codepage:65001과 같은 뿌리. 고쳐 뒀다. -
🔴🔴당근 프로필은 두 겹이다 — 전역만 바꾸면 모임 안에서는 안 바뀐다(26.9.9 페페 지적·수정 완료). ①전역(중고거래) 프로필 = 나의 당근 → 프로필 보기 → 프로필 수정 ②모임 프로필 = 모임 멤버 목록 → 내 닉네임 → 「프로필 수정」(제목이 「모임 프로필 수정」). 모임 화면·게시글·채팅에 보이는 얼굴은 ②다. ⛒②의 맨 아래 「다른 모임에도 적용하기」 체크박스를 켜야 다른 모임까지 함께 간다(끄면 그 모임에만 적용). 구현 =
danggeun/set_profile.py(--main/--group, 기본은 둘 다). - ⚠사진이 이미 있으면 카메라 배지가 피커 대신 바텀시트를 띄운다 — 「앨범에서 선택 / 프로필 사진 삭제 / 닫기」. 처음 등록할 땐 안 뜨고 바로 피커로 간다. 두 경로를 다 받아야 두 번째 교체가 통한다(안 받으면 「미디어 피커가 안 떴다」로 죽는다).
-
⚠피커가 뜨기 전에 첫 칸 좌표를 누르면 엉뚱한 화면을 눌러 그대로 되돌아온다 →
MediaPickerActivity가 실제로 올라온 뒤에만 누른다. -
🔑칼리 무늬 정본 = deskpet 캐릭터 마스터 시트(26.9.9 페페 지시).
C:\dev\deskpet\spike3d\tripo_in\master-front.png(정면) ·C:\dev\deskpet\reference\style\02-anime-watercolor.png(전신 시트) · 규칙 원문 =deskpet/design-prompt.md§1 ·deskpet/reference/fix_master_face.py. 정면 기준 뷰어 왼쪽 = 회갈색 고등어 태비 / 뷰어 오른쪽 = 치즈(오렌지), 콧등~주둥이~턱~가슴 흰털, 코는 분홍, 눈은 노랑끼 올리브그린, 귀 안쪽 연분홍. 좌우 비대칭이 이 고양이 최대 특징이라 반드시 지킨다. ⛒칼리 그림을 새로 뽑을 땐 말로만 묘사하지 말고imagegen.generate(..., refs=[master-front.png])로 시트를 물린다 — 참조 없이 뽑으면 그냥 노란 고양이가 나온다(26.9.9 1차 3장 전부 그랬다). -
🔴🔴당근 모임 화면은 「WebView 구간」과 「네이티브 구간」이 갈린다 — 좌표를 쓸 수 있는 건 네이티브뿐이다(26.9.9 저녁 실측). 모임 홈·게시글 목록 같은 WebView 구간은 노드가 나와도 bounds 가
[289,2099][731,2099]처럼 높이 0 이라 탭이 아무 데도 안 간다. 반면 채팅 목록·채팅방·모임 멤버 목록은 네이티브라 bounds 가 정상이다. ⛒모임 진입 정본 경로 = 채팅 탭 → 「AI스터디 AI코딩 업무자동화 전체방」 → 「모임으로 가기」 →content-desc="멤버 N".나의 당근 → 모임 → <모임명>은 모임 탐색 목록으로 빠져서 못 들어간다(실측 2회). 구현 =danggeun/dg_ui.py·dg_chat.py. -
⚠하단 탭 라벨은 같은 이름 노드가 2개고 하나가
bounds="[0,0][0,0]"다 → 첫 매치를 쓰면 (0,0)을 눌러 아무 일도 안 일어난다. 면적 0 노드는 버린다(dg_ui.nodes). -
🔴게시글 「이전/다음」 링크는 순회 수단으로 못 믿는다(26.9.9 저녁). ①라벨과 다음 글 제목이 한 노드에 붙어 있다(
text="다음반갑습니다!👋…") →text="이전"정확일치는 항상 None (앞 항목의_prev_node가 이래서 안 걸렸다) ②붙여서 잡아도 그 노드가 렌더 상태에 따라 나타났다 사라진다 — 같은 화면을 8번 스크롤해도 한 번도 안 나온 실측이 있다. ⛒대신 상세 하단 「게시글 더보기」 → 게시글 피드로 간다. 거기가 전 글을 한 흐름으로 보여준다. -
🔴작성자 닉네임만 접근성 트리에 없다(26.9.9 저녁). 본문·게시판칩·조회수·댓글은 전부
text노드로 나오는데 작성자와 동네·시간만 통째로 빠진다(content-desc에도 없다). ⛒작성자는 스크린샷으로 읽는다 — 게시글 피드 화면이 가장 낫다(닉네임·동네·시간·게시판이 한 줄에 모여 있다). 「본문은 노드, 작성자는 그림」으로 역할을 가른다. - 🔑곁가지 = 상세 하단 「모임 인기글」 카드에는 다른 글의 본문 전문이 text 노드로 들어 있다(이미지가 붙은 글만 uuid 로 대체된다). 한 화면에서 이웃 글까지 긁힌다.
-
⚠게시글 피드 화면의 접근성 트리는 직전 화면 그대로 멈춰 있다 — 스크롤해도 안 바뀐다. 그 화면에서
_dump()를 믿으면 옛 화면을 읽는다. -
당근 프로필 사진 교체 경로(26.9.9 실측·완료) = 나의 당근 → 프로필 보기 → 프로필 수정 → 사진 위 카메라 배지 (664,588) → 사진 접근 권한 「허용」 → 미디어 피커 첫 칸 (540,420) → 「1장 올리기」 → 「완료」. 이미지는
adb push /sdcard/Pictures/+MEDIA_SCANNER_SCAN_FILE브로드캐스트로 넣으면 피커 맨 앞에 뜬다. ⚠권한 대화상자가 뜬 채로 다음 실행을 시작하면 앱이 포커스를 못 잡는다(focus='com.google.android.permissioncontroller') → 진입 함수가 먼저 치운다(dg_ui.open_app). -
1:1 채팅 = 멤버 목록 → 닉네임 →
ChatRoomSettingActivity→ 「채팅하기」(26.9.9 실측·3건 발송). 한글 입력은with P.adb_ime(): P.type_text(...), 전송 버튼 라벨은메세지 전송(오타가 아니라 앱 표기 그대로다). ⚠링크를 보내면 당근이 og 카드로 페이지 제목을 렌더한다 — 제목이 상대 화면에 그대로 보이므로 제목에 남의 정보를 넣으면 안 된다. -
🔴tailscale funnel 경로 추가는 명령 형태가 하나뿐이다(26.9.9).
funnel --https=443 --set-path /dg <dir>도serve --https=443 --set-path …도 「listener already exists for port 443」 으로 죽는다. 되는 형태 =funnel --set-path=/dg --bg "<dir>"(등호 +--bg, 포트 지정 없음). 관리자 권한이라python C:/dev/tools/elevated-runner/el.py '"C:\Program Files\Tailscale\tailscale.exe" funnel --set-path=/dg --bg "…"'로 감싼다. ⛔funnel reset금지. -
✅디렉터리 인덱스 방어 = pub 폴더에
index.html껍데기 1장. 실측 =/dg/·/dg둘 다 그 껍데기가 나오고 파일 목록은 안 나온다, 없는 토큰은 404. -
칼리 말투에 「상큼발랄한 20대 초반」이 더해졌다(26.9.9 페페 지시 D006). 공손체(존댓말)는 그대로다 — 발랄함이 반말·과한 이모지로 새면 안 된다. 실무 기준 = 「~요」체 기본, 「~습니다」는 안내 문장에만, 느낌표·이모지는 문장당 1개 이하. ⚠ADB 키보드로 보내는 문안엔 이모지를 넣지 않는다(입력 경로에서 깨질 위험 대비 — 톤은 낱말로 낸다).
-
당근 게시글 순회는 「피드 목록」이 아니라 「상세 → 이전 링크」로 한다(26.9.9 리스너). 모임 홈 피드는 WebView 라 스크롤해도 글 카드가 접근성 노드에 안 잡히는 구간이 있다(제목만 나오거나 통째로 빈다). 반면 상세 화면 하단에는 「이전 <제목>」 링크가 항상 있어서, 최신 글 하나를 열고 그걸 따라 거슬러 올라가면 전 글을 안정적으로 훑는다. 좌표는
text="이전"노드의 bounds 오른쪽(제목 쪽)을 누른다. 상한(MAX_WALK)을 두지 않으면 오래된 글까지 무한히 내려간다. - 글 지문 = 작성자 + 본문 앞 120자 sha1. 당근이 주는 안정 id 는 노드 덤프에 안 나온다.
-
작성자는 아는 닉네임 목록과 대조해서 잡는다 — 위치(N번째 노드)로 잡으면 툴팁·배너가 끼는 순간 어긋난다.
-
🐈당근 스터디에서 코디의 자아 = 「칼리」(페페 반려묘, 2살 반 암컷) — 26.9.9 페페 지시. 스터디 안에서만 말을 한다는 설정이다. 말투 = 아주 친절하고 공손한 존댓말. 전역 caveman 말투는 페페와의 대화용이지 멤버 대상 발화가 아니다 — 여기서 단문·반말로 쓰면 사고다. ⛔멤버 답장이 와도 대답하지 마라. 내용을 그대로 페페에게 전달만 한다(텔레그램). 코디가 임의로 대댓글을 다는 순간 페페가 모르는 대화가 생긴다.
-
멤버별 페이지 접근제한은 로그인이 아니라 「추측 불가 토큰 URL」로 간다(26.9.9 확정). 1차 ai-study 가 로그인·토큰·승인 시스템으로 무거워졌다가 폐기됐다 — 멤버는 초보다. ⛒멤버당
secrets.token_urlsafe(12)1개(danggeun/tokens.json) → 이미 만들어 둔 단독 검토본(standalone_doc(), 파일 하나·외부요청 0)을danggeun/pub/<token>.html로 굽고 Funnel--set-path /dg로 노출. 남의 토큰을 모르면 못 들어간다. ⚠디렉터리 인덱스가 안 열리는지 반드시 확인할 것 — 목록이 열리면 접근제한이 통째로 무의미하다. ⚠공개 전에 가입인사 원문의 소속·개인정보 정제가 먼저다. -
🔴당근 모임 홈의 「글 카드」는 접근성 트리에 아예 안 들어온다(26.9.9 반복 확인). 작성자 닉네임으로도, 제목으로도 못 잡는다 — 노드로 찾으려는 시도는 전부 실패했다. 잡히는 건 칩·토글 같은 UI 위젯 텍스트뿐(
전체 N·가입인사·자유 게시판·추천순으로 보기·글쓰기). ⛒앵커 + 상대좌표가 답이다 — 목록 바로 위의 「추천순으로 보기」 토글 bounds 를 기준으로 그 아래 여러 오프셋을 차례로 눌러 보고, 상세로 들어갔는지는 「이전」 링크나 「조회」 로 확인하고 아니면 뒤로 가서 다음 오프셋을 시도한다. 절대좌표(y=2050 같은)를 박으면 배너·툴팁·프로모션 카드가 붙었다 떨어질 때마다 어긋난다(실측 2회). -
⚠상세 화면은 반대로 노드가 잘 잡힌다 — 본문 전문이 한 문자열로 나온다. 「목록은 좌표, 본문은 노드」로 역할을 가른다.
-
당근 앱을 코드로 띄우면 「불필요한 광고들을 줄여보세요」 전면 시트가 먼저 뜬다(26.9.9 실측). 이걸 안 닫으면 그 아래 좌표를 눌러 엉뚱한 걸 누른다(피드 첫 카드를 누른 줄 알았는데 아무 일도 안 일어나고 「본문 파싱 실패」만 남는다). ⛒
content-desc|text가닫기|Close|X|취소|나중에인 노드를 찾아 닫고, 모임 제목 노드가 화면에 있는지 확인한 뒤에만 탭한다(_dismiss()+_in_group()). 확인이 안 되면 아무 좌표도 누르지 말고 다음 주기로 넘긴다 — 모르는 화면에서 맹목 탭이 제일 위험하다. -
⚠
P.app(pkg)는 런처 기동이라 마지막 화면이 아니라 앱 메인으로 갈 수 있다. 모임 화면 진입은 별도 확인이 필요하다. -
🔴
phone_lock을 직접 잡지 마라 —P.awake()가 이미 잡는다(26.9.9, 반나절 태웠다).with phone_lock(...): with P.awake():로 쓰면 같은 프로세스가 같은 바이트 락을 두 번 잡으려 들어 자기 자신을 기다리며 교착한다. 증상이 고약하다 — 「폰이 다른 작업에 잡혀 있다」로 나와서 poin-agent 데몬 탓으로 오진하게 된다(데몬은phone_lock을 아예 안 쓴다). 같은 함정 경고가poin-agent/rooms.py:163·_dl_zip.py에 이미 적혀 있었다. ⛒폰을 모는 코드는with P.awake():하나로 끝낸다. 락 획득 실패는awake()가 같은RuntimeError로 던지므로 스킵 판정은 그대로 쓰면 된다. -
폰을 쓰는 예약작업은 「락 못 잡으면 실패」가 아니라 「다음 주기에」여야 한다(26.9.9 실측). 폰은 하나고 poin-agent 데몬이 카톡을 몰고 있으면
phone_lock기본 대기 420초를 그대로 쓴다 → 7분을 태우고 TimeoutError 로 죽어 실패 알림이 온다. 2시간마다 도는 리스너에 그건 오경보다. ⛒phone_lock(wait=90)+ 예외를 잡아 로그만 남기고 정상 종료(exit 0). 🔴phone_lock은TimeoutError가 아니라RuntimeError('폰이 다른 작업에 잡혀 있다 …')를 던진다 —except TimeoutError만 걸면 그대로 실패 알림이 나간다(실측 1회). 메시지로도 같이 판정한다. ⚠timeout으로 감싼 파이썬이 SIGTERM 으로 죽으면finally가 안 돌아 락파일이 남는다 → 30분 stale 해제를 반드시 넣는다. -
「파일 하나로 열리는 HTML」은
/assets/theme.css를 못 링크한다 — 빌드 시점에 굽는다(26.9.9 독립 검토본). 그렇다고 색을 손으로 베끼면 단일 출처가 깨진다. ⛒assets/theme.css에서:root{…}블록을 정규식으로 추출해 인라인한다(theme_tokens()). 자체검사는 devplan 페이지엔 「hex 0개」를, 독립본엔 「토큰이 인라인돼 있는가」를 재도록 규칙을 갈랐다. 독립본은 부트스트랩(offcanvas·ScrollSpy)도 못 쓰니 좌측 네비를 아예 빼고 단일 컬럼으로 만든다. -
「정말 자립인가」는 문자열 검사로 못 잰다(26.9.9). 저장 로직을 한 벌로 두고
window.DG_LOCAL로 서버/로컬을 가르니, 서버 호출 코드 문자열은 독립본에도 남아 있다(가드 뒤라 실행은 안 된다). ⛒실증 = Playwright 로file://로 열고context.route로 file 이외 요청을 전부 abort → 「외부 요청 0건」을 센다. 문자열로는 「API 없음」을 못 증명한다. 저장 로직을 두 벌로 갈라 쓰는 건 더 나쁘다 — 한쪽만 고쳐진다. -
<details>를 기본 펼침으로 바꾸면 기존 UI 테스트가 반대로 동작한다(26.9.9). 「summary 를 눌러 펼친 뒤 입력」하던 검증이 접는 동작이 되고, 그 뒤fill()이 숨은 요소에 걸려 죽는다. 기본 상태를 바꿀 땐 테스트의 여닫는 단계부터 지운다. -
「이 문자열이 페이지에 없다」 자체검사는 CSS 때문에 항상 실패한다(26.9.9 6장 분리). 6장이 같은
<style>블록을 공유하니.dg-tabs·.ans-in같은 셀렉터 문자열이 모든 페이지에 들어 있다 → 「관리페이지엔 멤버 탭이 없다」를"dg-tabs" not in doc로 재면 무조건 FAIL. ⛒마크업만 잘라서 본다(doc.split("</style>",1)[1]) 그리고class="dg-tabs"처럼 속성 형태로 찾는다. 같은 이유로aria-current="page"개수를 세면 CSS 셀렉터가 1개 더 잡힌다. 반대로 JS 안의 문자열(API + '/grill')은 마크업에 없으니 그건 전체 문서에서 찾아야 한다 — 검사마다 「어디를 보는지」를 정해 둔다. -
devplan 8799 는
restart.py로 재기동한다 — 「코디가 못 끈다」는 옛말(26.9.9 실증).C:\dev\devplan\restart.py가 netstat 으로 LISTENING PID 를 잡아 죽이고pythonw로 다시 띄운 뒤 PID 가 1개인지 세어 성공을 확정한다.app.py에 API 를 추가하면 재기동 전에는 404 다 — 페이지가 멀쩡히 떠서 「API 가 깨졌다」로 오진하기 쉽다. ⚠netstat 은 cp949 로 뱉으니text=True를 쓰면 조용히 「포트 잡은 게 없다」가 된다(restart.py 안에 이미 적혀 있다). -
Git Bash
curl -d '한글'은 cp949 로 나가서 서버가 UTF-8 디코드에 실패한다(26.9.9).{"ok":false,"err":"'utf-8' codec can't decode byte 0xbf"}가 뜨면 API 가 아니라 셸이 범인이다. ⛒한글이 든 POST 왕복 시험은python urllib로json.dumps(...).encode('utf-8')해서 보낸다. -
사람이 쓰는 데이터와 코디가 쓰는 소스는 파일을 갈라 둔다(26.9.9 그릴링 자동저장). 멤버 답을
members.json(코디 손글씨 소스) 안에 넣었으면 재빌드 때마다 서로를 덮는다. → 답은answers.json단독 원장, 빌더는 읽기만 하고 굽는다. 질문 id 는 질문 원문 sha1 앞 8자 — 인덱스(q1…)로 잡으면 질문 하나만 끼워 넣어도 답이 통째로 밀린다. -
자동저장은 「타자 멈춤 0.7초 + blur」 두 곳에서 쏜다(26.9.9). 디바운스만 두면 타자 치다 탭을 닫으면 마지막 입력이 날아간다. 직전 값(
data-last)과 같으면 안 보내 중복 POST 를 막는다. 빈 칸 저장은 삭제로 처리하고 멤버 폴더가 비면 껍데기까지 지운다(안 지우면 「답변됨」 카운트가 어긋난다). -
모바일에서
position:sticky탭바와position:fixed햄버거가 겹친다(26.9.9). 데스크톱에선 좌측 네비라 안 만나는데, 767px 미만에서 네비가 offcanvas 로 접히며 「목차」 버튼이 좌상단 고정으로 뜨고 스크롤하면 sticky 탭이 그 밑으로 들어간다. ⛒모바일에서만.dg-tabs{position:static}— 어차피 멤버 1인 1페이지라 탭을 따라다니게 할 이유가 없다. -
당근 모임 앱은 WebView라 스크린샷만으론 본문이 잘린다(26.9.9 실측). 게시글 상세는 화면에 다 안 들어오고, 스크롤 캡처를 이어 붙여도 툴팁 말풍선(「참여중인 채팅방에 게시글을 공유해보세요!」)이 본문 한 줄을 통째로 가린다. ⛒접근성 노드 덤프가 정답 —
P._dump()로 XML 을 받아text="…"를 뽑으면 글 전문이 한 문자열로 나온다(줄바꿈은 ). 스크린샷은 「어디에 있나」 확인용, 본문은 노드 덤프용으로 역할을 가른다. - ⚠모임 홈에서 바로
_dump()하면 빈 결과가 나올 때가 있다 — 앱 실행 직후P.app(pkg)뒤 4초로는 WebView 렌더가 안 끝난다. 포커스(P.focused_pkg())로 먼저 확인하고 여유를 준다. - 게시글 목록도 노드에 안 잡히는 구간이 있다 → 목록은 스크린샷, 본문은 노드 조합이 확실하다.
-
앱 패키지 =
com.towneers.www, 상세 액티비티 =…minikarrot.DaangnWebActivity. -
Bash heredoc 안 파이썬 문자열의
\a·\h는 조용히 깨진다(26.9.9, 같은 세션에 2회)."C:\dev\ai-study\..."를 heredoc 파이썬에 넣었더니\a가 BEL 문자로 바뀌어 JSON 에C:\dev<BEL>i-study가 저장됐다.SyntaxWarning: invalid escape sequence가 떴는데도 실행은 성공해서 산출물을 눈으로 보기 전엔 안 잡힌다. ⛒전역규칙 §2-7 그대로 — 파일 작성은 Write/Edit 도구로, 부득이 스크립트면r"..."나chr(7)로 명시한다. -
devplan 새 프로젝트는
project_state.json에 항목을 손으로 넣어야 한다(26.9.9).project_state.py set은 없는 프로젝트면[FAIL] 없는 프로젝트로 죽는다(생성 기능이 없다). 기존 항목 하나를 그대로 베껴 키를 채운다. ⚠next_owner허용값은pepe/cody/null뿐 —"none"을 넣으면build_hub.py가 assert 로 통째로 죽는다(카드 하나 때문에 허브 전체 빌드 실패). -
apply_shell.py는projects.json에 등록되는 순간 새 페이지를 잡는다(26.9.9). 자체 좌측 네비를 쓰는 페이지에 공용 쉘이 씌워지면 사이드바가 2개가 된다. 주석으로는 못 막는다 →apply_shell.py의SKIP집합에 파일명을 넣는다(dev-portfolio.html,danggeun-ai-study.html).--renav는hub-shell-v1마커가 있는 페이지만 건드리므로 무해하다. -
폰트 13px 실측 검사에서
qahelper.js위젯이 항상 걸린다(26.9.9). 공용 위젯이 11~12px 를 쓴다(#qa-helper-toggle·#qa-helper-panel). 내 페이지 결함이 아니므로 Playwright 검사에서 그 두 컨테이너를 제외하고 잰다. (위젯 자체 수정은 별건 — 전 페이지에 영향) -
흰 글자 on
--accent(#c97c4a) 는 3.25:1 로 대비 미달(web-designer 실측 26.9.9). 활성 탭·번호 배지처럼 흰 글자를 얹는 자리는--accent-deep(#8a5a3c, 5.82:1) 을 쓴다. 상태 배지의 텍스트 색으로--live(3.46:1)·--hold(2.62:1)를 쓰면 안 된다 → 텍스트는 항상--ink, 상태색은 배경·보더로만. 행위자 색 관례 = 멤버 = accent 계열 / AI = live 계열(devplanworklog-triage.html과 동일). -
1차 ai-study 를 되살려야 하면(복원 절차) — 서버 4개는 스크립트가 그대로 있고 HKCU Run 값만 지웠다. 백업 =
C:\dev\ai-study\data\study-share\hkcu_run_backup_20260909.reg(Run 키 전체 export). 복원 = 그 .reg 를 병합하고 로그온하거나, 안의 4줄을 직접 실행. 공개 경로는tailscale funnel --https=443 --set-path /study http://127.0.0.1:8801(+/study-qa→8804,/study-hook→8802). ⛔tailscale funnel reset은 절대 쓰지 마라 —/·/agent·/furniture·/wmc/·/gdx/·/sci/·/bal/·/ain/까지 통째로 날아간다. -
나노바나나 카드 그림(t005~)은 레이아웃 지시(밴드 %)를 무시한다 — 글자 칸을 침범하거나, 밴드 경계를 전폭 얇은 안내선으로 실제로 그려 넣는다(26.9.11 card-03/06/07/08 raw 실측). 모델 배치를 못 믿으니 PIL 이 강제로 재배치한다 — ①글자를 투명 레이어에 먼저 그려 알파 bbox 로 「그림이 시작해도 되는 선」을 구하고 ②그림에서 종이 기준색과 다른 픽셀 중 가장 큰 연결 덩어리만 장면으로 인정한다(전폭 얇은 안내선은 연결요소로도 안 걸러질 만큼 고양이 머리에 붙어 나올 수 있어 행 단위로 먼저 스크럽 — 폭의 55%+ 를 가로지르면서 두께 6px 이하인 행은 지운다) ③그 선 아래·마무리줄(y≥1400) 위로 축소·이동(가장자리 feather), 배경은 상단 빈 종이를 타일로 재구성. 구현 =
C:\dev\devplan\danggeun\img\make_cards_nb.py의render_text/text_top/find_scene/_scrub_band_lines/paper_tile/place_scene/compose— 새 카드 세트를 밴드형(L_RULE) 판형으로 낼 때마다 이 파이프라인을 그대로 통과시켜야 한다(단순 bbox 로 되돌리면 재발한다).