Skip to content

confluence-mdx: reverse-sync local proof를 엄격하게 검증합니다#1030

Merged
jk-kim0 merged 1 commit into
mainfrom
jk/refactor-reverse-sync-local-proof
Jul 27, 2026
Merged

confluence-mdx: reverse-sync local proof를 엄격하게 검증합니다#1030
jk-kim0 merged 1 commit into
mainfrom
jk/refactor-reverse-sync-local-proof

Conversation

@jk-kim0

@jk-kim0 jk-kim0 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

#1029에서 고정한 remote snapshot과 PUT transaction 위에, MDX 변경으로 만든 candidate XHTML이 실제 발행 가능한지 증명하는 strict local proof를 추가합니다.

  • Markdown table의 cell 바깥 padding과 separator dash 길이만 안전한 source formatting 차이로 허용하는 reverse-sync-equivalence-v1 typed canonical model을 추가합니다.
  • 변경하지 않은 top-level fragment, separator, document envelope를 byte-equal로 유지하는 online patch renderer를 추가합니다.
  • source identity, base parity, intent completeness, artifact integrity, Storage XHTML well-formedness, preservation, semantic round-trip, determinism, idempotency, dependency의 10개 gate를 manifest schema v2에 결합합니다.
  • diagnostic pass와 발행 가능한 verified_local을 분리하고, legacy pass가 잘못 push_eligible로 표시되어도 단일·배치 발행을 차단합니다.
  • OpenSpec 2.5 task와 strict proof 검증 근거를 갱신합니다.

Impact

  • online push는 10개 gate를 모두 통과한 verified_local manifest만 발행 후보로 인정합니다.
  • 16개 golden page를 remote PUT 없는 shadow online mode로 검증했으며, 4개는 verified_local, 12개는 visible whitespace, unresolved link, raw HTML table mutation 등의 근거로 fail-closed했습니다.
  • 승인된 canary page가 없어 remote PUT과 remote canary는 실행하지 않았습니다.

Test plan

  • cd confluence-mdx && venv/bin/python3 -m pytest -q — 1054 passed, 2 skipped
  • cd confluence-mdx/tests && make test-convert — 21 passed
  • cd confluence-mdx/tests && make test-reverse-sync — golden 16 passed, regression 43 passed
  • cd confluence-mdx/tests && make test-byte-verify — fast/splice 각각 21/21 passed
  • openspec validate complete-reverse-sync --strict
  • git diff --check

Related tickets & links

🤖 Generated with Codex

@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
querypie-docs Canceled Canceled Comment Jul 27, 2026 6:51am

Request Review

## Summary
MDX 변경을 Confluence Storage XHTML로 반영하기 전에 typed equivalence와 보존 증거를 모두 검증하도록 local proof 계약을 강화합니다.

- Markdown table의 안전한 source formatting 차이만 허용하는 versioned canonical model을 추가합니다.
- unchanged fragment와 document envelope를 byte-preserving하는 online patch renderer를 추가합니다.
- well-formedness, preservation, determinism, idempotency를 포함한 10개 필수 gate를 manifest에 결합합니다.
- diagnostic pass와 verified_local을 분리하고 legacy pass의 발행을 차단합니다.
- OpenSpec task와 golden shadow 검증 결과를 갱신합니다.

## Test plan
- [x] 전체 Python test 1054 passed, 2 skipped
- [x] make test-convert 21 passed
- [x] make test-reverse-sync golden 16 passed, regression 43 passed
- [x] make test-byte-verify fast/splice 각각 21/21 passed
- [x] openspec validate complete-reverse-sync --strict
- [x] git diff --check

🤖 Generated with Codex

Co-Authored-By: Atlas <atlas@jk.agent>
@jk-kim0
jk-kim0 force-pushed the jk/refactor-reverse-sync-local-proof branch from e385566 to 7d71336 Compare July 27, 2026 06:47
@jk-kim0
jk-kim0 merged commit 0b96749 into main Jul 27, 2026
6 of 7 checks passed
@jk-kim0
jk-kim0 deleted the jk/refactor-reverse-sync-local-proof branch July 27, 2026 06:50
jk-kim0 added a commit that referenced this pull request Jul 27, 2026
## Summary
MDX 변경이 올바른 Confluence page와 dependency를 대상으로 하는지 증명한 뒤에만 Storage XHTML
candidate와 push manifest를 생성합니다.

- page ID, `confluenceUrl`, `src/content/ko/**.mdx` path,
`pages.qm.yaml` row를 하나의 source identity로 결합합니다.
- `page.v1.yaml` provenance를 classification-only evidence로 사용하여
`stale_original_mdx`와 `forward_converter_drift`를 구분합니다.
- 새 attachment reference를 Confluence v2 attachment catalog 전체
pagination으로 검증합니다.
- 새 internal link를 유일한 page ID/path로 resolve하고 `ac:link`/`ri:page`
macro로 렌더링합니다.
- attachment와 internal page dependency를 local proof에 hash-bound
evidence로 기록합니다.
- publisher가 required attachment filename과 linked page ID/status/title을
PUT 직전에 다시 확인합니다.
- 잘못된 title/H1, unresolved/ambiguous link, missing attachment,
unsupported external image/raw link attribute는 fail-closed로 차단합니다.
- OpenSpec P0 base parity/dependency task와 durable contract를 현재 구현에 맞게
갱신합니다.

## Safety boundary
- 기존 page에 존재하는 attachment의 새 reference만 지원합니다.
- attachment upload/update/delete, page title update, active draft
reconciliation은 수행하지 않습니다.
- 이 PR은 remote PUT이나 canary update를 실행하지 않습니다.

## Test plan
- [x] 전체 Python test: 1085 passed, 2 skipped
- [x] reverse-sync Python test: 762 passed
- [x] `make test-convert`: 21 passed
- [x] `make test-reverse-sync`: golden 16 passed, regression fixture 통과
- [x] `make test-byte-verify`: fast/splice 각각 21/21 passed
- [x] `openspec validate complete-reverse-sync --strict`
- [x] `git diff --check`

## Stack
- Base: #1030
- Foundation: #1029
- 이 PR은 #1030 merge 후 base를 `main`으로 변경할 수 있습니다.

🤖 Generated with Codex

---------

Co-authored-by: Atlas <atlas@jk.agent>
jk-kim0 added a commit that referenced this pull request Jul 27, 2026
## Summary
push-eligible planning에서 provenance가 없는 normalized text prefix target
선택을 제거합니다.

- offline diagnostic fixture는 기존 list text fallback을 유지합니다.
- online verify는 최초 candidate, determinism 재생성, idempotency 재계획 모두
`allow_text_identity_fallback=false`를 강제합니다.
- provenance mapping을 찾지 못하면 `no_mapping`으로 기록하고 `intent_complete`
gate에서 block합니다.
- tool version을 `reverse-sync-cli-v4`로 올려 과거 manifest의 재검증을 요구합니다.
- OpenSpec planner/renderer migration boundary와 task를 갱신합니다.

## Why
normalized text prefix는 중복 list나 유사 content에서 다른 XHTML fragment를 선택할 수
있습니다. 진단 경로에서는 fixture migration을 위해 유지할 수 있지만, remote update를 허용하는
proof의 target identity로 사용할 수는 없습니다.

## Test plan
- [x] 전체 Python test: 1086 passed, 2 skipped
- [x] reverse-sync Python test: 763 passed
- [x] `make test-reverse-sync`: golden 16 passed, regression fixture 통과
- [x] `make test-byte-verify`: fast/splice 각각 21/21 passed
- [x] `openspec validate complete-reverse-sync --strict`
- [x] `git diff --check`

## Stack
- Base: #1031
- Strict proof: #1030
- Publisher foundation: #1029
- 이 PR은 선행 PR merge 후 base를 순차적으로 `main`으로 변경할 수 있습니다.

🤖 Generated with Codex

---------

Co-authored-by: Atlas <atlas@jk.agent>
jk-kim0 added a commit that referenced this pull request Jul 27, 2026
## Summary
reverse-sync push 경로가 `build_patches()`의 raw dict를 직접 신뢰하지 않도록 typed
planning과 renderer boundary를 도입합니다.

- `capabilities.py`에 capability ID, support level, renderer owner,
required proof, block reason registry를 추가합니다.
- `operations.py`에 immutable `ChangeIntent`, `TargetIdentity`,
`PatchOperation`, `PatchPlan` schema v2를 추가합니다.
- `planner.py`가 기존 `build_patches()`를 `legacy-patch-builder-v2` adapter로
감싸고 raw dict를 typed plan에 격리합니다.
- MDX content hash와 line range가 모두 일치하는 유일한 sidecar provenance를
operation target과 결합합니다.
- exact intent provenance가 없거나 하나의 intent가 여러 operation에 대응하면
`intent_complete`를 허용하지 않습니다.
- push 경로의 `raw_html_table_edit`와 `unknown_macro_mutation`을
`unsupported_capability`로 차단합니다.
- source formatting용 empty block이 `<p></p>` insert mutation으로 바뀌지 않도록
제거합니다.
- `render_patch_plan_preserving()`이 target fragment hash, sidecar MDX
hash, line range를 base와 다시 비교한 뒤에만 raw renderer input을 복원합니다.
- CLI와 local proof가 raw patch dict 대신 typed plan을 소비하도록 전환하고 tool
version을 `reverse-sync-cli-v5`로 올립니다.

## OpenSpec
- 기준 change: `openspec/changes/complete-reverse-sync`
- 완료: P1 typed `PatchPlan`/operation 및 raw patch boundary
- 계속 남는 범위: `patch_builder.py`의 capability별 strategy 추출, visible model
확장, 모든 table/macro skip reason의 capability 표준화
- 이 PR은 현재 migration adapter의 완료 범위를 design과 tasks에 정확히 기록합니다.

## Safety impact
- legacy builder가 target을 제안하더라도 strict plan의 exact provenance와 일치하지 않으면
renderer에서 실행하지 않습니다.
- 검증 후 target identity가 바뀌거나 다른 base에 plan을 적용하면
`PatchApplicationError`로 차단합니다.
- blocked capability는 candidate에 일부 적용하지 않고 stable reason code로 남깁니다.
- offline diagnostic은 기존 text fallback과 renderer 호환성을 유지하지만 push
eligibility를 부여하지 않습니다.

## Test plan
- [x] 전체 Python test: 1096 passed, 2 skipped
- [x] reverse-sync Python test: 773 passed
- [x] `make test-convert`: 21 passed
- [x] `make test-reverse-sync`: golden 16 passed, regression 43 passed
- [x] `make test-byte-verify`: fast/splice 각각 21/21 passed
- [x] `openspec validate complete-reverse-sync --strict`
- [x] `git diff --check`
- [x] Python `compileall`

## Stack
- Base: #1032
- Input/dependency gates: #1031
- Strict proof: #1030
- Publisher foundation: #1029
- 선행 PR merge 후 base를 순차적으로 `main`으로 변경할 수 있습니다.

🤖 Generated with Codex

Co-Authored-By: Atlas <atlas@jk.agent>

---------

Co-authored-by: Atlas <atlas@jk.agent>
jk-kim0 added a commit that referenced this pull request Jul 27, 2026
## Summary
검증된 reverse-sync 실행을 나중에 발행할 때 latest pointer가 아니라 명시적인 immutable
manifest만 선택하도록 publish 경계를 완성합니다.

- `reverse-sync push --manifest <manifest.json>` 경로를 추가하고 online verify와
분리합니다.
- `_do_push()`가 keyword-only `manifest_path`를 반드시 받게 하고
`reverse-sync.manifest.path` fallback을 제거합니다.
- manifest/tool/policy/artifact hash와 required gate를 인증 및 원격 접근 전에 다시
검증합니다.
- PatchPlan schema v2를 요구하고 직렬화된 `intent_complete`를 신뢰하지 않고 intent별
executable operation coverage를 재계산합니다.
- `local-proof.json`의 base/candidate/plan hash와 gate 결과를 manifest와 교차
검증합니다.
- `--manifest`와 MDX/branch/diagnostic 옵션을 상호 배타적으로 만들고 confirmation에 run
ID, page/version, change/operation 수, candidate hash를 표시합니다.
- `--yes`는 confirmation만 생략하며 무결성·proof·preflight·postcondition gate는
그대로 실행합니다.

## OpenSpec
- 기준 change: `openspec/changes/complete-reverse-sync`
- 완료: explicit run/manifest publish 입력과 latest pointer fallback 제거
- 보강: PatchPlan coverage 재계산 및 local proof–manifest binding 검증
- 외부 Confluence canary/PUT은 이 PR 검증 범위에서 수행하지 않았습니다.

## Safety impact
- 오래되거나 다른 실행을 latest pointer로 잘못 발행할 수 없습니다.
- schema v1 검증 결과는 `stale_verification`으로 차단합니다.
- hash가 자기 artifact와 결합되지 않은 local proof와 불완전하거나 중복 coverage인 plan은 원격
page를 읽기 전에 차단합니다.
- 기존 단일/배치 online verify 흐름도 생성된 explicit manifest 경로를 publisher에 전달합니다.

## Test plan
- [x] 전체 Python test: 1106 passed, 2 skipped
- [x] reverse-sync Python test: 783 passed
- [x] `make test-convert`: 21 passed
- [x] `make test-reverse-sync`: golden 16 passed, regression 43 passed
- [x] `make test-byte-verify`: fast/splice 각각 21/21 passed
- [x] `openspec validate complete-reverse-sync --strict`
- [x] `git diff --check`
- [x] Python `compileall`

## Stack
- Base: #1033
- Strict provenance identity: #1032
- Input/dependency gates: #1031
- Strict proof: #1030
- Publisher foundation: #1029
- 선행 PR merge 후 base를 순차적으로 `main`으로 변경할 수 있습니다.

🤖 Generated with Codex

Co-Authored-By: Atlas <atlas@jk.agent>

Co-authored-by: Codex <noreply@openai.com>
jk-kim0 added a commit that referenced this pull request Jul 27, 2026
## Summary
reverse-sync branch batch의 page별 결과와 전체 partial success를 자동화 도구가 안정적으로
판별할 수 있는 versioned report로 만듭니다.

- `BatchReport`와 `reverse-sync-batch-report` schema v1을 추가합니다.
- branch `--json` 출력이 raw array 대신 command, branch, outcome, exit code,
summary, page별 result를 가진 object를 반환합니다.
- page별 local/publish 상태를 stable `batch_status`와 reason code로 정규화합니다.
- 성공과 실패가 섞이면 `partial_success`, 실패만 있으면 `failed`, 전부 통과하면 `success`로
분류합니다.
- partial/failed는 exit 1, success와 사용자 cancellation은 exit 0으로 고정합니다.
- postcondition failure 뒤 남은 verified page를 `not_attempted`로 표시하고
`resume_manifests`에 explicit manifest 경로를 기록합니다.
- conflict, publish error, cancellation에도 stable reason code를 기록합니다.
- text 출력도 `REMOTE VERIFIED`, `ALREADY APPLIED`, `NOT ATTEMPTED`와
overall batch outcome을 구분합니다.

## OpenSpec
- 기준 change: `openspec/changes/complete-reverse-sync`
- 완료: batch partial success/conflict/postcondition exit-code 및 JSON
schema
- 완료: postcondition 중단 뒤 explicit manifest 목록 기반 resume 경계
- conflict나 remote drift manifest는 stale base일 수 있으므로 resume 목록에 포함하지
않습니다.

## Safety impact
- 이미 성공한 page를 batch 전체 실패처럼 숨기거나 rollback된 것처럼 표시하지 않습니다.
- postcondition 실패 뒤 실제 PUT하지 않은 page를 단순 `verified_local` 성공으로 오인하지
않습니다.
- resume 대상은 원격 발행을 시도하지 않은 immutable manifest로 제한합니다.
- `--yes`와 사용자 cancellation은 local proof/preflight/postcondition gate
의미를 바꾸지 않습니다.

## Test plan
- [x] 전체 Python test: 1113 passed, 2 skipped
- [x] reverse-sync Python test: 790 passed
- [x] `make test-convert`: 21 passed
- [x] `make test-reverse-sync`: golden 16 passed, regression 43 passed
- [x] `make test-byte-verify`: fast/splice 각각 21/21 passed
- [x] `openspec validate complete-reverse-sync --strict`
- [x] `git diff --check`
- [x] Python `compileall`

## Stack
- Base: #1034
- Typed plan: #1033
- Strict provenance identity: #1032
- Input/dependency gates: #1031
- Strict proof: #1030
- Publisher foundation: #1029
- 선행 PR merge 후 base를 순차적으로 `main`으로 변경할 수 있습니다.

🤖 Generated with Codex

Co-Authored-By: Atlas <atlas@jk.agent>

Co-authored-by: Codex <noreply@openai.com>
jk-kim0 added a commit that referenced this pull request Jul 27, 2026
## Summary
legacy patch builder가 operation 생성 전에 skip한 table/macro 변경도 typed
PatchPlan의 stable capability contract로 정규화합니다.

- `unsafe_html_table_edit`, `raw_html_table`, `not_markdown_table`을
`unsupported_capability` + `raw_html_table_edit`로 변환합니다.
- `preserved_anchor_table`을 `unsupported_capability` +
`unknown_macro_mutation`으로 변환합니다.
- `no_mapping`, `missing_roundtrip_sidecar`를 strict plan의
`missing_identity`로 변환합니다.
- legacy skip의 block ID를 exact sidecar provenance 또는 legacy MDX-sidecar
진단 mapping으로 원래 `ChangeIntent`에 연결합니다.
- operation target identity가 없는 경우에도 issue를 intent에 연결하되 operation 실행
provenance에는 legacy fallback을 사용하지 않습니다.
- 이미 issue가 연결된 intent에 후속 generic `missing_identity`를 중복 생성하지 않습니다.

## OpenSpec
- 기준 change: `openspec/changes/complete-reverse-sync`
- 완료: unsupported table/macro 구조의 explicit block reason 전환
- 계속 남는 범위: capability별 renderer strategy 추출, provenance-first planner
전환, visible segment model 확장

## Safety impact
- push 결과와 자동화가 legacy 내부 분기명에 의존하지 않고 stable reason/capability ID를 사용할
수 있습니다.
- 하나의 unsupported 변경이 여러 issue로 보이는 진단 중복을 제거합니다.
- raw table/macro 변경은 계속 fail-closed이며 이 PR에서 새 capability를 실행 가능하게 만들지
않습니다.
- legacy mapping은 issue attribution에만 사용하며 executable target identity
gate를 우회하지 않습니다.

## Test plan
- [x] 전체 Python test: 1114 passed, 2 skipped
- [x] reverse-sync Python test: 791 passed
- [x] `make test-convert`: 21 passed
- [x] `make test-reverse-sync`: golden 16 passed, regression 43 passed
- [x] `make test-byte-verify`: fast/splice 각각 21/21 passed
- [x] `openspec validate complete-reverse-sync --strict`
- [x] `git diff --check`
- [x] Python `compileall`

## Stack
- Base: #1035
- Explicit manifest publish: #1034
- Typed plan: #1033
- Strict provenance identity: #1032
- Input/dependency gates: #1031
- Strict proof: #1030
- Publisher foundation: #1029
- 선행 PR merge 후 base를 순차적으로 `main`으로 변경할 수 있습니다.

🤖 Generated with Codex

Co-Authored-By: Atlas <atlas@jk.agent>

Co-authored-by: Codex <noreply@openai.com>
jk-kim0 added a commit that referenced this pull request Jul 27, 2026
## Summary
repository의 reverse-sync skill과 CLI help를 현재 offline diagnostic / online
manifest publish lifecycle에 맞춥니다.

- offline `verify`/`debug`가 diagnostic이며 `push_eligible=false`임을 명확히
합니다.
- `push --dry-run`, inline publish, explicit `push --manifest`의 차이를
설명합니다.
- immutable run artifact, manifest integrity, preflight, postcondition,
`--yes` 경계를 문서화합니다.
- batch schema v1의 partial success, exit code, `not_attempted`,
`resume_manifests`를 추가합니다.
- 지원 상태와 stable reason code, canary 이전 production batch 금지를 반영합니다.
- 존재하지 않는 `var/pages.yaml`과 `--xhtml` 안내를 현재 `pages.qm.yaml`,
`--page-id`, `--page-dir`로 수정합니다.
- branch mode에서 이전에는 조용히 무시되던 `--page-id`와 `--page-dir`를 fail-fast로
거부합니다.

## OpenSpec
- 기준 change: `openspec/changes/complete-reverse-sync`
- 완료: `.agents/skills/reverse-sync/SKILL.md`의 current lifecycle/artifact
경로 동기화
- accepted spec 승격과 historical plan archive는 canary/P1 완료 후 별도로 남습니다.

## Safety impact
- offline `pass`를 publish 가능한 proof로 오해하지 않도록 합니다.
- flat compatibility artifact를 publisher 입력으로 안내하지 않습니다.
- `--yes`가 safety gate를 우회한다는 오해를 막습니다.
- branch에서 적용되지 않는 page option을 성공한 것처럼 보이지 않고 실행 전에 차단합니다.

## Test plan
- [x] 전체 Python test: 1117 passed, 2 skipped
- [x] reverse-sync Python test: 794 passed
- [x] `make test-reverse-sync`: golden 16 passed, regression 43 passed
- [x] `openspec validate complete-reverse-sync --strict`
- [x] stale `pages.yaml`/`--xhtml` reference search
- [x] `git diff --check`
- [x] Python `compileall`

## Stack
- Base: #1036
- Batch report: #1035
- Explicit manifest publish: #1034
- Typed plan: #1033
- Strict provenance identity: #1032
- Input/dependency gates: #1031
- Strict proof: #1030
- Publisher foundation: #1029
- 선행 PR merge 후 base를 순차적으로 `main`으로 변경할 수 있습니다.

🤖 Generated with Codex

Co-Authored-By: Atlas <atlas@jk.agent>

Co-authored-by: Codex <noreply@openai.com>
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