# Milestone: Plane-Origin Authoring Roundtrip Sync

## 위치

- Roadmap: `agent-roadmap/ROADMAP.md`
- Phase: `agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md`

## 목표

Plane `Backlog + AGENT assignee` 상위 티켓에서 시작한 Milestone authoring을 최신 dev 환경 기준으로 다시 닫되, Git/Plane 동기화의 canonical identity를 `agent-roadmap` Milestone 파일명 slug 하나로 정리한다. Gito HTTP webhook delivery는 단순 변경 파일 projection이 아니라 active roadmap Milestone reconcile을 깨우는 신호로 쓰고, archive를 제외한 모든 active Milestone이 Plane에 존재하도록 생성/갱신한다. Plane work item id와 roadmap path는 canonical id가 아니라 외부 참조와 현재 위치 속성으로만 취급한다.

## 상태

[진행중]

## 승격 조건

- 없음

## 구현 잠금

- 상태: 해제
- SDD: 필요
- SDD 문서: `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md`
- SDD 사유: 외부 provider 쓰기, IOP 실행 호출, git push, Gito webhook, identity map, retry/timeout, live smoke가 모두 걸린 runtime sync 마일스톤이다.
- 잠금 해제 조건:
  - [x] SDD 잠금이 해제되어 있다.
  - [x] SDD 사용자 리뷰가 없거나 승인/해결되었다.
  - [x] Acceptance Scenario가 아래 기능 Task와 연결되어 있다.
  - [x] Evidence Map이 plan의 `Spec Targets`와 완료 시 `Spec Completion`으로 검증 가능하게 연결되어 있다.
- 결정 필요: 없음

## 범위

- Plane-origin work item intake 이후 authoring 실행과 `develop` 반영 사이의 실제 runtime handoff
- IOP OpenAI-compatible Responses `/v1/responses` 호출의 long-running authoring 처리, timeout, queue timeout, stale monitoring 기준
- Milestone 파일명 slug를 Git/Plane 동기화의 단일 canonical id로 사용하고, path와 Plane work item id는 mutable attribute/foreign key로 분리하는 방식
- Gito HTTP webhook delivery를 wakeup으로 받아 Core가 local develop checkout을 fetch하고 archive를 제외한 active Milestone 전체를 reconcile하는 흐름
- Plane에 없는 active Milestone을 생성하고, 이미 있는 Milestone은 같은 slug 기준으로 본문/제목/status/ledger를 갱신하는 흐름
- authoring 후 별도 push 단계가 필요할 때 IOP workspace agent에 push-only 요청을 보내고, remote `develop` 반영을 Core가 재검증하는 흐름
- Plane 원문 댓글 보존, 본문/제목 갱신, `Todo` 이동, task/slot terminal state까지 이어지는 live-cycle smoke

## 기능

### Epic: [authoring-runtime] IOP authoring runtime contract

Plane-origin authoring이 짧은 사용자 입력과 workspace metadata만으로 실행되되, 장시간 작업과 push 분리를 runtime이 감당하도록 정리한다.

- [x] [thin-prompt] 기본 authoring instruction은 `다음 메시지를 바탕으로 마일스톤을 작성해.` 수준으로 유지하고, Plane/provider 계약 세부를 사용자 프롬프트에 섞지 않는다. 검증: `services/core/internal/authoring` 테스트에서 기본 instruction이 얇고 provider 계약 문구가 포함되지 않음을 확인한다.
- [x] [iop-long-run] IOP Responses 호출이 10분 이상 걸릴 수 있는 작업을 실패로 조기 확정하지 않도록 timeout, retry, queue timeout, stale 판단 기준을 재정의한다. 검증: `MODEL_TIMEOUT_SEC`/`WORKFLOW_TASK_TIMEOUT_SEC` 설정과 scheduler authoring state가 long-running 작업을 `failed`로 조기 전환하지 않고 관찰 가능한 상태를 남긴다.
- [x] [iop-progress] `/v1/responses` streaming 지원 여부를 dev IOP 계약으로 확인하고, stream 미지원 환경에서는 `authoring_run_updated_at`과 task metadata 기반 stale monitor로 대체한다. 검증: stream 미지원 응답이 silent failure가 아니라 명시 사유로 기록되고, stream 지원 시에는 진행 갱신 중단을 감지할 수 있다.
- [x] [push-command] authoring 결과 작성 이후 Core가 workspace agent에 `변경된 내용에 대해 develop 브런치에 푸시해` push-only 요청을 별도 단계로 보낼 수 있다. 검증: 첫 authoring 응답 성공만으로 task 완료를 단정하지 않고, push-only 단계와 remote `develop` 확인이 있어야 다음 단계로 넘어간다.

### Epic: [identity-sync] Plane-origin identity guard

사용자 프롬프트에 provider 계약을 넣지 않고도 Plane-origin authoring 결과가 원래 Plane 티켓과 매칭되도록 기존 identity guard를 보강한다. 이 Epic은 이미 완료된 authoring-origin 안전장치이며, 신규 active reconcile의 canonical id는 아래 `canonical-reconcile` Epic에서 filename slug로 정리한다.

- [x] [identity-source] Plane work item identity는 task external ref, payload `work_item`, checkout metadata, project sync 설정에서 가져오고 사용자 작성 문구에 의존하지 않는다. 검증: `BuildAuthoringGenerateInput`이 workspace metadata를 유지하고, identity source 누락 시 authoring 또는 projection이 명시 오류로 멈춘다.
- [x] [identity-write] authoring 산출물에 `## Provider identity` block이 없더라도 Core/runtime이 provider, tenant, project, work item id, milestone id를 결정적으로 주입하거나 동등한 sync ledger를 만들어 `gitosync` scan이 매칭할 수 있게 한다. 검증: provider identity 없는 generated Milestone이 Gito callback 이후 조용히 drop되지 않고, match 가능 상태 또는 명시 failure로 수렴한다.
- [x] [develop-match] pushed `develop` revision에서 실제 Milestone path 변경과 provider identity가 원래 Plane 티켓과 일치할 때만 Plane projection을 실행한다. 검증: slot-local dirty, push 실패, identity mismatch, milestone path 없음은 Plane `Todo` projection으로 넘어가지 않는다.
- [x] [idempotency-retry] 같은 Plane 티켓, 같은 Milestone path, 같은 Gito revision 재처리가 중복 Milestone/중복 Plane mutation 없이 남은 단계만 재시도한다. 검증: `roadmap_sync_identities`, `roadmap_sync_steps`, Gito revision dedup이 부분 실패 복구와 충돌 중단을 구분한다.

### Epic: [canonical-reconcile] Filename slug based active Milestone reconcile

Git/Plane 동기화는 path나 provider work item id가 아니라 Milestone 파일명 slug 하나를 canonical id로 삼는다. path는 active/archive 위치를 찾기 위한 속성이고, provider work item id는 Plane foreign key다.

- [x] [canonical-id] `agent-roadmap/phase/*/milestones/<milestone-id>.md`의 `<milestone-id>`를 단일 canonical sync id로 정의하고, `roadmap_sync_identities`/parser/matcher/projection이 path 대신 이 id를 1차 판별값으로 사용한다. 검증: phase 이동, archive 이동 후보, provider work item id 변경이 있어도 같은 filename slug는 같은 Milestone으로 판별된다.
- [x] [active-index] Gito wakeup 이후 Core가 remote `develop`을 fetch한 뒤 `agent-roadmap/phase/*/milestones/*.md`만 active Milestone index로 스캔하고 `agent-roadmap/archive/**`는 sync 대상에서 제외한다. 검증: active 문서는 reconcile 후보가 되고 archive 문서는 생성/갱신 대상에서 제외되지만 slug lookup으로 이력 조회 후보를 찾을 수 있다.
- [x] [plane-missing-create] active Milestone slug가 ledger와 Plane에서 발견되지 않으면 Plane work item을 생성하고, 생성된 Plane work item id를 slug ledger와 Milestone provider identity block 또는 동등한 sync marker에 기록한다. 검증: Plane에 없는 active Milestone 전체가 중복 없이 생성되고 제목에는 `[milestone-id]`가 들어간다.
- [x] [slug-reconcile] 같은 Milestone slug 재처리는 중복 Plane item을 만들지 않고 path, provider work item id, revision, 완료 step만 갱신한다. 검증: 같은 slug의 재처리/부분 실패 복구는 resume되고, slug 충돌 또는 파일명 재사용은 자동 병합하지 않고 명시 failure로 멈춘다.

### Epic: [gito-plane] Gito callback and Plane projection

Gito HTTP webhook wakeup 이후 Core sync pipeline이 active Milestone reconcile과 Plane Todo projection까지 닫히는지 실제 환경 기준으로 검증한다.

- [x] [gito-delivery] Forgejo push -> Gito -> NomadCode Core signed HTTP webhook delivery가 remote `develop` push마다 들어온다. 검증: Gito subscription target, signed delivery 202, Core gito webhook log, duplicate delivery 처리 결과를 secret 없이 확인한다.
- [x] [scan-enqueue] Gito wakeup이 local develop checkout fetch와 active Milestone index scan 이후 slug 단위 reconcile job enqueue로 이어진다. 검증: 변경 파일 힌트와 무관하게 active Milestone 전체가 reconcile 후보가 되고, archive Milestone은 제외된다.
- [x] [plane-todo] reconcile job이 Plane 원문 댓글 보존, Milestone 본문 projection, `[milestone-id]` 제목 갱신, `Todo` 이동까지 완료한다. 검증: Plane UI/API와 `roadmap_sync_steps`에서 `milestone_id_matched`, `original_comment_preserved`, `plane_body_updated`, `plane_todo_moved`를 확인한다.
- [x] [slot-finalize] projected, failed, timeout, queue timeout, push failed, identity missing 결과가 workspace slot 상태와 task metadata에 일관되게 반영된다. 검증: 성공은 slot `available`, 수동 복구가 필요한 git 상태는 `dirty`, bridge/provider 오류는 `error`로 수렴한다.

### Epic: [live-gate] End-to-end live smoke gate

이 마일스톤은 unit/fake seam만으로 닫지 않고 실제 dev 환경에서 한 사이클 증거를 남긴다.

- [ ] [remote-baseline] standard remote runner, Core compose, IOP workspace clone, Gito service, Forgejo webhook, project sync DB 설정을 현재 요청 기준으로 reset/clean/reclone 또는 rebuild해 맞춘다. 검증: dirty runner 상태를 차단 사유로 삼지 않고 최신 local 작업 범위와 같은 테스트 환경으로 만든다.
- [ ] [full-cycle] 새 Plane Backlog 티켓을 AGENT에 assign한 authoring roundtrip과, Git에만 있는 active Milestone을 Plane에 생성하는 reconcile roundtrip을 함께 확인한다. 검증: `agent-test/live-cycle-smoke.md` 절차에 따라 secret redaction 상태의 live evidence가 남는다.
- [x] [regression-doc] 이번 회귀 원인과 방지 기준을 `agent-test/live-cycle-smoke.md` 또는 core README의 비밀 없는 운영 규칙에 반영한다. 검증: filename slug canonical id, archive 제외, provider identity 누락, IOP queue timeout, push-only 단계 누락, Gito delivery-only 성공을 각각 완료 조건으로 오인하지 않는 기준이 문서화된다.

## 완료 리뷰

- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 검토 항목:
  - [x] SDD gate가 해제되었다.
  - [ ] 모든 기능 Task와 검증이 충족되었다.
  - [ ] 실제 dev Plane-origin full-cycle smoke에서 Plane `Todo` projection까지 확인했다.
  - [ ] 사용자 완료 확인과 archive 승인을 받았다.
- 리뷰 코멘트: 없음

## 범위 제외

- Plane `Todo -> In Progress` 이후 실행 lifecycle
- Milestone Task를 Plane 하위 티켓으로 생성하거나 plan/code-review 루프에 연결하는 작업
- Plane 외 provider(Jira 등)에 active Milestone missing-create를 적용하는 작업
- archive Milestone을 Plane과 계속 실시간 동기화하는 작업
- Milestone 파일명 slug rename/reuse를 자동 추론해 병합하는 작업
- IOP 내부 모델 라우팅, queue 구현, RAG, output validation 변경
- 외부 agent 제어 표면 또는 MCP tool policy 확정
- 사용자 승인 없는 archive 이동

## 작업 컨텍스트

- 관련 경로: `services/core/internal/authoring/`, `services/core/internal/adapters/openai/`, `services/core/internal/scheduler/`, `services/core/internal/gitosync/`, `services/core/internal/roadmapsync/`, `services/core/internal/roadmapsyncpipeline/`, `services/core/internal/projectsync/`, `services/core/internal/workitempipeline/`, `services/core/internal/http/`, `services/core/internal/storage/`, `services/core/README.md`, `agent-test/live-cycle-smoke.md`, `packages/contracts/notes/flutter-core-api-candidates.md`
- 표준선(선택): Plane 티켓 본문은 사용자 요청 원문이고, authoring 프롬프트도 사용자 요청 중심으로 둔다. Git/Plane 동기화의 canonical Milestone id는 파일명 slug 하나이며, path와 Plane work item id는 각각 현재 위치와 provider foreign key로만 다룬다. provider identity, project sync 설정, push 검증, Gito delivery, Plane projection은 사용자 프롬프트가 아니라 Core/runtime의 결정적 책임이다.
- 선행 작업: `Milestone Work Item Creation Sync`, `Plane Work Item Webhook Intake`, `Gito HTTP Webhook Consumer Readiness`
- 후속 작업: `Milestone Execution Lifecycle Sync`
- 현재 관찰:
  - 최신 dev smoke에서 Plane webhook과 Core task 생성, IOP Responses 호출, Gito delivery 자체는 관찰되었다.
  - IOP `/v1/responses`는 현재 non-streaming 경로이며, 장시간/queue timeout 상황을 authoring 실패로 조기 확정할 위험이 있다.
  - 얇은 authoring prompt로 생성된 Milestone에는 provider identity block이 빠질 수 있으므로, identity writer가 push 전 주입하거나 mismatch/missing을 명시 failure로 막는다.
  - 첫 authoring 호출만으로는 `develop` push가 보장되지 않으며, push-only workspace agent 요청과 remote `develop` 재검증이 필요하다.
  - 현재 구현은 `roadmap_milestone_path`와 provider work item id에 강하게 기대고 있어, phase/archive 이동이나 path 변경 시 같은 마일스톤 판별이 깨질 수 있다.
  - Gito webhook 202만으로는 Plane 동기화 완료가 아니며, active Milestone slug reconcile, `roadmap_sync_identities`, `roadmap_sync_steps`, Plane `Todo` 상태까지 확인해야 한다.
- 작업 현황 동기화(2026-06-20):
  - SDD는 `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md`에 작성되었고 `[승인됨]`, `SDD 잠금: 해제`, 사용자 리뷰 없음 상태다.
  - 마일스톤 구현 잠금은 `해제` 상태이며, 활성 상태는 `[진행중]`이다.
  - `thin-prompt` Task는 `services/core/internal/authoring` 테스트 근거로 완료 처리되었다.
  - archive 완료 로그의 `Roadmap Completion`/`Spec Completion` 근거로 `iop-long-run`(`S02`), `iop-progress`(`S03`), `push-command`(`S04`) Task를 완료 처리했다.
  - 완료 근거:
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/01_iop_long_run/complete.log`
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/02+01_iop_progress/complete.log`
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/03+01,02_push_command/complete.log`
  - `identity-source` Task는 `BuildAuthoringGenerateInputStrict`/scheduler authoring path가 provider work item id 누락을 명시 오류로 중단하도록 보강했고, 현재 workspace와 standard remote runner에서 `cd services/core && go test ./...` 통과 근거로 완료 처리했다.
  - `identity-write` Task는 writer/workspace metadata 필수화, 기존 provider identity mismatch 차단, identity write failure/missing category와 slot error mapping 보강 근거로 완료 처리했다.
  - 완료 근거:
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/04+03_identity_write/complete.log`
  - `develop-match` Task는 `roadmapsync.MatchDevelopMilestone`/`roadmapsyncpipeline.SyncCreation`의 not-ready gate 테스트와 현재 workspace/standard remote runner `cd services/core && go test ./...` 통과 근거로 완료 처리했다.
  - `idempotency-retry` Task는 `roadmapsync.ReconcileCreationCycle`, `roadmap_sync_identities`, `roadmap_sync_steps`, `roadmapsyncpipeline`, `gitosync` dedup 테스트와 현재 workspace/standard remote runner `cd services/core && go test ./...` 통과 근거로 완료 처리했다.
  - 현재 활성 `agent-task` plan/review/user-review/complete 파일은 없다.
  - 당시 남은 실구현/검증 후보는 `canonical-id`, `active-index`, `plane-missing-create`, `slug-reconcile`, `gito-delivery`, `scan-enqueue`, `plane-todo`, `slot-finalize`, `remote-baseline`, `full-cycle`, `regression-doc`이다.
- 핸즈오프(2026-06-20):
  - 현재 타겟은 이 마일스톤이다. 로컬 `agent-roadmap/current.md`의 활성 Milestone은 `Plane-Origin Authoring Roundtrip Sync` 하나로 정리되어 있다.
  - SDD gate는 작성과 해제까지 완료되어 구현 plan 생성이 가능하다.
  - 다음 세션은 AGENTS 규칙을 다시 읽은 뒤 이 마일스톤, SDD, `agent-test/live-cycle-smoke.md`, `services/core/internal/authoring/`, `services/core/internal/adapters/openai/`, `services/core/internal/gitosync/`, `services/core/internal/roadmapsync/`, `services/core/internal/roadmapsyncpipeline/`를 우선 확인한다.
  - 중요한 방향: Plane 티켓 본문과 authoring prompt는 사용자 요청 원문 중심으로 얇게 유지한다. provider identity, project sync 설정, push-only 단계, Gito callback, Plane Todo projection은 사용자 프롬프트가 아니라 Core/runtime의 결정적 책임으로 설계한다.
  - 현재 알려진 회귀: IOP authoring은 milestone 파일을 만들 수 있지만 remote `develop` push가 별도 조치 없이는 보장되지 않는다. provider identity block 누락은 identity writer가 push 전 주입하거나 mismatch/missing을 명시 failure로 막도록 보강되었고, 남은 검증은 Gito delivery -> active slug reconcile -> Plane 생성/갱신 -> Plane Todo projection full-cycle이다.
  - 검증 기준: Gito webhook 202나 remote `develop` commit만으로 완료로 보지 않는다. active Milestone filename slug 기준 reconcile, `roadmap_sync_identities`, `roadmap_sync_steps`의 단계 기록과 Plane `Todo` 상태까지 확인해야 full-cycle 완료다.
  - 원격 테스트 runner는 disposable mirror로 취급한다. dirty 상태를 이유로 멈추지 말고 reset/clean/reclone 또는 파일 동기화 후 현재 요청 기준 상태로 맞춰 테스트한다.
  - 이 workspace에는 이미 여러 변경이 섞여 있으므로 다음 세션은 `git status --short`와 대상 파일 diff를 먼저 보고, 관련 없는 사용자/이전 변경을 되돌리지 않는다.
- 작업 현황 동기화(2026-06-21):
  - `active-index` Task는 `services/core/internal/gitosync/scanner.go`가 Gito wakeup 이후 `git diff`가 아니라 `git ls-tree -r --name-only <revision> -- agent-roadmap/phase agent-roadmap/archive`로 remote `develop` revision의 active Milestone 전체를 인덱싱하고, archive Milestone은 `ArchiveCandidates` slug lookup 후보로만 보존하도록 보강해 완료 처리했다.
  - 검증 근거: `cd services/core && go test ./internal/gitosync`, `cd services/core && go test ./...`, `git diff --check` 통과.
  - `canonical-id` Task는 filename slug canonical id와 path/provider work item id 속성화, 기존 row mutation 전 revision mismatch 차단, safe attribute update 보강 근거로 완료 처리했다.
  - `plane-missing-create` Task는 Plane에 없는 active Milestone slug가 bridge-produced missing-create job에서도 중복 없이 Plane item 생성과 ledger upsert로 수렴하도록 보강한 근거로 완료 처리했다.
  - `slug-reconcile` Task는 same-slug 재처리 시 최신 incoming provider ref를 보존하고, completed-cycle no-op에서도 safe attribute upsert가 일어나도록 보강한 근거로 완료 처리했다.
  - 완료 근거:
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/05_canonical_id/complete.log`
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/06+05_plane_missing_create/complete.log`
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/07+05,06_slug_reconcile/complete.log`
  - `gito-delivery` Task는 signed delivery 202, Core Gito webhook log, duplicate delivery 202 결과를 secret 없이 재확인한 근거로 완료 처리했다.
  - `scan-enqueue` Task는 Gito wakeup 이후 active Milestone 5개가 `roadmap_creation_sync`로 enqueue되고 archive Milestone 17개가 제외된 live evidence 근거로 완료 처리했다.
  - `plane-todo` Task는 Plane work item 원문 댓글 보존, Milestone body/title projection, `Todo` 이동, `roadmap_sync_steps` evidence와 bridge regression test 보강 근거로 완료 처리했다.
  - `slot-finalize` Task는 success completion의 stale authoring failure metadata 정리, terminal task metadata, slot state evidence와 workflow/scheduler/authoring 테스트 근거로 완료 처리했다.
  - `regression-doc` Task는 `agent-test/live-cycle-smoke.md`에 filename slug canonical id, archive 제외, provider identity 누락/불일치, IOP queue timeout/stale, push-only 단계, Gito delivery-only 성공을 완료로 오인하지 않는 기준을 문서화해 완료 처리했다.
  - 완료 근거:
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/08+07_gito_delivery/complete.log`
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/09+08_scan_enqueue/complete.log`
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/10+09_plane_todo/complete.log`
    - `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/11+10_slot_finalize/complete.log`
    - `agent-test/live-cycle-smoke.md`
  - `remote-baseline`과 `full-cycle`은 큰 live runtime 작업으로 분류해 plan-loop에 진입시켰다.
  - 활성 plan/review:
    - `agent-task/m-plane-origin-authoring-roundtrip-sync/12_remote_baseline/PLAN-cloud-G07.md`
    - `agent-task/m-plane-origin-authoring-roundtrip-sync/12_remote_baseline/CODE_REVIEW-cloud-G07.md`
    - `agent-task/m-plane-origin-authoring-roundtrip-sync/13+12_full_cycle/PLAN-cloud-G08.md`
    - `agent-task/m-plane-origin-authoring-roundtrip-sync/13+12_full_cycle/CODE_REVIEW-cloud-G08.md`
  - 현재 남은 실구현/검증 후보는 `remote-baseline`, `full-cycle`이며, 둘 다 active plan 상태다.
- 확인 필요: 없음


## Provider identity
- provider: plane
- tenant: general
- project: a6beb42f-7a8a-410c-b50f-ea3ca94828f3
- work item id: aade6b05-49f8-491b-8e23-d938c578958d
- milestone id: plane-origin-authoring-roundtrip-sync
