2026-06-14
날짜는 UTC 기준으로 나눴습니다(9월 22일부터는 한국 시간 기준). 커밋은 커미터 시각(committer date), PR은 생성·병합 시각으로 분류했습니다. 목록은 2026-10-06 KST에 GitHub에서 다시 조회해 보강했습니다. 공개 저장소의 기본 브랜치 활동만 포함합니다.
요약 (AI 작성)
maru는 ⌘N 새 창을 위한 세션 컬렉션 정리와 창 팩토리(#396, #397)로 멀티 창을 열고, 한 창을 닫을 때 나던 over-release 크래시를 고쳤습니다. 이어 maru.workspace.v1 직렬화 writer·reader(#399), 라이브 세션 캡처, 정상 종료 시 저장, 시작 시 여러 창을 되살리는 복원(#404), 민감 데이터 가드와 없는 cwd 처리(#405)까지 워크스페이스 복원 R1–R6을 마쳤고, 리뷰에서 나온 stale 포인터·손상 트리 처리 등을 바로잡았습니다. 오후부터는 레이어링·이식성 전략과 chrome 디자인 시스템 설계를 문서로 정한 뒤, src/chrome 타입 계약과 Notice 모달(#409, #411), 세션 구조 무효화 계약과 순수 입력·IME 로직의 src/session 추출(#412), 레이어 import 방향을 검사하는 경계 테스트(#418)를 넣었습니다. 스크롤백 찾기와 커맨드 팝업을 chrome 컴포넌트로 옮기면서(#420, #427) 오버레이 입력 커서와 IME 조합 표시, caret 깜빡임을 붙였고, 한글이 잘리던 문제를 EAW 셀 폭, 오버레이 폰트 실측, atlas 캐시 키의 셀 폭 포함으로 차례로 고쳤습니다. 오버레이 글자 1.3배 확대는 넣었다 되돌리고 다시 넣은 끝에 터미널과 같은 크기로 돌아갔고, chrome의 config import 금지 가드도 추가했다가 되돌렸습니다(#438, #439). 마지막으로 divider, sidebar, tabbar의 마우스 hit-test를 chrome 컴포넌트로 옮겼습니다(#440, #441, #443).
zntc는 전날 열린 진단 게이트 #4264를 병합하고 ES2025 정규식 (?s:…), (?i:…), (?m:…) modifier 다운레벨(#4265부터 #4267까지)을 완성했습니다. 이후 70개 가까운 커밋으로 저장소 전반의 결함을 정리했는데, 번들러의 ModuleKey 스택 버퍼 오버플로와 minify·bundler의 UAF, napi 오류 경로의 자원 누수, dev 서버 WS writer 데이터 경합과 프록시 바디 미전달, generator 라벨 continue와 for-in 의미 위반, v 플래그 집합 연산을 합집합으로 바꾸던 정규식 문제(#4308), mangler가 eval을 이름으로 배정하던 문제(#4313), lexer의 BOM·UTF-8 검증, sourcemap VLQ의 정수 오버플로, React Native open-url 입력 검증, CLI 플래그와 BuildOptions 스키마 불일치(#4310) 등이 포함됐습니다. 성능 쪽에서는 기본 worker 풀을 8개로 제한하고(#4359), 의존 export 요청과 top-level 이름 순회를 O(N²)에서 O(N)으로 줄였습니다(#4406, #4407). 같은 주제의 #4300, #4336은 병합되지 않고 닫혔습니다.
cheolsu-proxy는 의존성 전체 버전업(#340) 뒤 심각도별로 버그를 정리했습니다. 백엔드 패닉·요청 무결성·압축 폭탄, 인증서 SAN 불일치와 mTLS fail-open 보안 문제(#342), 스크립팅 엔진의 무한 루프·메모리 폭주 방어, throttle 프리셋 유실, 프론트엔드 이미지 손상과 규칙 페이지 크래시를 High로 고쳤고, 데이터 모델·ops·daemon·proxyapi·프론트엔드의 Medium·Low 항목(#346부터 #361까지)과 리뷰 후속 하드닝이 이어졌습니다. MCP 도구 48개, CLI, 스크립팅·SSE, 설치 문서를 실제 구현과 맞추고 테스트 가이드를 쓴 뒤 v0.1.2 릴리스 커밋(#374)을 넣었고, 릴리스 빌드 실패를 일으킨 미사용 필드를 지웠습니다(#375).
suji는 Node 24 type stripping으로 main.ts 진입점을 지원하고, macOS 전용이던 네이티브 기능 4종을 Windows·Linux로 넓혔으며(#142), Electron 백로그 메서드 9종(#143), 권한 핸들러의 카메라·마이크 통합(#144), app.getFileIcon·app.relaunch()(#146, #147)를 추가했습니다. Android에 libnode NDK 크로스빌드와 내장 Node.js 백엔드 예제를 넣었고(#145), Windows 내장 CPython을 dev와 패키지 양쪽에서 지원하며 CI e2e 가드를 달았습니다(#150, #151). Rust·Go SDK의 autoUpdater(#155), Windows 업로드 경로 unescape(#156)도 들어왔습니다. iris는 Android 벤치마크 비교 측정 경로(#38)와 엔진 호환성 정책 갱신(#39)을 병합했습니다.
블로그 저장소(ohah.github.io)에는 이날의 오늘의 커밋 요약을 올린 커밋 1개가 있었습니다.
공개 커밋 191개, 해당일 생성 또는 병합된 PR 181개를 정리했습니다. PR 생성 180개·병합 179개는 같은 PR이 양쪽에 포함될 수 있습니다.
커밋
ohah/cheolsu-proxy
- fix(mcp): 사용되지 않는 tool_router 필드 제거 (릴리스 빌드 실패 수정)
- chore: release v0.1.2
- style(docs): oxfmt 마크다운 테이블 정규화
- docs(testing): 테스트 가이드 본문 작성 (스텁 대체)
- docs: 고아 TLS 노트 제거 및 테스트 가이드 작성
- docs(install): 설치 가이드를 실제 빌드/아티팩트와 동기화
- docs(scripting/sse): 스크립팅·SSE 문서를 실제 API와 동기화
- docs(cli): CLI 문서를 실제 clap 정의와 동기화
- docs(mcp): MCP 도구 문서를 실제 구현(48개)과 동기화
- fix(query-filter): 필터 값의 큰따옴표를 escape해 round-trip 보존
- fix(websocket): 메시지에 표시용 URL을 실어 UUID 노출 회귀 수정
- fix(system_proxy): 이전 프록시 복원을 활성화 당시 서비스로 한정
- fix(script_bridge): 스크립트 바디 교체 시 stale content-length/encoding 헤더 제거
- fix(scripting): 코드리뷰 발견 스크립트/규칙 하드닝 4건
- fix(proxy): 평문 GET-over-CONNECT ClientHello 읽기 무한 블록 회귀 수정
- fix: get_learned_tls_strategies가 항상 빈 배열 반환하던 문제 (L16)
- fix: WebSocket conn_id를 URI 대신 연결별 고유 ID로 변경 (L2)
- fix: load_script 디렉터리 경계 추가 (홈 디렉터리 화이트리스트, L12)
- fix: multipart 바이너리 파트 size 부정확 — 바이트 단위 파서로 재작성 (FE-L1)
- fix: 프론트엔드 Low 버그 3건 (분석 count/N+1 오탐/GraphQL 탭)
- fix: src-tauri Low 버그 2건 (로그 경로 탐색, advanced_repeat 지연 순서)
- fix: load_session extend가 MAX 상한을 우회하던 문제 (L14)
- fix: ScriptHandle::shutdown이 멈춘 엔진에서 무한 블로킹되던 문제 (L11)
- fix: proxy_daemon Low 버그 6건 (블로킹IO/누수/WS/gRPC)
- fix: proxyapi_v2 Low 버그 3건 (ClientHello read/eager abort/메트릭)
- fix: 프론트엔드 Medium 버그 8건 (cURL/취소가드/누수/필터/동기화/Waterfall)
- fix: start_proxy_v2 동시 호출 시 DaemonConnection 누수 방지 (M14)
- fix: proxyapi_v2 Medium 버그 2건 (Upstream CONNECT over-read, IPv6 SOCKS5)
- fix: proxy_daemon Medium 버그 5건 (curl/SSE/브레이크포인트/시스템프록시/분석)
- fix: ops Medium 버그 3건 (SSE UTF-8 패닉, ID 충돌, 세션 규칙 동기화)
- fix: 데이터 모델 Medium 버그 3건 (UTF-8 패닉/손상, HAR Set-Cookie)
- fix: 프론트엔드 High 버그 2건 수정 (이미지 손상/규칙 페이지 크래시)
- fix: throttle 프리셋(gprs/3g/lte/wifi)이 프록시 재시작 시 유실되던 문제 수정
- fix: 스크립팅 엔진 안정성 (무한 루프/메모리 폭주 시 데몬 보호)
- fix: 백엔드 High 보안 버그 2건 수정 (인증서 SAN 불일치, mTLS fail-open)
- fix: 백엔드 High 버그 4건 수정 (패닉/요청 무결성/압축 폭탄)
- chore: 의존성 전체 버전업 (deno_core/v8/oxc, rmcp, tauri 등)
ohah/iris
ohah/maru
- test(chrome): C3b 리뷰 반영 — tabbar/barMetrics 커버리지 + dividerAtPoint borrow 주석
- feat(chrome): tabbar hit-test를 chrome 컴포넌트로 이주 (C3b — 마지막 hit-test 컴포넌트)
- refactor(chrome): C3a 리뷰 반영 — props seam·dividerAtPoint 단순화·sidebar 일관성
- feat(chrome): sidebar를 chrome 컴포넌트로 이주 (C3a — 마우스 hit-test 패턴 확장)
- feat(chrome): divider를 chrome 컴포넌트로 이주 (C2 — 마우스 hit-test 첫 선례)
- Revert "test(boundary): chrome 레이어가 config를 import하지 못하게 가드 추가"
- test(boundary): chrome 레이어가 config를 import하지 못하게 가드 추가
- refactor(chrome): find·palette 입력 오버레이 중복을 overlay_input 공유 모듈로
- fix(platform): 오버레이 배타·notice IME 라우팅·오버레이 프레임 소유권 정정
- fix(chrome): 오버레이 IME 조합 중 커서가 조합 글자를 덮도록 — 터미널과 일치
- refactor(app): IME 입력 라우팅을 단일 출처(inputFocus)로 — 조합 상태 안 보이던 버그 수정
- fix(app): 오버레이 wide 글리프 continuation 칸 배경이 글리프 오른쪽을 덮던 버그 — 한글 ㄱ 잘림 수정
- fix(renderer): atlas 캐시 키에 span(cell_width) 포함 — 한글 ㄱ 잘림(공유 atlas) 수정
- fix(app): 오버레이 caret이 안 보이던 버그 — cursor를 overlays에 넣어야 그려진다
- refactor(app): 오버레이 1.3× 확대 제거 — 터미널과 같은 셀 크기(1×)로 그린다
- feat(chrome): 오버레이 caret 깜빡임 — 터미널 커서 메커니즘 재활용(PaneFrame.cursor + suffix-trim)
- fix(app): 오버레이 cell을 오버레이 font의 CoreText 실측으로 — 한글 약간 잘림 수정
- feat(chrome): C1b — 커맨드 팝업을 chrome 컴포넌트로 이주(레거시 완전 제거)
- fix(app): 커맨드 팝업 텍스트도 EAW 폭으로 — 한글 ㄱㄴㄷ 잘림 수정 + find 실측 회귀 테스트
- fix(chrome): 오버레이 텍스트·caret을 EAW 셀 폭으로 — 한글 잘림 수정
- fix(chrome): 오버레이 1.3× 확대 재수정 — 폰트 크기까지 함께 스케일(루트커즈)
- Revert "feat(chrome): 오버레이 글자 1.3× 확대 — 가독성(실사용 피드백)"
- feat(chrome): 오버레이 글자 1.3× 확대 — 가독성(실사용 피드백)
- feat(chrome): find 오버레이 입력 UX — 입력 커서 + IME 조합(preedit) 표시
- feat(chrome): C1a — 스크롤백 Find를 chrome 컴포넌트로 이주
- refactor(platform): C1-prep — 일반 오버레이 ChromeDraw→cells rasterizer
- test(boundary): B 중립성 가드 — L1~L3 import-방향 완성 + OS-타입 by-name 금지
- fix(session): /code-review max 수정 3/3 — S1 표적 divider + per-window 알림 + 경계 doc
- fix(chrome): /code-review max 수정 2/3 — 오버레이 frame dedup + Notice 테두리 렌더링
- fix(chrome): /code-review max 수정 1/3 — 모달 correctness·정책·토큰 seam
- refactor(session): S2 슬라이스 2 — IME 순수 판정을 src/session/ime(L2)으로 추출
- refactor(session): S2 슬라이스 1 — 순수 입력/재정렬 수학을 src/session(L2)으로 추출
- refactor(session): S1 구조-무효화 계약 — destroyPane chokepoint로 라이브-트리 포인터 표적 무효화
- feat(chrome): C0 Notice 모달 wiring — ChromeDraw→CoreText lower + ABI show_notice + 손상 알림
- fix(chrome): 계획-기반 토큰/필드는 유지 — slot_height·chrome_minimal 복원
- fix(chrome): C0 /code-review max 수정 — 모달 박스 clamp + 미사용 토큰/필드 제거
- feat(chrome): C0 타입 계약 — src/chrome 스켈레톤 + Notice 컴포넌트
- docs: 레이어링·이식성 전략 + 적대적 검증 반영(chrome·renderer 정렬)
- docs(chrome): chrome 디자인 시스템 구조 설계 1차
- docs(pr-checklist): PR Mermaid 다이어그램은 가능하면 세로(좁고 긴)로
- fix(workspace): 통합 /code-review max 후속 — 루트코즈 수정 (ABI 39)
- fix(workspace): parse 구조 불변식(손상 트리 graceful) + 헤더 단일 출처(ABI)
- fix(workspace): restore 리뷰 수정 7건 — stale 포인터·cwd 디렉터리 검사·OOM 누수 외
- feat(workspace): restore R6 — 민감 데이터 가드 + 없는 cwd graceful
- feat(workspace): restore R4b — 시작 시 로드 + 멀티 창 복원 (ABI 38, end-to-end)
- feat(workspace): restore R4a — applyWorkspaceWindow (모델 → 라이브 트리 재생성)
- feat(workspace): restore R5 — 정상 종료 시 멀티 창 workspace 저장 (ABI 37)
- feat(workspace): restore R3 — 라이브 DevSession → workspace.Window 캡처
- feat(workspace): restore R2 — maru.workspace.v1 reader + round-trip
- feat(workspace): restore R1 — maru.workspace.v1 직렬화 writer + 모델
- fix(app): 멀티 창에서 한 창 닫을 때 over-release 크래시(isReleasedWhenClosed)
- feat(app): New Window W2 — ⌘N으로 새 창(팩토리 + per-window tick/lifecycle)
- feat(app): New Window W1 — 세션 컬렉션 seam (primary → windows, 동작 불변)
ohah/ohah.github.io
ohah/suji
- feat(sdk): add Request.stringUnescaped() + fix latent JSON-unescape path bugs
- fix(upload): Windows "forbidden path" — unescape filePath to match allowlist
- feat(sdk): add autoUpdater to Rust + Go SDKs (parity with JS/Node)
- docs(cef-refactor): reconcile status table with current modules
- refactor(cef): split cef_single_instance into state + platform submodules
- fix(test): repair python unit tests broken by version-constant refactor
- ci(windows): add Python staging + dev/packaged embedded-CPython e2e guards
- feat(python): complete packaged Windows python — stage stdlib (Lib/+DLLs/) bundle
- feat(python): Windows embedded CPython support (dev) + version single-source consts
- fix(review): Rust permission clear listener 누수 + getFileIcon rep autorelease
- fix(win): relaunchSelf Windows build break + run-cef-ipc -Dlua (post-merge Windows verify)
- feat(app): app.relaunch() — quit 후 재시작 (Electron parity)
- feat(app): app.getFileIcon — 파일 시스템 아이콘 PNG (Electron parity)
- fix(ci): android libnode — host toolset 을 native gcc (V8 host build android 누출)
- fix(ci): android libnode — android-configure 는 python(source 금지) + --shared sed 주입
- feat(mobile): android — embedded Node.js 백엔드 예제 + libnode NDK 크로스빌드
- feat(session): setPermissionRequestHandler 에 camera/mic(media-access) 통합 — 코어 + 전 SDK
- test(e2e): PR2 parity 메서드 e2e 검증 + suji-js dist 재빌드
- feat(parity): Electron 백로그 메서드 9종 — 코어 + 전 SDK(JS/Node/Rust/Go)
- feat(platform): macOS-only 네이티브 기능 4종 → Windows/Linux 확장
- feat(backend/node): support main.ts entry via Node 24 type-stripping
ohah/zntc
- perf(linker): forEachTopLevelOwnerName O(N²)→O(N) — 대형 fan-out local_name 인덱스
- perf(graph): requestDependencyExports O(N²)→O(N) — record→bindings CSR 인덱스
- fix(semantic): addUnresolvedReference OOM 삼킴 표면화 (#40 sweep)
- fix(transformer): 잔여 template data.none==0 alias 사이트 5곳 (#47 sweep)
- fix(semantic): analyzer OOM 을 조용히 삼키지 않고 alloc_failed 로 표면화
- fix(semantic): checkExportBinding 을 module-scope 조회로 한정
- fix(transformer): 치환 template expression 변환이 list.start==0 에서 누락
- fix(transformer): emotion interp label/sourceMap 재작성 결합 해제
- fix(transformer): buildRefreshSigCall 긴 signature 가짜 OOM 중단 제거
- fix(transformer): _s(Component, "sig") 가 mangler rename 따라가도록 symbol_id 전파
- fix(transformer): buildRefreshRegCall 긴 컴포넌트명에서 가짜 OOM 중단 제거
- fix(parser): tryReinterpretAsTypedArrow 의 죽은 is_empty_paren 분기 제거
- fix(parser): Flow conditional type span 이 check type 에서 잘려 false branch 미포함
- fix(parser): import attribute 비-string value 가 진단 없이 silent 수용 (+ dead 조건 제거)
- fix(bundler): matchGlob brace 확장이 4096 초과 alternative 를 silent skip → 매치 누락
- fix(codegen): export-default 합성 placeholder 판별을 이름 prefix 추론 → linker flag
- fix(regexp): legacy octal escape 가 3 digit 초과 소비 → byte 범위 초과 + round-trip 깨짐
- fix(regexp): 빈 character class(negated full range) → never-match (?!) (not (?:))
- fix(codegen): import.meta.glob 객체가 minify_whitespace 무시 — whitespace 헬퍼 경유
- fix(core): loadEnv 가 경로를 문자열 연결로 만들어 Windows separator 혼합
- fix(parser): directive prologue 가 .none(stripped) 문 뒤 string literal 을 directive 로 오인
- fix(parser): parseImportDeclaration 의 도달 불가 dynamic-import 블록 제거 (dead + 잠재 divergence)
- fix(parser): containsLoneSurrogate 의 도달 불가 보조 loop 제거 (dead code)
- fix(core): serializeFunctionInfo 가 OOM 시 buf backing leak — errdefer 추가
- fix(config): tsconfig extends + 양쪽 paths 시 base paths 컨테이너 leak
- perf(bundler): 기본 worker 풀을 8 로 cap — 동일-dir openat vnode 경합 해소
- fix(bundler): buildEntrySet symlink arm 이 put 실패 시 entry.name leak
- fix(parser): generic-arrow speculation 실패 경로가 AST 노드 미복원 → orphan 잔존
- fix(bundler): buildPlaceholder 가 chunk index-hash 를 u32 절단 → placeholder 충돌 silent mislink
- fix(codegen): sourcemap encodeVLQ 가 i32 minInt 에서 overflow panic
- fix(transformer): worklet makeI32Literal 이 i32 minInt 에서 overflow panic
- fix(semantic): visitVariableDeclaration declarator 슬라이스 바운드 가드 누락 — OOB panic
- fix(lexer): decodeUtf8 continuation byte 미검증 → overlong/후속바이트 오소비
- fix(lexer): getLineColumn 이 BOM 영역 offset 에서 u32 underflow + OOB panic
- fix(server): dev proxy 가 POST/PUT 바디 미전달 + Host 무조건 :port
- fix(transformer): top-level-await wrap 이 styled-components css-prop 추출 decl 소실
- fix(transformer): generator for-in 이 Object.keys(own-only/shadow) snapshot → for-in 의미 위반
- fix(core): writeOutputFiles 가 모든 .map 을 outfile.map 으로 broad-match — 다중 map 충돌(잠재)
- fix(core): readFileOrThrowNotFound 가 workspace 부재도 'config file not found' 로 오안내
- fix(cli): bench worker 가 transpile 에러를 swallow → 무의미한 측정값 + 신호 없음
- fix(parser): break/continue 가 expectSemicolon 대신 eat(.semicolon) — ASI 종결 미강제
- fix(codegen): sourcemap addMapping dedup 이 name_index 무시 → 명명 매핑 소실
- fix(react-native): metro-resolve 가 빈 assetFiles 시 bare specifier 를 경로로 반환
- fix(vite-plugin): Vite 버전 게이트가 ESM require 실패 + parseInt 취약 → Vite 5 이중변환
- fix(core): transpile/tokenize 가 빈 소스('')를 거부 — 빈 파일은 유효 입력
- fix(server): resolveLazySeedPath 가 대문자 hex 청크 요청 404 — case-insensitive 비교
- fix(cli): --proxy https 대상 기본 포트 443 + 파싱 중복 제거
- fix(server): mime lookup 이 대문자 확장자(.JS/.PNG) 미매칭 → 잘못된 Content-Type
- fix(mangler): isReservedOrGlobal 에 strict 예약어 eval 추가 — base54 eval 배정 SyntaxError 방지
- fix(parser): decodeStringKey 가 비-ASCII import-attr 키 byte 누락 → 거짓 중복 에러
- fix(schema): #4223 CLI flag ↔ BuildOptions schema sync drift 4건 해소
- fix(regexp): collectClassSet 이 v-flag intersection/subtraction 을 union 으로 miscompile
- fix(rn): in-flight refreshBundle 완료가 새 staleness 마스킹 방지 — generation guard
- fix(bundler): dynamic import attributes specifier 미교체 회귀 — 닫는 quote 뒤 ',' 허용
- fix(server): WS 초기 write + 등록을 한 ws_clients.mutex 임계영역으로 — 공유 writer data race
- fix(server): watchLoop changed_set/paths 가 watcher event path alias — intake dupe
- fix(bundler): clearCanonicalNames 가 ns_export_cache 미무효화 — canonical_strings borrow UAF
- fix(bundler): dynamic import specifier 재작성이 substring first-match — opener 게이트 + walk
- fix(flow): 리터럴 타입이 binary/octal/exponential 숫자 누락 — isNumericLiteral() 일반화
- fix(core): 플러그인 filter g/y 플래그 stateful lastIndex — 파일 격번 skip
- fix(codegen): export default sequence 괄호 drop — emitExpr(.comma) 로 wrap
- fix(config): tsconfig target case-sensitive 매칭 — PascalCase 다운레벨 비활성화
- fix(core): identifyWorkspaceEntries 가 다중 inline 워크스페이스를 cwd-dedup 으로 누락
- fix(codegen): private mangler 가 생존 원본 이름과 충돌하는 generated 이름 할당
- fix(transformer): generator 라벨 continue 가 for-of/for-in/do-while 에서 잘못된 타겟 점프
- fix(transformer): ES2015 class 식 IIFE 재빌드가 _this alias 누락 — 재빌드 제거
- fix(napi): build/watch async 에러 경로 자원 누수 — full cleanup 통일
- fix(react-native): open-url 미검증 입력 — scheme allowlist + win32 non-shell opener
- fix(minify): simplifySequence raw-slice realloc UAF — iterateExtraList 전환
- fix(semantic): checkImportMutation member-target OOB panic 가드
- fix(bundler): makeModuleKeyBuf 스택 버퍼 오버플로 — ModuleKey heap-spill로 교체
- fix(transformer): ES2025
(?i:\[…\])비-ASCII class fold bail 시 중첩 class miscompile (#4210) - feat(transformer): ES2025 regex
(?m:…)multiline 앵커 다운레벨 — i/s/m 트리오 완성 (#4210) - feat(transformer): ES2025 regex
(?i:…)modifier ASCII non-u 다운레벨 + transform-driven 진단 (#4210) - feat(transformer): ES2025 regex
(?s:…)modifier 다운레벨 + effective-flag 컨텍스트 (#4210) - feat(compat): ES2025 regex inline modifier (?i:...) 미지원 타겟 진단 게이트 (#4210)
PR (해당일 생성/머지)
상태는 조회 시점 기준입니다. merged는 아래 대상 브랜치에 병합됐다는 뜻이며, 기능 브랜치 병합과 main 반영을 구분합니다. 같은 PR이 생성일과 병합일 양쪽 기록에 나타날 수 있습니다.