From 432283bfc8ee0299b67e88a6693564108857cd63 Mon Sep 17 00:00:00 2001 From: JK Date: Sat, 25 Apr 2026 23:25:08 +0900 Subject: [PATCH 1/4] =?UTF-8?q?confluence-mdx:=20reverse-sync=20=EB=8C=80?= =?UTF-8?q?=EC=B2=B4=20=EA=B3=84=ED=9A=8D=20=EB=AC=B8=EC=84=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 2026-04-25 기준의 새 reverse-sync replacement plan을 작성합니다. - 기존 3월 phase/cleanup/review 계획 문서에 superseded 안내를 추가합니다. - capability registry, planner/strategy/proof 분리, verifier taxonomy 재정의를 중심으로 새 계획을 정리합니다. Co-Authored-By: Claude Opus 4.6 --- ...verse-sync-reconstruction-design-review.md | 4 + ...3-13-reverse-sync-reconstruction-design.md | 4 + ...verse-sync-reconstruction-cleanup-scope.md | 4 + ...026-04-25-reverse-sync-replacement-plan.md | 462 ++++++++++++++++++ 4 files changed, 474 insertions(+) create mode 100644 confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md diff --git a/confluence-mdx/docs/plans/2026-03-13-reverse-sync-reconstruction-design-review.md b/confluence-mdx/docs/plans/2026-03-13-reverse-sync-reconstruction-design-review.md index a8b02493e..7b9e5587b 100644 --- a/confluence-mdx/docs/plans/2026-03-13-reverse-sync-reconstruction-design-review.md +++ b/confluence-mdx/docs/plans/2026-03-13-reverse-sync-reconstruction-design-review.md @@ -1,5 +1,9 @@ # Reverse Sync 전면 재구성 설계 — 검토 평가 결과 (v5) +> 상태: Superseded review +> 대체 문서: `2026-04-25-reverse-sync-replacement-plan.md` +> 비고: 이 문서는 2026-03 시점 설계안에 대한 검토 기록입니다. 현재 계획 논의는 새 replacement plan을 기준으로 진행합니다. + > 검토 대상: `2026-03-13-reverse-sync-reconstruction-design.md` > 검토일: 2026-03-13 > 검토 기준 버전: PR #913 head `33fa095e56cb26766995b3930d3616a58559685e` diff --git a/confluence-mdx/docs/plans/2026-03-13-reverse-sync-reconstruction-design.md b/confluence-mdx/docs/plans/2026-03-13-reverse-sync-reconstruction-design.md index efc0208cc..16570429b 100644 --- a/confluence-mdx/docs/plans/2026-03-13-reverse-sync-reconstruction-design.md +++ b/confluence-mdx/docs/plans/2026-03-13-reverse-sync-reconstruction-design.md @@ -1,5 +1,9 @@ # Reverse Sync 전면 재구성 설계 +> 상태: Superseded +> 대체 문서: `2026-04-25-reverse-sync-replacement-plan.md` +> 비고: 이 문서는 2026-03 시점의 phase 계획과 당시의 코드 상태를 보존하기 위한 기록입니다. 현재 작업 계획은 새 replacement plan을 기준으로 합니다. + > 최초 작성일: 2026-03-13 > 갱신일: 2026-03-19 (4차 — Phase 5 진행 현황 반영 및 설계 기준선 교정) > 기준 브랜치: `main` diff --git a/confluence-mdx/docs/plans/2026-03-15-reverse-sync-reconstruction-cleanup-scope.md b/confluence-mdx/docs/plans/2026-03-15-reverse-sync-reconstruction-cleanup-scope.md index ac3ffdcb5..89d1b94b8 100644 --- a/confluence-mdx/docs/plans/2026-03-15-reverse-sync-reconstruction-cleanup-scope.md +++ b/confluence-mdx/docs/plans/2026-03-15-reverse-sync-reconstruction-cleanup-scope.md @@ -1,5 +1,9 @@ # Reverse Sync 재구성 후 삭제 대상 범위 +> 상태: Superseded +> 대체 문서: `2026-04-25-reverse-sync-replacement-plan.md` +> 비고: 이 문서는 2026-03 시점 cleanup 가정과 삭제 범위를 담고 있습니다. 현재 cleanup 계획은 새 replacement plan의 단계별 실행 계획을 기준으로 합니다. + > 작성일: 2026-03-15 > 갱신일: 2026-03-16 > 기준 브랜치: `main` diff --git a/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md b/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md new file mode 100644 index 000000000..5443d0995 --- /dev/null +++ b/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md @@ -0,0 +1,462 @@ +# Reverse Sync 대체 계획 (2026-04-25) + +> 상태: Draft +> 대상: `confluence-mdx/bin/reverse_sync/`, `bin/reverse_sync_cli.py`, `tests/`, `docs/` +> 목적: 기존 reconstruction phase 문서를 현재 코드 기준으로 대체하고, 앞으로의 개선 작업을 "구현 현실"에 맞는 계획으로 다시 정의합니다. + +--- + +## 1. 이 문서가 대체하는 기존 계획 문서 + +이 문서는 아래 3개 문서를 포괄적으로 대체합니다. + +- `2026-03-13-reverse-sync-reconstruction-design.md` +- `2026-03-13-reverse-sync-reconstruction-design-review.md` +- `2026-03-15-reverse-sync-reconstruction-cleanup-scope.md` + +기존 문서들은 당시로서는 타당한 문제의식과 설계 방향을 담고 있었지만, 현재 main의 구현 상태와 다음 이유로 어긋납니다. + +1. 이미 완료된 작업을 아직 계획 단계처럼 서술하는 부분이 있습니다. +2. 삭제된 모듈(`text_transfer.py`, `list_patcher.py`, `table_patcher.py`)을 전제로 하는 cleanup 항목이 남아 있습니다. +3. `mapping.yaml`과 roundtrip sidecar v3의 실제 역할 분리가 문서 구조에 충분히 반영되지 않았습니다. +4. 현재의 핵심 위험이 "재구성 자체의 부재"보다 "patch_builder 정책 집중 + verifier 결합 + capability 경계 불명확"으로 이동했는데, 예전 문서는 이 상태를 담지 못합니다. + +이 문서는 따라서 "예전 계획의 6차 개정판"이 아니라, 현재 구현을 출발점으로 다시 세운 replacement plan입니다. + +--- + +## 2. 현재 기준선 + +현재 reverse-sync의 사실상 표준 경로는 다음과 같습니다. + +1. 원본/교정 MDX 로드 +2. `parse_mdx_blocks()` + `diff_blocks()` +3. `record_mapping(page.xhtml)` +4. `generate_sidecar_mapping()` / `mapping.yaml` +5. `build_sidecar()` / `expected.roundtrip.json` schema v3 +6. `build_patches()` +7. `patch_xhtml()` +8. patched XHTML 재기록 +9. forward converter 재실행 +10. `verify_roundtrip()` +11. pass 시에만 push 후보로 취급 + +현재 구현의 핵심 특성: + +- reverse-sync는 text patcher가 아니라 sidecar 기반 fragment-preserving system입니다. +- `patch_builder.py`가 실제 정책 엔진입니다. +- `mapping.yaml`은 lookup/lost_info 계층이고, roundtrip sidecar v3는 identity/reconstruction 계층입니다. +- list, preserved anchor, table, parameter-bearing container는 여전히 별도 capability boundary를 갖습니다. +- verifier와 forward converter의 정규화 특성 변화가 reverse-sync pass/fail에 직접 영향을 줍니다. + +이 기준선은 "무엇을 새로 만들 것인가"보다 먼저 "무엇을 더 이상 가정하지 말아야 하는가"를 정해줍니다. + +--- + +## 3. 이번 계획의 목표 + +### 3.1 최종 목표 + +reverse-sync를 "모든 MDX 변경을 무조건 Confluence에 반영하는 시스템"으로 만들겠다는 목표는 현실적이지 않습니다. 대신 다음을 목표로 삼습니다. + +1. 지원 범위를 capability 단위로 명확히 문서화합니다. +2. 지원 범위 안에서는 roundtrip proof까지 포함해 신뢰할 수 있게 만듭니다. +3. 지원 범위 밖에서는 skip/fail 이유가 코드와 문서에 일관되게 드러나게 만듭니다. +4. `patch_builder.py`의 전략 집중을 완화해 회귀 수정 비용을 줄입니다. +5. verifier/fixture/manifest 체계를 재정리해 "왜 pass/fail인지"를 추적 가능하게 만듭니다. + +### 3.2 비목표 + +이번 계획의 비목표는 다음과 같습니다. + +- Confluence XHTML의 모든 구조를 일반 emitter만으로 재생성하기 +- skip reason을 전부 제거하기 +- 테이블/복합 anchor/container를 단기간에 완전 지원하기 +- reverse-sync를 forward converter와 완전히 분리된 서브시스템으로 만들기 + +즉, 목표는 "전면 자동화"가 아니라 "지원 범위의 명확화 + 구조적 유지보수성 향상"입니다. + +--- + +## 4. 설계 원칙 + +### 4.1 fail-closed를 유지합니다 + +지원 범위가 애매한 변경은 계속 skip/fail-closed로 남겨야 합니다. coverage 없이 공격적으로 허용하는 방향은 반복 회귀를 다시 부릅니다. + +### 4.2 sidecar를 진실원으로 취급하지 않고, 계약(contract)으로 취급합니다 + +- `mapping.yaml`은 구조 lookup 계약입니다. +- roundtrip sidecar v3는 fragment identity 계약입니다. +- 둘 중 하나만으로 전체 문제를 해결하려고 하면 문서와 코드가 다시 어긋납니다. + +### 4.3 정책과 실행을 분리합니다 + +현재 `patch_builder.py`에는 다음이 함께 들어 있습니다. + +- capability 판별 +- fallback 선택 +- patch shape 생성 +- skip reason 생성 +- 일부 list/table 전용 로직 + +앞으로는 planner와 strategy 실행을 분리해야 합니다. + +### 4.4 테스트는 "설계 검증"과 "회귀 방지"를 분리합니다 + +예전 문서는 둘을 한 축에 놓는 경향이 있었고, 그 결과 oracle이 흐려졌습니다. 앞으로는 테스트를 다음으로 분리합니다. + +- 계약 테스트(contract tests) +- strategy 단위 회귀 테스트 +- page fixture 기반 통합 테스트 +- batch manifest 기반 상태 리포트 + +### 4.5 문서와 코드의 시간축을 분리합니다 + +현황 문서는 현재 코드가 하는 일을 적고, 계획 문서는 앞으로 바꿀 일을 적어야 합니다. 둘을 한 문서에 섞지 않습니다. + +--- + +## 5. 핵심 문제 재정의 + +현재 reverse-sync의 가장 큰 문제는 "아직 reconstruction이 덜 구현되었다"가 아닙니다. 현재는 다음 5개가 더 중요합니다. + +### P1. capability 경계가 코드에만 있고 문서/테스트 표면에 명시되지 않습니다 + +예: + +- 어떤 table은 replace 가능하고 어떤 table은 skip됩니다. +- 어떤 preserved anchor list는 처리되고 어떤 것은 여전히 위험합니다. +- 어떤 container는 reconstruction 경로를 타지만 parameter-bearing container는 별도 취급됩니다. + +하지만 이 차이가 문서/테스트/CLI 결과에서 일관된 capability taxonomy로 드러나지 않습니다. + +### P2. `patch_builder.py`가 planner + strategy dispatcher + partial executor 역할을 동시에 수행합니다 + +이 구조에서는 새 회귀가 나올 때마다 if/elif를 추가하는 방향으로 수렴하기 쉽습니다. + +### P3. verifier와 converter 정규화가 reverse-sync 결과 해석을 어렵게 만듭니다 + +pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicalization 변화인지, verifier normalization 차이인지 즉시 분리되지 않는 경우가 있습니다. + +### P4. fixture/manifest는 많지만 계층이 섞여 있습니다 + +- `tests/testcases/` +- `tests/reverse-sync/pages.yaml` +- unit test +- e2e regression fixture + +각 자산의 역할이 겹치고, 어떤 테스트가 "정책 계약"을 검증하는지 명확하지 않은 부분이 있습니다. + +### P5. 계획 문서가 실제 main과 엇갈리며, 삭제된/완료된 축을 계속 참조합니다 + +이 상태에서는 새 작업을 시작할 때마다 먼저 문서를 해석해야 하므로, 문서가 가이드보다 부담이 됩니다. + +--- + +## 6. 목표 아키텍처 + +이번 계획의 목표 아키텍처는 "새 시스템을 다시 처음부터 만들자"가 아니라, 현재 구조를 다음처럼 재배치하는 것입니다. + +### 6.1 Planner / Strategy / Proof 3계층 + +1. Planner + - 변경 블록을 capability 단위로 분류 + - 사용 가능한 identity source 결정 + - strategy 후보 결정 + - skip/fail reason 결정 + +2. Strategy + - direct edit + - fragment replacement + - container reconstruction + - list strategy + - table strategy + - preserved-anchor template rewrite + +3. Proof + - patch 적용 + - forward roundtrip + - result classification + - push eligibility + +현재는 이 셋이 `patch_builder.py`와 `reverse_sync_cli.py` 사이에 뒤섞여 있습니다. 앞으로는 책임 경계를 명시해야 합니다. + +### 6.2 Capability registry 도입 + +다음과 같은 capability 단위를 문서와 코드 양쪽에 명시적으로 도입합니다. + +- `paragraph_text_edit` +- `heading_text_edit` +- `inline_whitespace_adjustment` +- `clean_block_replace` +- `container_body_reconstruction` +- `preserved_anchor_template_rewrite` +- `list_visible_segment_edit` +- `table_fragment_replace` +- `unsafe_table_edit` +- `unsupported_complex_anchor_structure` + +중요한 것은 naming 그 자체보다, 각 capability가 아래를 갖는 것입니다. + +- 지원 여부 +- strategy owner +- skip/fail reason +- 대표 fixture +- regression test location + +### 6.3 Result taxonomy 표준화 + +현재 `pass/fail/no_changes/skipped_changes`는 존재하지만, 더 세밀한 해석이 필요합니다. 계획상 목표 taxonomy는 다음과 같습니다. + +- `pass` +- `pass_with_normalization` +- `no_changes` +- `skipped_capability_boundary` +- `failed_patch_generation` +- `failed_roundtrip` +- `blocked_push_safety` + +이 taxonomy는 CLI, result.yaml, 문서, 테스트 설명이 공통으로 써야 합니다. + +--- + +## 7. 단계별 실행 계획 + +### Stage 0. 문서/분류 기준선 확정 + +목표: + +- current-state 문서와 plan 문서의 역할을 분리합니다. +- capability registry 초안을 문서에 먼저 정의합니다. +- 기존 plan 문서를 superseded 상태로 전환합니다. + +산출물: + +- 현재 구현 상태 문서 +- 본 replacement plan +- 기존 plan 문서 superseded 표기 + +완료 기준: + +- 새 작업이 더 이상 3월 phase 문서를 기준으로 시작되지 않습니다. + +### Stage 1. capability matrix와 fixture inventory 정리 + +목표: + +- 현재 처리 가능한 변경을 capability 기준으로 표에 정리합니다. +- `pages.yaml`, testcase fixture, unit test 사이의 관계를 표준화합니다. + +작업: + +1. `failure_type`, label, severity를 capability/skip reason과 매핑합니다. +2. 각 capability에 대표 fixture를 1~3개씩 지정합니다. +3. `expected_status`가 무엇을 뜻하는지 문서에서 재정의합니다. +4. unsupported 영역을 명시적으로 목록화합니다. + +완료 기준: + +- "이 케이스는 왜 아직 안 되나"를 capability 이름으로 설명할 수 있습니다. +- 회귀 이슈가 들어오면 어느 capability에 속하는지 바로 분류할 수 있습니다. + +### Stage 2. `patch_builder.py` 분해 1차 — planner 추출 + +목표: + +- `patch_builder.py`에서 정책 판단과 patch 생성 책임을 분리합니다. + +작업: + +1. planner 입력/출력 구조 정의 + - change + - mapping source + - sidecar source + - capability + - chosen strategy + - skip reason +2. strategy dispatcher 인터페이스 정의 +3. 기존 `build_patches()`는 planner + strategy executor orchestration으로 축소 + +완료 기준: + +- 새 회귀 수정 시 `build_patches()` 본체에 직접 if/elif를 추가하지 않고, planner rule 또는 strategy handler 수정으로 끝낼 수 있습니다. + +### Stage 3. list / preserved anchor / container 전략 분리 + +목표: + +- 현재 가장 복잡한 capability를 독립 전략 모듈로 분리합니다. + +우선순위: + +1. list visible-segment 전략 +2. preserved-anchor template rewrite 전략 +3. parameter-bearing container reconstruction 전략 + +완료 기준: + +- 각 전략이 독립 테스트 파일과 fixture 세트를 가집니다. +- `patch_builder.py`는 분기 지점만 남고 세부 알고리즘을 직접 품지 않습니다. + +### Stage 4. table 경계 명시화 + +목표: + +- table 지원을 넓히기 전에 먼저 boundary를 명확히 합니다. + +작업: + +1. 현재 skip reason을 capability 문서와 1:1로 연결 +2. markdown table / raw HTML table / preserved-anchor table을 명확히 분리 +3. 어떤 table이 "지원 대상"인지 acceptance contract를 먼저 고정 + +완료 기준: + +- table 관련 버그가 들어왔을 때 "미지원"과 "회귀"를 혼동하지 않습니다. +- 새로운 지원 확대는 capability 추가로 표현합니다. + +### Stage 5. verifier contract 정리 + +목표: + +- patch quality 문제와 normalization 문제를 분리합니다. + +작업: + +1. `verify_roundtrip()` 결과를 reason code 중심으로 재분류 +2. `--lenient`, `--no-normalize`의 의미를 문서와 테스트에서 고정 +3. converter normalization 변화로 인한 false failure를 별도 카테고리로 분리 + +완료 기준: + +- fail 원인을 `patch mismatch` / `normalization mismatch` / `forward canonicalization drift`로 구분할 수 있습니다. + +### Stage 6. push rollout contract 정리 + +목표: + +- verify pass와 push eligibility를 같은 개념으로 취급하지 않도록 정리합니다. + +작업: + +1. push safety gate 문서화 +2. conflict / remote drift / dry-run / human confirmation 경계 정리 +3. CLI 출력과 result.yaml에 push-blocked reason 추가 + +완료 기준: + +- "verify는 통과했지만 왜 push하지 않았는가"가 결과에 명시됩니다. + +--- + +## 8. 테스트 계획 + +### 8.1 테스트 계층 + +1. Contract tests + - sidecar schema + - planner classification + - result taxonomy + +2. Strategy tests + - list visible segment + - preserved anchor rewrite + - container reconstruction + - table classification + +3. Fixture integration tests + - `tests/testcases/` + - `original.mdx` / `improved.mdx` / `expected.reverse-sync.patched.xhtml` + +4. Batch manifest tests + - `tests/reverse-sync/pages.yaml` + - capability/expected_status/failure_type alignment 검증 + +### 8.2 테스트 원칙 + +- 새 capability를 추가할 때는 representative fixture를 반드시 함께 추가합니다. +- skip reason을 바꿀 때는 result taxonomy 테스트도 함께 갱신합니다. +- verifier normalization 변경은 strategy 테스트가 아니라 verifier contract 테스트로 검증합니다. +- pages.yaml은 단순 case catalog가 아니라 regression reporting asset으로 관리합니다. + +### 8.3 우선 추가할 테스트 + +1. planner classification snapshot test +2. table skip reason classification test +3. list visible segment capability fixture set +4. verifier reason-code split test +5. result.yaml schema test + +--- + +## 9. 문서 구조 계획 + +최종적으로 reverse-sync 문서는 다음 구조를 목표로 합니다. + +- `docs/architecture.md` + - 현재 코드가 실제로 어떻게 동작하는지 설명 +- `docs/analysis-reverse-sync-refactoring.md` + - 현재 구현 상태와 구조적 리스크 분석 +- `docs/plans/2026-04-25-reverse-sync-replacement-plan.md` + - 앞으로의 변경 계획 +- (선택) capability matrix 문서 + - 지원/미지원 범위를 표로 관리 + +즉, 현황 / 분석 / 계획을 분리합니다. + +--- + +## 10. 기존 계획 문서에서 유지할 것과 버릴 것 + +### 유지할 것 + +- fail-closed 원칙 +- sidecar 기반 identity 보존 방향 +- reconstruction 중심 접근 +- 테스트 우선 사고 +- regression gate를 먼저 세우는 태도 + +### 버릴 것 + +- phase 번호 중심 서술 +- 이미 삭제된 모듈을 기준으로 한 cleanup 계획 +- `mapping.yaml` 단독 설명으로 전체 reverse-sync를 설명하려는 방식 +- 구현 완료/미완료 상태와 계획을 한 문서에 섞는 방식 + +--- + +## 11. 승인 기준 + +이 계획은 다음 상태가 되면 실행 가능하다고 봅니다. + +1. capability registry의 1차 naming이 합의됩니다. +2. planner 분리 범위가 합의됩니다. +3. table을 "당장 더 지원할 것인지"보다 "경계를 먼저 고정할 것인지"에 대한 방향이 합의됩니다. +4. verifier reason taxonomy가 합의됩니다. + +즉, 코드 착수 전 필요한 것은 "모든 세부 구현의 확정"이 아니라, 앞으로 무엇을 지원 capability로 보고 무엇을 boundary로 둘지에 대한 합의입니다. + +--- + +## 12. 리뷰에서 확인받고 싶은 쟁점 + +이 PR은 Draft이며, 아래 쟁점에 대한 리뷰를 받고 싶습니다. + +1. capability registry naming이 과한지, 아니면 필요한지 +2. table을 지원 확대보다 경계 명시화부터 하는 우선순위가 맞는지 +3. planner/strategy/proof 3계층 분리가 실제 코드 정리의 중심축으로 적절한지 +4. `pages.yaml`를 계속 manifest+metadata 겸용으로 둘지, 역할을 분리할지 +5. verifier taxonomy를 세분화하는 것이 운영상 도움이 되는지 + +--- + +## 13. 결론 + +예전 계획의 핵심 직감은 맞았습니다. reverse-sync는 heuristic patch를 계속 덧대는 방향만으로는 안정화되지 않습니다. 다만 현재 시점에는 이미 많은 reconstruction/sidecar 기반 구현이 main에 들어와 있으므로, 이제 필요한 것은 "새 phase를 더 추가하는 문서"가 아니라 다음입니다. + +- 현재 구조를 capability 기준으로 다시 설명하고 +- 정책 엔진을 분해할 수 있는 계획을 세우고 +- 지원 범위와 한계를 문서/테스트/CLI에서 같은 언어로 표현하는 것 + +이 문서는 그 전환을 위한 새로운 기준 문서입니다. From 98619bae23ff727c678efbcbc72f46e109f54fe0 Mon Sep 17 00:00:00 2001 From: JK Date: Sun, 26 Apr 2026 00:17:14 +0900 Subject: [PATCH 2/4] =?UTF-8?q?confluence-mdx:=20reverse-sync=20=EB=8C=80?= =?UTF-8?q?=EC=B2=B4=20=EA=B3=84=ED=9A=8D=20=EB=AC=B8=EC=84=9C=EC=9D=98=20?= =?UTF-8?q?=ED=95=A9=EC=9D=98=20=EB=B0=A9=ED=96=A5=EC=9D=84=20=EB=B0=98?= =?UTF-8?q?=EC=98=81=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - replacement plan을 현재 기준의 주 문서로 명시합니다 - planner/strategy/proof, table verifier normalization, pages.yaml 역할 합의를 반영합니다 - verifier taxonomy를 Accept/Review/Block/Error 기준으로 구체화합니다 Co-Authored-By: Claude Opus 4.6 --- ...026-04-25-reverse-sync-replacement-plan.md | 85 +++++++++++-------- 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md b/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md index 5443d0995..11e35ad06 100644 --- a/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md +++ b/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md @@ -22,6 +22,7 @@ 4. 현재의 핵심 위험이 "재구성 자체의 부재"보다 "patch_builder 정책 집중 + verifier 결합 + capability 경계 불명확"으로 이동했는데, 예전 문서는 이 상태를 담지 못합니다. 이 문서는 따라서 "예전 계획의 6차 개정판"이 아니라, 현재 구현을 출발점으로 다시 세운 replacement plan입니다. +이 문서를 현재 기준의 주 문서로 삼고, 3월 문서들은 historical record로만 남깁니다. --- @@ -139,14 +140,14 @@ reverse-sync를 "모든 MDX 변경을 무조건 Confluence에 반영하는 시 pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicalization 변화인지, verifier normalization 차이인지 즉시 분리되지 않는 경우가 있습니다. -### P4. fixture/manifest는 많지만 계층이 섞여 있습니다 +### P4. fixture/reporting 자산은 많지만 taxonomy가 아직 정리되지 않았습니다 - `tests/testcases/` - `tests/reverse-sync/pages.yaml` - unit test - e2e regression fixture -각 자산의 역할이 겹치고, 어떤 테스트가 "정책 계약"을 검증하는지 명확하지 않은 부분이 있습니다. +실데이터 기준으로 `pages.yaml`의 역할은 이미 비교적 명확합니다. reverse-sync 입장에서는 참조용 metadata catalog이며, 테스트 구현 과정에서만 추가 필드가 얹혀 있습니다. 문제는 `pages.yaml` 자체보다, capability / expected_status / verifier outcome을 어떤 taxonomy로 읽을지 아직 정리되지 않았다는 점입니다. ### P5. 계획 문서가 실제 main과 엇갈리며, 삭제된/완료된 축을 계속 참조합니다 @@ -207,17 +208,27 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza ### 6.3 Result taxonomy 표준화 -현재 `pass/fail/no_changes/skipped_changes`는 존재하지만, 더 세밀한 해석이 필요합니다. 계획상 목표 taxonomy는 다음과 같습니다. - -- `pass` -- `pass_with_normalization` -- `no_changes` -- `skipped_capability_boundary` -- `failed_patch_generation` -- `failed_roundtrip` -- `blocked_push_safety` - -이 taxonomy는 CLI, result.yaml, 문서, 테스트 설명이 공통으로 써야 합니다. +현재 `pass/fail/no_changes/skipped_changes`는 존재하지만, 더 세밀한 운영 의미가 필요합니다. 특히 table, whitespace, column-width 같은 formatting 수준 차이를 semantic mismatch와 분리해야 합니다. 계획상 목표 taxonomy는 다음 4계층으로 둡니다. + +1. Accept + - `exact_match` + - `normalized_match` + - `formatting_only_match` +2. Review + - `semantic_diff_needs_review` + - `reconstruction_needs_review` + - `preservation_uncertain` +3. Block + - `capability_boundary_blocked` + - `missing_identity` + - `unsafe_edit` + - `ambiguous_target` +4. Error + - `patch_generation_error` + - `roundtrip_verification_error` + - `reconversion_error` + +이 taxonomy는 CLI, result.yaml, 문서, 테스트 설명이 공통으로 써야 합니다. 구현 세부 enum은 더 쪼갤 수 있지만, 문서와 운영 보고는 위 중간 해상도를 기준으로 맞춥니다. --- @@ -246,13 +257,13 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 목표: - 현재 처리 가능한 변경을 capability 기준으로 표에 정리합니다. -- `pages.yaml`, testcase fixture, unit test 사이의 관계를 표준화합니다. +- `pages.yaml`를 실데이터 기준의 reference metadata catalog로 문서화하고, 테스트 전용 부가 필드와 구분해 설명합니다. 작업: 1. `failure_type`, label, severity를 capability/skip reason과 매핑합니다. 2. 각 capability에 대표 fixture를 1~3개씩 지정합니다. -3. `expected_status`가 무엇을 뜻하는지 문서에서 재정의합니다. +3. `expected_status`와 verifier outcome이 taxonomy 어디에 매핑되는지 문서에서 재정의합니다. 4. unsupported 영역을 명시적으로 목록화합니다. 완료 기준: @@ -303,34 +314,37 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 목표: -- table 지원을 넓히기 전에 먼저 boundary를 명확히 합니다. +- table 지원을 넓히기 전에 먼저 boundary를 명확히 하고, verifier가 formatting-level 차이를 과도하게 mismatch로 보지 않도록 정리합니다. 작업: 1. 현재 skip reason을 capability 문서와 1:1로 연결 2. markdown table / raw HTML table / preserved-anchor table을 명확히 분리 3. 어떤 table이 "지원 대상"인지 acceptance contract를 먼저 고정 +4. whitespace-only / column-width-only 차이는 `formatting_only_match`로 분류하는 verifier 규칙을 정의 완료 기준: - table 관련 버그가 들어왔을 때 "미지원"과 "회귀"를 혼동하지 않습니다. +- whitespace-only / column-width-only table diff는 더 이상 semantic mismatch로 집계되지 않습니다. - 새로운 지원 확대는 capability 추가로 표현합니다. ### Stage 5. verifier contract 정리 목표: -- patch quality 문제와 normalization 문제를 분리합니다. +- patch quality 문제와 normalization 문제를 분리하고, proof 계층의 결과 언어를 고정합니다. 작업: -1. `verify_roundtrip()` 결과를 reason code 중심으로 재분류 +1. `verify_roundtrip()` 결과를 Accept / Review / Block / Error taxonomy로 재분류 2. `--lenient`, `--no-normalize`의 의미를 문서와 테스트에서 고정 -3. converter normalization 변화로 인한 false failure를 별도 카테고리로 분리 +3. converter normalization 변화로 인한 false failure를 `normalized_match` 또는 `formatting_only_match`와 구분해 분리 +4. proof 계층에서 result classification과 push eligibility를 연결하는 규칙 정의 완료 기준: -- fail 원인을 `patch mismatch` / `normalization mismatch` / `forward canonicalization drift`로 구분할 수 있습니다. +- fail 및 review 원인을 `semantic review` / `capability block` / `normalization-driven accept` / `system error`로 구분할 수 있습니다. ### Stage 6. push rollout contract 정리 @@ -371,14 +385,14 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 4. Batch manifest tests - `tests/reverse-sync/pages.yaml` - - capability/expected_status/failure_type alignment 검증 + - capability/expected_status/failure_type/result taxonomy alignment 검증 ### 8.2 테스트 원칙 - 새 capability를 추가할 때는 representative fixture를 반드시 함께 추가합니다. - skip reason을 바꿀 때는 result taxonomy 테스트도 함께 갱신합니다. - verifier normalization 변경은 strategy 테스트가 아니라 verifier contract 테스트로 검증합니다. -- pages.yaml은 단순 case catalog가 아니라 regression reporting asset으로 관리합니다. +- `pages.yaml`은 실데이터 기준 reference metadata catalog이며, 테스트에서는 regression reporting asset으로도 활용합니다. ### 8.3 우선 추가할 테스트 @@ -428,26 +442,27 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza ## 11. 승인 기준 -이 계획은 다음 상태가 되면 실행 가능하다고 봅니다. +이 계획은 아래 방향 합의를 기준선으로 삼고 실행합니다. -1. capability registry의 1차 naming이 합의됩니다. -2. planner 분리 범위가 합의됩니다. -3. table을 "당장 더 지원할 것인지"보다 "경계를 먼저 고정할 것인지"에 대한 방향이 합의됩니다. -4. verifier reason taxonomy가 합의됩니다. +1. capability registry naming을 유지합니다. +2. planner / strategy / proof 3계층 분리를 코드 정리의 중심축으로 삼습니다. +3. table은 지원 확대보다 boundary 명시와 verifier normalization 보정을 우선합니다. +4. `pages.yaml`는 실데이터 기준 reference metadata catalog로 보고, 이 점을 과도한 설계 쟁점으로 확대하지 않습니다. +5. verifier taxonomy는 세부적으로 분류합니다. -즉, 코드 착수 전 필요한 것은 "모든 세부 구현의 확정"이 아니라, 앞으로 무엇을 지원 capability로 보고 무엇을 boundary로 둘지에 대한 합의입니다. +즉, 이제 남은 것은 큰 방향의 재논의가 아니라, 위 기준선 아래에서 capability 매핑과 proof taxonomy를 실제 코드/CLI/테스트에 반영하는 일입니다. --- -## 12. 리뷰에서 확인받고 싶은 쟁점 +## 12. 이번 리뷰에서 합의된 방향 -이 PR은 Draft이며, 아래 쟁점에 대한 리뷰를 받고 싶습니다. +이 PR은 Draft이며, 아래 항목은 이번 리뷰에서 방향이 합의된 상태로 간주합니다. -1. capability registry naming이 과한지, 아니면 필요한지 -2. table을 지원 확대보다 경계 명시화부터 하는 우선순위가 맞는지 -3. planner/strategy/proof 3계층 분리가 실제 코드 정리의 중심축으로 적절한지 -4. `pages.yaml`를 계속 manifest+metadata 겸용으로 둘지, 역할을 분리할지 -5. verifier taxonomy를 세분화하는 것이 운영상 도움이 되는지 +1. capability registry naming은 유지합니다. +2. table은 현 수준의 지원을 유지하되, verifier에서 whitespace-only / column-width-only 차이를 mismatch가 아니라 `formatting_only_match`로 판정하는 쪽을 우선합니다. +3. planner / strategy / proof 3계층 분리는 실제 코드 정리의 중심축으로 채택합니다. +4. `pages.yaml`는 reverse-sync 관점에서 reference metadata catalog로 보고, 테스트 전용 부가 필드 때문에 역할 논의를 과도하게 확대하지 않습니다. +5. verifier taxonomy는 운영 판단에 직접 쓰일 수 있도록 세부적으로 분류합니다. --- From ef74208288e4e8a799b384b2981bf1303c805dd1 Mon Sep 17 00:00:00 2001 From: JK Date: Sun, 26 Apr 2026 11:59:57 +0900 Subject: [PATCH 3/4] =?UTF-8?q?confluence-mdx:=20reverse-sync=20visible=20?= =?UTF-8?q?segment=20=EC=84=A4=EA=B3=84=20=EB=B0=A9=ED=96=A5=EC=9D=84=20?= =?UTF-8?q?=EA=B3=84=ED=9A=8D=EC=97=90=20=EB=B0=98=EC=98=81=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit replacement plan에 visible segment 기반 planner 방향을 명시합니다. text-bearing block은 MDX visible model에서 edit sequence를 도출한 뒤, XHTML node edit operation으로 lowering하는 구조를 목표 아키텍처에 추가합니다. 또한 planner 출력, strategy 분리, paragraph/heading 확장, contract/strategy 테스트 계획까지 함께 보강합니다. Co-Authored-By: Claude Opus 4.6 --- ...026-04-25-reverse-sync-replacement-plan.md | 82 ++++++++++++++++--- 1 file changed, 72 insertions(+), 10 deletions(-) diff --git a/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md b/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md index 11e35ad06..4adc62a77 100644 --- a/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md +++ b/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md @@ -103,7 +103,28 @@ reverse-sync를 "모든 MDX 변경을 무조건 Confluence에 반영하는 시 앞으로는 planner와 strategy 실행을 분리해야 합니다. -### 4.4 테스트는 "설계 검증"과 "회귀 방지"를 분리합니다 +### 4.4 visible segment를 planning 언어로 승격합니다 + +현재 `visible_segments.py`는 주로 list 경로의 정밀 판별 보조 모델로만 쓰이지만, 앞으로는 이 개념을 reverse-sync의 planning 언어로 확장하는 방향을 택합니다. + +- MDX 쪽 변경은 가능하면 먼저 visible segment model로 정규화합니다. +- XHTML 쪽 원본 fragment도 visible segment model 또는 그에 대응하는 visible node view로 투영합니다. +- planner는 block diff만으로 바로 patch를 만들지 않고, 우선 `visible edit sequence`를 도출합니다. +- strategy는 이 edit sequence를 그대로 DOM에 적용하지 않고, 안전한 XHTML node edit operation으로 lowering합니다. + +즉 앞으로의 중심 표현은 `plain-text diff` 자체가 아니라 `visible segment -> edit sequence -> node operation`입니다. + +### 4.5 universal emitter를 목표로 하지 않습니다 + +visible segment 중심 설계는 paragraph / heading / list / 일반 inline text 변경에는 잘 맞지만, preserved anchor / parameter-bearing container / raw HTML table / Confluence macro 구조까지 단일 모델로 무리하게 일반화하면 오히려 안전성이 떨어집니다. + +따라서 다음 원칙을 둡니다. + +- text-bearing block은 visible segment 기반 planning을 우선합니다. +- 구조 보존이 중요한 block은 sidecar/template-preserving reconstruction을 fallback 또는 authority로 유지합니다. +- 위험 구조는 `replace_fragment` 또는 `skip`으로 남깁니다. + +### 4.6 테스트는 "설계 검증"과 "회귀 방지"를 분리합니다 예전 문서는 둘을 한 축에 놓는 경향이 있었고, 그 결과 oracle이 흐려졌습니다. 앞으로는 테스트를 다음으로 분리합니다. @@ -112,7 +133,7 @@ reverse-sync를 "모든 MDX 변경을 무조건 Confluence에 반영하는 시 - page fixture 기반 통합 테스트 - batch manifest 기반 상태 리포트 -### 4.5 문서와 코드의 시간축을 분리합니다 +### 4.7 문서와 코드의 시간축을 분리합니다 현황 문서는 현재 코드가 하는 일을 적고, 계획 문서는 앞으로 바꿀 일을 적어야 합니다. 둘을 한 문서에 섞지 않습니다. @@ -164,10 +185,13 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 1. Planner - 변경 블록을 capability 단위로 분류 - 사용 가능한 identity source 결정 + - MDX/XHTML visible model 생성 여부 결정 + - visible edit sequence 도출 - strategy 후보 결정 - skip/fail reason 결정 2. Strategy + - visible edit sequence를 XHTML node edit operation으로 lowering - direct edit - fragment replacement - container reconstruction @@ -183,12 +207,33 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 현재는 이 셋이 `patch_builder.py`와 `reverse_sync_cli.py` 사이에 뒤섞여 있습니다. 앞으로는 책임 경계를 명시해야 합니다. -### 6.2 Capability registry 도입 +### 6.2 Visible segment planner와 XHTML node operation 계층 + +이번 replacement plan에서 새로 채택하는 핵심 방향은, `visible_segments.py`를 list 전용 보조 유틸에 머무르게 두지 않고 planner 계층의 공통 표현으로 승격하는 것입니다. + +목표 파이프라인은 다음과 같습니다. + +1. old/new MDX block -> visible segment model +2. original XHTML fragment -> visible segment model 또는 visible node view +3. 두 model 사이의 `visible edit sequence` 계산 +4. `visible edit sequence`를 XHTML node edit operation으로 lowering +5. 기존 `patch_xhtml()` 계층으로 적용 +6. roundtrip verifier로 proof + +여기서 중요한 점은 다음과 같습니다. + +- `visible edit sequence`는 곧바로 DOM mutation이 아닙니다. +- 중간 lowering 단계에서 capability boundary, sidecar identity, template preservation 필요 여부를 함께 판단해야 합니다. +- 결과 operation은 현재 patch 체계와 호환되는 `modify`, `delete`, `insert`, `replace_fragment` 계열로 귀결되어도 됩니다. + +즉 이 계획은 apply 계층을 버리는 것이 아니라, patch 생성 전의 정책 언어를 visible segment 중심으로 재구성하는 계획입니다. + +### 6.3 Capability registry 도입 다음과 같은 capability 단위를 문서와 코드 양쪽에 명시적으로 도입합니다. -- `paragraph_text_edit` -- `heading_text_edit` +- `paragraph_visible_segment_edit` +- `heading_visible_segment_edit` - `inline_whitespace_adjustment` - `clean_block_replace` - `container_body_reconstruction` @@ -206,7 +251,7 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza - 대표 fixture - regression test location -### 6.3 Result taxonomy 표준화 +### 6.4 Result taxonomy 표준화 현재 `pass/fail/no_changes/skipped_changes`는 존재하지만, 더 세밀한 운영 의미가 필요합니다. 특히 table, whitespace, column-width 같은 formatting 수준 차이를 semantic mismatch와 분리해야 합니다. 계획상 목표 taxonomy는 다음 4계층으로 둡니다. @@ -283,15 +328,20 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza - change - mapping source - sidecar source + - mdx visible model + - xhtml visible model 또는 visible node view + - visible edit sequence - capability - chosen strategy - skip reason -2. strategy dispatcher 인터페이스 정의 -3. 기존 `build_patches()`는 planner + strategy executor orchestration으로 축소 +2. `visible edit sequence`를 표준 planning 산출물로 고정 +3. strategy dispatcher 인터페이스 정의 +4. 기존 `build_patches()`는 planner + strategy executor orchestration으로 축소 완료 기준: - 새 회귀 수정 시 `build_patches()` 본체에 직접 if/elif를 추가하지 않고, planner rule 또는 strategy handler 수정으로 끝낼 수 있습니다. +- planner 출력만 보면 "어떤 visible 변화가 어떤 node operation 후보로 내려갔는지"를 설명할 수 있습니다. ### Stage 3. list / preserved anchor / container 전략 분리 @@ -305,10 +355,17 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 2. preserved-anchor template rewrite 전략 3. parameter-bearing container reconstruction 전략 +세부 방향: + +- list는 현재 `visible_segments.py`를 그대로 출발점으로 삼되, 결과를 `visible edit sequence`로 명시화합니다. +- paragraph / heading은 새 visible model extractor를 도입해 plain-text transfer보다 planner 기반 lowering을 우선 검토합니다. +- preserved anchor / container는 visible planning 결과만으로 충분하지 않은 경우 template-preserving reconstruction으로 안전하게 내려갑니다. + 완료 기준: - 각 전략이 독립 테스트 파일과 fixture 세트를 가집니다. - `patch_builder.py`는 분기 지점만 남고 세부 알고리즘을 직접 품지 않습니다. +- text-bearing block에 대해서는 "MDX visible model -> edit sequence -> node operation" 흐름을 설명할 수 있습니다. ### Stage 4. table 경계 명시화 @@ -371,10 +428,12 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 1. Contract tests - sidecar schema - planner classification + - visible edit sequence schema / invariants - result taxonomy 2. Strategy tests - list visible segment + - paragraph/heading visible segment lowering - preserved anchor rewrite - container reconstruction - table classification @@ -399,8 +458,9 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 1. planner classification snapshot test 2. table skip reason classification test 3. list visible segment capability fixture set -4. verifier reason-code split test -5. result.yaml schema test +4. paragraph/heading visible edit sequence snapshot test +5. verifier reason-code split test +6. result.yaml schema test --- @@ -449,6 +509,7 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 3. table은 지원 확대보다 boundary 명시와 verifier normalization 보정을 우선합니다. 4. `pages.yaml`는 실데이터 기준 reference metadata catalog로 보고, 이 점을 과도한 설계 쟁점으로 확대하지 않습니다. 5. verifier taxonomy는 세부적으로 분류합니다. +6. visible segment model을 planner 계층의 중심 표현으로 승격하되, apply 계층은 patch/DOM/sidecar 체계를 유지합니다. 즉, 이제 남은 것은 큰 방향의 재논의가 아니라, 위 기준선 아래에서 capability 매핑과 proof taxonomy를 실제 코드/CLI/테스트에 반영하는 일입니다. @@ -463,6 +524,7 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 3. planner / strategy / proof 3계층 분리는 실제 코드 정리의 중심축으로 채택합니다. 4. `pages.yaml`는 reverse-sync 관점에서 reference metadata catalog로 보고, 테스트 전용 부가 필드 때문에 역할 논의를 과도하게 확대하지 않습니다. 5. verifier taxonomy는 운영 판단에 직접 쓰일 수 있도록 세부적으로 분류합니다. +6. visible segment 기반 `edit sequence -> XHTML node operation` 흐름은 text-bearing block의 목표 설계로 채택하되, sidecar/template-preserving fallback을 함께 유지합니다. --- From 003118735be553be127eb9bc5581374b138b0ee6 Mon Sep 17 00:00:00 2001 From: JK Date: Sun, 26 Apr 2026 13:59:20 +0900 Subject: [PATCH 4/4] =?UTF-8?q?confluence-mdx:=20reverse-sync=20=EA=B3=84?= =?UTF-8?q?=ED=9A=8D=20=EB=AC=B8=EC=84=9C=EC=97=90=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=B6=84=ED=95=B4=EC=95=88=EC=9D=84=20=EB=B3=B4=EA=B0=95?= =?UTF-8?q?=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit replacement plan에 visible segment planner 기준의 구체적 코드 분해안을 추가합니다. planner/lowering/strategy 모듈 분리, 초기 함수 시그니처, 테스트 파일 배치안을 문서화해 구현 착수 전 책임 경계를 더 명확히 정리합니다. Co-Authored-By: Claude Opus 4.6 --- ...026-04-25-reverse-sync-replacement-plan.md | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md b/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md index 4adc62a77..3526c41c6 100644 --- a/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md +++ b/confluence-mdx/docs/plans/2026-04-25-reverse-sync-replacement-plan.md @@ -343,6 +343,88 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza - 새 회귀 수정 시 `build_patches()` 본체에 직접 if/elif를 추가하지 않고, planner rule 또는 strategy handler 수정으로 끝낼 수 있습니다. - planner 출력만 보면 "어떤 visible 변화가 어떤 node operation 후보로 내려갔는지"를 설명할 수 있습니다. +초기 모듈 분해 초안: + +- `confluence-mdx/bin/reverse_sync/planner_types.py` + - `VisibleEdit` + - `VisibleEditSequence` + - `PlanningContext` + - `PlanningDecision` +- `confluence-mdx/bin/reverse_sync/visible_planner.py` + - `plan_visible_edit_sequence(...) -> VisibleEditSequence` + - `plan_change(...) -> PlanningDecision` +- `confluence-mdx/bin/reverse_sync/node_operations.py` + - `NodeOperation` + - `NodeOperationSequence` +- `confluence-mdx/bin/reverse_sync/operation_lowering.py` + - `lower_visible_edits_to_node_operations(...) -> NodeOperationSequence` + - `lower_node_operations_to_patches(...) -> list[dict[str, str]]` +- `confluence-mdx/bin/reverse_sync/strategy_dispatcher.py` + - `choose_strategy(...) -> str` + - `execute_strategy(...) -> list[dict[str, str]]` +- 전략 하위 모듈 + - `confluence-mdx/bin/reverse_sync/strategies/list_strategy.py` + - `confluence-mdx/bin/reverse_sync/strategies/text_block_strategy.py` + - `confluence-mdx/bin/reverse_sync/strategies/preserved_anchor_strategy.py` + - `confluence-mdx/bin/reverse_sync/strategies/container_strategy.py` + - `confluence-mdx/bin/reverse_sync/strategies/table_strategy.py` + +초기 함수 시그니처 초안: + +```python +@dataclass(frozen=True) +class VisibleEdit: + kind: Literal[ + "keep", + "insert_text", + "delete_text", + "replace_text", + "split_segment", + "merge_segment", + "formatting_only", + ] + old_segment_ids: tuple[str, ...] = () + new_segment_ids: tuple[str, ...] = () + old_text: str = "" + new_text: str = "" + meta: dict[str, Any] = field(default_factory=dict) + + +def plan_visible_edit_sequence( + *, + old_mdx: str, + new_mdx: str, + xhtml_fragment: str, + capability: str, +) -> VisibleEditSequence: + ... + + +def plan_change(change: BlockChange, context: PlanningContext) -> PlanningDecision: + ... + + +def lower_visible_edits_to_node_operations( + sequence: VisibleEditSequence, + context: PlanningContext, +) -> NodeOperationSequence: + ... + + +def lower_node_operations_to_patches( + operations: NodeOperationSequence, + context: PlanningContext, +) -> list[dict[str, str]]: + ... +``` + +이 초안의 의도는 다음과 같습니다. + +- planner 출력은 patch dict가 아니라 `VisibleEditSequence`입니다. +- lowering 계층은 visible edit와 DOM/node edit를 연결합니다. +- strategy 계층은 capability boundary와 fallback 선택을 담당합니다. +- 최종 apply는 기존 `xhtml_patcher.py`를 계속 사용합니다. + ### Stage 3. list / preserved anchor / container 전략 분리 목표: @@ -462,6 +544,39 @@ pass/fail이 실제 patch 품질 문제인지, forward converter의 canonicaliza 5. verifier reason-code split test 6. result.yaml schema test +### 8.4 초기 테스트 파일 배치안 + +- `confluence-mdx/tests/test_visible_planner.py` + - planner classification snapshot + - paragraph/heading visible edit sequence snapshot +- `confluence-mdx/tests/test_operation_lowering.py` + - visible edit sequence -> node operation lowering + - node operation -> patch emission +- `confluence-mdx/tests/test_strategy_dispatcher.py` + - capability별 strategy 선택 + - fallback / skip reason 결정 +- `confluence-mdx/tests/test_list_strategy.py` + - 기존 list visible segment fixture 재사용 +- `confluence-mdx/tests/test_text_block_strategy.py` + - paragraph / heading text-bearing block fixture +- `confluence-mdx/tests/test_preserved_anchor_strategy.py` + - preserved anchor fallback / reconstruction 경계 +- `confluence-mdx/tests/test_container_strategy.py` + - parameter-bearing container reconstruction 경계 +- `confluence-mdx/tests/test_table_strategy.py` + - table capability boundary / skip reason / formatting-only verifier 연계 + +fixture 배치 초안: + +- `confluence-mdx/tests/testcases/visible-planner/paragraph-*` +- `confluence-mdx/tests/testcases/visible-planner/heading-*` +- `confluence-mdx/tests/testcases/visible-planner/list-*` +- `confluence-mdx/tests/testcases/strategies/preserved-anchor-*` +- `confluence-mdx/tests/testcases/strategies/container-*` +- `confluence-mdx/tests/testcases/strategies/table-*` + +이 배치는 planner, lowering, strategy, proof를 테스트 파일 수준에서도 분리하기 위한 최소 단위 제안입니다. + --- ## 9. 문서 구조 계획