virtual-insanity
← 리포트 목록

JP모건 수집 경로 한계 진단 및 대체 목록 경로 제안서

2026-09-26 cowork [외사리서치, jpmorgan, 수집기, 커버리지, proposal]

[참고본] 정본은 /Users/ron/knowledge-agent/400-reports/260926_cowork_jpmorgan-discovery-alternative-proposal.md 이다. 이 문서는 선행 진단(실측 근거)으로만 유지한다. 아래 1순위 두 건은 2026-09-26 06:22(report_routing.py)·06:29(build_house_daily_digest.py _collection_window)에 이미 반영됐다.

JP모건 수집 경로 한계 진단 및 대체 목록 경로 제안서

조사 시각: 2026-09-26 05:20~05:50 KST · 방식: 실행 로그·색인 재집계 + 살아있는 JPM 세션(CDP 9236)에서 읽기 전용 조회(GET만, 저장·동의 클릭 없음) 대상 코드: hermes-research-sales-engine/scripts/collect_jpmorgan_archive.py(492행), report_routing.py, build_house_daily_digest.py

[권고]

한 줄 결론: "JPM이 9월에 안 보인다"는 한 가지 원인이 아니라 서로 다른 세 층이 겹친 것이다. ① 목록이 서버 고정 50건(요청 변수로 못 늘림) ② 그 50건 중 크레딧 데스크 글은 제목 규칙에 안 걸리면 빠짐 ③ JPM 주간물은 금·토 발행이라 토·일에만 저장되는데, 외사별일일은 평일에만 돌고 "그날 저장분"만 봐서 JPM이 구조적으로 0건이 된다. 제외 규칙이 주간물만 남긴 게 아니라 목록 자체가 주간물 위주이고, 외사별일일 0건은 목록과 무관한 날짜 창 문제다.

  • 1순위 — 외사별일일 날짜 창 보정 (codex, 목록 경로 문제와 무관하게 즉시 효과)
  • 무엇을: build_house_daily_digest.py main()의 409~410행 collected != target.isoformat() 조건을 "직전 평일 다음날 ~ target"(월요일이면 토·일·월 포함)으로 넓힌다. 새 도우미 함수 _collection_window(target) -> tuple[date, date] 1개 추가.
  • 왜: JPM 색인 46건의 최초 저장 요일이 토 22 / 일 13 / 금 5 / 목 5 / 월 1이고, 9월 JPM 저장일 5개(09-06 일, 09-12 토, 09-13 일, 09-19 토, 09-20 일)가 전부 주말이다. 외사별일일 크론(research-house-daily-0815, 15 8 * * 1-5)은 평일에만 돌아 이 5일치를 한 번도 못 본다.
  • 기대효과: 9월 JPM 외사별일일 0건 → 월요일마다 1건(4~5개 리포트 묶음). 9월(01~25) 기준 0/19 평일 → 3/19(09-07·14·21 월요일 3회 — 주말 저장분 11건 전부 흡수). 바클레이즈 등 평일 수집 외사는 변화 없음(창이 target 하루와 같음).
  • 1순위(병행) — JPM 라우팅의 간행물 메타 인정 (codex)
  • 무엇을: report_routing.py 402~411행 if source_key == "jpmorgan": 분기에 "publications에 Credit Market Outlook & Strategy·High Grade Weekly Spotlight·HG Credit Foreign Demand Monitor가 있거나 businessGroup == "Credit Research"이고 regions에 NorthAmerica/Global 포함이면 include/ig_market" 규칙 추가. 신규 상수 _JPMORGAN_CREDIT_PUBLICATIONS.
  • 왜: 오늘(09-26) 피드에 새로 뜬 An in-depth look at the question of 144A index inclusion(GPS-5456329-0, 09-25, Credit Research, 간행물=Credit Market Outlook & Strategy, 1.6조달러 HG 채권 지수편입 이슈)이 US IG·한국물·미국 금리/거시 연결이 확인되지 않음(536행)으로 제외됐다. JPM 분기는 제목 정규식만 보고(407행), 간행물 메타는 안 본다. 메타 조합에 따라 결과가 흔들리는 것도 확인(아래 현황 3) — 간행물명으로 확정하는 규칙이 필요한 이유.
  • 기대효과: 오늘 피드 기준 +1건, 크레딧 데스크 단발 리포트(연 수십 건 추정 — 미확인)가 노출되는 날 놓치지 않음.
  • 2순위 — 두 번째 목록 채널(섹션별 목록) 도입, 단 선행조건 1건은 해리 조치 필요
  • 무엇을: BofA 방식(SECTIONS 튜플 → 섹션마다 목록 조회 → 합쳐서 중복 제거)을 JPM에 이식. 후보 섹션은 메뉴 API에서 실측한 Research & Insights > Research > Global Research(JPMM_ID research), Asset Classes(research.asset_classes), My Research(research.my_research), Global Index Research(research.bond_index).
  • 선행조건(차단 요인): 이 네 화면을 새 탭으로 열면 모두 "Terms of Use — Research Application Addendum … By clicking Accept" 동의 화면에서 멈추고, 목록 호출이 한 번도 안 나간다(XHR은 메뉴·프로필·핑뿐). CFP 검색 경로(/research/CFP?page=search, page=publication)는 "Authentication Error Page … (user: hychoi280, page: search)"로 막힌다. 약관 동의는 법적 동의 행위라 에이전트가 누르지 않는다 → 해리가 JPM 세션에서 리서치 앱 약관을 1회 수락해야 섹션 목록 주소를 실측할 수 있다.
  • 동의 후 codex 작업: (a) 살아있는 세션에서 위 화면이 부르는 목록 주소·응답 형태를 먼저 실측(추측 구현 금지) (b) SECTIONS 상수 + _fetch_section_listing(session, budget, section) -> list[dict] 추가 (c) collect()에서 _fetch_feed() 결과와 합쳐 doc_id로 중복 제거, listing_channel에 섹션명 기록.
  • 기대효과: 크레딧 데스크 간행물(High Grade Weekly Spotlight 등)의 상시 노출. 08-27 단 1회 노출 때 5건이 전부 저장된 선례로 볼 때, 노출만 되면 필터·본문 경로는 이미 통과한다.
  • 2순위(병행, 선행조건 없음) — 기대 시리즈 감시
  • 무엇을: collect_jpmorgan_archive.py에 EXPECTED_SERIES(US Weekly Prospects, U.S. Fixed Income Markets Weekly, Global FI Markets Weekly, Credit Market Outlook & Strategy, The J.P. Morgan View) + _series_staleness(listing_rows) -> list[str] 추가. 최신 발행일이 9일 초과면 result["stale_series"]에 넣고 status="partial".
  • 왜: 지금은 목록이 안 움직여도 ok로 찍힌다(09-22→23→24 목록 id 차집합 0/0, 3일 연속 완전 동일).
  • 하지 말 것 — 50건 상한 조정: 상한은 우리 코드가 아니라 서버 쪽이다. &size=200/&limit=200/&pageSize=200/&page=2/&offset=50/&assetClass=FixedIncome/&publicationId=238 전부 같은 50건(첫 id GPS-5463860-0 동일)을 돌려줬고, type=credit|fixedincome|publications|news는 HTTP 500. 우리 쪽 상한(MAX_ARTICLE_OPENS=12, 50행)도 9월 내내 not_attempted_due_cap=0이라 병목이 아니다. 상한 숫자를 올리는 수정은 효과 0이다.

[현황]

1. discovery.jsonl 분포 (runs/2026092{2..5}/jpmorgan/)

실행일 목록 발행일 범위 include exclude fetch_status 버킷
09-22 50 08-07~09-21 23 27 duplicate 23 / excluded 27 other_review 27, macro_deep 19, ig_market 4
09-23 50 08-07~09-21 23 27 동일 동일
09-24 50 08-07~09-21 23 27 동일 동일
09-25 50 08-10~09-24 21 29 duplicate 21 / excluded 29 other_review 29, macro_deep 17, ig_market 4
  • 연속 실행 간 새 문서: 09-22→23 0건, 09-23→24 0건, 09-24→25 2건(Oil Markets Weekly 09-24, Flows & Liquidity 09-23 — 둘 다 제외 타당). 09-26 오늘 조회: 새 3건(Securitized Products Weekly, FX Markets Weekly, 144A 편입 분석).
  • 09-25 목록 50행은 서로 다른 제목 16개뿐: US Weekly Prospects 7, Equity Strategy 6, Flows & Liquidity 5, U.S. FI Markets Weekly 4, Credit Market Outlook & Strategy 4, Securitized Products Weekly 4, Oil Markets Weekly 3 … → 주간 연재물 묶음이라 6주치가 50칸에 들어간다.
  • 제외 29건 사유: 주식 전략 8, 연결 확인 안 됨 11(Flows & Liquidity 5·Oil 3·Perspectives 2·EM 1), 환율 5, 구조화 4, 비미국 1. 제목을 전부 대조한 결과 크레딧 데스크 글은 0건 — 제외 규칙이 크레딧을 막은 사례는 이 4일 안에는 없다. 즉 "주간물만 남는 것"은 목록 구조 때문이다(판정: 필터 제외 아님, 목록 미노출).
  • 43회 전체 실행 이력(08-13~09-25, 3,000행, listing_channel 100% home_research_feed)에서 크레딧 데스크 제목은 08-27 회차에만 1회 노출: High Grade Weekly Spotlight, HG Credit Foreign Demand Monitor, European Credit Weekly ×2, High Yield Weekly Spotlight, LATAM Corporates Daily, CNH Credit Markets. 같은 날 18:47 재조회 목록에선 이미 사라짐 → 피드가 계정 맞춤·회전형이라는 증거. 그 회차에 노출된 5건은 전부 html+pdf+txt로 저장됨(access_status=retrieved_html, 본문 45,073~51,770자).

2. archive_index.json (jpmorgan 46건) - 시리즈: 위 주간 5종 40건 + 08-27 단발 노출 5건 + EM Outlook 1건. - 최초 저장 요일: 토 22 / 일 13 / 금 5 / 목 5 / 월 1. 9월 저장 = 09-06(일) 2, 09-12(토) 1, 09-13(일) 3, 09-19(토) 1, 09-20(일) 4 = 11건, 전부 주말. - 대조: 바클레이즈는 같은 기간 저장일 09-21 2 / 22 5 / 23 4 / 24 4 / 25 5 (평일 매일), 발행일 09-21~24 일별 4~5건. 바클레이즈는 live.barcap.com/RSX/content-archive/v1/REST/publication/search를 상품군(Credit & Securitized 2594052, Macro 2594054)별로 pageSize=100, pubDateRange=2 weeks로 두 번 부른다 — 서버가 페이지 크기·기간을 받아주는 검색 API가 있다는 점이 JPM과의 결정적 차이다. - 볼트 외사 리서치/2026-09-*/00_외사별일일/: JPM 파일 0/19 평일, 바클레이즈 18/19. 반면 분류 폴더에는 JPM 노트 11개가 주말 날짜 폴더(09-06·12·13·19·20)에 정상 존재 → 원문은 들어왔는데 외사별일일만 비는 것.

3. 라우팅 재현(읽기 전용, 오늘 피드 원행으로 classify_report 호출) - 144A 글 실제 메타 전체 → exclude(regions를 US로 바꾸거나 비워도 exclude). 반면 최소 메타(assetClasses=FixedIncome, regions=US, businessGroup=Credit Research, 간행물명, 요약 빈칸)로 만들면 include(ig_market) → 판정이 요약·지역 등 메타 조합에 따라 흔들린다(단일 원인 필드는 미특정). JPM 분기(402~411행)는 제목 정규식(_JPMORGAN_FIXED_INCOME_INCLUDE)만 보고, 일반 경로의 _DIRECT_IG는 "HG bonds"/"US Agg" 표현을 못 잡는다. - 참고로 08-27에 저장된 HG Weekly Spotlight·HG Credit Foreign Demand Monitor는 현재 규칙에서도 include(ig_market, 최소 메타로 재현) → 노출만 되면 통과.

4. 대체 경로 탐색 결과(오늘 실측) - 홈 탭이 부르는 목록류 주소: mcp-home/api/search-service/saved-search·recent-search(둘 다 null), dp-gateway/omni-channel-api/public/dpweb/menu(151KB 메뉴 트리). 메뉴의 리서치 항목은 위 2순위 후보 4개 + FICC Market Structure & Liquidity(research.ficc_market_structure). - 리서치 앱 네 화면 모두 약관 동의 화면에서 정지 → 목록 호출 없음. 저장된 검색이 비어 있어 "My Research"에 구독을 걸어두면 개인화 목록으로 쓸 여지가 있으나 미확인(약관 수락 후 실측 필요).

[리스크]

  • 단일 장애점: JPM 목록은 FEED_URL(38행) 하나이고 서버가 50건·맞춤형으로 고정한다. 피드 구성(개인화 로직)이 바뀌면 주간 5종마저 사라질 수 있고, 지금 구조에선 그걸 ok로 보고한다(2순위 감시가 없는 한 조용한 누락).
  • 약관 수락 의존: 2순위 섹션 경로는 해리 계정의 리서치 앱 약관 수락 없이는 실측조차 불가. 수락 후에도 섹션 목록이 CFP 권한(docstring 11~13행의 "not onboarded onto CFP-RESEARCH")에 막힐 가능성 있음 — 현재 본문(CFP?page=article_page)은 열리지만 page=search/page=publication은 인증 오류, 즉 권한이 화면 종류별로 다르다.
  • 날짜 창 보정의 부작용: 월요일 외사별일일이 토·일·월 3일치를 묶으면 바클레이즈 등도 주말 저장분이 월요일에 합쳐진다(현재 주말 저장분은 어느 외사든 외사별일일에서 누락 중이므로 오히려 복구). 주간 크레딧 요약(build_weekly_credit_house_summary.py)은 target-6~target 날짜 폴더 파일을 읽으므로, 월요일 외사별일일 md가 생기면 JPM 재료가 늘어난다 — 중복 인용 여부는 검증 필요.
  • 라우팅 완화의 오탐: businessGroup=Credit Research만으로 include하면 European Credit Weekly, LATAM Corporates Daily, CNH Credit Markets(08-27 노출분)까지 들어온다. regions에 Europe/LatAm/Asia가 있으면 기존 지역 배제를 먼저 적용해야 한다.
  • 세션 부하: 섹션 추가 시 요청 수 증가. 현재 MAX_PORTAL_REQUESTS=90, 요청 간격 3초, 실제 사용 하루 1~9회라 여유는 충분.

[검증방법]

codex 구현 후 아래 기준으로 판정한다(모두 발송 없이 실행).

  1. 외사별일일 날짜 창 — cd hermes-research-sales-engine && python3 scripts/build_house_daily_digest.py --date 2026-09-21 --no-upload(발송 플래그 --send 금지)
  2. 기대값: 외사 리서치/2026-09-21/00_외사별일일/260921_jpmorgan_외사별일일.md 생성, "포함 리포트: 4건"(09-20 저장 4건) 이상. 바클레이즈 파일 건수는 변경 전과 동일하거나 주말분만큼 증가.
  3. 단위: _collection_window(date(2026,9,21)) → (2026-09-19, 2026-09-21), _collection_window(date(2026,9,23)) → (2026-09-23, 2026-09-23).
  4. 롤백 조건: 평일(화~금) 외사별일일 건수가 변경 전과 달라지면 되돌림.
  5. 라우팅 — python3 -c "from report_routing import classify_report; ..."로 GPS-5456329-0(144A, regions=NorthAmerica, publications=Credit Market Outlook & Strategy) → include/ig_market. 동시에 European Credit Weekly(regions=Europe) → exclude 유지, Securitized Products Weekly → exclude 유지.
  6. 회귀: 09-22~25 discovery.jsonl 200행을 새 규칙으로 재분류해 include 수 변화를 표로 제출. 기대: 증가 0~1건(크레딧 데스크 글이 그 4일 목록에 없었으므로), 감소 0건.
  7. 기대 시리즈 감시 — 09-22 목록으로 재현 시 stale_series=[], 목록에서 Credit Market Outlook & Strategy 행을 빼고 돌리면 stale_series=["Credit Market Outlook & Strategy"], status=partial.
  8. 섹션 채널(약관 수락 후) — python3 scripts/collect_jpmorgan_archive.py --max-reports 12 --max-opens 12 실행 결과에서 discovery.jsonl의 listing_channel 값이 2종 이상, 발견 수 > 50, 한 주 동안 High Grade Weekly Spotlight 또는 HG Credit Foreign Demand Monitor가 최소 1회 저장. 실패 기준: 섹션 목록이 인증 오류를 내면 status=partial + 홈 피드 결과는 그대로 저장(홈 피드 수집이 줄면 롤백).
  9. KPI(2주 관찰): JPM 평일 외사별일일 ≥ 주 1건, JPM 신규 저장 ≥ 주 5건 유지, 크레딧 데스크 간행물 ≥ 주 1건(섹션 채널 가동 후).

해리 확인 필요 1건

JPM 사이트 리서치 메뉴를 처음 열면 뜨는 약관 동의(Research Application Addendum) 를 해리 계정으로 한 번 수락해야 2순위 섹션 목록 경로를 실측할 수 있다. 에이전트가 대신 누르지 않았다(법적 동의 행위).

근거 경로

  • hermes-research-sales-engine/scripts/collect_jpmorgan_archive.py 11~13행(CFP 권한 메모), 38행(FEED_URL), 49~50행(상한), 199~215행(_fetch_feed), 323행(listing_channel="home_research_feed")
  • hermes-research-sales-engine/scripts/report_routing.py 138~146행(JPM 제목 정규식), 402~411행(JPM 분기), 536행(연결 미확인 제외)
  • hermes-research-sales-engine/scripts/build_house_daily_digest.py 409~410행(수집일=target 필터)
  • hermes-research-sales-engine/scripts/collect_bofa_portal_archive.py 24~28행(SECTIONS), 319행(섹션 반복)
  • hermes-research-sales-engine/scripts/collect_barclays_archive.py 191~206행(_search, pageSize 100), 215~217행(상품군 2개)
  • hermes-research-sales-engine/runs/2026092{2,3,4,5}/jpmorgan/discovery.jsonl·discovery-summary.json, runs/20260827/jpmorgan/listing-055724.untitled.json·listing-184740.json
  • hermes-research-sales-engine/data/archive_index.json(jpmorgan 46건)
  • /Users/ron/.hermes/cron/jobs.json — research-house-daily-0815(15 8 * * 1-5), c1dcf1d3c808 daily-broker-archive(45 5 * * *)