2026-09-21
요약 (AI 작성)
@ohah/pdf v0.2.0 이 나갔습니다 — PDF → Markdown/JSON, LLM 에 먹이는 꼴로. pdf.markdown({ pages? }) 와 pdf.blocks({ pages? }) 가 제목 계층·문단(하이픈 잇기)·목록·코드·표·머리말/꼬리말을 뽑고, 태그 PDF 는 구조 나무를 따라가며 괘선 없는 표도 찾습니다. 글자 뽑기를 pdf.js 수준으로 올리고(조각 폭·틈 판정·합자·내장 인코딩), 한국어 실전 문서로 다듬어 docling 과 맞댔으며, 무작위 27편(arXiv 22·한국 보고서 5)에서 드러난 아홉을 고치고, 큰 암호 문서 여는 데 56초 걸리던 것을 90ms 로 줄이고 누운 글(arXiv 스탬프)을 거릅니다. zntc 도 v0.1.10 을 냈습니다 — dev 가 사라진 CSS import 의 <link> 를 지우고(#4671), 아직 없는 경로도 감시 목록에 남기고(#4683), 중첩된 dev 산출 디렉토리를 CSS 탐색·복사에서 제외하며(#4678), CSS 파이프라인 사전 패스의 비용 측정과 D2a 선행 조건 재판정을 RFC 에 적었습니다.
maru 편집기는 파일 없이 여는 편집기(U1)와 이름 없는 문서 저장(U2), 저장 실패 사유와 「연 뒤 바뀌었나」 질문(C0), 저장 충돌을 «고르게» 하는 것과 네이티브 다시 읽기(C1a)를 얻었고, LSP 2단은 foldingRange 접힘 3층(⑨), didSave 통지(⑩ — rustc 진단이 저장에만 다시 돌아 고친 오류가 남아 있었다), 참조 피커 ⇧F12(⑪), 구현·타입 정의·선언으로 이동(⑫, open)까지 갔습니다. 비교 뷰에도 구문 색이 납니다. 에이전트 훅은 원격 Term 의 턴 스냅샷·✎ 귀속을 저쪽 기계에서 세우고(AT3c), ✎ 의 근거를 로컬·원격으로 통일하고(AT3d), 훅 커맨드 하나로 로컬/원격 설치기의 핑퐁을 없애고(RA8), 원격 tmux pane 별 훅 슬롯 테이블·라우팅·사이드바 행·«+N pane 밀림» 고지까지 RA7 조각 다섯을 쌓았습니다. 실기 e2e(새 Maru.app → maru ssh → loopback sshd → claude 한 턴) 도구와 결과를 문서로 남겼습니다.
build.zig 는 21,352줄에서 8,835줄로 줄었습니다 — 등록을 «바뀌는 이유» 별로 build/ 로 가르고, 빌드 등록을 문자열이 아니라 AST 뷰 build_graph 로 세며, tests/boundary/ 판정자 스무 개를 표로 모았습니다. #3833 과 #3839 가 각자 초록으로 머지돼 main 이 컴파일되지 않던 것을 고쳤고, 잃은 게 없는데 저장을 막아 껐다 켤 때마다 배치가 사라지던 두 교착도 닫았습니다. hwpjs 는 EMF 레코드 wire 지원을 분류하고 polyline·Path 기하·closure·fill path/ellipse 를 조립하며, hwp5 가 EMF+ world transform 을 replay 합니다.
커밋
ohah/hwpjs
- feat(emf): classify record wire support
- feat(emf): parse fill closed curve
- docs(emf): update record coverage
- feat(emf): resolve relative point data
- feat(emf): assemble polyline segments
- feat(emf): assemble cardinal spline spans
- feat(emf): parse fill path
- feat(emf): parse fill region
- feat(emf): assemble Path geometry
- feat(emf): assemble Bezier segments
- feat(emf): materialize Path closures
- feat(emf): parse fill pie
- feat(emf): parse fill ellipse
- feat(emf): track terminal server clips
- feat(emf): track terminal server graphics
- feat(emf): track get dc interleaving
- feat(hwp5): replay EMF+ world transforms
- feat(hwp5): replay EMF+ container transforms
- feat(emf): replay page transforms
- feat(emf): track clipping state
- feat(emf): track graphics properties
ohah/maru
- 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)
- 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 의 «반응» 은 왜 아직 안 고쳤나, 미룬다면 어떤 기계로 도나
- 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) - 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)
- refactor(build): build.zig 21,352 → 8,835 — 등록을 «바뀌는 이유»별로 build/ 로 가르고, 판정자가 보는 「빌드 소스」를 한 곳이 소유하게 한다
- fix(workspace): 잃은 게 없는데 저장을 막아, 껐다 켤 때마다 배치가 사라지던 두 교착
- docs: window-surface-mobility 의
Term좌표를 줄 없이 파일+심볼로 — HookSlot 삽입으로 정의가 59줄 내려갔다 (check-doc-line-refs) - refactor(agent-hooks): RA7 조각 1 — 훅 모드 상태를
session_model.HookSlot로 뽑고 Term 은 인라인 슬롯 하나를 든다,applyHookEventTo(term, slot, ev)(동작 불변) - 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 실기 결과 기록 - 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)
- 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)
- 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) - docs(agent-hooks): 실기 e2e 에 tmux 변형(pane 1 = 사용자 플로우 RA6 역조회, pane 2 = RA7 배치) — 둘 다 실기로 찍었다; RA7 재실측·조각화·착수 전 공격
- refactor(build): 빌드 등록을 «문자열이 아니라 구조로» 센다 — AST 뷰 build_graph 와 첫 판정자 이관
- feat(agent-hooks): RA7 조각 2·3 — 원격 tmux pane 별 훅 슬롯 테이블과 라우팅, Term 배지는 pane 중 하나라도 running 이면 running, 턴 끝·알림은 pane 마다
- refactor(build): 뷰에 «역방향» 조회를 연다 — dependentsOf 가 없어 38건을 「안 매달렸다」고 읽었다
- refactor(build): 빌드 그래프 뷰가 «안 담은 것을 없다고 말하지» 않게 한다 — VarCalls 를 모든 receiver 에 만들고 dependenciesOf·countCall 을 연다
- feat(agent-hooks): RA7 조각 4 — 사이드바에 원격 tmux pane 행, 클릭은 그 pane 의 세션을 최근 세션으로
- test(app-session): IME preedit 판정자가 자식의 첫 줄이 도착한 뒤에 기준 셀을 잡는다 — CI 에서 세 PR 연속
expected 12622, found 77플레이크 - feat(editor): LSP 2단 ⑩ — 저장 통지 didSave: 디스크 쓰기에 성공한 뒤 밀린 didChange 를 먼저 보내고 didSave(includeText 면 저장한 본문)를 보낸다 — rust-analyzer 의 rustc 진단은 저장에만 다시 돌아, 고친 오류가 다시 열 때까지 남아 있었다 (§8.2k; §8.2a 「진단은 didChange 로 온다」 정정)
- 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단 ⑪ — 참조 피커: ⇧F12 가 textDocument/references 를 묻고 위치 전부를 팔레트 기반 피커(세 번째 소비자)에 행으로 세운다 — 현재 파일 먼저·중복 하나·상한 500·미리보기(root 안만)·root 밖 행은 알림; 하나면 바로 이동; 로드 중 content modified 는 400 ms 뒤 되묻기(최대 8); 보조 텍스트 꼬리 28칸·제목은 남는 폭 (§8.2l)
- fix(editor): didSave 판정자 다섯도 «bool 저장»을 쓰고 있었다
- fix(editor): 디버그 픽스처가 저장 오류를 버리고 있었다 — main 이 컴파일되지 않는다
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(web,server): 죽은 주입 경로 제거 + css-update href 타입 정정 (#4680, #4681)
- fix(server): 아직 없는 경로도 감시 목록에 남긴다 (#4683)
- fix(web): dev 가 사라진 CSS import 의 <link> 를 지운다 (#4671)
- chore: release v0.1.10
- docs(rfc): CSS 파이프라인 사전 패스의 비용 측정 + D2a 선행 조건 재판정 (§11)
- fix(web): 중첩된 dev 산출 디렉토리를 CSS 탐색·복사에서 제외 (#4678)