twitter-collector 복구
결론
Hermes 쪽 twitter-collector는 수집 자격 파일과 cron 등록이 빠져 있어 최신 산출물이 없었고, 실행 경로도 twikit 2.3.3의 KEY_BYTE indices 실패 후 Playwright/Scrapling으로 떨어지면서 macOS MachPort EPERM에 막히는 구조였다.
복구 결과:
- accounts.json 146개 계정 + X cookie cache를 Hermes memory로 복원.
- twikit ClientTransaction 실패 시 no-op transaction id로 재시도하도록 twitter_collector.py 수정.
- 수동 실행 성공: 3명 / 1개 트윗 수집, DB 저장, 리포트 생성.
- Hermes cron 신규 등록: ocTC-twitter-collector, 10 */6 * * * (6시간 간격), 다음 실행 2026-04-16T12:10:00+09:00.
- 기존 fundamental-twitter-collector도 Python 3.13 경로로 보정.
- macro/fundamental/technical wrapper가 Twitter context를 읽도록 연동 확인.
1. 위치 식별
스크립트:
- /Users/ron/.hermes/workspace/scripts/pipeline/twitter_collector.py
- 원본 OpenClaw: /Users/ron/.openclaw/workspace/scripts/pipeline/twitter_collector.py
Hermes 출력 위치:
- memory: /Users/ron/.hermes/workspace/memory/twitter-collector/
- reports: /Users/ron/.hermes/workspace/memory/twitter-collector/reports/
- DB: /Users/ron/.hermes/data/ops_multiagent.db, table tweets
- log: /Users/ron/.hermes/workspace/logs/twitter_collector.log
OpenClaw cron 원본:
- id: twitter-collector
- 상태: enabled=false
- schedule: 0 0,12 * * * Asia/Seoul
- command: cd /Users/ron/.openclaw/workspace/scripts/pipeline && python3 twitter_collector.py --notify --sync-following
Hermes 기존 상태:
- ~/.hermes/workspace/memory/twitter-collector/ 디렉터리는 있었지만 산출물 없음.
- ~/.hermes/cron/jobs.json에는 처음 조사 시 twitter_collector.py를 정식 6시간 수집으로 돌리는 cron이 없었음.
- 작업 도중 이미 생긴 fundamental-twitter-collector도 발견했지만, 06:20 1일 1회 사전 수집용이었고 Python 경로를 보정했다.
2. 실패 원인
확인된 원인 4개:
- Hermes memory 이관 누락
accounts.json이 없어 수집 대상이 없었다.-
과거 OpenClaw 로그에도
No accounts to collect from가 반복됨. -
cookie cache 이관 누락/불확실
- X 수집은
auth_token/ct0쿠키 기반. -
Hermes 쪽 최신 memory에 파일이 없었고, migration archive에만 남아 있었다.
-
twikit 2.3.3 ClientTransaction 파서 실패
- 증상:
Couldn't get KEY_BYTE indices -
X의 ondemand JS 패턴 변화로 twikit이
X-Client-Transaction-Id생성에 실패. -
Scrapling/Playwright fallback이 현재 macOS 실행 환경에서 EPERM
- 직접 재현한 브라우저 launch 실패 핵심:
bootstrap_check_in org.chromium.Chromium.MachPortRendezvousServer... Permission denied (1100) - 따라서 “twikit 실패 → 브라우저 fallback”은 안정 복구 경로가 아니었다.
3. 복구 조치
3-1. credentials/data 복원
복원 출처:
- /Users/ron/.hermes/migration/openclaw/20260403T154207/archive/workspace/memory/twitter-collector/accounts.json
- /Users/ron/.hermes/migration/openclaw/20260403T154207/archive/workspace/memory/twitter-collector/cookies_cache.json
복원 결과:
accounts_count 146
cookie_auth 5941...f521
cookie_ct0 9582...ea61
cookie_keys ['__cf_bm', '__cuid', 'att', 'auth_token', 'ct0', 'external_referer', 'gt', 'guest_id', 'guest_id_ads', 'guest_id_marketing', 'kdt', 'personalization_id', 'twid']
권한:
- accounts.json: 600
- cookies_cache.json: 600
3-2. 코드 수정
수정 파일:
- /Users/ron/.hermes/workspace/scripts/pipeline/twitter_collector.py
수정 내용:
- twikit ClientTransaction이 KEY_BYTE indices에서 실패하면 브라우저 fallback으로 바로 내려가지 않고, no-op transaction id("0")로 twikit 요청을 재시도.
- 실제 테스트에서 authenticated timeline 요청은 dummy transaction id로 정상 응답함.
- Playwright fallback은 남겨두되, 1차 복구 경로는 twikit no-op retry로 변경.
검증:
/opt/homebrew/bin/python3.13 -m py_compile /Users/ron/.hermes/workspace/scripts/pipeline/twitter_collector.py
OK
3-3. 수동 실행 검증
실행 1 — Python 3.13:
cd /Users/ron/.hermes/workspace/scripts/pipeline
PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/opt/homebrew/sbin \
/opt/homebrew/bin/python3.13 twitter_collector.py --dry-run --limit 3
결과:
[2026-04-16 10:02:55] Starting Twitter collector pipeline
[2026-04-16 10:02:55] Loaded 146 accounts
[2026-04-16 10:02:55] Collecting from 3 accounts
[2026-04-16 10:02:55] Cookies loaded from cache
[2026-04-16 10:02:55] [WARN] twikit ClientTransaction fallback enabled: Couldn't get KEY_BYTE indices
[2026-04-16 10:02:56] @dair_ai: 1 tweets
[2026-04-16 10:03:03] Collection done: 3 ok, 0 failed, 1 tweets
[2026-04-16 10:03:03] Saved 1 tweets to DB
[2026-04-16 10:03:21] Report saved: /Users/ron/.hermes/workspace/memory/twitter-collector/reports/report-2026-04-16-1003.md
실행 2 — /usr/bin/python3 경로 호환 확인:
/usr/bin/python3 twitter_collector.py --dry-run --limit 3
결과:
[2026-04-16 10:10:37] Starting Twitter collector pipeline
[2026-04-16 10:10:37] Loaded 146 accounts
[2026-04-16 10:10:37] Collecting from 3 accounts
[2026-04-16 10:10:37] Cookies loaded from cache
[2026-04-16 10:10:37] [WARN] twikit ClientTransaction fallback enabled: Couldn't get KEY_BYTE indices
[2026-04-16 10:10:38] @dair_ai: 1 tweets
[2026-04-16 10:10:45] Collection done: 3 ok, 0 failed, 1 tweets
[2026-04-16 10:10:45] Saved 1 tweets to DB
[2026-04-16 10:11:05] Report saved: /Users/ron/.hermes/workspace/memory/twitter-collector/reports/report-2026-04-16-1011.md
최신 산출물:
/Users/ron/.hermes/workspace/memory/twitter-collector/reports/report-2026-04-16-1011.md
/Users/ron/.hermes/workspace/memory/twitter-collector/reports/report-2026-04-16-1003.md
DB 확인:
count (2109,)
max created/collected ('2026-04-15T15:21:07+00:00', '2026-04-16 10:03:03')
recent ('dair_ai', 'Small models are cheap to run, but expensive to adapt...', '2026-04-15T15:21:07+00:00', '2026-04-16 10:03:03')
4. Hermes cron 등록
수정 파일:
- /Users/ron/.hermes/cron/jobs.json
백업:
- /Users/ron/.hermes/cron/jobs.json.bak-twitter-collector-20260416T100534
- /Users/ron/.hermes/cron/jobs.json.bak-twitter-collector-nonotify-20260416T100620
- /Users/ron/.hermes/cron/jobs.json.bak-twitter-python313-20260416T101114
- /Users/ron/.hermes/cron/jobs.json.bak-twitter-restore-6h-20260416T101343
신규 job:
id: ocTC-twitter-collector
enabled: True
schedule: 10 */6 * * * Asia/Seoul
next_run_at: 2026-04-16T12:10:00+09:00
timeout_seconds: 2400
command: PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/opt/homebrew/sbin PYTHONPATH=/Users/ron/.hermes/workspace/scripts/shared:/Users/ron/.hermes/workspace/scripts/pipeline /opt/homebrew/bin/python3.13 /Users/ron/.hermes/workspace/scripts/pipeline/twitter_collector.py --sync-following
주의: 6시간마다 Telegram 발송은 스팸 가능성이 있어 cron command에서는 --notify를 뺐다. 수동 발송이 필요할 때만 --notify를 붙이면 된다.
기존 보조 job 처리:
id: fundamental-twitter-collector
enabled: False
state: paused
reason: superseded by ocTC-twitter-collector
schedule: 20 6 * * * Asia/Seoul
command 보정: ... /opt/homebrew/bin/python3.13 ... twitter_collector.py --sync-following --limit 0
중복 부하를 피하기 위해 보조 job은 정지하고, 6시간 간격 primary job(ocTC-twitter-collector)만 활성 상태로 유지했다.
Gateway 상태:
- lsof: 127.0.0.1:18789 LISTEN, PID 20146
- curl http://127.0.0.1:18789/v1/health: {"status":"ok","platform":"hermes-agent"}
- hermes gateway status: launchd service loaded, PID 20146
- hermes cron status는 Codex sandbox의 ps 제한 때문에 “Gateway is not running”을 표시했으나, 실제 port/health/launchd 기준으로는 gateway가 살아 있다.
5. analyst wrapper 연동
수정 파일:
- /Users/ron/.hermes/workspace/scripts/knowledge_context_builder.py
- /Users/ron/.hermes/workspace/scripts/fundamental_context_filter.py
- /Users/ron/.hermes/workspace/scripts/technical_context_filter.py
- /Users/ron/.hermes/workspace/scripts/analyst_runner.sh
반영 내용:
- knowledge_context_builder.py
- Twitter source root에 ~/.hermes/workspace/memory/twitter-collector/reports 추가.
- macro/fundamental/technical 각각 Twitter source limit 활성화.
- macro는 기존 룰대로 z-score/MA/편차/모멘텀/차트류는 감점·제거.
- fundamental_context_filter.py
- twitter-collector/reports를 직접 읽도록 추가.
- technical_context_filter.py
- twitter_collector 최신 리포트를 twitter_context 후보로 사용.
- analyst_runner.sh
- technical analyst 실행 때 technical_context_filter.py --write-latest 결과를 prompt에 주입.
검증:
/opt/homebrew/bin/python3.13 -m py_compile \
twitter_collector.py \
knowledge_context_builder.py \
fundamental_context_filter.py \
technical_context_filter.py
OK
bash -n analyst_runner.sh
OK
wrapper 실측:
fund twitter_count 1
fund first /Users/ron/.hermes/workspace/memory/twitter-collector/reports/report-2026-04-16-1011.md
tech twitter_context ['twitter_collector: 소형 AI 모델은 추론 비용은 낮지만, 데이터 수집, 실패 진단, 평가 시스템 구축 등 적응 과정이 비싼 과제로 지적된다...', ...]
builder_has_twitter True
macro_builder_has_twitter True
6. 남은 리스크
- X가 다시 authenticated timeline에
X-Client-Transaction-Id를 강제하면 no-op transaction fallback도 막힐 수 있다. - cookie cache는 브라우저 세션 기반이라 만료 가능. 만료 시 Chrome 로그인 또는 cache 재추출 필요.
- Playwright/Scrapling fallback은 현재 Codex/launch 환경에서 MachPort EPERM에 취약하므로 1차 fallback으로 믿으면 안 된다.
- 146개 계정 전체 수집은 시간이 걸리므로 timeout을 2400초로 늘렸다. 다만 X rate-limit가 걸리면 계정 수 제한 또는 batch splitting이 필요하다.
fundamental-twitter-collector는 중복 부하 방지를 위해 paused 상태다. 필요하면 06:20 사전 수집용으로 다시 켤 수 있지만, 현재 primary는ocTC-twitter-collector하나다.
자체평가
- 정확성: 4.7/5 — 실제 수집/DB/report/wrapper 검증 완료.
- 완성도: 4.6/5 — cron 등록과 wrapper 연동까지 완료. 다만 다음 12:10 정기 실행은 아직 미래라 실제 scheduled fire는 미확인.
- 검증: 4.6/5 — Python 3.13 +
/usr/bin/python3둘 다 수동 수집 성공, compile/shell syntax/context 검증 완료. - 최소 변경: 4.5/5 — collector fallback과 wrapper source mapping 중심 변경. 기존 shared LLM 경로는 건드리지 않음.
종합: 4.6/5