2026-08-06
요약 (AI 작성)
스크롤 컨테이너를 제대로 된 추상으로 만든 날입니다. ScrollView 설계를 문서로 세우고 이름부터 코드가 실제로 부르던 ScrollArea 로 맞춘 뒤, SV1a 로 스크롤 좌표계를 도크 밖 공용 자리로 옮기고, SV1b 로 스크롤 발행과 clip 을 tree.build 가 소유하게 했으며, SV1c 로 뷰포트 높이를 예측하는 대신 layout 에게 묻고 스크롤바 드래그 수명과 분수 휠 잔여까지 scroll_area.State 가 소유하도록 옮겼습니다. 각 단계마다 문서를 실제로 만들어진 구조에 맞춰 고쳐 썼고, 도크 build 버퍼 크기를 build 자신이 소유하게 하고 도크 props 를 한 함수로 모아 테스트가 같은 경로를 타게 했습니다.
이 리팩터를 받쳐 준 건 촘촘한 판정자들입니다. 예측한 뷰포트와 layout 이 만든 뷰포트가 같은지, 스크롤 좌표와 발행된 tree 가 실제로 맞는지, 텍스트가 나르는 clip rect 가 무엇인지, 재투영이 스냅샷 세대를 올리는지, 무변화 이동이 리페인트를 부르지 않는지를 각각 고정했고, 휠 스크롤 경로 전체와 스크롤바 드래그의 down·흡수·소비 계약, 키보드 스크롤과 anchor 경계, 상한 축소와 빈 목록이라는 무판정 구간까지 덮었습니다. 스크롤바를 실제로 보는 골든 게이트도 세우고, 그 골든이 무엇을 판정하고 무엇을 안 하는지 명시했습니다. 적대적 검증은 여러 라운드에 걸쳐 렌더 낡음·깜빡임, 기하 스탬프, lock 계약, 배치 실패 가드 같은 프레임 일관성 결함을 계속 찾아냈고 — 검증이 이번 수선 자체에서 만든 결함까지 포함해 — 라운드마다 고쳤습니다. "계약을 깨뜨려 확인할 때 틀리는 여섯 가지"를 문서로 남긴 것도 이 과정의 산물입니다.
그 위에서 기능 두 가지가 들어왔습니다. 도크 그룹 헤더를 스크롤 상단에 고정(sticky)하면서 sticky 가 자식 슬롯일 수 없는 이유와 emit 순서를 문서에 적었고, 하단 상태표시줄 자리를 dock_layout 에 내고(SB1-S1, 높이 0) 상태바가 사이드바 배경 strip 을 자를 수 있는 ABI 를 열었습니다(SB1-S2a·S2b). 아이콘 스택도 정리해 semantic 이름 registry 를 생성물로 만들고(IC1), 소비처를 codepoint 리터럴에서 이름으로 옮기고(IC2), 소비처 이름으로 등록하던 아이콘을 fit 축으로 흡수하고(IC3), 크기 값을 chrome 토큰으로 모았습니다(IC4). 여기서도 적대적 검증이 가드 구멍과 이름↔그림 사슬의 끊김을 라운드마다 찾아내 메웠고, 화면 배치 소유권 규칙(ML-GEO)을 문서로 세우면서 stale 서술을 함께 걷어냈습니다.
커밋
ohah/maru
- test(boundary): app_session 인벤토리 digest를 sticky 배선 뒤로 갱신한다
- feat(chrome): 도크 그룹 헤더를 스크롤 상단에 고정한다
- test(chrome): 상태바 seam의 손-미러 갭과 right 도크 계약을 막는다(적대적 검증)
- feat(chrome): 상태바가 사이드바 배경 strip을 자를 수 있게 ABI를 낸다 (SB1-S2a, 값 0)
- docs(chrome): sticky가 자식 슬롯일 수 없는 이유와 emit 순서를 적는다
- docs(chrome): clip 예외가 사라진 것을 문서 전체에 반영하고 경계 판정을 적는다
- feat(chrome): 하단 상태표시줄 자리를 dock_layout에 낸다 (SB1-S1, 높이 0)
- chore(chrome): SV1c로 바뀐 반사 인벤토리 digest를 갱신한다
- docs(chrome): SV1c 완료 상태를 모듈 헤더와 계획에 반영한다
- refactor(chrome): 분수 휠 잔여를 scroll_area.State가 소유하게 한다 (SV1c-3)
- refactor(chrome): 스크롤바 드래그 수명을 scroll_area가 소유하게 한다 (SV1c-2)
- refactor(chrome): 뷰포트 높이를 예측하지 말고 layout에게 묻는다 (SV1c-1)
- test(chrome): 배치 실패 신호의 진입 clear 계약을 못박는다(5라운드 적대적 검증)
- fix(chrome): 락 계약을 남은 두 호출부까지 완결한다(3라운드 적대적 검증)
- fix(chrome): 2라운드 적대적 검증이 찾은 술어 결함 둘을 고친다
- fix(chrome): 적대적 검증이 이번 수선 자체에서 찾은 결함 넷을 고친다
- fix(chrome): 렌더 프레임 일관성 결함 셋을 더 고친다 — 기하 스탬프·lock 계약·배치 실패 가드
- fix(chrome): 적대적 검증이 찾은 렌더 낡음·깜빡임 결함 셋을 고친다
- chore(chrome): 리네이밍으로 바뀐 반사 인벤토리 digest를 갱신한다
- docs(chrome): SV1b가 실제로 만든 구조로 §4와 계획을 고친다
- refactor(chrome): 스크롤 발행과 clip을 tree.build가 소유하게 한다 (SV1b)
- refactor(chrome): ScrollView를 ScrollArea로 고쳐 코드가 부르던 이름과 맞춘다
- docs(chrome): 도크 텍스트 clip 경로를 실측해 stale 서술을 고친다
- docs(chrome): 그룹 헤더 sticky 계약을 세운다
- docs(chrome): SV1b 전에 세워야 할 텍스트 clip 픽셀 게이트를 적는다
- chore(chrome): app_session 외부 반사 인벤토리 digest를 갱신한다
- test(chrome): 예측한 뷰포트와 layout이 만든 뷰포트가 같은지 본다
- docs(chrome): 계약을 깨뜨려 확인할 때 틀리는 여섯 가지를 적는다
- test(chrome): 키보드 스크롤과 anchor 경계 계약을 세운다
- test(chrome): 재투영이 스냅샷 세대를 올린다는 것을 고정한다
- test(chrome): 스크롤바 드래그의 down·흡수·소비 계약을 세운다
- test(chrome): 도크 휠 스크롤 경로 전체에 판정자를 세운다
- test(chrome): 텍스트가 나르는 clip rect를 판정한다
- refactor(chrome): 도크 build 버퍼 크기를 build 자신이 소유하게 한다
- refactor(chrome): 도크 props를 한 함수로 모으고 테스트가 그것을 태우게 한다
- test(chrome): 스크롤 좌표와 발행 tree를 실제로 대조한다
- test(chrome): 무변화 이동이 리페인트를 부르지 못하게 고정한다
- test(chrome): 상한 축소와 빈 목록이라는 두 무판정 구간을 닫는다
- test(chrome): 스크롤바 기하의 판정되지 않던 두 함수를 고정한다
- refactor(chrome): 스크롤 좌표계를 도크 밖 공용 자리로 옮긴다
- docs(chrome): ML-GEO에 SB1 구현자가 실제로 밟을 함정을 적는다
- docs(chrome): ML-GEO 재검증이 잡은 5건을 고친다
- docs(chrome): 2차 적대적 검증이 잡은 것을 고친다 — 내가 "고쳤다"고 한 것 포함
- docs(chrome): 화면 배치 소유권 규칙을 적고 아이콘 스택의 stale 서술을 고친다
- fix(icons): 적대적 검증 2·3라운드가 깬 것을 고친다 — 이름↔그림 사슬을 닫는다
- fix(icons): 적대적 검증 1라운드가 깬 가드 구멍을 메운다
- refactor(icons): 아이콘 크기 값을 chrome 토큰으로 모으고 .m도 이름으로 고르게 한다
- refactor(icons): 소비처 이름으로 등록하던 아이콘을 fit 축으로 흡수한다
- refactor(icons): 아이콘 소비처를 codepoint 리터럴에서 이름으로 옮긴다
- feat(icons): 아이콘 semantic 이름 registry를 생성물로 만든다
- test(chrome): 스크롤바 골든이 무엇을 판정하고 무엇을 안 하는지 적는다
- test(chrome): 스크롤바를 실제로 보는 골든 게이트를 세운다
- docs(chrome): ScrollView 스크롤 컨테이너 설계를 세운다