Skip to content

fix(reverse_sync): code span 뒤 공백이 소실되는 문제를 수정합니다#979

Merged
jk-kim0 merged 5 commits intomainfrom
fix/reverse-sync-code-span-trailing-space
Apr 5, 2026
Merged

fix(reverse_sync): code span 뒤 공백이 소실되는 문제를 수정합니다#979
jk-kim0 merged 5 commits intomainfrom
fix/reverse-sync-code-span-trailing-space

Conversation

@jk-kim0
Copy link
Copy Markdown
Contributor

@jk-kim0 jk-kim0 commented Apr 3, 2026

Summary

_apply_text_changes의 노드 간 gap whitespace 처리 로직을 전면 개편합니다.

기존에는 gap 축소 시 현재 노드의 leading whitespace를 전부 제거하는 단순 로직이었으나, 이로 인해 두 가지 버그가 발생했습니다:

  1. code span 뒤 공백 소실: <code>{{..}}</code><span> 안의</span> 구조에서 gap이 2→1로 축소될 때, <span>의 leading이 전부 제거되어 <span>안의</span>가 됨
  2. 마크업 경계 포함 gap 미처리: <strong>Secure </strong> : 구조에서 gap에 </strong> 경계가 포함되어 gap_old.isspace() 조건에 진입하지 못하고, trailing space가 잔존

변경 사항

  • _compute_gap_whitespace_delta: gap 변경에서 공통 토큰(마크업 등)을 제외한 공백 길이 변화량만 분리하는 헬퍼 추출
  • _redistribute_gap_whitespace: gap 축소/확장/삭제 시 current leading ↔ previous trailing 간 재분배 헬퍼 추출
  • prev_replaced / prev_eff_end 추적으로 다중 노드 간 gap 분배 지원
  • trailing_in_range로 이미 diff 처리된 영역을 gap 계산에서 제외

테스트

  • 테스트케이스 883654669 (Slack DM 연동) 추가
  • 798064641 golden test (bold 라벨 뒤 colon spacing)
  • gap 축소/확장/삭제/mixed 시나리오 단위 테스트 6건

Test plan

  • make test-reverse-sync-bugs-one TEST_ID=883654669 PASS
  • make test-reverse-sync-bugs — 43 passed, 0 failed
  • make test-convert — 21 passed
  • make test-reverse-sync — 43 passed
  • make test-skeleton — 18 passed
  • make test-image-copy — 1 passed
  • make test-xhtml-diff — 15 passed
  • make test-byte-verify — 21 passed
  • make test-render — 21 passed
  • pytest — 959 passed (1 pre-existing failure)

🤖 Generated with Claude Code

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
querypie-docs Ready Ready Preview, Comment Apr 4, 2026 5:09pm

Request Review

@jk-kim0
Copy link
Copy Markdown
Contributor Author

jk-kim0 commented Apr 4, 2026

[debate-review][sha:bee8454fbfba5b34451cf65f94a769e9601feb34] Consensus reached after 2 rounds.

No actionable issues remain.

@jk-kim0
Copy link
Copy Markdown
Contributor Author

jk-kim0 commented Apr 4, 2026

[debate-review][sha:0f41c45496e5bb8f5999cf30282f4e719a8c8ac8] Consensus reached after 3 rounds.

Debate Summary

  • isu_001 [withdrawn] gap이 이전 노드의 trailing 공백과 현재 노드의 leading 공백에 걸쳐 있을 때, len(gap_old) > len(leading) 조건으로 leading을 전부 제거하면 trailing_in_range가 trailing도 흡수하여 총 공백이 0이 되는 엣지 케이스가 존재합니다. 예: X 안의에서 gap 2→1 축소 시 두 노드 모두 공백이 제거됩니다.

Withdrawn Findings

  • confluence-mdx/bin/reverse_sync/xhtml_patcher.py:684 - gap이 이전 노드의 trailing 공백과 현재 노드의 leading 공백에 걸쳐 있을 때, len(gap_old) > len(leading) 조건으로 leading을 전부 제거하면 trailing_in_range가 trailing도 흡수하여 총 공백이 0이 되는 엣지 케이스가 존재합니다. 예: X 안의에서 gap 2→1 축소 시 두 노드 모두 공백이 제거됩니다.
    Reason: 현재 코드와 base 코드에서 동일하게 재현되는 기존 문제라서 이번 PR diff가 도입한 신규 이슈로 볼 수 없습니다.

jk-kim0 added a commit that referenced this pull request Apr 4, 2026
## Summary

- `navigable_string_as_markdown()`에서 `re.sub(r'\s+', ' ', text)` 연속 공백
정규화를 제거합니다
- HTML과 Markdown/MDX 모두 렌더링 시 연속 공백을 단일 공백으로 표시하므로, FC 변환 단계의 정규화는
불필요합니다
- 이 정규화는 XHTML 원본의 공백 정보를 손실시켜, reverse-sync 파이프라인에서 `collapse_ws` 보상
로직과 gap 공백 축소 등 불필요한 복잡도를 유발합니다 (PR #979 참조)

## 변경 내용

- `bin/converter/context.py`: 연속 공백 정규화 2줄 제거
- 7개 테스트케이스의 `expected.mdx` 및 `expected.roundtrip.json` 업데이트

## 이력

이 정규화는 2025-07-25 PR #34 (`a0da79dd`)에서 `as_markdown()` 함수 추출 시 방어적으로
추가된 것으로, 특정 버그 수정이 아닌 HTML 텍스트 노드의 일반적인 공백 정규화 목적이었습니다.

## Test plan

- [x] 변환 테스트 21/21 통과
- [x] pytest 938 passed
- [x] reverse-sync 통합 테스트 42/42 통과

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
jk-kim0 and others added 2 commits April 4, 2026 20:35
_apply_text_changes의 gap whitespace 축소 로직에서, gap 전체가 노드의
leading whitespace인 경우(gap_old <= leading) 축소된 gap만큼만 leading을
조정하도록 변경합니다. 기존에는 gap이 축소되면 leading을 전부 제거하여,
<code>{{..}}</code><span>  안의</span> 구조에서 span 선행 공백이 소실되었습니다.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
<code>{{..}}</code><span>  안의</span> 구조에서 gap이 2→1로 축소될 때
leading이 전부 제거되는 버그를 재현하는 테스트케이스입니다.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jk-kim0 jk-kim0 force-pushed the fix/reverse-sync-code-span-trailing-space branch from 0f41c45 to 25b9f57 Compare April 4, 2026 11:35
FC가 이중 공백을 보존하므로 original.mdx, improved.mdx의
`{{..}}` 뒤 공백을 1→2로 맞춥니다.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jk-kim0
Copy link
Copy Markdown
Contributor Author

jk-kim0 commented Apr 4, 2026

[debate-review][sha:5abda6e94b92c4b0e025ab504a0380d60d87a731] Consensus reached after 2 rounds.

No actionable issues remain.

@jk-kim0 jk-kim0 changed the title fix(reverse_sync): code span 뒤 공백이 소실되는 문제를 수정합니다 [debate: failed] fix(reverse_sync): code span 뒤 공백이 소실되는 문제를 수정합니다 Apr 4, 2026
@jk-kim0 jk-kim0 changed the title [debate: failed] fix(reverse_sync): code span 뒤 공백이 소실되는 문제를 수정합니다 fix(reverse_sync): code span 뒤 공백이 소실되는 문제를 수정합니다 Apr 4, 2026
이전 노드 trailing + 현재 노드 leading에 걸친 gap 변경 시:
- 축소: leading 우선 흡수 → 부족하면 prev trailing에서 추가 흡수
- 확장: prev trailing에 공백 추가
- trailing_in_range 이중 적용 방지를 위해 prev_eff_end 추적

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: 토론 리뷰 결과 반영 (라운드 1)

- isu_001 (confluence-mdx/bin/reverse_sync/xhtml_patcher.py:704): 새 gap 분배 로직은 gap_old/gap_new가 공백만으로 이루어진 경우에만 leading을 줄입니다. 그래서 **Secure** :처럼 마크업 토큰과 공백이 함께 바뀌는 케이스에서는 앞 공백이 그대로 남아 reverse-sync/798064641가 **Secure**:대신 **Secure** :로 round-trip 되며 현재 CI의 Test Confluence MDX Converter가 실제로 이 회귀로 실패합니다.
@jk-kim0
Copy link
Copy Markdown
Contributor Author

jk-kim0 commented Apr 4, 2026

[debate-review][sha:ded30dfddef259e92723ebe53fba706e2b57511f] Consensus reached after 4 rounds.

Debate Summary

  • isu_001 [accepted] 새 gap 분배 로직은 gap_old/gap_new가 공백만으로 이루어진 경우에만 leading을 줄입니다. 그래서 Secure :처럼 마크업 토큰과 공백이 함께 바뀌는 케이스에서는 앞 공백이 그대로 남아 reverse-sync/798064641가 Secure:대신 Secure :로 round-trip 되며 현재 CI의 Test Confluence MDX Converter가 실제로 이 회귀로 실패합니다.
  • isu_002 [accepted] gap 삭제(line 689-701)와 gap 축소(line 706-717) 분기에 leading 줄이기→prev_replaced trailing 흡수 로직이 완전히 동일하게 중복됩니다. 헬퍼 함수로 추출하면 CI 실패(isu_001)와 같은 분기별 불일치 버그를 예방하고, 향후 한쪽만 수정되는 위험을 제거할 수 있습니다.

Applied Fixes

  • confluence-mdx/bin/reverse_sync/xhtml_patcher.py:704 - (reported by codex, applied by codex) 새 gap 분배 로직은 gap_old/gap_new가 공백만으로 이루어진 경우에만 leading을 줄입니다. 그래서 Secure :처럼 마크업 토큰과 공백이 함께 바뀌는 케이스에서는 앞 공백이 그대로 남아 reverse-sync/798064641가 Secure:대신 Secure :로 round-trip 되며 현재 CI의 Test Confluence MDX Converter가 실제로 이 회귀로 실패합니다.
  • confluence-mdx/bin/reverse_sync/xhtml_patcher.py:706 - (reported by cc, applied by None) gap 삭제(line 689-701)와 gap 축소(line 706-717) 분기에 leading 줄이기→prev_replaced trailing 흡수 로직이 완전히 동일하게 중복됩니다. 헬퍼 함수로 추출하면 CI 실패(isu_001)와 같은 분기별 불일치 버그를 예방하고, 향후 한쪽만 수정되는 위험을 제거할 수 있습니다.

jk-kim0 added a commit to jk-kim0/skills-jk that referenced this pull request Apr 5, 2026
## 문제현상

debate-review 종료 시 `update_pr_status`가 PR title 앞에 `[debate:
consensus]`, `[debate: failed]` 등의 label prefix를 자동으로 붙임. 외부
repo(querypie/querypie-docs#979)의 PR 제목까지 임의 변경하는 사고 발생.

## 구현내용

- `follow_through.py`: `update_pr_status()` 함수, `_OUTCOME_LABELS`,
`_DEBATE_LABEL_RE` 제거
- `cli.py`: `update-pr-status` subcommand 제거
- `orchestrator.py`: `_follow_through()`에서 `update_pr_status` 호출 제거,
`SubprocessDebateCli.update_pr_status()` 메서드 제거
- `test_follow_through.py`: `TestUpdatePrStatus` 클래스 및 CLI integration
test 제거
- `test_orchestrator.py`: `FakeCli.update_pr_status` 및 관련 assertions 제거

정규화 코드(`_extract_json_from_text`, `_normalize_cross_verifications`,
`_normalize_withdrawals`)는 PR #183에서 별도로 다룹니다.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@jk-kim0 jk-kim0 merged commit a3ba59c into main Apr 5, 2026
7 checks passed
@jk-kim0 jk-kim0 deleted the fix/reverse-sync-code-span-trailing-space branch April 5, 2026 10:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant