nomadcode/agent-roadmap/archive/phase/agent-ops-mcp-control-plane/milestones/plane-work-item-webhook-intake.md
toki 0109c89eb9 update: agent-ops-mcp-control-plane 로드맵 정리 및 gitoevents 클라이언트 개선
- 마일스톤 문서 archive로 이동 (gito-branch-event-sync-bridge, plane-work-item-webhook-intake)
- PHASE.md 및 ROADMAP.md 갱신
- gitoevents/client.go: 클라이언트 로직 개선
- gitoevents/client_test.go: 테스트 커버리지 추가
2026-06-16 21:05:31 +09:00

8.7 KiB

Milestone: Plane Work Item Webhook Intake

위치

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

목표

Plane에서 상위 work item 생성, 상태 변경, assignee 변경 이벤트가 발생하면 NomadCode Core가 이를 webhook으로 받아 Backlog + AGENT assignee 조건을 재검증하고 기존 Plane-origin Milestone creation sync pipeline을 시작한다. 이 마일스톤이 끝나면 사용자는 Plane UI에서 티켓을 만들고 AGENT에 assign하는 동작만으로 NomadCode authoring flow가 시작되는지 확인할 수 있다.

상태

[완료]

구현 잠금

  • 상태: 해제
  • 결정 필요:
    • dev Plane에서 호출할 NomadCode Core webhook URL은 http://toki-labs.com:18010/api/integrations/plane/webhook로 둔다. plane.toki-labs.com은 Plane의 동일 호스트/하위 도메인 차단 규칙에 걸리므로 사용하지 않는다.
    • Plane webhook 인증 방식은 Plane UI에서 발급한 webhook secret/signature 검증으로 둔다. secret 원문은 tracked 파일에 기록하지 않고 SOPS encrypted file secrets/nomadcode.dev.sops.yamlPLANE_WEBHOOK_SECRET으로 보관한다.
    • AGENT assignee로 사용할 Plane user id는 5d116a77-d3df-4f54-80bf-eca61e0118c4로 확인했다.
    • webhook-only live smoke는 기존 Backlog item NOMAD-10, NOMAD-11의 AGENT assign 이벤트로 확인했다.

범위

  • Plane native webhook payload 샘플을 확보하고 work item 생성, 상태 변경, assignee 변경 이벤트에서 필요한 필드를 식별한다.
  • NomadCode Core에 Plane raw webhook receiver endpoint를 추가한다.
  • Plane webhook secret/signature 또는 동등한 shared-secret 검증을 구현하고, raw secret은 tracked 파일과 로그에 남기지 않는다.
  • webhook payload는 변경 힌트로만 사용하고, 최종 trigger 판정 전 Plane API로 work item을 다시 조회한다.
  • 기존 workitempipeline trigger gate를 재사용해 Backlog + AGENT assignee 조건, actor/self guard, project sync setting, workspace provision, slot reservation 경계를 유지한다.
  • 중복 webhook, 재시도, NomadCode self mutation event가 들어와도 중복 task나 중복 Milestone authoring run을 만들지 않도록 idempotency 기준을 고정한다.
  • dev Plane project에 webhook을 등록하고, 사용자가 Plane UI에서 상위 티켓 생성/assign만으로 NomadCode flow가 시작되는 smoke를 확인한다.

기능

Epic: [plane-webhook] Plane Webhook Intake

Plane에서 발생한 work item event를 NomadCode creation sync trigger로 안전하게 정규화한다.

  • [payload-sample] dev Plane webhook payload 샘플과 이벤트 종류를 확보하고 receiver 입력 fixture 또는 문서화된 contract candidate로 남긴다. 검증: raw secret/token 없이 work item create/update, state change, assignee change 후보 payload shape를 확인한다.
  • [webhook-receiver] POST /api/integrations/plane/webhook receiver를 추가하고 webhook auth 또는 shared-secret 검증을 통과한 요청만 처리한다. 검증: HTTP handler 테스트에서 인증 실패, payload 오류, 정상 accepted 응답을 확인한다.
  • [event-normalize] Plane webhook payload를 provider-neutral work item ref와 actor/change hint로 정규화하되, 최종 work item 상태는 Plane API 재조회 결과를 사용한다. 검증: payload 필드 누락 또는 stale event가 있어도 fetch 기반 trigger 판정으로 수렴한다.
  • [trigger-dispatch] Backlog + AGENT assignee 이벤트만 기존 workitempipeline.CreateTaskFromWorkItem 경로로 넘기고 나머지는 side effect 없이 ignored 처리한다. 검증: ignored event가 workspace provision 또는 slot reservation을 발생시키지 않는다.
  • [loop-idempotency] duplicate webhook, provider retry, NomadCode self actor event를 중복 creation task 없이 처리한다. 검증: 같은 provider/work item/revision 재처리와 self actor 입력이 task 중복 생성으로 이어지지 않는다.
  • [plane-registration] dev Plane project에 NomadCode webhook을 등록하고 운영자가 바꿔야 하는 URL, secret, event scope를 tracked 문서나 roadmap에 secret 없이 남긴다. 검증: Plane DB/UI에서 active project webhook이 존재하고 target이 NomadCode receiver를 가리키는지 확인한다.
  • [live-smoke] Plane UI에서 상위 티켓을 만들고 Backlog 상태에서 AGENT에 assign하면 NomadCode task가 생성되고 Milestone authoring flow가 시작된다. 검증: 테스트 Plane 티켓 id, Core task id, authoring run 시작 또는 ignored 사유를 secret redaction 상태로 기록한다.

완료 리뷰

  • 상태: 승인됨
  • 요청일: 2026-06-15
  • 승인일: 2026-06-16
  • 완료 근거: Plane Webhook intake 및 normalized trigger dispatch, idempotency 처리가 구현 및 원격 배포되었으며, 2026-06-15 live smoke 테스트를 통해 Plane UI/API에서 새 Backlog 티켓 생성 및 AGENT assignee 지정 시 webhook 202 Accepted 수신 및 Core Task(e3c92411-4056-4b76-a879-66f7904125d0) 생성 및 실행이 시작되는 것을 검증 완료함. 2026-06-16 코드 레벨 재검토에서 receiver/auth/normalize/dispatch/idempotency/config wiring과 관련 테스트를 재확인했고 blocking issue가 없었다.
  • 리뷰 필요:
    • 사용자가 완료 결과를 확인했다
    • archive 이동을 승인했다
  • 리뷰 코멘트: 코드 레벨 검토 후 종료 처리함.

범위 제외

  • Plane Todo -> In Progress 실행 lifecycle 시작
  • Milestone Task를 Plane 하위 티켓으로 생성하거나 동기화하는 구현
  • Gito branch.updated event producer 또는 proto-socket consumer 구현
  • Jira webhook intake
  • provider polling 기반 reconcile loop 구현
  • 사용자 승인 없는 archive 이동

작업 컨텍스트

  • 관련 경로: services/core/internal/http/, services/core/internal/workitempipeline/, services/core/internal/adapters/plane/, services/core/internal/scheduler/, services/core/internal/roadmapsyncpipeline/, services/core/internal/config/, packages/contracts/notes/, agent-roadmap/
  • 표준선: Plane webhook payload는 신뢰할 source of truth가 아니라 wakeup hint로 취급하고, NomadCode는 Plane API 재조회와 기존 trigger gate로 실제 실행 여부를 결정한다.
  • 선행 작업: Milestone Work Item Creation Sync
  • 후속 작업: Gito Branch Event Creation Sync Bridge, Milestone Execution Lifecycle Sync
  • 사용자 액션:
    • NomadCode Core webhook endpoint는 dev Plane에서 접근 가능한 http://toki-labs.com:18010/api/integrations/plane/webhook로 사용한다.
    • webhook secret은 Plane UI에서 발급받았고 secrets/nomadcode.dev.sops.yaml에 SOPS로 저장했다. 구현 시 PLANE_WEBHOOK_SECRET env로 주입한다. raw secret 값은 roadmap/docs/log에 남기지 않는다.
    • AGENT assignee로 쓸 Plane 계정/id는 5d116a77-d3df-4f54-80bf-eca61e0118c4다.
    • webhook-only live smoke용 기존 Plane 티켓은 NOMAD-10, NOMAD-11을 사용했다.
    • live smoke 후 Plane UI에서 Todo projection 또는 authoring 시작 상태를 확인한다.
  • 확인 필요: 없음
  • 작은 작업 처리 결과: webhook-receiver는 signed fixture/invalid signature/basic-auth bypass 테스트와 dev Core synthetic/live webhook smoke로 확인했다. plane-registration은 dev Plane active webhook e25a2d41-2c9f-4f5f-a0ce-cad6b993853f, target http://toki-labs.com:18010/api/integrations/plane/webhook, issue=True, response 202 발송 로그 8건으로 확인했다. 2026-06-15 live smoke에서 Plane issue 93b677f5-7913-4111-ae05-916033ae533b에 대한 webhook 수신(202 Accepted) 및 Core Task e3c92411-4056-4b76-a879-66f7904125d0 기동을 검증함.
  • payload fixture: assignee update 샘플은 services/core/internal/http/testdata/plane_webhook_issue_assignees_updated.json에 PII redaction 상태로 남겼다. create/state-change 후보는 plane_webhook_issue_created.json, plane_webhook_issue_state_updated.json으로 추가했고 live create/state 로그 미확보로 관찰된 issue envelope 기반 synthetic candidate임을 agent-test/plane-dev.md에 명시했다. normalize helper(normalizePlaneWebhookPayload)는 payload를 wakeup hint로만 보고 provider-neutral ref/actor/change hint만 추출한다.
  • plane-webhook 후속 plan:
    • agent-task/m-plane-work-item-webhook-intake/01_payload_normalization/PLAN-local-G06.md: [payload-sample], [event-normalize]
    • agent-task/m-plane-work-item-webhook-intake/02+01_trigger_dispatch/PLAN-local-G07.md: [trigger-dispatch]
    • agent-task/m-plane-work-item-webhook-intake/03+02_idempotency/PLAN-cloud-G06.md: [loop-idempotency]
    • agent-task/m-plane-work-item-webhook-intake/04+01,02,03_live_smoke/PLAN-local-G05.md: [live-smoke]