feat: workspace provision pipeline archive and authoring result, scheduler fixes
This commit is contained in:
parent
096efb0a83
commit
dd0c4d953b
14 changed files with 968 additions and 20 deletions
|
|
@ -17,8 +17,7 @@ Plane-origin 경로로 Milestone을 생성하고, `develop` branch의 agent-road
|
|||
|
||||
- 상태: 해제
|
||||
- 결정 필요: 없음
|
||||
- 부분 잠금:
|
||||
- `plane-agent-authoring`: IOP Edge OpenAI-compatible HTTP 통로로 workspace-bound agent run을 실행할 수 있을 때까지 실행 잠금
|
||||
- 부분 잠금: 없음
|
||||
|
||||
## 범위
|
||||
|
||||
|
|
@ -78,17 +77,17 @@ Project sync workspace를 고정 branch workspace와 agent 작업 slot으로 분
|
|||
- [x] [slot-layout] agent authoring 작업공간을 `slots/000`, `slots/001`, `slots/002`처럼 `slots/` 하위 3자리 index로 계산하도록 경로 규칙을 갱신한다. 검증: `workspace_base_path=/home/user/workspace`, `repo_dir_name=nomadcode`이면 `develop` 기준 workspace는 `/home/user/workspace/nomadcode/branches/develop`, 기본 작업 slot은 `/home/user/workspace/nomadcode/slots/000`이다.
|
||||
- [x] [slot-source-branch] 새 agent slot은 source-of-truth branch인 `develop` 기준으로 checkout/branch 준비를 하되, Plane `Todo` projection은 slot local file이 아니라 `branches/develop` 또는 remote `develop` 반영 여부를 기준으로 판단한다. 검증: slot dirty 상태나 미push 변경만으로 Plane 본문 치환/`Todo` 이동을 하지 않는다.
|
||||
- [x] [branch-sync-state] branch workspace와 slot workspace의 상태 모델을 분리한다. 검증: branch workspace는 `synced`, `stale`, `error` 같은 sync 상태 후보를 갖고, slot workspace는 기존 `available`, `in_use`, `dirty`, `error` 같은 배정 상태를 유지한다.
|
||||
- [ ] [workspace-provision] project sync 설정 저장 또는 첫 사용 시 `branches/main`, `branches/develop`, 최소 `slots/000`의 checkout 준비 기준을 남긴다. 검증: missing workspace를 조용히 임의 cwd로 대체하지 않고 준비 실패를 명시 오류로 반환한다.
|
||||
- [x] [workspace-provision] project sync 설정 저장 또는 첫 사용 시 `branches/main`, `branches/develop`, 최소 `slots/000`의 checkout 준비 기준을 남긴다. 검증: missing workspace를 조용히 임의 cwd로 대체하지 않고 준비 실패를 명시 오류로 반환한다.
|
||||
|
||||
### Epic: [agent-bridge] Workspace agent IOP bridge
|
||||
|
||||
Plane-origin sync가 workspace agent를 실행할 수 있도록 IOP Edge OpenAI-compatible HTTP 기반 1차 실행 통로를 선행으로 둔다.
|
||||
|
||||
- [ ] [iop-http-channel] Core/runtime이 IOP Edge OpenAI-compatible HTTP를 통해 workspace-bound agent authoring run을 시작하는 최소 통로를 정의한다. 검증: runtime이 `slots/<index>` workspace path, Plane 티켓 제목/본문, provider work item id, project sync 설정, roadmap 작성 지시를 `/v1/responses` 요청의 `input`과 `metadata.workspace`로 전달할 수 있다.
|
||||
- [ ] [authoring-state] Workspace agent authoring run의 최소 상태 모델을 정의한다. 검증: 첫 구현은 `in_progress`, `succeeded`, `failed`만 상태로 저장하고, stale/timeout은 별도 상태가 아니라 `updated_at` 기준으로 판정한다.
|
||||
- [ ] [provider-identity] Plane 티켓과 workspace agent 결과를 연결하는 최소 identity를 정의한다. 검증: agent가 작성한 Milestone 작업 컨텍스트에 provider와 Plane work item id가 남고, sync layer는 이 identity로 pushed Milestone을 원래 Plane 티켓과 매칭한다. 별도 `authoring_run_id`는 첫 slice의 필수 매칭 키로 만들지 않는다.
|
||||
- [ ] [agent-run-result] Workspace agent authoring run의 성공/실패 판정 기준을 정의한다. 검증: authoring 성공은 별도 구조화 응답이 아니라 `develop` branch에 Milestone 파일 변경이 commit/push된 상태로 판정하며, sync layer의 Plane work item id 검증은 `pushed-milestone-match` 단계에서 처리한다. 실패는 exit code, push 실패, dirty workspace, 충돌 상태로 구분된다.
|
||||
- [ ] [agent-bridge-lock] Plane authoring 실행 단계의 선행 잠금을 정의한다. 검증: IOP Edge OpenAI-compatible HTTP workspace agent 실행 통로가 없으면 `plane-agent-authoring` 단계는 실행하지 않고, project sync 설정과 branch/slot workspace 준비까지만 진행할 수 있다.
|
||||
- [x] [iop-http-channel] Core/runtime이 IOP Edge OpenAI-compatible HTTP를 통해 workspace-bound agent authoring run을 시작하는 최소 통로를 정의한다. 검증: `authoring.BuildAuthoringGenerateInput`이 Plane 티켓 본문, provider work item id, slot workspace path를 `model.GenerateInput`으로 만들고, scheduler가 Plane-origin authoring task를 A2A가 아니라 OpenAI-compatible model bridge로 라우팅한다.
|
||||
- [x] [authoring-state] Workspace agent authoring run의 최소 상태 모델을 정의한다. 검증: 첫 구현은 `in_progress`, `succeeded`, `failed`만 상태로 저장하고, stale/timeout은 별도 상태가 아니라 `updated_at` 기준으로 판정한다.
|
||||
- [x] [provider-identity] Plane 티켓과 workspace agent 결과를 연결하는 최소 identity를 정의한다. 검증: `ExternalProvider`/`ExternalID` 또는 payload `work_item`의 provider/work item id가 workspace metadata에 남고, pushed Milestone matching은 provider + work item id + Milestone path를 쓰며 별도 `authoring_run_id`를 필수 매칭 키로 쓰지 않는다.
|
||||
- [ ] [agent-run-result] Workspace agent authoring run의 성공/실패 판정 기준을 정의한다. 검증: authoring 성공은 별도 구조화 응답이 아니라 `develop` branch에 Milestone 파일 변경이 commit/push된 상태로 판정하며, sync layer의 Plane work item id 검증은 `pushed-milestone-match` 단계에서 처리한다. 실패는 exit code, push 실패, dirty workspace, 충돌 상태로 구분된다. 계획: `agent-task/m-milestone-work-item-creation-sync/08_agent_run_result_gate/`
|
||||
- [x] [agent-bridge-lock] Plane authoring 실행 단계의 선행 잠금을 정의한다. 검증: IOP Edge OpenAI-compatible HTTP bridge가 Plane-origin authoring task의 실행 통로가 되었고, authoring 조건이 없거나 workspace checkout metadata가 없으면 일반 실행/준비 흐름으로 남는다.
|
||||
|
||||
### Epic: [creation-sync] Milestone creation sync
|
||||
|
||||
|
|
@ -149,6 +148,8 @@ Plane-origin 생성 경로를 `develop` agent-roadmap 기준의 `Todo` 검토
|
|||
- 현황 동기화(2026-06-13): `agent-task/archive/2026/06/m-milestone-work-item-creation-sync/*/complete.log`의 `Roadmap Completion` 근거로 `cycle-workspace-topology`, `cycle-iop-http-ready`, `cycle-authoring-run`, `cycle-develop-sync`, `cycle-plane-todo`를 완료 처리했다.
|
||||
- 현황 동기화(2026-06-14): `agent-task/archive/2026/06/m-milestone-work-item-creation-sync/05+03,04_idempotency_retry/complete.log`의 `Roadmap Completion` 근거로 `cycle-idempotency`를 완료 처리했다. 검증 근거는 identity map의 원자적 conflict 처리, strict retry identity key, `cd services/core && go test -count=1 ./internal/storage ./internal/roadmapsync ./internal/adapters/plane`, `cd services/core && go test ./...`, `git diff --check` PASS다. `./bin/sqlc`는 기존 `queries/workspace_slots.sql:19:11` ambiguity로 차단되어 완료 로그에 별도 기록되어 있다.
|
||||
- Workspace topology 세부 동기화(2026-06-14): `agent-task/archive/2026/06/m-milestone-work-item-creation-sync/01_workspace_topology/complete.log`, `02+01_workspace_slot_store/complete.log`, `03+01,02_project_binding_checkout/complete.log`, `03+02_develop_match/complete.log`, `04+03_plane_todo_projection/complete.log`와 현재 `projectsync`/`workitempipeline` 테스트 근거로 `[branch-workspaces]`, `[slot-layout]`, `[slot-source-branch]`, `[branch-sync-state]`를 완료 처리했다. `[workspace-provision]`은 실제 first-use checkout 준비 검증과 기본 slot 등록, missing workspace 명시 오류 연결이 남아 `agent-task/m-milestone-work-item-creation-sync/06_workspace_provision/` 및 `agent-task/m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline/` 계획으로 분리했다.
|
||||
- Workspace provision pipeline 동기화(2026-06-14): `agent-task/archive/2026/06/m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline/complete.log`의 `Roadmap Completion` 근거로 `[workspace-provision]`을 완료 처리했다. 검증 근거는 workspace provision hook의 slot 예약/provider fetch/task creation 이전 실행, HTTP binder의 default `slots/000` 등록, `ErrWorkspaceProvisionNotReady` 409 매핑, `cd services/core && go test -count=1 ./internal/projectsync ./internal/workitempipeline ./internal/http`, `cd services/core && go test ./...`, `cd services/core && go vet ./...`, `git diff --check` PASS다.
|
||||
- Agent bridge 소형 항목 동기화(2026-06-14): 현재 Core 코드의 `authoring.BuildAuthoringGenerateInput`, OpenAI-compatible `/v1/responses` adapter, scheduler authoring route/state metadata, `roadmapsync` identity/develop match 기준을 근거로 `[iop-http-channel]`, `[authoring-state]`, `[provider-identity]`, `[agent-bridge-lock]`을 완료 처리했다. 검증: `cd services/core && go test -count=1 ./internal/authoring ./internal/scheduler ./internal/roadmapsync` PASS. `[agent-run-result]`는 model bridge 응답 성공과 `develop` push 검증 사이의 성공 판정 경계를 보강해야 하므로 `agent-task/m-milestone-work-item-creation-sync/08_agent_run_result_gate/` 계획으로 분리했다.
|
||||
- 중지 지점: project sync 설정, workspace topology, IOP Edge HTTP authoring run 경계, pushed Milestone identity match, Plane 원문 댓글 보존/본문·제목 갱신/`Todo` 이동 projection, identity map 기반 idempotency/retry는 완료 근거가 있다.
|
||||
- 루프 목표: Plane `Backlog + AGENT assignee` -> `slots/<index>` workspace 예약/준비 -> IOP Edge HTTP로 workspace agent authoring run 실행 -> agent가 Milestone 파일 작성/갱신 후 `develop` push -> sync layer가 `branches/develop` 또는 remote `develop`에서 push 완료/roadmap scan을 감지 -> Plane 원문 댓글 보존/본문 치환/제목 변경/`Todo` 이동 -> 사용자가 확인 후 `In Progress`로 이동하는 지점까지다. 최상위 `plane-nomad-iop-cycle` 실행 단위는 완료 근거가 있으며, `In Progress` 이후 실행은 후속 잠금 범위다.
|
||||
- 후속 잠금: `Todo -> In Progress` 이후 실행 lifecycle은 사용자가 명시적으로 잠금을 해제할 때까지 진행하지 않는다.
|
||||
|
|
|
|||
|
|
@ -59,16 +59,16 @@ task=m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline, pla
|
|||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [ ] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [ ] active `CODE_REVIEW-*-G??.md`를 `code_review_{review_lane}_GNN_N.log`로 아카이브한다.
|
||||
- [ ] active `PLAN-*-G??.md`를 `plan_{build_lane}_GNN_M.log`로 아카이브한다.
|
||||
- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_{review_lane}_GNN_N.log`로 아카이브한다.
|
||||
- [x] active `PLAN-*-G??.md`를 `plan_{build_lane}_GNN_M.log`로 아카이브한다.
|
||||
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [ ] PASS이면 active task 디렉터리 `agent-task/{task_name}/`를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [x] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
|
|
@ -153,3 +153,18 @@ $ git diff --check
|
|||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- 종합 판정: FAIL
|
||||
- 차원별 평가:
|
||||
- correctness: Pass
|
||||
- completeness: Fail
|
||||
- test coverage: Pass
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Pass
|
||||
- verification trust: Fail
|
||||
- 발견된 문제:
|
||||
- Required: `agent-task/m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline/CODE_REVIEW-cloud-G07.md:112`부터 `:148`까지의 `검증 결과`가 실제 stdout/stderr가 아니라 `(output)` placeholder로 남아 있습니다. 이 파일의 필수 규칙은 실제 stdout/stderr 기록을 요구하고, 구현 체크리스트의 `focused/final 검증을 실행한다` 항목은 matching verification output 없이는 완료로 인정할 수 없습니다. 후속 구현은 계획의 검증 명령을 그대로 재실행하고 각 code block의 `(output)`을 실제 출력으로 교체해야 합니다.
|
||||
- 다음 단계: FAIL 후속 `PLAN-*-G??.md`와 `CODE_REVIEW-*-G??.md`를 작성해 검증 증거 기록만 보완한다.
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
<!-- task=m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline plan=1 tag=REVIEW_API -->
|
||||
|
||||
# Code Review Reference - REVIEW_API
|
||||
|
||||
> **[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`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-14
|
||||
task=m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline, plan=1, tag=REVIEW_API
|
||||
|
||||
## Roadmap Targets
|
||||
|
||||
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
|
||||
- Task ids:
|
||||
- `workspace-provision`: project sync 설정 저장 또는 첫 사용 시 `branches/main`, `branches/develop`, 최소 `slots/000`의 checkout 준비 기준을 남긴다.
|
||||
- Completion mode: check-on-pass
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||
|
||||
1. 판정을 append한다.
|
||||
2. `CODE_REVIEW-{review_lane}-GNN.md` -> `code_review_{review_lane}_GNN_N.log`, `PLAN-{build_lane}-GNN.md` -> `plan_{build_lane}_GNN_M.log`로 아카이브한다.
|
||||
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다. `USER_REVIEW.md`가 사용자 결정으로 완료/PASS 해소되면 code-review가 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log` 작성 후 archive 이동한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [REVIEW_API-1] Verification evidence recovery | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [x] 계획된 검증 명령을 그대로 재실행하고 실제 stdout/stderr를 `CODE_REVIEW-local-G04.md`의 `검증 결과` 섹션에 기록한다.
|
||||
- [x] 검증 실패가 발생하면 임의 대체 명령으로 PASS 처리하지 말고 실패 출력과 최소 진단 범위를 `계획 대비 변경 사항`에 기록한다.
|
||||
- [x] 소스 코드 변경이 필요하지 않으면 소스 파일을 수정하지 않는다.
|
||||
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_{review_lane}_GNN_N.log`로 아카이브한다.
|
||||
- [x] active `PLAN-*-G??.md`를 `plan_{build_lane}_GNN_M.log`로 아카이브한다.
|
||||
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [x] PASS이면 active task 디렉터리 `agent-task/{task_name}/`를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [x] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
계획에 명시된 검증 명령어를 그대로 정상 실행하였으며 특이사항은 없습니다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
본 작업은 소스 코드의 로직 변경 없이, 누락되었던 검증 명령어의 출력 결과(stdout/stderr)를 정확하게 기록하여 증거를 보완하는 작업입니다.
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `검증 결과`의 모든 code block이 `(output)` placeholder가 아니라 실제 stdout/stderr 또는 명시적 무출력 성공 기록인지 확인한다.
|
||||
- 후속 구현이 소스 코드 변경 없이 검증 증거만 보완했는지 확인한다.
|
||||
- 검증 실패가 있으면 실패 출력과 최소 진단이 `계획 대비 변경 사항`에 남아 있는지 확인한다.
|
||||
- `Roadmap Targets`의 `workspace-provision`은 이 후속 계획이 PASS일 때만 check-on-pass 대상이다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
### REVIEW_API-1 중간 검증
|
||||
```
|
||||
$ cd services/core && go test -count=1 ./internal/workitempipeline
|
||||
ok github.com/nomadcode/nomadcode-core/internal/workitempipeline 0.003s
|
||||
```
|
||||
|
||||
```
|
||||
$ cd services/core && go test -count=1 ./internal/http
|
||||
ok github.com/nomadcode/nomadcode-core/internal/http 0.005s
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```
|
||||
$ cd services/core && go test -count=1 ./internal/projectsync ./internal/workitempipeline ./internal/http
|
||||
ok github.com/nomadcode/nomadcode-core/internal/projectsync 0.004s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/workitempipeline 0.003s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/http 0.003s
|
||||
```
|
||||
|
||||
```
|
||||
$ cd services/core && go test ./...
|
||||
ok github.com/nomadcode/nomadcode-core/cmd/plane-smoke (cached)
|
||||
? github.com/nomadcode/nomadcode-core/cmd/server [no test files]
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/a2a (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/jira (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/mattermost (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/openai (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/plane (cached)
|
||||
? github.com/nomadcode/nomadcode-core/internal/agent [no test files]
|
||||
ok github.com/nomadcode/nomadcode-core/internal/authoring (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/config (cached)
|
||||
? github.com/nomadcode/nomadcode-core/internal/db [no test files]
|
||||
ok github.com/nomadcode/nomadcode-core/internal/http (cached)
|
||||
? github.com/nomadcode/nomadcode-core/internal/model [no test files]
|
||||
ok github.com/nomadcode/nomadcode-core/internal/notification (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/projectsync (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/protosocket (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/roadmapsync (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/scheduler (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/storage (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/workflow (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/workitem (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/workitempipeline (cached)
|
||||
```
|
||||
|
||||
```
|
||||
$ cd services/core && go vet ./...
|
||||
<success: no output>
|
||||
```
|
||||
|
||||
```
|
||||
$ git diff --check
|
||||
<success: no output>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- 종합 판정: PASS
|
||||
- 차원별 평가:
|
||||
- correctness: Pass
|
||||
- completeness: Pass
|
||||
- test coverage: Pass
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Pass
|
||||
- verification trust: Pass
|
||||
- 발견된 문제: 없음
|
||||
- 다음 단계: PASS 종결. `complete.log` 작성 후 task directory를 archive로 이동한다.
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# Complete - m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline
|
||||
|
||||
## 완료 일시
|
||||
|
||||
2026-06-14
|
||||
|
||||
## 요약
|
||||
|
||||
Workspace provision pipeline 연결과 검증 증거 보완을 2회 리뷰 루프로 검토했고 최종 판정은 PASS다.
|
||||
|
||||
## 루프 이력
|
||||
|
||||
| Plan | Review | Verdict | 메모 |
|
||||
|------|--------|---------|------|
|
||||
| `plan_cloud_G07_0.log` | `code_review_cloud_G07_0.log` | FAIL | 구현과 회귀 테스트는 판단 가능했지만 review stub의 검증 결과가 `(output)` placeholder로 남아 verification trust가 부족했다. |
|
||||
| `plan_local_G04_1.log` | `code_review_local_G04_1.log` | PASS | 계획된 검증 명령의 실제 stdout/stderr가 기록되었고 리뷰 재실행 결과도 모두 통과했다. |
|
||||
|
||||
## 구현/정리 내용
|
||||
|
||||
- `workitempipeline.ProjectBinder`에 workspace provision hook을 추가하고 slot 예약/provider fetch/task creation 전에 실행되도록 연결했다.
|
||||
- HTTP project sync binder가 filesystem provisioner를 실행하고 기본 `slots/000`을 기존 `UpsertWorkspaceSlot`로 등록하도록 연결했다.
|
||||
- `ErrWorkspaceProvisionNotReady`를 HTTP 409로 매핑하고 pipeline/HTTP 회귀 테스트를 추가했다.
|
||||
- 후속 루프에서 누락된 검증 stdout/stderr 증거를 `CODE_REVIEW-local-G04.md`에 기록해 verification trust 공백을 해소했다.
|
||||
|
||||
## 최종 검증
|
||||
|
||||
- `cd services/core && go test -count=1 ./internal/workitempipeline` - PASS; `ok github.com/nomadcode/nomadcode-core/internal/workitempipeline 0.003s`.
|
||||
- `cd services/core && go test -count=1 ./internal/http` - PASS; `ok github.com/nomadcode/nomadcode-core/internal/http 0.004s`.
|
||||
- `cd services/core && go test -count=1 ./internal/projectsync ./internal/workitempipeline ./internal/http` - PASS; `projectsync`, `workitempipeline`, `http` 모두 통과.
|
||||
- `cd services/core && go test ./...` - PASS; core 전체 package 테스트 통과, 일부 package는 cached 또는 no test files.
|
||||
- `cd services/core && go vet ./...` - PASS; 출력 없음.
|
||||
- `git diff --check` - PASS; 출력 없음.
|
||||
|
||||
## Roadmap Completion
|
||||
|
||||
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
|
||||
- Completed task ids:
|
||||
- `workspace-provision`: PASS; evidence=`agent-task/archive/2026/06/m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline/plan_local_G04_1.log`, `agent-task/archive/2026/06/m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline/code_review_local_G04_1.log`; verification=`cd services/core && go test -count=1 ./internal/projectsync ./internal/workitempipeline ./internal/http`, `cd services/core && go test ./...`, `cd services/core && go vet ./...`, `git diff --check`
|
||||
- Not completed task ids: 없음
|
||||
|
||||
## 잔여 Nit
|
||||
|
||||
- 없음
|
||||
|
||||
## 후속 작업
|
||||
|
||||
- 없음
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<!-- task=m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline plan=1 tag=REVIEW_API -->
|
||||
|
||||
# Workspace Provision Pipeline Follow-up Plan - REVIEW_API
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채우는 것이 필수 최종 단계다. 이 후속 작업은 소스 코드 변경이 아니라 누락된 검증 증거를 보완하는 작업이다. 아래 검증 명령을 그대로 실행하고 실제 stdout/stderr를 review stub에 기록한 뒤 active 파일을 남겨 리뷰를 요청한다. 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 review stub의 `사용자 리뷰 요청` 섹션에 정확한 근거를 기록하고 멈춘다. 구현 중 사용자에게 직접 묻거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 공백은 사용자 리뷰 요청이 아니다.
|
||||
|
||||
## 배경
|
||||
|
||||
이전 루프는 workspace provision pipeline의 코드 변경과 회귀 테스트 자체는 리뷰 가능한 상태였고, 리뷰 에이전트 재실행 기준으로 focused/core/vet/diff 검증도 통과했다. 그러나 archived review log `code_review_cloud_G07_0.log`의 `검증 결과`가 실제 출력이 아니라 `(output)` placeholder로 남아 있어, 구현 체크리스트의 검증 완료 항목을 완료로 인정할 수 없다.
|
||||
|
||||
## Roadmap Targets
|
||||
|
||||
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
|
||||
- Task ids:
|
||||
- `workspace-provision`: project sync 설정 저장 또는 첫 사용 시 `branches/main`, `branches/develop`, 최소 `slots/000`의 checkout 준비 기준을 남긴다.
|
||||
- Completion mode: check-on-pass
|
||||
|
||||
## 실패 근거
|
||||
|
||||
- Archived review: `agent-task/m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline/code_review_cloud_G07_0.log`
|
||||
- Archived plan: `agent-task/m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline/plan_cloud_G07_0.log`
|
||||
- Required issue: previous review stub lines `112` through `148` contained `(output)` placeholders instead of actual stdout/stderr.
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] 계획된 검증 명령을 그대로 재실행하고 실제 stdout/stderr를 `CODE_REVIEW-local-G04.md`의 `검증 결과` 섹션에 기록한다.
|
||||
- [ ] 검증 실패가 발생하면 임의 대체 명령으로 PASS 처리하지 말고 실패 출력과 최소 진단 범위를 `계획 대비 변경 사항`에 기록한다.
|
||||
- [ ] 소스 코드 변경이 필요하지 않으면 소스 파일을 수정하지 않는다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
### [REVIEW_API-1] Verification Evidence Recovery
|
||||
|
||||
- `문제`: 이전 review stub은 검증 명령 목록만 남겼고 실제 stdout/stderr를 기록하지 않았다. 이 때문에 `focused/final 검증을 실행한다` 체크리스트 항목의 증거가 없다.
|
||||
- `해결 방법`: 아래 명령을 순서대로 실행하고, 각 명령의 실제 출력을 `CODE_REVIEW-local-G04.md`에 붙여 넣는다. 출력이 없으면 `<success: no output>`처럼 명령 성공과 무출력을 명시한다.
|
||||
- `수정 파일 및 체크리스트`:
|
||||
- [ ] `agent-task/m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline/CODE_REVIEW-local-G04.md`: 모든 검증 code block에 실제 stdout/stderr를 기록한다.
|
||||
- `테스트 작성`: 새 테스트 작성은 필요 없다. 이 후속 작업은 기존 검증 증거 복구만 수행한다.
|
||||
- `중간 검증`: 아래 focused 명령들이 PASS해야 한다.
|
||||
|
||||
```bash
|
||||
cd services/core && go test -count=1 ./internal/workitempipeline
|
||||
cd services/core && go test -count=1 ./internal/http
|
||||
```
|
||||
|
||||
## 수정 파일 요약
|
||||
|
||||
| 파일 | 항목 |
|
||||
|------|------|
|
||||
| `agent-task/m-milestone-work-item-creation-sync/07+06_workspace_provision_pipeline/CODE_REVIEW-local-G04.md` | REVIEW_API-1 |
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
cd services/core && go test -count=1 ./internal/projectsync ./internal/workitempipeline ./internal/http
|
||||
```
|
||||
|
||||
예상: PASS.
|
||||
|
||||
```bash
|
||||
cd services/core && go test ./...
|
||||
```
|
||||
|
||||
예상: PASS. cache 출력은 허용한다.
|
||||
|
||||
```bash
|
||||
cd services/core && go vet ./...
|
||||
```
|
||||
|
||||
예상: PASS. 출력이 없으면 무출력 성공으로 기록한다.
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
```
|
||||
|
||||
예상: 출력 없음. 무출력 성공으로 기록한다.
|
||||
|
||||
모든 검증 출력 기록을 마친 뒤 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
<!-- task=m-milestone-work-item-creation-sync/08_agent_run_result_gate plan=0 tag=AGENT_BRIDGE -->
|
||||
|
||||
# Code Review Reference - AGENT_BRIDGE
|
||||
|
||||
> **[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`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-14
|
||||
task=m-milestone-work-item-creation-sync/08_agent_run_result_gate, plan=0, tag=AGENT_BRIDGE
|
||||
|
||||
## Roadmap Targets
|
||||
|
||||
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
|
||||
- Task ids:
|
||||
- `agent-run-result`: Workspace agent authoring run의 성공/실패 판정 기준
|
||||
- Completion mode: check-on-pass
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||
|
||||
1. 판정을 append한다.
|
||||
2. `CODE_REVIEW-cloud-G07.md` -> `code_review_cloud_G07_N.log`, `PLAN-cloud-G07.md` -> `plan_cloud_G07_M.log`로 아카이브한다.
|
||||
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-milestone-work-item-creation-sync/08_agent_run_result_gate/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다. `USER_REVIEW.md`가 사용자 결정으로 완료/PASS 해소되면 code-review가 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log` 작성 후 archive 이동한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [AGENT_BRIDGE-1] Authoring result gate | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [x] [AGENT_BRIDGE-1] bridge 응답 성공과 develop 반영 성공을 분리하는 authoring result gate를 구현하고, `agent-run-result`의 성공/실패 판정 테스트를 추가한다.
|
||||
- [x] 중간 검증 `cd services/core && go test -count=1 ./internal/authoring ./internal/scheduler ./internal/roadmapsync`를 실행한다.
|
||||
- [x] 최종 검증 `cd services/core && go test ./...`, `cd services/core && go vet ./...`, `git diff --check`를 실행한다.
|
||||
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_cloud_G07_N.log`로 아카이브한다.
|
||||
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G07_M.log`로 아카이브한다.
|
||||
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [x] PASS이면 active task 디렉터리 `agent-task/m-milestone-work-item-creation-sync/08_agent_run_result_gate/`를 `agent-task/archive/YYYY/MM/m-milestone-work-item-creation-sync/08_agent_run_result_gate/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [x] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-milestone-work-item-creation-sync/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-cloud-G07.md`와 `CODE_REVIEW-cloud-G07.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
- 없음
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- `services/core/internal/authoring/result.go` 및 `result_test.go`를 신설하여 `DecideAuthoringResult` 헬퍼 함수를 추가하고, BridgeSuccess, DevelopMatch, ExitCode, PushFailed, DirtyWorkspace, Conflict 등 입력에 따라 run state 및 failure category를 판정하는 규칙을 통합 및 격리함.
|
||||
- `services/core/internal/scheduler/jobs.go`의 `runTask`에서 모델 Generate 성공 시 run state를 곧바로 `succeeded`로 기재하던 기존 방식 대신 `in_progress`로 설정하게 조정하여, 이후 로드맵 동기화 단계(develop Milestone match 완료) 전까지 success 판정을 조기 선언하지 않도록 제어함.
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `Model.Generate` 성공만으로 `authoring_run_state=succeeded`가 기록되지 않는지 확인한다.
|
||||
- develop-ready signal만 성공으로 분류되고, push failure/dirty/conflict/exit code는 failed로 분류되는지 확인한다.
|
||||
- 새 상태 값이 늘지 않고 기존 `in_progress`, `succeeded`, `failed` 범위 안에서 metadata reason이 남는지 확인한다.
|
||||
- `Roadmap Targets`의 `agent-run-result` 완료 주장과 실제 구현/검증이 일치하는지 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
### AGENT_BRIDGE-1 중간 검증
|
||||
|
||||
```bash
|
||||
$ cd services/core && go test -count=1 ./internal/authoring ./internal/scheduler ./internal/roadmapsync
|
||||
ok github.com/nomadcode/nomadcode-core/internal/authoring 0.002s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/scheduler 2.012s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/roadmapsync 0.004s
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
|
||||
```bash
|
||||
$ cd services/core && go test ./...
|
||||
ok github.com/nomadcode/nomadcode-core/cmd/plane-smoke (cached)
|
||||
? github.com/nomadcode/nomadcode-core/cmd/server [no test files]
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/a2a (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/jira (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/mattermost (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/openai (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/plane (cached)
|
||||
? github.com/nomadcode/nomadcode-core/internal/agent [no test files]
|
||||
ok github.com/nomadcode/nomadcode-core/internal/authoring 0.004s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/config (cached)
|
||||
? github.com/nomadcode/nomadcode-core/internal/db [no test files]
|
||||
ok github.com/nomadcode/nomadcode-core/internal/http (cached)
|
||||
? github.com/nomadcode/nomadcode-core/internal/model [no test files]
|
||||
ok github.com/nomadcode/nomadcode-core/internal/notification (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/projectsync (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/protosocket (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/roadmapsync (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/scheduler 2.011s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/storage (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/workflow (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/workitem (cached)
|
||||
ok github.com/nomadcode/nomadcode-core/internal/workitempipeline (cached)
|
||||
|
||||
$ cd services/core && go vet ./...
|
||||
(exit code 0, no errors)
|
||||
|
||||
$ git diff --check
|
||||
(exit code 0, no errors)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
## Ownership
|
||||
|
||||
| Section | Owner | Note |
|
||||
|---------|-------|------|
|
||||
| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | Implementing agent must not modify or execute these |
|
||||
| Roadmap Targets | Fixed at stub creation from plan | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS |
|
||||
| 구현 항목별 완료 여부 | Implementing agent | Check `[ ]` -> `[x]` only |
|
||||
| 구현 체크리스트 | Implementing agent | Check `[ ]` -> `[x]` only; final checkbox is mandatory |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | Replace placeholder text with actual content |
|
||||
| 사용자 리뷰 요청 | Implementing agent | Keep `상태: 없음` unless user input is required to proceed |
|
||||
| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Pre-filled from plan |
|
||||
| 검증 결과 | Implementing agent | Fill command output only |
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- **종합 판정**: PASS
|
||||
- **차원별 평가**:
|
||||
- Correctness: Pass
|
||||
- Completeness: Pass
|
||||
- Test coverage: Pass
|
||||
- API contract: Pass
|
||||
- Code quality: Pass
|
||||
- Plan deviation: Pass
|
||||
- Verification trust: Pass
|
||||
- **발견된 문제**: 없음
|
||||
- **다음 단계**: PASS - `complete.log` 작성 및 `agent-task/archive/` 하위로 작업 폴더 이동을 진행한다.
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Complete - m-milestone-work-item-creation-sync/08_agent_run_result_gate
|
||||
|
||||
## 완료 일시
|
||||
|
||||
2026-06-14
|
||||
|
||||
## 요약
|
||||
|
||||
Workspace agent authoring run의 성공/실패 판정 기준 수립을 위한 Authoring Result Gate 구현 완료 (1 loop, PASS)
|
||||
|
||||
## 루프 이력
|
||||
|
||||
| Plan | Review | Verdict | 메모 |
|
||||
|------|--------|---------|------|
|
||||
| `plan_cloud_G07_0.log` | `code_review_cloud_G07_0.log` | PASS | Authoring Result Gate 구현 및 테스트 추가 완료 |
|
||||
|
||||
## 구현/정리 내용
|
||||
|
||||
- `services/core/internal/workflow/model.go`에 `MetadataKeyAuthoringFailureCategory` 상수 추가
|
||||
- `services/core/internal/authoring/result.go` 및 `result_test.go` 신설하여 `DecideAuthoringResult` 헬퍼 함수 구현 및 테스트 작성
|
||||
- `services/core/internal/scheduler/jobs.go` 수정하여 모델 Generate 성공 시 `authoring_run_state`를 `in_progress`로 변경
|
||||
- `services/core/internal/scheduler/jobs_test.go`의 `TestRunTaskAuthoringSuccessRecordsState` 테스트 코드가 `in_progress` 상태를 올바르게 검증하도록 수정
|
||||
|
||||
## 최종 검증
|
||||
|
||||
- `cd services/core && go test ./...` - PASS; 전체 테스트 통과
|
||||
- `cd services/core && go vet ./...` - PASS; 정적 분석 에러 없음
|
||||
- `git diff --check` - PASS; 스타일 및 공백 검사 오류 없음
|
||||
|
||||
## Roadmap Completion
|
||||
|
||||
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
|
||||
- Completed task ids:
|
||||
- `agent-run-result`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`; verification=`go test ./...`
|
||||
- Not completed task ids: 없음
|
||||
|
||||
## 잔여 Nit
|
||||
|
||||
- 없음
|
||||
|
||||
## 후속 작업
|
||||
|
||||
- 없음
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
<!-- task=m-milestone-work-item-creation-sync/08_agent_run_result_gate plan=0 tag=AGENT_BRIDGE -->
|
||||
|
||||
# Plan - AGENT_BRIDGE
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
`CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채우는 것이 필수다. 구현 후 검증을 실행하고 active 파일은 그대로 둔 채 리뷰 준비를 보고한다. 사용자 결정, 사용자 소유 외부 환경, 범위 충돌로 막히면 review stub의 `사용자 리뷰 요청`에 근거를 기록하고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 명령 재실행이나 산출물 수집으로 닫을 수 있는 증거 공백은 사용자 리뷰 요청이 아니다. 최종 archive, `complete.log`, roadmap 반영은 code-review/runtime 책임이다.
|
||||
|
||||
## 배경
|
||||
|
||||
`agent-bridge`의 라우팅, 최소 상태, provider identity, 실행 잠금 기준은 현재 Core 코드와 테스트로 확인된다. 남은 문제는 scheduler가 IOP bridge 응답 성공만으로 `authoring_run_state=succeeded`를 기록하는 반면, 마일스톤의 성공 기준은 `develop` branch에 Milestone 변경이 commit/push되고 이후 sync layer가 provider identity로 매칭하는 것이다. 이 계획은 bridge 응답 성공과 develop 반영 성공을 분리해 `[agent-run-result]`의 완료 기준을 코드와 테스트로 닫는다.
|
||||
|
||||
## 사용자 리뷰 요청 흐름
|
||||
|
||||
구현 중 사용자 결정이나 사용자 소유 외부 환경/secret이 필요하면 active `CODE_REVIEW-cloud-G07.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 사용자 프롬프트는 금지되며, code-review가 요청의 타당성을 판단하고 필요할 때만 `USER_REVIEW.md`를 작성한다.
|
||||
|
||||
## Roadmap Targets
|
||||
|
||||
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
|
||||
- Task ids:
|
||||
- `agent-run-result`: Workspace agent authoring run의 성공/실패 판정 기준
|
||||
- Completion mode: check-on-pass
|
||||
|
||||
## 분석 결과
|
||||
|
||||
### 읽은 파일
|
||||
|
||||
- `agent-roadmap/current.md`
|
||||
- `agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md`
|
||||
- `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
|
||||
- `agent-ops/rules/project/domain/core/rules.md`
|
||||
- `agent-ops/rules/project/domain/workspace-ops/rules.md`
|
||||
- `agent-test/local/rules.md`
|
||||
- `agent-test/local/core-smoke.md`
|
||||
- `agent-test/local/workspace-ops-smoke.md`
|
||||
- `services/core/internal/scheduler/jobs.go`
|
||||
- `services/core/internal/scheduler/jobs_test.go`
|
||||
- `services/core/internal/authoring/request.go`
|
||||
- `services/core/internal/authoring/request_test.go`
|
||||
- `services/core/internal/model/model.go`
|
||||
- `services/core/internal/adapters/openai/client.go`
|
||||
- `services/core/internal/adapters/openai/client_test.go`
|
||||
- `services/core/internal/workflow/model.go`
|
||||
- `services/core/internal/workflow/lifecycle.go`
|
||||
- `services/core/internal/roadmapsync/identity.go`
|
||||
- `services/core/internal/roadmapsync/identity_test.go`
|
||||
- `services/core/internal/roadmapsync/develop_match.go`
|
||||
- `services/core/internal/roadmapsync/develop_match_test.go`
|
||||
- `services/core/internal/projectsync/config.go`
|
||||
- `services/core/internal/projectsync/checkout.go`
|
||||
- `services/core/internal/projectsync/provision.go`
|
||||
- `services/core/internal/workitempipeline/service.go`
|
||||
- `services/core/internal/config/config.go`
|
||||
- `services/core/cmd/server/main.go`
|
||||
|
||||
### 테스트 환경 규칙
|
||||
|
||||
- `test_env=local`.
|
||||
- `agent-test/local/rules.md`를 읽었다.
|
||||
- core 변경 기준으로 `agent-test/local/core-smoke.md`를 읽었다. 적용 명령은 `cd services/core && go test ./...`, 보조로 `cd services/core && go vet ./...`다.
|
||||
- roadmap/task artifact 변경 기준으로 `agent-test/local/workspace-ops-smoke.md`를 읽었다. 적용 명령은 `git diff --check`다.
|
||||
- `<확인 필요>` 값은 실행 환경 설명 예시에만 있고, 이번 계획의 명령 선택을 막지 않는다.
|
||||
|
||||
### 테스트 커버리지 공백
|
||||
|
||||
- Plane-origin authoring task가 IOP OpenAI-compatible model bridge로 라우팅되는 동작은 `services/core/internal/scheduler/jobs_test.go`와 `services/core/internal/authoring/request_test.go`가 다룬다.
|
||||
- `metadata.workspace`가 `/v1/responses` request에 flat string으로 들어가는 동작은 `services/core/internal/adapters/openai/client_test.go`가 다룬다.
|
||||
- provider/work item identity와 pushed develop Milestone match 기준은 `services/core/internal/roadmapsync/*_test.go`가 다룬다.
|
||||
- model bridge 응답 성공만으로 authoring 성공을 확정하지 않는 회귀 테스트가 없다. 이번 구현에서 추가해야 한다.
|
||||
- exit code, push 실패, dirty workspace, conflict 신호를 authoring failure reason으로 분류하는 단위 테스트가 없다. 이번 구현에서 추가해야 한다.
|
||||
|
||||
### 심볼 참조
|
||||
|
||||
- renamed/removed symbol: none.
|
||||
|
||||
### 분할 판단
|
||||
|
||||
분할 정책을 먼저 평가했다. 이 작업은 milestone-linked shared task group `m-milestone-work-item-creation-sync` 아래의 단일 subtask `08_agent_run_result_gate`로 둔다. 수정 범위는 Core authoring/scheduler result gate와 해당 테스트로 한정되고, API foundation과 광범위 call-site rollout이 분리되지 않는다. git/process 실행 자체를 여기서 새로 구현하지 않고 post-authoring 결과 판정 계약과 scheduler metadata 경계를 닫는 작업이므로 별도 선행 subtask가 필요하지 않다. 디렉터리명에 `+` dependency가 없으므로 predecessor `complete.log` 확인은 필요 없다.
|
||||
|
||||
### 범위 결정 근거
|
||||
|
||||
- Plane `Todo -> In Progress` 실행 시작, 하위 티켓 생성, User Review/Done/Cancelled projection은 마일스톤 범위 제외라 건드리지 않는다.
|
||||
- 실제 IOP Edge 원격 smoke나 real git push는 사용자/환경 의존성이 크므로 단위 테스트 대상이 아니다.
|
||||
- `roadmapsync.MatchDevelopMilestone`의 develop scan matching 규칙은 이미 존재하므로, 이번 작업은 그 결과를 authoring run 성공 판정에 반영할 수 있는 Core-side 경계로 제한한다.
|
||||
- DB migration과 SQLC 생성은 새 persisted column이 필요할 때만 확장한다. 가능하면 기존 task metadata에 authoring result/failure metadata를 남긴다.
|
||||
|
||||
### 빌드 등급
|
||||
|
||||
- build=`cloud-G07`, review=`cloud-G07`: scheduler 상태 전이와 git/develop push 성공 의미를 분리하는 작업이며, 실패 분류와 검증 신뢰도가 중요하다.
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] [AGENT_BRIDGE-1] bridge 응답 성공과 develop 반영 성공을 분리하는 authoring result gate를 구현하고, `agent-run-result`의 성공/실패 판정 테스트를 추가한다.
|
||||
- [ ] 중간 검증 `cd services/core && go test -count=1 ./internal/authoring ./internal/scheduler ./internal/roadmapsync`를 실행한다.
|
||||
- [ ] 최종 검증 `cd services/core && go test ./...`, `cd services/core && go vet ./...`, `git diff --check`를 실행한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
### [AGENT_BRIDGE-1] Authoring Result Gate
|
||||
|
||||
### 문제
|
||||
|
||||
`services/core/internal/scheduler/jobs.go:140-157`은 model bridge 호출이 성공하면 바로 `authoring_run_state=succeeded`를 result payload에 넣는다.
|
||||
|
||||
```go
|
||||
140 result := map[string]any{
|
||||
141 "message": generated.Text,
|
||||
142 "mode": "authoring_run",
|
||||
143 "model": generated.Model,
|
||||
144 "response_id": generated.ID,
|
||||
145 "authoring_run_state": "succeeded",
|
||||
146 "authoring_run_updated_at": time.Now().UTC().Format(time.RFC3339),
|
||||
147 "usage": map[string]int{
|
||||
148 "input_tokens": generated.Usage.InputTokens,
|
||||
149 "output_tokens": generated.Usage.OutputTokens,
|
||||
150 "total_tokens": generated.Usage.TotalTokens,
|
||||
151 },
|
||||
152 }
|
||||
153 raw, err := json.Marshal(result)
|
||||
154 if err != nil {
|
||||
155 return nil, "", err
|
||||
156 }
|
||||
157 return raw, "authoring run completed", nil
|
||||
```
|
||||
|
||||
마일스톤 기준에서는 authoring 성공이 `develop` branch Milestone 변경 commit/push이며, `roadmapsync.MatchDevelopMilestone`은 이미 pushed develop revision과 provider identity match만 projection-ready로 본다.
|
||||
|
||||
```go
|
||||
44 func MatchDevelopMilestone(in MatchInput) ProjectionCandidate {
|
||||
45 revision := in.Scan.Revision.Normalize()
|
||||
52 if !revision.OnDevelop() {
|
||||
55 if revision.Revision == "" {
|
||||
58 if !changedFilesContainMilestone(in.Scan.ChangedFiles, expected.RoadmapMilestonePath) {
|
||||
62 scanned, ok := scannedIdentityForPath(in.Scan.ScannedMilestones, expected.RoadmapMilestonePath)
|
||||
68 if !expected.Matches(scanned) {
|
||||
72 return ProjectionCandidate{
|
||||
75 Ready: true,
|
||||
76 Reason: reasonReady,
|
||||
77 }
|
||||
```
|
||||
|
||||
### 해결 방법
|
||||
|
||||
1. `services/core/internal/authoring/`에 result decision helper를 추가한다. helper는 bridge response success, develop match ready, exit code/push failure/dirty/conflict 같은 failure signal을 입력으로 받아 기존 최소 상태인 `in_progress`, `succeeded`, `failed` 중 하나와 metadata reason을 반환한다.
|
||||
2. scheduler는 `Model.Generate` 성공만으로 `succeeded`를 기록하지 않는다. develop match evidence가 아직 없으면 `authoring_run_state`를 유지하거나 `in_progress`로 두고, response id/model/usage 같은 bridge evidence만 별도 metadata에 남긴다.
|
||||
3. sync layer가 pushed develop match를 확인한 뒤 사용할 수 있도록 helper의 ready path는 `succeeded`, failure path는 `failed`와 failure category를 반환하게 한다. 기존 `roadmapsync.MatchDevelopMilestone`은 수정하지 않고 호출 가능한 결정 입력으로 활용한다.
|
||||
4. 기존 tests 중 `TestRunTaskAuthoringSuccessRecordsState`는 model response만으로 success를 기대하지 않도록 바꾼다. 새 tests는 develop-ready signal에서만 `succeeded`, push failure/dirty/conflict/exit code signal에서 `failed`가 되는지 확인한다.
|
||||
|
||||
### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `services/core/internal/authoring/result.go`를 추가하거나 동등한 authoring result helper를 만든다.
|
||||
- [ ] `services/core/internal/authoring/result_test.go`를 추가해 ready/failure/in-progress 분류를 검증한다.
|
||||
- [ ] `services/core/internal/scheduler/jobs.go`에서 authoring model response result payload가 success를 과잉 주장하지 않게 조정한다.
|
||||
- [ ] `services/core/internal/scheduler/jobs_test.go`의 authoring success 관련 기대값을 새 경계에 맞게 갱신하고 회귀 테스트를 추가한다.
|
||||
- [ ] 필요 시 `services/core/internal/workflow/model.go`에 authoring failure category metadata key를 추가하되, 새 task 상태 값은 만들지 않는다.
|
||||
|
||||
### 테스트 작성
|
||||
|
||||
테스트를 작성한다.
|
||||
|
||||
- `services/core/internal/authoring/result_test.go`: develop match ready signal만 `succeeded`가 되는지 검증한다.
|
||||
- `services/core/internal/authoring/result_test.go`: exit code, push failure, dirty workspace, conflict signal이 `failed`와 구체 reason/category로 분류되는지 검증한다.
|
||||
- `services/core/internal/scheduler/jobs_test.go`: model bridge 응답 성공만으로 `authoring_run_state=succeeded`가 기록되지 않는지 검증한다.
|
||||
- 기존 `roadmapsync` tests는 유지하고, 새 helper가 필요로 하는 ready candidate fixture만 재사용한다.
|
||||
|
||||
### 중간 검증
|
||||
|
||||
```bash
|
||||
cd services/core && go test -count=1 ./internal/authoring ./internal/scheduler ./internal/roadmapsync
|
||||
```
|
||||
|
||||
예상 결과: 세 패키지 테스트가 실패 없이 종료한다. fresh 실행이 중요하므로 `-count=1`을 사용한다.
|
||||
|
||||
## 수정 파일 요약
|
||||
|
||||
| 파일 | 항목 |
|
||||
|------|------|
|
||||
| `services/core/internal/authoring/result.go` | AGENT_BRIDGE-1 |
|
||||
| `services/core/internal/authoring/result_test.go` | AGENT_BRIDGE-1 |
|
||||
| `services/core/internal/scheduler/jobs.go` | AGENT_BRIDGE-1 |
|
||||
| `services/core/internal/scheduler/jobs_test.go` | AGENT_BRIDGE-1 |
|
||||
| `services/core/internal/workflow/model.go` | AGENT_BRIDGE-1 |
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
cd services/core && go test ./...
|
||||
cd services/core && go vet ./...
|
||||
git diff --check
|
||||
```
|
||||
|
||||
예상 결과: 모든 명령이 실패 없이 종료한다. `go test ./...`는 전체 회귀 확인이므로 캐시 출력이 허용된다. whitespace 검증은 repo root에서 실행한다.
|
||||
|
||||
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
89
services/core/internal/authoring/result.go
Normal file
89
services/core/internal/authoring/result.go
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package authoring
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nomadcode/nomadcode-core/internal/roadmapsync"
|
||||
)
|
||||
|
||||
// DecisionInput contains the outputs and signals from the authoring process,
|
||||
// used to determine the final authoring run state.
|
||||
type DecisionInput struct {
|
||||
BridgeSuccess bool
|
||||
DevelopMatch roadmapsync.ProjectionCandidate
|
||||
ExitCode *int
|
||||
PushFailed bool
|
||||
DirtyWorkspace bool
|
||||
Conflict bool
|
||||
}
|
||||
|
||||
// Decision represents the state, reason, and failure category determined by the result helper.
|
||||
type Decision struct {
|
||||
State string // "in_progress", "succeeded", "failed"
|
||||
Reason string
|
||||
FailureCategory string // "bridge_failed", "exit_code", "push_failed", "dirty_workspace", "conflict"
|
||||
}
|
||||
|
||||
// DecideAuthoringResult evaluates the authoring run inputs and signals to classify
|
||||
// the task outcome as succeeded, failed (with specific category), or in_progress.
|
||||
func DecideAuthoringResult(in DecisionInput) Decision {
|
||||
if !in.BridgeSuccess {
|
||||
return Decision{
|
||||
State: "failed",
|
||||
Reason: "model bridge response failed",
|
||||
FailureCategory: "bridge_failed",
|
||||
}
|
||||
}
|
||||
|
||||
if in.ExitCode != nil && *in.ExitCode != 0 {
|
||||
return Decision{
|
||||
State: "failed",
|
||||
Reason: fmt.Sprintf("agent process exited with non-zero code %d", *in.ExitCode),
|
||||
FailureCategory: "exit_code",
|
||||
}
|
||||
}
|
||||
|
||||
if in.PushFailed {
|
||||
return Decision{
|
||||
State: "failed",
|
||||
Reason: "git push to develop branch failed",
|
||||
FailureCategory: "push_failed",
|
||||
}
|
||||
}
|
||||
|
||||
if in.DirtyWorkspace {
|
||||
return Decision{
|
||||
State: "failed",
|
||||
Reason: "workspace contains dirty changes",
|
||||
FailureCategory: "dirty_workspace",
|
||||
}
|
||||
}
|
||||
|
||||
if in.Conflict {
|
||||
return Decision{
|
||||
State: "failed",
|
||||
Reason: "git merge conflict detected",
|
||||
FailureCategory: "conflict",
|
||||
}
|
||||
}
|
||||
|
||||
if in.DevelopMatch.Ready {
|
||||
reason := in.DevelopMatch.Reason
|
||||
if reason == "" {
|
||||
reason = "pushed develop milestone matched expected identity"
|
||||
}
|
||||
return Decision{
|
||||
State: "succeeded",
|
||||
Reason: reason,
|
||||
}
|
||||
}
|
||||
|
||||
reason := in.DevelopMatch.Reason
|
||||
if reason == "" {
|
||||
reason = "waiting for pushed develop milestone match"
|
||||
}
|
||||
return Decision{
|
||||
State: "in_progress",
|
||||
Reason: reason,
|
||||
}
|
||||
}
|
||||
131
services/core/internal/authoring/result_test.go
Normal file
131
services/core/internal/authoring/result_test.go
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
package authoring
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/nomadcode/nomadcode-core/internal/roadmapsync"
|
||||
)
|
||||
|
||||
func TestDecideAuthoringResult(t *testing.T) {
|
||||
intPtr := func(v int) *int { return &v }
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input DecisionInput
|
||||
expected Decision
|
||||
}{
|
||||
{
|
||||
name: "bridge failure",
|
||||
input: DecisionInput{
|
||||
BridgeSuccess: false,
|
||||
},
|
||||
expected: Decision{
|
||||
State: "failed",
|
||||
Reason: "model bridge response failed",
|
||||
FailureCategory: "bridge_failed",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "exit code nonzero",
|
||||
input: DecisionInput{
|
||||
BridgeSuccess: true,
|
||||
ExitCode: intPtr(1),
|
||||
},
|
||||
expected: Decision{
|
||||
State: "failed",
|
||||
Reason: "agent process exited with non-zero code 1",
|
||||
FailureCategory: "exit_code",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "exit code zero is ignored",
|
||||
input: DecisionInput{
|
||||
BridgeSuccess: true,
|
||||
ExitCode: intPtr(0),
|
||||
},
|
||||
expected: Decision{
|
||||
State: "in_progress",
|
||||
Reason: "waiting for pushed develop milestone match",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "push failed",
|
||||
input: DecisionInput{
|
||||
BridgeSuccess: true,
|
||||
PushFailed: true,
|
||||
},
|
||||
expected: Decision{
|
||||
State: "failed",
|
||||
Reason: "git push to develop branch failed",
|
||||
FailureCategory: "push_failed",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dirty workspace",
|
||||
input: DecisionInput{
|
||||
BridgeSuccess: true,
|
||||
DirtyWorkspace: true,
|
||||
},
|
||||
expected: Decision{
|
||||
State: "failed",
|
||||
Reason: "workspace contains dirty changes",
|
||||
FailureCategory: "dirty_workspace",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "conflict",
|
||||
input: DecisionInput{
|
||||
BridgeSuccess: true,
|
||||
Conflict: true,
|
||||
},
|
||||
expected: Decision{
|
||||
State: "failed",
|
||||
Reason: "git merge conflict detected",
|
||||
FailureCategory: "conflict",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "develop match ready succeeds",
|
||||
input: DecisionInput{
|
||||
BridgeSuccess: true,
|
||||
DevelopMatch: roadmapsync.ProjectionCandidate{
|
||||
Ready: true,
|
||||
Reason: "matched",
|
||||
},
|
||||
},
|
||||
expected: Decision{
|
||||
State: "succeeded",
|
||||
Reason: "matched",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "develop match not ready is in_progress",
|
||||
input: DecisionInput{
|
||||
BridgeSuccess: true,
|
||||
DevelopMatch: roadmapsync.ProjectionCandidate{
|
||||
Ready: false,
|
||||
Reason: "no revision yet",
|
||||
},
|
||||
},
|
||||
expected: Decision{
|
||||
State: "in_progress",
|
||||
Reason: "no revision yet",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := DecideAuthoringResult(tt.input)
|
||||
if got.State != tt.expected.State {
|
||||
t.Errorf("expected state %q, got %q", tt.expected.State, got.State)
|
||||
}
|
||||
if got.Reason != tt.expected.Reason {
|
||||
t.Errorf("expected reason %q, got %q", tt.expected.Reason, got.Reason)
|
||||
}
|
||||
if got.FailureCategory != tt.expected.FailureCategory {
|
||||
t.Errorf("expected failure category %q, got %q", tt.expected.FailureCategory, got.FailureCategory)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ func (w *TaskWorker) runTask(ctx context.Context, task storage.Task) (json.RawMe
|
|||
"mode": "authoring_run",
|
||||
"model": generated.Model,
|
||||
"response_id": generated.ID,
|
||||
"authoring_run_state": "succeeded",
|
||||
"authoring_run_state": "in_progress",
|
||||
"authoring_run_updated_at": time.Now().UTC().Format(time.RFC3339),
|
||||
"usage": map[string]int{
|
||||
"input_tokens": generated.Usage.InputTokens,
|
||||
|
|
|
|||
|
|
@ -605,8 +605,8 @@ func TestRunTaskAuthoringSuccessRecordsState(t *testing.T) {
|
|||
if err := json.Unmarshal(raw, &result); err != nil {
|
||||
t.Fatalf("unmarshal result: %v", err)
|
||||
}
|
||||
if result["authoring_run_state"] != "succeeded" {
|
||||
t.Errorf("expected authoring_run_state=succeeded, got %#v", result["authoring_run_state"])
|
||||
if result["authoring_run_state"] != "in_progress" {
|
||||
t.Errorf("expected authoring_run_state=in_progress, got %#v", result["authoring_run_state"])
|
||||
}
|
||||
if result["authoring_run_updated_at"] == nil || result["authoring_run_updated_at"] == "" {
|
||||
t.Error("expected authoring_run_updated_at to be set")
|
||||
|
|
|
|||
|
|
@ -54,9 +54,10 @@ const (
|
|||
// authoring_run_state values: "in_progress", "succeeded", "failed".
|
||||
// Stale detection uses authoring_run_updated_at compared against a
|
||||
// configured staleness threshold — no separate timeout state is stored.
|
||||
MetadataKeyAuthoringRunState = "authoring_run_state"
|
||||
MetadataKeyAuthoringRunUpdatedAt = "authoring_run_updated_at"
|
||||
MetadataKeyAuthoringFailureType = "authoring_failure_type"
|
||||
MetadataKeyAuthoringRunState = "authoring_run_state"
|
||||
MetadataKeyAuthoringRunUpdatedAt = "authoring_run_updated_at"
|
||||
MetadataKeyAuthoringFailureType = "authoring_failure_type"
|
||||
MetadataKeyAuthoringFailureCategory = "authoring_failure_category"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue