2026-09-21
날짜는 UTC 기준으로 나눴습니다(9월 22일부터는 한국 시간 기준). 커밋은 커미터 시각(committer date), PR은 생성·병합 시각으로 분류했습니다. 목록은 2026-10-06 KST에 GitHub에서 다시 조회해 보강했습니다. 공개 저장소의 기본 브랜치 활동만 포함합니다.
요약 (AI 작성)
@ohah/pdf가 0.2.0 커밋을 낸 날입니다. 글자 뽑기를 pdf.js 수준으로 올리고(조각 폭·틈 판정·합자·내장 인코딩), PDF를 LLM에 먹이는 Markdown으로 바꾸는 markdown()과 같은 규칙의 JSON인 blocks(), 워커 창구를 직접 쓰는 markdownOf(pages)를 넣었습니다. 한국어 실전 문서로 다듬어 docling과 맞댔고, 태그 PDF는 구조 나무를 따라가며 괘선 없는 표도 찾습니다. 무작위 27편(arXiv 22편, 한국 보고서 5편)에서 드러난 아홉을 고치고, 큰 암호 문서를 여는 데 56초 걸리던 것을 90ms로 줄이며 누운 글(arXiv 스탬프)을 거르게 했습니다. zntc도 v0.1.10 릴리스 커밋을 냈습니다(#4691). dev가 사라진 CSS import의 <link>를 지우고(#4686), 아직 없는 경로도 감시 목록에 남기며(#4688), 중첩된 dev 산출 디렉토리를 CSS 탐색·복사에서 제외했고(#4690), CSS 파이프라인 사전 패스의 비용 측정을 RFC에 적었습니다(#4689).
maru 편집기는 파일 없이 여는 편집기(U1, #3823)와 이름 없는 문서 저장(U2, #3827)을 얻었고, 저장이 실패하면 이유를 말하며 「연 뒤 바뀌었나」를 처음으로 묻게 했습니다(C0, #3839). LSP 2단은 foldingRange 접힘 3층(⑨, #3828), rustc 진단이 저장에만 다시 돌아 고친 오류가 남던 문제를 푸는 didSave 통지(⑩, #3833), ⇧F12 참조 피커(⑪, #3840)까지 갔습니다. #3833과 #3839가 각자 초록으로 병합되며 main이 컴파일되지 않던 것은 #3844로 고쳤고, 같은 목적의 #3843은 닫혔습니다. 구현·타입 정의·선언으로 이동하는 ⑫ #3846과 저장 충돌을 고르게 하고 네이티브 다시 읽기를 만드는 C1a #3847은 이날 PR이 열렸습니다. 비교 뷰에도 구문 색이 나고(#3819), 전날 열린 property·attribute 색 지정 #3818도 병합됐습니다.
에이전트 훅은 원격 Term의 턴 스냅샷과 ✎ 귀속을 저쪽 기계에서 세우고(AT3c, #3820), ✎의 근거를 로컬·원격으로 통일했으며(AT3d, #3826), 훅 커맨드 하나로 로컬/원격 설치기의 핑퐁을 없앴습니다(RA8, #3825). RA7은 훅 모드 상태를 HookSlot으로 뽑고, 원격 tmux pane별 훅 슬롯 테이블과 라우팅, 사이드바 pane 행까지 조각 넷을 병합했으며(#3838), 밀린 pane 고지를 넣는 조각 5 #3842는 이날 열렸습니다. 새 Maru.app에서 maru ssh와 loopback sshd를 거쳐 claude 한 턴을 도는 실기 e2e 도구와 결과도 문서로 남겼습니다(#3829).
build.zig는 등록을 바뀌는 이유별로 build/로 갈라 21,352줄에서 8,835줄로 줄였고(#3824), 빌드 등록을 문자열이 아니라 AST 뷰 build_graph로 세게 했습니다(#3831). tests/boundary/ 판정자 스무 개를 표로 모으는 #3845는 이날 열렸습니다. workspace는 잃은 게 없는데 저장을 막아 껐다 켤 때마다 배치가 사라지던 두 교착을 닫았습니다(#3830). hwpjs는 EMF fill 레코드와 레코드 wire 지원 분류, 페이지·클리핑·그래픽 속성 상태 추적, polyline·Bezier·cardinal spline과 Path 기하·closure 조립을 넣었고, HWP5가 EMF+ world·container transform을 replay합니다.
공개 커밋 116개, 해당일 생성 또는 병합된 PR 36개를 정리했습니다. PR 생성 35개·병합 30개는 같은 PR이 양쪽에 포함될 수 있습니다.
커밋
ohah/hwpjs
- feat(emf): materialize Path closures
- feat(emf): assemble Path geometry
- feat(emf): assemble cardinal spline spans
- feat(emf): assemble Bezier segments
- feat(emf): assemble polyline segments
- feat(emf): resolve relative point data
- feat(emf): track terminal server graphics
- feat(emf): track terminal server clips
- feat(emf): track graphics properties
- feat(emf): track clipping state
- feat(emf): replay page transforms
- feat(hwp5): replay EMF+ container transforms
- feat(hwp5): replay EMF+ world transforms
- feat(emf): track get dc interleaving
- feat(emf): classify record wire support
- docs(emf): update record coverage
- feat(emf): parse fill closed curve
- feat(emf): parse fill path
- feat(emf): parse fill region
- feat(emf): parse fill pie
- feat(emf): parse fill ellipse
ohah/maru
- fix(editor): didSave 판정자 다섯도 «bool 저장»을 쓰고 있었다
- fix(editor): 디버그 픽스처가 저장 오류를 버리고 있었다 — main 이 컴파일되지 않는다
- feat(editor): LSP 2단 ⑪ — 참조 피커: ⇧F12 가 textDocument/references 를 묻고 위치 전부를 팔레트 기반 피커(세 번째 소비자)에 행으로 세운다 — 현재 파일 먼저·중복 하나·상한 500·미리보기(root 안만)·root 밖 행은 알림; 하나면 바로 이동; 로드 중 content modified 는 400 ms 뒤 되묻기(최대 8); 보조 텍스트 꼬리 28칸·제목은 남는 폭 (§8.2l)
- test(editor): 하네스를 적대적으로 — 20초 장님 실패와 개행만 다른 저장 (회차 1·3)
- ci(editor): 저장 충돌 스모크를 CI 에 — 손으로만 도는 게이트는 안 돈다
- docs(editor): §3.9d 판정에 «헤드리스가 못 보는 두 조각» — 그리고 ABI 는 186
- test(editor): 저장 충돌을 실제 AppKit 프로세스에서 — 진짜 ⌘S 와 디스크 대조
- test(boundary): 저장 실패 문구 표가 둘인 «근거»를 못 박는다 (C0 적대적 5회차)
- fix(editor): 외부 변경 문구가 할 수 없는 일을 지시했다 (C0 적대적 4회차)
- fix(editor): 이름이 붙은 문서에 디스크 지문을 세운다 (C0 적대적 3회차)
- test(editor): 기존 판정자 넷의 기대를 정확한 이유로 (C0)
- test(boundary): C0 이 바꾼 실패 문구의 자리를 다시 센다
- feat(editor): 저장 실패의 이유를 올린다 + 「연 뒤 바뀌었나」를 처음으로 묻는다(C0)
- feat(editor): LSP 2단 ⑩ — 저장 통지 didSave: 디스크 쓰기에 성공한 뒤 밀린 didChange 를 먼저 보내고 didSave(includeText 면 저장한 본문)를 보낸다 — rust-analyzer 의 rustc 진단은 저장에만 다시 돌아, 고친 오류가 다시 열 때까지 남아 있었다 (§8.2k; §8.2a 「진단은 didChange 로 온다」 정정)
- test(app-session): IME preedit 판정자가 자식의 첫 줄이 도착한 뒤에 기준 셀을 잡는다 — CI 에서 세 PR 연속
expected 12622, found 77플레이크 - feat(agent-hooks): RA7 조각 4 — 사이드바에 원격 tmux pane 행, 클릭은 그 pane 의 세션을 최근 세션으로
- refactor(build): 뷰에 «역방향» 조회를 연다 — dependentsOf 가 없어 38건을 「안 매달렸다」고 읽었다
- refactor(build): 빌드 그래프 뷰가 «안 담은 것을 없다고 말하지» 않게 한다 — VarCalls 를 모든 receiver 에 만들고 dependenciesOf·countCall 을 연다
- feat(agent-hooks): RA7 조각 2·3 — 원격 tmux pane 별 훅 슬롯 테이블과 라우팅, Term 배지는 pane 중 하나라도 running 이면 running, 턴 끝·알림은 pane 마다
- docs: window-surface-mobility 의
Term좌표를 줄 없이 파일+심볼로 — HookSlot 삽입으로 정의가 59줄 내려갔다 (check-doc-line-refs) - refactor(agent-hooks): RA7 조각 1 — 훅 모드 상태를
session_model.HookSlot로 뽑고 Term 은 인라인 슬롯 하나를 든다,applyHookEventTo(term, slot, ev)(동작 불변) - fix(workspace): 잃은 게 없는데 저장을 막아, 껐다 켤 때마다 배치가 사라지던 두 교착
- fix(editor): 굴려서 caret 이 화면 밖에 나가도 상자가 돌아온다 (U2 적대적 20회차)
- test(editor): 팔레트·config 이름까지 실제로 닿는가 (U2 적대적 19회차)
- refactor(editor): base 의 원격 가드는 중복이었다 — 단일 출처를 가리킨다 (U2 적대적 18회차)
- test(editor): U3 가 설 전제를 못 박고 계획을 고친다 (U2 적대적 18회차)
- fix(editor): 쓰기 «뒤» 실패에 「저장하지 못했다」는 거짓이다 (U2 적대적 17회차)
- fix(editor): 저장 상자의 클릭-어웨이는 확정이 아니라 취소다 (U2 적대적 16회차)
- fix(editor): 대상이 사라진 덮어쓰기 확인이 안 접혔다 (U2 적대적 15회차)
- test(editor): 저장 뒤 밖으로 나가는 값 (U2 적대적 14회차)
- fix(editor): 저장 상한을 두 경로에 같게 — 만들 수 있는데 다시 저장 못 하는 문서 (U2 적대적 13회차)
- test(editor): 「이미 열림」의 범위는 창 하나 — 그 한계를 못 박는다 (U2 적대적 12회차)
- refactor(editor): 그 경로에 무엇이 있나 — 한 번 분류한다 (U2 적대적 11회차 보강)
- fix(editor): 폴더 이름에 대고 「덮어쓸까요?」를 묻지 않는다 (U2 적대적 11회차)
- fix(editor): 대상이 사라진 팝업 rename 이 안 접혔다 (U2 적대적 10회차)
- test(editor): 저장 물음은 이름 없는 문서에만 — 회귀 축 (U2 적대적 9회차)
- test(boundary): 저장의 허용된 자리를 센다 (U2 적대적 8회차)
- fix(chrome): 팝업 rename 이 세팅 화면 위에 남았다 (U2 적대적 7회차)
- fix(editor): NUL 이 든 이름을 거절한다 (U2 적대적 6회차)
- test(editor): 이름 상자를 실제로 세우고, 닫힌 문서를 잘못 집지 않는다 (U2 적대적 5회차)
- fix(editor): 저장의 checkpoint 축은 persisted_surface 다 (U2 적대적 4회차)
- test(editor): 도달 불가였던 실패 갈래를 주입해서 잰다 (U2 적대적 3회차)
- test(editor): 저장 수명·실패 섞기 판정자 (U2 적대적 3회차)
- fix(editor): 트리에서 연 네이티브 문서가 dirty 인데 확인 없이 닫혔다 (U2 적대적 2회차)
- test(editor): 배타 생성 축을 못 박는다 (U2 적대적 1회차)
- feat(editor): 이름 없는 문서를 저장한다 — 이름을 묻고 보통 문서가 된다(U2)
- refactor(build): 빌드 등록을 «문자열이 아니라 구조로» 센다 — AST 뷰 build_graph 와 첫 판정자 이관
- docs(agent-hooks): 실기 e2e 에 tmux 변형(pane 1 = 사용자 플로우 RA6 역조회, pane 2 = RA7 배치) — 둘 다 실기로 찍었다; RA7 재실측·조각화·착수 전 공격
- docs(agent-hooks): 에이전트 턴 축 실기 e2e —
tools/remote-scm/agent_turn_e2e.sh(새 Maru.app → maru ssh → 이 Mac 의 loopback sshd → claude 한 턴 → 에이전트 탭), 하네스 sshd 에 stock 과 같은AcceptEnv LC_*, AT3c·RA8·AT3d 실기 결과 기록 - test(agent-hooks): AT3d 적대적 3~5회차 — 도크 join 뮤턴트 5(E2 꼬리 일치 생존 → 루트 같은 이름 판정자), 규칙 불변식 property 2만 회 위반 0, 새 파일·삭제 파일 배지 판정자, NotebookEdit notebook_path 한계 기록
- test(agent-hooks): AT3d 적대적 2회차 — platform 격상 경로 뮤턴트(D7~D9), «Edit 뒤 Read» 판정자로 D9 를 잡는다, 실데이터 재생: 같은 턴 Read 선행은 3.2%
- fix(agent-hooks): AT3d —
✎의 근거를 «편집 도구가 겨냥 ∧ 그 턴의 tree 목록» 으로 로컬·원격 통일한다, 되돌림은 Read 에서 뜬 before 가 있을 때만, 시간 창 폴백(AT3b-3)은 폐기 (§4.2·§8-1, 계획 AT3d) - test(editor): FLD 조용 시계 판정을 실제 경과로 잰다 — CI 러너에서 「240 ms 안에는 안 묻는다」가 창을 넘겨 빨갰다(제품은 맞게 물었다); 창은 글자 숫자·사건 시각은 판정자가 직접 재 시계 변이(B3·B7·B8·B11·B13)는 여전히 죽는다 (§8.2j 적대적 5회차)
- feat(editor): LSP 2단 ⑨ — foldingRange 접힘 3층: 서버가 ready 면 문서 전체를 묻고 응답이 구문 층 위에 서버 범위를 갈아 끼운다(use 묶음·문서 주석 묶음이 접힌다); 오류·null·빈 응답은 「아직 아니다」로 두 배 조용 시계로 되묻고, 승격은 3층이 먼저 왔으면 건너뛴다; 2·3층 갈아 끼우기를 한 자리로 모으며 들여쓰기 0 문서의 표식 배열 구멍을 메운다 (§8.2j)
- refactor(build): build.zig 21,352 → 8,835 — 등록을 «바뀌는 이유»별로 build/ 로 가르고, 판정자가 보는 「빌드 소스」를 한 곳이 소유하게 한다
- test(editor): 적대적 사용자 조작 순서 (적대적 10회차)
- test(editor): 빈 문서를 실제로 그려 본다 (적대적 9회차)
- feat(editor): 이름 발급 소진을 OOM 이라 부르지 않는다 + 배타 불변식 판정자 (적대적 8회차)
- test(editor): 컨트롤 플레인에도 이름 없는 문서가 그대로 나간다 (적대적 7회차)
- test(editor): 알려진 한계와 조합(IME) 축을 못 박는다 (적대적 6회차)
- test(editor): 창이 둘일 때 이름이 겹치지 않는다 (적대적 6회차)
- fix(build): 전역 sed 가 갈아먹은 남의 expect 숫자를 되돌린다
- docs+test(editor): 문서 동기 + 허용된 자리를 세는 경계 판정자 (적대적 5회차)
- test(editor): 이름 없는 문서의 수명·편집 경로 판정자 (적대적 4회차)
- feat(editor): 이름 없는 문서는 닫기 확인 문구가 다르다 (적대적 3회차)
- fix(workspace): 이름 없는 편집기 Term 을 셸로 저장하지 않는다 (적대적 2회차)
- test(editor): U1 전용 게이트 — 배선(U1)과 L2 규칙(UT)을 한 이름으로 돌린다
- feat(editor): New Editor Tab — 파일 없이 여는 편집기(U1)
- fix(agent-hooks): 설치기가
<home>/.cache부터 만든다 — HOME 규칙(RA8)에서는 XDG 디렉터리가 미리 있던 전제가 사라진다; 설치 판정자 넷을 같은 규칙으로 (CI test-provider-session-removal) - docs(agent-hooks): AT3c 계획의 오진을 정정한다 — 원격 훅 설치기는 다른 기기의 maru 가 아니라 ssh 대상 기계의 CLI 다 (RA8 재실측)
- feat(agent-hooks): RA8 — 훅 커맨드 하나로 로컬/원격 설치기의 핑퐁을 없앤다, 로그 디렉터리는 HOME 만으로, 원격 nonce 경로 탈출을 막는다 (§4.1, 계획 RA8)
- test(agent-hooks): AT3c 적대적 2회차 — 원격 wire 프레임이 봉인·스냅샷 요청까지 닿는 판정자, 실제 원격 로그 재생(opt-in), 배선 뮤턴트 3/3
- test(agent-hooks):
submitTurnFiles거절 판정자 셋에 원격 인자를 맞춘다 — CItest-macos-app-host-abi컴파일 (AT3c) - test(agent-hooks): 설치 판정자 둘을 «원격 세트 = 로컬 세트»(AT3c) 에 맞춘다 — scope 가 세트를 보는 사실은 그대로 지킨다
- feat(agent-hooks): AT3c — 원격 Term 의 턴 스냅샷·
✎귀속을 저쪽 기계에서 세운다, 원격 세트 = 로컬 세트, 턴 목록은 tree 가 있는 기계에서 읽는다 (§8-14, 계획 AT3c) - docs(editor): 이름 없는 문서 계약·계획 — 초안이 든 근거 넷이 코드와 반대였다
- feat(editor): 비교 뷰에도 구문 색을 낸다 — 계약은 있었고 구현이 반쪽이었다
- feat(syntax): property = ANSI 7(white) · attribute = ANSI 5(magenta) — LSP 2층이 낸 enumMember·member 구분이 화면에 나타나게 자리를 가른다 (§5.3 2026-09-21)
- docs(session-host): §12.6 — PartialFrame 의 «반응» 은 왜 아직 안 고쳤나, 미룬다면 어떤 기계로 도나
ohah/pdf
- chore: 0.2.0 — Markdown/JSON 변환·태그 PDF·괘선 없는 표
- feat: 태그 PDF 는 구조 나무를 따라 Markdown 으로, 괘선 없는 표도 찾는다
- fix: 두 단 골 폭 문턱을 글자 높이만큼으로 — 학술지의 좁은 골(12pt)을 찾는다
- fix: 무작위 27편(arXiv 22·한국 보고서 5)에서 드러난 것 아홉
- feat: blocks() — markdown() 과 같은 규칙의 JSON 꼴
- fix: 큰 암호 문서 여는 데 56초 → 90ms, 누운 글(arXiv 스탬프) 거르기
- feat: markdownOf(pages) — 워커 창구를 직접 쓰는 앱용
- feat: markdown() 을 한국어 실전 문서로 다듬고 docling 과 맞댄다
- feat: markdown() — PDF 를 LLM 먹이용 Markdown 으로
- feat: 글자 뽑기를 pdf.js 수준으로 — 조각 폭·틈 판정·합자·내장 인코딩
ohah/zntc
- chore: release v0.1.10
- fix(web): 중첩된 dev 산출 디렉토리를 CSS 탐색·복사에서 제외 (#4678)
- docs(rfc): CSS 파이프라인 사전 패스의 비용 측정 + D2a 선행 조건 재판정 (§11)
- fix(server): 아직 없는 경로도 감시 목록에 남긴다 (#4683)
- chore(web,server): 죽은 주입 경로 제거 + css-update href 타입 정정 (#4680, #4681)
- fix(web): dev 가 사라진 CSS import 의 <link> 를 지운다 (#4671)
PR (해당일 생성/머지)
상태는 조회 시점 기준입니다. merged는 아래 대상 브랜치에 병합됐다는 뜻이며, 기능 브랜치 병합과 main 반영을 구분합니다. 같은 PR이 생성일과 병합일 양쪽 기록에 나타날 수 있습니다.