update: agent-test files - refine dev rules, live-cycle smoke tests, and plane-dev

This commit is contained in:
toki 2026-07-03 15:51:38 +09:00
parent 1d5708542e
commit ea97e73608
3 changed files with 244 additions and 6 deletions

View file

@ -1,6 +1,6 @@
--- ---
test_env: dev test_env: dev
last_rule_updated_at: 2026-07-01 last_rule_updated_at: 2026-07-03
--- ---
# dev 테스트 규칙 # dev 테스트 규칙
@ -16,6 +16,7 @@ last_rule_updated_at: 2026-07-01
- raw token, password, webhook secret, provider credential, private key는 ignored local profile 또는 remote secret store에서만 주입한다. - raw token, password, webhook secret, provider credential, private key는 ignored local profile 또는 remote secret store에서만 주입한다.
- 컨테이너 내부 listen 포트는 제품 기본값을 우선 유지하고, workspace 충돌 관리는 host publish/direct smoke 포트로 처리한다. - 컨테이너 내부 listen 포트는 제품 기본값을 우선 유지하고, workspace 충돌 관리는 host publish/direct smoke 포트로 처리한다.
- 테스트용 Docker subnet을 새로 만들 때는 `192.168.0.0/24` 대역을 사용하지 않는다. - 테스트용 Docker subnet을 새로 만들 때는 `192.168.0.0/24` 대역을 사용하지 않는다.
- Plane-origin full-cycle 검증은 `agent-test/live-cycle-smoke.md`를 따른다. 수동 Gito redelivery는 진단/복구 근거일 뿐 자동 Forgejo -> Gito 경로 통과 근거로 기록하지 않는다.
## 기본 환경 ## 기본 환경
@ -49,8 +50,17 @@ dev NomadCode의 Gito webhook target은 `http://127.0.0.1:18011/api/integrations
- `GITO_DEVELOP_REPO_PATH`는 Core container에서 접근 가능한 checkout path여야 한다. - `GITO_DEVELOP_REPO_PATH`는 Core container에서 접근 가능한 checkout path여야 한다.
- 계약 원문은 `agent-contract/outer/gito-branch-webhook-consumer-v1.md`와 Gito 제공 계약 `../gito/agent-contract/provided/gito-forgejo-branch-events-v1.md`를 함께 따른다. - 계약 원문은 `agent-contract/outer/gito-branch-webhook-consumer-v1.md`와 Gito 제공 계약 `../gito/agent-contract/provided/gito-forgejo-branch-events-v1.md`를 함께 따른다.
## Forgejo -> Gito Webhook 기준
- dev Forgejo repository hook이 host Gito dev port로 delivery할 때 target은 `http://host.docker.internal:18061/callbacks/forgejo/push?repo_id=nomadcode` 형태일 수 있다.
- 이 경우 Forgejo app config `[webhook] ALLOWED_HOST_LIST`에는 기존 허용 host와 함께 `host.docker.internal`이 포함되어야 한다.
- allowlist가 막히면 Forgejo `hook_task.response_content``webhook can only call allowed HTTP servers`가 남고, Core task는 git push 후 `develop_match` 대기에서 멈출 수 있다.
- allowlist를 조정할 때는 config 백업을 먼저 만들고, raw secret이나 token 값은 조회/출력/기록하지 않는다.
- Forgejo 컨테이너에서 `curl http://host.docker.internal:18061/healthz`가 성공해야 provider callback 네트워크가 열린 것으로 본다.
## 라우팅 ## 라우팅
- core / full-cycle / Plane-origin milestone authoring, git develop push, Forgejo/Gito branch.updated, Plane Todo projection: `agent-test/live-cycle-smoke.md`
- core / smoke / services/core backend baseline: `agent-test/local/core-smoke.md` - core / smoke / services/core backend baseline: `agent-test/local/core-smoke.md`
- mobile / smoke / apps/client Flutter baseline: `agent-test/local/mobile-smoke.md` - mobile / smoke / apps/client Flutter baseline: `agent-test/local/mobile-smoke.md`
- mobile / smoke / Android SDK remote runner and debug APK validation: `agent-test/local/mobile-android-sdk-smoke.md` - mobile / smoke / Android SDK remote runner and debug APK validation: `agent-test/local/mobile-android-sdk-smoke.md`

View file

@ -1,25 +1,29 @@
--- ---
test_env: local test_env: local
test_env_scope: local_and_dev_profiles
test_profile: live-cycle-smoke test_profile: live-cycle-smoke
domain: core domain: core
verification_type: smoke verification_type: smoke
last_rule_updated_at: 2026-06-21 last_rule_updated_at: 2026-07-03
--- ---
# live-cycle-smoke # live-cycle-smoke
전체 webhook → authoring → develop match → Plane projection → slot 회수 사이클을 검증한다. 전체 webhook -> authoring -> git develop push -> Forgejo/Gito branch event -> Plane projection -> slot 회수 사이클을 검증한다.
이 문서는 절차 기술과 runtime-equivalent 근거를 함께 기록한다. 이 문서는 절차 기술과 runtime-equivalent 근거를 함께 기록한다.
## 읽기 조건 ## 읽기 조건
- `live-webhook-task`, `webhook-auto-enqueue`, `live-creation-projection` 증거가 필요한 경우. - `live-webhook-task`, `webhook-auto-enqueue`, `live-creation-projection` 증거가 필요한 경우.
- dev profile에서 Plane-origin milestone 생성이 git에 등록되고 다시 Plane `Todo`로 이동하는지 검증하는 경우.
- `agent-task/m-milestone-work-item-creation-sync/14+12,13_live_cycle_smoke` 구현/리뷰 시. - `agent-task/m-milestone-work-item-creation-sync/14+12,13_live_cycle_smoke` 구현/리뷰 시.
## 환경 ## 환경
- host: standard remote runner `toki@toki-labs.com`, checkout `$HOME/agent-work/nomadcode`. - host: standard remote runner `toki@toki-labs.com`.
- Core server: Docker Compose (`services/core/docker-compose.yml`), host port `18010->8080`. - local profile checkout: `$HOME/agent-work/nomadcode`, Core host port `18010->8080`, Gito source `18060`.
- dev profile checkout: `$HOME/agent-work/nomadcode-dev`, Core host port `18011->8080`, Gito source `18061`.
- Core server: Docker Compose (`services/core/docker-compose.yml`).
- Plane dev: `https://plane.toki-labs.com`, workspace `general`, project `NOMAD`. - Plane dev: `https://plane.toki-labs.com`, workspace `general`, project `NOMAD`.
- Secrets: `.env.plane.local` (ignored), SOPS `secrets/nomadcode.dev.sops.yaml` (webhook secret). - Secrets: `.env.plane.local` (ignored), SOPS `secrets/nomadcode.dev.sops.yaml` (webhook secret).
- runner checkout: 검증용 disposable mirror다. dirty worktree, uncommitted 변경, 임시 파일을 이유로 중단하지 않고 현재 대화 workspace의 요청 범위 상태와 같게 reset/clean/reclone 또는 파일 동기화한 뒤 테스트한다. - runner checkout: 검증용 disposable mirror다. dirty worktree, uncommitted 변경, 임시 파일을 이유로 중단하지 않고 현재 대화 workspace의 요청 범위 상태와 같게 reset/clean/reclone 또는 파일 동기화한 뒤 테스트한다.
@ -30,6 +34,32 @@ last_rule_updated_at: 2026-06-21
- `PLANE_WEBHOOK_SECRET`, `PLANE_TOKEN` 등 secret은 `.env.plane.local` 또는 SOPS에서 로드한다. - `PLANE_WEBHOOK_SECRET`, `PLANE_TOKEN` 등 secret은 `.env.plane.local` 또는 SOPS에서 로드한다.
- Plane dev 서버가 `https://plane.toki-labs.com`에서 정상 동작 중이어야 한다. - Plane dev 서버가 `https://plane.toki-labs.com`에서 정상 동작 중이어야 한다.
- workspace slot 행이 DB에 `available` 상태로 최소 1개 이상 있어야 한다. - workspace slot 행이 DB에 `available` 상태로 최소 1개 이상 있어야 한다.
- dev profile에서는 `agent-test/dev/rules.md`를 먼저 읽고, Core `18011`, Gito `18061`, Forgejo provider hook 경로가 모두 열려 있어야 한다.
- Forgejo repository hook이 `host.docker.internal:18061`로 Gito에 전달하는 환경이면 Forgejo `[webhook] ALLOWED_HOST_LIST``host.docker.internal`을 허용해야 한다.
## dev profile 프리플라이트
아래 확인은 secret 값을 출력하지 않는다. 실패하면 Plane work item을 새로 만들기 전에 환경을 먼저 고친다.
```sh
# 1. Core/Gito readiness
curl -fsS http://127.0.0.1:18011/readyz
curl -fsS http://127.0.0.1:18061/readyz
# 2. Gito branch watch / subscription
curl -fsS http://127.0.0.1:18061/api/listeners/branches
curl -fsS http://127.0.0.1:18061/api/webhook-subscriptions
# Expected: repo_id=nomadcode, branch=develop, event=branch.updated.
# 3. Forgejo container -> Gito host endpoint reachability
docker exec forgejo curl -fsS --max-time 5 http://host.docker.internal:18061/healthz
# 4. Forgejo webhook allowlist
docker exec forgejo sh -c 'grep -n "^ALLOWED_HOST_LIST" /data/gitea/conf/app.ini'
# Expected when hook target uses host.docker.internal: value includes host.docker.internal.
```
Gito watch 또는 subscription이 없으면 Gito 제공 계약의 `/api/listeners/branches``/api/webhook-subscriptions` bootstrap 절차를 따른다. raw secret 대신 `secret_ref` 또는 환경 참조만 사용한다.
## Fixture IDs (non-secret) ## Fixture IDs (non-secret)
@ -87,6 +117,107 @@ for t in d.get('tasks', []):
# 9. slot 재사용 확인: 두 번째 smoke 티켓 생성 → 같은 slot_id 또는 새 available slot에서 reservation # 9. slot 재사용 확인: 두 번째 smoke 티켓 생성 → 같은 slot_id 또는 새 available slot에서 reservation
``` ```
## dev profile 자동 경로 체크리스트
dev profile에서는 아래 순서가 모두 이어져야 Plane-origin full-cycle 통과로 본다.
1. Plane에서 새 `Backlog + AGENT assignee` work item을 만든다.
- 제목/본문에는 유일한 timestamp를 넣는다.
- 요청 범위는 roadmap milestone 문서 생성처럼 작은 산출물로 제한한다.
- 생성 직후 work item UUID만 기록하고 token, webhook secret, private key는 기록하지 않는다.
2. Core task 생성과 authoring 진입을 확인한다.
```sh
CORE_URL="http://127.0.0.1:18011"
WORK_ITEM_UUID="<plane-work-item-uuid>"
curl -fsS "$CORE_URL/api/tasks" | python3 -c "
import json, sys
wid='$WORK_ITEM_UUID'
for t in json.load(sys.stdin).get('tasks', []):
if t.get('external_id') == wid:
m=t.get('metadata') or {}
print('task_id:', t.get('id'))
print('status:', t.get('status'))
print('authoring_run_state:', m.get('authoring_run_state'))
print('push_request_state:', m.get('push_request_state'))
print('wait_type:', m.get('wait_type'))
"
```
3. git remote `develop`에 새 revision이 생겼는지 확인한다.
```sh
cd "$HOME/agent-work/nomadcode-dev/workspaces/nomadcode/branches/develop"
git fetch -q origin develop
git log --oneline -1 origin/develop
git diff-tree --no-commit-id --name-status -r origin/develop
```
4. Forgejo provider hook delivery가 성공했는지 확인한다.
```sh
docker exec -i forgejo-db sh -lc 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -At' <<'SQL'
select id, hook_id, uuid, event_type, is_delivered, is_succeed, left(request_content, 400), left(response_content, 220)
from hook_task
order by id desc
limit 5;
SQL
```
기대값은 현재 `AFTER_SHA`나 milestone path가 들어 있는 push task의 `event_type=push`, `is_delivered=t`, `is_succeed=t`, response status `202`다. 동시 push가 있을 수 있으므로 단순 최신 행이 아니라 현재 테스트의 `after` revision 또는 changed file path와 매칭한다.
5. Gito가 `branch.updated` event를 만들었는지 확인한다.
```sh
AFTER_SHA="<origin-develop-after-sha>"
tmp=$(mktemp)
curl -fsS http://127.0.0.1:18061/api/events > "$tmp"
python3 - "$tmp" "$AFTER_SHA" <<'PY'
import json, sys
with open(sys.argv[1], encoding="utf-8") as f:
data=json.load(f)
after=sys.argv[2]
for event in data.get("events", []):
rev=event.get("revision") or {}
if rev.get("after") == after:
print("event_id:", event.get("id"))
print("delivery_id:", event.get("delivery_id"))
print("repo_id:", rev.get("repo_id"))
print("branch:", rev.get("branch"))
print("changed_files:", rev.get("changed_files"))
PY
rm -f "$tmp"
```
6. Core가 Gito webhook을 받고 Plane projection을 완료했는지 확인한다.
- Core log에 `POST /api/integrations/gito/webhook` status `202`가 있어야 한다.
- 같은 revision에서 대상 work item의 `gito creation sync enqueued``roadmap creation sync completed`가 이어져야 한다.
- Core task result의 `next_step``plane_todo_moved`, `authoring_run_state``succeeded`여야 한다.
7. Plane API 또는 UI에서 work item state가 `Todo`인지 확인한다.
```sh
cd "$HOME/agent-work/nomadcode-dev"
set -a; source .env.plane.local; set +a
python3 - <<'PY'
import os, json, ssl, urllib.request
wid="<plane-work-item-uuid>"
base=os.environ["PLANE_BASE_URL"].rstrip("/")
ws=os.environ.get("PLANE_WORKSPACE_SLUG", "general")
project=os.environ["PLANE_PROJECT_ID"]
token=os.environ["PLANE_TOKEN"]
todo=os.environ.get("PLANE_TODO_STATE_ID")
ctx=ssl._create_unverified_context()
req=urllib.request.Request(
f"{base}/api/v1/workspaces/{ws}/projects/{project}/work-items/{wid}",
headers={"X-Api-Key": token, "Accept": "application/json"},
)
with urllib.request.urlopen(req, context=ctx, timeout=20) as r:
item=json.load(r)
state_id=item.get("state") or item.get("state_id")
print(json.dumps({"work_item_id": wid, "state_id": state_id, "matches_todo_env": state_id == todo}, ensure_ascii=False))
PY
```
## 검증 항목 ## 검증 항목
| 항목 | 증거 유형 | 단계 | | 항목 | 증거 유형 | 단계 |
@ -95,6 +226,7 @@ for t in d.get('tasks', []):
| `webhook-auto-enqueue`: task가 별도 API 호출 없이 authoring queue 진입 | Core log 또는 status=running | 6 | | `webhook-auto-enqueue`: task가 별도 API 호출 없이 authoring queue 진입 | Core log 또는 status=running | 6 |
| `live-creation-projection`: develop 스캔 → ledger steps → Plane Todo | Core log + Plane UI | 7→8 | | `live-creation-projection`: develop 스캔 → ledger steps → Plane Todo | Core log + Plane UI | 7→8 |
| slot 재사용: 두 번째 smoke에서 slot available | API 응답 | 9 | | slot 재사용: 두 번째 smoke에서 slot available | API 응답 | 9 |
| `forgejo-auto-delivery`: Forgejo hook task success + Gito branch.updated event | Forgejo DB + Gito API | dev 4→5 |
## 완료 오인 방지 기준 ## 완료 오인 방지 기준
@ -104,8 +236,72 @@ for t in d.get('tasks', []):
- IOP queue timeout/stale: IOP `/v1/responses` 장시간 대기, queue timeout, stale monitor는 각각 task metadata에 관찰 가능한 상태로 남아야 한다. authoring 시작이나 단일 실패 로그만으로 terminal 완료/실패를 단정하지 않는다. - IOP queue timeout/stale: IOP `/v1/responses` 장시간 대기, queue timeout, stale monitor는 각각 task metadata에 관찰 가능한 상태로 남아야 한다. authoring 시작이나 단일 실패 로그만으로 terminal 완료/실패를 단정하지 않는다.
- push-only 누락: authoring 응답 성공은 완료 근거가 아니다. push-only 요청, remote `develop` revision 확인, Gito wakeup 이후 reconcile evidence가 이어져야 다음 단계 완료로 본다. - push-only 누락: authoring 응답 성공은 완료 근거가 아니다. push-only 요청, remote `develop` revision 확인, Gito wakeup 이후 reconcile evidence가 이어져야 다음 단계 완료로 본다.
- Gito delivery-only 성공: signed webhook 202 또는 duplicate 202는 delivery 증거일 뿐 full-cycle 완료 근거가 아니다. active Milestone slug reconcile enqueue, `roadmap_sync_steps`, Plane body/title/comment projection, `Todo` 이동까지 확인한다. - Gito delivery-only 성공: signed webhook 202 또는 duplicate 202는 delivery 증거일 뿐 full-cycle 완료 근거가 아니다. active Milestone slug reconcile enqueue, `roadmap_sync_steps`, Plane body/title/comment projection, `Todo` 이동까지 확인한다.
- Forgejo 자동 경로 누락: Gito `/callbacks/forgejo/push`에 직접 POST해서 만든 event는 진단/복구 근거다. Forgejo hook task의 성공 delivery 또는 Forgejo UI/API redelivery 성공이 없으면 자동 Forgejo -> Gito 경로 통과 근거로 쓰지 않는다.
- allowlist 복구 후 재검증: `webhook can only call allowed HTTP servers`가 관찰된 run은 환경 문제 발견 근거로만 남긴다. allowlist 수정 후 새 Plane work item으로 한 번 더 자동 경로를 통과시켜야 한다.
- full-cycle 완료: 새 Plane `Backlog + AGENT assignee` authoring roundtrip과 Git에만 있는 active Milestone missing-create/reconcile roundtrip을 모두 secret redaction 상태로 남긴다. - full-cycle 완료: 새 Plane `Backlog + AGENT assignee` authoring roundtrip과 Git에만 있는 active Milestone missing-create/reconcile roundtrip을 모두 secret redaction 상태로 남긴다.
## dev profile 트러블슈팅
### git push 후 `develop_match` 대기
증상:
- Core task metadata에 `push_request_state=succeeded`가 있는데 task가 `wait_type=develop_match` 또는 running 상태로 오래 남는다.
- Gito `/api/events`에 새 `after` SHA가 없다.
확인:
```sh
docker exec -i forgejo-db sh -lc 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -At' <<'SQL'
select id, uuid, event_type, is_delivered, is_succeed, left(request_content, 400), left(response_content, 300)
from hook_task
order by id desc
limit 5;
SQL
```
`response_content``webhook can only call allowed HTTP servers`가 있으면 Forgejo allowlist 문제다.
복구:
```sh
cfg="$HOME/docker/services/forgejo/data/volume/gitea/conf/app.ini"
cp "$cfg" "$cfg.bak-$(date +%Y%m%d%H%M%S)"
# [webhook] ALLOWED_HOST_LIST에 host.docker.internal을 추가한다.
grep -n "^ALLOWED_HOST_LIST" "$cfg"
cd "$HOME/docker/services/forgejo/compose"
docker compose restart forgejo || docker compose up -d --force-recreate forgejo
docker inspect forgejo --format '{{.State.Health.Status}}'
docker exec forgejo curl -fsS --max-time 5 http://host.docker.internal:18061/healthz
```
복구 후에는 기존 run을 수동 redelivery로 닫을 수 있지만, 자동 경로 판정은 새 Plane work item으로 다시 수행한다.
### Gito watch 또는 subscription 누락
증상:
- Forgejo hook task는 `202`를 받았는데 Gito `/api/events`에 event가 없다.
- `curl http://127.0.0.1:18061/api/listeners/branches` 또는 `/api/webhook-subscriptions`가 빈 목록이다.
복구:
- Gito 제공 계약의 branch watch와 webhook subscription bootstrap을 따른다.
- dev target은 `http://127.0.0.1:18011/api/integrations/gito/webhook`이다.
- signing secret 값은 직접 쓰지 말고 `secret_ref` 또는 Gito runtime의 env resolver를 사용한다.
### Plane Todo 미전환
증상:
- Forgejo hook task 성공, Gito event 생성, Core Gito webhook `202`까지 확인되었지만 Plane state가 Todo가 아니다.
확인:
- Core log에서 대상 work item의 `gito creation sync enqueued`, `roadmap creation sync completed`, `action`, `reason`을 확인한다.
- 생성된 milestone의 provider identity와 filename slug가 Plane work item과 맞는지 확인한다.
- Core task result의 `next_step=plane_todo_moved`가 없으면 완료로 보지 않는다.
## 대체 근거 (런타임 에퀄리번트) ## 대체 근거 (런타임 에퀄리번트)
reviewed commit을 현재 실행 중인 서버에 배포하지 않은 경우 아래 단계로 대체 근거를 수집한다. reviewed commit을 현재 실행 중인 서버에 배포하지 않은 경우 아래 단계로 대체 근거를 수집한다.

View file

@ -37,10 +37,43 @@ webhook dispatch trigger gate에 주입하는 non-secret env. secret(`PLANE_WEBH
## Webhook Smoke Baseline ## Webhook Smoke Baseline
- Webhook URL: `http://toki-labs.com:18010/api/integrations/plane/webhook` - Webhook URL: `http://toki-labs.com:18010/api/integrations/plane/webhook`
- Dev profile Core endpoint on the remote host: `http://127.0.0.1:18011/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`. - 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`.
## Dev Full-Cycle Baseline
2026-07-03 dev profile에서 Plane-origin milestone 생성 roundtrip을 확인했다. 이 섹션은 non-secret evidence만 기록한다.
### Primary automatic proof
- Plane work item: `982c14b6-b57f-4de9-8773-bcf00fe1d25a`
- Created title marker: `LIVE-SYNC post-allowlist auto smoke 1783057173`
- Core task: `89e40ba4-efbd-4254-b873-48e54e33ade0`
- git `origin/develop`: `42b0d1a8a5790a6fb93f84cf04925d06a0290ce7`
- commit summary: `42b0d1a docs(roadmap): post allowlist smoke 마일스톤을 추가한다`
- added milestone path: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/post-allowlist-automatic-plane-git-gito-plane-smoke-1783057173.md`
- Forgejo provider delivery: `c77f67fe-3e18-484e-b292-9813e1c741e4`, hook task `is_succeed=t`, Gito callback status `202`
- Gito event: `event-de33bb1fc267c84a`, type `branch.updated`, repo `nomadcode`, branch `develop`
- Plane final state: `Todo` (`45ba7449-f684-4381-af6d-5854747c5e8d`)
### Diagnostic run
- Plane work item: `67706758-9555-456b-b051-547fa6b4f093`
- git `origin/develop`: `738f4b8d202e9254f7c4c8fe91bb6f5e729100f0`
- This run exposed a dev Forgejo allowlist issue before the automatic provider delivery path was fixed.
- The run was completed after Gito callback redelivery, so it is evidence for Core/Gito/Plane projection recovery but not primary proof of automatic Forgejo -> Gito delivery.
## Agent Usage Notes
- 새 full-cycle test item은 `Backlog` state와 AGENT assignee로 만든다.
- 제목/본문에는 timestamp marker를 넣어 git commit, milestone slug, Plane item을 쉽게 대조할 수 있게 한다.
- 요청 범위는 roadmap milestone 문서처럼 작은 산출물로 제한하고, 기능 코드 구현이나 contract 변경을 요구하지 않는다.
- full-cycle 통과 판정은 `agent-test/live-cycle-smoke.md`의 dev profile 자동 경로 체크리스트를 따른다.
- `Todo` 이동 확인 전에는 Plane item이 완료됐다고 보고하지 않는다.
- raw API token, webhook secret, provider credential, private key는 이 문서나 최종 응답에 기록하지 않는다.
## Webhook Payload Fixtures ## Webhook Payload Fixtures
`services/core/internal/http/testdata/` 아래 fixture로 payload shape를 고정한다. 모든 fixture는 PII/secret redaction 상태이며 work item id는 placeholder다. `services/core/internal/http/testdata/` 아래 fixture로 payload shape를 고정한다. 모든 fixture는 PII/secret redaction 상태이며 work item id는 placeholder다.
@ -48,4 +81,3 @@ webhook dispatch trigger gate에 주입하는 non-secret env. secret(`PLANE_WEBH
- `plane_webhook_issue_assignees_updated.json`: live dev Plane assignee-update 로그 기반 redacted 샘플 (`event=issue`, `action=updated`, `activity.field=assignees`). - `plane_webhook_issue_assignees_updated.json`: live dev Plane assignee-update 로그 기반 redacted 샘플 (`event=issue`, `action=updated`, `activity.field=assignees`).
- `plane_webhook_issue_created.json`: create 후보. live create 로그를 따로 확보하지 않아 관찰된 issue envelope 기반 synthetic candidate다 (`event=issue`, `action=created`, Backlog state). - `plane_webhook_issue_created.json`: create 후보. live create 로그를 따로 확보하지 않아 관찰된 issue envelope 기반 synthetic candidate다 (`event=issue`, `action=created`, Backlog state).
- `plane_webhook_issue_state_updated.json`: state-change 후보. synthetic candidate다 (`event=issue`, `action=updated`, `activity.field=state`, Backlog -> Todo). - `plane_webhook_issue_state_updated.json`: state-change 후보. synthetic candidate다 (`event=issue`, `action=updated`, `activity.field=state`, Backlog -> Todo).