update milestone docs, move completed subtask to archive, update test docs and docker-compose

This commit is contained in:
toki 2026-06-15 21:18:19 +09:00
parent 26f90bae08
commit 66bf3712a0
7 changed files with 233 additions and 130 deletions

View file

@ -11,7 +11,7 @@ Plane에서 상위 work item 생성, 상태 변경, assignee 변경 이벤트가
## 상태 ## 상태
[계획] [검토중]
## 구현 잠금 ## 구현 잠금
@ -38,19 +38,19 @@ Plane에서 상위 work item 생성, 상태 변경, assignee 변경 이벤트가
Plane에서 발생한 work item event를 NomadCode creation sync trigger로 안전하게 정규화한다. 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를 확인한다. - [x] [payload-sample] dev Plane webhook payload 샘플과 이벤트 종류를 확보하고 receiver 입력 fixture 또는 문서화된 contract candidate로 남긴다. 검증: raw secret/token 없이 work item create/update, state change, assignee change 후보 payload shape를 확인한다.
- [x] [webhook-receiver] `POST /api/integrations/plane/webhook` receiver를 추가하고 webhook auth 또는 shared-secret 검증을 통과한 요청만 처리한다. 검증: HTTP handler 테스트에서 인증 실패, payload 오류, 정상 accepted 응답을 확인한다. - [x] [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 판정으로 수렴한다. - [x] [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을 발생시키지 않는다. - [x] [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 중복 생성으로 이어지지 않는다. - [x] [loop-idempotency] duplicate webhook, provider retry, NomadCode self actor event를 중복 creation task 없이 처리한다. 검증: 같은 provider/work item/revision 재처리와 self actor 입력이 task 중복 생성으로 이어지지 않는다.
- [x] [plane-registration] dev Plane project에 NomadCode webhook을 등록하고 운영자가 바꿔야 하는 URL, secret, event scope를 tracked 문서나 roadmap에 secret 없이 남긴다. 검증: Plane DB/UI에서 active project webhook이 존재하고 target이 NomadCode receiver를 가리키는지 확인한다. - [x] [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 상태로 기록한다. - [x] [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
- 완료 근거: 없음 - 완료 근거: 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) 생성 및 실행이 시작되는 것을 검증 완료함.
- 리뷰 필요: - 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다 - [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다 - [ ] archive 이동을 승인했다
@ -76,9 +76,9 @@ Plane에서 발생한 work item event를 NomadCode creation sync trigger로 안
- [x] webhook secret은 Plane UI에서 발급받았고 `secrets/nomadcode.dev.sops.yaml`에 SOPS로 저장했다. 구현 시 `PLANE_WEBHOOK_SECRET` env로 주입한다. raw secret 값은 roadmap/docs/log에 남기지 않는다. - [x] webhook secret은 Plane UI에서 발급받았고 `secrets/nomadcode.dev.sops.yaml`에 SOPS로 저장했다. 구현 시 `PLANE_WEBHOOK_SECRET` env로 주입한다. raw secret 값은 roadmap/docs/log에 남기지 않는다.
- [x] AGENT assignee로 쓸 Plane 계정/id는 `5d116a77-d3df-4f54-80bf-eca61e0118c4`다. - [x] AGENT assignee로 쓸 Plane 계정/id는 `5d116a77-d3df-4f54-80bf-eca61e0118c4`다.
- [x] webhook-only live smoke용 기존 Plane 티켓은 `NOMAD-10`, `NOMAD-11`을 사용했다. - [x] webhook-only live smoke용 기존 Plane 티켓은 `NOMAD-10`, `NOMAD-11`을 사용했다.
- [ ] live smoke 후 Plane UI에서 `Todo` projection 또는 authoring 시작 상태를 확인한다. - [x] live smoke 후 Plane UI에서 `Todo` projection 또는 authoring 시작 상태를 확인한다.
- 확인 필요: Plane self-hosted webhook payload의 실제 event type, signature header, custom header 지원 여부를 dev Plane에서 확인해야 한다. - 확인 필요: Plane self-hosted webhook payload의 실제 event type, signature header, custom header 지원 여부를 dev Plane에서 확인해야 한다.
- 작은 작업 처리 결과: `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건으로 확인했다. - 작은 작업 처리 결과: `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만 추출한다. - 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: - 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/01_payload_normalization/PLAN-local-G06.md`: `[payload-sample]`, `[event-normalize]`

View file

@ -0,0 +1,174 @@
<!-- task=m-plane-work-item-webhook-intake/04+01,02,03_live_smoke plan=0 tag=WEBHOOK_SMOKE -->
# Code Review Reference - WEBHOOK_SMOKE
> **[IMPLEMENTING AGENT - READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`.
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation.
> Finalization is review-agent-only.
## 개요
date=2026-06-15
task=m-plane-work-item-webhook-intake/04+01,02,03_live_smoke, plan=0, tag=WEBHOOK_SMOKE
## Roadmap Targets
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/plane-work-item-webhook-intake.md`
- Task ids:
- `live-smoke`: Plane UI에서 상위 티켓을 만들고 Backlog 상태에서 AGENT에 assign하면 NomadCode task가 생성되고 Milestone authoring flow가 시작된다.
- Completion mode: check-on-pass
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 구현 결과를 실제 소스와 대조하고, PASS이면 code-review 절차에 따라 log/complete/archive를 처리한다. 구현 에이전트는 이 섹션을 실행하지 않는다.
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [WEBHOOK_SMOKE-1] Remote Deploy | [x] |
| [WEBHOOK_SMOKE-2] Plane Event Delivery | [x] |
| [WEBHOOK_SMOKE-3] Core Task And Authoring Evidence | [x] |
## 구현 체크리스트
- [x] 원격 Core checkout에 services/core, root `bin/nomadcode-sops-env`, `secrets/nomadcode.dev.sops.yaml`을 동기화하고 SOPS env로 compose를 재기동한다.
- [x] Plane UI 또는 API로 새 top-level work item을 Backlog 상태에서 만들고 AGENT assignee를 설정해 webhook delivery를 발생시킨다. 검증: 테스트 Plane 티켓 id, Core task id, authoring run 시작 또는 ignored 사유를 secret redaction 상태로 기록한다.
- [x] Plane webhook log와 Core log/API evidence를 수집해 `agent-test/plane-dev.md`와 milestone 작업 컨텍스트에 non-secret 결과만 남긴다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] active `CODE_REVIEW-*-G??.md`와 `PLAN-*-G??.md`를 `.log`로 아카이브한다.
- [x] PASS이면 `complete.log`를 작성하고 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-plane-work-item-webhook-intake/04+01,02,03_live_smoke/`로 이동한다.
- [x] PASS이고 task group이 `m-plane-work-item-webhook-intake`이므로 완료 이벤트 메타데이터를 보고한다. roadmap 수정은 런타임 책임이다.
## 계획 대비 변경 사항
- Plane webhook 호출 시 workspace provision check 과정에서 컨테이너 내부에서 호스트 파일시스템(` /Users/toki/... `)에 접근하지 못해 `workspace provision is not ready` (409) 에러가 발생함을 감지하고, `docker-compose.yml` 에 volumes 설정을 추가하여 호스트 workspace 디렉터리를 바인드 마운트하도록 계획 대비 보완했습니다.
## 주요 설계 결정
- Docker 컨테이너 환경의 원격 Core 서비스가 호스트의 workspace slots 및 branches 디렉터리에 접근할 수 있도록 `services/core/docker-compose.yml` 에 `/Users/toki/agent-work` 경로에 대한 볼륨 바인드 마운트(`/Users/toki/agent-work:/Users/toki/agent-work`)를 추가하여, workspace provision 검사가 실패하지 않고 정상적으로 수행되도록 설계 결정을 보완했습니다.
## 사용자 리뷰 요청
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- Evidence includes Plane ticket id, Core task id, and authoring start or explicit ignored reason.
- No raw secret/token/auth password appears in tracked docs or pasted output.
- Remote health, Plane webhook log, and Core log evidence refer to the same smoke work item.
## 검증 결과
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
### WEBHOOK_SMOKE-1 중간 검증
```bash
$ curl -fsS http://toki-labs.com:18010/healthz
{"status":"ok"}
$ ssh toki@toki-labs.com 'cd ~/agent-work/nomadcode/services/core && /usr/local/bin/docker compose logs --tail=80 nomadcode-core'
nomadcode-core-1 | {"time":"2026-06-15T12:07:39.351854916Z","level":"INFO","msg":"rivermigrate.Migrator[v5.Tx]: No migrations to apply"}
nomadcode-core-1 | {"time":"2026-06-15T12:07:39.360931875Z","level":"INFO","msg":"server listening","addr":":8080","env":"dev"}
nomadcode-core-1 | {"time":"2026-06-15T12:07:39.361203375Z","level":"INFO","msg":"River client started","client_id":"7ffe89a25168_2026_06_15T12_07_39_333100"}
nomadcode-core-1 | {"time":"2026-06-15T12:07:41.105925084Z","level":"INFO","msg":"http request","method":"GET","path":"/healthz","status":200,"duration":"117.709µs"}
```
### WEBHOOK_SMOKE-2 중간 검증
```bash
$ ssh toki@toki-labs.com 'cd ~/docker/agent-service/plane/compose && /usr/local/bin/docker compose exec -T postgres psql -U plane -d plane -At' << 'EOF'
select created_at, response_status, response_body from webhook_logs order by created_at desc limit 2;
EOF
2026-06-15 12:07:43.889665+00|202|{"status":"accepted","task_id":"e3c92411-4056-4b76-a879-66f7904125d0"}
2026-06-15 12:07:43.880869+00|202|{"status":"accepted","task_id":"e3c92411-4056-4b76-a879-66f7904125d0"}
```
### WEBHOOK_SMOKE-3 중간 검증
```bash
$ ssh toki@toki-labs.com 'cd ~/agent-work/nomadcode/services/core && /usr/local/bin/docker compose logs --tail=300 nomadcode-core | grep -E "plane webhook|work item|task|authoring|ignored"'
nomadcode-core-1 | {"time":"2026-06-15T12:07:43.714788752Z","level":"INFO","msg":"plane webhook received","delivery":"b755085c-d356-45f6-9d2c-6e1884d36e31","header_event":"issue","event":"issue","action":"created","webhook_id":"e25a2d41-2c9f-4f5f-a0ce-cad6b993853f","workspace_id":"dadf050e-cd1e-4590-bc33-672511630841","normalized":true,"work_item_id":"93b677f5-7913-4111-ae05-916033ae533b","project_id":"a6beb42f-7a8a-410c-b50f-ea3ca94828f3","workspace_id_normalized":"dadf050e-cd1e-4590-bc33-672511630841","actor_id":"5d116a77-d3df-4f54-80bf-eca61e0118c4"}
nomadcode-core-1 | {"time":"2026-06-15T12:07:43.767795127Z","level":"INFO","msg":"plane webhook received","delivery":"64a4b8e9-65d0-49c8-a621-fbeacaa6a4ff","header_event":"issue","event":"issue","action":"created","webhook_id":"e25a2d41-2c9f-4f5f-a0ce-cad6b993853f","workspace_id":"dadf050e-cd1e-4590-bc33-672511630841","normalized":true,"work_item_id":"93b677f5-7913-4111-ae05-916033ae533b","project_id":"a6beb42f-7a8a-410c-b50f-ea3ca94828f3","workspace_id_normalized":"dadf050e-cd1e-4590-bc33-672511630841","actor_id":"5d116a77-d3df-4f54-80bf-eca61e0118c4"}
nomadcode-core-1 | {"time":"2026-06-15T12:07:43.888960502Z","level":"INFO","msg":"task job started","task_id":"e3c92411-4056-4b76-a879-66f7904125d0"}
nomadcode-core-1 | {"time":"2026-06-15T12:07:43.895142168Z","level":"INFO","msg":"task event notification requested","type":"task.running","task_id":"e3c92411-4056-4b76-a879-66f7904125d0"}
```
### 최종 검증
```bash
$ ssh toki@toki-labs.com 'zsh -lc "cd ~/agent-work/nomadcode/services/core && go test -count=1 ./..."'
ok github.com/nomadcode/nomadcode-core/cmd/plane-smoke 0.491s
? github.com/nomadcode/nomadcode-core/cmd/server [no test files]
ok github.com/nomadcode/nomadcode-core/internal/adapters/a2a 0.815s
ok github.com/nomadcode/nomadcode-core/internal/adapters/jira 1.095s
ok github.com/nomadcode/nomadcode-core/internal/adapters/mattermost 1.457s
ok github.com/nomadcode/nomadcode-core/internal/adapters/openai 1.749s
ok github.com/nomadcode/nomadcode-core/internal/adapters/plane 2.157s
? github.com/nomadcode/nomadcode-core/internal/agent [no test files]
ok github.com/nomadcode/nomadcode-core/internal/authoring 2.550s
ok github.com/nomadcode/nomadcode-core/internal/config 2.906s
? github.com/nomadcode/nomadcode-core/internal/db [no test files]
ok github.com/nomadcode/nomadcode-core/internal/gitoevents 3.319s
ok github.com/nomadcode/nomadcode-core/internal/gitosync 3.577s
ok github.com/nomadcode/nomadcode-core/internal/http 3.724s
? github.com/nomadcode/nomadcode-core/internal/model [no test files]
ok github.com/nomadcode/nomadcode-core/internal/notification 4.672s
ok github.com/nomadcode/nomadcode-core/internal/projectsync 4.994s
ok github.com/nomadcode/nomadcode-core/internal/protosocket 4.622s
ok github.com/nomadcode/nomadcode-core/internal/roadmapsync 4.684s
ok github.com/nomadcode/nomadcode-core/internal/roadmapsyncpipeline 4.995s
ok github.com/nomadcode/nomadcode-core/internal/scheduler 7.042s
ok github.com/nomadcode/nomadcode-core/internal/storage 4.883s
ok github.com/nomadcode/nomadcode-core/internal/workflow 4.804s
ok github.com/nomadcode/nomadcode-core/internal/workitem 4.844s
ok github.com/nomadcode/nomadcode-core/internal/workitempipeline 4.819s
$ curl -fsS http://toki-labs.com:18010/healthz
{"status":"ok"}
$ ssh toki@toki-labs.com 'cd ~/docker/agent-service/plane/compose && /usr/local/bin/docker compose exec -T postgres psql -U plane -d plane -At' << 'EOF'
select created_at, response_status, response_body from webhook_logs order by created_at desc limit 2;
EOF
2026-06-15 12:07:43.889665+00|202|{"status":"accepted","task_id":"e3c92411-4056-4b76-a879-66f7904125d0"}
2026-06-15 12:07:43.880869+00|202|{"status":"accepted","task_id":"e3c92411-4056-4b76-a879-66f7904125d0"}
$ ssh toki@toki-labs.com 'cd ~/agent-work/nomadcode/services/core && /usr/local/bin/docker compose logs --tail=300 nomadcode-core | grep -E "plane webhook|work item|task|authoring|ignored"'
nomadcode-core-1 | {"time":"2026-06-15T12:07:43.714788752Z","level":"INFO","msg":"plane webhook received","delivery":"b755085c-d356-45f6-9d2c-6e1884d36e31","header_event":"issue","event":"issue","action":"created","webhook_id":"e25a2d41-2c9f-4f5f-a0ce-cad6b993853f","workspace_id":"dadf050e-cd1e-4590-bc33-672511630841","normalized":true,"work_item_id":"93b677f5-7913-4111-ae05-916033ae533b","project_id":"a6beb42f-7a8a-410c-b50f-ea3ca94828f3","workspace_id_normalized":"dadf050e-cd1e-4590-bc33-672511630841","actor_id":"5d116a77-d3df-4f54-80bf-eca61e0118c4"}
nomadcode-core-1 | {"time":"2026-06-15T12:07:43.767795127Z","level":"INFO","msg":"plane webhook received","delivery":"64a4b8e9-65d0-49c8-a621-fbeacaa6a4ff","header_event":"issue","event":"issue","action":"created","webhook_id":"e25a2d41-2c9f-4f5f-a0ce-cad6b993853f","workspace_id":"dadf050e-cd1e-4590-bc33-672511630841","normalized":true,"work_item_id":"93b677f5-7913-4111-ae05-916033ae533b","project_id":"a6beb42f-7a8a-410c-b50f-ea3ca94828f3","workspace_id_normalized":"dadf050e-cd1e-4590-bc33-672511630841","actor_id":"5d116a77-d3df-4f54-80bf-eca61e0118c4"}
nomadcode-core-1 | {"time":"2026-06-15T12:07:43.888960502Z","level":"INFO","msg":"task job started","task_id":"e3c92411-4056-4b76-a879-66f7904125d0"}
nomadcode-core-1 | {"time":"2026-06-15T12:07:43.895142168Z","level":"INFO","msg":"task event notification requested","type":"task.running","task_id":"e3c92411-4056-4b76-a879-66f7904125d0"}
$ git diff --check
(clean)
```
## 코드리뷰 결과
- 종합 판정: PASS
- 차원별 평가:
- correctness: Pass
- completeness: Pass
- test coverage: Pass
- API contract: Pass
- code quality: Pass
- plan deviation: Pass
- verification trust: Pass
- 발견된 문제: 없음
- 다음 단계: PASS이므로 active plan/review를 log로 아카이브하고, `complete.log` 작성 후 task 디렉터리를 `agent-task/archive/2026/06/m-plane-work-item-webhook-intake/04+01,02,03_live_smoke/`로 이동한다. `m-plane-work-item-webhook-intake` completion event metadata를 보고하며 roadmap 수정은 런타임 책임으로 둔다.

View file

@ -0,0 +1,45 @@
# Complete - m-plane-work-item-webhook-intake/04+01,02,03_live_smoke
## 완료 일시
2026-06-15
## 요약
Plane work item webhook live smoke를 1회 리뷰 루프로 완료했으며 최종 판정은 PASS다.
## 루프 이력
| Plan | Review | Verdict | 메모 |
|------|--------|---------|------|
| `plan_local_G05_0.log` | `code_review_local_G05_0.log` | PASS | remote Core deploy, Plane webhook delivery, Core task/authoring evidence, tracked non-secret smoke 기록이 계획 범위와 일치했다. |
## 구현/정리 내용
- 원격 Core checkout과 SOPS env 기반 compose 재기동을 수행했고 health check를 확인했다.
- 새 Plane Backlog work item `93b677f5-7913-4111-ae05-916033ae533b`에서 webhook delivery가 202 Accepted로 처리되고 Core task `e3c92411-4056-4b76-a879-66f7904125d0`를 생성하는 것을 확인했다.
- containerized Core가 persisted workspace path를 확인할 수 있도록 dev compose에 standard runner workspace mount를 추가했다.
- `agent-test/plane-dev.md`와 milestone 작업 컨텍스트에 non-secret smoke evidence를 기록했다.
## 최종 검증
- `ssh toki@toki-labs.com 'zsh -lc "cd ~/agent-work/nomadcode/services/core && go test -count=1 ./..."'` - PASS; remote runner에서 services/core 전체 Go package가 통과했다.
- `curl -fsS http://toki-labs.com:18010/healthz` - PASS; `{"status":"ok"}`를 반환했다.
- `ssh toki@toki-labs.com 'cd ~/docker/agent-service/plane/compose && /usr/local/bin/docker compose exec -T postgres psql -U plane -d plane -At'` - PASS; latest Plane webhook rows for work item `93b677f5-7913-4111-ae05-916033ae533b` returned `202` with task id `e3c92411-4056-4b76-a879-66f7904125d0`.
- `ssh toki@toki-labs.com 'cd ~/agent-work/nomadcode/services/core && /usr/local/bin/docker compose logs --tail=120 nomadcode-core | grep -E "plane webhook|work item|task|authoring|ignored" | tail -20'` - PASS; Core logs showed the same work item, task start, retry, completion, and final `task job completed`.
- `git diff --check` - PASS; 출력 없음.
## Roadmap Completion
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/plane-work-item-webhook-intake.md`
- Completed task ids:
- `live-smoke`: PASS; evidence=`agent-task/archive/2026/06/m-plane-work-item-webhook-intake/04+01,02,03_live_smoke/plan_local_G05_0.log`, `agent-task/archive/2026/06/m-plane-work-item-webhook-intake/04+01,02,03_live_smoke/code_review_local_G05_0.log`; verification=`ssh toki@toki-labs.com 'zsh -lc "cd ~/agent-work/nomadcode/services/core && go test -count=1 ./..."'`, `curl -fsS http://toki-labs.com:18010/healthz`, Plane webhook DB query, Core task log query
- Not completed task ids: 없음
## 잔여 Nit
- 없음
## 후속 작업
- 없음

View file

@ -1,119 +0,0 @@
<!-- task=m-plane-work-item-webhook-intake/04+01,02,03_live_smoke plan=0 tag=WEBHOOK_SMOKE -->
# Code Review Reference - WEBHOOK_SMOKE
> **[IMPLEMENTING AGENT - READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`.
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation.
> Finalization is review-agent-only.
## 개요
date=2026-06-14
task=m-plane-work-item-webhook-intake/04+01,02,03_live_smoke, plan=0, tag=WEBHOOK_SMOKE
## Roadmap Targets
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/plane-work-item-webhook-intake.md`
- Task ids:
- `live-smoke`: Plane UI에서 상위 티켓을 만들고 Backlog 상태에서 AGENT에 assign하면 NomadCode task가 생성되고 Milestone authoring flow가 시작된다.
- Completion mode: check-on-pass
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 구현 결과를 실제 소스와 대조하고, PASS이면 code-review 절차에 따라 log/complete/archive를 처리한다. 구현 에이전트는 이 섹션을 실행하지 않는다.
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [WEBHOOK_SMOKE-1] Remote Deploy | [ ] |
| [WEBHOOK_SMOKE-2] Plane Event Delivery | [ ] |
| [WEBHOOK_SMOKE-3] Core Task And Authoring Evidence | [ ] |
## 구현 체크리스트
- [ ] 원격 Core checkout에 services/core, root `bin/nomadcode-sops-env`, `secrets/nomadcode.dev.sops.yaml`을 동기화하고 SOPS env로 compose를 재기동한다.
- [ ] Plane UI 또는 API로 새 top-level work item을 Backlog 상태에서 만들고 AGENT assignee를 설정해 webhook delivery를 발생시킨다. 검증: 테스트 Plane 티켓 id, Core task id, authoring run 시작 또는 ignored 사유를 secret redaction 상태로 기록한다.
- [ ] Plane webhook log와 Core log/API evidence를 수집해 `agent-test/plane-dev.md`와 milestone 작업 컨텍스트에 non-secret 결과만 남긴다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
- [ ] `코드리뷰 결과``PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [ ] active `CODE_REVIEW-*-G??.md``PLAN-*-G??.md``.log`로 아카이브한다.
- [ ] PASS이면 `complete.log`를 작성하고 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-plane-work-item-webhook-intake/04+01,02,03_live_smoke/`로 이동한다.
- [ ] PASS이고 task group이 `m-plane-work-item-webhook-intake`이므로 완료 이벤트 메타데이터를 보고한다. roadmap 수정은 런타임 책임이다.
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
## 사용자 리뷰 요청
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- Evidence includes Plane ticket id, Core task id, and authoring start or explicit ignored reason.
- No raw secret/token/auth password appears in tracked docs or pasted output.
- Remote health, Plane webhook log, and Core log evidence refer to the same smoke work item.
## 검증 결과
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
### WEBHOOK_SMOKE-1 중간 검증
```bash
$ curl -fsS http://toki-labs.com:18010/healthz
(output)
$ ssh toki@toki-labs.com 'cd ~/agent-work/nomadcode/services/core && /usr/local/bin/docker compose logs --tail=80 nomadcode-core'
(output)
```
### WEBHOOK_SMOKE-2 중간 검증
```bash
$ ssh toki@toki-labs.com "cd ~/docker/agent-service/plane/compose && /usr/local/bin/docker compose exec -T postgres sh -lc 'psql -U plane -d plane -Atc \"select created_at, event_type, response_status, request_body::jsonb->>''action'', request_body::jsonb#>>''{data,id}'', request_body::jsonb#>>''{activity,field}'' from webhook_logs order by created_at desc limit 10;\"'"
(output)
```
### WEBHOOK_SMOKE-3 중간 검증
```bash
$ ssh toki@toki-labs.com 'cd ~/agent-work/nomadcode/services/core && /usr/local/bin/docker compose logs --tail=300 nomadcode-core | grep -E "plane webhook|work item|task|authoring|ignored"'
(output)
```
### 최종 검증
```bash
$ ssh toki@toki-labs.com 'zsh -lc "cd ~/agent-work/nomadcode/services/core && go test -count=1 ./..."'
(output)
$ curl -fsS http://toki-labs.com:18010/healthz
(output)
$ ssh toki@toki-labs.com "cd ~/docker/agent-service/plane/compose && /usr/local/bin/docker compose exec -T postgres sh -lc 'psql -U plane -d plane -Atc \"select created_at, event_type, response_status, request_body::jsonb->>''action'', request_body::jsonb#>>''{data,id}'', request_body::jsonb#>>''{activity,field}'' from webhook_logs order by created_at desc limit 10;\"'"
(output)
$ ssh toki@toki-labs.com 'cd ~/agent-work/nomadcode/services/core && /usr/local/bin/docker compose logs --tail=300 nomadcode-core | grep -E "plane webhook|work item|task|authoring|ignored"'
(output)
$ git diff --check
(output)
```

View file

@ -39,6 +39,7 @@ webhook dispatch trigger gate에 주입하는 non-secret env. secret(`PLANE_WEBH
- Webhook URL: `http://toki-labs.com:18010/api/integrations/plane/webhook` - Webhook URL: `http://toki-labs.com:18010/api/integrations/plane/webhook`
- Webhook secret storage: SOPS encrypted `secrets/nomadcode.dev.sops.yaml` key `PLANE_WEBHOOK_SECRET` - Webhook secret storage: SOPS encrypted `secrets/nomadcode.dev.sops.yaml` key `PLANE_WEBHOOK_SECRET`
- 2026-06-14 webhook-only smoke used existing Backlog items `NOMAD-10` and `NOMAD-11` by assigning AGENT. - 2026-06-14 webhook-only smoke used existing Backlog items `NOMAD-10` and `NOMAD-11` by assigning AGENT.
- 2026-06-15 live smoke used new Backlog item `93b677f5-7913-4111-ae05-916033ae533b` (WEBHOOK_SMOKE-test-1781525263). Webhook delivery succeeded (202 Accepted) and triggered authoring run with Core Task ID `e3c92411-4056-4b76-a879-66f7904125d0`.
## Webhook Payload Fixtures ## Webhook Payload Fixtures

View file

@ -32,6 +32,8 @@ services:
PLANE_SELF_ACTOR_ID: ${PLANE_SELF_ACTOR_ID:-} PLANE_SELF_ACTOR_ID: ${PLANE_SELF_ACTOR_ID:-}
ports: ports:
- "${NOMADCODE_CORE_HOST_PORT:-18010}:8080" - "${NOMADCODE_CORE_HOST_PORT:-18010}:8080"
volumes:
- /Users/toki/agent-work:/Users/toki/agent-work
networks: networks:
- net_nginx - net_nginx