--- test_env: local test_profile: live-cycle-smoke domain: core verification_type: smoke last_rule_updated_at: 2026-06-20 --- # live-cycle-smoke 전체 webhook → authoring → develop match → Plane projection → slot 회수 사이클을 검증한다. 이 문서는 절차 기술과 runtime-equivalent 근거를 함께 기록한다. ## 읽기 조건 - `live-webhook-task`, `webhook-auto-enqueue`, `live-creation-projection` 증거가 필요한 경우. - `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`. - Core server: Docker Compose (`services/core/docker-compose.yml`), host port `18010->8080`. - Plane dev: `https://plane.toki-labs.com`, workspace `general`, project `NOMAD`. - Secrets: `.env.plane.local` (ignored), SOPS `secrets/nomadcode.dev.sops.yaml` (webhook secret). - runner checkout: 검증용 disposable mirror다. dirty worktree, uncommitted 변경, 임시 파일을 이유로 중단하지 않고 현재 대화 workspace의 요청 범위 상태와 같게 reset/clean/reclone 또는 파일 동기화한 뒤 테스트한다. ## 전제 조건 - Core server는 현재 검증 대상 상태로 빌드·배포되어 있어야 한다. 원격 checkout이나 실행 컨테이너가 낡았으면 테스트 수행자가 reset/clean/reclone, 파일 동기화, compose rebuild/recreate로 최신화한다. - `PLANE_WEBHOOK_SECRET`, `PLANE_TOKEN` 등 secret은 `.env.plane.local` 또는 SOPS에서 로드한다. - Plane dev 서버가 `https://plane.toki-labs.com`에서 정상 동작 중이어야 한다. - workspace slot 행이 DB에 `available` 상태로 최소 1개 이상 있어야 한다. ## Fixture IDs (non-secret) - `agent-test/plane-dev.md` 참조. webhook smoke에서는 `Backlog + AGENT assignee` 상태 티켓을 생성하거나 AGENT를 assign한다. - work item UUID는 Plane에서 새로 생성하거나 기존 NOMAD-10/NOMAD-11 같은 기존 fixture를 재사용할 수 있다. ## 명령 (SECRET_FREE) ```sh # 1. 환경 로드 (secrets은 ignored local file에서) set -a; source .env.plane.local; set +a # 2. Core server 헬스 확인 CORE_URL="http://127.0.0.1:18010" curl -s "$CORE_URL/api/tasks" | python3 -c \ "import sys,json; d=json.load(sys.stdin); print('task_count:', len(d.get('tasks',[])))" # 3. DB slot 상태 확인 (slot_id=1 기준) # - slot available이면 smoke 가능 # - slot in_use/dirty/error이면 prior run이 미완료 또는 오류임 curl -s "$CORE_URL/api/workspaces/slots" 2>/dev/null | head -200 || echo "(slot API 없음 - DB 직접 확인 필요)" # 4. Plane: Backlog + AGENT assignee 티켓 생성 또는 AGENT 배정 # - Plane UI 또는 API로 수행; work_item_uuid만 기록 WORK_ITEM_UUID="" # 5. Plane webhook 수동 전송 (plane-dev.md 참조) # - Plane dev UI → Webhook Settings → Test Delivery # - 또는 curl로 직접 (PLANE_WEBHOOK_SECRET 필요, secret 출력 금지) # Expected: HTTP 202, Core logs show task created # 6. Core task 생성 확인 (external_id=WORK_ITEM_UUID 로 조회) curl -s "$CORE_URL/api/tasks?source=plane" 2>/dev/null | python3 -c " import sys, json d = json.load(sys.stdin) for t in d.get('tasks', []): if t.get('external_id') == '$WORK_ITEM_UUID': m = t.get('metadata', {}) c = m.get('checkout', {}) print('task_id:', t['id']) print('status:', t['status']) print('slot_id:', c.get('slot_id')) print('slot_path:', c.get('slot_path')) print('authoring_run_state:', m.get('authoring_run_state')) print('wait_type:', m.get('wait_type')) " # Expected: task found, checkout.slot_id > 0, authoring_run_state=in_progress # 7. develop 브랜치에 push 발생 → gitosync scanner가 pick up (자동) # Core log: roadmap_creation_sync job enqueued, SyncCreation 호출 # 8. projection 완료 후 task 상태 재확인 # Expected: authoring_run_state=succeeded, status=completed, slot released # 9. slot 재사용 확인: 두 번째 smoke 티켓 생성 → 같은 slot_id 또는 새 available slot에서 reservation ``` ## 검증 항목 | 항목 | 증거 유형 | 단계 | |------|----------|------| | `live-webhook-task`: webhook 202 + task 생성 + checkout metadata | Live API 응답 | 5→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 | | slot 재사용: 두 번째 smoke에서 slot available | API 응답 | 9 | ## 대체 근거 (런타임 에퀄리번트) reviewed commit을 현재 실행 중인 서버에 배포하지 않은 경우 아래 단계로 대체 근거를 수집한다. ### 단계 A: unit test ```sh cd services/core && go test -count=1 \ ./cmd/plane-smoke/... \ ./internal/http/... \ ./internal/scheduler/... \ ./internal/roadmapsyncpipeline/... ``` 커버 범위: - `TestRoadmapCreationSyncWorkerFinalizesExternalTaskOnProjected` → projection + slot available 전환 - `TestMarkFailedWithTaskAuthoringRecordsState` → failure + slot error 전환 - `TestMarkFailedWithTaskAuthoringMissingSlotIDSkipsSlotUpdate` → missing slot_id skip - `TestSyncCreationReadyRunsStepsAndMarksLedger` → ledger steps all marked - webhook HTTP handler tests → dispatch gate logic ### 단계 B: 기존 baseline 확인 ```sh # 2026-06-15 smoke baseline (commit 55e0139 기준 서버) curl -s http://127.0.0.1:18010/api/tasks/e3c92411-4056-4b76-a879-66f7904125d0 # Expected: status=completed, checkout.slot_id=1, source=plane ``` `live-webhook-task`와 `webhook-auto-enqueue`의 일부 증거는 이 baseline이 커버한다. `live-creation-projection` (Plane Todo 이동)과 slot terminal state 회수는 reviewed commit 배포 후만 검증 가능. ## 차단 기준 - Core server를 현재 검증 대상 상태로 재배포할 수 없으면 `live-creation-projection`과 slot 회수 증거를 수집할 수 없다. - 원격 runner checkout의 dirty 상태는 차단 기준이 아니다. reset/clean/reclone, 파일 동기화, Docker image 재빌드·재배포를 먼저 수행하고, 권한·secret·외부 서비스 장애처럼 에이전트가 해소할 수 없는 사유만 차단으로 보고한다. ## 보고 항목 - 실행한 명령: - 성공한 검증: - 실패/차단된 검증: - 생략 사유: - 남은 위험: