nomadcode/agent-task/m-plane-origin-authoring-roundtrip-sync/07+05,06_slug_reconcile/PLAN-local-G05.md
toki 528e9d6966 feat(roadmapsync): plane origin authoring roundtrip 기능 및 마일스톤 ID 지원
- roadmapsync pipeline에 retry 로직 및 개발 일치 검증 로직 추가
- gitosync scanner에 slug 재조정 및 plane 매칭 로직 강화
- roadmap sync identity 관리를 위한 migration(00009) 및 SQL 쿼리 추가
- milestone parser 테스트 및 retry 테스트 보강
- agent-ops 문서(PHASE, SDD, milestones) 갱신
- agent-task archive 및 작업 디렉터리 추가
2026-06-21 07:59:56 +09:00

8.3 KiB

Plan - REVIEW_REFACTOR

이 파일을 읽는 구현 에이전트에게

이 후속 계획은 이전 review의 Required 2건만 닫는다. 직접 사용자에게 질문하지 말고, 새 결정이 필요한 경우에도 선택된 SDD 결정 또는 Milestone lock 결정만 CODE_REVIEW-*-G??.md사용자 리뷰 요청에 기록한다. 이번 범위는 repo-fixable code/test follow-up이므로 기본적으로 USER_REVIEW.md 대상이 아니다.

배경

이전 구현은 같은 filename slug 재처리에서 canonical id 중심 lookup과 conflict mapping을 추가했지만, 기존 identity row가 있을 때 provider projection target과 completed-cycle safe attribute update가 계획/SDD S12를 완전히 만족하지 못한다. 같은 slug 재처리는 중복 Plane item을 만들지 않으면서 path, provider work item id, revision, completed step ledger를 갱신해야 한다.

Roadmap Targets

  • Milestone: agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/plane-origin-authoring-roundtrip-sync.md
  • Task ids:
    • slug-reconcile: 같은 Milestone slug 재처리는 중복 Plane item을 만들지 않고 path, provider work item id, revision, 완료 step만 갱신한다.
  • Completion mode: check-on-pass

Spec Targets

  • SDD: agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md
  • Acceptance scenarios:
    • S12: task=slug-reconcile; evidence=retry/idempotency tests for same slug reprocess, partial failure resume, and slug conflict/reuse failure
  • Completion mode: spec-check-on-pass

Archive Evidence Snapshot

  • Current archived plan: agent-task/m-plane-origin-authoring-roundtrip-sync/07+05,06_slug_reconcile/plan_cloud_G05_0.log
  • Current archived review: agent-task/m-plane-origin-authoring-roundtrip-sync/07+05,06_slug_reconcile/code_review_cloud_G05_0.log
  • Verdict: FAIL
  • Required summary:
    • services/core/internal/roadmapsyncpipeline/service.go:128: existing row lookup overwrites incoming trigger identity/ref, so provider projection can target the stale persisted Plane item while the ledger upsert records the new work item id.
    • services/core/internal/roadmapsyncpipeline/service.go:265: ActionComplete returns before safe attribute upsert, so all-steps-complete same-slug reprocesses do not update path/work item/revision attributes.
  • Suggested/Nit summary: 없음
  • Affected files:
    • services/core/internal/roadmapsyncpipeline/service.go
    • services/core/internal/roadmapsyncpipeline/service_test.go
    • 필요 시 services/core/internal/roadmapsync/retry.go 또는 services/core/internal/roadmapsync/retry_test.go
  • Verification evidence from failed loop:
    • go test -count=1 ./internal/gitosync ./internal/roadmapsync ./internal/storage ./internal/roadmapsyncpipeline in services/core: PASS
    • go test -count=1 ./... in services/core: PASS
    • git diff --check: PASS after review-only EOF blank-line cleanup
  • Roadmap carryover: slug-reconcile
  • Spec carryover: S12
  • Narrow archive reread allowed: if exact prior context is needed, read only the two archived files listed above.

분석 결과

범위 결정 근거

이 후속은 SyncCreation orchestration과 해당 unit tests에 한정한다. Scanner duplicate active slug detection, storage SQL unique index, live Plane smoke, Gito delivery, Plane Todo projection 전체 smoke는 이번 Required의 직접 수정 범위가 아니다.

빌드 등급

local-G05: bounded Go service/test 수정이며 provider side effect target과 complete-row update를 fake tests로 결정적으로 검증할 수 있다.

구현 체크리스트

  • 기존 identity row가 있어도 SyncCreation이 incoming trigger identity/ref를 stale persisted row로 덮어쓰지 않고, provider projection target이 matched candidate의 최신 provider work item id/path를 사용하도록 수정한다.
  • all-steps-complete same-slug 재처리에서도 provider call 없이 safe attribute upsert가 수행되어 path, provider work item id, revision이 갱신되도록 수정한다.
  • roadmapsyncpipeline tests에 changed provider work item id 재처리 provider Ref 검증과 completed-cycle attribute update/no-provider-call 검증을 추가한다.
  • cd services/core && go test -count=1 ./internal/roadmapsyncpipelinecd services/core && go test -count=1 ./internal/gitosync ./internal/roadmapsync ./internal/storage ./internal/roadmapsyncpipelinecd services/core && go test -count=1 ./...git diff --check를 통과시킨다.
  • CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

의존 관계 및 구현 순서

이 plan은 기존 07+05,06_slug_reconcile follow-up이다. 선행 complete evidence는 이전 loop에서 확인되었으므로 새 archive 검색을 반복하지 않는다.

[REVIEW_REFACTOR-1] Preserve Trigger Ref For Provider Projection

문제: SyncCreation이 existing row를 milestone id로 찾은 뒤 in.Expectedin.Ref를 persisted row 값으로 덮어쓴다. 이후 MatchDevelopMilestone은 scanned identity의 새 work item id를 candidate로 만들 수 있지만, provider projection input은 stale in.Ref를 사용한다.

해결 방법: persisted row는 ExistingIdentity/revision/step ledger 판단에만 사용하고, incoming trigger identity/ref는 별도로 보존한다. Projection ref는 normalized candidate.Identity에서 만들거나, incoming ref가 candidate와 일치하면 incoming ref를 사용한다. tenant/project fallback이 필요하면 existing row를 "빈 필드 보충"에만 사용하고 새 work item id를 덮지 않는다.

수정 파일 및 체크리스트:

  • services/core/internal/roadmapsyncpipeline/service.go
  • services/core/internal/roadmapsyncpipeline/service_test.go

테스트 작성: 작성한다. fake provider가 comment/body/status input ref를 기록하도록 확장하고, existing row의 WorkItemID=NOMAD-OLD, scanned/incoming identity의 WorkItemID=NOMAD-1인 partial resume에서 provider calls가 NOMAD-1을 대상으로 실행되고 row도 NOMAD-1로 갱신되는지 확인한다.

중간 검증: cd services/core && go test -count=1 ./internal/roadmapsyncpipeline.

[REVIEW_REFACTOR-2] Update Attributes Before Complete No-Op

문제: ReconcileCreationCycleActionComplete를 반환하면 SyncCreation이 즉시 SyncActionComplete로 빠져 safe attribute upsert를 실행하지 않는다. 모든 step이 완료된 same-slug reprocess에서 path/work item/revision 변경을 ledger row에 반영하지 못한다.

해결 방법: reconcile이 conflict/self-mutation이 아니고 existing row가 있는 경우, complete 반환 전에도 candidate identity와 trigger revisions가 persisted row와 다르면 provider side effect 없이 upsert한다. 다만 revision mismatch conflict는 기존처럼 upsert 전에 차단해야 한다.

수정 파일 및 체크리스트:

  • services/core/internal/roadmapsyncpipeline/service.go
  • services/core/internal/roadmapsyncpipeline/service_test.go

테스트 작성: 작성한다. completed set에 develop_matched, original_comment_preserved, plane_body_updated, plane_todo_moved가 모두 있는 existing row에서 scanned path/work item id/revision이 바뀐 입력을 넣고, 결과는 SyncActionComplete, provider calls는 없음, store upsert는 최신 path/work item id/revision으로 1회 발생해야 한다.

중간 검증: cd services/core && go test -count=1 ./internal/roadmapsyncpipeline.

수정 파일 요약

파일 항목
services/core/internal/roadmapsyncpipeline/service.go REVIEW_REFACTOR-1, REVIEW_REFACTOR-2
services/core/internal/roadmapsyncpipeline/service_test.go REVIEW_REFACTOR-1, REVIEW_REFACTOR-2

최종 검증

cd services/core && go test -count=1 ./internal/roadmapsyncpipeline

cd services/core && go test -count=1 ./internal/gitosync ./internal/roadmapsync ./internal/storage ./internal/roadmapsyncpipeline

cd services/core && go test -count=1 ./...

git diff --check

모든 코드 변경 완료 후 반드시 CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.