This release adds 3 notable features for engineering teams evaluating rollout.
✓ No known CVEs patched in this version
Topics
+12 more
Affected surfaces
Summary
AI summaryUpdates Migration Notes, M0-b, and M0-c across a mixed release.
Full changelog
[2.9.0] — 2026-05-14 — Substrate 3.0 — Phase 0 + M0
wmux의 substrate identity 를 v3.0 으로 끌고 가기 위한 첫 번째 ship unit. v2.8.x 에서 이미 ~50% 가 출하돼 있던 substrate 표면 (PaneMetadata, EventBus, bootId, asOfSeq, system.capabilities, MCP host, mcp.claimWorkspace) 위에 (a) 그 표면의 contract 를 명문화한 Phase 0 문서, (b) main process 측 metadata authority 인 MetadataStore 와 그 wire 통합 (M0-a~f), (c) v2.8.x dogfood 중 노출된 스크롤백 손상 + reconcile race + logSink durable write 안정성 픽스를 한꺼번에 ship. 메인 PR 은 #34 (Substrate 3.0 — Phase 0 + M0, v2.9.0 ship unit) 이고 후속 마이그레이션 도구는 #35 (chopped-dump recovery tool) 로 따라간다. 외부 RFC 협의는 #15 (@alphabeen) 에서 진행됐고 그 OCC + mergeMode 디자인이 코드로 착지.
업그레이드 영향:
- 와이어 contract 는 v2.x 와 backwards-compatible 이다 (
expectedVersion,mergeMode,pane.metadata.changed의version모두 additive optional). - 디스크에 새로 등장하는 폴더:
userData/wmux/scrollback/corrupted/와scrollback/*.txt.bak[.1..3]회전 슬롯. 둘 다 자동 관리. - v2.8.x 사용자가 첫 부팅 때 일부 패널 스크롤백이 비어 보일 수 있다 — 이미 디스크에 chopped 형태로 저장돼 있던 dump 가 v2.9.0 detector 에 의해 격리되기 때문. 데이터는 격리 폴더에 보존되며
scripts/recover-scrollback.mjs로 사람이 읽을 수 있는 텍스트로 복원 가능. 자세한 가이드는docs/upgrade-v2.9.0.md참조.
Added
- Substrate 3.0 contract documentation —
docs/PROTOCOL.md(substrate wire contract: layered status, namespacing, optimistic concurrency,mergeMode, cursor opaqueness, snapshot reconciliation, permission enforcement sketch, Named Pipe token security model),docs/api/{inventory,versioning,stability}.md(모든 RPC/MCP/event 의 stability tier + semver + 자동 업데이트 호환 정책),docs/internal/{m0-design,paneSlice-callsite-inventory}.md(M0 race specs + paneSlice 변경 blast-radius). MetadataStore모듈 (M0-a) — main process 의PaneMetadataauthority.get/set/clear/snapshot/hydrate/serialize/migrate/onPaneDeleted, per-pane monotonicversion,expectedVersion기반 OCC, 세 가지mergeMode(merge/replace/replaceShared). 31 unit test 가 CRUD + version + mergeMode 트랜잭션 + OCC + 검증 + snapshot + persistence + EventBus emission 을 cover, codex full-stack review 가 catch 한 3건 (replaceShared의 custom 보호, 누적 size cap,updatedAt추가 후 cap 적용) regression test 포함.pane.resolveActiveLeafIPC 채널 (M0-b) — caller 가paneId를 생략하면 main 이 renderer 에 active leaf id 를 query (read-only, paneSlice 쓰기 0) 한 뒤 MetadataStore 에 commit. codex P1 review 가 잡은 split-store read-after-write 구멍 닫힘.MetadataStore.snapshot()↔pane.list통합 (M0-c) —pane.listenvelope 가 store snapshot 으로 anchored,asOfSeq가 snapshot lineage 를 반영. renderer 가 더 이상 metadata 를 자체 합성하지 않음.SessionManager.saveMetadataSync와이어 (M0-e) — MetadataStore 의 persist callback 이metadata.json에 atomic write, launch 시 store 가 그 파일에서 hydrate. codex P2 review 가 잡은 strict field validation 포함.- Wire format 추가 (M0-f) —
pane.setMetadata가 optionalexpectedVersion+mergeMode, reply / event / list 가 optionalversion필드. v2.x subscriber 영향 없음 (모두 additive). - Optional
version필드 onpane.metadata.changedevents. - PR template with CHANGELOG + stability-tier sections.
atomicWriteText/atomicReadText(sync + async) —core.ts의 JSON 변종과 짝이 되는 텍스트 변종. rotation chain + quarantine 파이프라인 공유. JSON 변종이 parseable payload 를 전제하기 때문에 raw-bytes contract 가 필요한 스크롤백을 위해 sibling 으로 분리.- Cols-collapse corruption detector (
src/main/scrollback/corruption.ts) — chopped dump 의 on-disk 시그니처 (median 비공백 행 길이 ≤ 3자, CRLF 바이트 비율 ≥ 0.3) 휴리스틱 검출기. 단일 패스 스캔, allocation 최소. 15 unit test 가 production v2.8.4 fixture (median=1, max=60 까지 outlier 살아남은 chopped 파일) 와 false-positive 저항 (정상 출력, sparse 세션, narrow pane, ANSI-rich 로그, 단일 긴 줄) cover. scrollbackDumputil 모듈 (src/renderer/utils/scrollbackDump.ts) — renderer 의 dump serializer 를AppLayout.tsx에서 분리. eligibility 가드 (cols < 12 / rows ≤ 0 /terminal.element.offsetWidth === 0/ detached) 가 unit-testable. 13 test 가 각 가드 branch + happy path 를 pin.scripts/recover-scrollback.mjs(#35) — read-only 마이그레이션 CLI. v2.8.x → v2.9.0 첫 부팅에서corrupted/로 격리된 chopped dump 를 reverse-reflow 로 사람이 읽을 수 있는 텍스트로 복원.node:utilparseArgs기반, dry-run / verbose / 입출력 dir 오버라이드 지원. 19 unit test (detector parity + 순수 transform + processFile e2e + CLI plumbing). 출력은 별도 폴더로만 쓰고 격리 원본은 절대 수정하지 않음.docs/upgrade-v2.9.0.md(#35) — v2.8.x → v2.9.0 사용자 마이그레이션 가이드.corrupted/폴더의 의미, 첫 부팅 시 무엇을 보게 되는지, 복원 스크립트 사용법, 복원 한계, 롤백 절차, FAQ.
Changed
- README opening 이 LSP-for-terminals substrate 프레이밍 으로 시작 (AI agent 가치 제안과 tmux 대체 키워드는 보존).
pane.{set,get,clear}Metadata핸들러 (M0-b) 가MetadataStore로 라우팅. paneSlice 는 더 이상 RPC metadata path 에 의해 mutate 되지 않음.- paneSlice 가 mirror-only (M0-d) — 컴파일-타임 write protection 추가. M0-b 가 이미 모든 write path 를 우회시켜 M0-d 는 거의 no-op.
pane.listenvelope (M0-c) 가MetadataStore.snapshot()으로 anchored. snapshot lineage 를asOfSeq가 반영.SessionManager(M0-e) 가metadata.json을MetadataStorepersist callback 으로 atomic write, launch 시 store 를 그 파일에서 hydrate.SCROLLBACK_DUMPIPC 핸들러 가 직접writeFileSync대신atomicWriteTextSync사용. rotation chain (.bak / .bak.1 / .bak.2 / .bak.3) 활성화. pre-write corruption 시그니처 검출 시 payload 거부 (defense in depth — renderer 가드 회귀 대비).SCROLLBACK_LOADIPC 핸들러 가atomicReadTextSync+ validate hook 으로 load. chopped 시그니처 매칭 시 primary 를corrupted/{ts}.bak으로 격리 후.bak체인 fallback 으로 시도. 구조화CORRUPT_FILE로그를 stderr 로 emit. 손상 파일이 fresh xterm 에 복원돼서 다음 5초 dump 가 chopped 상태를 다시 디스크에 쓰는 자기증식 루프를 끊음.vitest.config.ts가scripts/__tests__/**/*.test.mjs도 include — 운영 도구 (마이그레이션 스크립트 등) 가 같은 test runner 아래에서 회귀 보호됨.
Fixed
replaceSharedmergeMode 가 caller 의custompatch 를 덮어쓰던 결함 (codex full-stack review P2) —patch.custom을 silently ignore 해 tool-namespace clobber 방지. substrate 의 namespace boundary guarantee.- MetadataStore size cap (
PANE_METADATA_MAX_BYTES) 이updatedAt추가 전에 검증되던 결함 (codex P2) — 최종 저장 shape (updatedAt포함) 에 대해 검증. boundary 안전. - MetadataStore
customentry cap 이 patch 에만 적용되던 결함 (codex P2) — 누적 merge 가 cap 을 우회하지 못하도록 post-merge shape 에 대해 검증. - Split-store read-after-write hole (M0-b codex P1) — paneId 없이 write 한 뒤 paneId 있는 read 가 stale 을 반환할 수 있던 구멍. 3 개의 metadata 핸들러 모두
pane.resolveActiveLeaf로 통일. workspaceId ?? ''가 기억된 scope 를 덮어쓰던 결함 (M0-b codex P2) — coercion 제거; MetadataStore 의 기존 fallback 이 정상 동작.- 스크롤백 손상 자기증식 루프 (P0 layered defense) — hidden / zero-width 컨테이너에 대한
fit()이cols를 ~2 로 collapse 시키면, renderer 의 5초 autosave 가 그 reflowed 버퍼를 캡처해 column-of-chars 로 디스크에 dump. 다음 부팅에 fresh xterm 에 복원되고 또 다시 5초 후에 dump 되며 영구적 손상 루프. 픽스는 네 층: (a) dump-time eligibility 가드 (cols < 12/rows ≤ 0/offsetWidth === 0/ detached element), (b) font/theme-changefit()의 visibility 가드 (마지막 unguarded fit 사이트 닫힘), (c) IPCSCROLLBACK_DUMP의 시그니처 거부, (d) IPCSCROLLBACK_LOAD의 시그니처 검출 + 격리 +.bak회전 체인 fallback. 시각 증상은 "재부팅하면 일부 패널 스크롤백이 비어 보임". 자세한 forensic 은 PR #34 참조. - 부팅 직후 일부 패널이 input-mute 였던 결함 (reconcile race) —
daemon.whenReady()와daemon.onConnected가 첫 연결에 같은 reconcile 을 동시에 trigger, 두 walk 가 같은 session 에 대해 race 하면서 한쪽이 ptyId 를 clear. 사용자 증상: 부팅 후 워크스페이스 전환을 한 번 해야 일부 패널이 살아남. 픽스:reconcileInFlightRef가 중복 trigger 를 drop, workspace snapshot 을 walk 마다 다시 읽어 동시 spawn 이 frozen view 에 가려지지 않음. pty:resize가 recovery PTY mute race 를 유발하던 결함 — daemon 이 아직 session 을 publish 하기 전에 renderer 가 보낸pty:resize가 "session not found" 로 실패하고 recovery PTY 가 muted 상태로 남던 결함. 50 × 20ms retry budget + 진단 로그 추가.- IPC
session+scrollback핸들러가 daemon-connect handler-swap cycle 의 unregister 윈도우에 떨어지던 결함 — cold boot 시scrollback:load가 "No handler registered" 로 거부되고 다음 5초 autosave 가 빈 버퍼를 디스크에 덮어쓰던 결함. session + scrollback 핸들러를 swap cycle 밖으로 이동. - logSink 의 EPIPE 무한 루프 — stdout 이 닫힌 상태에서 console.error 가 logSink 를 호출하고 logSink 가 다시 console.error 를 호출하던 reentrancy 루프. reentrancy 가드 +
orig()try/catch 추가.appendFileSync사용으로 로그가 디스크에 durable.
Migration Notes
- 자동 마이그레이션. 사용자 액션 불필요한 부분: substrate wire 변경 (모두 additive optional), MetadataStore 통합 (paneSlice consumer 영향 없음), atomic write + .bak rotation (v2.7.x 부터 이미 다른 파일에 적용된 패턴).
- v2.8.x 의 chopped 스크롤백: 첫 부팅에서 자동 격리된다. 데이터를 v2.9.0 이 버린 게 아니라 v2.8.x 시점에 이미 chopped 형태로 저장돼 있던 것을 v2.9.0 이 검출만 한 것. 사람이 읽을 수 있는 텍스트로의 회수는
node scripts/recover-scrollback.mjs --verbose로 가능 (자세한 가이드는docs/upgrade-v2.9.0.md). corrupted/폴더: 30 일 / 폴더당 10 파일까지 자동 정리. 수동 삭제도 안전.pane.metadata.changedevent subscriber: optionalversion필드가 추가됐다. 무시해도 v2.x 와 동일 동작.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About Wmux
All releases →Related context
Beta — feedback welcome: [email protected]