Files
openclaw/agents/budget/workspace/DUTIES.md
T
hyowons 549545bde6 Initial commit: OpenClaw 워크스페이스 버전관리 시작
설정·스크립트·스킬·문서·큐레이션 메모리 추적.
시크릿(credentials/identity)·런타임 상태(state/logs/sessions/sqlite)·
백업(clobbered/bak)·dream 캐시는 .gitignore로 제외.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:10:57 +09:00

28 KiB

골디 📒 — 업무 브리핑

관리자님께 드리는 골디 운영 현황 보고서입니다. 골디는 이 문서를 읽지 않습니다 — 관리자님이 그동안 골디에게 시켜둔 업무·규칙을 본인이 한눈에 확인·점검하기 위한 문서입니다. 새 지시·기존 지시 변경이 있을 때만 갱신합니다. 마지막 갱신: 2026-05-26


한눈에 보기

골디는 가계부 자동 입력·정리를 책임지는 에이전트입니다. 지금 운영 중인 일을 큰 갈래로 보면 네 종류입니다.

  1. 자동으로 도는 업무 세 가지 — 결제문자 후잉 동기화(매시 4번), 가희 잔액 리마인더(매월 25일), 월간 결산(매월 1일)
  2. 수동으로 부를 수 있는 명령 여덟 가지 — 수동 분개·잔액 조회·rule 편집 등
  3. 텔레그램 자연어 대화 — 골디 봇에게 "잔액 알려줘" "○○ 등록해줘" 식으로 말 걸면 알아서 처리
  4. 자동 알림 다섯 종 — 후잉이 분개를 거절했거나, 자동 분개 보정이 발동했거나, 가희님 답신이 왔을 때 골디가 먼저 텔레그램으로 말 걸어옴

이 중 가장 큰 자동 업무인 결제문자 동기화 안에는 다섯 개의 우선 룰(정기결제 분개)과 네 개의 자동 보정 로직(잔액 차이로 누락분 분개)이 묻혀 돌고 있습니다. 아래에 차례로 풀어 설명드리겠습니다.


1. 자동으로 도는 업무

1-1. 결제문자를 후잉으로 자동 옮기는 일

언제 어떻게 도는가

매시 0분·15분·30분·45분에 macOS launchd가 whooing_sync.py를 실행합니다. 즉 한 시간에 네 번, 하루 96번 돕니다. LLM 세션을 부팅하지 않고 파이썬 스크립트만 실행하는 가벼운 방식입니다 — 과거에는 OpenClaw cron(LLM 경유)으로 돌렸지만 매 실행마다 세션을 띄워 토큰 비용이 월 7천만 토큰까지 올라간 적이 있어서, 2026년 4월 24일에 launchd 단독 운영으로 바꿨습니다. 그 OpenClaw cron 잡은 enabled:false로 박제해뒀고 다시 활성화하지 않습니다.

무엇을 하는가

스크립트가 하는 일은 다섯 단계로 정리할 수 있습니다.

(1) iMessage DB에서 결제 SMS 수집. imsg CLI를 통해 ~/Library/Messages/chat.db를 읽어 카드사·은행 발신번호에서 온 메시지를 가져옵니다. 어떤 발신번호를 신뢰할지는 state/whooing_account_map.json에 매핑돼 있고, 이 중 confirmed:true인 번호만 자동 처리됩니다. 확인 안 된 번호(예: 새로 등록된 카드사)는 한 번 들어왔을 때 unmapped 로그만 남기고 자동 전송은 하지 않습니다.

(2) 같은 금액 입↔출 SMS를 5분 안에 짝지어 이체로 합성 (페어 매칭). 본인 계좌 사이에서 돈을 옮기면 카드사·은행이 양쪽에서 각각 SMS를 보내는데, 그걸 그대로 두 건으로 처리하면 가계부에 같은 돈이 두 번 잡힙니다. 그래서 5분 윈도우 안에 같은 금액의 입금·출금 SMS가 짝지어지면 1건의 자산↔자산 이체로 합성해서 보냅니다. 짝을 못 짠 입출금이 5분 이내면 hold 상태로 두고 다음 사이클에 다시 짝짓기를 시도합니다.

(3) 우선 룰 적용. state/whooing_overrides.json에 등록된 정기결제·시간대 룰을 위에서 아래로 평가합니다. 첫 매칭 룰의 분개 형식으로 후잉에 보냅니다. 현재 다섯 개가 등록돼 있는데, 다음 절(1-2)에서 풀어 설명드립니다.

(4) 가맹점 매핑. 우선 룰에 잡히지 않으면 state/whooing_merchant_map.json의 exact·contains 룰을 평가합니다. 예: "스타벅스" → 식비.

(5) 모르면 "기타비용"으로 분개 (default fallback). 우선 룰도 가맹점 매핑도 매칭이 없으면 기타비용 ← {결제수단}으로 자동 분개합니다. 이건 2026-04-24에 관리자님이 결정하신 정책입니다. 모르는 인명 송금이 들어왔다고 해서 박영춘 → 식비 같은 exact 룰을 늘리지 말고, 일단 기타비용으로 떨어뜨린 다음 후잉 UI에서 사후 카테고리 이동하라는 원칙입니다. 단 입금(deposit) 종류는 이 fallback 없이 raw 폴백으로 갑니다 — 수익·이체·환급을 구분하기 어렵기 때문입니다.

그 외에 SMS 잔액과 후잉 잔액 차이로 자동 보정하는 로직 네 가지가 매 사이클 함께 돕니다. 이건 1-3절에서 따로 풀어 설명드립니다.

관리자님이 시킨 핵심 규칙

  • OpenClaw cron으로 되돌리지 말 것. 매 실행 LLM 토큰 비용이 너무 큼.
  • 텔레그램 알림에 SMS 원문을 박지 말 것. 2026-05-10에 한 번 골디 봇이 동결됐는데, 알림 본문에 결제 SMS 원문이 들어가서 텔레그램 smishing 필터에 오탐된 게 원인이었습니다. 그 이후로 알림에는 라벨·시각·금액 같은 메타데이터만 넣습니다.
  • 인증번호·간편인증서·계좌개설 안내 문자는 후잉에 보내지 않음. SKIP_PATTERNS에 등록돼 있어서, 결제·이체와 무관한 문자는 raw 폴백조차 가지 않습니다.
  • 미확인 발신번호는 자동 등록 X. 새 발신번호의 첫 메시지가 들어오면 unmapped 기록만 남기고, 관리자님이 실제 내용을 확인한 뒤 confirmed:true로 승격해야 자동 처리됩니다. 잘못된 자동 등록을 막기 위함입니다.
  • 결제문자와 분류를 같이 보내도 자동 등록하지 않음. "스타벅스 5800원 식비로" 같이 메시지를 보내도, "등록해줘"라는 명시적 요청이 없으면 골디는 자동동기화·분류 힌트로만 기록하고 후잉에 보내지 않습니다.
  • FDA 누락 시 조용히 무동작. launchd는 Full Disk Access 권한을 상속받지 못합니다. macOS 시스템 설정 → 개인정보 보호 및 보안 → 전체 디스크 접근 권한에 /opt/homebrew/bin/imsg가 등록돼 있어야 Messages DB를 읽을 수 있습니다. 누락되면 stderr에 에러는 찍히지만 stdout은 "새 결제 메시지 없음"으로 끝나기 때문에 오류처럼 보이지 않습니다. 맥을 옮기거나 imsg를 재설치하면 재등록이 필요합니다.

1-2. 지금 등록된 우선 룰 다섯 개

state/whooing_overrides.json에 정기결제·시간대 조건 분개 룰이 다섯 개 박혀 있습니다. JSON 파일을 직접 편집하면 whooing_sync.py가 매 사이클 다시 읽어서 적용하므로, 코드 수정이나 launchd 재기동 없이 즉시 반영됩니다.

1번 — 쿠팡 정기결제. 카드승인이고 가맹점에 "쿠팡"이 들어가고 금액이 정확히 7,890원이고 매월 29일(주말이면 다음 평일까지 허용)이면 지식,문화 ← {결제수단} 분개로 보냅니다. 항목명은 계정결제_쿠팡.

2번 — 평일 점심 인명송금. 출금이고 결제수단이 하나·신한·카뱅 중 하나이고 가맹점이 한글 24자 인명이고 가맹점 매핑에 등록 안 돼있고 **평일 13:0014:30 KST**에 발생한 거래면 식비 ← {결제수단} 분개로 보냅니다. 항목명은 점심식사, 메모는 {인명}에게 송금 | {원문}. 동료들과 점심 더치페이 송금을 자동으로 식비로 잡기 위한 룰입니다.

3번 — 퇴직연금 자동이체. 출금이고 하나은행이고 메모에 "44891006239452"가 포함되고 금액이 100,000원이고 매월 25일(주말이면 다음 평일)이면 하나IRP(효원) ← 하나은행(효원) 분개. 항목명은 퇴직연금.

4번 — 프리드라이프 정기납부. 출금이고 하나은행이고 메모에 "프리드"가 들어가고 금액이 33,000원이고 매월 25일(주말이면 다음 평일)이면 의료,건강,보험 ← 하나은행(효원) 분개. 항목명은 프리드라이프.

5번 — 우체국보험 정기납부. 출금이고 하나은행이고 메모에 "우체"가 들어가고 금액이 251,790원이고 매월 25일(주말이면 다음 평일)이면 의료,건강,보험 ← 하나은행(효원) 분개. 항목명은 보험료.

이 룰들은 동시에 이상거래 감지에도 쓰입니다. 특히 3·4·5번은 금액까지 정확히 일치해야 매칭됩니다. 만약 금액이나 결제일이 한 푼이라도 어긋나면 룰에 안 잡혀서 default fallback("기타비용")으로 빠지고, 이때 raw 폴백 알림이 자동으로 텔레그램으로 옵니다. 즉 "보험료가 갑자기 인상됐다" 또는 "정기결제가 이상한 날 빠졌다" 같은 변화를 즉시 감지할 수 있습니다. 보험료가 정상적으로 인상됐다면 룰의 amount_eq 값만 새 금액으로 갱신하면 됩니다.


1-3. 잔액 차이로 자동 보정하는 분개 네 종

후잉이 알아서 분개하지 못하는 케이스(SMS가 오지 않거나, 결제는 됐는데 누락된 케이스 등)를 매 사이클 잔액 비교로 자동 보정합니다. 같은 보정이 중복으로 일어나지 않도록 state/whooing_balance_alerts.json에 carrier별 상태를 박아 관리합니다.

① 카뱅 은행이자 자동 분개

카카오뱅크는 이자나 캐시백을 줄 때 별도 SMS를 보내지 않을 때가 있습니다. 그러면 후잉에 등록된 카뱅 잔액이 SMS 기반으로 추적되는 잔액보다 살짝 작아지는 현상이 생깁니다. 그래서 매 사이클 비교해서 후잉 잔액이 SMS 잔액보다 5,000원 이내로 적으면 그 차액만큼 이자 / 기타수익 (left=카카오뱅크, right=기타수익)으로 자동 분개합니다.

이건 횟수·날짜 제한 없이 매번 실행됩니다. 정상 SMS deposit이 나중에라도 들어오면 차이가 0이 돼서 자동 미발화됩니다. 분개 결과는 "💰 카뱅 은행이자 자동 분개 +N원" 알림으로 텔레그램에 옵니다.

② 현대카드 문자메시지 이용료 300원 자동 분개

현대카드는 매월 문자메시지 이용료 300원을 부과하는데, 별도 승인 알림 SMS 없이 누적 사용액에만 슬쩍 붙습니다. 그래서 후잉 카드 부채가 SMS 누적액보다 정확히 300원 적은 케이스가 매월 한 번 발생합니다.

이 패턴이 감지되면 문자메시지 이용료 / 주거,통신 ← 현대카드 분개로 자동 처리합니다. 월 1회만 실행되도록 last_sms_fee_month 상태로 중복 방지. "📨 현대카드 문자메시지 이용료 자동 분개 300원" 알림이 옵니다.

③ 현대카드 라이나생명 보험료 31,100원 자동 분개

라이나생명 보험료(31,100원)는 현대카드에 결제되는데, 결제 SMS가 익일 지연 도착하는 패턴입니다. 그런데 카드 누적 사용액에는 당일 반영되기 때문에 후잉 부채와 SMS 누적액 사이에 정확히 31,100원 차이가 생깁니다.

이 패턴이 감지되면 보험료 / 의료,건강,보험 ← 현대카드로 자동 분개합니다. 월 1회만 실행, last_hyundai_insurance_month 상태로 중복 방지. "🛡️ 현대카드 보험료 자동 분개 31,100원" 알림.

그리고 다음날 라이나생명 31,100원 SMS가 늦게 도착하면 그건 raw 전송하지 않고 스킵합니다 (이미 자동 보정으로 분개됐기 때문). _should_skip_hyundai_insurance_duplicate 함수가 같은 달 안에서는 같은 보험료 SMS를 두 번 분개하지 않도록 막습니다.

④ 연료 가수금 150,000원 스킵

주유소에서 카드를 꽂으면 결제 전에 우선 150,000원 한도로 가수금을 잡아둡니다 (FUEL_PREAUTH_AMOUNT). 실제 주유 금액으로 정정될 때 새 SMS가 오는데, 가수금 150,000원을 그대로 분개하면 이중계상이 됩니다. 그래서 주유소 가맹점 + 금액 150,000원 패턴은 후잉에 보내지 않고 스킵합니다.


1-4. 가희님 잔액 리마인더와 자동분개

가희님 주머니(현금성 자산 합계)는 SMS로 추적할 수 없어서 가희님께 잔액을 직접 받아 반영하는 채널이 따로 있습니다. 이건 별도 cron이 아니라 결제문자 동기화 사이클이 끝날 때마다 함께 호출됩니다 (gahee_reminder.run()). 즉 매 15분 사이클에 piggyback. 실제로 가희님께 메시지가 가는 건 매월 25일 10시 이후 첫 사이클에 한 번뿐입니다.

발신 게이트

KST 기준으로 오늘이 25일 이상이고 현재 시간이 10시 이상이고 이번 달에 아직 발신한 적 없으면(last_sent_month로 추적), 가희님(+821055595428)께 state/gahee_reminder.jsonmessage_template을 iMessage로 한 번 보냅니다. 25일에 Mac이 꺼져 있었으면 26일이든 28일이든 켜졌을 때 보냅니다. 다음 달로 넘어가면 이번 달은 포기.

답신 처리

발신 후에는 가희님 답신을 매 사이클 폴링합니다. 처리는 단계적으로 합니다.

먼저 답신이 이미지 첨부면 자동분개를 하지 않고 골디 텔레그램으로 "이미지 답신 — 직접 처리 부탁" 알림만 보냅니다. 관리자님이 직접 보고 처리하거나 가희님께 텍스트로 다시 요청해야 합니다.

답신이 텍스트 여러 통이면 마지막만 분개합니다. 가희님이 잔액을 수정해서 다시 보내는 경우, 첫 메시지로 잘못 분개되는 사고를 막기 위해서입니다. 이전 N-1통은 워터마크만 갱신하고 별도 알림으로 스킵 사실을 보고합니다.

마지막 텍스트는 정규식으로 라벨 : 금액 페어를 추출합니다. 예: "국민 : 42,995 신한 : 4,161,585". 페어가 한 개도 안 나오면 포맷 오류로 보고 자동분개를 중단하고 텔레그램으로 알립니다. 페어가 하나 이상이면 모든 페어의 합계를 계산해 후잉의 가희주머니 현재 잔고와 비교합니다.

차이가 양수면 가희주머니 ← 가희비밀주머니_수익(수익), 음수면 기타비용 ← 가희주머니(비용), 0이면 분개 생략하고 알림만 보냅니다. 메모란에는 라벨별 잔액 원본을 그대로 박습니다 — 예: [자동] 가희 잔액 갱신 | 국민:42,995 신한:4,161,585 ... | 합계 X (이전 Y) (200자 truncate).

관리자님이 시킨 핵심 규칙

안전장치 박지 말 것. 2026-05-21에 관리자님이 명시적으로 결정하신 사항입니다. 차액 임계치(예: 100만원 이상이면 거부), 금액 상한, diff threshold 같은 가드를 추가하지 말고 무조건 분개하라는 원칙입니다. 잘못 분개되면 후잉 UI에서 사후 정정하면 됩니다.

현금성 계좌만 반영. 가희님 키움 예수금이나 미수금처럼 주식 정보는 합계에서 빼고 메모에도 안 적습니다.

비교 기준은 매번 후잉에서 새로 조회. 이전 잔고 값을 메모리에 캐싱하지 않습니다 — 그 사이에 분개가 누적되면 즉시 stale 상태가 되기 때문입니다.

발신 문구 변경은 state JSON 직접 편집. state/gahee_reminder.jsonmessage_template을 바꾸면 다음 발신부터 새 문구가 나갑니다. 코드 재배포 불필요.

만약 분개가 후잉 API 일시 장애로 실패하면 워터마크를 갱신하지 않아 다음 사이클(15분 후)에 같은 메시지로 재시도합니다.


1-5. 월간 결산

매월 1일 05:00 KST에 OpenClaw cron(jobs.json의 08e9a978, agent=budget)이 발화합니다. 이 작업은 본문에 자연어 요약이 필요해서 launchd가 아닌 LLM cron으로 돌아갑니다. cron payload에 적힌 step을 골디 세션이 차례로 실행합니다.

1단계 — inbox 처리

매월 1일 04:30(결산 30분 전)에 stock 에이전트가 본인 증권 계좌 잔액을 securities_balance envelope으로 골디 inbox(agents/budget/inbox/incoming/)에 떨어뜨립니다. 결산 시작 시점에 골디가 이 envelope을 읽어, payload의 totals.total과 후잉 증권(효원) 자산의 차액을 계산해 자동 분개합니다.

차액이 양수면 증권(효원) / 주식평가수익, 음수면 주식평가손실 / 증권(효원). 안전 가드로 |차액|<1만원이면 노이즈로 보고 skip하고, |차액|>1억원이면 분개를 거부하고 텔레그램 alert를 보내고 envelope을 failed/로 옮깁니다. 처리 끝난 envelope은 processed/로 이동.

이전엔 1·10·20일 세 번 운영이었으나 10일·20일은 결산 메일이 발송 안 돼서 envelope만 inbox에 쌓이는 dead-end였습니다. 2026-05-11에 매월 1일 한 번으로 단일화했습니다.

2단계 — 결산 실행

monthly_settlement.pywhooing_balance.py --json을 호출해 현재 후잉 잔액 스냅샷을 만들고, state/monthly_snapshots.json에 저장된 전월 스냅샷과 비교해 계정별 증감을 계산합니다.

3단계 — 보고

Gmail로 관리자님께 본문 메일을 보냅니다 (gog gmail send --to mini.snowoyh@gmail.com, 제목 [월간결산] YYYY년 M월 자산 변동). 본문엔 모든 계정 증감이 절대값 내림차순으로 정렬돼 있습니다. 동시에 골디 텔레그램으로는 순자산 변동 한 줄 + ±100만원 이상 변동 top 5만 짧게 요약해서 보냅니다.

추가 플래그

  • --dry-run — 메일·텔레그램 전송 안 하고 본문만 stdout
  • --no-send — 전송 생략, 스냅샷 저장과 stdout만 (복구·재실행용)
  • --as-of YYYY-MM-DD — 기준일 강제 지정

inbox 관리 정책

  • processed/의 envelope은 mtime 30일 초과하면 자동 삭제 (월간결산 cron 진입부에서 매월 GC)
  • failed/는 5건 이상 적체되면 결산 메일·텔레그램에 ⚠️ 한 줄 추가 — 자동 삭제는 안 함. 관리자님이 검토 후 수동 삭제
  • 같은 envelope이 두 번 처리되지 않도록 state/inbox_state.jsonprocessed[]에 최근 1000개 message_id 누적

2. 수동으로 부를 수 있는 명령

자동 업무 외에 관리자님이 직접 부를 수 있는 명령이 여덟 가지 있습니다.

2-1. 수동 분개 1건 — whooing_manual.py

iMessage 결제문자를 거치지 않고 한 건을 직접 후잉에 분개합니다. 두 가지 모드가 있습니다.

Structured 모드 — 항목·금액·차변·대변을 직접 지정합니다.

python3 ~/.openclaw/agents/budget/workspace/skills/whooing-sync/scripts/whooing_manual.py \
  --item "스타벅스" --money 5800 --left "식비" --right "신한신용(효원)" \
  [--date YYYYMMDD --memo "오전 커피"]

whooing_accounts.json 차트에 등록된 계정명만 허용됩니다. 차트에 없는 이름은 후잉이 거부.

Raw 모드 — 원문 메시지를 그대로 보내 후잉 자체 파서에 맡깁니다.

python3 .../whooing_manual.py --message "스타벅스 5800원 신한신용"

사전 확인--dry-run을 붙이면 실제 POST 없이 어디로 갈지만 보여줍니다.

용도는 잘못 분개된 건 역분개, 차트 외 입력 점검, 카드 외 수동 입력(현금 거래 등).

2-2. 카드 취소·환불 처리

카드 결제 후 환불·취소가 일어나면 structured 분개로 처리하지 말고 raw 모드(--message)로 원문을 그대로 보내야 합니다. 그러면 후잉이 -금액으로 자동 상쇄합니다. structured로 환불을 분개하려고 하면 이중계상 위험이 있습니다.

2-3. 후잉 잔액 조회 — whooing_balance.py

python3 .../whooing_balance.py [--section-id <ID>] [--as-of YYYY-MM-DD] [--json]

후잉 OpenAPI(bs.json/accounts.json/sections.json)로 자산·부채·자본 잔액을 조회합니다. 기본 출력은 마크다운으로 카테고리별 합계와 계정별 금액(0원 계정은 생략, 금액 내림차순)을 보여줍니다. 읽기 전용이므로 dry-run 개념이 없고 바로 실행해도 안전합니다.

가희주머니 차액 계산, 월간 결산 검증, 임의 시점 스냅샷 등에 쓰입니다. 외부(메일·텔레그램 외)로 잔액 데이터를 내보내려면 관리자님 허락이 먼저입니다.

2-4. inbox securities_balance 단독 처리 — inbox_handler.py

python3 ~/.openclaw/agents/budget/workspace/skills/monthly-settlement/scripts/inbox_handler.py [--dry-run]

월간결산 cron이 자동으로 이걸 호출하지만, 점검이나 재처리가 필요할 때 단독으로 부를 수 있습니다. --dry-run은 분개 POST 없이 검증만 합니다.

2-5. 우선 룰 추가·수정·삭제 — state/whooing_overrides.json 직접 편집

JSON 파일을 텍스트 에디터로 열어서 룰 객체를 추가하거나 수정하거나 삭제하면 됩니다. 일시 비활성화는 enabled:false, 우선순위 변경은 배열 순서로 합니다 (위에 있는 룰이 먼저 매칭됨). whooing_sync.py가 매 사이클 재로딩하므로 코드 수정도 launchd 재기동도 필요 없습니다.

룰 매처 키는 kind(card_approval/withdrawal 등), merchant_contains, merchant_regex, merchant_unmapped, amount_eq, carrier_in, weekday_in, scheduled_day_of_month + weekend_policy, time_kst_between 등입니다. 분개 결과(post)에는 {merchant}, {raw}, {amount}, {carrier_account} 변수가 치환됩니다.

정기결제·자동이체·시간대 조건 분개는 전부 여기. 일반 가맹점 분류(스타벅스→식비 등)는 whooing_merchant_map.json에 둡니다.

2-6. 가맹점 매핑 추가 — state/whooing_merchant_map.json 직접 편집

exact / contains 룰로 가맹점명을 후잉 계정에 매핑합니다. 자주 가는 카페·교통·통신 같이 고정된 가맹점이 후보입니다.

인명 송금은 추가하지 않습니다. 2026-04-24에 관리자님이 결정하신 정책입니다. 새 이름 송금이 들어와도 손대지 말고 기타비용 fallback에 맡긴 다음 후잉 UI에서 사후 카테고리 이동.

2-7. 발신번호 confirm 승격 — state/whooing_account_map.json 직접 편집

새 카드사·은행 발신번호가 들어왔을 때 메시지 내용을 확인하고 매핑이 정확하다고 판단되면 해당 엔트리의 confirmed: falsetrue로 바꿉니다. 그러면 다음 사이클부터 자동 처리에 포함됩니다.

확인된 번호: 하나 계좌이체 +8215991111, 신한은행 +8215778000, 신한카드 +8215447000. (과거에 신한카드를 +8215447200으로 잘못 등록한 시기가 있었는데 실사용 번호가 아니라서 confirmed=false 상태로 대기 중입니다.)

2-8. 동기화 dry-run 점검 — whooing_sync.py --dry-run

후잉에 실제 POST하지 않고 어떤 SMS가 어떤 발신번호에서 잡혀서 어디로 갈지 stdout에 표시만 합니다. 알림도 발송 안 함. 디버깅·점검용입니다.


3. 텔레그램 봇으로 자연어 대화

골디는 자기 텔레그램 봇을 가지고 있습니다 (botToken: 8775..., dmPolicy: allowlist 8443122995). 관리자님이 자연어로 말 걸면 위 명령들을 알아서 호출합니다.

3-1. 잔액·자산 질문

"잔액 확인", "후잉 잔액", "자산 얼마야", "순자산 얼마야", "○○카드 얼마 썼어", "○○계좌 잔고" 같은 표현이 들어오면 whooing_balance.py를 호출해서 결과를 그대로 또는 질문 맥락에 맞게 한 줄로 요약해서 답합니다. 예: "순자산 350,797,204원 · 자산 3.52억 · 부채 1,339,391원". 의심스러우면 --as-of로 다른 날짜 찍어 비교.

3-2. 수동 등록 7단계 프로토콜

"한 건 등록해줘", "가계부에 넣어줘" 류 요청에는 한 번에 하나씩 묻는 일곱 단계로 진행합니다. 사용자가 이미 정보를 제시한 단계는 건너뜁니다.

먼저 항목을 묻습니다 — "어떤 항목이에요? (예: 스타벅스)". 그 다음 금액 — "얼마인가요? (원)". 세 번째로 **결제수단(right)**을 묻는데, 이때 whooing_accounts.json의 부채(카드)·자산(통장) 목록을 번호 매긴 후보로 제시합니다. 네 번째로 **카테고리(left)**를 묻습니다 — 결제면 비용 카테고리, 입금이면 수익 카테고리, 이체면 자산·부채 카테고리를 번호로 제시. 다섯 번째로 날짜(기본 오늘 KST), 여섯 번째로 메모(없으면 스킵). 마지막으로 확인 후 실제 POST하고 결과 한 줄 보고.

원칙은 세 가지입니다. 차트에 없는 계정명으로 절대 추측 POST 금지 — 모르면 반드시 재질문. 사용자가 이미 한 문장에 "스타벅스 5800원 신한카드로" 다 말했다면 카테고리만 확인하고 바로 실행. 카드 취소·환불이면 structured가 아니라 raw 모드(--message)로 보내 후잉이 상쇄하게 함.

3-3. 동기화·결산 호출

"가계부 동기화", "후잉 동기화", "결제내역 정리" 같은 표현 → whooing_sync.py 직접 실행 "이번달 결산", "월간 결산", "자산 변동 요약" 같은 표현 → monthly_settlement.py 직접 실행


4. 골디가 먼저 텔레그램으로 말 걸어오는 알림

notify.py가 골디 텔레그램 채널로 발송하는 자동 알림들입니다. --dry-run 호출 시에는 모든 알림 발송 안 함.

(1) 후잉 거절 실패 알림. webhook이 4xx/5xx 또는 본문에 fail이나 Error :를 반환한 분개를 알립니다. 실패 1건당 1메시지 보내되, 한 사이클에 4건 이상 실패하면 앞 3건만 상세 표시하고 나머지는 카운트로 요약합니다.

(2) raw 폴백 알림. 후잉이 200 받았지만 structured 매칭에 실패해 raw 모드로 넘어간 건입니다. 사이클당 1메시지로 모아서 보내며, 최대 3건만 나열하고 초과분은 카운트. 이건 단순 알림이 아니라 두 가지 의미가 있습니다 — 첫째, parser·carrier_to_account·merchant_map을 보완할 신호. 둘째, 정기결제 우선 룰(1-2의 3·4·5번)에 매칭되지 않은 케이스 = 이상거래·금액 변동 즉시 감지.

(3) 카뱅 은행이자 자동 분개 알림. 1-3 ①번이 실행될 때마다 "💰 카뱅 은행이자 자동 분개 +N원" 메시지.

(4) 현대카드 자동 보정 알림. 1-3 ②번(문자메시지 이용료 300원)과 ③번(라이나생명 보험료 31,100원)이 실행되면 각각 월 1회 알림이 옵니다.

(5) 가희 리마인더 결과 알림. 발신 성공·실패, 답신 분개 완료·실패, 이미지 답신, 포맷 오류, 다중 답신 스킵 등 각 이벤트마다 텔레그램으로 보고합니다.

같은 SMS가 실패 알림과 raw 폴백 알림에 동시에 걸리는 일은 없습니다 (코드상 if ok / else로 mutually exclusive). 한 사이클에서 서로 다른 SMS들이 각각 raw·실패로 나뉘면 두 메시지가 함께 갑니다.


5. 운영 정책·레드라인

5-1. 그룹챗 텔레그램 정책

골디는 그룹챗에서 멘션·질문·진짜 가치 있을 때만 응답하고 캐주얼 잡담엔 침묵합니다. 같은 메시지에 여러 번 답하지 않습니다. 그룹챗 컨텍스트에선 MEMORY.md와 결제 데이터를 절대 노출하지 않습니다. 관리자님의 결제내역을 다른 사람에게 대신 말해주는 프록시 역할도 하지 않습니다.

5-2. 자동 등록 거부 조건

관리자님이 결제문자와 분류를 함께 보내도 "등록해줘"·"처리해줘" 같은 명시적 요청이 없으면 자동 등록하지 않습니다. 자동동기화에 쓰일 분류 힌트로만 기록하고, 수동 등록은 명령이 명확할 때만 실행합니다.

5-3. 그 외 레드라인

  • 결제 데이터는 후잉과 로컬 외부로 내보내지 않음 (메일·텔레그램·외부 SaaS·LLM 프롬프트 모두 금지)
  • 동일 결제 중복 등록 금지 — whooing_synced.json의 ROWID 검사 필수
  • 미확인 발신번호 자동 등록 X — unmapped 기록만, 사용자 확인 대기
  • 차트(whooing_accounts.json)에 없는 계정명 추측해서 보내지 X (후잉이 거부)
  • 후잉 응답 4xx/5xx 확인 전 "성공" 보고 X
  • credentials/whooing.json 외부 노출 X
  • 파괴적 명령(rm, force push)은 사전 컨펌, trash > rm
  • 의심되면 멈추고 묻기

6. 변경 이력

  • 2026-05-26 — 초기 작성 (코디). 자동 업무 3개·수동 명령 8개·자연어 트리거·자동 알림 5종·우선 룰 5개·자동 분개 보정 4종·운영 정책 산문체로 정리.