# SDD: Agent-Origin Milestone Creation Sync ## 위치 - Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/agent-origin-milestone-creation-sync.md` - Phase: `agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md` ## 상태 [승인됨] ## SDD 잠금 - 상태: 해제 - 사용자 리뷰: 없음 - 잠금 항목: - 없음 ## 문제 / 비목표 - 문제: Plane-origin 흐름은 Plane 요청에서 시작해 pushed develop SHA를 확인한 뒤 Plane Todo projection까지 수렴하지만, agent 또는 사람이 `agent-roadmap` active Milestone을 직접 수정해 push한 경우 provider identity가 없는 Milestone을 Plane work item과 안정적으로 연결하고 그 identity를 repo에 되돌려 쓰는 경로가 부족하다. - 비목표: - Todo 이후 실행 lifecycle과 Plane 하위 티켓 동기화 - MCP control surface 또는 외부 agent tool permission 정책 - provider native API schema 일반화 또는 Jira 구현 - 사용자 승인 없는 archive 이동 ## Source of Truth | 영역 | 기준 | 메모 | |------|------|------| | Roadmap | `agent-roadmap/phase/**/milestones/*.md` on `develop` | active Milestone markdown이 Plane projection의 본문/제목 기준이며 filename slug가 canonical milestone id다. | | Code | `services/core/internal/gitosync/`, `services/core/internal/roadmapsyncpipeline/`, `services/core/internal/roadmapsync/` | Gito revision scan, identity matching, provider mutation, ledger/retry orchestration을 소유한다. | | External Provider | Plane | Plane work item id와 state는 provider side effect 결과이며 raw token/secret은 tracked 문서에 기록하지 않는다. | | User Decision | 없음 | 사용자는 agent-origin identity backfill 방향을 승인했고, 남은 항목은 기존 sync/domain rule로 구현 가능하다. | ## State Machine | 상태 | 진입 조건 | 다음 상태 | 근거 | |------|-----------|-----------|------| | `branch_event_received` | Gito `branch.updated` webhook이 target repo/branch로 들어온다. | `revision_verified` 또는 `not_ready` | `agent-contract/outer/gito-branch-webhook-consumer-v1.md` | | `revision_verified` | local develop checkout fetch 후 `origin/develop`이 event `after` SHA와 일치한다. | `milestone_scanned` | `git fetch`, `git rev-parse`, `git ls-tree`, `git show` | | `milestone_scanned` | active Milestone diff와 active index를 읽고 identity 유무를 분류한다. | `missing_identity_candidate`, `identity_matched`, `conflict` | roadmap parser, duplicate slug guard | | `missing_identity_candidate` | provider identity가 없는 active Milestone이 생성 후보로 판별된다. | `plane_created` 또는 `conflict` | filename slug, project sync config, ledger lookup | | `plane_created` | Plane work item 생성과 DB identity upsert가 성공한다. | `identity_backfilled` | Plane adapter, `roadmap_sync_identities` | | `identity_backfilled` | Milestone markdown에 `Provider identity` block을 주입한 commit이 `develop`에 push된다. | `self_loop_checked` | Core-authored git commit/push | | `identity_matched` | provider identity가 있는 Milestone 변경이다. | `plane_projected`, `complete`, `conflict` | roadmap revision guard, completed-step ledger | | `self_loop_checked` | identity-only backfill commit webhook이 재수신된다. | `complete` 또는 `conflict` | actor/commit marker, markdown identity, ledger | | `conflict` | slug reuse, identity mismatch, duplicate active slug, destructive overwrite 위험이 감지된다. | `conflict` | no provider mutation, operator/user review evidence | ## Interface Contract - 계약 원문: `agent-contract/outer/gito-branch-webhook-consumer-v1.md` - 입력: - `repo_id`: target repository id. `GITO_REPO_ID`와 일치해야 한다. - `branch`: target branch. 기본값은 `develop`이다. - `before`: 이전 git SHA. diff 후보 산정에 사용하되 source-of-truth로 단정하지 않는다. - `after`: 새 git SHA. fetch/scan 및 idempotency 기준이다. - `changed_files`: wakeup relevance 힌트. 실제 sync는 target revision scan으로 확인한다. - 출력: - Plane work item 생성/갱신 결과 - `roadmap_sync_identities` identity row와 completed step ledger - provider identity block backfill commit SHA - conflict/not-ready/complete/projected 로그와 job result - 금지: - `changed_files`만 믿고 Plane 또는 roadmap 파일을 mutation하지 않는다. - provider identity가 충돌하는 Milestone을 덮어쓰지 않는다. - Core-authored backfill commit 재전달로 Plane work item을 중복 생성하지 않는다. - raw secret, token, provider credential을 tracked evidence나 로그에 남기지 않는다. ## Acceptance Scenarios | ID | Milestone Task | Given | When | Then | |----|----------------|-------|------|------| | S01 | `scan-diff` | Gito event가 `before`, `after`, `changed_files`를 포함한다. | Core가 fetch 후 `origin/develop`과 `after` SHA를 비교한다. | SHA가 일치할 때만 active Milestone scan이 진행되고, 불일치하면 not-ready로 남는다. | | S02 | `missing-create` | active Milestone 파일이 추가됐고 provider identity가 없다. | `after` revision scan에서 생성 후보로 분류된다. | Plane work item이 1개만 생성되고 같은 revision 재처리는 중복 생성하지 않는다. | | S03 | `identity-ledger` | 생성된 Plane work item id와 milestone slug가 있다. | identity row를 upsert한다. | 같은 slug/provider key는 재시도 가능하고, 다른 provider work item과 충돌하면 conflict로 멈춘다. | | S04 | `identity-backfill` | Plane 생성과 identity ledger 기록이 완료됐다. | Core가 Milestone markdown에 provider identity block을 추가한다. | identity-only backfill commit이 `develop`에 push되고 unrelated 변경은 포함되지 않는다. | | S05 | `self-loop` | backfill commit으로 다시 Gito webhook이 들어온다. | Core가 actor/commit marker, markdown identity, ledger를 비교한다. | Plane 생성/갱신이 반복되지 않고 complete/no-op으로 수렴한다. | | S06 | `identity-update` | provider identity가 있는 Milestone markdown이 agent-origin으로 수정됐다. | Core가 target revision을 scan한다. | Plane 제목/본문 갱신이 ledger step으로 재시도 가능하게 수행된다. | | S07 | `conflict-policy` | rename, slug reuse, stale provider item, duplicate active slug 중 하나가 발생한다. | Core가 sync를 시도한다. | destructive overwrite 없이 conflict/not-ready/skip 중 하나로 분류하고 provider mutation을 제한한다. | | S08 | `field-smoke` | dev Plane/Gito/NomadCode/IOP 환경이 준비되어 있다. | agent가 identity 없는 active Milestone을 직접 push한다. | Plane ticket 생성, identity backfill commit, 재전달 no-op, secret-redacted evidence가 확인된다. | ## Evidence Map | Scenario | Required Evidence | `agent-task` 연결 | 완료 Evidence 기대 | |----------|-------------------|------------------|---------------------------| | S01 | gitosync scanner/bridge unit test and webhook handler test | `agent-task/m-agent-origin-milestone-creation-sync/...` | `scan-diff` Roadmap Completion, test output, revision mismatch/not-ready evidence | | S02 | roadmapsyncpipeline missing-create idempotency test | `agent-task/m-agent-origin-milestone-creation-sync/...` | `missing-create` Roadmap Completion, duplicate retry evidence | | S03 | storage identity conflict/upsert test | `agent-task/m-agent-origin-milestone-creation-sync/...` | `identity-ledger` Roadmap Completion, conflict evidence | | S04 | identity backfill writer test and git commit scope check | `agent-task/m-agent-origin-milestone-creation-sync/...` | `identity-backfill` Roadmap Completion, commit diff evidence | | S05 | self-loop/redelivery test across process restart or durable ledger | `agent-task/m-agent-origin-milestone-creation-sync/...` | `self-loop` Roadmap Completion, no-op/complete evidence | | S06 | provider identity update projection test | `agent-task/m-agent-origin-milestone-creation-sync/...` | `identity-update` Roadmap Completion, Plane body/title projection evidence | | S07 | conflict classification tests | `agent-task/m-agent-origin-milestone-creation-sync/...` | `conflict-policy` Roadmap Completion, no destructive provider mutation evidence | | S08 | dev field smoke with redacted logs/DB/Plane/git evidence | `agent-task/m-agent-origin-milestone-creation-sync/...` | `field-smoke` Roadmap Completion, final dev cycle evidence without secrets | ## Cross-repo Dependencies - Gito provides `gito.forgejo-branch-events.v1`; NomadCode consumes it through `agent-contract/outer/gito-branch-webhook-consumer-v1.md`. ## Drift Check - [x] Milestone 기능 Task와 Acceptance Scenario가 일치한다. - [x] Evidence Map이 code-review/complete.log에서 검증 가능하다. - [x] agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다. - [x] 사용자 리뷰가 필요한 항목은 `USER_REVIEW.md`에만 남겼다. ## 사용자 리뷰 이력 - 없음 ## 작업 컨텍스트 - 표준선: `develop` branch의 active Milestone markdown이 roadmap source of truth이며, Gito webhook은 wakeup으로만 사용한다. Provider identity block은 repo portable anchor이고, DB ledger는 runtime idempotency/retry state다. - 후속 SDD: Milestone Execution Lifecycle Sync에서 하위 티켓/agent-task lifecycle을 다룰 때 별도 SDD 필요 여부를 다시 판정한다.