# 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이 IOP Responses workspace agent 실행, `develop` push, Gito HTTP webhook delivery, Core develop scan, provider identity match, Plane `Todo` projection까지 한 사이클로 수렴하도록 최신 dev 환경 기준으로 다시 닫는다. 사용자 메시지는 단순 authoring 입력으로 유지하고, provider identity와 push/projection 책임은 Core/runtime의 결정적 처리로 옮긴다.

## 상태

[진행중]

## 승격 조건

- 없음

## 구현 잠금

- 상태: 해제
- 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 기준
- authoring 프롬프트를 사용자 요청 중심으로 얇게 유지하면서 provider identity를 Milestone 문서 또는 sync ledger에 결정적으로 연결하는 방식
- authoring 후 별도 push 단계가 필요할 때 IOP workspace agent에 push-only 요청을 보내고, remote `develop` 반영을 Core가 재검증하는 흐름
- Gito HTTP webhook delivery를 wakeup으로 받아 Core가 local develop checkout을 fetch/scan하고 creation sync job으로 넘기는 흐름
- 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 계약 문구가 포함되지 않음을 확인한다.
- [ ] [iop-long-run] IOP Responses 호출이 10분 이상 걸릴 수 있는 작업을 실패로 조기 확정하지 않도록 timeout, retry, queue timeout, stale 판단 기준을 재정의한다. 검증: `MODEL_TIMEOUT_SEC`/`WORKFLOW_TASK_TIMEOUT_SEC` 설정과 scheduler authoring state가 long-running 작업을 `failed`로 조기 전환하지 않고 관찰 가능한 상태를 남긴다.
- [ ] [iop-progress] `/v1/responses` streaming 지원 여부를 dev IOP 계약으로 확인하고, stream 미지원 환경에서는 `authoring_run_updated_at`과 task metadata 기반 stale monitor로 대체한다. 검증: stream 미지원 응답이 silent failure가 아니라 명시 사유로 기록되고, stream 지원 시에는 진행 갱신 중단을 감지할 수 있다.
- [ ] [push-command] authoring 결과 작성 이후 Core가 workspace agent에 `변경된 내용에 대해 develop 브런치에 푸시해` push-only 요청을 별도 단계로 보낼 수 있다. 검증: 첫 authoring 응답 성공만으로 task 완료를 단정하지 않고, push-only 단계와 remote `develop` 확인이 있어야 다음 단계로 넘어간다.

### Epic: [identity-sync] Provider identity and develop scan

사용자 프롬프트에 provider 계약을 넣지 않고도 pushed Milestone이 원래 Plane 티켓과 매칭되도록 identity 연결을 결정적으로 보장한다.

- [ ] [identity-source] Plane work item identity는 task external ref, payload `work_item`, checkout metadata, project sync 설정에서 가져오고 사용자 작성 문구에 의존하지 않는다. 검증: `BuildAuthoringGenerateInput`이 workspace metadata를 유지하고, identity source 누락 시 authoring 또는 projection이 명시 오류로 멈춘다.
- [ ] [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로 수렴한다.
- [ ] [develop-match] pushed `develop` revision에서 실제 Milestone path 변경과 provider identity가 원래 Plane 티켓과 일치할 때만 Plane projection을 실행한다. 검증: slot-local dirty, push 실패, identity mismatch, milestone path 없음은 Plane `Todo` projection으로 넘어가지 않는다.
- [ ] [idempotency-retry] 같은 Plane 티켓, 같은 Milestone path, 같은 Gito revision 재처리가 중복 Milestone/중복 Plane mutation 없이 남은 단계만 재시도한다. 검증: `roadmap_sync_identities`, `roadmap_sync_steps`, Gito revision dedup이 부분 실패 복구와 충돌 중단을 구분한다.

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

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

- [ ] [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 없이 확인한다.
- [ ] [scan-enqueue] Gito wakeup이 local develop checkout fetch/scan 이후 `roadmap_creation_sync` job enqueue로 이어진다. 검증: provider identity가 있는 Milestone 변경은 정확히 하나의 creation sync job으로 이어지고, identity 없는 변경은 명시 사유를 남긴다.
- [ ] [plane-todo] creation sync job이 Plane 원문 댓글 보존, Milestone 본문 projection, `[milestone-id]` 제목 갱신, `Todo` 이동까지 완료한다. 검증: Plane UI/API와 `roadmap_sync_steps`에서 `develop_matched`, `original_comment_preserved`, `plane_body_updated`, `plane_todo_moved`를 확인한다.
- [ ] [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한 뒤 Core task 생성, IOP authoring, push-only 단계, remote `develop` commit, Gito callback, roadmap sync identity/steps, Plane `Todo` projection까지 확인한다. 검증: `agent-test/live-cycle-smoke.md` 절차에 따라 secret redaction 상태의 live evidence가 남는다.
- [ ] [regression-doc] 이번 회귀 원인과 방지 기준을 `agent-test/live-cycle-smoke.md` 또는 core README의 비밀 없는 운영 규칙에 반영한다. 검증: 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 루프에 연결하는 작업
- Agent-origin Milestone 생성 후 Plane 티켓을 만드는 역방향 생성 sync
- 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 프롬프트도 사용자 요청 중심으로 둔다. 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이 빠질 수 있고, 현재 `gitosync` scanner는 identity 없는 Milestone을 projection 대상으로 삼지 않는다.
  - 첫 authoring 호출만으로는 `develop` push가 보장되지 않으며, push-only workspace agent 요청과 remote `develop` 재검증이 필요하다.
  - Gito webhook 202만으로는 Plane 동기화 완료가 아니며, `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` 테스트 근거로 완료 처리되었다.
  - 현재 활성 `agent-task` plan/review/user-review/complete 파일은 없다.
  - 다음 실구현은 남은 Task를 `agent-task/m-plane-origin-authoring-roundtrip-sync/` 아래 milestone 기반 plan으로 분해해 진행한다.
- 핸즈오프(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가 별도 조치 없이는 보장되지 않고, 생성된 Milestone에 `## Provider identity` block이 없으면 `gitosync` scanner가 projection 대상으로 삼지 않는다.
  - 검증 기준: Gito webhook 202나 remote `develop` commit만으로 완료로 보지 않는다. `roadmap_sync_identities`, `roadmap_sync_steps`의 단계 기록과 Plane `Todo` 상태까지 확인해야 full-cycle 완료다.
  - 원격 테스트 runner는 disposable mirror로 취급한다. dirty 상태를 이유로 멈추지 말고 reset/clean/reclone 또는 파일 동기화 후 현재 요청 기준 상태로 맞춰 테스트한다.
  - 이 workspace에는 이미 여러 변경이 섞여 있으므로 다음 세션은 `git status --short`와 대상 파일 diff를 먼저 보고, 관련 없는 사용자/이전 변경을 되돌리지 않는다.
- 확인 필요: 없음
