Skip to content

편집 확장의 identity·유효성·관찰 계약을 보강한다 #709

Closed

Description

@developer-1px

Goal Anchor

  • Outcome: Core 위의 편집 확장들을 조합해도 수정 범위, 노드 identity, domain 유효성, 선택과 관찰 계약이 보존됩니다.
  • Done:
    1. RichText의 escaped subtree 경로가 정확한 대상만 수정합니다.
    2. Document selection.move와 RichText node.move가 원래 노드 identity를 유지하여 동시 속성 편집을 잃지 않습니다.
    3. RichText가 잘못된 구조를 만드는 node.remove/node.move 및 public apply를 성공 처리하지 않습니다. 정상 Intent 경로의 같은 검증 누락도 확인하고 막습니다.
    4. Editing subscriber의 예외와 재진입이 완료된 편집 결과나 알림 순서를 깨지 않으며 snapshot selection 변경이 내부 상태와 history를 오염시키지 않습니다.
    5. 외부 변경 후 RichText 선택을 현재 topology에 맞게 보정하고, editor 내부 document 구독이 사용 종료 뒤 남지 않습니다.
    6. 두 RangeSelection family에서 앞 range가 제거되어도 살아남은 primary range identity를 유지합니다.
    7. Web clipboard binding이 지원하는 편집을 거절했을 때 browser 기본 동작으로 우회하지 못하도록 이벤트를 취소합니다. 지원하지 않는 형식의 pass-through는 유지합니다.
    8. 각 결함의 pre-fix 실패 / post-fix 성공 회귀 테스트와 관련 전체 테스트·타입·문서 검증으로 확인합니다.
  • Don't: Core나 Collaboration wire/schema를 확장하지 않습니다. 외부 변경 시 local inverse history를 초기화하는 기존 정책을 유지하며, 협업 selective history 통합과 의미 기반 외부 selection mapping 프로토콜의 전체 설계는 이번에 포함하지 않습니다. Composer의 인접 JSON 필드 apply, 정상 편집·undo/redo, 기존 public API, incremental typing 성능을 보존합니다. Calendar·Database·Annotation의 미병합 작업을 가져오거나 수정하지 않습니다. merge는 별도 승인 대상입니다.

근거와 정본 경계

사용자 요청: Core 밖 프로토콜 리뷰 후 “개선해줘”.
기준: origin/main 276c955. 기존 1,175 테스트는 통과하지만 public API 재현에서 위 계약 위반이 확인되었습니다.

  • RichText diff.ts의 자체 경로 파싱 → Core parsePointer 소비.
  • Editing document.ts / RichText editor.ts의 remove+add 이동 → identity 보존 이동.
  • RichText validation/topology/editor → domain 성공·실패와 선택 유효성 및 구독 lifecycle.
  • Editing session.ts → snapshot/history 소유권과 알림 전달.
  • Selection range/index.ts, range/materialized.ts → primary range 대응.
  • Web clipboard.ts → 처리 소유권과 default cancellation.
    새 보편 Editor/history 추상화나 Host 보완 코드를 만들지 않고 각 기존 owner에서 닫습니다.

검증 범위

public API 회귀 테스트(일반·fresh snapshot·협업 document), 이동과 동시 변경 통합, 구조 실패 원자성, 재진입·구독 해제, 두 range family, clipboard 거절 및 pass-through, 전체 package tests/build, 관련 Site consumer 및 문서 검사.
브라우저 확인 시 기존 Chrome 연결을 우선합니다. 미확인 native 동작은 확인된 것으로 보고하지 않습니다.

Activity

  1. self-assigned this
    on Sep 7, 2026
  2. developer-1px commented on Sep 7, 2026

    @developer-1px
    OwnerAuthor

    작업 계획

    원격 이슈를 다시 읽어 사용자 개선 요청과 Outcome / Done 1–8 / Don't의 양방향 대응을 확인했습니다. 이슈 본문 Goal Anchor를 그대로 실행 계약으로 유지합니다.

    회귀 재현
    ├─ Selection / Editing / Web 계약 수정
    ├─ RichText 경로·이동·유효성·선택·관찰 lifecycle 수정
    └─ public 조합 및 소비자 검증 → 문서 → 검증된 후보 PR
    

    기존 Core parsePointer/applyPatch 및 RichText validation/topology, EditingSession, Selection family, Web binding을 재사용합니다. 공통 새 editor/history 계층은 도입하지 않습니다.

    pending frontier

    위험 게이트

    • version-skew: 기존 JSON Patch move와 기존 collaboration wire만 사용. 구·신 domain writer 결과를 동일 runtime reader가 처리하는 조합을 확인합니다.
    • recovery: 새 데이터 형식/마이그레이션 없음. 잘못된 과거 데이터 및 이미 잃은 동시 편집은 자동 복구하지 않으며, 수정 후 정상 문서가 구 구현에서도 읽히는지 검증합니다.
    • concurrency/data ownership qualified review: merge 전에 별도 qualified owner 검토가 필요합니다. 이전 PR #708의 self-review 예외를 승계하지 않습니다.
    • operational observation: 배포·telemetry 변경 없음. 결정적 public API 통합 테스트로 실패 신호를 확인합니다.
    • 완료 조건은 객관적 계약 테스트이며 UI 디자인 변경이나 시각 취향 승인은 해당하지 않습니다. 실제 브라우저 adapter 동작은 기존 Chrome 연결에서 확인 가능한 범위를 기록합니다.
  3. developer-1px commented on Sep 7, 2026

    @developer-1px
    OwnerAuthor

    검증 중간 지점

    • pre-fix에서 새 회귀 17건 실패를 확인했습니다. RichText 외부 관찰 테스트의 wrapper value getter도 실제 JSONDocument contract에 맞게 교정해 재검증했습니다.
    • escaped subtree, concurrent move, invalid structure/public apply, observer exception/reentrancy, immutable selection, primary range, clipboard rejection 회귀가 수정 뒤 통과했습니다.
    • Done 2/5와 Don't의 실제 React consumer 보존을 위해 render-store.ts를 확인했습니다. 새 move를 기존 렌더러가 구조 변경으로 인식하지 않는 회귀를 별도 테스트로 재현하여 수정했고, unmount 후 남던 render store 구독도 동일 lifecycle 경계에서 해제합니다. 추가 제품 기능이 아닌 producer 변경의 필수 소비자 보존입니다.
    • 전체 실행 1,201 cases 중 기존 2개 assertion이 의도적으로 달라진 clipboard cancellation 및 lazy observation 계측 가정을 사용했습니다. 해당 assertion의 의미를 정정했고, 전체 재실행 및 native browser 확인이 남았습니다.
    • createEditingSession에 선택적 reconcileSelection callback을 추가해 domain 선택 보정을 외부 변경 관찰/조회와 같은 revision에 수행합니다. applied-change mapping이나 collaborative history rebase를 의미하지 않습니다. Owner reference/Usage/source closure를 갱신합니다.
    • npm registry의 Editing 조회는 E404, GitHub release 목록은 비어 있습니다. 배포/버전 변경은 하지 않으며 현재 draft 소스 조합을 검증합니다. 새 RichText의 외부 선택 보정은 이 callback을 지원하는 Editing과 함께 소비해야 합니다.
  4. developer-1px commented on Sep 7, 2026

    @developer-1px
    OwnerAuthor

    구현·검증 완료 후보

    원격 Goal Anchor의 Done 1–8 및 Don't와 최종 diff를 다시 대조했습니다. 승인된 계약 변경은 없습니다.

    • base: 276c955eaad57ef1dbfec4e0462a7540c29f8c4d
    • HEAD: 5114b7d951841e495cbcda7169455140a48e5e37
    • tree: cbd506b05b8e8e11518757b4e0618f0876b14aec
    • 환경: Node v24.16.0, 전용 worktree의 lockfile로 설치한 의존성.

    완료 근거

    Done 구현과 판별 검증
    1 Core parsePointer를 사용해 escaped RichText subtree의 실제 public apply/Intent 수정 범위를 확인했습니다.
    2 Document selection.move와 RichText node.move를 JSON Patch move로 전환했습니다. 원래 노드 identity·동시 속성 수정·추적 pointer·반복 그룹 이동 undo/redo 및 React DOM 순서 회귀를 확인했습니다.
    3 기존 recursive validator를 정본화하고, remove/move/insert/split/join/mark/public apply의 유효성·ID·cardinality 누락을 막았습니다. 실패 원자성과 Composer 인접 JSON 필드 apply도 통과했습니다.
    4 snapshot selection을 불변 소유하고 알림을 순서대로 전달합니다. subscriber 예외·재진입과 외부 snapshot 변경이 결과/history를 깨뜨리는 회귀를 확인했습니다.
    5 외부 변경과 같은 revision에서 canonical Selection family로 유효성을 보정합니다. editor 및 React render store의 마지막 unsubscribe/unmount와 미관찰 후 catch-up을 확인했습니다.
    6 두 RangeSelection family에서 제거된 앞 range 뒤의 살아남은 primary identity를 보존합니다.
    7 지원하는 cut/paste를 model이 거절해도 native 기본 동작이 실행되지 않게 callback 전에 취소합니다. unsupported pass-through는 유지합니다.
    8 protocol pre-fix 실패 17건을 확인한 뒤 회귀를 닫았습니다. React move 렌더링 및 마지막 source closure 누락도 각각 실패를 확인하고 수정했습니다. package reference·Usage·source 연결을 검증했습니다.

    실행 결과

    • npm run test:projects: 131 files / 1,206 passed / 4 skipped. 마지막 source 등록 보완 뒤 재실행했습니다.
    • npm run build, 관련 5개 package test tsconfig: 통과. 마지막 commit은 README·Site source 등록·테스트만 변경하여 package 구현 검증과 동일한 코드를 유지합니다.
    • npm run standard:check: 통과. Core conformance 345 passed / 4 skipped, RichText requirement/vector 검사 통과.
    • npm run docs:api:check(28 packages / 1,008 exports), npm run docs:evaluate, npm run workspace:check: 통과.
    • Site typecheck 및 전체 canonical/UI guard, Site production build(4,051 modules), git diff --check: 통과.
    • 기존 Chrome 프로필의 실제 RichText route에서 합성 beforeinput 입력 → Undo → Redo와 오류 없음 확인. 실제 Chrome ClipboardEvent/DataTransfer를 사용한 public binding의 거절된 cut/paste는 모두 defaultPrevented=true입니다.
    • native 키보드/시스템 clipboard 검증은 unavailable: System Events keystroke 권한 오류 1002. 임시 Chrome 프로필이나 사용자 clipboard로 대체하지 않았습니다.

    성능·호환성·복구 경계

    • 10k typing fast-path 회귀는 full validation/topology 재생성 없이 통과했습니다. 동일 120회 입력 probe(20회 warm-up)의 10k p95는 base 0.061ms / 후보 0.056ms입니다. 전체 성능 개선 주장이나 다른 동작의 보증은 아닙니다.
    • 전체 PERF_RICH_TEXT_BLOCKS=100,1000,10000 node packages/json-document-rich-text/benchmarks/editor.mjs는 base와 후보 모두 기존 Core proxy getOwnPropertyDescriptor 오류로 실패합니다. json-document/dist/foundation/json/clone.js:187 → Editing inverse 계산 경로입니다. 이 전체 benchmark를 통과했다고 판단하지 않으며 Core 수정은 이번 Don't 밖입니다.
    • pristine base/후보 Collaboration 소스 구현으로 old writer/new reader 및 new writer/old reader 두 조합의 move·동시 REMOTE 편집 교환 후 수렴/유효성을 확인했습니다. Core/Collaboration wire·schema·소스 변경은 없습니다.
    • 새 RichText 외부 선택 보정은 새 선택적 callback을 제공하는 동일 Draft Editing과 함께 소비해야 합니다. npm 조회 E404 및 release 부재로 공개 배포본 조합은 확인하지 못했습니다. 배포·버전 변경은 하지 않았습니다.
    • 데이터 형식은 구 reader에서도 읽혀 형식 차원의 recovery는 revert-safe입니다. revert가 이전 결함을 고치거나 이미 잃은 데이터를 복구한다는 뜻은 아닙니다.
    • 외부 변경 시 local inverse history 초기화는 유지합니다. 의미 기반 외부 selection mapping 전체 설계와 selective collaboration history 통합은 범위 밖입니다.

    정본·자가 검토와 pending frontier

    canonical-module-audit / doubt 관점에서 중복 pointer parser와 shallow validator를 제거하고 기존 owner API를 확장했습니다. 새 보편 Editor/history 계층, Host 우회, 독립 제품 기능은 없습니다. appliedOperationsFor.from의 실제 React 소비 소스까지 기존 Site 등록 방식으로 연결했습니다.

    push 직전 remote/base와 모든 worktree·open PR을 다시 확인했습니다. #704 eba5017 / #587 f0d0b09 / #589 4c89fbc7는 그대로이며 기존 unrelated / boundary-overlap 분류를 유지합니다. 후보와의 merge-tree도 각각 3 / 8 / 20개 충돌로 combined 실행은 unavailable입니다. 다른 PR 변경을 가져오거나 충돌을 해결하지 않았습니다. foreign worktree와 untracked 자료는 보존했고, 이번 검증용 임시 baseline worktree만 제거했습니다.

    다음은 이 후보를 push하고 PR로 게시하는 단계입니다. merge 권한은 없으며, concurrency/data ownership의 별도 qualified owner review도 merge 전 필요합니다. 자가 검토를 그 승인으로 대체하지 않습니다.

  5. developer-1px commented on Sep 7, 2026

    @developer-1px
    OwnerAuthor

    PR 게시 완료

    PR #710을 열었습니다.

    • 원격 이슈·PR 본문·28개 changed files·closing issue 연결을 다시 읽어 Done 1–8 / Don't 및 검증 기록과 양방향으로 대조했습니다.
    • 원격 PR head와 검증한 로컬 HEAD가 모두 5114b7d951841e495cbcda7169455140a48e5e37로 일치합니다. 전용 branch codex/issue-709-extension-protocol은 push되었고 worktree는 clean입니다.
    • local 검증은 위 기록대로 1,206 passed / 4 skipped입니다. 원격 CI는 시작되어 진행 중이며 통과를 선결론으로 두지 않습니다.
    • 상태는 pr-open입니다. Issue는 OPEN, 별도 연결 Project는 없습니다.
    • merge하지 않았습니다. 남은 경계는 원격 CI 결과, merge 전 qualified concurrency/data ownership review, 기존 Core benchmark 실패 및 native 검증 unavailable입니다. 선택 의미 mapping 전체와 협업 selective history 통합은 이번 범위 밖 그대로입니다.
  6. developer-1px commented on Sep 7, 2026

    @developer-1px
    OwnerAuthor

    self-review·merge 후속 승인 및 CI 원인

    사용자 후속 요청: “PR하고 self review하고 merge”.

    기존 “merge는 별도 승인” 조건에 대해 이번 요청으로 merge 권한을 받았습니다. 직전 보고한 별도 qualified owner review 조건은 이번 요청의 명시적인 self-review 방식으로 이 PR에 한해 대체합니다. GitHub의 강제 승인·보호 규칙을 우회하는 것은 아닙니다. 현재 main protection은 Branch not protected, rulesets는 빈 목록이며 공식 review/comment는 없습니다. 기존 기능 Outcome / Done 1–8 / Don't의 코드 범위는 그대로입니다.

    현재 base 276c955e, PR/local head 5114b7d9, tree cbd506b0는 이전 검증 후보와 동일합니다. #704 / #587 / #589와 다른 worktree의 상태도 변하지 않았습니다.

    CI는 Site·External kit 통과, Package 실패입니다. 로그에서 추가한 tests/editor-protocol.test.ts가 @interactive-os/json-document-collaboration/history를 import하지만 RichText의 devDependencies에 없어서, clean checkout의 선택적 dependency build 후 TS2307이 발생함을 확인했습니다. 이전 전체 build는 이를 가렸습니다.

    Done 2의 실제 Collaboration 조합 회귀와 Done 8의 clean package 검증에 필요한 test-only dependency를 기존 manifest/lockfile에 선언하겠습니다. runtime peer, public API, Collaboration 구현과 CI 정책은 변경하지 않습니다. 수정 후 dependency build부터 확인하고 원격 CI를 다시 통과시킵니다.

  7. developer-1px commented on Sep 7, 2026

    @developer-1px
    OwnerAuthor

    self-review 발견: public validation의 unknown parent 회귀

    validateRichTextNodeAt를 recursive validator로 통합하면서 이전 standalone validator의 unknown parent 검사가 사라졌습니다. schema.nodes에 부모 타입이 없는 provider 조합에서 public 함수가 rich-text.schema-violation 대신 Cannot read properties of undefined (reading 'content')를 throw하는 것을 현재 후보에서 재현했습니다.

    이는 이 PR의 validator 통합이 만든 회귀이며 Done 3과 Don't의 기존 public API 보존에 직접 해당합니다. 기존 guard를 정본 validator에 복원하고 validateRichTextNodeAt / validateRichTextPath 회귀 테스트로 판별하겠습니다. 새 API나 fallback 정책을 만들지 않습니다.

  8. developer-1px commented on Sep 7, 2026

    @developer-1px
    OwnerAuthor

    self-review 발견: 비연속 Document 선택 이동 순서

    이동 계획을 1–6개 block의 모든 비어 있지 않은 선택 집합·양방향으로 검증하던 중, [0,1,2,3,4,5]에서 [0,3,4] 선택을 아래로 옮기면 기존 결과 [1,0,3,4,2,5] 대신 [1,0,3,2,4,5]가 되는 회귀를 재현했습니다. 단순 역순 move는 앞/뒤 방향 이동이 섞인 비연속 선택에서 이미 배치한 노드를 다시 밀었습니다.

    Done 2의 identity-preserving move 전환이 만든 기존 선택 이동 의미의 회귀이므로 현재 PR에서 수정합니다. 목표 위치보다 뒤에 있는 멤버는 앞에서부터, 앞에 있는 멤버는 뒤에서부터 배치하여 선택한 멤버만 각각 최대 한 번 이동합니다. 새 abstraction 없이 기존 planner 내부에서 닫고, 240개 선택/방향 조합으로 기존 순서·경계 거절·undo/redo·move-only 계약을 확인하겠습니다.

  9. developer-1px commented on Sep 7, 2026

    @developer-1px
    OwnerAuthor

    Merge·정리 완료 — landed-clean

    • PR #710 MERGED, 이슈 편집 확장의 identity·유효성·관찰 계약을 보강한다 #709 CLOSED.
    • squash merge: facc55d1418b179cbf121bcf5210623b54dbf39d.
    • merge된 main tree가 검증한 8719626f74e669bbc830d97616247254f1143e36와 정확히 같습니다.
    • 최신 PR head 8bf79847c9024bd22c56b258a6027299f62eb221의 Plan / Package(전체 release graph) / Site(전체 browser suite) / External kit가 모두 통과했습니다.
    • self-review에서 test dependency 누락, unknown-parent validation 예외, 비연속 선택의 이동 순서 회귀 3건을 수정했습니다. 최종 로컬 검증은 1,208 passed / 4 skipped입니다.
    • workflow-owned worktree /Users/user/Desktop/@interactive-os/json-document-issue-709는 clean 상태 확인 후 제거했고, 등록과 디스크에서 모두 사라진 것을 확인했습니다. 로컬·원격 codex/issue-709-extension-protocol branch도 제거했습니다. 소스와 원래 후보 commit은 merged PR 기록에서 복구할 수 있습니다.
    • 이 worktree의 Vite 서버만 중지했습니다. 일치하는 소유 preview tab을 찾지 못해 다른 Chrome 탭은 변경하지 않았습니다.
    • 기존 Calendar worktree와 untracked 사용자 자료는 그대로입니다. json-document-issue-705의 local main checkout은 다른 workflow 소유이므로 fast-forward하지 않았습니다. authoritative origin/main은 위 merge commit으로 갱신했습니다.
    • 연결된 Project가 없어 별도 Project 전이는 없습니다.

    기존 RichText 전체 benchmark의 Core proxy 오류와 공개 배포본/native 입력 검증 제한, 전체 의미 기반 selection mapping·selective collaborative history 제외는 앞선 기록 그대로이며, 이를 이번 merge로 해결했다고 주장하지 않습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions