Compare commits
35 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b964287062 | ||
|
|
c1db9de07b | ||
|
|
a808912f4c | ||
|
|
448d6d0633 | ||
|
|
e21644ee65 | ||
|
|
bd66594ffe | ||
|
|
ac170f5302 | ||
|
|
77c902d4c8 | ||
|
|
4c5d56f9dd | ||
|
|
42b0d1a8a5 | ||
|
|
738f4b8d20 | ||
|
|
6fc5e384e6 | ||
|
|
2999229248 | ||
|
|
936ee616a8 | ||
|
|
c9f3728607 | ||
|
|
29c7182d98 | ||
|
|
fcf8b2c661 | ||
|
|
e12a973f4e | ||
|
|
5f7aac1c28 | ||
|
|
60dd7deee2 | ||
|
|
bf15e34a01 | ||
|
|
5b40d1db49 | ||
|
|
8ecb496cce | ||
|
|
0169c94e3b | ||
| 881181dbb6 | |||
|
|
551e0de09d | ||
|
|
2641bf9e1f | ||
|
|
21f9f1db45 | ||
|
|
75b6b560a5 | ||
|
|
e16f4615b5 | ||
|
|
a050decf69 | ||
| b0c8863d3e | |||
| de9db7234b | |||
|
|
89aefff4d8 | ||
|
|
38f71628f2 |
268 changed files with 1526 additions and 28901 deletions
18
.clinerules
18
.clinerules
|
|
@ -3,21 +3,15 @@
|
|||
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- `agent-ops/rules/common/**`와 `agent-ops/skills/common/**`은 중앙 관리되는 공통 영역이므로 어떤 프로젝트 작업에서도 사용자가 직접 지시하지 않는 이상 절대 직접 수정하지 않는다. 프로젝트별 규칙과 스킬은 반드시 대응하는 `project/**` 영역에만 반영한다.
|
||||
- 최종 답변은 한국어로 한다.
|
||||
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우, plan 스킬이 같은 task group의 새 index를 충돌 없이 할당하는 경우, 또는 `sync-agent-ui mode=reconcile-completion`에 exact `completion-log` 경로가 전달된 경우에만 필요한 범위를 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다. index 할당은 같은 task group의 archived sibling directory basename만 열람하고 내부 파일은 읽지 않는다. UI 완료 정합화는 전달된 exact `complete.log` 한 건만 읽고 sibling archive log를 탐색하지 않는다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, 또는 plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우에만 필요한 파일을 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-spec/` 디렉터리가 있는 프로젝트에서 현재 구현 스펙 확인, 기존 기능 변경, 완료 검토, 구현 스펙 생성/갱신 요청은 세션 1회 `agent-ops/rules/common/rules-agent-spec.md`를 읽고, `agent-spec/index.md`와 매칭되는 spec 문서만 읽는다.
|
||||
- `agent-spec/archive/**`는 일반 작업에서 읽지 않는다. 과거 스펙 확인, 복원, 비교, 특정 archive 경로 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-spec.md`의 archive 접근 규칙을 따른다.
|
||||
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||
- project skill 경로 `agent-ops/skills/project/<skill-name>/SKILL.md`를 선택했을 때 같은 이름의 `agent-ops/skills/private/<skill-name>/SKILL.md`가 있으면 private skill을 우선한다. 없으면 project skill을 사용한다.
|
||||
- project skill과 짝이 없는 private skill은 `agent-ops/rules/private/rules.md`에 명시적으로 라우팅한다. private skill 디렉터리 전체를 탐색하지 않는다.
|
||||
- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
|
|
@ -35,16 +29,12 @@
|
|||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW
|
||||
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||
- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리
|
||||
- agent-spec 생성/갱신, 현재 구현 스펙 문서화, 구현 스펙 업데이트, 스펙 동기화
|
||||
- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리
|
||||
- README 생성
|
||||
- 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- SDD 작성/갱신, SDD 필요 여부, SDD gate 확인, SDD 사용자 리뷰, SDD 잠금 해제
|
||||
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||
- 마일스톤 완료 검토 / 종료 검토 / 현재 마일스톤 닫기 / 다음 마일스톤 지정
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
|
|
|
|||
18
.cursorrules
18
.cursorrules
|
|
@ -3,21 +3,15 @@
|
|||
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- `agent-ops/rules/common/**`와 `agent-ops/skills/common/**`은 중앙 관리되는 공통 영역이므로 어떤 프로젝트 작업에서도 사용자가 직접 지시하지 않는 이상 절대 직접 수정하지 않는다. 프로젝트별 규칙과 스킬은 반드시 대응하는 `project/**` 영역에만 반영한다.
|
||||
- 최종 답변은 한국어로 한다.
|
||||
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우, plan 스킬이 같은 task group의 새 index를 충돌 없이 할당하는 경우, 또는 `sync-agent-ui mode=reconcile-completion`에 exact `completion-log` 경로가 전달된 경우에만 필요한 범위를 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다. index 할당은 같은 task group의 archived sibling directory basename만 열람하고 내부 파일은 읽지 않는다. UI 완료 정합화는 전달된 exact `complete.log` 한 건만 읽고 sibling archive log를 탐색하지 않는다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, 또는 plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우에만 필요한 파일을 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-spec/` 디렉터리가 있는 프로젝트에서 현재 구현 스펙 확인, 기존 기능 변경, 완료 검토, 구현 스펙 생성/갱신 요청은 세션 1회 `agent-ops/rules/common/rules-agent-spec.md`를 읽고, `agent-spec/index.md`와 매칭되는 spec 문서만 읽는다.
|
||||
- `agent-spec/archive/**`는 일반 작업에서 읽지 않는다. 과거 스펙 확인, 복원, 비교, 특정 archive 경로 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-spec.md`의 archive 접근 규칙을 따른다.
|
||||
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||
- project skill 경로 `agent-ops/skills/project/<skill-name>/SKILL.md`를 선택했을 때 같은 이름의 `agent-ops/skills/private/<skill-name>/SKILL.md`가 있으면 private skill을 우선한다. 없으면 project skill을 사용한다.
|
||||
- project skill과 짝이 없는 private skill은 `agent-ops/rules/private/rules.md`에 명시적으로 라우팅한다. private skill 디렉터리 전체를 탐색하지 않는다.
|
||||
- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
|
|
@ -35,16 +29,12 @@
|
|||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW
|
||||
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||
- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리
|
||||
- agent-spec 생성/갱신, 현재 구현 스펙 문서화, 구현 스펙 업데이트, 스펙 동기화
|
||||
- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리
|
||||
- README 생성
|
||||
- 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- SDD 작성/갱신, SDD 필요 여부, SDD gate 확인, SDD 사용자 리뷰, SDD 잠금 해제
|
||||
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||
- 마일스톤 완료 검토 / 종료 검토 / 현재 마일스톤 닫기 / 다음 마일스톤 지정
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -50,6 +50,3 @@ agent-test/runs/
|
|||
!agent-task/**/*.log
|
||||
agent-roadmap/current.md
|
||||
# END Agent-Ops managed gitignore
|
||||
|
||||
# Agent-Ops Private Skills
|
||||
agent-ops/skills/private/
|
||||
|
|
|
|||
18
AGENTS.md
18
AGENTS.md
|
|
@ -3,21 +3,15 @@
|
|||
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- `agent-ops/rules/common/**`와 `agent-ops/skills/common/**`은 중앙 관리되는 공통 영역이므로 어떤 프로젝트 작업에서도 사용자가 직접 지시하지 않는 이상 절대 직접 수정하지 않는다. 프로젝트별 규칙과 스킬은 반드시 대응하는 `project/**` 영역에만 반영한다.
|
||||
- 최종 답변은 한국어로 한다.
|
||||
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우, plan 스킬이 같은 task group의 새 index를 충돌 없이 할당하는 경우, 또는 `sync-agent-ui mode=reconcile-completion`에 exact `completion-log` 경로가 전달된 경우에만 필요한 범위를 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다. index 할당은 같은 task group의 archived sibling directory basename만 열람하고 내부 파일은 읽지 않는다. UI 완료 정합화는 전달된 exact `complete.log` 한 건만 읽고 sibling archive log를 탐색하지 않는다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, 또는 plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우에만 필요한 파일을 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-spec/` 디렉터리가 있는 프로젝트에서 현재 구현 스펙 확인, 기존 기능 변경, 완료 검토, 구현 스펙 생성/갱신 요청은 세션 1회 `agent-ops/rules/common/rules-agent-spec.md`를 읽고, `agent-spec/index.md`와 매칭되는 spec 문서만 읽는다.
|
||||
- `agent-spec/archive/**`는 일반 작업에서 읽지 않는다. 과거 스펙 확인, 복원, 비교, 특정 archive 경로 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-spec.md`의 archive 접근 규칙을 따른다.
|
||||
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||
- project skill 경로 `agent-ops/skills/project/<skill-name>/SKILL.md`를 선택했을 때 같은 이름의 `agent-ops/skills/private/<skill-name>/SKILL.md`가 있으면 private skill을 우선한다. 없으면 project skill을 사용한다.
|
||||
- project skill과 짝이 없는 private skill은 `agent-ops/rules/private/rules.md`에 명시적으로 라우팅한다. private skill 디렉터리 전체를 탐색하지 않는다.
|
||||
- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
|
|
@ -35,16 +29,12 @@
|
|||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW
|
||||
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||
- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리
|
||||
- agent-spec 생성/갱신, 현재 구현 스펙 문서화, 구현 스펙 업데이트, 스펙 동기화
|
||||
- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리
|
||||
- README 생성
|
||||
- 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- SDD 작성/갱신, SDD 필요 여부, SDD gate 확인, SDD 사용자 리뷰, SDD 잠금 해제
|
||||
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||
- 마일스톤 완료 검토 / 종료 검토 / 현재 마일스톤 닫기 / 다음 마일스톤 지정
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
|
|
|
|||
18
CLAUDE.md
18
CLAUDE.md
|
|
@ -3,21 +3,15 @@
|
|||
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- `agent-ops/rules/common/**`와 `agent-ops/skills/common/**`은 중앙 관리되는 공통 영역이므로 어떤 프로젝트 작업에서도 사용자가 직접 지시하지 않는 이상 절대 직접 수정하지 않는다. 프로젝트별 규칙과 스킬은 반드시 대응하는 `project/**` 영역에만 반영한다.
|
||||
- 최종 답변은 한국어로 한다.
|
||||
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우, plan 스킬이 같은 task group의 새 index를 충돌 없이 할당하는 경우, 또는 `sync-agent-ui mode=reconcile-completion`에 exact `completion-log` 경로가 전달된 경우에만 필요한 범위를 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다. index 할당은 같은 task group의 archived sibling directory basename만 열람하고 내부 파일은 읽지 않는다. UI 완료 정합화는 전달된 exact `complete.log` 한 건만 읽고 sibling archive log를 탐색하지 않는다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, 또는 plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우에만 필요한 파일을 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-spec/` 디렉터리가 있는 프로젝트에서 현재 구현 스펙 확인, 기존 기능 변경, 완료 검토, 구현 스펙 생성/갱신 요청은 세션 1회 `agent-ops/rules/common/rules-agent-spec.md`를 읽고, `agent-spec/index.md`와 매칭되는 spec 문서만 읽는다.
|
||||
- `agent-spec/archive/**`는 일반 작업에서 읽지 않는다. 과거 스펙 확인, 복원, 비교, 특정 archive 경로 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-spec.md`의 archive 접근 규칙을 따른다.
|
||||
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||
- project skill 경로 `agent-ops/skills/project/<skill-name>/SKILL.md`를 선택했을 때 같은 이름의 `agent-ops/skills/private/<skill-name>/SKILL.md`가 있으면 private skill을 우선한다. 없으면 project skill을 사용한다.
|
||||
- project skill과 짝이 없는 private skill은 `agent-ops/rules/private/rules.md`에 명시적으로 라우팅한다. private skill 디렉터리 전체를 탐색하지 않는다.
|
||||
- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
|
|
@ -35,16 +29,12 @@
|
|||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW
|
||||
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||
- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리
|
||||
- agent-spec 생성/갱신, 현재 구현 스펙 문서화, 구현 스펙 업데이트, 스펙 동기화
|
||||
- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리
|
||||
- README 생성
|
||||
- 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- SDD 작성/갱신, SDD 필요 여부, SDD gate 확인, SDD 사용자 리뷰, SDD 잠금 해제
|
||||
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||
- 마일스톤 완료 검토 / 종료 검토 / 현재 마일스톤 닫기 / 다음 마일스톤 지정
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
|
|
|
|||
18
GEMINI.md
18
GEMINI.md
|
|
@ -3,21 +3,15 @@
|
|||
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- `agent-ops/rules/common/**`와 `agent-ops/skills/common/**`은 중앙 관리되는 공통 영역이므로 어떤 프로젝트 작업에서도 사용자가 직접 지시하지 않는 이상 절대 직접 수정하지 않는다. 프로젝트별 규칙과 스킬은 반드시 대응하는 `project/**` 영역에만 반영한다.
|
||||
- 최종 답변은 한국어로 한다.
|
||||
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우, plan 스킬이 같은 task group의 새 index를 충돌 없이 할당하는 경우, 또는 `sync-agent-ui mode=reconcile-completion`에 exact `completion-log` 경로가 전달된 경우에만 필요한 범위를 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다. index 할당은 같은 task group의 archived sibling directory basename만 열람하고 내부 파일은 읽지 않는다. UI 완료 정합화는 전달된 exact `complete.log` 한 건만 읽고 sibling archive log를 탐색하지 않는다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, 또는 plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우에만 필요한 파일을 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-spec/` 디렉터리가 있는 프로젝트에서 현재 구현 스펙 확인, 기존 기능 변경, 완료 검토, 구현 스펙 생성/갱신 요청은 세션 1회 `agent-ops/rules/common/rules-agent-spec.md`를 읽고, `agent-spec/index.md`와 매칭되는 spec 문서만 읽는다.
|
||||
- `agent-spec/archive/**`는 일반 작업에서 읽지 않는다. 과거 스펙 확인, 복원, 비교, 특정 archive 경로 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-spec.md`의 archive 접근 규칙을 따른다.
|
||||
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||
- project skill 경로 `agent-ops/skills/project/<skill-name>/SKILL.md`를 선택했을 때 같은 이름의 `agent-ops/skills/private/<skill-name>/SKILL.md`가 있으면 private skill을 우선한다. 없으면 project skill을 사용한다.
|
||||
- project skill과 짝이 없는 private skill은 `agent-ops/rules/private/rules.md`에 명시적으로 라우팅한다. private skill 디렉터리 전체를 탐색하지 않는다.
|
||||
- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
|
|
@ -35,16 +29,12 @@
|
|||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW
|
||||
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||
- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리
|
||||
- agent-spec 생성/갱신, 현재 구현 스펙 문서화, 구현 스펙 업데이트, 스펙 동기화
|
||||
- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리
|
||||
- README 생성
|
||||
- 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- SDD 작성/갱신, SDD 필요 여부, SDD gate 확인, SDD 사용자 리뷰, SDD 잠금 해제
|
||||
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||
- 마일스톤 완료 검토 / 종료 검토 / 현재 마일스톤 닫기 / 다음 마일스톤 지정
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
|
|
|
|||
12
README.md
12
README.md
|
|
@ -83,11 +83,11 @@ flutter run
|
|||
|
||||
| 표면 | 현재 compatibility baseline | workspace 기준 | 비고 |
|
||||
|------|-----------------------------|----------------|------|
|
||||
| Flutter web/code-server preview | local smoke에서 빈 포트를 고르고 `/proxy/<port>/` base href를 사용합니다. 기존 예시는 `8081`입니다. | remote local profile은 `13010`, remote dev profile은 `13011`입니다. 병렬 임시 preview는 이후 빈 포트를 고릅니다. | code-server가 proxy prefix를 유지하거나 제거해도 정적 리소스가 열려야 합니다. |
|
||||
| Flutter web/code-server preview | local smoke에서 빈 포트를 고르고 `/proxy/<port>/` base href를 사용합니다. 기존 예시는 `8081`입니다. | 안정적인 workspace preview는 `13010`부터 사용하고 병렬 preview는 `13011`, `13012`처럼 증가시킵니다. | code-server가 proxy prefix를 유지하거나 제거해도 정적 리소스가 열려야 합니다. |
|
||||
| code-server workspace entry | client mock workspace URL은 `http://localhost:8080/?folder=...`를 사용합니다. | 유지 | 이 값은 code-server entry URL 호환성이고 Flutter preview 포트가 아닙니다. |
|
||||
| Core HTTP/API | process/container 내부 기본값은 `HTTP_ADDR=:8080`, Docker `EXPOSE 8080`, local curl 예시는 `localhost:8080`입니다. | remote local profile은 `18010:8080`, remote dev profile은 `18011:8080`입니다. | 기존 `8080` local default는 migration compatibility로 유지하고, compose에서 필요하면 `NOMADCODE_CORE_HOST_PORT=8080`으로 되돌립니다. |
|
||||
| PostgreSQL | compose와 local script는 `code-server-postgres:5432` service DNS를 사용합니다. | host 노출이 꼭 필요하면 local `15410:5432`, dev `15411:5432`를 후보로 둡니다. | 기본은 service DNS이며 host publish를 추가하지 않습니다. |
|
||||
| Redis | compose와 local script는 `code-server-redis:6379` service DNS를 사용합니다. | host 노출이 꼭 필요하면 local `16310:6379`, dev `16311:6379`를 후보로 둡니다. | 기본은 service DNS이며 host publish를 추가하지 않습니다. |
|
||||
| Core HTTP/API | process/container 내부 기본값은 `HTTP_ADDR=:8080`, Docker `EXPOSE 8080`, local curl 예시는 `localhost:8080`입니다. | compose host publish 기본값은 `18010:8080`입니다. | 기존 `8080` local default는 migration compatibility로 유지하고, compose에서 필요하면 `NOMADCODE_CORE_HOST_PORT=8080`으로 되돌립니다. |
|
||||
| PostgreSQL | compose와 local script는 `code-server-postgres:5432` service DNS를 사용합니다. | host 노출이 꼭 필요하면 `15410:5432`를 후보로 둡니다. | 기본은 service DNS이며 host publish를 추가하지 않습니다. |
|
||||
| Redis | compose와 local script는 `code-server-redis:6379` service DNS를 사용합니다. | host 노출이 꼭 필요하면 `16310:6379`를 후보로 둡니다. | 기본은 service DNS이며 host publish를 추가하지 않습니다. |
|
||||
| IOP Edge / provider endpoints | `MODEL_*`, `A2A_*`, `PROTO_SOCKET_*`, `PLANE_*`, `JIRA_*`, `MATTERMOST_*` env로 분리합니다. | public port를 예약하지 않고 각 provider endpoint를 env로 주입합니다. | token, password, API key 원문은 tracked 문서에 쓰지 않고 ignored local env/secret 파일에서만 관리합니다. |
|
||||
|
||||
## 구조
|
||||
|
|
@ -138,14 +138,14 @@ IOP 경계가 걸린 작업은 같은 workspace에 sibling IOP repository가 있
|
|||
| Core | `DATABASE_URL` | 스크립트 사용 시 선택 | Core script는 local 기본값을 제공합니다. 다른 PostgreSQL을 쓰거나 binary를 직접 실행할 때 설정합니다. |
|
||||
| Core | `REDIS_URL`, `REDIS_KEY_PREFIX` | 스크립트 사용 시 선택 | worker/queue 상태에 사용할 Redis 주소와 key prefix입니다. |
|
||||
| Core | `AUTH_USERNAME`, `AUTH_PASSWORD` | 선택 | `AUTH_PASSWORD`를 설정하면 `/readyz`와 `/api/*`에 HTTP Basic Auth가 적용됩니다. |
|
||||
| Core | `NOMADCODE_CORE_HOST_PORT` | 선택 | Docker Compose host publish 포트입니다. remote local 기본값은 `18010`, remote dev 기준은 `18011`이고 container 내부는 `8080`입니다. |
|
||||
| Core | `NOMADCODE_CORE_HOST_PORT` | 선택 | Docker Compose host publish 포트입니다. 기본값은 remote/local test workspace 기준 `18010`이고 container 내부는 `8080`입니다. |
|
||||
| Core | `MODEL_BASE_URL`, `MODEL_API_KEY`, `MODEL_NAME`, `MODEL_CONTEXT_SIZE`, `MODEL_TIMEOUT_SEC` | 선택 | worker execution에서 사용할 IOP Edge OpenAI-compatible Responses endpoint 설정입니다. IOP/NomadCode 전용 실행 문맥은 요청 `metadata`로 전달하는 방향을 기준으로 합니다. |
|
||||
| Core | `A2A_EDGE_URL`, `A2A_AGENT_URL`, `A2A_TOKEN`, `A2A_TIMEOUT_SEC` | 선택 | 향후 A2A-compatible agent delegation 경로 설정입니다. 현재 기본 실행 경로는 아닙니다. |
|
||||
| Core/Client | `PROTO_SOCKET_PATH`, `PROTO_SOCKET_HEARTBEAT_INTERVAL_SEC`, `PROTO_SOCKET_HEARTBEAT_WAIT_SEC`, `PROTO_SOCKET_HOST`, `PROTO_SOCKET_PORT`, `PROTO_SOCKET_SECURE`, `PROTO_SOCKET_ENABLED`, `PROTO_SOCKET_HEARTBEAT_INTERVAL_SECONDS`, `PROTO_SOCKET_HEARTBEAT_WAIT_SECONDS` | 선택 | Core proto-socket endpoint와 Flutter client connector 설정입니다. Client는 host가 없으면 연결을 비활성화합니다. |
|
||||
| Core | `WORKFLOW_TASK_TIMEOUT_SEC` | 선택 | workflow task timeout 기본값을 조정합니다. |
|
||||
| Core | `MATTERMOST_BASE_URL`, `MATTERMOST_TOKEN`, `MATTERMOST_CHANNEL_ID` | 선택 | Mattermost task completion message 발송용 설정입니다. token 값은 문서에 기록하지 않습니다. |
|
||||
| Core | `PLANE_BASE_URL`, `PLANE_TOKEN` | 선택 | Plane work item 조회, comment, state update 연동용 설정입니다. token 값은 문서에 기록하지 않습니다. |
|
||||
| Core | `GITO_WEBHOOK_SECRET`, `GITO_REPO_ID`, `GITO_DEVELOP_REPO_PATH`, `GITO_BRANCH`, `GITO_REMOTE_NAME`, `ROADMAP_CREATION_TODO_STATE_ID`, `PLANE_TODO_STATE_ID`, `GITO_PROTO_SOCKET_URL` | 선택 | Gito signed HTTP webhook `branch.updated` consumer 설정입니다. signing secret, repo id, local develop checkout, Todo state id가 모두 있을 때 HTTP consumer가 켜집니다. Gito local `18060`은 NomadCode local `18010`으로, Gito dev `18061`은 NomadCode dev `18011`로 delivery합니다. `GITO_PROTO_SOCKET_URL`은 이전 proto-socket 호환 경로가 필요할 때만 설정합니다. `ROADMAP_CREATION_TODO_STATE_ID`가 `PLANE_TODO_STATE_ID`보다 우선합니다. |
|
||||
| Core | `GITO_WEBHOOK_SECRET`, `GITO_REPO_ID`, `GITO_DEVELOP_REPO_PATH`, `GITO_BRANCH`, `GITO_REMOTE_NAME`, `ROADMAP_CREATION_TODO_STATE_ID`, `PLANE_TODO_STATE_ID`, `GITO_PROTO_SOCKET_URL` | 선택 | Gito signed HTTP webhook `branch.updated` consumer 설정입니다. signing secret, repo id, local develop checkout, Todo state id가 모두 있을 때 HTTP consumer가 켜집니다. `GITO_PROTO_SOCKET_URL`은 이전 proto-socket 호환 경로가 필요할 때만 설정합니다. `ROADMAP_CREATION_TODO_STATE_ID`가 `PLANE_TODO_STATE_ID`보다 우선합니다. |
|
||||
| Core | `JIRA_BASE_URL`, `JIRA_EMAIL`, `JIRA_API_TOKEN` | 선택 | Jira issue 조회, comment, status transition 연동용 설정입니다. Jira Cloud Basic auth(`Email:APIToken`) 형식을 사용합니다. |
|
||||
|
||||
## 참고 문서
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
# Agent Contract Index
|
||||
|
||||
## 읽기 규칙
|
||||
|
||||
외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업에서만 이 index를 읽는다. 매칭되는 제공/소비 계약만 추가로 읽고, 계약 원문을 README, docs, rules에 복제하지 않는다.
|
||||
|
||||
## 제공 계약
|
||||
|
||||
| id | 읽는 조건 | path |
|
||||
| --- | --- | --- |
|
||||
| 없음 | 없음 | 없음 |
|
||||
|
||||
## 소비 계약
|
||||
|
||||
| id | 읽는 조건 | source |
|
||||
| --- | --- | --- |
|
||||
| `nomadcode.gito-branch-webhook-consumer.v1` | Gito `branch.updated` HTTP webhook 소비, `POST /api/integrations/gito/webhook`, Gito/NomadCode local/dev port profiles `18060/18061` and `18010/18011`, `GITO_WEBHOOK_SECRET`, `GITO_REPO_ID`, `GITO_DEVELOP_REPO_PATH` | `agent-contract/outer/gito-branch-webhook-consumer-v1.md` |
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
# Contract: nomadcode.gito-branch-webhook-consumer.v1
|
||||
|
||||
## 범위
|
||||
|
||||
이 계약은 NomadCode Core가 Gito의 signed HTTP `branch.updated` webhook delivery를 수신해 develop checkout fetch/scan 및 roadmap creation sync wakeup으로 넘기는 외부 소비 경계를 정의한다.
|
||||
|
||||
원문 제공 계약은 Gito `agent-contract/provided/gito-forgejo-branch-events-v1.md`의 `gito.forgejo-branch-events.v1`이다. 이 문서는 NomadCode가 소비자로서 강제하는 endpoint, headers, enablement, response 의미만 기록한다.
|
||||
|
||||
## 비범위
|
||||
|
||||
- Forgejo/Git provider webhook을 직접 수신하거나 정규화하는 책임은 Gito에 있다.
|
||||
- Gito event 생성, branch watch, webhook subscription 저장/전송 책임은 Gito에 있다.
|
||||
- IOP model execution port와 Responses API 동작은 NomadCode task execution dependency이며 이 webhook 소비 계약의 schema가 아니다.
|
||||
|
||||
## Endpoint
|
||||
|
||||
### `POST /api/integrations/gito/webhook`
|
||||
|
||||
Gito가 delivery하는 `branch.updated` JSON payload를 수신한다. Basic Auth를 우회하는 public callback 경계이며, request body HMAC 서명으로 검증한다.
|
||||
|
||||
Headers:
|
||||
|
||||
| Field | Required | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `X-Gito-Event` | 필수 | 고정값 `branch.updated`. 다른 값은 `400`으로 거부한다. |
|
||||
| `X-Gito-Delivery` | 필수 | stable delivery id. HTTP layer idempotency key로 사용한다. |
|
||||
| `X-Gito-Signature` | 필수 | request body에 대한 HMAC-SHA256 hex digest. `sha256=` prefix와 raw hex를 모두 허용한다. |
|
||||
|
||||
Request body minimum shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "branch.updated",
|
||||
"repo_id": "nomadcode",
|
||||
"branch": "develop",
|
||||
"before": "old-sha",
|
||||
"after": "new-sha",
|
||||
"changed_files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"change_type": "modified"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Accepted payload rules:
|
||||
|
||||
| Field | Required | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `type` | 선택 | 있으면 `branch.updated`여야 한다. |
|
||||
| `repo_id` | 필수 | `GITO_REPO_ID`와 같을 때만 처리 대상이다. |
|
||||
| `branch` | 필수 | `GITO_BRANCH` 또는 기본값 `develop`과 같을 때만 처리 대상이다. |
|
||||
| `before` | 선택 | 이전 revision SHA. 내부 bridge로 전달한다. |
|
||||
| `after` | 선택 | 새 revision SHA. 있으면 revision idempotency key에 포함한다. |
|
||||
| `changed_files` | 선택 | 있으면 object list여야 한다. wakeup 힌트이며 source-of-truth로 단정하지 않는다. |
|
||||
|
||||
Response handling:
|
||||
|
||||
| Status | Body | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `202` | `{"status":"accepted"}` | 대상 repo/branch event를 처리했다. |
|
||||
| `202` | `{"status":"ignored"}` | repo 또는 branch가 target과 달라 side effect 없이 ack했다. |
|
||||
| `202` | `{"status":"duplicate"}` | 같은 delivery id 또는 같은 `repo_id:branch:after` revision을 이미 처리했다. |
|
||||
| `400` | error object | event type, delivery id, JSON, payload shape가 잘못됐다. |
|
||||
| `401` | error object | signature가 없거나 검증에 실패했다. |
|
||||
| `413` | error object | body가 1 MiB 제한을 넘었다. |
|
||||
| `500` | error object | 내부 handler가 실패했다. 재시도 가능하다. |
|
||||
| `503` | error object | consumer enablement 입력이 준비되지 않았다. |
|
||||
|
||||
## Enablement
|
||||
|
||||
NomadCode Core는 아래 값이 모두 있을 때 Gito HTTP webhook consumer를 wiring한다.
|
||||
|
||||
| Env | Required | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `GITO_WEBHOOK_SECRET` | 필수 | `X-Gito-Signature` 검증용 signing secret. raw value는 tracked docs에 쓰지 않는다. |
|
||||
| `GITO_REPO_ID` | 필수 | target repo id. |
|
||||
| `GITO_DEVELOP_REPO_PATH` | 필수 | fetch/scan할 develop checkout path. Core container에서 접근 가능해야 한다. |
|
||||
| `ROADMAP_CREATION_TODO_STATE_ID` 또는 `PLANE_TODO_STATE_ID` | 필수 | Plane-origin roadmap creation sync projection 대상 Todo state id. |
|
||||
| `GITO_BRANCH` | 선택 | 기본값 `develop`. |
|
||||
| `GITO_REMOTE_NAME` | 선택 | 기본값 `origin`. |
|
||||
|
||||
## Environment Port Profiles
|
||||
|
||||
포트 profile은 같은 remote host에서 local용 환경과 dev용 환경을 동시에 분리 운영하기 위한 기본값이다. Endpoint path, headers, body schema는 profile과 무관하게 동일하다.
|
||||
|
||||
| Profile | NomadCode Core URL | Gito source URL | Preview | DB/cache 후보 | Subscription target |
|
||||
| --- | --- | --- | ---: | ---: | --- |
|
||||
| remote local | `http://127.0.0.1:18010` | `http://127.0.0.1:18060` | `13010` | `15410/16310` | `http://127.0.0.1:18010/api/integrations/gito/webhook` |
|
||||
| remote dev | `http://127.0.0.1:18011` | `http://127.0.0.1:18061` | `13011` | `15411/16311` | `http://127.0.0.1:18011/api/integrations/gito/webhook` |
|
||||
|
||||
NomadCode Core container 내부 listen은 `8080`을 유지하고 host publish만 `18010` 또는 `18011`로 분리한다. IOP dev model endpoint `http://toki-labs.com:18083/v1`은 NomadCode 실행 dependency이며 이 계약이 소유하는 port가 아니다.
|
||||
|
||||
## Consumer Responsibilities
|
||||
|
||||
- NomadCode는 `branch.updated`를 wakeup signal로만 받아들인다.
|
||||
- NomadCode는 Plane, agent-roadmap, 기타 source-of-truth mutation 전에 target checkout을 fetch/scan해 실제 revision 상태를 재확인한다.
|
||||
- `changed_files`는 relevance 판단 힌트이며 단독 증거가 아니다.
|
||||
- raw webhook secret, token, provider credential, private endpoint 원문은 tracked 문서나 로그에 기록하지 않는다.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `services/core/internal/http/gito_webhook.go`
|
||||
- `services/core/internal/config/config.go`
|
||||
- `services/core/internal/http/router.go`
|
||||
- `services/core/docker-compose.yml`
|
||||
- `services/core/README.md`
|
||||
- `../gito/agent-contract/provided/gito-forgejo-branch-events-v1.md`
|
||||
|
|
@ -1 +1 @@
|
|||
1.1.178
|
||||
1.1.151
|
||||
|
|
|
|||
|
|
@ -56,26 +56,6 @@ agent_ops_ensure_gitignore_task_artifact_block() {
|
|||
fi
|
||||
}
|
||||
|
||||
agent_ops_ensure_private_overrides_gitignore() {
|
||||
local file="$1"
|
||||
|
||||
touch "$file"
|
||||
if ! grep -qxF "agent-ops/rules/private/" "$file"; then
|
||||
if [[ -s "$file" ]]; then
|
||||
printf "\n" >> "$file"
|
||||
fi
|
||||
printf "%s\n" "# Agent-Ops Private Rules" >> "$file"
|
||||
printf "%s\n" "agent-ops/rules/private/" >> "$file"
|
||||
fi
|
||||
if ! grep -qxF "agent-ops/skills/private/" "$file"; then
|
||||
if [[ -s "$file" ]]; then
|
||||
printf "\n" >> "$file"
|
||||
fi
|
||||
printf "%s\n" "# Agent-Ops Private Skills" >> "$file"
|
||||
printf "%s\n" "agent-ops/skills/private/" >> "$file"
|
||||
fi
|
||||
}
|
||||
|
||||
agent_ops_ensure_ai_ignore_block() {
|
||||
local file="$1"
|
||||
local tmp
|
||||
|
|
@ -235,7 +215,6 @@ ensure_agent_ops_ai_ignore_config() {
|
|||
local target_dir="$1"
|
||||
local ignore_file
|
||||
|
||||
agent_ops_ensure_private_overrides_gitignore "$target_dir/.gitignore"
|
||||
if [[ -f "$target_dir/.agent-ops-source" ]]; then
|
||||
echo " AI ignore 보강 건너뜀: .agent-ops-source repo"
|
||||
return
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ create_project_agent_ops_dirs() {
|
|||
mkdir -p "$agent_ops_dir/rules/project/domain"
|
||||
mkdir -p "$agent_ops_dir/rules/private"
|
||||
mkdir -p "$agent_ops_dir/skills/project"
|
||||
mkdir -p "$agent_ops_dir/skills/private"
|
||||
}
|
||||
|
||||
copy_common_agent_ops() {
|
||||
|
|
@ -324,6 +323,11 @@ ensure_agent_ops_ai_ignore_config "$TARGET_DIR"
|
|||
TOUCH_GITIGNORE="$TARGET_DIR/.gitignore"
|
||||
touch "$TOUCH_GITIGNORE"
|
||||
agent_ops_ensure_gitignore_task_artifact_block "$TOUCH_GITIGNORE"
|
||||
if ! grep -q "agent-ops/rules/private/" "$TOUCH_GITIGNORE"; then
|
||||
echo "" >> "$TOUCH_GITIGNORE"
|
||||
echo "# Agent-Ops Private Rules" >> "$TOUCH_GITIGNORE"
|
||||
echo "agent-ops/rules/private/" >> "$TOUCH_GITIGNORE"
|
||||
fi
|
||||
if ! grep -qxF "# Agent-Test Local Environment" "$TOUCH_GITIGNORE"; then
|
||||
echo "" >> "$TOUCH_GITIGNORE"
|
||||
echo "# Agent-Test Local Environment" >> "$TOUCH_GITIGNORE"
|
||||
|
|
@ -336,5 +340,4 @@ ensure_agent_test_local "$TARGET_DIR"
|
|||
|
||||
echo "Successfully initialized agent-ops in $TARGET_DIR"
|
||||
echo "Note: agent-ops/rules/project and agent-ops/skills/project are initialized as empty."
|
||||
echo "Note: agent-ops/rules/private and agent-ops/skills/private are initialized and ignored by git."
|
||||
echo "Note: agent-test/local rules and baseline test profiles are initialized and ignored by git."
|
||||
|
|
|
|||
|
|
@ -62,9 +62,6 @@ sync_folder() {
|
|||
[[ -n "$exclude" && "$name" == "$exclude" ]] && continue
|
||||
rm -rf "$dst/$name"
|
||||
cp -r "$item" "$dst/"
|
||||
# 검증 실행 중 생긴 Python bytecode는 공통 산출물이 아니므로 전파하지 않는다.
|
||||
find "$dst/$name" -type f \( -name '*.pyc' -o -name '*.pyo' \) -delete
|
||||
find "$dst/$name" -depth -type d -name '__pycache__' -empty -delete
|
||||
done
|
||||
}
|
||||
|
||||
|
|
@ -73,8 +70,6 @@ sync_common() {
|
|||
sync_folder "$src/rules/common" "$dst/rules/common"
|
||||
sync_folder "$src/skills/common" "$dst/skills/common"
|
||||
sync_folder "$src/bin" "$dst/bin"
|
||||
create_project_agent_ops_dirs "$dst"
|
||||
agent_ops_ensure_private_overrides_gitignore "$(dirname "$dst")/.gitignore"
|
||||
}
|
||||
|
||||
common_differs() {
|
||||
|
|
@ -93,26 +88,11 @@ common_differs() {
|
|||
return 1
|
||||
}
|
||||
|
||||
entry_files_differ() {
|
||||
local rules_md="$1" target_root="$2"
|
||||
local f
|
||||
|
||||
[[ -f "$rules_md" ]] || return 0
|
||||
for f in "${AGENT_OPS_ENTRY_FILES[@]}"; do
|
||||
if [[ ! -f "$target_root/$f" ]] || ! cmp -s "$rules_md" "$target_root/$f"; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
create_project_agent_ops_dirs() {
|
||||
local agent_ops_dir="$1"
|
||||
mkdir -p "$agent_ops_dir/rules/project/domain"
|
||||
mkdir -p "$agent_ops_dir/rules/private"
|
||||
mkdir -p "$agent_ops_dir/skills/project"
|
||||
mkdir -p "$agent_ops_dir/skills/private"
|
||||
}
|
||||
|
||||
copy_common_scaffold() {
|
||||
|
|
@ -163,33 +143,6 @@ agent_ops_git_paths() {
|
|||
done
|
||||
}
|
||||
|
||||
stage_private_gitignore_only() {
|
||||
local file=".gitignore"
|
||||
local index_file private_file patch_file
|
||||
|
||||
if ! git ls-files --error-unmatch "$file" >/dev/null 2>&1; then
|
||||
echo -e "${RED}Error: $file 이 추적 중이 아니어서 private ignore만 분리 stage할 수 없습니다.${RESET}"
|
||||
return 1
|
||||
fi
|
||||
if ! git diff --cached --quiet -- "$file"; then
|
||||
echo -e "${RED}Error: $file 에 기존 staged 변경이 있어 private ignore만 분리 stage할 수 없습니다.${RESET}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
index_file="$(mktemp)"
|
||||
private_file="$(mktemp)"
|
||||
patch_file="$(mktemp)"
|
||||
git show ":$file" > "$index_file"
|
||||
cp "$index_file" "$private_file"
|
||||
agent_ops_ensure_private_overrides_gitignore "$private_file"
|
||||
|
||||
if ! cmp -s "$index_file" "$private_file"; then
|
||||
diff -u --label "a/$file" --label "b/$file" "$index_file" "$private_file" > "$patch_file" || true
|
||||
git apply --cached "$patch_file"
|
||||
fi
|
||||
rm -f "$index_file" "$private_file" "$patch_file"
|
||||
}
|
||||
|
||||
commit_and_push_agent_ops_scope() {
|
||||
local repo="$1" message="$2"
|
||||
local include_ai_config="${3:-1}"
|
||||
|
|
@ -202,10 +155,6 @@ commit_and_push_agent_ops_scope() {
|
|||
(
|
||||
cd "$repo"
|
||||
mapfile -t paths < <(agent_ops_git_paths "$include_ai_config")
|
||||
if [[ "$include_ai_config" == "private-gitignore" ]]; then
|
||||
stage_private_gitignore_only
|
||||
paths+=(".gitignore")
|
||||
fi
|
||||
git add -- "${paths[@]}"
|
||||
if git ls-files --error-unmatch "$AGENT_ROADMAP_CURRENT_LOCAL_PATTERN" >/dev/null 2>&1 \
|
||||
&& grep -qxF "$AGENT_ROADMAP_CURRENT_LOCAL_PATTERN" ".gitignore" 2>/dev/null; then
|
||||
|
|
@ -313,11 +262,6 @@ fi
|
|||
if [[ "$IS_FRAMEWORK" == "1" ]]; then
|
||||
SRC_VER="$(cat "$SRC_AO/.version" 2>/dev/null || echo "0.0.0")"
|
||||
echo " .agent-ops-source 감지: push 동기화에서는 버전 bump 없이 v$SRC_VER 그대로 전파"
|
||||
if entry_files_differ "$SRC_AO/rules/common/rules.md" "$PROJECT_ROOT"; then
|
||||
echo " 공통 원본 repo 진입 파일 재적용"
|
||||
apply_agent_ops_entry_files "$SRC_AO/rules/common/rules.md" "$PROJECT_ROOT"
|
||||
commit_and_push_agent_ops_scope "$PROJECT_ROOT" "sync: reapply agent-ops entry files" "0"
|
||||
fi
|
||||
if [[ -n "$TARGET_INPUT" ]]; then
|
||||
TARGET="$(resolve_target "$TARGET_INPUT")"
|
||||
if [[ -z "$TARGET" ]]; then
|
||||
|
|
@ -371,31 +315,15 @@ if ! common_differs "$SRC_AO" "$DST_AO"; then
|
|||
COMMON_CHANGED="0"
|
||||
fi
|
||||
|
||||
ENTRY_FILES_CHANGED="0"
|
||||
if entry_files_differ "$SRC_AO/rules/common/rules.md" "$PROJECT_ROOT" \
|
||||
|| entry_files_differ "$DST_AO/rules/common/rules.md" "$TARGET"; then
|
||||
ENTRY_FILES_CHANGED="1"
|
||||
fi
|
||||
|
||||
if [[ "$COMMON_CHANGED" == "1" ]] && version_gt "$DST_VER" "$SRC_VER"; then
|
||||
echo -e "${RED}⚠ 버전 충돌: 원본 repo($DST_VER) > current($SRC_VER)${RESET}"
|
||||
echo -e "${YELLOW} 먼저 sync-pull로 내려받은 뒤 재시도하세요.${RESET}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$COMMON_CHANGED" == "0" && "$ENTRY_FILES_CHANGED" == "0" ]]; then
|
||||
echo " 공통 파일/진입 파일 변경 없음: .version 차이는 무시하고 버전 갱신/커밋을 건너뜀"
|
||||
echo -e "${GREEN}✓ 완료 (공통 변경 없음)${RESET}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$COMMON_CHANGED" == "0" ]]; then
|
||||
echo " 공통 파일 변경 없음: 진입 파일만 재적용"
|
||||
apply_agent_ops_entry_files "$SRC_AO/rules/common/rules.md" "$PROJECT_ROOT"
|
||||
apply_agent_ops_entry_files "$DST_AO/rules/common/rules.md" "$TARGET"
|
||||
commit_and_push_agent_ops_scope "$TARGET" "sync: reapply agent-ops entry files" "0"
|
||||
commit_and_push_agent_ops_scope "$PROJECT_ROOT" "sync: reapply agent-ops entry files" "0"
|
||||
echo -e "${GREEN}✓ 완료 (진입 파일 재적용)${RESET}"
|
||||
echo " 공통 파일 변경 없음: .version 차이는 무시하고 버전 갱신/커밋을 건너뜀"
|
||||
echo -e "${GREEN}✓ 완료 (공통 변경 없음)${RESET}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
|
@ -403,10 +331,8 @@ NEW_VER="$(bump_version "$SRC_VER")"
|
|||
sync_common "$SRC_AO" "$DST_AO"
|
||||
echo "$NEW_VER" > "$SRC_AO/.version"
|
||||
echo "$NEW_VER" > "$DST_AO/.version"
|
||||
apply_agent_ops_entry_files "$SRC_AO/rules/common/rules.md" "$PROJECT_ROOT"
|
||||
apply_agent_ops_entry_files "$DST_AO/rules/common/rules.md" "$TARGET"
|
||||
|
||||
commit_and_push_agent_ops_scope "$TARGET" "sync: from $(basename "$PROJECT_ROOT") v$NEW_VER" "private-gitignore"
|
||||
commit_and_push_agent_ops_scope "$PROJECT_ROOT" "sync: to agentic-framework v$NEW_VER" "private-gitignore"
|
||||
commit_and_push_agent_ops_scope "$TARGET" "sync: from $(basename "$PROJECT_ROOT") v$NEW_VER" "0"
|
||||
commit_and_push_agent_ops_scope "$PROJECT_ROOT" "sync: to agentic-framework v$NEW_VER" "0"
|
||||
|
||||
echo -e "${GREEN}✓ 완료 (v$SRC_VER → v$NEW_VER)${RESET}"
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
---
|
||||
test_env: <env>
|
||||
test_env: <local|dev|qa|prod>
|
||||
last_rule_updated_at: <YYYY-MM-DD>
|
||||
---
|
||||
|
||||
# <env> 테스트 규칙
|
||||
# <test_env> 테스트 규칙
|
||||
|
||||
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
|
||||
## 공통 규칙
|
||||
|
||||
- <env> 테스트/검증은 이 파일을 기준으로 판단한다.
|
||||
- <test_env> 테스트/검증은 이 파일을 기준으로 판단한다.
|
||||
- 작업 완료 검증은 변경 범위 기준으로 선택한다.
|
||||
- 필수 검증을 실행하지 못하면 차단 사유로 보고한다.
|
||||
- 최종 보고에는 실행 명령, 결과, 생략 사유, 남은 위험을 남긴다.
|
||||
|
|
@ -18,22 +18,17 @@ last_rule_updated_at: <YYYY-MM-DD>
|
|||
## 기본 환경
|
||||
|
||||
- host:
|
||||
- repo root:
|
||||
- sync 기준:
|
||||
- port:
|
||||
- runtime:
|
||||
- package manager:
|
||||
- docker:
|
||||
- external service:
|
||||
- model endpoint:
|
||||
- credential:
|
||||
|
||||
## 프리플라이트
|
||||
|
||||
- plan 작성 시 필수 검증이 현재 checkout을 벗어나 원격 runner, 외부 서비스, Docker/code-server, emulator/device, 공유 장기 runtime을 사용하면 먼저 테스트 환경 프리플라이트를 계획에 기록한다.
|
||||
- 테스트 환경 프리플라이트에는 runner, repo root/workdir, branch/HEAD/dirty 상태, local 변경과 원격 source 동기화 여부, binary/artifact 경로와 필요한 help/version 출력, config path, runtime identity, port/process 상태, 외부 host, OS/arch 가정을 포함한다.
|
||||
- 프리플라이트에서 dirty/divergent checkout, stale artifact, 잘못된 identity, missing command, closed port, host OS 불일치, source 미동기화가 확인되면 plan은 먼저 setup/sync/rebuild 단계를 만들거나 blocker로 보고한다.
|
||||
|
||||
## 라우팅
|
||||
|
||||
- <domain 또는 project-wide> / <verification-type> / <scope 요약>: `agent-test/<env>/<test-profile>.md`
|
||||
- <domain 또는 project-wide> / <verification-type> / <scope 요약>: `agent-test/<test_env>/<test-profile>.md`
|
||||
|
||||
## 라우팅 규칙
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
- 그룹 간 연결은 사용자 명령, 런타임 이벤트, 또는 판별 가능한 파일 상태로만 한다.
|
||||
- 구현 작업 그룹은 `plan`과 `code-review`의 PLAN/CODE_REVIEW 루프를 소유한다.
|
||||
- 로드맵 그룹은 `create-roadmap`과 `update-roadmap`의 문서 작성, 의미 판단, 배치 제안, file-based fallback 갱신 흐름을 소유한다.
|
||||
- Phase/Milestone 상태 전환, 구현 잠금 동기화, archive 이동, 완료 이벤트 반영처럼 결정적으로 판별 가능한 action은 Core/MCP 또는 런타임이 있으면 그쪽 책임으로 둔다.
|
||||
- Phase/Milestone 상태 전환, 구현 잠금 동기화, archive 이동, 완료 이벤트 반영처럼 결정적으로 판별 가능한 action은 NomadCode Core 또는 런타임이 있으면 그쪽 책임으로 둔다.
|
||||
- `code-review`가 남긴 PASS 완료 이벤트를 로드맵에 반영할지, 언제 반영할지는 런타임이 판단하고 Core/MCP action이 있으면 그쪽으로, 없으면 `update-roadmap` file-based fallback 흐름으로 넘긴다.
|
||||
- cross-project 잠금이나 `.agent-roadmap-sync` 같은 workspace-level 상태는 로드맵 그룹, Core, 런타임의 공동 경계다. `plan`과 `code-review`에 의존성 동기화 규칙을 넣지 않는다.
|
||||
- 새 스킬을 만들기 전에 기존 그룹의 자연스러운 입력, 상태 전환, 후처리 지점에 넣을 수 있는지 먼저 본다. 다만 다른 그룹 경계를 침범해야 하면 런타임 이벤트로 분리한다.
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
# agent-spec 규칙
|
||||
|
||||
`agent-spec/`가 있는 프로젝트 또는 agent-spec 생성, 갱신, 마일스톤 종료 검토 요청에서 적용한다.
|
||||
|
||||
## 목적
|
||||
|
||||
`agent-spec/`는 사람과 AI agent가 현재 구현된 기능 목록, 동작 흐름, 계약 링크, 검증 방법을 함께 파악하기 위한 living spec 저장소다.
|
||||
로드맵 완료 이력, SDD 설계 논의, 계약 원문, 사람용 가이드를 대체하지 않는다.
|
||||
|
||||
## 기본 구조
|
||||
|
||||
```text
|
||||
agent-spec/
|
||||
index.md
|
||||
archive/
|
||||
<area>/
|
||||
<spec-id>.log
|
||||
<area>/
|
||||
<spec-id>.md
|
||||
```
|
||||
|
||||
- `index.md`는 현재 스펙 목록과 읽기 라우팅 source of truth다.
|
||||
- `<area>/<spec-id>.md`는 현재 구현 스펙 문서다.
|
||||
- `archive/**`는 폐기되거나 대체된 과거 스펙 스냅샷이다.
|
||||
- `<area>`와 `<spec-id>`는 소문자 영문, 숫자, 하이픈만 사용한다.
|
||||
|
||||
## Source of Truth
|
||||
|
||||
- `agent-spec/**`는 현재 구현 지도를 제공하지만 최종 truth는 코드, `agent-contract/`, 테스트, 설정 예시다.
|
||||
- API, wire protocol, runtime call, event/config schema, 프로세스 간 요청/응답 계약 원문은 `agent-contract/`에 두고 agent-spec에는 링크와 사용 맥락만 남긴다.
|
||||
- 코드 배치, 주요 구성 요소, 구현 진입점, 도메인 간 책임 경계, 유지할 패턴, 금지 사항은 domain rule에 둔다.
|
||||
- agent-spec에는 기능 이해에 필요한 최소 경계만 적고, 코딩할 때 따라야 하는 경계 규칙을 반복하지 않는다.
|
||||
- SDD는 구현 전 설계 게이트다. agent-spec은 구현 후 현재 상태를 설명한다.
|
||||
- 로드맵과 complete.log는 완료 근거와 변경 힌트로 사용한다. 현재 동작은 코드와 계약으로 재확인한다.
|
||||
- 사람용 최신 가이드는 `docs/`에 둔다. agent-spec은 기능 파악과 작업 문맥을 우선한다.
|
||||
|
||||
## Frontmatter Schema
|
||||
|
||||
- 활성 Markdown 문서는 YAML frontmatter를 둔다.
|
||||
- `spec_doc_type`은 `index`, `spec`, `archive-log` 중 하나다.
|
||||
- spec 문서는 `spec_id`, `status`, `source_evidence`를 둔다.
|
||||
- 활성 spec 문서의 `status` 값은 `구현됨`, `부분`, `가정`, `불명확` 중 하나다.
|
||||
- archive log의 `status` 값은 `폐기됨`을 사용할 수 있다.
|
||||
- `구현됨`은 코드/계약/테스트 evidence로 현재 동작이 확인된 상태다.
|
||||
- `부분`은 핵심 경로는 확인됐지만 일부 흐름, 설정, 검증, 한계가 남은 상태다.
|
||||
- `가정`은 사용자 입력 또는 제한된 evidence를 바탕으로 임시 정리한 상태다.
|
||||
- `불명확`은 코드와 계약 기준으로 현재 동작을 확정할 수 없는 상태다.
|
||||
- `폐기됨`은 활성 spec 문서에 두지 않는다.
|
||||
- `source_evidence`는 list이며 각 항목은 `type`, `path`, `notes`를 둔다.
|
||||
- `source_evidence.type`은 `code`, `contract`, `roadmap`, `sdd`, `test`, `docs`, `complete-log`, `user` 중 하나다.
|
||||
- 실제 파일 근거가 없으면 `path: null`을 사용한다. placeholder 문자열을 현재 근거처럼 남기지 않는다.
|
||||
|
||||
## 읽기 규칙
|
||||
|
||||
- 일반 작업마다 `agent-spec/`를 읽지 않는다.
|
||||
- 기존 기능의 기능 목록, 주요 흐름, 계약 링크, 현재 구현 상태가 필요한 작업에서만 세션 1회 `agent-spec/index.md`를 읽는다.
|
||||
- `index.md`에서 매칭되는 spec 문서만 읽는다.
|
||||
- 매칭 spec이 없으면 스펙이 없다고 보고하고 코드, 계약, 테스트에서 직접 확인한다. 추측으로 spec 내용을 만들지 않는다.
|
||||
- spec 문서가 코드/계약과 충돌하면 코드/계약을 우선하고 `update-spec` 필요를 보고한다.
|
||||
- 코드 배치, 구현 위치, 패턴, 금지 사항, 도메인 간 상세 책임 경계가 필요하면 프로젝트 규칙의 도메인 매핑에 따라 domain rule을 읽는다.
|
||||
- API, wire protocol, runtime call, event/config schema, 프로세스 간 요청/응답 계약에 닿으면 `agent-contract/index.md`의 규칙에 따라 매칭 계약 문서도 읽는다.
|
||||
- `agent-spec/archive/**`는 일반 작업에서 읽지 않는다.
|
||||
- 예외: 사용자가 과거 스펙 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우에만 필요한 archive 문서만 좁게 읽는다.
|
||||
|
||||
## 생성/갱신 흐름
|
||||
|
||||
- agent-spec 최초 도입, 현재 구현 스펙 신규 작성, 전체 bootstrap 작성은 `create-spec`을 사용한다.
|
||||
- 기존 spec을 코드/계약/테스트/완료 근거에 맞게 갱신하는 작업은 `update-spec`을 사용한다.
|
||||
- 마일스톤 종료 검토에서는 `complete-milestone`이 `update-spec`을 필수 gate로 실행한다.
|
||||
- `agent-spec/`가 없으면 `complete-milestone`의 spec gate는 `skipped-no-agent-spec`으로 기록할 수 있다.
|
||||
- `agent-spec/`가 있으면 `complete-milestone`은 `Spec updated` 또는 `Spec update not needed`를 완료 리뷰에 남긴 뒤에만 Milestone 완료/archive를 진행한다.
|
||||
- `Spec blocked` 또는 `create-spec needed`이면 Milestone 완료/archive를 진행하지 않는다.
|
||||
- 새 스펙 작성이나 갱신은 현재 코드/계약/테스트 evidence를 우선하고, 완료된 roadmap archive는 사용자가 요청했거나 현재 스펙의 배경 확인이 꼭 필요한 경우에만 좁게 읽는다.
|
||||
|
||||
## 문서 작성 기준
|
||||
|
||||
- 현재형으로 작성한다.
|
||||
- 과거 작업 일지, 설계 논쟁 전문, 완료된 roadmap task 전체 복사, 함수 단위 코드 설명을 넣지 않는다.
|
||||
- 스펙 본문은 기능 단위의 작동 지도여야 한다. 먼저 기능 목록을 두고, 필요한 흐름만 뒤에 보강한다.
|
||||
- 기능 목록은 `기능`과 `설명` 중심으로 작성한다. 활성 spec은 구현된 기능만 기록하므로 기능별 `상태` 칼럼을 기본으로 두지 않는다.
|
||||
- 기능별 부분 지원, 조건부 동작, 한계는 설명 또는 `한계와 주의사항`에 짧게 적는다.
|
||||
- 주요 흐름은 텍스트만 길게 나열하지 말고 Mermaid `sequenceDiagram` 또는 `flowchart`를 우선 고려한다. 단순 기능은 짧은 목록으로 충분하다.
|
||||
- 책임 경계는 기능 오해를 막는 최소 수준만 허용한다. 패키지 배치, 구현 진입점, 유지할 패턴, 금지 사항은 domain rule에 둔다.
|
||||
- `코드 진입점` 섹션은 기본 섹션으로 두지 않는다. 필요한 코드 근거는 frontmatter `source_evidence`와 domain rule로 좁힌다.
|
||||
- 계약 원문, proto field 전체 목록, config schema 원문을 복제하지 말고 `agent-contract/` 또는 코드 경로를 링크한다.
|
||||
- 불확실한 내용은 단정하지 말고 `불명확` 또는 `확인 필요`로 남긴다.
|
||||
- spec 갱신이 필요 없으면 `Spec update not needed: <사유>`를 결과 보고나 Milestone 완료 리뷰에 남긴다.
|
||||
|
||||
## 기본 섹션
|
||||
|
||||
spec 문서는 아래 섹션을 기본 순서로 작성한다. 해당 spec에 의미가 없는 섹션은 만들지 않는다.
|
||||
|
||||
1. `목적`
|
||||
2. `기능 목록`
|
||||
3. `범위`
|
||||
4. `주요 흐름`
|
||||
5. `계약`
|
||||
6. `설정/데이터/이벤트`
|
||||
7. `검증`
|
||||
8. `한계와 주의사항`
|
||||
9. `변경 기록`
|
||||
|
||||
`책임 경계`가 기능 이해에 꼭 필요하면 별도 섹션으로 짧게 둘 수 있다. 이때 domain rule의 구성 요소, 코드 배치, 금지 사항을 반복하지 않는다.
|
||||
|
||||
## 템플릿
|
||||
|
||||
- `index.md`: `agent-ops/skills/common/_templates/agent-spec/index-template.md`
|
||||
- spec 문서: `agent-ops/skills/common/_templates/agent-spec/spec-template.md`
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
# agent-ui 규칙
|
||||
|
||||
`agent-ui/`가 있는 프로젝트 또는 agent-ui 생성, 갱신, 검증 요청에서 적용한다.
|
||||
|
||||
## 목적
|
||||
|
||||
`agent-ui/`는 AI agent와 사람이 UI 의도, 화면 구조, 와이어프레임, 반복 구성요소, 코드 반영 상태를 동기화하기 위한 작업 문맥 저장소다.
|
||||
초기 기준은 ops/dev UI이며, product UI는 같은 구조 위에 brand, content, assets, tokens, motion 같은 레이어를 추가할 수 있다.
|
||||
|
||||
## 기본 구조
|
||||
|
||||
```text
|
||||
agent-ui/
|
||||
README.md
|
||||
.sync-state.json # 선택: agent-ui -> code 기준점과 plan/Milestone work 매핑
|
||||
USER_REVIEW.md # 선택: 사용자 판단이 필요한 활성 리뷰
|
||||
archive/
|
||||
user-review/
|
||||
user_review_001.log
|
||||
|
||||
definition/
|
||||
index.md
|
||||
views/
|
||||
index.md
|
||||
<view-id>/
|
||||
index.md
|
||||
components/
|
||||
index.md
|
||||
<component-id>/
|
||||
index.md
|
||||
archive/
|
||||
views/
|
||||
<view-id>/
|
||||
index.log
|
||||
components/
|
||||
<component-id>/
|
||||
index.log
|
||||
|
||||
frame/
|
||||
index.md
|
||||
views/
|
||||
<view-id>/
|
||||
index.md # visual source가 있을 때만 생성
|
||||
wire.excalidraw # 선택: 1차 visual source 후보
|
||||
```
|
||||
|
||||
## Source of Truth
|
||||
|
||||
- `agent-ui/definition/**`은 현재 UI 정의의 source of truth다.
|
||||
- `agent-ui/frame/**`은 와이어프레임과 visual source를 연결하는 보조 자료다.
|
||||
- visual source가 없는 view는 `frame/views/<view-id>/`를 만들지 않는다. view 문서의 `frame`은 `null`로 둔다.
|
||||
- `.excalidraw` 파일만으로 현재 UI 기준을 확정하지 않는다. visual source가 있으면 반드시 대응되는 `frame/views/<view-id>/index.md`가 있어야 한다.
|
||||
- `frame/views/<view-id>/index.md`는 대응되는 `definition/views/<view-id>/index.md`를 가리켜야 한다.
|
||||
- 화면 의도, 상태, 액션, 정보 우선순위는 definition에 둔다.
|
||||
- 배치, 밀도, 시각적 영역 관계는 frame에 둔다.
|
||||
- 생성된 view/component는 코드, 문서, 사용자 입력 중 어떤 근거에서 왔는지 `Source Evidence`에 남긴다.
|
||||
|
||||
## Frontmatter Schema
|
||||
|
||||
- 활성 Markdown 문서는 YAML frontmatter를 둔다.
|
||||
- `ui_doc_type`은 `readme`, `definition-index`, `views-index`, `view`, `components-index`, `component`, `frame-index`, `frame-view`, `user-review`, `archive-log` 중 하나다.
|
||||
- definition-index 문서는 `surface_type`, `source_evidence`를 둘 수 있다.
|
||||
- view 문서는 `view_id`, `status`, `frame`, `source_evidence`를 둔다.
|
||||
- component 문서는 `component_id`, `status`, `source_evidence`를 둔다.
|
||||
- view 문서의 `frame`은 frame-view 문서가 있으면 경로, 없으면 `null`로 둔다.
|
||||
- frame-view 문서는 visual source가 있을 때만 만들며 `view_id`, `definition`, `visual_source`, `regions`를 둔다.
|
||||
- definition-index/view/component의 `source_evidence`는 list이며 각 항목은 `type`, `path`, `notes`를 둔다.
|
||||
- 이 문서들의 `source_evidence.type`은 `code`, `docs`, `user` 중 하나다.
|
||||
- 실제 파일 근거가 없으면 `path: null`을 사용한다. placeholder 문자열을 현재 근거처럼 남기지 않는다.
|
||||
- view에 visual source가 없으면 view 문서의 `frame`을 `null`로 두고 frame-view 문서를 만들지 않는다.
|
||||
- frame-view를 만들 때 `visual_source`는 실제 존재하는 visual source 경로여야 한다. 없는 `wire.excalidraw`를 기본 근거처럼 쓰지 않는다.
|
||||
- view/component의 `status` 값은 `구현됨`, `계획`, `가정`, `불명확` 중 하나다. frame-view와 index 문서에는 `status`를 두지 않는다.
|
||||
- `구현됨`은 코드 반영 완료 상태다. 코드 근거가 있으면 존재하는 `code` evidence path를 함께 둔다.
|
||||
- `계획`은 정합화된 UI 정의지만 아직 코드 반영 전이거나 사용자 확인 후 재작업 대상인 상태다.
|
||||
- `가정`은 사용자 입력 또는 추정만 있고 확정 근거가 부족한 상태다.
|
||||
- `불명확`은 근거가 부족하거나 판단할 수 없는 상태다.
|
||||
- `가정`과 `불명확`은 코드 동기화 대상이 아니며, sync 전에 `agent-ui/USER_REVIEW.md`로 분리한다.
|
||||
- view는 frontmatter의 `status`, `source_evidence`, `regions`와 본문 `Status`, `Source Evidence`, `Regions`가 같은 기준을 말해야 한다.
|
||||
- component는 frontmatter의 `status`, `source_evidence`와 본문 `Status`, `Source Evidence`가 같은 기준을 말해야 한다.
|
||||
- frame-view는 frontmatter `regions`와 본문 `Required Regions`가 같은 기준을 말해야 하며, `status`나 `Source Evidence`를 요구하지 않는다.
|
||||
- frontmatter는 기계적 검증을 위한 최소 schema이고, 본문 Markdown은 사람과 agent가 읽는 설명을 유지한다.
|
||||
|
||||
## 운영 동기화 흐름
|
||||
|
||||
- 초기 생성 이후 기본 방향은 `agent-ui -> code` 단방향이다. 코드에서 agent-ui를 만드는 흐름은 `create-agent-ui` 최초 생성에만 사용한다.
|
||||
- 화면정의서, view, component, frame, wireframe을 agent로 수정하는 요청은 `update-agent-ui`로 처리한다.
|
||||
- 사용자 리뷰 결정 반영, `UIR-NNN` 해결, "화면정의서와 코드가 안 맞아" 같은 회귀 요청도 `update-agent-ui` 또는 `validate-agent-ui`로 들어와 같은 루프를 재개한다.
|
||||
- `update-agent-ui`는 agent-ui 문서 갱신을 맡는다. 코드 구현 규모 판정, plan 라우팅, roadmap/milestone 라우팅은 하지 않는다.
|
||||
- `update-agent-ui` 후에는 변경 범위에 따라 `validate-agent-ui` 필요 여부와 code sync intent 전달 여부만 판단한다. 실행한다면 `validate-agent-ui`가 항상 `sync-agent-ui`보다 먼저 실행된다.
|
||||
- `validate-agent-ui`는 agent-ui 내부 문서 그래프를 정합화한다. definition, frame, visual source, component, archive, USER_REVIEW 사이의 누락과 충돌을 같은 수준으로 맞춘다.
|
||||
- 운영 단계의 `validate-agent-ui`는 코드 후보만 보고 새 view/component를 자동 생성하지 않는다. 코드와 agent-ui가 어긋나면 agent-ui 기준 sync 대상, status 회귀, 또는 USER_REVIEW로 분리한다.
|
||||
- `sync-agent-ui`는 정합화된 agent-ui 변경분을 코드에 반영하기 전에 코드 작업 규모를 판정한다. 작은 코드 작업은 직접 반영하고, 중간 코드 작업은 `plan` 루프로, Milestone이 필요한 큰 코드 작업은 `update-roadmap`의 Milestone/Epic/Task 갱신으로 넘긴다.
|
||||
- `sync-agent-ui`의 기본 모드는 `.sync-state.json` 기준 이후 변경분만 동기화한다.
|
||||
- 사용자가 "agent-ui와 코드 전체 동기화"처럼 전체 동기화를 명시한 경우에만 현재 agent-ui 전체를 코드와 대조한다.
|
||||
- `update-agent-ui` 또는 수동 `validate-agent-ui`가 코드 반영 필요성을 판단했으면 그 판단을 다음 단계로 전달한다. 전달된 판단이 있으면 뒤 단계는 문서 정합성과 sync intent 자체를 재판단하지 않지만, `sync-agent-ui`는 실제 코드 반영 방식 판정을 수행한다.
|
||||
- 직접 sync가 검증되면 반영된 view/component의 `status`를 `구현됨`으로 바꾼다.
|
||||
- `sync-agent-ui`가 코드 작업을 `plan-required`로 라우팅한 경우에는 일반 plan/review 문서에 agent-ui 전용 completion section을 추가하지 않는다.
|
||||
- plan pair 생성 뒤 `sync-agent-ui mode=prepare-code-work`가 `.sync-state.json.pending_code_work`에 task path, status 전환 대상 view/component, validation-only frame-view, 코드 후보, 검증 기준을 기록한다.
|
||||
- pending UI task가 plan refinement 또는 sibling reindex로 경로가 바뀌면 전체 status 대상을 닫는 child 하나로 기존 entry를 rebind한다. 이전 task path를 남기거나 같은 status/frame path를 여러 child에 중복 배정하지 않는다.
|
||||
- 일반 code-review PASS와 exact `complete.log` 생성 뒤 원래 `task-path`와 `completion-log`를 전달받은 `sync-agent-ui mode=reconcile-completion`이 matching pending entry만 사용해 `update-agent-ui`와 `validate-agent-ui`를 순서대로 실행한다. view/component만 `구현됨`으로 반영하고 frame-view에는 status를 추가하지 않는다.
|
||||
- `sync-agent-ui`가 코드 작업을 `milestone-required`로 라우팅하면 exact active Milestone과 UI/code evidence를 `.sync-state.json.pending_milestone_work`에 기록한다. 일반 Milestone 문서에는 agent-ui 전용 완료 필드를 추가하지 않는다.
|
||||
- Milestone 종료 요청에서는 `complete-milestone check-only`가 종료 가능 근거를 반환한 뒤에만 `sync-agent-ui reconcile-milestone-completion`을 실행한다. 최종 검증과 code evidence가 확인된 view/component만 status를 반영하고 연결된 frame은 정합성만 검증하며, 성공 뒤에만 caller/router가 Milestone close를 계속한다.
|
||||
- 사용자 확인 또는 후속 검증에서 불일치가 발견되면 해당 항목은 `계획`으로 되돌릴 수 있다.
|
||||
- `sync-agent-ui`가 검증 실패, 환경 차단, 구현 방향 충돌, 반복 실패를 스스로 해결하지 못하면 commit/push하지 않고 `agent-ui/USER_REVIEW.md`에 게이트를 남긴다.
|
||||
- 실패한 `sync-agent-ui`가 남긴 작업트리 변경은 사용자 결정과 충돌하지 않으면 보존하고, USER_REVIEW 해결 후 같은 변경을 이어서 재검증할 수 있다.
|
||||
|
||||
## Sync State
|
||||
|
||||
- `agent-ui/.sync-state.json`은 agent-ui 변경분을 코드에 반영한 기준점이다.
|
||||
- `create-agent-ui`는 생성 결과를 최초 baseline으로 보고 `.sync-state.json`을 만든다.
|
||||
- 기존 방식으로 생성되어 `.sync-state.json`이 없는 agent-ui는 legacy 상태다. 이 경우 기본 변경분 sync를 시작하지 말고 validate 후 baseline migration으로 기준점을 먼저 만든다.
|
||||
- baseline은 `code-first`, `concept-first`, `blank` 모두에서 생성된 agent-ui 기준선을 뜻한다. `concept-first` baseline은 코드 구현 완료가 아니라 agent-ui 기준선 확정이다.
|
||||
- `last_synced_head`는 agent-ui 변경분과 코드 반영이 들어간 sync 결과 commit hash다. `.sync-state.json` 자체를 기록한 commit hash가 아니다.
|
||||
- schema version 4의 `pending_code_work`/`reconciled_code_work`는 `plan-required` task/UI 매핑과 완료 근거고, `pending_milestone_work`/`reconciled_milestone_work`는 `milestone-required` Milestone/UI 매핑과 완료 근거다. 일반 plan/review/complete.log/Milestone 문서는 이 schema를 알 필요가 없다.
|
||||
- `status_paths`에는 status schema가 있는 view/component만, `frame_paths`에는 validation-only frame-view만 기록한다.
|
||||
- pending entry의 `status_paths`와 `frame_paths`는 task와 Milestone을 통틀어 중복 소유할 수 없다. refinement/reindex에서는 helper의 `previous-task-path` rebind를 사용하고 scope/evidence 변경이 있을 때만 검증 후 replace한다.
|
||||
- direct sync의 agent-ui 경로 트리는 code/Milestone pending entry가 소유한 `status_paths`/`frame_paths`와 겹칠 수 없다. 코드 변경 전과 commit 전 확인하고, `record-sync`도 lock 안에서 동일·상위·하위 경로 겹침을 거부한다.
|
||||
- pending entry는 `prepare-code-work`만 생성/갱신하고 `reconcile-completion` 검증 통과 시에만 `reconciled_code_work`로 이동한다. 실패, ambiguous completion, evidence 부족에서는 유지한다.
|
||||
- Milestone pending entry는 `prepare-milestone-work`만 생성/갱신하고 `complete-milestone check-only`와 UI 검증이 모두 통과한 `reconcile-milestone-completion`에서만 `reconciled_milestone_work`로 이동한다. 실패하면 Milestone close를 진행하지 않는다.
|
||||
- `sync-agent-ui`의 prepare, reconcile, direct/baseline 기록은 모두 `sync-agent-ui/scripts/sync_state.py`의 agent-ui directory lock과 inspection 시점 SHA-256 검증으로 수행한다. shared state를 수동 read-modify-write하지 않는다.
|
||||
- `reconcile-completion`은 matching agent-ui/code 결과를 모두 포함하는 commit hash가 검증된 경우에만 `last_synced_head`를 갱신한다. 그렇지 않으면 기존 기준점을 보존하고 notes에 사유를 남긴다.
|
||||
- baseline 또는 sync 완료 시 commit은 두 단계로 남길 수 있다. 먼저 agent-ui/code 변경 commit을 만들고, 그 commit hash를 `.sync-state.json`에 기록한 별도 commit을 만든 뒤 push한다.
|
||||
- 변경분 판정에서는 `.sync-state.json` 자체 변경을 제외한다.
|
||||
|
||||
## 명명 규칙
|
||||
|
||||
- view id, component id, 파일명, 디렉터리명은 kebab-case를 사용한다.
|
||||
- view 기준 문서는 `definition/views/<view-id>/index.md`에 둔다.
|
||||
- component 기준 문서는 `definition/components/<component-id>/index.md`에 둔다.
|
||||
- 같은 레벨에서 `<name>.md`와 `<name>/`를 함께 두지 않는다.
|
||||
- 하위 정의가 필요하면 `<name>/index.md`와 `<name>/<child>.md`를 사용한다.
|
||||
|
||||
## ID 규칙
|
||||
|
||||
- region id는 `<view-id>.<region>` 형식을 사용한다.
|
||||
- 하위 region은 `<view-id>.<region>.<subregion>` 형식을 사용할 수 있다.
|
||||
- component id는 `definition/components/` 아래 경로에서 `index.md`를 제외한 path id로 본다. 예: `data-table`, `data-table/job-list`.
|
||||
- frame-view가 있으면 view 정의서의 region id와 frame 정의서의 region id는 동일해야 한다.
|
||||
- view에서 참조한 component id는 대응되는 component 정의 문서가 있어야 한다.
|
||||
- frame-view가 있으면 frame-view frontmatter의 `regions`와 view 본문의 region id는 같은 집합이어야 한다. 단, 차이가 제품 판단을 요구하면 USER_REVIEW로 남긴다.
|
||||
|
||||
## Archive 접근
|
||||
|
||||
- `agent-ui/definition/archive/**`는 일반 작업에서 읽지 않는다.
|
||||
- `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다.
|
||||
- 예외: 사용자가 과거 결정 확인, 복원, 비교, 특정 archive 경로 확인, 해결된 user review 확인을 요청한 경우에만 필요한 파일을 좁게 읽는다.
|
||||
- validate 작업은 archive 경로 존재 여부와 tree 대응 여부를 확인할 수 있지만, 위 예외가 없으면 archive 본문을 읽지 않는다.
|
||||
|
||||
## USER_REVIEW
|
||||
|
||||
- agent가 확정할 수 없는 UI 의도, 화면 구조, region 추가/삭제, component 신규 생성 여부, page/drawer/split 같은 UX 결정은 `agent-ui/USER_REVIEW.md`에 남긴다.
|
||||
- `agent-ui/USER_REVIEW.md`는 `update-agent-ui`, `validate-agent-ui`, `sync-agent-ui`의 통합 gate다.
|
||||
- 항목에는 어느 단계에서 막혔는지 알 수 있게 `Source Skill`, `Stage`, `Blocking Step`, `Context`, `Options`, `Needed For`를 남긴다.
|
||||
- 현재 동기화 범위에 미해결 USER_REVIEW 항목이 있으면 `sync-agent-ui`는 실행하지 않는다.
|
||||
- 해결된 user review는 `agent-ui/archive/user-review/user_review_N.log`로 이동할 수 있다.
|
||||
- USER_REVIEW 해결 요청은 관련 결정을 agent-ui 활성 문서에 반영한 뒤, 해당 항목을 archive log로 이동하고, 필요하면 `validate-agent-ui`와 `sync-agent-ui`를 순서대로 재개한다.
|
||||
- `USER_REVIEW.md`가 있으면 관련 agent-ui 갱신이나 검증 결과에 남은 review id를 보고한다.
|
||||
|
||||
## Excalidraw
|
||||
|
||||
- 1차 visual source 후보는 `wire.excalidraw`다.
|
||||
- VS Code Excalidraw extension은 초기 편집 워크플로우로 사용할 수 있다.
|
||||
- excalidraw.com import/export 워크플로우는 기본 표준으로 삼지 않는다.
|
||||
- Excalidraw self-host는 R&D 후보이며, 기본 agent-ui scaffold의 필수 조건이 아니다.
|
||||
- `.excalidraw`는 JSON으로 다룬다. 검증 시 가능하면 JSON parser로 `elements`의 text label 또는 `customData.region_id`를 확인한다.
|
||||
- visual source에 region label이 있으면 `frame-view.regions`와 `definition` region id의 집합과 비교한다.
|
||||
- visual source가 있는데 region label이 없으면 frame과 definition의 연결 근거가 부족한 상태로 본다.
|
||||
- visual source에 정의되지 않은 region label이 있거나 필수 region label이 없으면 자동으로 UI 의도를 확정하지 않고 USER_REVIEW로 남긴다.
|
||||
|
||||
## 스킬
|
||||
|
||||
- agent-ui 초기 scaffold 생성은 `create-agent-ui`를 사용한다.
|
||||
- 화면정의서, view, component, frame, wireframe 갱신은 `update-agent-ui`를 사용한다.
|
||||
- 구조와 정합성 검사, 문서 간 자동 보정, USER_REVIEW 생성은 `validate-agent-ui`를 사용한다.
|
||||
- 정합화된 agent-ui 변경분을 코드에 반영할 때는 `sync-agent-ui`를 사용한다.
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
## 구조
|
||||
|
||||
- 최상위 로드맵은 `agent-roadmap/ROADMAP.md`다.
|
||||
- Phase를 가로지르는 전역 Milestone 실행 순서는 `agent-roadmap/priority-queue.md`에 둔다.
|
||||
- 활성 Phase는 `agent-roadmap/phase/<phase-slug>/PHASE.md`에 둔다.
|
||||
- 활성 Milestone은 해당 Phase 아래 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`에 둔다.
|
||||
- `<phase-slug>`와 `<milestone-slug>`는 소문자 영문, 숫자, 하이픈만 사용한다.
|
||||
|
|
@ -16,16 +15,6 @@
|
|||
- SDD 사용자 리뷰가 필요하면 같은 디렉터리에 `USER_REVIEW.md`를 둔다. 해결된 리뷰는 `user_review_N.log`로 남긴다.
|
||||
- 완료 또는 폐기된 Milestone의 SDD는 `agent-roadmap/archive/sdd/<phase-slug>/<milestone-slug>/`로 이동한다.
|
||||
|
||||
## 링크 표기
|
||||
|
||||
- 사용자에게 보여주는 답변과 활성 로드맵 문서의 문서 포인터는 raw path만 쓰지 말고 `[표시 제목](상대경로)` Markdown 링크로 쓴다.
|
||||
- 로드맵 문서 안의 링크 target은 링크를 작성하는 Markdown 파일 위치 기준 상대경로로 쓴다. 예: `ROADMAP.md`에서는 `[PHASE.md](phase/example-phase/PHASE.md)`, Phase 문서에서는 `[Milestone](milestones/example-milestone.md)`, Milestone 문서에서는 `[ROADMAP.md](../../../ROADMAP.md)`와 `[PHASE.md](../PHASE.md)`를 쓴다.
|
||||
- 채팅 결과 보고처럼 저장 위치가 없는 출력은 repo root 기준 상대경로를 쓸 수 있다. 예: `[PHASE.md](agent-roadmap/phase/example-phase/PHASE.md)`.
|
||||
- 채팅 결과에 로드맵 문서에서 읽은 링크를 재사용할 때는 원본 Markdown 파일 위치 기준으로 target을 해석한 뒤 repo root 기준 상대경로로 다시 쓴다. 예: `agent-roadmap/current.md`에서 읽은 `(phase/foo/PHASE.md)`는 채팅 출력에서 `(agent-roadmap/phase/foo/PHASE.md)`로, `agent-roadmap/phase/foo/PHASE.md`에서 읽은 `(milestones/bar.md)`는 `(agent-roadmap/phase/foo/milestones/bar.md)`로 쓴다.
|
||||
- 실제 활성 로드맵 문서에는 `<phase-slug>`, `<milestone-slug>`, `<relative-...>` 같은 placeholder가 들어간 링크 target을 남기지 않는다. 템플릿 placeholder는 문서 생성/갱신 시 실제 파일 위치 기준 상대경로 또는 `없음`으로 치환한다.
|
||||
- 기존 raw path 또는 backtick path는 읽기 입력으로 허용한다. 갱신 범위에 포함된 활성 문서 포인터만 Markdown 링크로 보정하고, archive 스냅샷은 링크 표기만을 이유로 재포맷하지 않는다.
|
||||
- `.agent-roadmap-sync/locks.yaml`의 `locked`, `rely-on.target`, Milestone identity(`<project>:agent-roadmap/...`)처럼 machine-readable 계약 값은 raw 값을 유지할 수 있다. 사용자-facing 설명에는 가능하면 별도 Markdown 문서 링크를 함께 붙인다.
|
||||
|
||||
## Runtime Action Boundary
|
||||
|
||||
- 로드맵 스킬은 기본적으로 로드맵 문서 작성, 의미 판단, 배치 제안, file-based fallback 갱신을 담당한다.
|
||||
|
|
@ -36,26 +25,20 @@
|
|||
## 로딩
|
||||
|
||||
- 세션 최초 1회 `agent-roadmap/current.md`가 있으면 읽고 활성 Phase, 활성 Milestone의 이름, 경로, 선택 규칙만 짧게 기억한다.
|
||||
- `agent-roadmap/priority-queue.md`가 있으면 Phase를 가로지르는 다음 작업 후보 선택, 사용자가 요청한 순서 조정, archive/폐기/경로 변경/split/merge 후 큐 정리, 깨진 링크 복구가 필요할 때만 읽는다.
|
||||
- `agent-roadmap/current.md`는 브랜치별 로컬 포인터이며 git 추적 대상이 아니다.
|
||||
- `current.md`가 없고 로드맵 기반 계획 또는 갱신이 필요하면 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식으로 로컬 파일을 만들거나 `ROADMAP.md`와 활성 `PHASE.md`에서 후보를 고른다.
|
||||
- 읽기 전용 로드맵 현지점 확인에서는 `current.md`가 없어도 만들지 않고, 로컬 current 없음으로 보고한 뒤 `priority-queue.md`가 있으면 전역 실행 순서와 `ROADMAP.md`의 Phase 흐름을 보여준다.
|
||||
- 읽기 전용 로드맵 현지점 확인에서는 `current.md`가 없어도 만들지 않고, 로컬 current 없음으로 보고한 뒤 `ROADMAP.md`의 Phase 흐름만 보여준다.
|
||||
- 일반 작업에서는 `ROADMAP.md`를 읽지 않는다.
|
||||
- 일반 작업에서는 `priority-queue.md`를 읽지 않는다. 단, 구현 계획이나 다음 작업 선택처럼 Phase를 가로지르는 후보 선택이 필요하면 읽는다.
|
||||
- 일반 작업에서는 `agent-roadmap/archive/**`를 읽지 않는다.
|
||||
- 기능 추가, 구조 변경, 구현 계획 전에는 요청과 변경 파일에 맞는 활성 Phase와 활성 Milestone 문서를 읽는다.
|
||||
- 선택한 Milestone의 `구현 잠금`에 `SDD: 필요`가 있으면 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`와 같은 디렉터리의 `USER_REVIEW.md` 존재 여부를 확인한다.
|
||||
- 로드맵 현지점 확인은 로컬 `current.md`, `priority-queue.md`의 실행 순서, `ROADMAP.md`의 Phase 흐름, 활성 `PHASE.md`의 Milestone 흐름, 활성 Milestone의 제목/목표/상태를 기본으로 읽는다. `SDD: 필요`이면 SDD 본문을 읽지 말고 SDD 문서 링크와 `USER_REVIEW.md` 존재 여부만 확인한다.
|
||||
- 로드맵 현지점 확인은 로컬 `current.md`, `ROADMAP.md`의 Phase 흐름, 활성 `PHASE.md`의 Milestone 흐름, 활성 Milestone의 제목/목표/상태를 기본으로 읽고, `SDD: 필요`이면 SDD 상태/잠금/사용자 리뷰 요약도 함께 확인한다.
|
||||
- `ROADMAP.md`는 로드맵 생성/갱신, Phase 추가/삭제/전환, 전체 구조 변경, 활성 범위 밖 작업 확인 때만 읽는다.
|
||||
- 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`에 있는 archive 링크를 따라가서 필요한 archive 문서만 읽는다.
|
||||
|
||||
## Phase와 Milestone 선택
|
||||
|
||||
- `current.md`는 현재 작업 위치가 아니라 활성 Phase와 활성 Milestone 후보 목록이다.
|
||||
- `priority-queue.md`는 현재 작업 위치가 아니라 Phase를 가로지르는 실행 순서 문서다. 위에 있는 항목을 먼저 검토한다.
|
||||
- `priority-queue.md`는 순서 전용 문서이며, Milestone 제목 링크와 식별용 한 줄 설명만 둔다. 상태, 목표, 범위, 잠금, 기능, 완료 근거, 의존성은 Milestone 문서를 원본으로 삼는다.
|
||||
- `priority-queue.md`의 순서는 사용자가 순서 조정을 요청한 경우에만 바꾼다. 단, archive/폐기 제거, 경로 변경, split/merge, 실행 의미 변경, 깨진 링크 복구는 예외다.
|
||||
- `priority-queue.md` 링크가 깨졌으면 추측하지 말고 활성 Milestone 문서를 기준으로 큐를 재정렬하거나 재생성한다.
|
||||
- `current.md`는 공유 진행 상태가 아니며, 공유해야 할 상태는 `ROADMAP.md`, `PHASE.md`, Milestone 문서, `.agent-roadmap-sync/locks.yaml`에 남긴다.
|
||||
- 활성 Phase는 `agent-roadmap/phase/**/PHASE.md`만 대상으로 한다.
|
||||
- 활성 Milestone은 `agent-roadmap/phase/**/milestones/*.md`만 대상으로 한다.
|
||||
|
|
@ -84,8 +67,7 @@
|
|||
- `[검토중]` 항목은 활성 경로에 남기고 `current.md`의 활성 후보로 유지할 수 있다.
|
||||
- 검토 결과 보완이 필요하면 별도 reopen 상태를 만들지 않고 `[진행중]`으로 되돌린 뒤 `완료 리뷰` 또는 `작업 컨텍스트`에 보완 방향을 남긴다.
|
||||
- 검토 결과 보류 또는 폐기 결정이 나면 `[보류]` 또는 `[폐기]`로 전환한다.
|
||||
- `ROADMAP.md`의 Phase 흐름은 실행 순서가 아니라 도메인/책임 영역의 구조적 지도다. 상태 그룹은 완료, 검토중, 진행중, 계획, 스케치 순서를 기본으로 하되 실제 다음 작업 선택은 `priority-queue.md`를 우선한다.
|
||||
- `PHASE.md`의 Milestone 흐름은 해당 Phase 안의 상태 정리 흐름이다. Phase를 가로지르는 실행 순서로 해석하지 않는다.
|
||||
- `ROADMAP.md`의 Phase 흐름과 `PHASE.md`의 Milestone 흐름은 완료, 검토중, 진행중, 계획, 스케치 순서를 기본으로 하며 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
|
|
@ -94,13 +76,13 @@
|
|||
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 합리적으로 정할 수 있는 항목은 `결정 필요`가 아니라 `작업 컨텍스트`의 표준선이나 구현 가정으로 기록한다.
|
||||
- Milestone 전체에서 에이전트가 확정할 수 없는 결정 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
|
||||
- 선택한 Milestone에 `구현 잠금` 섹션이 없거나, 상태가 `잠금`이거나, 미완료 `결정 필요` 항목이 하나라도 있으면 코드 구현, `agent-task` 구현 계획, 세부 API/파일 구조 확정을 시작하지 않는다.
|
||||
- 잠금 상태에서 허용되는 작업은 로드맵 현지점 확인, 잠금 해소, SDD gate 처리, 범위/후속 Milestone 정리 같은 roadmap-only 갱신뿐이다. 실구현 계획 요청이면 잠금 차단으로 보고하고 `PLAN-*.md`/`CODE_REVIEW-*.md`를 만들지 않는다.
|
||||
- 잠금 상태에서 허용되는 작업은 로드맵 현지점 확인, 잠금 해소, SDD gate 처리, 범위/후속 Milestone 정리 같은 roadmap-only 갱신뿐이다. 실구현 plan 요청이면 잠금 차단으로 보고하고 `PLAN-*.md`/`CODE_REVIEW-*.md`를 만들지 않는다.
|
||||
- 남은 `결정 필요` 항목이 현재 Milestone 실구현 범위가 아니라면 먼저 `update-roadmap`으로 `범위 제외`, 후속 Milestone, 또는 `작업 컨텍스트`로 옮기고 `구현 잠금`을 `해제`한 뒤 별도 실구현 계획을 시작한다.
|
||||
- `구현 잠금`은 SDD gate를 포함할 수 있다. `SDD: 필요`이면 SDD 상태가 `[승인됨]`이고 `SDD 잠금`이 `해제`이며 SDD `USER_REVIEW.md`가 없어야 구현 잠금 해제 후보가 된다.
|
||||
- SDD 사용자 리뷰는 채팅 질문으로 직접 처리하지 않고 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md`에 남긴다. 사용자의 답변이 반영되면 `user_review_N.log`로 이동한다.
|
||||
- SDD가 필요한데 문서가 없거나 gate 정보가 부족하면 Milestone 구현 잠금을 해제하지 않는다. 실구현 계획 요청은 잠금 차단으로 보고하고, SDD 작성/확인은 `roadmap-sdd` 또는 `update-roadmap` 흐름에서 처리한다.
|
||||
- SDD가 필요한데 문서가 없거나 gate 정보가 부족하면 `plan` 스킬은 `roadmap-sdd` pre-plan gate로 SDD 작성/확인을 먼저 수행한다. 그 결과 SDD 잠금이 남거나 SDD 사용자 리뷰가 열려 있으면 구현 계획을 만들지 않는다.
|
||||
- SDD가 불필요한 Milestone은 `SDD: 불필요`과 짧은 사유를 `구현 잠금`에 남긴다.
|
||||
- 잠금 상태의 Milestone에서는 "현재 요청과 직접 관련 없음"을 이유로 실구현 계획이나 코드 구현을 진행하지 않는다. 관련 없음 판단은 잠금 해소용 roadmap-only 갱신으로 먼저 문서화한다.
|
||||
- 잠금 상태의 Milestone에서는 "현재 요청과 직접 관련 없음"을 이유로 실구현 plan이나 코드 구현을 진행하지 않는다. 관련 없음 판단은 잠금 해소용 roadmap-only 갱신으로 먼저 문서화한다.
|
||||
- 잠금 상태를 바꾸더라도 `기능` Task를 자동 완료 처리하지 않는다.
|
||||
- `[스케치]` 상태의 Milestone은 `구현 잠금`이 `해제`로 보이더라도 구현 계획과 코드 구현 대상이 아니다. 먼저 `[계획]`으로 승격해야 한다.
|
||||
|
||||
|
|
@ -136,11 +118,9 @@
|
|||
- SDD 작성, 갱신, gate 확인, 사용자 리뷰 대기, 잠금 해제는 `agent-ops/skills/common/roadmap-sdd/SKILL.md`를 따른다.
|
||||
- SDD는 cross-repo 계약, 외부 provider 쓰기, 상태 머신, idempotency/retry/identity map, API/proto/config/env/schema, field smoke, 사용자 승인 gate에 영향을 주는 Milestone에만 강제한다.
|
||||
- 작은 리팩터링, 문서 정리, 테스트 보강, 작은 UI 보강, Milestone Task의 `검증:`만으로 닫히는 작업에는 SDD를 강제하지 않는다.
|
||||
- 로드맵 갱신으로 새 Milestone을 만들거나 `[스케치]` Milestone을 `[계획]`으로 승격하면서 `SDD: 필요`로 판정하면 같은 흐름에서 SDD 파일도 만든다. 사용자가 명시적으로 SDD 생성을 뒤로 미루지 않았는데 `SDD: 필요`와 SDD 문서 링크만 있고 파일이 없는 상태로 종료하지 않는다.
|
||||
- SDD 문서는 `agent-ops/skills/common/_templates/roadmap-sdd-template.md`의 표준 섹션, 순서, 필수 표 컬럼을 유지해야 한다.
|
||||
- SDD의 `Acceptance Scenarios`는 Milestone 기능 Task id와 연결되어야 한다.
|
||||
- SDD의 `Evidence Map`은 code-review/complete.log의 `Roadmap Completion`과 최종 검증 evidence로 검증 가능해야 한다.
|
||||
- `SDD: 필요` Milestone의 구현 계획은 승인된 SDD를 입력으로 삼아 작성한다. 구현 계획은 Milestone 기능 Task만 보고 실행 항목을 만들지 않고, 연결된 Acceptance Scenario와 Evidence Map에서 구현 범위, 검증, 완료 evidence를 역산해야 한다.
|
||||
- SDD의 `Evidence Map`은 plan/code-review/complete.log의 `Spec Targets`와 `Spec Completion`으로 검증 가능해야 한다.
|
||||
- 외부 API 또는 프로젝트 간 호출 계약 원문은 `agent-contract/`에 두고 SDD에는 링크만 남긴다.
|
||||
- SDD 전체 검토를 채팅 질문으로 처리하지 않는다. 에이전트가 확정할 수 없는 source of truth, 상태 전이, 책임 경계, 권한, 비용, 데이터 보존, 실패 처리만 `USER_REVIEW.md`로 분리한다.
|
||||
|
||||
|
|
@ -168,10 +148,10 @@
|
|||
- 런타임은 파일 내부가 아니라 task group 이름만으로 Milestone 기반 작업 여부를 판별한다.
|
||||
- `code-review`에서 `m-<milestone-slug>` 작업이 PASS되면 roadmap을 직접 수정하거나 `update-roadmap`을 직접 호출하지 않는다.
|
||||
- 런타임은 PASS 완료 이벤트의 task group에서 `m-<milestone-slug>`를 판별하고, 상태 체크 후 Core/MCP action으로 Milestone 업데이트를 호출한다. Core/MCP action이 없으면 `update-roadmap` file-based fallback 흐름을 호출한다. 단, Milestone 기능 Task 체크는 `complete.log`에 `Roadmap Completion` 섹션과 명시 Task id가 있을 때만 수행하고, 섹션이 없으면 no-op으로 둔다.
|
||||
- SDD 대상 Milestone은 런타임 완료 이벤트의 `complete.log`에 있는 `Roadmap Completion`과 최종 검증 evidence가 SDD `Evidence Map`을 충족해야 roadmap Task 체크 후보가 된다. 단, 사용자가 명시적으로 evidence를 전달한 수동 `update-roadmap` 갱신에서는 Evidence Map 충족 근거를 보조 근거로 사용할 수 있다.
|
||||
- SDD 대상 Milestone은 런타임 완료 이벤트의 `complete.log`에 `Spec Completion`이 있어야 roadmap Task 체크 후보가 된다. SDD `Evidence Map`은 `Spec Completion` 검증 기준이며 단독 대체 근거가 아니다. 단, 사용자가 명시적으로 evidence를 전달한 수동 `update-roadmap` 갱신에서는 Evidence Map 충족 근거를 보조 근거로 사용할 수 있다.
|
||||
- 런타임 완료 이벤트가 최종 archive 경로만 갖고 있으면 `agent-task/archive/YYYY/MM/m-<milestone-slug>/...`를 `agent-task/m-<milestone-slug>/...` 형태의 `origin-task`로 정규화해 전달한다.
|
||||
- 런타임 호출에서 매칭되는 활성 Milestone이 없거나 둘 이상이면 추정하지 말고 수동 target 선택이 필요하다고 보고한다.
|
||||
- `WARN` 또는 `FAIL`은 Milestone 완료 업데이트를 하지 않는다. 일반적으로 같은 `m-<milestone-slug>` task group에서 후속 계획/리뷰를 이어가지만, code-review의 user-review gate가 트리거되면 연결된 Milestone 잠금 결정을 `USER_REVIEW.md`에 남긴다.
|
||||
- `WARN` 또는 `FAIL`은 Milestone 완료 업데이트를 하지 않는다. 일반적으로 같은 `m-<milestone-slug>` task group에서 follow-up plan/review를 이어가지만, code-review의 user-review gate가 트리거되면 연결된 SDD/Milestone 잠금 결정을 `USER_REVIEW.md`에 남긴다.
|
||||
- `[스케치]` Milestone은 Milestone 기반 `agent-task` 생성 대상이 아니다. 런타임이나 plan 스킬은 이를 구현 작업으로 라우팅하지 않고 `[계획]` 승격 필요를 보고한다.
|
||||
|
||||
## 완료 리뷰
|
||||
|
|
@ -200,6 +180,5 @@
|
|||
- Milestone 아카이브 전에는 이동 전 활성 경로 identity로 `.agent-roadmap-sync/locks.yaml`을 확인한다. 해당 identity가 `rely-on.target`이면 `[완료]` 상태에서 `enable`로 동기화하고, 해당 identity가 `locked`이면 의존 조건 충족 여부를 보고하며, 어느 쪽에도 없으면 `관련 lock 없음`으로 보고한다.
|
||||
- `구현 잠금`이 남아 있는 Milestone은 `[완료]` 전환이나 완료 archive 대상으로 삼지 않는다. 명시적인 폐기 근거가 있는 `[폐기]` archive는 허용한다.
|
||||
- 아카이빙할 때는 활성 `ROADMAP.md` 또는 활성 `PHASE.md`에 archive 문서 링크와 짧은 요약만 남긴다.
|
||||
- 아카이빙할 때 `priority-queue.md`가 있으면 이동 전 활성 Milestone 경로 항목을 제거한다. archive 경로로 바꿔 남기지 않는다.
|
||||
- 아카이브된 Phase/Milestone은 로컬 `current.md`에 남기지 않고, 일반 Phase/Milestone 선택이나 위치 분석의 후보로 삼지 않는다.
|
||||
- 아카이브 문서는 과거 기록 스냅샷으로 보고, 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.
|
||||
|
|
|
|||
|
|
@ -3,21 +3,15 @@
|
|||
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- `agent-ops/rules/common/**`와 `agent-ops/skills/common/**`은 중앙 관리되는 공통 영역이므로 어떤 프로젝트 작업에서도 사용자가 직접 지시하지 않는 이상 절대 직접 수정하지 않는다. 프로젝트별 규칙과 스킬은 반드시 대응하는 `project/**` 영역에만 반영한다.
|
||||
- 최종 답변은 한국어로 한다.
|
||||
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우, plan 스킬이 같은 task group의 새 index를 충돌 없이 할당하는 경우, 또는 `sync-agent-ui mode=reconcile-completion`에 exact `completion-log` 경로가 전달된 경우에만 필요한 범위를 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다. index 할당은 같은 task group의 archived sibling directory basename만 열람하고 내부 파일은 읽지 않는다. UI 완료 정합화는 전달된 exact `complete.log` 한 건만 읽고 sibling archive log를 탐색하지 않는다.
|
||||
- `agent-task/archive/**`는 일반 작업에서 읽지 않는다. 예외: 사용자가 과거 작업 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우, active `PLAN-*.md` / `CODE_REVIEW-*.md` / `USER_REVIEW.md`가 특정 archive evidence 경로를 명시한 경우, 또는 plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인하는 경우에만 필요한 파일을 좁게 읽는다. split 의존성 확인은 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다.
|
||||
- `agent-spec/` 디렉터리가 있는 프로젝트에서 현재 구현 스펙 확인, 기존 기능 변경, 완료 검토, 구현 스펙 생성/갱신 요청은 세션 1회 `agent-ops/rules/common/rules-agent-spec.md`를 읽고, `agent-spec/index.md`와 매칭되는 spec 문서만 읽는다.
|
||||
- `agent-spec/archive/**`는 일반 작업에서 읽지 않는다. 과거 스펙 확인, 복원, 비교, 특정 archive 경로 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-spec.md`의 archive 접근 규칙을 따른다.
|
||||
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||
- project skill 경로 `agent-ops/skills/project/<skill-name>/SKILL.md`를 선택했을 때 같은 이름의 `agent-ops/skills/private/<skill-name>/SKILL.md`가 있으면 private skill을 우선한다. 없으면 project skill을 사용한다.
|
||||
- project skill과 짝이 없는 private skill은 `agent-ops/rules/private/rules.md`에 명시적으로 라우팅한다. private skill 디렉터리 전체를 탐색하지 않는다.
|
||||
- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
|
|
@ -35,16 +29,12 @@
|
|||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW
|
||||
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||
- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리
|
||||
- agent-spec 생성/갱신, 현재 구현 스펙 문서화, 구현 스펙 업데이트, 스펙 동기화
|
||||
- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리
|
||||
- README 생성
|
||||
- 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- SDD 작성/갱신, SDD 필요 여부, SDD gate 확인, SDD 사용자 리뷰, SDD 잠금 해제
|
||||
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||
- 마일스톤 완료 검토 / 종료 검토 / 현재 마일스톤 닫기 / 다음 마일스톤 지정
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
domain: contracts
|
||||
last_rule_review_commit: a95fc27151e5e0750c1e25df3f72ad10f2d89506
|
||||
last_rule_updated_at: 2026-06-24
|
||||
last_rule_review_commit: 03187a4be3d9864419221d14bb44b8bc6645e6f1
|
||||
last_rule_updated_at: 2026-05-31
|
||||
---
|
||||
|
||||
# contracts
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
NomadCode 런타임 사이의 공유 계약 도메인이다. API schema, event schema, roadmap/work item sync 후보, generated client boundary, compatibility note를 관리한다.
|
||||
NomadCode 런타임 사이의 공유 계약 도메인이다. API schema, event schema, generated client boundary, compatibility note를 관리한다.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ NomadCode 런타임 사이의 공유 계약 도메인이다. API schema, event s
|
|||
## 주요 구성 요소
|
||||
|
||||
- `packages/contracts/README.md` — 현재 contracts 도메인의 역할과 사용 방향.
|
||||
- `packages/contracts/notes/flutter-core-api-candidates.md` — Flutter/Core REST compatibility map, proto-socket semantic envelope, task channel, Gito branch event consumer, roadmap/work item sync, roadmap operations control plane, workspace metadata, client integration 설정 후보.
|
||||
- `packages/contracts/notes/flutter-core-api-candidates.md` — Flutter/Core REST compatibility map, proto-socket semantic envelope, task channel, diagnostics, workspace metadata, client integration 설정 후보.
|
||||
|
||||
## 유지할 패턴
|
||||
|
||||
|
|
@ -34,7 +34,6 @@ NomadCode 런타임 사이의 공유 계약 도메인이다. API schema, event s
|
|||
- generated client가 생기면 생성 명령과 source schema를 문서화한다.
|
||||
- 내부 런타임 통신은 `proto-socket` channel/action을 우선 기준으로 삼고, REST/HTTP 유지나 신규 추가는 health/readiness, 외부 provider compatibility, smoke/curl, public callback, 단순 정적 조회 같은 예외 사유를 기록한다.
|
||||
- source schema가 아직 없는 계약은 compatibility note로 표시하고, 실제 schema/generator 도입 전까지 단일 source-of-truth인 것처럼 다루지 않는다.
|
||||
- Gito branch event와 roadmap/work item sync 후보는 외부 원문 계약과 Core 구현 경계를 함께 링크하고, source-of-truth branch/revision과 wakeup hint의 차이를 명시한다.
|
||||
|
||||
## 다른 도메인과의 경계
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
---
|
||||
domain: core
|
||||
last_rule_review_commit: a95fc27151e5e0750c1e25df3f72ad10f2d89506
|
||||
last_rule_updated_at: 2026-06-24
|
||||
last_rule_review_commit: 03187a4be3d9864419221d14bb44b8bc6645e6f1
|
||||
last_rule_updated_at: 2026-06-01
|
||||
---
|
||||
|
||||
# core
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
NomadCode의 백엔드 오케스트레이션 도메인이다. workflow, scheduling, persistence, HTTP/proto-socket API, work item intake, authoring bridge, project/roadmap sync, 외부 서비스 adapter를 통해 AI 작업 실행 상태와 자동화 흐름을 관리한다.
|
||||
NomadCode의 백엔드 오케스트레이션 도메인이다. workflow, scheduling, persistence, HTTP/proto-socket API, work item intake, 외부 서비스 adapter를 통해 AI 작업 실행 상태와 자동화 흐름을 관리한다.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
- `services/core/cmd/` — 서버와 Plane smoke 실행 entrypoint.
|
||||
- `services/core/internal/agent/` — agent 모델과 실행 단위.
|
||||
- `services/core/internal/authoring/` — Plane-origin workspace authoring 입력, 결과 판정, identity write 경계.
|
||||
- `services/core/internal/config/` — 환경 변수 기반 core 설정 로딩.
|
||||
- `services/core/internal/model/` — 모델 호출 추상 인터페이스와 입출력 타입.
|
||||
- `services/core/internal/workflow/` — workflow 모델과 서비스.
|
||||
|
|
@ -22,11 +21,6 @@ NomadCode의 백엔드 오케스트레이션 도메인이다. workflow, scheduli
|
|||
- `services/core/internal/notification/` — task notification 모델과 발행 서비스.
|
||||
- `services/core/internal/http/` — HTTP router, handlers, middleware.
|
||||
- `services/core/internal/protosocket/` — proto-socket envelope, dispatcher, server, task channel, event broadcaster.
|
||||
- `services/core/internal/gitoevents/` — Gito branch event 계약 decode와 subscribe envelope.
|
||||
- `services/core/internal/gitosync/` — Gito develop branch event를 roadmap sync enqueue로 연결하는 bridge/runner/scanner.
|
||||
- `services/core/internal/projectsync/` — provider project sync 설정, checkout/provision, workspace slot 경계.
|
||||
- `services/core/internal/roadmapsync/` — roadmap/work item identity, develop match, Plane projection, retry/reconcile 결정.
|
||||
- `services/core/internal/roadmapsyncpipeline/` — roadmap creation sync side-effect orchestration과 step ledger 호출.
|
||||
- `services/core/internal/workitem/` — provider-neutral work item reference, capability, projection, task input mapping.
|
||||
- `services/core/internal/workitempipeline/` — 외부 work item을 core task로 변환하는 pipeline service.
|
||||
- `services/core/internal/db/` — SQLC 생성 코드, DB pool, persistence 모델.
|
||||
|
|
@ -53,42 +47,19 @@ NomadCode의 백엔드 오케스트레이션 도메인이다. workflow, scheduli
|
|||
- `internal/model/model.go` — 모델 client interface와 generation DTO.
|
||||
- `internal/scheduler/river.go` — River scheduler 연결.
|
||||
- `internal/scheduler/jobs.go` — background job 정의.
|
||||
- `internal/scheduler/roadmap_sync_jobs.go` — Plane-origin Milestone creation sync River job.
|
||||
- `internal/scheduler/slot_finalizer.go` — authoring task 종료 시 workspace slot 상태 반영.
|
||||
- `internal/scheduler/stale.go` — authoring in-progress 관측 시각 stale 판정.
|
||||
- `internal/notification/service.go` — task 완료 notification 발행.
|
||||
- `internal/protosocket/server.go` — proto-socket WebSocket server, heartbeat, diagnostics logging, broadcast.
|
||||
- `internal/protosocket/dispatcher.go` — channel/action dispatch registry.
|
||||
- `internal/protosocket/envelope.go` — `nomadcode.proto-socket.v1` semantic envelope 변환.
|
||||
- `internal/protosocket/tasks.go` — `task.create/list/get/enqueue` proto-socket channel handlers.
|
||||
- `internal/protosocket/events.go` — notification event를 `task.status.changed` event로 투영.
|
||||
- `internal/gitoevents/events.go` — Gito `branch.updated` payload decode와 roadmap milestone path hint 판정.
|
||||
- `internal/gitoevents/client.go` — Gito proto-socket subscription client.
|
||||
- `internal/gitosync/bridge.go` — verified develop scan 결과를 roadmap creation sync enqueue로 변환.
|
||||
- `internal/gitosync/scanner.go` — develop branch revision에서 active Milestone 문서와 provider identity를 scan.
|
||||
- `internal/gitosync/runner.go` — Gito branch event stream을 bridge로 전달하는 runner.
|
||||
- `internal/authoring/request.go` — Plane-origin authoring task의 model input/push input 구성.
|
||||
- `internal/authoring/identity_write.go` — authoring 결과의 provider identity를 Milestone 문서에 기록하는 경계.
|
||||
- `internal/authoring/result.go` — authoring 결과와 workspace slot terminal state 판정.
|
||||
- `internal/adapters/openai/client.go` — OpenAI integration.
|
||||
- `internal/adapters/a2a/client.go` — A2A integration.
|
||||
- `internal/adapters/mattermost/client.go` — Mattermost task notification integration.
|
||||
- `internal/adapters/plane/client.go` — Plane work item 조회, comment 생성, state update integration.
|
||||
- `internal/adapters/jira/client.go` — Jira issue lookup/comment/status projection integration.
|
||||
- `internal/projectsync/config.go` — provider project target, branch workspace, slot path/state 모델.
|
||||
- `internal/projectsync/provision.go` — project workspace와 branch workspace provision.
|
||||
- `internal/projectsync/checkout.go` — work item 실행용 workspace slot checkout.
|
||||
- `internal/roadmapsync/identity.go` — provider-neutral Milestone/Task identity와 revision 모델.
|
||||
- `internal/roadmapsync/develop_match.go` — develop scan 결과와 expected identity match gate.
|
||||
- `internal/roadmapsync/plane_projection.go` — Plane Todo projection formatting.
|
||||
- `internal/roadmapsync/retry.go` — sync step ledger 기반 retry/reconcile 결정.
|
||||
- `internal/roadmapsyncpipeline/service.go` — Plane-origin Milestone creation sync 실행 순서와 side-effect 기록.
|
||||
- `internal/workitem/provider.go` — provider-neutral work item abstraction과 task input mapping.
|
||||
- `internal/workitempipeline/service.go` — work item reader와 workflow task creator 연결.
|
||||
- `internal/db/tasks.sql.go` — SQLC generated query boundary.
|
||||
- `internal/storage/project_sync_settings.go` — project sync 설정 persistence.
|
||||
- `internal/storage/workspace_slots.go` — workspace slot persistence.
|
||||
- `internal/storage/roadmap_sync_identities.go`, `internal/storage/roadmap_sync_steps.go` — roadmap sync identity/step ledger persistence.
|
||||
|
||||
## Plane dev 작업 메모
|
||||
|
||||
|
|
@ -116,10 +87,6 @@ NomadCode의 백엔드 오케스트레이션 도메인이다. workflow, scheduli
|
|||
- 외부 서비스 호출은 `internal/adapters/<provider>` 아래에 격리한다.
|
||||
- provider-neutral work item 계약은 `internal/workitem`에 두고, Plane/Jira 같은 provider별 HTTP/DTO 세부는 adapter 아래에 둔다.
|
||||
- work item을 core task로 만드는 흐름은 `internal/workitempipeline`에서 조립하고, workflow service에 provider별 DTO를 직접 넣지 않는다.
|
||||
- project/workspace checkout 규칙과 slot 상태 전이는 `internal/projectsync`와 storage/scheduler 경계를 통해 처리한다.
|
||||
- Plane-origin authoring task는 provider identity와 checkout metadata를 보존하고, identity 누락은 task id fallback으로 숨기지 않는다.
|
||||
- Gito branch event의 `changed_files`는 wakeup hint로만 사용하고, 실제 sync 여부는 develop revision scan과 `roadmapsync` identity match로 판정한다.
|
||||
- roadmap/work item sync side effect는 identity/step ledger를 기준으로 idempotent하게 재개하고, provider 호출 성공 직후 step을 기록한다.
|
||||
- 신규 내부 런타임 통신은 `proto-socket` channel/action을 우선 검토하고, REST/HTTP 예외는 health/readiness, smoke/curl, 외부 provider 호환 API처럼 사유가 분명할 때 contracts 또는 domain rule에 남긴다.
|
||||
- proto-socket envelope diagnostics에는 connection id, protocol version, channel/action, error code, timestamp 같은 운영 필드만 남기고 secret이나 payload 원문을 로그에 싣지 않는다.
|
||||
- 환경 변수 기본값과 alias는 `internal/config`에서 관리하고 README의 실행 예시와 어긋나지 않게 유지한다.
|
||||
|
|
@ -133,14 +100,12 @@ NomadCode의 백엔드 오케스트레이션 도메인이다. workflow, scheduli
|
|||
- **contracts**: API, proto-socket envelope/channel/action, diagnostics 의미가 클라이언트와 공유되면 contracts에 먼저 표현하거나 compatibility note로 문서화한다.
|
||||
- **mobile**: mobile은 public API, proto-socket semantic envelope, notification/auth 계약만 의존하며 core 내부 패키지를 직접 참조하지 않는다.
|
||||
- **web**: [Legacy/Retired] React web 도메인은 완전히 제거되었습니다.
|
||||
- **workspace-ops**: root helper, agent-roadmap 문서 형식, agent-ops 규칙은 workspace-ops가 소유한다. core-local bin 변경만 core 소유이며, core는 sync/action 경계에서 필요한 roadmap 문서를 scan하거나 provider projection에 사용한다.
|
||||
- **workspace-ops**: root helper 변경은 workspace-ops 소유이고, core-local bin 변경만 core 소유다.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- `apps/**`의 UI 상태나 라우팅을 core 변경에 끼워 넣지 않는다.
|
||||
- 외부 provider별 세부 구현을 workflow/service 레이어에 직접 흘리지 않는다.
|
||||
- proto-socket payload를 임의 map indexing으로 여기저기 해석하지 말고 envelope/channel boundary에서 typed DTO로 변환한다.
|
||||
- Gito `changed_files`만 믿고 roadmap/provider mutation을 실행하지 않는다.
|
||||
- roadmap sync projection에서 identity/step ledger를 우회하거나 provider side effect를 중복 실행하지 않는다.
|
||||
- SQLC 생성 파일만 수동 수정하지 않는다.
|
||||
- 테스트 없이 scheduler, persistence, adapter behavior를 크게 바꾸지 않는다.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
domain: mobile
|
||||
last_rule_review_commit: a95fc27151e5e0750c1e25df3f72ad10f2d89506
|
||||
last_rule_updated_at: 2026-06-24
|
||||
last_rule_review_commit: 03187a4be3d9864419221d14bb44b8bc6645e6f1
|
||||
last_rule_updated_at: 2026-05-31
|
||||
---
|
||||
|
||||
# mobile
|
||||
|
|
@ -15,7 +15,6 @@ NomadCode의 Flutter-first 제품 UI 도메인이다. 모바일/데스크톱/선
|
|||
- `apps/client/lib/` — Flutter application code.
|
||||
- `apps/client/lib/src/app/` — app host, bootstrap, workbench shell.
|
||||
- `apps/client/lib/src/features/` — product feature UI and local feature state.
|
||||
- `apps/client/lib/src/features/workspaces/domain/` — workspace/project/task UI model.
|
||||
- `apps/client/lib/src/integrations/` — Mattermost, proto-socket, workspace launcher 같은 외부 경계 adapter.
|
||||
- `apps/client/test/` — Flutter widget/service tests.
|
||||
- `apps/client/assets/` — Flutter asset bundle과 ignored local smoke credential 위치.
|
||||
|
|
@ -34,19 +33,15 @@ NomadCode의 Flutter-first 제품 UI 도메인이다. 모바일/데스크톱/선
|
|||
- `lib/main.dart` — Flutter app entrypoint.
|
||||
- `lib/src/app/nomadcode_client_app.dart` — MaterialApp host와 integration lifecycle wiring.
|
||||
- `lib/src/app/nomadcode_workbench_shell.dart` — top titlebar, 우측 activity rail, 중앙 content 전환, 우측 Agent dock panel, 하단 IOP slot을 가진 workbench shell.
|
||||
- `lib/src/features/workspaces/domain/project_workspace.dart` — workspace/project 목록 UI 모델과 mock workspace seed.
|
||||
- `lib/src/features/workspaces/domain/workspace_task.dart` — Core `task` channel 응답을 파싱하는 client-side task 모델.
|
||||
- `lib/src/features/workspaces/presentation/workspace_home_page.dart` — workspace project/task UI. workbench mount 시 `showAppBar: false`로 내부 app bar를 숨길 수 있다.
|
||||
- `lib/src/integrations/mattermost/mattermost_auth_service.dart` — Mattermost auth flow.
|
||||
- `lib/src/integrations/mattermost/mattermost_push_client.dart` — Mattermost-compatible push interface.
|
||||
- `lib/src/integrations/mattermost/mattermost_push_plugin_client.dart` — production-only `NexoMessagingPlugin.instance` adapter.
|
||||
- `lib/src/integrations/mattermost/mattermost_push_host_integration.dart` — Mattermost push host initialization, auth handoff, notification navigation.
|
||||
- `lib/src/integrations/proto_socket/proto_socket_client.dart` — local `proto_socket` package 기반 real connector/transport.
|
||||
- `lib/src/integrations/proto_socket/proto_socket_endpoint_config.dart` — `PROTO_SOCKET_*` env/dart-define 기반 endpoint value object.
|
||||
- `lib/src/integrations/proto_socket/proto_socket_envelope.dart` — core와 공유하는 semantic envelope DTO.
|
||||
- `lib/src/integrations/proto_socket/proto_socket_lifecycle.dart` — proto-socket connection lifecycle facade.
|
||||
- `lib/src/integrations/proto_socket/proto_socket_task_service.dart` — workspace task loading over proto-socket transport.
|
||||
- `lib/src/integrations/proto_socket/proto_socket_branch_event_service.dart` — Gito `branch.updated` event subscribe/wakeup service.
|
||||
- `lib/src/integrations/workspace/workspace_launcher.dart` — workspace/code-server launch boundary.
|
||||
- `android/app/src/main/java/com/tokilabs/mattermost/MainActivity.kt` — Android Flutter activity host.
|
||||
- `test/widget_test.dart` — baseline widget test.
|
||||
|
|
@ -62,8 +57,6 @@ NomadCode의 Flutter-first 제품 UI 도메인이다. 모바일/데스크톱/선
|
|||
- IOP entry는 우측 rail 하단에 둔다. IOP-specific 운영 화면은 `iopContent` 같은 선택적 widget slot으로 mount하고, IOP package가 없는 기본 빌드에서는 placeholder로 유지한다.
|
||||
- 공통 agent interaction UI는 sibling `agent_shell` package를 사용한다. NomadCode-specific workflow/web context capability는 NomadCode mobile domain이 소유하고, IOP-specific 운영 화면은 향후 IOP-owned package/widget을 선택적으로 mount한다.
|
||||
- proto-socket 연결은 `ProtoSocketLifecycle`과 connector/transport interface 뒤에 두고, bootstrap은 안전한 no-op 기본값으로 시작한다.
|
||||
- `PROTO_SOCKET_HOST`가 없으면 endpoint config는 null/disabled로 두고, bootstrap에서 네트워크 연결을 강제하지 않는다.
|
||||
- Gito `branch.updated` event는 UI wakeup hint로만 소비하고, 클라이언트가 source-of-truth 상태나 provider/roadmap mutation을 직접 수행하지 않는다.
|
||||
- production code에서 `NexoMessagingPlugin.instance` 직접 참조는 `MattermostPushPluginClient`에만 둔다.
|
||||
- `assets/mattermost_credentials.json`은 local smoke credential로만 쓰며 ignored file 상태를 유지한다.
|
||||
- `flutter test`를 기본 검증으로 사용한다.
|
||||
|
|
@ -72,7 +65,7 @@ NomadCode의 Flutter-first 제품 UI 도메인이다. 모바일/데스크톱/선
|
|||
## 다른 도메인과의 경계
|
||||
|
||||
- **core**: mobile은 core API/notification 계약에 의존하되 core 내부 구현을 알지 않는다.
|
||||
- **contracts**: mobile이 사용하는 API/event/proto-socket envelope shape와 Gito branch event 소비 의미는 contracts 후보로 올린다.
|
||||
- **contracts**: mobile이 사용하는 API/event/proto-socket envelope shape는 contracts 후보로 올린다.
|
||||
- **agent-shell**: common chat/agent shell widget과 message model만 제공하는 sibling package다. Product routing, workbench section, web context 조작, IOP mount 결정은 mobile domain에서 조립한다.
|
||||
- **IOP**: IOP는 runtime/operation/agent capability와 IOP console widget/package 경계를 소유한다. mobile은 IOP 기능을 직접 복제하지 않고 선택적 section으로 mount한다.
|
||||
- **web**: [Legacy/Retired] React web 도메인은 완전히 제거되었습니다.
|
||||
|
|
@ -85,7 +78,6 @@ NomadCode의 Flutter-first 제품 UI 도메인이다. 모바일/데스크톱/선
|
|||
- Firebase 초기화/handler 변경을 테스트나 수동 검증 메모 없이 마무리하지 않는다.
|
||||
- IOP client UI나 runtime/operation semantics를 NomadCode mobile code에 직접 복제하지 않는다.
|
||||
- `agent_shell` package에 NomadCode 전용 workflow/web context/IOP product logic을 밀어 넣지 않는다.
|
||||
- branch event 수신만으로 roadmap/provider 상태를 변경하지 않는다.
|
||||
- `nexo_messaging` plugin singleton을 host UI나 auth service에서 직접 호출하지 않는다.
|
||||
- local smoke credential 파일을 tracked asset으로 커밋하지 않는다.
|
||||
- generated/platform build output을 의도 없이 커밋하지 않는다.
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
domain: workspace-ops
|
||||
last_rule_review_commit: a95fc27151e5e0750c1e25df3f72ad10f2d89506
|
||||
last_rule_updated_at: 2026-06-24
|
||||
last_rule_review_commit: 03187a4be3d9864419221d14bb44b8bc6645e6f1
|
||||
last_rule_updated_at: 2026-05-31
|
||||
---
|
||||
|
||||
# workspace-ops
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
NomadCode 원레포 운영 도메인이다. 루트 helper, 문서, ignore/secret 정책, 원레포 구조, agent/tooling entry 파일, agent-ops project rules와 roadmap을 관리한다.
|
||||
NomadCode 원레포 운영 도메인이다. 루트 helper, 문서, ignore 정책, 원레포 구조, agent entry 파일, agent-ops project rules와 roadmap을 관리한다.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
|
|
@ -16,10 +16,8 @@ NomadCode 원레포 운영 도메인이다. 루트 helper, 문서, ignore/secret
|
|||
- `docs/` — architecture and operations documents.
|
||||
- `README.md` — workspace overview.
|
||||
- `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` — root agent entry instructions.
|
||||
- `.aiexclude`, `.clineignore`, `.clinerules`, `.cursorignore`, `.cursorrules`, `.geminiignore`, `.claude/`, `opencode.json` — agent/tooling ignore와 configuration.
|
||||
- `opencode.json` — agent/tooling configuration.
|
||||
- `.gitignore` — workspace-level ignore policy.
|
||||
- `.sops.yaml`, `secrets/` — encrypted secret policy와 SOPS-managed tracked secret material.
|
||||
- `collect_evidence.sh` — local evidence collection helper.
|
||||
- `agent-ops/.version` — agent-ops framework/version marker.
|
||||
- `agent-ops/bin/` — agent-ops 초기화, sync, entry file helper.
|
||||
- `agent-ops/rules/project/` — project/domain rules.
|
||||
|
|
@ -38,21 +36,13 @@ NomadCode 원레포 운영 도메인이다. 루트 helper, 문서, ignore/secret
|
|||
- `bin/lint` — vet/check/analyze entrypoint.
|
||||
- `bin/build` — build entrypoint.
|
||||
- `bin/dev` — development entrypoint 안내.
|
||||
- `bin/nomadcode-sops-env` — SOPS-managed env material 실행 helper.
|
||||
- `collect_evidence.sh` — workspace evidence 수집 helper.
|
||||
- `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` — agent별 루트 진입 규칙.
|
||||
- `.aiexclude`, `.clineignore`, `.cursorignore`, `.geminiignore` — agent별 archive/private ignore 경계.
|
||||
- `.clinerules`, `.cursorrules`, `.claude/settings.json`, `opencode.json` — agent/tooling별 루트 설정.
|
||||
- `agent-test/local/rules.md` — local 테스트 환경 routing과 private input 사용 경계.
|
||||
- `agent-ops/rules/project/rules.md` — 프로젝트 전체 agent routing.
|
||||
- `agent-roadmap/ROADMAP.md` — 전체 Phase와 Milestone index.
|
||||
- `agent-roadmap/current.md` — 현재 Phase와 기본 Milestone pointer.
|
||||
- `agent-ops/bin/sync.sh` — agent-ops 동기화 helper.
|
||||
- `agent-ops/bin/ai-ignore.sh` — agent별 archive/private ignore 파일 생성 helper.
|
||||
- `agent-ops/bin/entry-files.sh` — root agent entry 파일 재생성 helper.
|
||||
- `agent-ops/bin/bump-version.sh` — agent-ops version marker 갱신 helper.
|
||||
- `agent-ops/bin/roadmap-dependency-checker.sh` — roadmap 외부 의존 lock 판별 helper.
|
||||
- `agent-test/live-cycle-smoke.md`, `agent-test/plane-dev.md` — lifecycle/Plane dev smoke routing 문서.
|
||||
- `agent-test/local/*-smoke.md` — 도메인별 local smoke routing 문서.
|
||||
- `agent-roadmap/phase/*/PHASE.md`, `agent-roadmap/phase/*/milestones/*.md` — 활성 Phase/Milestone 문서.
|
||||
|
||||
|
|
@ -63,7 +53,6 @@ NomadCode 원레포 운영 도메인이다. 루트 helper, 문서, ignore/secret
|
|||
- roadmap은 `agent-roadmap/`에 두고, 서비스별 README에 Phase 계획을 중복 유지하지 않는다.
|
||||
- 일반 작업에서 `agent-roadmap/archive/**`와 `agent-task/archive/**`는 사용자가 명시하거나 규칙이 허용한 경우에만 읽는다.
|
||||
- `.gitignore`에는 private rules와 local-only `agent-test/local/`, `agent-test/runs/`만 제외하고, `agent-task/archive/**`는 AI ignore/permission 파일에서 제어한다.
|
||||
- raw `.env*` secret은 tracked 문서/규칙에 값으로 기록하지 않고, SOPS encrypted material과 local ignored env material의 경계를 유지한다.
|
||||
- 원레포 구조 설명은 README를 기준으로 갱신하고, 별도 운영/아키텍처 세부가 있을 때만 docs에 분리한다.
|
||||
|
||||
## 다른 도메인과의 경계
|
||||
|
|
@ -77,5 +66,4 @@ NomadCode 원레포 운영 도메인이다. 루트 helper, 문서, ignore/secret
|
|||
- 하위 앱/서비스에 별도 agent entry 파일이나 agent-ops scaffold를 복제하지 않는다.
|
||||
- framework 공통 파일을 프로젝트 요구에 맞춰 직접 수정하지 않는다.
|
||||
- root helper에 특정 개발자 로컬 절대경로를 넣지 않는다.
|
||||
- SOPS encrypted file을 평문 secret 문서처럼 다루거나 secret 값을 rules/roadmap/docs에 기록하지 않는다.
|
||||
- roadmap이나 agent-task archive 문서를 최신 템플릿에 맞춘다는 이유만으로 재포맷하지 않는다.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ NomadCode는 AI 병렬 작업 운용을 위한 원레포다. 백엔드 오케스
|
|||
| `services/core/**` | core | `agent-ops/rules/project/domain/core/rules.md` |
|
||||
| `apps/client/**` | mobile | `agent-ops/rules/project/domain/mobile/rules.md` |
|
||||
| `packages/contracts/**` | contracts | `agent-ops/rules/project/domain/contracts/rules.md` |
|
||||
| `bin/**`, `docs/**`, `README.md`, `.gitignore`, `.aiexclude`, `.clineignore`, `.clinerules`, `.cursorignore`, `.cursorrules`, `.geminiignore`, `.claude/**`, `.sops.yaml`, `secrets/**`, `collect_evidence.sh`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `opencode.json`, `agent-ops/.version`, `agent-ops/bin/**`, `agent-roadmap/**`, `agent-test/**`, `agent-ops/rules/project/**` | workspace-ops | `agent-ops/rules/project/domain/workspace-ops/rules.md` |
|
||||
| `bin/**`, `docs/**`, `README.md`, `.gitignore`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `opencode.json`, `agent-ops/.version`, `agent-ops/bin/**`, `agent-roadmap/**`, `agent-test/**`, `agent-ops/rules/project/**` | workspace-ops | `agent-ops/rules/project/domain/workspace-ops/rules.md` |
|
||||
|
||||
## 스킬 라우팅
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
spec_doc_type: index
|
||||
status: 활성
|
||||
---
|
||||
|
||||
# 구현 스펙 색인
|
||||
|
||||
## 목적
|
||||
|
||||
이 디렉터리는 사람과 agent가 함께 보는 현재 구현 기능 living spec을 관리한다.
|
||||
로드맵 완료 이력, SDD, 계약 원문, 사람용 docs를 대체하지 않는다.
|
||||
|
||||
## 읽기 규칙
|
||||
|
||||
- 필요한 작업에서만 이 index를 읽고, 매칭되는 spec 문서만 읽는다.
|
||||
- `archive/**`는 과거 비교, 복원, 특정 근거 확인 요청이 있을 때만 읽는다.
|
||||
- API, wire protocol, config/event schema, 프로세스 간 계약 원문은 `agent-contract/`를 따른다.
|
||||
- 코드 배치, 구현 진입점, 도메인 간 상세 책임 경계는 domain rule을 따른다.
|
||||
|
||||
## Spec Map
|
||||
|
||||
| id | 상태 | 언제 읽나 | path | 주요 근거 |
|
||||
|----|------|-----------|------|-----------|
|
||||
| 없음 | 없음 | 없음 | 없음 | 없음 |
|
||||
|
||||
## 작성 규칙
|
||||
|
||||
- 현재 구현 기준으로 작성한다.
|
||||
- 기능 목록과 주요 흐름을 먼저 파악할 수 있게 작성한다.
|
||||
- 코드/계약/테스트 evidence를 우선한다.
|
||||
- 계약 원문은 복제하지 않고 링크한다.
|
||||
- 코드 진입점과 도메인룰 성격의 상세 경계는 반복하지 않는다.
|
||||
- 불확실한 내용은 `불명확`으로 남긴다.
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
---
|
||||
spec_doc_type: spec
|
||||
spec_id: <area>/<spec-id>
|
||||
status: 불명확
|
||||
source_evidence:
|
||||
- type: code
|
||||
path: null
|
||||
notes: <현재 구현 근거>
|
||||
---
|
||||
|
||||
# 스펙: <title>
|
||||
|
||||
## 목적
|
||||
|
||||
<이 spec이 설명하는 현재 구현 기능과 이 문서를 읽어야 하는 이유>
|
||||
|
||||
## 기능 목록
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| <기능명> | <현재 코드와 계약으로 확인된 동작> |
|
||||
|
||||
## 범위
|
||||
|
||||
- 포함: <현재 spec이 다루는 범위>
|
||||
- 제외: <다른 spec, roadmap, SDD, contract, docs로 넘기는 범위>
|
||||
|
||||
## 주요 흐름
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant A as <주체>
|
||||
participant B as <주체>
|
||||
A->>B: <주요 메시지 또는 동작>
|
||||
```
|
||||
|
||||
## 계약
|
||||
|
||||
- <관련 agent-contract 문서 또는 코드 계약 포인터>
|
||||
|
||||
## 설정/데이터/이벤트
|
||||
|
||||
- <관련 config, 저장소, event, runtime state 요약. 원문 schema는 복제하지 않는다.>
|
||||
|
||||
## 검증
|
||||
|
||||
- `<command or profile>` - <기대 결과>
|
||||
|
||||
## 한계와 주의사항
|
||||
|
||||
- <현재 구현 한계 또는 조건부 동작>
|
||||
|
||||
## 변경 기록
|
||||
|
||||
- <YYYY-MM-DD>: <생성/갱신 근거>
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
ui_doc_type: archive-log
|
||||
target: <target>
|
||||
---
|
||||
|
||||
# <target> log
|
||||
|
||||
## <YYYY-MM-DD>
|
||||
|
||||
### Changed
|
||||
|
||||
- <변경 또는 폐기된 정의>
|
||||
|
||||
### Reason
|
||||
|
||||
- <변경 이유>
|
||||
|
||||
### Superseded
|
||||
|
||||
- <대체된 이전 기준 또는 없음>
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
---
|
||||
ui_doc_type: component
|
||||
component_id: <component-id>
|
||||
status: <구현됨|계획|가정|불명확>
|
||||
source_evidence:
|
||||
- type: code
|
||||
path: null
|
||||
notes: <구현 근거. 없으면 없음>
|
||||
- type: docs
|
||||
path: null
|
||||
notes: <컨셉/계획 근거. 없으면 없음>
|
||||
- type: user
|
||||
path: null
|
||||
notes: <사용자 명시 입력. 없으면 없음>
|
||||
---
|
||||
|
||||
# <Component Name>
|
||||
|
||||
Component ID: `<component-id>`
|
||||
|
||||
Status: `<구현됨|계획|가정|불명확>`
|
||||
|
||||
## Source Evidence
|
||||
|
||||
| Type | Path | Notes |
|
||||
|------|------|-------|
|
||||
| code | 없음 | <구현 근거. 없으면 `없음`> |
|
||||
| docs | 없음 | <컨셉/계획 근거. 없으면 `없음`> |
|
||||
| user | 없음 | <사용자 명시 입력. 없으면 `없음`> |
|
||||
|
||||
## Purpose
|
||||
|
||||
<이 component가 해결하는 UI 문제를 적는다.>
|
||||
|
||||
## Used By
|
||||
|
||||
- `<view-id>`: <사용 위치 또는 region id>
|
||||
|
||||
## Anatomy
|
||||
|
||||
- <구성 부분>
|
||||
|
||||
## Variants
|
||||
|
||||
- default: <기본 사용>
|
||||
|
||||
## States
|
||||
|
||||
- default
|
||||
- loading
|
||||
- empty
|
||||
- error
|
||||
- disabled
|
||||
|
||||
## Rules
|
||||
|
||||
- <사용 규칙>
|
||||
|
||||
## Decision History
|
||||
|
||||
- <YYYY-MM-DD>: <현재 기준으로 남길 결정 요약>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
---
|
||||
ui_doc_type: components-index
|
||||
components: []
|
||||
---
|
||||
|
||||
# Component Definitions
|
||||
|
||||
## Component List
|
||||
|
||||
| Component ID | Status | Evidence | Description |
|
||||
|--------------|--------|----------|-------------|
|
||||
| 없음 | - | - | - |
|
||||
|
||||
## Rules
|
||||
|
||||
- component 정의는 구현 API가 아니라 UI 사용 규칙을 다룬다.
|
||||
- view별 변형이 필요하면 `<component-id>/<variant>.md` 또는 하위 디렉터리를 사용한다.
|
||||
- 실제 구현체 이름과 다를 수 있지만, view 정의서에서 참조하는 component id는 이 목록에 있어야 한다.
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
---
|
||||
ui_doc_type: definition-index
|
||||
surface_type: ops-dev
|
||||
source_evidence:
|
||||
- type: code
|
||||
path: null
|
||||
notes: <UI 구현 근거 요약>
|
||||
- type: docs
|
||||
path: null
|
||||
notes: <컨셉/계획 근거 요약>
|
||||
- type: user
|
||||
path: null
|
||||
notes: <사용자 명시 입력 요약>
|
||||
---
|
||||
|
||||
# UI Definition
|
||||
|
||||
## Purpose
|
||||
|
||||
<이 agent-ui가 다루는 UI 표면과 목표를 적는다.>
|
||||
|
||||
## Surface Type
|
||||
|
||||
- Type: ops-dev
|
||||
- Notes: <product UI 레이어가 필요한 경우 brand/content/assets/tokens/motion 확장 후보를 적는다.>
|
||||
|
||||
## Source Evidence
|
||||
|
||||
| Type | Path | Notes |
|
||||
|------|------|-------|
|
||||
| code | 없음 | <UI 구현 근거 요약> |
|
||||
| docs | 없음 | <컨셉/계획 근거 요약> |
|
||||
| user | 없음 | <사용자 명시 입력 요약> |
|
||||
|
||||
## Structure
|
||||
|
||||
- `views/`: 화면 또는 업무 단위 정의
|
||||
- `components/`: 반복 UI 구성요소 정의
|
||||
- `archive/`: 현재 기준이 아닌 과거 정의/결정 로그
|
||||
|
||||
## Reading Rules
|
||||
|
||||
- 현재 UI 동기화는 이 디렉터리의 활성 문서를 기준으로 한다.
|
||||
- `archive/**`는 과거 비교, 복원, 특정 근거 확인 요청이 있을 때만 읽는다.
|
||||
|
||||
## Sync Rules
|
||||
|
||||
- frame-view가 있으면 view region id와 frame region id는 동일해야 한다.
|
||||
- view에서 참조한 component id는 `components/` 아래에 정의되어야 한다.
|
||||
- frame은 definition을 대체하지 않는다.
|
||||
- `구현됨`, `계획`, `가정`, `불명확` 상태를 섞어 쓰지 않는다.
|
||||
- 기본 코드 동기화는 `.sync-state.json` 기준 이후 변경분만 대상으로 한다.
|
||||
- plan-required 코드 작업의 task/UI 매핑과 완료 정합화는 `.sync-state.json.pending_code_work`를 사용한다.
|
||||
- milestone-required 코드 작업의 Milestone/UI 매핑과 완료 정합화는 `.sync-state.json.pending_milestone_work`를 사용한다.
|
||||
- view/component status와 validation-only frame-view를 분리하고 완료 기록은 대응하는 `reconciled_*_work`에 둔다.
|
||||
- 전체 동기화는 사용자가 명시한 경우에만 수행한다.
|
||||
|
||||
## Decision History
|
||||
|
||||
- <YYYY-MM-DD>: <초기 결정 또는 변경 요약>
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
ui_doc_type: frame-index
|
||||
frames: []
|
||||
---
|
||||
|
||||
# UI Frames
|
||||
|
||||
## Purpose
|
||||
|
||||
이 디렉터리는 visual source가 있는 view의 wireframe과 definition 연결 정보를 보관한다.
|
||||
|
||||
## Frame Sources
|
||||
|
||||
- `views/<view-id>/index.md`: visual source가 있는 view의 frame 연결 문서
|
||||
- `views/<view-id>/wire.excalidraw`: 선택 visual source
|
||||
|
||||
## Rules
|
||||
|
||||
- frame은 definition을 대체하지 않는다.
|
||||
- visual source가 있으면 대응되는 frame index에 기록한다.
|
||||
- visual source가 없으면 `views/<view-id>/`를 만들지 않는다.
|
||||
- frame-view가 있으면 frame region id는 definition region id와 동일해야 한다.
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
---
|
||||
ui_doc_type: frame-view
|
||||
view_id: <view-id>
|
||||
definition: ../../../definition/views/<view-id>/index.md
|
||||
visual_source: <frame-source>
|
||||
regions:
|
||||
- <view-id>.<region>
|
||||
---
|
||||
|
||||
# <View Name> Frame
|
||||
|
||||
Definition:
|
||||
- `../../../definition/views/<view-id>/index.md`
|
||||
|
||||
Visual Source:
|
||||
- `<frame-source>`
|
||||
|
||||
## Frame Intent
|
||||
|
||||
- <이 frame이 검증하려는 배치, 밀도, 시선 흐름을 적는다.>
|
||||
|
||||
## Required Regions
|
||||
|
||||
- `<view-id>.<region>`: <visual source의 라벨 또는 위치 설명>
|
||||
|
||||
## Layout Notes
|
||||
|
||||
- desktop: <배치 기준>
|
||||
- tablet: <배치 기준>
|
||||
- mobile: <배치 기준>
|
||||
|
||||
## Sync Rules
|
||||
|
||||
- visual source의 주요 박스 text label 또는 `customData.region_id`는 가능한 한 region id를 포함한다.
|
||||
- definition에 없는 region을 frame에 추가하지 않는다. 필요한 경우 `agent-ui/USER_REVIEW.md`에 남긴다.
|
||||
- frame에서 제거한 region은 definition에서도 제거 대상인지 확인한다.
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
ui_doc_type: readme
|
||||
surface_type: ops-dev
|
||||
---
|
||||
|
||||
# agent-ui
|
||||
|
||||
이 디렉터리는 AI agent와 사람이 UI 의도, 화면 구조, 와이어프레임, 반복 구성요소를 동기화하기 위한 작업 문맥 저장소다.
|
||||
|
||||
## 대상
|
||||
|
||||
- 1차 대상: ops/dev UI
|
||||
- 확장 후보: product UI
|
||||
|
||||
## 구조
|
||||
|
||||
- `definition/`: 현재 UI 정의 source of truth
|
||||
- `frame/`: visual source가 있는 view의 wireframe 연결
|
||||
- `.sync-state.json`: agent-ui -> code 동기화 기준점, plan/Milestone pending 매핑, 완료 정합화 기록
|
||||
- `USER_REVIEW.md`: 사용자 판단이 필요한 활성 질문
|
||||
- `archive/user-review/`: 해결된 사용자 리뷰 로그
|
||||
|
||||
## 기본 규칙
|
||||
|
||||
- 현재 기준은 `definition/**`에 둔다.
|
||||
- visual wireframe은 visual source가 있을 때만 `frame/**`에 둔다.
|
||||
- `.excalidraw` 파일만으로 UI 기준을 확정하지 않는다.
|
||||
- 초기 생성 이후 기본 흐름은 `agent-ui -> code` 방향이다.
|
||||
- plan-required 코드 작업은 `.sync-state.json.pending_code_work`로 연결하고 일반 code-review 완료 뒤 `sync-agent-ui`가 정합화한다.
|
||||
- milestone-required 코드 작업은 `.sync-state.json.pending_milestone_work`로 연결하고 Milestone 종료 직전에 `sync-agent-ui`가 정합화한다.
|
||||
- `sync-agent-ui`의 state transition은 bundled helper가 담당하며 frame-view는 status 전환 대상이 아니다.
|
||||
- `definition/archive/**`와 `archive/user-review/**`는 과거 기록이며 일반 작업에서 읽지 않는다.
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"schema_version": 4,
|
||||
"surface_type": "ops-dev",
|
||||
"baseline_mode": "<code-first|concept-first|blank|migration>",
|
||||
"last_sync_mode": "baseline",
|
||||
"last_synced_head": "<git-commit-hash>",
|
||||
"last_synced_at": "<ISO-8601>",
|
||||
"agent_ui_paths": [],
|
||||
"code_paths": [],
|
||||
"pending_code_work": [],
|
||||
"reconciled_code_work": [],
|
||||
"pending_milestone_work": [],
|
||||
"reconciled_milestone_work": [],
|
||||
"notes": []
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
ui_doc_type: user-review
|
||||
status: open
|
||||
---
|
||||
|
||||
# agent-ui 사용자 리뷰
|
||||
|
||||
이 문서는 agent가 확정할 수 없는 UI 결정을 사용자에게 넘기기 위한 활성 리뷰 문서다.
|
||||
해결된 항목은 `agent-ui/archive/user-review/user_review_N.log`로 이동할 수 있다.
|
||||
|
||||
## Review Items
|
||||
|
||||
- [ ] [UIR-001] <결정이 필요한 질문>
|
||||
- Source Skill: <update-agent-ui | validate-agent-ui | sync-agent-ui>
|
||||
- Stage: <definition-edit | document-consistency | code-sync>
|
||||
- Blocking Step: <validate-agent-ui | sync-agent-ui | none>
|
||||
- Context: <관련 view/component/frame 경로>
|
||||
- Options: <후보가 있으면 적는다>
|
||||
- Needed For: <차단되는 작업>
|
||||
- Resume From: <해결 후 재개할 스킬/명령>
|
||||
- Pending Changes: <남은 작업트리 변경 파일 또는 없음>
|
||||
|
||||
## Notes
|
||||
|
||||
- 없음
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
---
|
||||
ui_doc_type: view
|
||||
view_id: <view-id>
|
||||
status: <구현됨|계획|가정|불명확>
|
||||
frame: null
|
||||
source_evidence:
|
||||
- type: code
|
||||
path: null
|
||||
notes: <구현 근거. 없으면 없음>
|
||||
- type: docs
|
||||
path: null
|
||||
notes: <컨셉/계획 근거. 없으면 없음>
|
||||
- type: user
|
||||
path: null
|
||||
notes: <사용자 명시 입력. 없으면 없음>
|
||||
regions:
|
||||
- <view-id>.<region>
|
||||
---
|
||||
|
||||
# <View Name>
|
||||
|
||||
View ID: `<view-id>`
|
||||
|
||||
Frame:
|
||||
- 없음
|
||||
|
||||
Status: `<구현됨|계획|가정|불명확>`
|
||||
|
||||
## Source Evidence
|
||||
|
||||
| Type | Path | Notes |
|
||||
|------|------|-------|
|
||||
| code | 없음 | <구현 근거. 없으면 `없음`> |
|
||||
| docs | 없음 | <컨셉/계획 근거. 없으면 `없음`> |
|
||||
| user | 없음 | <사용자 명시 입력. 없으면 `없음`> |
|
||||
|
||||
## Purpose
|
||||
|
||||
<이 view의 목적을 1-3줄로 적는다.>
|
||||
|
||||
## Primary Users
|
||||
|
||||
- <사용자 역할>
|
||||
|
||||
## Primary Tasks
|
||||
|
||||
- <사용자 작업>
|
||||
|
||||
## Information Priority
|
||||
|
||||
1. <가장 먼저 보여야 하는 정보>
|
||||
2. <다음 우선순위 정보>
|
||||
|
||||
## Regions
|
||||
|
||||
| Region ID | Purpose | Component | Priority | Notes |
|
||||
|-----------|---------|-----------|----------|-------|
|
||||
| `<view-id>.<region>` | <역할> | `<component-id 또는 없음>` | high | <비고> |
|
||||
|
||||
## Actions
|
||||
|
||||
| Action ID | Trigger | Result | Guard |
|
||||
|-----------|---------|--------|-------|
|
||||
| `<view-id>.<action>` | <사용자 입력> | <결과> | <권한/상태 조건> |
|
||||
|
||||
## States
|
||||
|
||||
- loading: <표시 기준>
|
||||
- empty: <표시 기준>
|
||||
- error: <표시 기준>
|
||||
- permission-denied: <표시 기준>
|
||||
|
||||
## Open Questions
|
||||
|
||||
- 없음
|
||||
|
||||
## Decision History
|
||||
|
||||
- <YYYY-MM-DD>: <현재 기준으로 남길 결정 요약>
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
---
|
||||
ui_doc_type: views-index
|
||||
views: []
|
||||
---
|
||||
|
||||
# View Definitions
|
||||
|
||||
## View Tree
|
||||
|
||||
| View ID | Status | Evidence | Description |
|
||||
|---------|--------|----------|-------------|
|
||||
| 없음 | - | - | - |
|
||||
|
||||
## Navigation
|
||||
|
||||
- `<from-view>` -> `<to-view>`: <이동 조건 또는 사용자 작업>
|
||||
|
||||
## Common States
|
||||
|
||||
- loading
|
||||
- empty
|
||||
- error
|
||||
- permission-denied
|
||||
|
||||
## Common Permissions
|
||||
|
||||
- <권한 이름>: <허용되는 view/action>
|
||||
|
||||
## Open Questions
|
||||
|
||||
- 없음
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 새 결정이 필요해 보여도 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 이 섹션은 선택된 SDD 결정 또는 선택된 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 차단할 때만 채운다. 외부 환경/secret/서비스 준비, 검증 증거 공백, 반복 실패, 일반 범위 조정은 사용자 리뷰 요청이 아니며 `검증 결과`, `계획 대비 변경 사항`, 또는 code-review의 일반 follow-up plan으로 처리한다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 연결 대상: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
|
@ -1,35 +1,30 @@
|
|||
# 현재 로드맵 컨텍스트
|
||||
|
||||
## 고정 참조
|
||||
|
||||
- Phase를 가로지르는 다음 작업 후보는 [전역 마일스톤 실행 순서](priority-queue.md)를 먼저 확인한다.
|
||||
- Phase는 도메인/책임 영역이며 순차 실행 게이트가 아니다.
|
||||
|
||||
## 활성 Phase
|
||||
|
||||
- [<스케치 | 계획 | 진행중 | 검토중 | 보류>] <phase-name>
|
||||
- 경로: [PHASE.md](phase/<phase-slug>/PHASE.md)
|
||||
- 경로: `agent-roadmap/phase/<phase-slug>/PHASE.md`
|
||||
|
||||
## 활성 Milestone
|
||||
|
||||
- [<스케치 | 계획 | 진행중 | 검토중 | 보류>] <milestone-name>
|
||||
- Phase: [PHASE.md](phase/<phase-slug>/PHASE.md)
|
||||
- 경로: [<milestone-name>](phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- Phase: `agent-roadmap/phase/<phase-slug>/PHASE.md`
|
||||
- 경로: `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`
|
||||
|
||||
## 선택 규칙
|
||||
|
||||
- 이 문서는 활성 Phase와 활성 Milestone 후보 목록이며, 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
|
||||
- 이 문서는 브랜치별 로컬 포인터이며 git 추적 대상이 아니다.
|
||||
- 활성 Phase는 [PHASE.md](phase/<phase-slug>/PHASE.md)를 가리킨다.
|
||||
- 활성 Milestone은 [Milestone 문서](phase/<phase-slug>/milestones/<milestone-slug>.md)를 가리킨다.
|
||||
- 활성 Phase는 `agent-roadmap/phase/<phase-slug>/PHASE.md`를 가리킨다.
|
||||
- 활성 Milestone은 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`를 가리킨다.
|
||||
- 활성 항목은 아카이브 경로를 포함하지 않는다.
|
||||
- `[검토중]` 항목은 완료 근거와 archive 조건이 정리될 때까지 활성 항목으로 남길 수 있다.
|
||||
- `[스케치]` 항목은 활성 후보로 남길 수 있지만 구현 계획 생성 대상은 아니며, `[계획]` 승격 조건을 정리하는 대상으로만 다룬다.
|
||||
- `[완료]` 또는 `[폐기]` 항목은 archive 링크를 남긴 뒤 활성 항목에서 제거한다.
|
||||
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 Phase와 Milestone을 선택하고 같은 세션에서 1회 읽는다.
|
||||
- 활성 Phase 또는 Milestone 둘 이상에 걸치면 필요한 문서를 모두 읽고 작업 범위를 좁힌다.
|
||||
- 활성 범위 밖의 작업이면 [ROADMAP.md](ROADMAP.md)의 Phase 흐름을 확인하고 범위 충돌을 보고한다. 제품/범위 결정이 필요하면 대상 Milestone의 `구현 잠금 > 결정 필요` 또는 SDD [USER_REVIEW.md](sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md)로 분리한다.
|
||||
- 활성 범위 밖의 작업이면 `agent-roadmap/ROADMAP.md`의 Phase 흐름을 확인하고 범위 충돌을 보고한다. 제품/범위 결정이 필요하면 대상 Milestone의 `구현 잠금 > 결정 필요` 또는 SDD `USER_REVIEW.md`로 분리한다.
|
||||
- 완료된 과거 내용이 필요할 때만 `ROADMAP.md` 또는 `PHASE.md`에 있는 archive 링크를 따라가서 읽는다.
|
||||
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 구현이나 구현 계획을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다. 관련 결정이 없고 표준선으로 처리 가능하면 잠금 해소용 roadmap-only 갱신으로 결정 항목을 정리한 뒤 진행하며, Milestone 전체에서 에이전트가 확정할 수 없는 결정 항목이 더 이상 없을 때만 `구현 잠금` 상태를 `해제`로 둔다.
|
||||
- 선택된 Milestone에 `SDD: 필요`가 있으면 [SDD.md](sdd/<phase-slug>/<milestone-slug>/SDD.md)가 `[승인됨]`이고 SDD 잠금이 해제되었으며 SDD [USER_REVIEW.md](sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md)가 없어야 구현이나 구현 계획을 시작한다.
|
||||
- 선택된 Milestone에 `SDD: 필요`가 있으면 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`가 `[승인됨]`이고 SDD 잠금이 해제되었으며 SDD `USER_REVIEW.md`가 없어야 구현이나 구현 계획을 시작한다.
|
||||
- 선택된 Milestone 상태가 `[스케치]`이면 `구현 잠금` 상태와 관계없이 구현이나 구현 계획을 시작하지 않고 `[계획]` 승격 필요를 보고한다.
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
## 위치
|
||||
|
||||
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
|
||||
- Phase: [PHASE.md](../PHASE.md)
|
||||
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||
- Phase: `agent-roadmap/phase/<phase-slug>/PHASE.md`
|
||||
|
||||
## 목표
|
||||
|
||||
|
|
@ -33,13 +33,11 @@
|
|||
|
||||
- 상태: <잠금 | 해제>
|
||||
- SDD: <필요 | 불필요>
|
||||
- SDD 문서: <없음 | [SDD.md](../../../sdd/<phase-slug>/<milestone-slug>/SDD.md)>
|
||||
- SDD 문서: <없음 | `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`>
|
||||
- SDD 사유: <필요/불필요 판정 근거 한 줄>
|
||||
- 잠금 해제 조건: <없음 | 아래 체크리스트>
|
||||
- [ ] <SDD가 필요한 경우: SDD 잠금이 해제되어 있다>
|
||||
- [ ] <SDD가 필요한 경우: SDD 사용자 리뷰가 없거나 승인/해결되었다>
|
||||
- [ ] <SDD가 필요한 경우: Acceptance Scenario가 Milestone 기능 Task와 연결되어 있다>
|
||||
- [ ] <SDD가 필요한 경우: Evidence Map이 완료 시 Roadmap Completion과 최종 검증 evidence로 검증 가능하게 연결되어 있다>
|
||||
- 결정 필요: <없음 | 아래 목록>
|
||||
- <에이전트가 확정할 수 없는 제품/범위/우선순위/책임 경계 결정 항목>
|
||||
|
||||
|
|
@ -56,7 +54,6 @@ Task는 `- [ ] [item-id] 설명` 형식을 사용한다.
|
|||
item-id는 공백 없는 짧은 ASCII 영문/숫자 segment 1~4개로 작성하고 segment 구분자는 -_+= 만 사용한다.
|
||||
epic-id와 item-id는 해당 Milestone 안에서만 유일하면 되고, 다른 Milestone에서는 같은 id를 다시 사용할 수 있다.
|
||||
Task는 기능 또는 산출물 단위다. 검증이 필요한 기능만 같은 Task 안에 `검증: <명령/확인 방법/기대 결과>`를 덧붙인다.
|
||||
각 Epic에는 기능 Task를 최대 5개만 둔다. 여섯 번째 Task가 필요하면 capability, 산출물, 의존성, 검증 경계 중 하나로 Epic을 분리한다. 분리된 Epic이 독립 목표면 새 Milestone 후보로 둔다.
|
||||
Task 체크리스트는 Epic 바로 아래의 flat list로 유지하고, 구현 세부나 테스트만 따로 떼어낸 하위 체크박스는 만들지 않는다.
|
||||
별도 `완료 기준` 섹션은 만들지 않는다.
|
||||
-->
|
||||
|
|
@ -87,6 +84,6 @@ Task 체크리스트는 Epic 바로 아래의 flat list로 유지하고, 구현
|
|||
|
||||
- 관련 경로: `<path>`
|
||||
- 표준선(선택): <기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 진행할 기본 기준>
|
||||
- 선행 작업: <없음 또는 파일 위치 기준 Markdown 링크(예: [Milestone 이름](../other-milestone.md))/태스크 이름>
|
||||
- 후속 작업: <없음 또는 파일 위치 기준 Markdown 링크(예: [Milestone 이름](../next-milestone.md))/태스크 이름>
|
||||
- 확인 필요: <없음 | `구현 잠금 > 결정 필요` 또는 [USER_REVIEW.md](../../../sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md)로 분리할 항목>
|
||||
- 선행 작업: <없음 또는 Milestone/태스크 이름>
|
||||
- 후속 작업: <없음 또는 Milestone/태스크 이름>
|
||||
- 확인 필요: <없음 | `구현 잠금 > 결정 필요` 또는 SDD USER_REVIEW.md로 분리할 항목>
|
||||
|
|
|
|||
|
|
@ -11,13 +11,11 @@
|
|||
## Milestone 흐름
|
||||
|
||||
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
|
||||
이 흐름은 해당 Phase 안의 상태 정리이며, Phase를 가로지르는 실행 순서는 아니다.
|
||||
Milestone은 완료, 검토중, 진행중, 계획, 스케치 또는 보류 상태 그룹으로 정리한다.
|
||||
Phase를 가로지르는 실제 다음 작업 선택은 [전역 마일스톤 실행 순서](../../priority-queue.md)를 우선한다.
|
||||
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||
|
||||
- [<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>] <Milestone 이름>
|
||||
- 경로: [<Milestone 이름>](milestones/<milestone-slug>.md) 또는 [archive <Milestone 이름>](../../archive/phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- 경로: `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 또는 `agent-roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md`
|
||||
- 요약: <목표 또는 결과 1문장>
|
||||
|
||||
## Phase 경계
|
||||
|
|
|
|||
|
|
@ -1,46 +1,29 @@
|
|||
# 로드맵 현지점
|
||||
|
||||
- local current: {없음 | [current.md](agent-roadmap/current.md)}
|
||||
- [local current.md](agent-roadmap/current.md)
|
||||
|
||||
<!--
|
||||
작성 규칙:
|
||||
- 아래 {...} placeholder는 실제 출력에 남기지 않는다.
|
||||
- 링크는 반드시 [제목](repo-root-relative-path) 형식으로 쓴다.
|
||||
- 문서 안에서 읽은 file-location-relative 링크는 원본 파일 위치 기준으로 해석한 뒤 repo root 기준 target으로 다시 쓴다.
|
||||
- 경로를 확정할 수 없는 항목은 깨진 Markdown 링크 대신 `링크 없음: <사유>`로 쓴다.
|
||||
- {PHASE_LINK}, {MILESTONE_LINK}, {SDD_LINK}, {USER_REVIEW_LINK}는 실제 Markdown 링크로 치환한다.
|
||||
- 이 주석은 출력하지 않는다.
|
||||
-->
|
||||
|
||||
## Breadcrumb
|
||||
|
||||
- [로드맵: {roadmap-name}](agent-roadmap/ROADMAP.md)
|
||||
- Phase: {PHASE_LINK}
|
||||
- Milestone: {MILESTONE_LINK}
|
||||
- [{상태}] {목표 또는 역할 한 줄}
|
||||
- SDD: {없음 | SDD_LINK | SDD_LINK (파일 없음)}
|
||||
- 사용자 리뷰: {없음 | USER_REVIEW_LINK}
|
||||
- Milestone: {MILESTONE_LINK}
|
||||
- [{상태}] {목표 또는 역할 한 줄}
|
||||
- SDD: {없음 | SDD_LINK | SDD_LINK (파일 없음)}
|
||||
- 사용자 리뷰: {없음 | USER_REVIEW_LINK}
|
||||
|
||||
## 전역 마일스톤 실행 순서
|
||||
|
||||
- {없음 | [MILESTONE_TITLE](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md): 식별용 한 줄 설명}
|
||||
- {[MILESTONE_TITLE](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md): 식별용 한 줄 설명 | 큐 정리 필요: 사유}
|
||||
- [로드맵: <roadmap-name>](agent-roadmap/ROADMAP.md)
|
||||
- [Phase: <phase-name>](agent-roadmap/phase/<phase-slug>/PHASE.md)
|
||||
- [Milestone: <milestone-name>](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- [<상태>] <목표 또는 역할 한 줄>
|
||||
- SDD: <없음 | [SDD.md](agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md) | 경로만 있음: `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`>
|
||||
- 사용자 리뷰: <없음 | [USER_REVIEW.md](agent-roadmap/sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md)>
|
||||
- [Milestone: <milestone-name>](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- [<상태>] <목표 또는 역할 한 줄>
|
||||
- SDD: <없음 | [SDD.md](agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md) | 경로만 있음: `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`>
|
||||
- 사용자 리뷰: <없음 | [USER_REVIEW.md](agent-roadmap/sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md)>
|
||||
|
||||
## 전체 Phase 흐름
|
||||
|
||||
- [{상태}] {PHASE_LINK}
|
||||
- [{상태}] {PHASE_LINK} ← 현재
|
||||
- [{상태}] {PHASE_LINK}
|
||||
- [<상태>] [<Phase 이름>](<phase-path>)
|
||||
- [<상태>] [<현재 Phase 이름>](<phase-path>) ← 현재
|
||||
- [<상태>] [<Phase 이름>](<phase-path>)
|
||||
|
||||
## 현재 Phase의 Milestone 흐름
|
||||
|
||||
- [{상태}] {MILESTONE_LINK} ← 현재 후보, {역할 태그}
|
||||
- SDD: {없음 | SDD_LINK | SDD_LINK (파일 없음)}
|
||||
- 사용자 리뷰: {없음 | USER_REVIEW_LINK}
|
||||
- [{상태}] {MILESTONE_LINK} ← 현재 후보, {역할 태그}
|
||||
- SDD: {없음 | SDD_LINK | SDD_LINK (파일 없음)}
|
||||
- 사용자 리뷰: {없음 | USER_REVIEW_LINK}
|
||||
- [<상태>] [<Milestone 이름>](<milestone-path>) ← 현재 후보, <역할 태그>
|
||||
- SDD: <없음 | [SDD.md](<sdd-path>) | 경로만 있음: `<sdd-path>`>
|
||||
- 사용자 리뷰: <없음 | [USER_REVIEW.md](<user-review-path>)>
|
||||
- [<상태>] [<Milestone 이름>](<milestone-path>) ← 현재 후보, <역할 태그>
|
||||
- SDD: <없음 | [SDD.md](<sdd-path>) | 경로만 있음: `<sdd-path>`>
|
||||
- 사용자 리뷰: <없음 | [USER_REVIEW.md](<user-review-path>)>
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
# 전역 마일스톤 실행 순서
|
||||
|
||||
이 문서는 Phase를 가로지르는 Milestone 실행 순서만 기록한다. 위에 있는 항목을 먼저 검토한다.
|
||||
|
||||
## 실행 순서
|
||||
|
||||
<!--
|
||||
작성 규칙:
|
||||
- 실행 후보가 없으면 이 섹션을 비워 둔다.
|
||||
- 항목은 Milestone 제목 링크와 식별용 한 줄 설명만 둔다.
|
||||
- 상태, 목표, 범위, 잠금, 기능, 완료 근거는 각 Milestone 문서를 원본으로 삼는다.
|
||||
- 링크 target은 이 파일 위치 기준 상대 경로로 쓴다.
|
||||
|
||||
예:
|
||||
1. [Milestone 제목](phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
이 Milestone에서 다루는 작업을 한 줄로 적는다.
|
||||
-->
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
## 위치
|
||||
|
||||
- Milestone: [Milestone 문서](../../../phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- Phase: [PHASE.md](../../../phase/<phase-slug>/PHASE.md)
|
||||
- Milestone: `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`
|
||||
- Phase: `agent-roadmap/phase/<phase-slug>/PHASE.md`
|
||||
|
||||
## 상태
|
||||
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
## SDD 잠금
|
||||
|
||||
- 상태: <잠금 | 해제>
|
||||
- 사용자 리뷰: <없음 | [USER_REVIEW.md](USER_REVIEW.md)>
|
||||
- 사용자 리뷰: <없음 | `USER_REVIEW.md`>
|
||||
- 잠금 항목:
|
||||
- [ ] [D01] <사용자만 결정할 source of truth, 상태 전이, 책임 경계, 범위, 권한, 비용, 실패 처리 항목>
|
||||
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
| 영역 | 기준 | 메모 |
|
||||
|------|------|------|
|
||||
| Roadmap | [Milestone 문서](../../../phase/<phase-slug>/milestones/<milestone-slug>.md) | <장기 원장, 상태 반영 기준> |
|
||||
| Roadmap | `<path>` | <장기 원장, 상태 반영 기준> |
|
||||
| Code | `<path>` | <구현 source of truth> |
|
||||
| External Provider | <없음 또는 provider> | <provider id/revision/status 기준> |
|
||||
| User Decision | <없음 또는 D-id> | <사용자 결정이 필요한 기준> |
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
## Interface Contract
|
||||
|
||||
- 계약 원문: <없음 또는 [계약 문서](../../../../agent-contract/...)>
|
||||
- 계약 원문: <없음 또는 `agent-contract/...` 링크>
|
||||
- 입력:
|
||||
- <field>: <의미>
|
||||
- 출력:
|
||||
|
|
@ -55,9 +55,9 @@
|
|||
|
||||
## Evidence Map
|
||||
|
||||
| Scenario | Required Evidence | `agent-task` 연결 | 완료 Evidence 기대 |
|
||||
| Scenario | Required Evidence | `agent-task` 연결 | `Spec Completion` 기대 |
|
||||
|----------|-------------------|------------------|---------------------------|
|
||||
| S01 | <test/smoke/search/user-review evidence> | `agent-task/m-<milestone-slug>/...` | <complete.log의 Roadmap Completion/최종 검증으로 남길 근거> |
|
||||
| S01 | <test/smoke/search/user-review evidence> | `agent-task/m-<milestone-slug>/...` | <complete.log에 남길 Spec Completion 근거> |
|
||||
|
||||
## Cross-repo Dependencies
|
||||
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
## Drift Check
|
||||
|
||||
- [ ] Milestone 기능 Task와 Acceptance Scenario가 일치한다.
|
||||
- [ ] Evidence Map이 code-review/complete.log에서 검증 가능하다.
|
||||
- [ ] Evidence Map이 plan/code-review/complete.log에서 검증 가능하다.
|
||||
- [ ] agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
|
||||
- [ ] 사용자 리뷰가 필요한 항목은 `USER_REVIEW.md`에만 남겼다.
|
||||
|
||||
|
|
@ -82,4 +82,4 @@
|
|||
## 작업 컨텍스트
|
||||
|
||||
- 표준선: <기존 구조, 도메인 rule, 플랫폼 관례>
|
||||
- 후속 SDD: <없음 또는 [SDD.md](../<other-milestone-slug>/SDD.md)>
|
||||
- 후속 SDD: <없음 또는 SDD 경로>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
## 검토 대상
|
||||
|
||||
- SDD: [SDD.md](SDD.md)
|
||||
- Milestone: [Milestone 문서](../../../phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- SDD: `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`
|
||||
- Milestone: `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`
|
||||
|
||||
## 사용자 결정 항목
|
||||
|
||||
|
|
|
|||
|
|
@ -1,57 +1,45 @@
|
|||
# 로드맵
|
||||
|
||||
## 고정 실행 순서
|
||||
|
||||
- 전역 Milestone 실행 순서는 [전역 마일스톤 실행 순서](priority-queue.md)를 먼저 확인한다.
|
||||
- Phase는 도메인/책임 영역이며 순차 실행 게이트가 아니다.
|
||||
- Phase 흐름과 상태는 로드맵 구조를 설명하고, 실제 다음 작업 선택은 `priority-queue.md`의 위아래 순서를 우선한다.
|
||||
- `priority-queue.md`는 순서 전용 문서이며, 상태, 목표, 범위, 잠금, 기능, 완료 근거는 각 Milestone 문서를 원본으로 삼는다.
|
||||
- `priority-queue.md` 항목은 Milestone 제목 링크와 식별용 한 줄 설명만 둔다.
|
||||
- `priority-queue.md`는 로드맵 생성 시 함께 만들며, 실행 후보가 없을 때도 문서와 `실행 순서` 섹션은 유지한다.
|
||||
- `priority-queue.md`는 사용자가 순서 조정을 요청한 경우, Milestone archive 시 완료 항목 제거가 필요한 경우, 큐에 있는 Milestone이 폐기, 경로 변경, split/merge, 또는 실행 의미가 바뀔 정도로 수정된 경우에만 재정렬한다.
|
||||
- `priority-queue.md`의 링크가 깨졌으면 활성 Milestone 문서를 기준으로 큐를 재정렬하거나 재생성한다.
|
||||
|
||||
## 전체 목표
|
||||
|
||||
<프로젝트가 최종적으로 달성하려는 결과를 1~3문장으로 작성>
|
||||
|
||||
## Phase 흐름
|
||||
|
||||
Phase는 실행 순서가 아니라 도메인/책임 영역의 구조적 지도다.
|
||||
위에서 아래로 진행된 순서와 예정 흐름을 나타낸다.
|
||||
완료된 Phase도 로드맵에서 제거하지 않고, archive의 Phase 문서로 연결한다.
|
||||
상태 그룹은 완료, 검토중, 진행중, 계획, 스케치 순서로 정리해 각 도메인 축의 성숙도와 정리 상태를 읽기 쉽게 한다.
|
||||
실제 다음 작업 선택은 [전역 마일스톤 실행 순서](priority-queue.md)의 위아래 순서를 우선한다.
|
||||
검토중 또는 진행중 Phase는 계획 Phase보다 위에 두어, 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||
스케치 Phase는 아직 구현 가능한 계획이 아니므로 계획 Phase보다 아래에 둔다.
|
||||
|
||||
- [<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>] <Phase 이름>
|
||||
- 경로: [PHASE.md](phase/<phase-slug>/PHASE.md) 또는 [archive PHASE.md](archive/phase/<phase-slug>/PHASE.md)
|
||||
- 경로: `agent-roadmap/phase/<phase-slug>/PHASE.md` 또는 `agent-roadmap/archive/phase/<phase-slug>/PHASE.md`
|
||||
- 요약: <이 Phase의 목표와 역할 1문장>
|
||||
|
||||
## 로딩 정책
|
||||
|
||||
- 일반 작업에서는 [ROADMAP.md](ROADMAP.md)를 매번 읽지 않는다.
|
||||
- Phase를 가로지르는 다음 작업 후보를 고를 때는 [전역 마일스톤 실행 순서](priority-queue.md)를 먼저 확인한다.
|
||||
- 기능 추가, 구조 변경, 스킬 추가/수정, 문서 구조 변경 작업을 수행할 때는 [current.md](current.md)를 먼저 읽는다.
|
||||
- 일반 작업에서는 `agent-roadmap/ROADMAP.md`를 매번 읽지 않는다.
|
||||
- 기능 추가, 구조 변경, 스킬 추가/수정, 문서 구조 변경 작업을 수행할 때는 `agent-roadmap/current.md`를 먼저 읽는다.
|
||||
- `current.md`는 현재 작업 위치가 아니라 활성 Phase와 활성 Milestone 후보 목록이다.
|
||||
- `current.md`는 브랜치별 로컬 포인터이며 git 추적 대상이 아니다. 로드맵 기반 계획/갱신에서 없으면 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식으로 생성해 사용하고, 읽기 전용 현지점 확인에서는 생성하지 않는다.
|
||||
- `current.md`에는 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
|
||||
- `current.md`의 활성 Phase는 [PHASE.md](phase/<phase-slug>/PHASE.md)를 가리킨다.
|
||||
- `current.md`의 활성 Milestone은 [Milestone 문서](phase/<phase-slug>/milestones/<milestone-slug>.md)를 가리킨다.
|
||||
- `current.md`의 활성 Phase는 `agent-roadmap/phase/<phase-slug>/PHASE.md`를 가리킨다.
|
||||
- `current.md`의 활성 Milestone은 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`를 가리킨다.
|
||||
- `current.md`는 `agent-roadmap/archive/**` 경로를 활성 항목으로 포함하지 않는다.
|
||||
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 활성 Phase와 Milestone 문서를 같은 세션에서 1회 읽는다.
|
||||
- 활성 Phase 또는 Milestone 밖의 작업이면 이 문서의 Phase 흐름을 확인하고 범위 충돌을 보고한다. 제품/범위 결정이 필요하면 대상 Milestone의 `구현 잠금 > 결정 필요` 또는 SDD `USER_REVIEW.md`로 분리한다.
|
||||
- 이 문서는 로드맵 생성/갱신, Phase 전환, Phase 추가/수정, 전체 구조 변경 요청이 있을 때만 읽는다.
|
||||
- 상세 작업은 각 Milestone 문서의 `기능`으로 관리한다. 검증이 필요한 기능만 같은 Task 안에 `검증:`으로 통합한다.
|
||||
- 큰 Milestone의 설계 게이트는 [SDD.md](sdd/<phase-slug>/<milestone-slug>/SDD.md)에 두고, Milestone `구현 잠금`의 SDD 조건과 연결한다.
|
||||
- SDD 사용자 리뷰가 필요하면 [USER_REVIEW.md](sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md)로 남기며, 해결 후 `user_review_N.log`로 보존한다.
|
||||
- 큰 Milestone의 설계 게이트는 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`에 두고, Milestone `구현 잠금`의 SDD 조건과 연결한다.
|
||||
- SDD 사용자 리뷰가 필요하면 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md`로 남기며, 해결 후 `user_review_N.log`로 보존한다.
|
||||
- `[스케치]` Phase/Milestone은 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태이며 구현 계획 생성 대상이 아니다.
|
||||
- `[스케치]` 항목은 `승격 조건`을 정리해 `[계획]`으로 전환한 뒤 구현 계획을 만든다.
|
||||
- 모든 기능 Task와 Task 안에 명시된 검증이 충족되고 `구현 잠금`이 해제된 Milestone은 먼저 `[검토중]`으로 두고, 완료 근거와 archive 조건이 정리되면 `[완료]`로 전환한다.
|
||||
- 완료된 Phase는 [archive PHASE.md](archive/phase/<phase-slug>/PHASE.md)로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
|
||||
- 진행중 Phase 안에서 완료된 Milestone은 활성 Phase 문서에 짧은 링크를 남기고, 상세 문서는 [archive milestones](archive/phase/<phase-slug>/milestones/)로 이동한다.
|
||||
- 완료된 Phase는 `agent-roadmap/archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
|
||||
- 진행중 Phase 안에서 완료된 Milestone은 활성 Phase 문서에 짧은 링크를 남기고, 상세 문서는 `agent-roadmap/archive/phase/<phase-slug>/milestones/`로 이동한다.
|
||||
- archive `PHASE.md`는 Phase 자체가 완료 또는 폐기될 때만 만들며, 진행중 Phase의 완료 Milestone만 archive된 경우 archive Phase 디렉터리에 `milestones/`만 있을 수 있다.
|
||||
- `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라가서 읽는다.
|
||||
- 아카이브된 Phase/Milestone 문서는 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.
|
||||
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나, 상태가 `잠금`이거나, 미완료 `결정 필요` 항목이 있으면 코드 구현, `agent-task` 구현 계획 생성, 세부 API/파일 구조 확정을 시작하지 않는다.
|
||||
- 선택된 Milestone에 `SDD: 필요`가 있으면 SDD 상태가 `[승인됨]`이고 SDD 잠금이 해제되었으며 SDD 사용자 리뷰가 없어야 구현 계획을 만들 수 있다.
|
||||
- 잠금 상태의 Milestone에서는 "현재 요청과 직접 관련 없음"을 이유로 실구현 계획이나 코드 구현을 진행하지 않는다. 먼저 roadmap-only 갱신으로 범위 제외, 후속 Milestone, 작업 컨텍스트 이동 또는 잠금 해제를 문서화한다.
|
||||
- 잠금 상태의 Milestone에서는 "현재 요청과 직접 관련 없음"을 이유로 실구현 plan이나 코드 구현을 진행하지 않는다. 먼저 roadmap-only 갱신으로 범위 제외, 후속 Milestone, 작업 컨텍스트 이동 또는 잠금 해제를 문서화한다.
|
||||
- Milestone 전체에서 에이전트가 확정할 수 없는 결정 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `구현 잠금` 상태를 `해제`로 둔다.
|
||||
|
|
|
|||
102
agent-ops/skills/common/agent-contract/SKILL.md
Normal file
102
agent-ops/skills/common/agent-contract/SKILL.md
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
---
|
||||
name: agent-contract
|
||||
version: 1.0.0
|
||||
description: agent-contract index와 제공/소비 계약 문서를 생성하거나 갱신한다.
|
||||
---
|
||||
|
||||
# agent-contract
|
||||
|
||||
## 목적
|
||||
|
||||
프로젝트 간 API, 런타임 호출, 요청/응답 스키마 계약을 `agent-contract/` 구조로 관리한다.
|
||||
계약 원문을 한 곳에 두고, README/docs/rules에는 라우팅 포인터만 남긴다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 외부 프로젝트가 참조할 API 또는 런타임 계약을 생성하거나 갱신할 때
|
||||
- 다른 프로젝트의 계약을 소비 계약으로 등록할 때
|
||||
- `agent-contract/index.md`의 제공/소비 계약 라우팅을 정리할 때
|
||||
- 계약 원문을 수정한 뒤 index, README, docs 포인터와 정합성을 확인할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `contract-id`: 계약 식별자, 예: `iop.openai-compatible-api` (필수)
|
||||
- `mode`: `provided` 또는 `consumed` (필수)
|
||||
- `contract-path`: 계약 원문 경로 또는 외부 source 경로 (필수)
|
||||
- `trigger-conditions`: 계약 문서를 읽어야 하는 조건 목록 (필수)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-contract/index.md`가 있는지 확인하고, 없으면 최초 생성 대상으로 본다.
|
||||
- [ ] 동일 `contract-id`가 이미 제공 또는 소비 계약에 있는지 확인한다.
|
||||
- [ ] 계약 원문이 `docs/`, `README`, `rules.md`에 중복 복제되어 있지 않은지 확인한다.
|
||||
- [ ] agent-ops 공통 규칙에는 특정 계약명이 아니라 `agent-contract/index.md` 조건부 진입 규칙만 있는지 확인한다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **초기 구조 확인**
|
||||
- `agent-contract/index.md`가 없으면 생성한다.
|
||||
- `agent-contract/provided/`가 없으면 생성한다.
|
||||
- 소비 계약 원문을 저장하지 않는 한 `agent-contract/consumed/`는 만들지 않는다.
|
||||
- index에는 읽기 규칙, 제공 계약 표, 소비 계약 표를 둔다.
|
||||
|
||||
2. **계약 위치 결정**
|
||||
- 제공 계약은 `agent-contract/provided/<contract-name>.md`에 둔다.
|
||||
- 소비 계약은 `agent-contract/index.md`의 소비 계약 표에 외부 source만 둔다.
|
||||
- 소비 계약 원문을 현재 프로젝트에 복제하지 않는다.
|
||||
|
||||
3. **index 갱신**
|
||||
- `agent-contract/index.md`의 읽기 규칙을 유지한다.
|
||||
- 제공 계약 표는 `id`, `읽는 조건`, `path` 열을 유지한다.
|
||||
- 소비 계약 표는 `id`, `읽는 조건`, `source` 열을 유지한다.
|
||||
- 제공 계약 또는 소비 계약 표에 `id`, 읽는 조건, 경로를 추가하거나 갱신한다.
|
||||
- 매칭 조건은 agent가 판단할 수 있는 API 이름, field 이름, runtime 이름, protocol 이름을 포함한다.
|
||||
|
||||
4. **계약 원문 갱신**
|
||||
- 계약 원문에는 범위, 최소 요청/응답 형태, 필드 의미, 금지 사항, 구현 메모를 둔다.
|
||||
- 사람용 설명 문서에는 계약 원문을 복제하지 않고 링크만 둔다.
|
||||
- 기존 계약을 수정할 때는 index의 읽는 조건과 path/source가 수정 후 계약 원문과 여전히 맞는지 확인한다.
|
||||
|
||||
5. **읽기 흐름 확인**
|
||||
- 계약 확인 작업은 common rule이 `agent-contract/index.md`를 조건부로 읽고, index가 매칭 계약 원문으로 라우팅한다.
|
||||
- 읽기 전용 작업에서는 계약 원문이나 index를 수정하지 않는다.
|
||||
- 매칭 계약이 없으면 계약을 추정하지 않고 사용자에게 확인한다.
|
||||
|
||||
6. **라우팅 문서 갱신**
|
||||
- README/docs/rules에는 계약 원문 경로만 남긴다.
|
||||
- common rule에는 특정 계약 id나 프로젝트명을 넣지 않는다.
|
||||
- project rule에는 해당 프로젝트 고유 코드/도메인 규칙만 두고 agent-contract 공통 라우팅을 반복하지 않는다.
|
||||
|
||||
7. **결과 보고**
|
||||
- 변경한 계약 index와 원문 경로를 보고한다.
|
||||
- 중복 제거한 문서와 남긴 포인터를 보고한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `agent-contract/index.md`가 계약 id와 경로를 포함하는가
|
||||
- [ ] `agent-contract/index.md`가 없던 프로젝트에서는 읽기 규칙, 제공 계약 표, 소비 계약 표가 생성되었는가
|
||||
- [ ] 제공 계약 원문이 `agent-contract/provided/` 아래에 있는가
|
||||
- [ ] 소비 계약 원문을 복제하지 않았는가
|
||||
- [ ] 소비 계약은 `source`만 가리키는가
|
||||
- [ ] 수정된 계약의 index 조건과 path/source가 계약 원문과 일치하는가
|
||||
- [ ] README/docs/rules가 계약 본문을 반복하지 않고 원문 경로만 가리키는가
|
||||
- [ ] common rule에 특정 계약명이 들어가지 않았는가
|
||||
- [ ] project rule에 agent-contract 공통 라우팅을 반복하지 않았는가
|
||||
- 검증 실패 시: 계약 원문을 한 곳으로 모으고 나머지 문서는 포인터로 축소한다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```text
|
||||
계약 정리 완료
|
||||
|
||||
- index: agent-contract/index.md
|
||||
- contract: agent-contract/provided/<contract-name>.md
|
||||
- pointers: <갱신한 README/docs/rules 경로>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 같은 계약 본문을 `docs/`, `README`, `rules.md`에 복제하지 않는다.
|
||||
- common rule에 특정 계약 id, 특정 프로젝트명, 특정 API 이름을 추가하지 않는다.
|
||||
- 소비 계약 원문을 현재 프로젝트에 복사하지 않는다.
|
||||
- 계약과 무관한 코드나 로드맵 상태를 함께 수정하지 않는다.
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: analyze-roadmap-position
|
||||
version: 1.13.0
|
||||
description: "여러 레포를 전환할 때 코드/git 분석 없이 priority-queue 실행 순서와 ROADMAP > Phase > Milestone > current 현지점을 링크 달린 흐름 목록으로 빠르게 보여주는 읽기 전용 스킬"
|
||||
version: 1.12.0
|
||||
description: "여러 레포를 전환할 때 코드/git 분석 없이 전체 ROADMAP > Phase > Milestone > current 현지점을 링크 달린 breadcrumb와 흐름 목록으로 빠르게 보여주는 읽기 전용 스킬"
|
||||
---
|
||||
|
||||
# 로드맵 현지점
|
||||
|
|
@ -9,8 +9,7 @@ description: "여러 레포를 전환할 때 코드/git 분석 없이 priority-q
|
|||
## 목적
|
||||
|
||||
여러 레포를 병렬 운용하다가 돌아왔을 때, 현재 작업이 전체 로드맵의 어느 Phase와 Milestone에 있는지 빠르게 보여준다.
|
||||
기본 출력은 전역 Milestone 실행 순서, `로드맵 > Phase > Milestone` breadcrumb, 전체 Phase 흐름, 현재 Phase의 Milestone 흐름이다.
|
||||
Phase 흐름은 실행 순서가 아니라 도메인/책임 영역의 구조적 지도이며, 다음 작업 후보는 `priority-queue.md` 순서를 우선한다.
|
||||
기본 출력은 `로드맵 > Phase > Milestone` breadcrumb와 전체 Phase 흐름, 현재 Phase의 Milestone 흐름이다.
|
||||
코드 진행도 감사, git diff 분석, 테스트 근거 확인, 남은 작업 정밀 판정은 기본 책임이 아니다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
|
@ -18,7 +17,6 @@ Phase 흐름은 실행 순서가 아니라 도메인/책임 영역의 구조적
|
|||
- 사용자가 "지금 작업이 뭐지?", "현재 작업이 뭐야?", "어디까지 했지?"라고 물을 때
|
||||
- 사용자가 레포 전환 직후 로드맵상 현재 좌표를 빠르게 알고 싶어 할 때
|
||||
- "로드맵상 현 위치", "현재 마일스톤 위치", "current 기준 breadcrumb"를 요청할 때
|
||||
- Phase를 가로지르는 다음 작업 후보 순서를 함께 보고 싶어 할 때
|
||||
- 구현 시작 전 전체 Roadmap > Phase > Milestone 관계만 확인하면 될 때
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
|
@ -26,11 +24,10 @@ Phase 흐름은 실행 순서가 아니라 도메인/책임 영역의 구조적
|
|||
- [ ] `agent-ops/skills/common/_templates/roadmap-position-report-template.md`를 읽어 최신 답변 템플릿 확인
|
||||
- [ ] `agent-roadmap/` 디렉터리 존재 여부 확인
|
||||
- [ ] 로컬 `agent-roadmap/current.md` 존재 여부 확인
|
||||
- [ ] `agent-roadmap/priority-queue.md`가 있으면 `실행 순서` 항목 확인
|
||||
- [ ] 로드맵이 있으면 `ROADMAP.md`의 `Phase 흐름`을 확인
|
||||
- [ ] 로컬 `current.md`의 활성 Phase와 활성 Milestone 이름, 상태, 경로 확인
|
||||
- [ ] 활성 Phase 문서의 `Milestone 흐름` 확인
|
||||
- [ ] 활성 Milestone 문서의 제목, `목표`, `상태`, `구현 잠금`의 SDD 문서 링크/경로만 확인
|
||||
- [ ] 활성 Milestone 문서의 제목, `목표`, `상태`, `구현 잠금`의 SDD 문서 경로만 확인
|
||||
|
||||
## 실행 절차
|
||||
|
||||
|
|
@ -38,54 +35,31 @@ Phase 흐름은 실행 순서가 아니라 도메인/책임 영역의 구조적
|
|||
- 없으면 로드맵 없음으로 짧게 보고하고 멈춘다.
|
||||
2. `agent-ops/skills/common/_templates/roadmap-position-report-template.md`를 읽는다.
|
||||
3. 로컬 `agent-roadmap/current.md`를 확인한다.
|
||||
- 없으면 로컬 current 없음으로 보고하고, `priority-queue.md`가 있으면 전역 실행 순서와 `ROADMAP.md`의 `Phase 흐름`을 보여준다.
|
||||
4. `agent-roadmap/priority-queue.md`가 있으면 `실행 순서` 항목을 읽어 전역 Milestone 실행 순서 목록을 만든다.
|
||||
- 각 항목은 순번, Milestone 제목 링크, 식별용 한 줄 설명만 남긴다.
|
||||
- 상태, 잠금, 목표, 기능 Task는 각 Milestone 문서 원본을 읽기 전에는 추정하지 않는다.
|
||||
- archive 링크가 있거나 링크가 깨진 것으로 보이면 `큐 정리 필요`로 표시하고 archive 문서는 읽지 않는다.
|
||||
- 파일이 없으면 `전역 실행 순서: 없음`으로 출력한다.
|
||||
5. `ROADMAP.md`의 `Phase 흐름`을 읽어 전체 Phase 목록을 만든다.
|
||||
- 없으면 로컬 current 없음으로 보고하고, `ROADMAP.md`가 있으면 `Phase 흐름`만 보여준다.
|
||||
4. `ROADMAP.md`의 `Phase 흐름`을 읽어 전체 Phase 목록을 만든다.
|
||||
- 각 Phase는 상태, 이름, 링크만 남긴다.
|
||||
- current의 활성 Phase와 일치하는 항목에 `← 현재` 표시를 붙인다.
|
||||
- 완료된 Phase가 archive 경로를 가리켜도 링크만 표시하고 archive 문서는 읽지 않는다.
|
||||
6. current의 활성 Phase 경로를 열고 `Milestone 흐름`을 읽는다.
|
||||
5. current의 활성 Phase 경로를 열고 `Milestone 흐름`을 읽는다.
|
||||
- 각 Milestone은 상태, 이름, 링크만 남긴다.
|
||||
- current의 활성 Milestone과 일치하는 항목에 `← 현재 후보` 표시를 붙인다.
|
||||
7. current의 활성 Milestone 문서를 열고 제목, `목표`, `상태`, `구현 잠금`의 SDD 문서 링크/경로만 읽는다.
|
||||
- `SDD 문서` 링크/경로가 있고 해당 `SDD.md` 파일이 존재하면 Milestone 아래에 `SDD: SDD_LINK`로 출력한다.
|
||||
- `SDD 문서` 링크/경로는 있으나 해당 파일이 없으면 Milestone 아래에 `SDD: SDD_LINK (파일 없음)` 형식으로 출력한다.
|
||||
- `SDD 문서` 링크/경로가 없거나 `SDD: 불필요`이면 Milestone 아래에 `SDD: 없음`으로 출력한다.
|
||||
- `SDD.md`와 같은 디렉터리에 `USER_REVIEW.md`가 있으면 Milestone 아래에 `사용자 리뷰: USER_REVIEW_LINK`로 출력하고, 없으면 `사용자 리뷰: 없음`으로 출력한다.
|
||||
6. current의 활성 Milestone 문서를 열고 제목, `목표`, `상태`, `구현 잠금`의 SDD 문서 경로만 읽는다.
|
||||
- `SDD 문서` 경로가 있고 해당 `SDD.md` 파일이 존재하면 Milestone 아래에 `SDD: [SDD.md](<sdd-path>)`로 출력한다.
|
||||
- `SDD 문서` 경로는 있으나 해당 파일이 없으면 Milestone 아래에 `SDD: 경로만 있음: <sdd-path>` 형식으로 출력한다.
|
||||
- `SDD 문서` 경로가 없거나 `SDD: 불필요`이면 Milestone 아래에 `SDD: 없음`으로 출력한다.
|
||||
- `SDD.md`와 같은 디렉터리에 `USER_REVIEW.md`가 있으면 Milestone 아래에 `사용자 리뷰: [USER_REVIEW.md](<user-review-path>)`로 출력하고, 없으면 `사용자 리뷰: 없음`으로 출력한다.
|
||||
- SDD 상태, 잠금, 승인 여부를 역할 태그나 상태 요약으로 출력하지 않는다. 필요한 독자는 출력된 SDD 링크를 열어 확인하게 한다.
|
||||
- SDD 본문은 읽지 않는다.
|
||||
- `기능`, `완료 리뷰`, `범위 제외`, `작업 컨텍스트`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||
8. 결과를 템플릿의 섹션 순서와 필드 의미에 맞춰 출력한다. 템플릿의 placeholder, 선택지 표기, HTML 주석은 출력하지 않는다.
|
||||
|
||||
## 링크 정규화
|
||||
|
||||
- 출력 링크는 채팅 결과이므로 항상 repo root 기준 상대경로를 target으로 쓴다. 예: `[PHASE.md](agent-roadmap/phase/example-phase/PHASE.md)`.
|
||||
- `current.md`, `ROADMAP.md`, `PHASE.md`, Milestone 문서에서 읽은 Markdown 링크는 그대로 복사하지 않는다. 반드시 링크가 들어 있던 원본 파일 위치 기준으로 target을 해석한 뒤 repo root 기준 상대경로로 다시 쓴다.
|
||||
- 예: `agent-roadmap/current.md`의 `[PHASE.md](phase/foo/PHASE.md)`는 출력에서 `[PHASE.md](agent-roadmap/phase/foo/PHASE.md)`로 쓴다.
|
||||
- 예: `agent-roadmap/priority-queue.md`의 `[Milestone](phase/foo/milestones/bar.md)`는 출력에서 `[Milestone](agent-roadmap/phase/foo/milestones/bar.md)`로 쓴다.
|
||||
- 예: `agent-roadmap/phase/foo/PHASE.md`의 `[Milestone](milestones/bar.md)`는 출력에서 `[Milestone](agent-roadmap/phase/foo/milestones/bar.md)`로 쓴다.
|
||||
- 예: `agent-roadmap/phase/foo/PHASE.md`의 `[Archive](../../archive/phase/foo/milestones/bar.md)`는 출력에서 `[Archive](agent-roadmap/archive/phase/foo/milestones/bar.md)`로 쓴다. archive 문서는 읽지 않고 링크만 표시한다.
|
||||
- 링크 label은 사람이 이해할 수 있는 이름을 쓰고, target에는 `<phase-path>`, `<milestone-path>`, `<sdd-path>`, `<user-review-path>`, `<phase-slug>`, `<milestone-slug>` 또는 `{PHASE_LINK}` 같은 placeholder를 남기지 않는다.
|
||||
- 템플릿의 `{PHASE_LINK}`, `{MILESTONE_LINK}`, `{SDD_LINK}`, `{USER_REVIEW_LINK}`는 실제 `[제목](repo-root-relative-path)` Markdown 링크로 치환한다.
|
||||
- 대상 경로를 확정할 수 없으면 Markdown 링크를 만들지 말고 `링크 없음: <사유>`로 표시한다. raw path만 단독으로 출력하거나 깨진 링크를 만들지 않는다.
|
||||
- 출력 전 자체 점검으로 `](<`, `](...<...>)`, `{PHASE_LINK}` 같은 placeholder 링크가 남아 있지 않은지 확인한다.
|
||||
7. 결과를 템플릿 형식 그대로 출력한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `roadmap-position-report-template.md`의 출력 구조를 유지했는가
|
||||
- [ ] `priority-queue.md`가 있으면 `실행 순서` 항목을 표시했고, 없으면 `전역 실행 순서: 없음`으로 표시했는가
|
||||
- [ ] 로컬 `current.md`, `priority-queue.md`, `ROADMAP.md`, 활성 `PHASE.md`, 활성 Milestone의 제목/목표/상태/SDD 문서 링크/경로만 기본으로 읽었는가
|
||||
- [ ] 로컬 `current.md`, `ROADMAP.md`, 활성 `PHASE.md`, 활성 Milestone의 제목/목표/상태/SDD 문서 경로만 기본으로 읽었는가
|
||||
- [ ] 현재 후보 Milestone 아래에 SDD와 사용자 리뷰를 링크 또는 `없음`으로 출력했는가
|
||||
- [ ] Phase, Milestone, SDD, 사용자 리뷰 등 모든 문서 포인터가 raw path만 남지 않고 Markdown 링크로 출력되었는가
|
||||
- [ ] 문서에서 읽은 file-location-relative 링크를 채팅 출력용 repo root 상대 링크로 정규화했는가
|
||||
- [ ] 출력에 placeholder 링크 target이나 `(제목)[링크]`처럼 뒤집힌 Markdown 문법이 남지 않았는가
|
||||
- [ ] SDD 상태, 잠금, 승인 여부를 역할 태그나 상태 요약으로 출력하지 않았는가
|
||||
- [ ] 완료 또는 archive Phase/Milestone은 링크만 표시하고 archive 문서를 읽지 않았는가
|
||||
- [ ] Phase 흐름을 실행 순서로 설명하지 않고, 전역 실행 순서는 별도 섹션으로 출력했는가
|
||||
- [ ] current가 여러 Milestone을 가리키면 모두 `현재 후보`로 표시했는가
|
||||
- [ ] 코드 파일, 테스트 파일, `git status`, `git diff`를 기본 동작에서 읽지 않았는가
|
||||
- [ ] 로드맵 파일을 수정하지 않았는가
|
||||
|
|
@ -93,16 +67,12 @@ Phase 흐름은 실행 순서가 아니라 도메인/책임 영역의 구조적
|
|||
## 출력 형식
|
||||
|
||||
- 템플릿 경로: `agent-ops/skills/common/_templates/roadmap-position-report-template.md`
|
||||
- 템플릿의 섹션 순서와 필드 의미를 따른다. placeholder 줄을 그대로 복사하지 말고, 실제 항목 수에 맞춰 행을 생성한다.
|
||||
- 출력에는 `<phase-path>`, `<milestone-path>`, `<sdd-path>`, `<user-review-path>`, `{PHASE_LINK}`, `{MILESTONE_LINK}`, `{SDD_LINK}`, `{USER_REVIEW_LINK}` placeholder를 그대로 남기지 않고 실제 repo root 기준 상대 링크 target으로 치환한다.
|
||||
- 템플릿을 그대로 복사해 placeholder를 채운다.
|
||||
- 섹션 제목과 필드명을 임의로 번역, 축약, 삭제하지 않는다.
|
||||
- current가 여러 Milestone을 가리키면 breadcrumb와 Milestone 흐름에 모두 표시한다.
|
||||
- 현재 후보의 역할 태그는 `선행 스케치`, `다음 구현 계획`, `검토 후보`, `보류 후보`처럼 짧게 쓰되 SDD 상태를 역할 태그에 넣지 않는다.
|
||||
- 현재 후보에 `SDD 문서` 링크/경로가 있으면 Milestone 아래에 SDD 링크를 배치한다. `USER_REVIEW.md`가 있으면 그 링크도 SDD 아래에 배치한다.
|
||||
- 문서 포인터는 항상 `[표시 제목](상대경로)` Markdown 링크로 출력한다. 파일이 없어도 raw path만 쓰지 말고 `SDD_LINK (파일 없음)`처럼 링크와 상태를 함께 쓴다.
|
||||
- `전역 마일스톤 실행 순서`에는 `priority-queue.md`의 항목 순서를 그대로 출력한다. Milestone 상태나 잠금은 각 Milestone 문서를 읽지 않았다면 출력하지 않는다.
|
||||
- 현재 후보에 `SDD 문서` 경로가 있으면 Milestone 아래에 SDD 링크를 배치한다. `USER_REVIEW.md`가 있으면 그 링크도 SDD 아래에 배치한다.
|
||||
- 로드맵이 없는 프로젝트에서는 로드맵 없음으로 짧게 보고하고 템플릿을 억지로 채우지 않는다.
|
||||
- 로컬 `current.md`가 없으면 `local current: 없음`으로 출력하고, `[current.md](agent-roadmap/current.md)` 링크를 만들지 않는다.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ Milestone identity 역검색과 개별 lock 판별은 `agent-ops/bin/roadmap-dep
|
|||
- stdout `false`와 exit code `1`은 아직 충족되지 않은 의존 조건이 있음을 보고한다.
|
||||
- exit code `2`는 설정 오류, 입력 오류, 필수 필드 누락, 파싱 오류로 보고한다.
|
||||
- `rely-on` 방향에서 대상 Milestone이 `[검토중]` 또는 `[완료]`인데 status가 `disable`이면 `update-roadmap` 동기화가 필요한 stale lock으로 보고한다. 이 스킬은 status를 바꾸지 않는다.
|
||||
- 사용자-facing 결과에 대상 Milestone 문서를 표시할 수 있으면 identity raw 값만 쓰지 말고 `[Milestone 문서](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)` 링크를 함께 보고한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
|
|
@ -69,7 +68,6 @@ Milestone identity 역검색과 개별 lock 판별은 `agent-ops/bin/roadmap-dep
|
|||
- [ ] lock id가 없을 때 대상 Milestone을 `locked`와 `rely-on.target` 양쪽에서 찾았는가
|
||||
- [ ] `locks.yaml`이 없는 경우 `false`가 아니라 `error`로 보고했는가
|
||||
- [ ] 이 스킬이 `locks.yaml`이나 roadmap 문서를 수정하지 않았는가
|
||||
- [ ] 대상 Milestone 문서를 표시할 수 있으면 Markdown 링크로 함께 보고했는가
|
||||
- 검증 실패 시: 오류 메시지와 사용한 `lock-id`, `locks-file` 경로를 보고하고 멈춘다.
|
||||
|
||||
## 출력 형식
|
||||
|
|
@ -78,7 +76,6 @@ Milestone identity 역검색과 개별 lock 판별은 `agent-ops/bin/roadmap-dep
|
|||
## 의존성 판별 결과
|
||||
|
||||
- target-milestone: `<identity | 해당 없음>`
|
||||
- target-document: <[Milestone 문서](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md) | 해당 없음>
|
||||
- direction: `<locked | rely-on | both>`
|
||||
- locks-file: `<locks-file>`
|
||||
- 결과: `<true | false | error | no-lock>`
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
name: code-review
|
||||
description: Use for active task review requests such as 리뷰 진행해, 리뷰해줘, 코드 리뷰해줘, code review, CODE_REVIEW.md, USER_REVIEW.md resolution, or 리뷰 루프. Review the active PLAN/CODE_REVIEW pair, append PASS/WARN/FAIL, archive both active files, and create the required next state. PASS writes complete.log and moves the task to archive; WARN/FAIL must invoke the plan skill, which reruns finalize-task-routing before writing the next pair, unless the review-agent-owned user-review gate requires USER_REVIEW.md.
|
||||
description: Use for active task review requests such as 리뷰 진행해, 리뷰해줘, 코드 리뷰해줘, code review, CODE_REVIEW.md, USER_REVIEW.md resolution, implementation-time 사용자 리뷰 요청, or 리뷰 루프. Review the active PLAN/CODE_REVIEW pair, append PASS/WARN/FAIL, archive both active files, and create the required next state: PASS writes complete.log and moves the task to archive; WARN/FAIL writes follow-up PLAN/CODE_REVIEW files unless the user-review gate requires USER_REVIEW.md; user review resolution that closes the task writes complete.log before archive. Never stop after verdict append or user-review closure without writing the required next-state artifact.
|
||||
---
|
||||
|
||||
# Code Review
|
||||
|
|
@ -10,43 +10,43 @@ description: Use for active task review requests such as 리뷰 진행해, 리
|
|||
Review the implementation phase of the plan-code-review loop:
|
||||
|
||||
```text
|
||||
plan skill -> finalize-task-routing -> implementation -> code-review skill
|
||||
^ |
|
||||
+----- WARN/FAIL: invoke plan skill with raw findings -+
|
||||
plan skill -> implementation -> code-review skill
|
||||
^ |
|
||||
+----- issues found: new routed plan/review files
|
||||
```
|
||||
|
||||
Implementation agents never decide or request user review. They record implementation, verification, deviation, and blocker evidence in implementation-owned review fields. The official code-review agent alone evaluates the selected Milestone state and, when the review-agent-owned gate is justified, writes `USER_REVIEW.md` from `agent-ops/skills/common/code-review/templates/user-review-template.md`.
|
||||
Implementation may stop early by filling the active review stub's `사용자 리뷰 요청` section from `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`. This is the only implementation-time decision-stop path, and it is valid only for a selected SDD decision or a selected Milestone `구현 잠금 > 결정 필요` item. Implementation must not ask the user directly, present choices in chat, or call a user-input tool such as `request_user_input`. Code-review validates that request and, when justified, writes `USER_REVIEW.md` from `agent-ops/skills/common/code-review/templates/user-review-template.md`.
|
||||
|
||||
## Core Loop Rules
|
||||
|
||||
- Trigger: Korean or English active-task review requests, including `리뷰 진행해` and `리뷰해줘`, must use this skill when an active `CODE_REVIEW-*-G??.md` or `USER_REVIEW.md` exists under `agent-task/*/` or `agent-task/*/*/`, excluding `agent-task/archive/**`.
|
||||
- Finalize every selected active state: for `CODE_REVIEW-*-G??.md`, append one verdict, prepare the required next state, archive the active review and plan files, then materialize exactly one next state; for `USER_REVIEW.md` completion, update the stop state, write `complete.log`, and archive the task.
|
||||
- Next state: `PASS` writes `complete.log` and moves the task under `agent-task/archive/YYYY/MM/`; if the task group is `m-<milestone-slug>`, report completion metadata for the runtime event. `WARN` or `FAIL` normally invokes `agent-ops/skills/common/plan/SKILL.md`, which must run `finalize-task-routing` before writing the next active pair; if the user-review gate triggers, write `USER_REVIEW.md` instead. A completed `USER_REVIEW.md` uses the same terminal `complete.log` and archive path as `PASS`.
|
||||
- The user-review gate is review-agent-owned and triggers only when current repository evidence proves that a concrete selected Milestone `구현 잠금 > 결정 필요` item blocks the next safe implementation step. Generic status fields or blocker text written by implementation are never a user-review request.
|
||||
- Finalize every selected active state: for `CODE_REVIEW-*-G??.md`, append one verdict, archive the active review and plan files, then create exactly one next state; for `USER_REVIEW.md` completion, update the stop state, write `complete.log`, and archive the task. Do not report before finalization is complete.
|
||||
- Next state: `PASS` writes `complete.log` and moves the task under `agent-task/archive/YYYY/MM/`; if the task group is `m-<milestone-slug>`, report completion metadata for the runtime event. `WARN` or `FAIL` normally writes the next active `PLAN-{build_lane}-GNN.md` and `CODE_REVIEW-{review_lane}-GNN.md`; if the user-review gate triggers, write `USER_REVIEW.md` instead. A completed `USER_REVIEW.md` uses the same terminal `complete.log` and archive path as `PASS`.
|
||||
- A filled implementation-owned `사용자 리뷰 요청` is a review input, not a next state by itself. The user-review gate triggers only when the request is tied to a concrete SDD decision or selected Milestone `구현 잠금 > 결정 필요` item. If it is vague, unsupported, repo-fixable, about external environment/secret/service setup, a generic scope conflict, loop exhaustion, or only missing evidence that a follow-up agent can produce by rerunning commands or collecting artifacts, write a normal WARN/FAIL follow-up plan instead.
|
||||
- Do not replace `USER_REVIEW.md` with an inline user question. When the user-review gate triggers, write the file-based stop state and report its path.
|
||||
- Do not ask for confirmation before WARN/FAIL follow-up files. If the user-review gate triggers, write `USER_REVIEW.md`; otherwise invoke the plan skill with the current raw findings and let it write the smallest concrete follow-up after fresh routing.
|
||||
- Recovery: if a prior turn appended a verdict without archive or next-state files, do not append another verdict; resume Step 5 preparation/archive from that verdict. If exactly one member of the pair was archived after both archive destinations had been preflighted, verify the archived member and remaining source/destination, finish that archive, then use the post-archive recovery below. If both logs exist with a verdict but the required next state is absent, reconstruct it from those exact logs: PASS resumes `complete.log`; WARN/FAIL reruns the plan skill in `write` mode with raw archived findings and `isolated-reassessment`; a valid user-review gate rerenders `USER_REVIEW.md`. If a prior turn resolved `USER_REVIEW.md` without `complete.log`, resume at the matching finalization step.
|
||||
- Do not ask for confirmation before WARN/FAIL follow-up files. If the user-review gate triggers, write `USER_REVIEW.md`; otherwise, if details are uncertain, write the smallest concrete follow-up plan with file references and verification commands.
|
||||
- Recovery: if a prior turn appended a verdict without archive or next-state files, or resolved `USER_REVIEW.md` without `complete.log`, resume at the matching finalization step and finish the missing artifacts first.
|
||||
|
||||
## User Review Gate
|
||||
|
||||
`USER_REVIEW.md` is a loop stop state only for selected Milestone lock decisions. Default to a normal WARN/FAIL follow-up; the gate requires positive evidence that the blocker is already represented, or must be represented, as a Milestone `구현 잠금 > 결정 필요` item.
|
||||
`USER_REVIEW.md` is a loop stop state only for SDD decisions or selected Milestone lock decisions. Default to a normal WARN/FAIL follow-up; the gate requires positive evidence that the blocker is already represented, or must be represented, as an SDD decision or Milestone `구현 잠금 > 결정 필요` item.
|
||||
|
||||
- Compute `review-number` as `count(agent-task/{task_name}/code_review_*.log) + 1` before archiving the active review.
|
||||
- Repeated `WARN`/`FAIL`, loop exhaustion, missing verification evidence, and test environment blockers do not trigger `USER_REVIEW.md` by themselves. Invoke the plan skill for a narrower follow-up or report the non-roadmap blocker as verification evidence that remains unresolved.
|
||||
- Resolve the selected Milestone from `Roadmap Targets` or another exact active Milestone path already fixed by the task. Read its current `구현 잠금 > 결정 필요` items and independently determine whether one exact unresolved decision blocks the next safe implementation step.
|
||||
- External environment/secret/service setup, unsupported device, generic scope conflict, agent execution limits, missing handoff evidence, incomplete verification records, arbitrary `상태` text, or anything not tied to that exact Milestone lock never triggers the gate. Archive the review and invoke the plan skill for a normal WARN/FAIL follow-up when implementation can continue, or report the non-user-review blocker.
|
||||
- `USER_REVIEW.md` is created from `agent-ops/skills/common/code-review/templates/user-review-template.md`, filled with the archived loop history, current archived plan/review paths, verdict, loop count, blocking evidence, connection target, and the exact Milestone decision item.
|
||||
- Repeated `WARN`/`FAIL`, loop exhaustion, missing verification evidence, and test environment blockers do not trigger `USER_REVIEW.md` by themselves. Write a narrower follow-up plan or report the non-roadmap blocker as verification evidence that remains unresolved.
|
||||
- If the active review file has a filled `사용자 리뷰 요청` with `상태` other than `없음`, validate that `사유 유형` is `sdd-decision` or `milestone-lock`, that `연결 대상` points to the selected SDD or Milestone, and that the requested decision matches an SDD decision or Milestone `구현 잠금 > 결정 필요` item.
|
||||
- If the filled request is about external environment/secret/service setup, unsupported device, generic scope conflict, agent execution limits, missing handoff evidence, incomplete verification records, or anything not tied to SDD/Milestone lock, do not write `USER_REVIEW.md`; archive the review and write a normal WARN/FAIL follow-up plan when implementation can continue, or report the blocker without asking the user.
|
||||
- `USER_REVIEW.md` is created from `agent-ops/skills/common/code-review/templates/user-review-template.md`, filled with the archived loop history, current archived plan/review paths, verdict, loop count, blocking evidence, connection target, and the exact SDD/Milestone decision item.
|
||||
|
||||
## User Review Resolution
|
||||
|
||||
When an active `USER_REVIEW.md` exists and the linked Milestone decision closes the task as complete/PASS, finalization is still owned by this skill.
|
||||
When an active `USER_REVIEW.md` exists and the linked SDD/Milestone decision closes the task as complete/PASS, finalization is still owned by this skill.
|
||||
|
||||
- Read `USER_REVIEW.md`, archived `plan_*.log`, and archived `code_review_*.log` in that task directory.
|
||||
- Verify the linked decision and any follow-up evidence are sufficient to close the task. If a new implementation plan is needed instead, do not close; route back to the plan skill, which archives `USER_REVIEW.md` to `user_review_N.log` before writing a new plan.
|
||||
- Update `USER_REVIEW.md` in place to show a resolved state, final verdict, loop history, fulfilled decision items, and the evidence that closed the stop state.
|
||||
- Write `complete.log` from `agent-ops/skills/common/code-review/templates/complete-log-template.md` before moving or archiving the task artifacts. Include both the original archived review verdict and the user-review resolution line in `루프 이력`.
|
||||
- Write `complete.log` from `agent-ops/skills/common/code-review/templates/complete-log-template.md` before moving or archiving the task directory. Include both the original archived review verdict and the user-review resolution line in `루프 이력`.
|
||||
- Then apply the same task-directory archive move and `m-<milestone-slug>` PASS completion metadata rules as a normal `PASS`.
|
||||
- Do not leave an active task directory that contains `USER_REVIEW.md` and `*.log` files but no `complete.log` after the linked Milestone decision resolves the task as complete/PASS.
|
||||
- Do not leave an active task directory that contains `USER_REVIEW.md` and `*.log` files but no `complete.log` after the linked SDD/Milestone decision resolves the task as complete/PASS.
|
||||
|
||||
## Workflow Contract
|
||||
|
||||
|
|
@ -68,7 +68,6 @@ Filename rules:
|
|||
- Review file: `CODE_REVIEW-{review_lane}-GNN.md`
|
||||
- `{lane}` is only `local` or `cloud`; never put model names in filenames.
|
||||
- `GNN` is a two-digit capability grade from `G01` to `G10`; runtime maps lane+grade to current models externally.
|
||||
- This skill reads the active routed names but does not choose follow-up lane/G. Follow-up basenames come only from `plan` executing `finalize-task-routing`.
|
||||
|
||||
Multi-plan runtime contract:
|
||||
|
||||
|
|
@ -84,30 +83,32 @@ Milestone task group contract:
|
|||
- `agent-task/m-<milestone-slug>/` is reserved for Milestone-linked work created by the plan skill.
|
||||
- Do not treat normal task groups that do not start with `m-` as runtime milestone completion targets.
|
||||
- For a selected task path, parse only the first path segment as `{task_group}`. If it matches `^m-[a-z0-9][a-z0-9-]*$`, strip `m-` to get `<milestone-slug>`.
|
||||
- Do not modify `agent-roadmap/**` for milestone routing during code-review finalization. Read only the Milestone path from `Roadmap Targets` and its SDD path when needed to verify SDD Evidence Map.
|
||||
- Do not read or modify `agent-roadmap/**` for milestone routing during code-review finalization.
|
||||
- Do not call `update-roadmap` from this skill. The runtime consumes the PASS completion event, checks current state, resolves the active Milestone, and calls `update-roadmap` if needed.
|
||||
- For `m-<milestone-slug>` PASS tasks, report the original active task path, final archive path, complete log path, task group, and milestone slug so the runtime has deterministic event inputs.
|
||||
|
||||
Follow-up routing boundary:
|
||||
Review routing rules:
|
||||
|
||||
- This skill records current source, actual verification output, and findings, but it must not estimate or recommend the next lane/G.
|
||||
- On WARN/FAIL, invoke the plan skill in `prepare-follow-up` mode with the selected task path and raw current evidence before archiving the current pair.
|
||||
- Do not pass the archived lane, grade, routing score, rationale, or filename as plan-routing input. Archive paths remain evidence pointers, and actual logs/findings remain raw evidence.
|
||||
- The plan skill must complete its full analysis and mandatory `finalize-task-routing` step before it writes the next pair. Code-review must not create a routed follow-up pair directly.
|
||||
- Prefer `local` whenever the scope is bounded and verifiable; high local usage is fine. Do not choose `cloud` just to balance lane usage.
|
||||
- `local` is for bounded, explicit, locally verifiable review: required behavior is explicit in the plan or existing pattern; relevant context fits in edited files plus nearby types/helpers, direct call sites, and existing or planned targeted tests/fixtures; correctness can be checked by code inspection plus type/build/unit tests or deterministic commands; no open-ended product/design judgment, live external provider/runtime semantics, broad cross-domain context, or evidence-trust diagnosis is decisive.
|
||||
- `cloud` is required when any local condition is false, including when correctness depends on behavior promised outside the bounded context, wider context, or evidence-trust diagnosis. Repeated Required issues are evidence only when they show a local condition is false.
|
||||
- `local-G01` through `local-G10` and `cloud-G01` through `cloud-G10` are valid. Lane is capability fit; grade is complexity within the chosen lane. Do not raise `local-GNN` to compensate for missing judgment, missing context, weak verification, or a previous loop failure.
|
||||
- Repair non-behavioral review artifact drift during review instead of failing solely for it when implementation correctness, tests, and contracts remain judgeable.
|
||||
- `cloud-G07` or higher is mandatory only when terminal-agent or external interactive behavior is central and cannot be made deterministic for local review, or when the review requires more source/test/diff/log context than local can hold without omitting material evidence: shell/CLI workflow implementation, bin script orchestration, process control, stdout/stderr parsing, exit-status contracts, long-running command diagnosis, terminal benchmark-style tasks, real bin/smoke/integration failures after unit tests passed, TUI/PTY/browser/screen repaint/cursor stream behavior, rerun-mismatched verification trust failures, or very large cross-module/cross-domain changes that cannot be safely split for review.
|
||||
- On WARN/FAIL follow-up with 5+ `Required` findings, reassess lane/grade and default to `cloud-G07` or higher unless all findings are one narrow mechanical fix pattern; if keeping `local`, record why local conditions still hold.
|
||||
- Previous loop lane does not matter. Recompute lane from the current review or follow-up scope using these rules.
|
||||
|
||||
Directory states:
|
||||
|
||||
| State | Meaning |
|
||||
|-------|---------|
|
||||
| `PLAN-*-G??.md` + unfilled `CODE_REVIEW-*-G??.md` stub/placeholders | Implementation is not judgeable; review should fail completeness if invoked |
|
||||
| `PLAN-*-G??.md` + filled `CODE_REVIEW-*-G??.md` without verdict | Ready for code-review skill |
|
||||
| `PLAN-*-G??.md` + `CODE_REVIEW-*-G??.md` with appended verdict | Review finalization pending; do not append another verdict, resume Step 5 preparation/archive |
|
||||
| Exactly one active pair member + its newly archived counterpart | Partial archive after a preflighted finalization; verify both identities, finish the remaining archive, then resume post-archive recovery |
|
||||
| `PLAN-*-G??.md` + `CODE_REVIEW-*-G??.md` with filled `사용자 리뷰 요청` | Implementation claims a selected SDD or Milestone lock decision blocker; review validates the request and writes `USER_REVIEW.md` only if justified |
|
||||
| `PLAN-*-G??.md` + filled `CODE_REVIEW-*-G??.md` | Ready for code-review skill |
|
||||
| `complete.log` + `*.log` files | Task complete (PASS or user-review-resolved PASS), before final task-directory archive move |
|
||||
| `USER_REVIEW.md` + `*.log` files | Automatic loop stopped; linked Milestone lock decision must be resolved before creating another plan |
|
||||
| `USER_REVIEW.md` + `*.log` files | Automatic loop stopped; linked SDD/Milestone lock decision must be resolved before creating another plan |
|
||||
| `agent-task/archive/YYYY/MM/{task_name}/complete.log` + `*.log` files | Archived completed task path (PASS or user-review-resolved PASS); not active |
|
||||
| Only `*.log` files (no `complete.log`) | If the newest review log has a verdict and its required next state is absent, post-archive finalization is pending; otherwise the task is terminated mid-loop or abandoned |
|
||||
| Only `*.log` files (no `complete.log`) | Task terminated mid-loop or abandoned |
|
||||
|
||||
The implementing agent never archives or deletes active files; archiving is this skill's responsibility.
|
||||
|
||||
|
|
@ -127,21 +128,14 @@ Classify the combined set of active `CODE_REVIEW-*-G??.md` and `USER_REVIEW.md`
|
|||
|
||||
| Result | Action |
|
||||
|--------|--------|
|
||||
| Exactly one active path and it is `CODE_REVIEW-*-G??.md` | Review that task; exactly one `PLAN-*-G??.md` is normally expected beside it. If the review already has a verdict and its exact plan counterpart was just archived, use partial-archive recovery instead of reporting a missing plan. |
|
||||
| Exactly one active path and it is `USER_REVIEW.md`, with a linked Milestone completion/resolution decision | Perform User Review Resolution for that task. |
|
||||
| One or more active paths and every active path is `USER_REVIEW.md`, with no completion/resolution decision | Report that the linked Milestone decision is required and list the paths. |
|
||||
| No active paths | Apply the finalization-recovery scan below; stop only when it finds no recoverable task. |
|
||||
| Exactly one active path and it is `CODE_REVIEW-*-G??.md` | Review that task; exactly one `PLAN-*-G??.md` is expected beside it. |
|
||||
| Exactly one active path and it is `USER_REVIEW.md`, with a linked SDD/Milestone completion/resolution decision | Perform User Review Resolution for that task. |
|
||||
| One or more active paths and every active path is `USER_REVIEW.md`, with no completion/resolution decision | Report that the linked SDD/Milestone decision is required and list the paths. |
|
||||
| No active paths | Stop and report that no active review exists. |
|
||||
| Multiple active paths | If the user/runtime named a task group, task path, or subtask directory that identifies exactly one active path, use that directory. Otherwise list paths and stop with an ambiguity report; do not choose by agent judgment and do not create a user-review request for routing ambiguity. |
|
||||
|
||||
If a selected task directory contains both `USER_REVIEW.md` and active `PLAN-*-G??.md` or `CODE_REVIEW-*-G??.md`, report an inconsistent loop state instead of overwriting either state.
|
||||
|
||||
Finalization-recovery scan, excluding `agent-task/archive/**`:
|
||||
|
||||
- Candidate A has exactly one active plan, no active review/USER_REVIEW/complete.log, and a newest review log whose verdict belongs to that plan's current loop.
|
||||
- Candidate B has no active plan/review/USER_REVIEW/complete.log, and its newest plan/review logs form one loop whose review verdict requires a missing next state.
|
||||
- Accept only candidates whose exact source/archive identities and verdict can be proven from headers, log suffixes, and review contents. Do not treat a generic log-only abandoned directory as recoverable.
|
||||
- If the user/runtime names one candidate task path, resume it. Otherwise resume only when exactly one candidate exists; list multiple candidates as ambiguity. Use the Core Loop Rules recovery path and never append a second verdict.
|
||||
|
||||
## Step 2 - Load Context
|
||||
|
||||
Count `agent-task/{task_name}/code_review_*.log` in the selected active task directory:
|
||||
|
|
@ -151,25 +145,18 @@ Count `agent-task/{task_name}/code_review_*.log` in the selected active task dir
|
|||
|
||||
The diff is the starting point, not the boundary. Follow behavior and API connections far enough to judge correctness.
|
||||
|
||||
Review scope control:
|
||||
|
||||
- Use the plan's commands and checkpoints as the primary evidence. Add one focused, possibly table-driven reproducer only when needed to prove a suspected blocking defect; do not build speculative exhaustive probe matrices.
|
||||
- In a follow-up review, keep Required findings within the current plan, inherited Required findings, direct regressions from the fix, and concrete violations of the original SDD or contract acceptance criteria. Exclude unrelated pre-existing work from the verdict and Required/Suggested/Nit counts; mention it only in the final report as an out-of-scope task candidate.
|
||||
- Before adding a new Required that the current plan did not state, cite the exact original plan/SDD/contract criterion it violates or provide a concrete failing case. Do not require a preferred test shape when existing deterministic evidence proves the same behavior.
|
||||
- When one invariant fails in multiple already-observed variants, report that known set together instead of revealing one variant per follow-up.
|
||||
|
||||
## Step 3 - Pre-Review Checklist
|
||||
|
||||
Before writing the verdict:
|
||||
|
||||
- Compare actual source files against every planned checklist item.
|
||||
- Compare the plan `Implementation Checklist` and review stub `Implementation Checklist` (legacy: `구현 체크리스트`); repair non-behavioral drift when implementation remains judgeable.
|
||||
- When the active artifacts have `Roadmap Targets`, check whether the referenced Milestone has `SDD: 필요`. When it does, read only that Milestone and its SDD, compare implementation evidence against the SDD Acceptance Scenarios/Evidence Map for the targeted task ids, and fail completeness or verification trust when evidence is insufficient. Do not require a separate SDD target section.
|
||||
- Compare the plan `구현 체크리스트` and review stub `구현 체크리스트`; repair non-behavioral drift when implementation remains judgeable.
|
||||
- If the plan or review stub has `Spec Targets`, read the referenced SDD and compare implementation evidence against the listed Acceptance Scenario ids and Evidence Map.
|
||||
- Directly repair obvious non-behavioral source nits when safe: typos, stale comments, docs, or formatting only, with no behavior/test/API contract change.
|
||||
- If a checklist item contains integrated verification for a feature, treat that feature item as incomplete until both implementation evidence and the matching verification output are present. Do not accept a separate unchecked completion-criteria item as a substitute.
|
||||
- Confirm the implementation marked the matching checklist items in the active review file, including the mandatory `CODE_REVIEW-*-G??.md` evidence item; repair clear artifact drift when evidence supports completion.
|
||||
- Confirm the implementation marked the matching checklist items in the active review file, including the final mandatory `CODE_REVIEW-*-G??.md` completion item; repair clear artifact drift when evidence supports completion.
|
||||
- Treat review artifact gaps as failures only when they prevent judging implementation correctness, tests, contracts, or verification trust.
|
||||
- Treat every generic `상태` field and implementation blocker record as ordinary evidence, never as a request to stop for the user. Evaluate the user-review gate independently from the current selected Milestone only after a WARN/FAIL finding requires a next state.
|
||||
- Read the `사용자 리뷰 요청` section. If `상태` is not `없음`, validate the exact decision needed, `연결 대상`, blocker evidence, command output or not-run reason, why automatic follow-up cannot resolve it, and resume condition before deciding whether the user-review gate triggers. Reject the request unless it is tied to an SDD decision or selected Milestone `구현 잠금 > 결정 필요` item.
|
||||
- Grep renamed/removed symbols for stale references.
|
||||
- Confirm every required test exists, name matches, and assertions are meaningful.
|
||||
- Cross-check claimed verification output in the active review file against actual code and project commands.
|
||||
|
|
@ -177,19 +164,16 @@ Before writing the verdict:
|
|||
|
||||
## Step 4 - Append Verdict
|
||||
|
||||
Append the review result to the active `CODE_REVIEW-*-G??.md`. For a canonical English review file, append `## Code Review Result`. For a legacy active review file using Korean headings, append `## 코드리뷰 결과` using Korean field labels to preserve schema compatibility for running legacy dispatchers.
|
||||
Append `코드리뷰 결과` to the active `CODE_REVIEW-*-G??.md`.
|
||||
|
||||
Required fields for canonical English active pairs:
|
||||
Required fields:
|
||||
|
||||
- `Overall Verdict`: exactly `PASS`, `WARN`, or `FAIL`.
|
||||
- `Dimension Assessment`: Pass/Warn/Fail for correctness, completeness, test coverage, API contract, code quality, implementation deviation, verification trust. If SDD Evidence Map applies through `Roadmap Targets`, also include spec conformance.
|
||||
- `Findings`: `None`, or bullets using `Required`, `Suggested`, or `Nit` with `file:line` and a concrete fix.
|
||||
- `Routing Signals`: calculate once and append `review_rework_count=<N>` and `evidence_integrity_failure=true|false`. Set rework count to archived same-task `WARN|FAIL` verdicts plus one only when the current verdict is non-PASS. Set integrity failure to true only when a claimed test, command, exit code, or production path is absent, unexecuted, or contradicted by fresh reviewer evidence.
|
||||
- `Next Step`: keep only the matching PASS, WARN/FAIL follow-up, or USER_REVIEW line.
|
||||
- `종합 판정`: exactly `PASS`, `WARN`, or `FAIL`.
|
||||
- `차원별 평가`: Pass/Warn/Fail for correctness, completeness, test coverage, API contract, code quality, plan deviation, verification trust. If `Spec Targets` exists, also include spec conformance.
|
||||
- `발견된 문제`: `없음`, or bullets using `Required`, `Suggested`, or `Nit` with `file:line` and a concrete fix.
|
||||
- `다음 단계`: keep only the matching PASS, WARN/FAIL follow-up, or USER_REVIEW line.
|
||||
|
||||
For legacy active pairs, use the equivalent legacy field labels: `종합 판정`, `차원별 평가`, `발견된 문제`, `라우팅 신호`, `다음 단계`.
|
||||
|
||||
Do not check archive/next-state items in `Review-Only Checklist` (legacy: `코드리뷰 전용 체크리스트`) during Step 4. Complete the applicable dedicated checklist items in the archived `code_review_*.log` during Step 7, after archive, next-state writes, and PASS task-artifact moves are done.
|
||||
Do not check archive/next-state items in `코드리뷰 전용 체크리스트` during Step 4. Complete the applicable dedicated checklist items in the archived `code_review_*.log` during Step 7, after archive, next-state writes, and PASS task-directory moves are done.
|
||||
|
||||
Severity semantics:
|
||||
|
||||
|
|
@ -211,34 +195,16 @@ Verdict consistency:
|
|||
- Any Fail dimension or any Required issue forces `FAIL`.
|
||||
- Any Warn dimension or any Suggested issue forces `WARN`, unless the only findings are explicitly Nit and every dimension remains Pass.
|
||||
|
||||
## Step 5 - Prepare Next State And Archive Active Files
|
||||
## Step 5 - Archive Active Files
|
||||
|
||||
Do not archive WARN/FAIL files until the next-state content is fully prepared in memory.
|
||||
Archive is mandatory for `PASS`, `WARN`, and `FAIL`. Before the archive order, ensure `.gitignore` has the Agent-Ops managed gitignore block for task artifacts before writing `*.log` outputs. Prefer `source agent-ops/bin/ai-ignore.sh && agent_ops_ensure_gitignore_task_artifact_block .gitignore`; if the helper is unavailable, add or update a block containing `!agent-task/`, `!agent-task/**/`, `!agent-task/**/*.md`, `!agent-task/**/*.log`, and `agent-roadmap/current.md`.
|
||||
|
||||
- `PASS`: no routed follow-up preparation is required.
|
||||
- `WARN`/`FAIL`: apply the user-review gate before any rename.
|
||||
- If the gate triggers, render the complete `USER_REVIEW.md` body from `agent-ops/skills/common/code-review/templates/user-review-template.md` in memory.
|
||||
- Otherwise build the follow-up handoff described below and fully execute `agent-ops/skills/common/plan/SKILL.md` in `prepare-follow-up` mode.
|
||||
Archive order is fixed:
|
||||
|
||||
Reuse the routing signals appended in Step 4; do not recount verdict history for routing. Separately count the existing logs once for archive identity: set `current_review_archive_number=count(code_review_*.log)` and `current_plan_archive_number=count(plan_*.log)`, then derive both archive names from the current active files' own lane/grade. These archive values describe the pair being closed, not the next route.
|
||||
1. Count existing `code_review_*.log` as `N`; rename `CODE_REVIEW-{review_lane}-GNN.md` to `code_review_{review_lane}_GNN_N.log`.
|
||||
2. Count existing `plan_*.log` as `M`; rename `PLAN-{build_lane}-GNN.md` to `plan_{build_lane}_GNN_M.log`.
|
||||
|
||||
The follow-up handoff contains the selected `{task_name}`, the current plan's requested outcome/acceptance/exclusions revalidated against current evidence, current verdict, Required/Suggested/Nit findings, affected files, actual verification output, current ownership/dependency facts, roadmap carryover, `review_rework_count`, `evidence_integrity_failure`, `REVIEW_<PARENT_TAG>`, and those predicted current-pair archive names. Keep current active paths only as evidence pointers. Do not add the prior lane, grade, routing score, rationale, or a preferred next route to the neutral routing snapshot, and require plan to omit route-bearing basenames from the isolated routing input. The plan may use current archive names only after routing to render `Archive Evidence Snapshot`.
|
||||
|
||||
- `prepare-follow-up` must return `status: routed`, the exact routed basenames, `prepared_plan`, `prepared_review`, `plan_number`, `current_plan_archive_name`, `current_plan_archive_number`, `current_review_archive_name`, `current_review_archive_number`, `plan_log_number`, `review_log_number`, and `gitignore_repair_needed`. It must have executed `finalize-task-routing` in `isolated-reassessment` mode.
|
||||
- Verify that the returned current archive names/numbers equal the values derived before preparation, and that `plan_log_number` / `review_log_number` are the post-archive counts embedded in the new review stub for its future archive.
|
||||
- If preparation returns `needs_evidence`, collect all named new evidence and rerun after the input changes; never rerun with unchanged evidence. If the evidence cannot be obtained in the current scope, leave the verdict-appended pair in place and report the exact finalization blocker.
|
||||
- If preparation returns `blocked`, leave the verdict-appended active PLAN/CODE_REVIEW pair in place, do not check archive/next-state items, and report a resumable finalization blocker. A later code-review invocation resumes this step without appending another verdict.
|
||||
|
||||
After the required next state is prepared, archive is mandatory for `PASS`, `WARN`, and `FAIL`. Ensure `.gitignore` has the Agent-Ops managed gitignore block for task artifacts before writing `*.log` outputs. Prefer `source agent-ops/bin/ai-ignore.sh && agent_ops_ensure_gitignore_task_artifact_block .gitignore`; if the helper is unavailable, add or update a block containing `!agent-task/`, `!agent-task/**/`, `!agent-task/**/*.md`, `!agent-task/**/*.log`, and `agent-roadmap/current.md`. Apply the repair here when `prepare-follow-up` returned `gitignore_repair_needed: true`.
|
||||
|
||||
Preflight both archive operations before either rename:
|
||||
|
||||
1. Recount existing `code_review_*.log` as `current_review_archive_number`. Parse the active review's lane/grade from its own basename and derive `current_review_archive_name=code_review_{current_review_lane}_{current_review_grade}_{current_review_archive_number}.log`.
|
||||
2. Recount existing `plan_*.log` as `current_plan_archive_number`. Parse the active plan's lane/grade from its own basename and derive `current_plan_archive_name=plan_{current_build_lane}_{current_build_grade}_{current_plan_archive_number}.log`.
|
||||
3. Require both destinations not to exist. When the active stub contains concrete expected archive names, require them to match the derived names; legacy generic placeholders do not override the derived values.
|
||||
4. For WARN/FAIL, require exact matches with both prepared current archive names/numbers. If any check fails, do not rename either file.
|
||||
|
||||
After both operations pass preflight, rename the active review and then the active plan to those exact names. If either current archive count or derived name changed after preparation, discard the prepared pair and rerun plan `prepare-follow-up` before renaming. After archiving, verify that the actual plan/review log counts equal the prepared `plan_log_number` and `review_log_number`; neither active `.md` file remains until Step 6 materializes the prepared next state.
|
||||
After archiving, neither active `.md` file remains unless Step 6 writes a follow-up plan/review or `USER_REVIEW.md`.
|
||||
|
||||
## Step 6 - Post-Review Actions
|
||||
|
||||
|
|
@ -251,36 +217,207 @@ Complete log template:
|
|||
- Do not leave placeholders in `complete.log`.
|
||||
- If the task did not close through `USER_REVIEW.md`, remove the optional user-review row from the `루프 이력` table.
|
||||
- If the archived plan or review log contains `Roadmap Targets`, copy it into `complete.log` as `Roadmap Completion`. Include the Milestone path, completed Task ids, archived plan/review log paths, and verification evidence. If there is no `Roadmap Targets` section, remove the optional `Roadmap Completion` template section entirely and do not invent roadmap targets.
|
||||
- If the archived plan or review log contains `Spec Targets`, copy it into `complete.log` as `Spec Completion`. Include the SDD path, completed Acceptance Scenario ids, archived plan/review log paths, and verification evidence. If there is no `Spec Targets` section, remove the optional `Spec Completion` template section entirely.
|
||||
- Use `없음` for empty `잔여 Nit` or `후속 작업`.
|
||||
- A PASS `complete.log` must not contain unresolved Required or Suggested issues. Nit-only leftovers may be recorded under `잔여 Nit`.
|
||||
|
||||
For `WARN` or `FAIL`, materialize the next state prepared in Step 5 immediately after archive:
|
||||
For `WARN` or `FAIL`, apply the user-review gate before writing follow-up files.
|
||||
|
||||
- If the user-review gate triggered, write the prepared body to `agent-task/{task_name}/USER_REVIEW.md`. It must use only `milestone-lock`, contain every archived loop entry plus the exact linked decision, and contain no placeholder. Do not write active PLAN/CODE_REVIEW files or `complete.log`.
|
||||
- Otherwise write `prepared_plan` and `prepared_review` byte-for-byte to their routed basenames. Do not rerun, adjust, compare, or upgrade their lane/G after archive.
|
||||
- Verify the written follow-up pair contains the predicted archived plan/review paths in identical `Archive Evidence Snapshot` sections and contains no unresolved token from the review-stub template inventory. Unrelated braces in commands or code are allowed.
|
||||
- Do not adjust the prepared route after finalization. For a `local-fit` base, `review_rework_count >= 2` or `evidence_integrity_failure=true` must produce `recovery-boundary`; `capability-gap` and `grade-boundary` keep their own basis.
|
||||
If the user-review gate triggers:
|
||||
|
||||
If the task group is `m-<milestone-slug>` and the user-review gate triggered, report that the milestone task is blocked on user review; do not emit PASS completion metadata and do not call `update-roadmap`.
|
||||
- Write `agent-task/{task_name}/USER_REVIEW.md` from `agent-ops/skills/common/code-review/templates/user-review-template.md`.
|
||||
- Fill every placeholder. Use only `sdd-decision` or `milestone-lock` as the reason type.
|
||||
- Include all available archived loop history in chronological order, the current archived plan/review log paths, the final verdict, review number, issue summary, blocking evidence, and the exact linked SDD/Milestone decision needed.
|
||||
- Do not write a new active `PLAN-{build_lane}-GNN.md` or `CODE_REVIEW-{review_lane}-GNN.md`.
|
||||
- Do not write `complete.log`.
|
||||
- If the task group is `m-<milestone-slug>`, report that the milestone task is blocked on user review; do not emit PASS completion metadata and do not call `update-roadmap`.
|
||||
|
||||
If the user-review gate does not trigger, write new routed plan/review files using the plan skill format:
|
||||
|
||||
- New plan number is the count of `plan_*.log` after archive.
|
||||
- Header tag is `REVIEW_<PARENT_TAG>`.
|
||||
- If the selected task group is `m-<milestone-slug>`, write the follow-up plan/review under the same `m-<milestone-slug>` task group.
|
||||
- Base the follow-up scope directly on the archived review findings. Keep it narrow and actionable.
|
||||
- Choose lane/grade again from the current follow-up scope using Review routing rules. Ignore the prior lane and do not increment GNN solely because the previous loop failed.
|
||||
- If the finding is only missing or untrusted verification evidence that an appropriate follow-up lane can produce by rerunning commands or collecting artifacts, do not write `USER_REVIEW.md` solely for that reason. Write a follow-up plan that reruns the exact commands in an appropriate lane and records actual stdout/stderr.
|
||||
- If follow-up verification involves mobile/UI hangs, timeouts, or no progress for 2 minutes, stop blind retries; require focused rerun output plus screenshot/window/UI-tree evidence path, or the exact reason capture is impossible.
|
||||
- Write an `Archive Evidence Snapshot` section in every WARN/FAIL follow-up plan. Copy enough prior-loop evidence from the archived plan/review logs for the next implementer to act without rereading archive by default: current archived plan/review log paths, verdict, Required/Suggested/Nit summary, affected files, verification evidence, and any roadmap/spec carryover. If exact prior context is still required, cite the specific archive file paths allowed to read; do not instruct the implementer to search `agent-task/archive/**` broadly.
|
||||
- Copy the follow-up plan's `Archive Evidence Snapshot` section exactly into the follow-up review stub.
|
||||
- Before choosing the follow-up route, apply this gate:
|
||||
- Keep the follow-up on `local` when all local allowlist conditions are true for the current fix; otherwise use `cloud`.
|
||||
- If the follow-up work is terminal-agent work that cannot be reduced to deterministic commands and evidence, use `cloud-G07` or higher.
|
||||
- If unit tests passed but a real bin/smoke/integration command failed and local follow-up cannot isolate the failure with deterministic evidence, use `cloud-G07` or higher.
|
||||
- If the task depends on interactive TUI/PTY/browser/external CLI behavior, screen repaint/cursor stream parsing, or live command-palette state that cannot be captured deterministically, use `cloud-G07` or higher.
|
||||
- If the follow-up requires more source/test/diff/log context than local can hold without dropping material evidence, or the failure spans broad cross-module/cross-domain context that cannot be safely split, use `cloud-G07` or higher.
|
||||
- If verification evidence is missing, reconstructed, stale, untrusted, or mismatched on rerun, use a local follow-up only when exact commands and actual stdout/stderr capture are enough; use `cloud-G07` or higher when evidence trust recovery needs stronger diagnosis.
|
||||
- `FAIL`: one plan item per Required issue.
|
||||
- `WARN`: one grouped plan item for Suggested issues, plus related Nit issues if useful.
|
||||
- Each plan item needs problem, solution with before/after when non-trivial, checklist, test decision, intermediate verification.
|
||||
- The follow-up plan and review stub must contain matching `구현 체크리스트` item text/order, including the final mandatory `CODE_REVIEW-*-G??.md` completion item.
|
||||
- The follow-up plan's implementer instructions and review stub must forbid direct user prompts and include the implementation-time `사용자 리뷰 요청` stop path so the next implementer can act without reading the plan skill.
|
||||
- Copy `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` into the follow-up review stub's `사용자 리뷰 요청` section.
|
||||
- If the archived plan had `Roadmap Targets` and the follow-up still works toward the same Milestone Task completion, copy that section into the follow-up plan and review stub. If the follow-up intentionally no longer claims roadmap Task completion, omit the section and explain why in the follow-up plan `범위 결정 근거`.
|
||||
- If the archived plan had `Spec Targets` and the follow-up still works toward the same SDD Acceptance Scenario completion, copy that section into the follow-up plan and review stub. If the follow-up no longer claims scenario completion, omit it and explain why in `범위 결정 근거`.
|
||||
|
||||
Routed review stub template (fill `{…}` placeholders; everything else is fixed and must not be changed by the implementing agent):
|
||||
|
||||
```markdown
|
||||
<!-- task={task_name} plan={N} tag={TAG} -->
|
||||
|
||||
# Code Review Reference - {TAG}
|
||||
|
||||
> **[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 selected SDD decision or selected Milestone `구현 잠금 > 결정 필요` item, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Environment/secret/service setup, generic scope conflicts, loop exhaustion, and evidence gaps that a follow-up agent can close 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 only the linked SDD/Milestone lock 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={YYYY-MM-DD}
|
||||
task={task_name}, plan={N}, tag={TAG}
|
||||
|
||||
{copy the follow-up plan's Roadmap Targets section exactly if present; omit this block if the follow-up plan has no Roadmap Targets}
|
||||
{copy the follow-up plan's Spec Targets section exactly if present; omit this block if the follow-up plan has no Spec Targets}
|
||||
{copy the follow-up plan's Archive Evidence Snapshot section exactly if present; omit this block if the follow-up plan has no Archive Evidence Snapshot}
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[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`가 연결된 SDD/Milestone 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log` 작성 후 archive 이동한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [{TAG}-1] {item description} | [ ] |
|
||||
| [{TAG}-2] {item description} | [ ] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
{copy the follow-up plan's 구현 체크리스트 items exactly, preserving order and checkbox text}
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[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하는지 확인한다.
|
||||
- [ ] 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`를 작성하지 않는다.
|
||||
- [ ] 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가 연결된 SDD/Milestone 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 새 결정이 필요해 보여도 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 이 섹션은 선택된 SDD 결정 또는 선택된 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 차단할 때만 채운다. 외부 환경/secret/서비스 준비, 검증 증거 공백, 반복 실패, 일반 범위 조정은 사용자 리뷰 요청이 아니며 `검증 결과`, `계획 대비 변경 사항`, 또는 code-review의 일반 follow-up plan으로 처리한다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 연결 대상: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
{pre-filled from plan — one bullet per review focus area}
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
|
||||
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.
|
||||
|
||||
### {TAG}-1 중간 검증
|
||||
```
|
||||
$ {verification command from plan}
|
||||
(output)
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```
|
||||
$ {final verification command from plan}
|
||||
(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.
|
||||
```
|
||||
|
||||
Sections and their ownership:
|
||||
|
||||
| 섹션 | 소유자 | 설명 |
|
||||
|------|--------|------|
|
||||
| 헤더 주석, 개요(date/task/plan/tag), 리뷰 에이전트 지시 | 스텁 생성 시 고정 | 구현 에이전트가 수정하거나 실행하지 않음 |
|
||||
| Roadmap Targets | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 수정하지 않음; PASS 시 code-review가 `complete.log`의 `Roadmap Completion`으로 복사 |
|
||||
| Spec Targets | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 수정하지 않음; PASS 시 code-review가 `complete.log`의 `Spec Completion`으로 복사 |
|
||||
| Archive Evidence Snapshot | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트의 기본 이전 루프 컨텍스트; 추가 확인이 필요할 때 여기에 명시된 archive 파일만 좁게 읽음 |
|
||||
| 구현 항목별 완료 여부 (항목명) | 스텁 생성 시 고정 | `[ ]` → `[x]` 체크만 구현 에이전트가 수행 |
|
||||
| 구현 체크리스트 (항목 텍스트/순서) | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 `[ ]` → `[x]` 체크만 수행; 마지막 체크박스는 저장 전 필수 |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | 구현 에이전트가 채움 | placeholder 텍스트를 실제 내용으로 교체 |
|
||||
| 사용자 리뷰 요청 | 구현 에이전트가 채움 | 선택된 SDD 결정 또는 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 차단할 때만 채움; 구현 중 직접 질문은 금지; 환경/secret/서비스/검증 공백/일반 범위 조정은 사용자 리뷰 요청으로 쓰지 않음 |
|
||||
| 리뷰어를 위한 체크포인트 | 스텁 생성 시 고정 | 계획에서 추출한 리뷰 포인트 |
|
||||
| 검증 결과 (섹션 제목 + 명령) | 스텁 생성 시 고정 | 실행 출력만 구현 에이전트가 채움; 명령 변경은 `계획 대비 변경 사항`에 기록 |
|
||||
| 코드리뷰 결과 | 리뷰 에이전트가 append | 스텁에 포함하지 않음 |
|
||||
|
||||
## Step 7 - Complete Review-Only Checklist, Move PASS Task, And Report
|
||||
|
||||
After Step 6:
|
||||
|
||||
- If verdict is `PASS`, determine archive month from the current completion date as `YYYY/MM`, create the needed archive parent directories, then move the selected task artifacts from `agent-task/{task_name}/` to `agent-task/archive/YYYY/MM/{task_name}/`. For split work, move the selected subtask directory itself and preserve the task group path, e.g. `agent-task/refactoring/01_core/` moves to `agent-task/archive/YYYY/MM/refactoring/01_core/`.
|
||||
- If verdict is `PASS`, determine archive month from the current completion date as `YYYY/MM`, create the needed archive parent directories, then move the selected active task directory `agent-task/{task_name}/` to `agent-task/archive/YYYY/MM/{task_name}/`. For split work, the selected active task directory is the subtask directory, and the archive must preserve the task group path, e.g. `agent-task/refactoring/01_core/` moves to `agent-task/archive/YYYY/MM/refactoring/01_core/`.
|
||||
- Do not overwrite an existing archive directory. If `agent-task/archive/YYYY/MM/{task_name}/` already exists, append the next numeric suffix to the final path segment: single-plan `agent-task/archive/YYYY/MM/{task_group}_1/`, split-plan `agent-task/archive/YYYY/MM/{task_group}/{subtask_dir}_1/`, and so on.
|
||||
- After moving a split subtask, remove the active parent `agent-task/{task_group}/` only when it is empty.
|
||||
- After moving a split subtask, remove the active parent `agent-task/{task_group}/` only if it is empty. If sibling subtask directories or other files remain, leave the parent task group in place.
|
||||
- If verdict is `PASS` and `{task_group}` matches `m-<milestone-slug>`, do not resolve the roadmap target and do not call `update-roadmap`. Report completion event metadata after the task archive move: `origin-task=agent-task/{task_name}` from the original active task path, `task-group={task_group}`, `milestone-slug=<milestone-slug>`, final archive path, `complete.log` path, archived plan/review log paths, and `roadmap-completion=<Task ids from complete.log or none>`.
|
||||
- The runtime consumes that completion event, checks current state, and calls `update-roadmap` if needed. `update-roadmap` only checks Milestone Task ids when `complete.log` contains `Roadmap Completion`; if the section is absent, roadmap Task completion is a no-op even for `m-*` task groups.
|
||||
- `WARN` and `FAIL` do not update the roadmap Milestone; the follow-up plan remains under the same `m-<milestone-slug>` task group when the original task was Milestone-linked.
|
||||
- `USER_REVIEW` does not update the roadmap Milestone and does not produce PASS completion metadata. Keep the active task directory in place with `USER_REVIEW.md` and archived plan/review logs until the linked Milestone lock decision is resolved.
|
||||
- If `USER_REVIEW.md` is later resolved as complete/PASS by linked Milestone decision and evidence, write `complete.log`, move the task artifacts to archive, and report `m-*` PASS completion metadata just like a normal `PASS`.
|
||||
- For `PASS`, open the moved `agent-task/archive/YYYY/MM/{final_task_name}/{current_review_archive_name}`, where `{final_task_name}` is the archived task path, including `{task_group}/` for split work.
|
||||
- `USER_REVIEW` does not update the roadmap Milestone and does not produce PASS completion metadata. Keep the active task directory in place with `USER_REVIEW.md` and archived plan/review logs until the linked SDD or Milestone lock decision is resolved.
|
||||
- If `USER_REVIEW.md` is later resolved as complete/PASS by linked SDD/Milestone decision and evidence, write `complete.log`, move the task directory to archive, and report `m-*` PASS completion metadata just like a normal `PASS`.
|
||||
- For `PASS`, open the moved `agent-task/archive/YYYY/MM/{final_task_name}/code_review_{review_lane}_GNN_N.log`, where `{final_task_name}` is the archived task path, including `{task_group}/` for split work.
|
||||
- For user-review-resolved PASS, confirm the moved archive contains the resolved `USER_REVIEW.md`, `complete.log`, and the existing archived `plan_*.log` / `code_review_*.log`; do not recreate an active review file only to add a new checklist item.
|
||||
- For `WARN` or `FAIL`, open `agent-task/{task_name}/{current_review_archive_name}`.
|
||||
- For `WARN` or `FAIL`, open `agent-task/{task_name}/code_review_{review_lane}_GNN_N.log`.
|
||||
- Run `git check-ignore -q --` on the generated task artifacts (`plan_*.log`, `code_review_*.log`, `user_review_*.log` when present, `complete.log` when present, and active follow-up `.md` files). If any are ignored, apply the Agent-Ops managed gitignore block and re-check before reporting.
|
||||
- Check every applicable item in `Review-Only Checklist` (legacy: `코드리뷰 전용 체크리스트`); leave mutually exclusive verdict items unchecked.
|
||||
- If any applicable item cannot be checked, finish the missing archive, `complete.log`, task-artifact move, mandatory plan-skill follow-up, or `USER_REVIEW.md` write first.
|
||||
- Check every applicable item in `코드리뷰 전용 체크리스트`; leave mutually exclusive verdict items unchecked.
|
||||
- If any applicable item cannot be checked, finish the missing archive, `complete.log`, task-directory move, follow-up plan/review write, or `USER_REVIEW.md` write first.
|
||||
- Do not recreate an active review file just to update this checklist; update the archived `code_review_*.log`.
|
||||
- Only report after the archived review log has the verdict, applicable checked review-only checklist, required next-state files, for `PASS` or user-review-resolved PASS the final task archive move, for `m-*` PASS tasks the completion event metadata, and for unresolved `USER_REVIEW` the filled `USER_REVIEW.md`.
|
||||
|
||||
|
|
@ -309,18 +446,20 @@ Report Required/Suggested counts, archive names, the final task archive path for
|
|||
|
||||
## Final Checklist
|
||||
|
||||
- `{current_review_archive_name}` exists with the verdict appended and was derived from the archived active review's own route.
|
||||
- `{current_plan_archive_name}` exists and was derived from the archived active plan's own route.
|
||||
- `code_review_{review_lane}_GNN_N.log` exists with verdict appended.
|
||||
- `plan_{build_lane}_GNN_M.log` exists.
|
||||
- `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores local `agent-roadmap/current.md`; generated task artifacts are not ignored by `git check-ignore`.
|
||||
- No active `PLAN-*.md`, `CODE_REVIEW-*.md`, or `USER_REVIEW.md` remains after PASS or user-review-resolved PASS.
|
||||
- PASS or user-review-resolved PASS: `complete.log` written from `agent-ops/skills/common/code-review/templates/complete-log-template.md`, then task artifacts moved under `agent-task/archive/YYYY/MM/` with task-group path preserved for split work.
|
||||
- No active `.md` files remain after PASS or user-review-resolved PASS.
|
||||
- PASS or user-review-resolved PASS: `complete.log` written from `agent-ops/skills/common/code-review/templates/complete-log-template.md`, then task directory moved under `agent-task/archive/YYYY/MM/` with task-group path preserved for split work.
|
||||
- PASS milestone task group: `m-<milestone-slug>` completion event metadata was reported for runtime; roadmap was not modified by code-review.
|
||||
- PASS with `Roadmap Targets`: `complete.log` contains `Roadmap Completion` with Milestone path, Task ids, archived plan/review evidence, and verification evidence.
|
||||
- PASS with `Spec Targets`: `complete.log` contains `Spec Completion` with SDD path, Acceptance Scenario ids, archived plan/review evidence, and verification evidence.
|
||||
- PASS without `Roadmap Targets`: `complete.log` omits `Roadmap Completion` and reported metadata says `roadmap-completion=none`.
|
||||
- WARN/FAIL without user-review gate: the plan skill was invoked for the exact task path with verified `review_rework_count` and `evidence_integrity_failure`, completed `finalize-task-routing`, and created new active `PLAN-{build_lane}-GNN.md` and `CODE_REVIEW-{review_lane}-GNN.md` files matching the fresh routed output; no `complete.log`.
|
||||
- WARN/FAIL follow-up: the plan input omitted prior route fields, revalidated outcome/acceptance/exclusions from current evidence, used the completed in-memory PLAN as the packet, and copied identical `Archive Evidence Snapshot` sections into the new plan/review pair.
|
||||
- Follow-up plans and review stubs keep implementation agents limited to implementation/test/evidence and contain no implementation-owned user-review request section.
|
||||
- PASS split: empty active parent `agent-task/{task_group}/` removed after the subtask move; non-empty parent left in place.
|
||||
- WARN/FAIL without user-review gate: new active `PLAN-{build_lane}-GNN.md` and `CODE_REVIEW-{review_lane}-GNN.md` created with matching headers and matching `구현 체크리스트`; no `complete.log`.
|
||||
- WARN/FAIL follow-up: new active plan and review stub contain identical `Archive Evidence Snapshot` sections with prior archived plan/review log paths, verdict, issue summary, affected files, verification evidence, and specific archive paths allowed for narrow reread when needed.
|
||||
- Follow-up review stubs include the `사용자 리뷰 요청` section from `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` and forbid direct user prompts during implementation.
|
||||
- USER_REVIEW: `USER_REVIEW.md` exists from template, no active `PLAN-*.md` or `CODE_REVIEW-*.md` remains, and no `complete.log` was written.
|
||||
- Review-agent-owned USER_REVIEW: the generated `USER_REVIEW.md` records the exact active Milestone decision and repository evidence that made automatic continuation unsafe.
|
||||
- Implementation-requested USER_REVIEW: archived review log preserves the filled `사용자 리뷰 요청` evidence and the generated `USER_REVIEW.md` records the exact linked SDD/Milestone decision needed.
|
||||
- USER_REVIEW resolved as PASS: archived task contains both resolved `USER_REVIEW.md` and `complete.log`.
|
||||
- The applicable review-agent-only finalization checklist was completed before reporting.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
interface:
|
||||
display_name: "Code Review"
|
||||
short_description: "Review and route task loops"
|
||||
default_prompt: "Use $code-review to review or resolve the active task, archive it, and on WARN/FAIL invoke $plan so $finalize-task-routing creates the next routed pair."
|
||||
default_prompt: "Use $code-review to review or resolve the active repository task, archive active files, and create complete.log, follow-up plan/review files, or USER_REVIEW.md."
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
| Plan | Review | Verdict | 메모 |
|
||||
|------|--------|---------|------|
|
||||
| `plan_{build_lane}_GNN_N.log` | `code_review_{review_lane}_GNN_N.log` | PASS/WARN/FAIL | {main outcome or follow-up reason} |
|
||||
| `USER_REVIEW.md` | linked Milestone decision | PASS/RESOLVED | {only when a user-review stop was resolved as the terminal completion path; remove this row otherwise} |
|
||||
| `USER_REVIEW.md` | linked SDD/Milestone decision | PASS/RESOLVED | {only when a user-review stop was resolved as the terminal completion path; remove this row otherwise} |
|
||||
|
||||
## 구현/정리 내용
|
||||
|
||||
|
|
@ -28,11 +28,19 @@
|
|||
{optional; include only when archived plan/review had Roadmap Targets. Remove this entire section when there are no Roadmap Targets.}
|
||||
|
||||
- Milestone: `{agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md}`
|
||||
- Milestone link: [Milestone 문서](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- Completed task ids:
|
||||
- `{task-id}`: PASS; evidence=`{archived-plan-log}`, `{archived-review-log}`; verification=`{command or saved output path}`
|
||||
- Not completed task ids: 없음
|
||||
|
||||
## Spec Completion
|
||||
|
||||
{optional; include only when archived plan/review had Spec Targets. Remove this entire section when there are no Spec Targets.}
|
||||
|
||||
- SDD: `{agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md}`
|
||||
- Completed scenario ids:
|
||||
- `{scenario-id}`: PASS; task=`{task-id}`; evidence=`{archived-plan-log}`, `{archived-review-log}`; verification=`{command or saved output path}`
|
||||
- Not completed scenario ids: 없음
|
||||
|
||||
## 잔여 Nit
|
||||
|
||||
- 없음
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ USER_REVIEW
|
|||
|
||||
## 사유
|
||||
|
||||
- 유형: milestone-lock
|
||||
- 연결 대상: {agent-roadmap/phase/<phase>/milestones/<milestone>.md}
|
||||
- 유형: {sdd-decision | milestone-lock}
|
||||
- 연결 대상: {agent-roadmap/sdd/<phase>/<milestone>/SDD.md 또는 agent-roadmap/phase/<phase>/milestones/<milestone>.md}
|
||||
- 현재 리뷰 회차: {review-number}
|
||||
- 최종 판정: {WARN or FAIL}
|
||||
- 요약: {Milestone 구현 잠금 항목이 실구현을 차단한 이유}
|
||||
- 요약: {SDD 결정 또는 Milestone 구현 잠금 항목이 실구현을 차단한 이유}
|
||||
|
||||
## 루프 이력
|
||||
|
||||
|
|
@ -30,15 +30,15 @@ USER_REVIEW
|
|||
- 현재 archive review: `{current-archived-review-log}`
|
||||
- 검증 명령: `{command or 없음}`
|
||||
- 실제 출력: {stdout/stderr excerpt or saved output path}
|
||||
- 차단 판단 근거: {연결 대상의 Milestone 결정 필요 항목과 일치하는 근거}
|
||||
- 차단 판단 근거: {연결 대상의 SDD 결정 또는 Milestone 결정 필요 항목과 일치하는 근거}
|
||||
|
||||
## 연결 결정 필요
|
||||
|
||||
- [ ] {Milestone `구현 잠금 > 결정 필요`에 기록된 결정 항목}
|
||||
- [ ] {SDD 또는 Milestone `구현 잠금 > 결정 필요`에 기록된 결정 항목}
|
||||
|
||||
## 재개 조건
|
||||
|
||||
- {위 결정이 Milestone 구현 잠금에 반영되고, 필요한 경우 해당 USER_REVIEW.md가 user_review_N.log로 해결되어야 한다}
|
||||
- {위 결정이 SDD 또는 Milestone 구현 잠금에 반영되고, 필요한 경우 해당 USER_REVIEW.md가 user_review_N.log로 해결되어야 한다}
|
||||
|
||||
## 다음 실행 힌트
|
||||
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
---
|
||||
name: complete-milestone
|
||||
description: "마일스톤 완료해도 될지 검토, 현 마일스톤 종료 검토, 현재 마일스톤 닫고 다음 마일스톤 지정, 검토중 Milestone 코드레벨 종료 감사 요청에 사용한다. 코드/테스트/계약/evidence를 점검하고 작은 보완은 처리하거나 큰 보완은 plan으로 넘기며, agent-spec이 있으면 update-spec을 필수 gate로 수행한 뒤 update-roadmap으로 완료/archive와 다음 Milestone 지정을 처리한다."
|
||||
---
|
||||
|
||||
# complete-milestone
|
||||
|
||||
## 목적
|
||||
|
||||
`[검토중]` 또는 완료 후보 Milestone을 코드레벨에서 종료해도 되는지 감사하고, 종료 가능할 때 spec sync와 roadmap 완료/archive까지 이어지는 오케스트레이션을 수행한다.
|
||||
`update-spec`과 `update-roadmap`의 책임을 합치지 않고, 이 스킬이 완료 workflow의 순서와 gate를 관리한다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 "마일스톤 완료해도 될지 검토해봐"라고 요청할 때
|
||||
- 사용자가 "현 마일스톤 종료 검토해", "현재 마일스톤 닫고 다음 마일스톤 지정해"라고 요청할 때
|
||||
- `[검토중]` Milestone의 완료 리뷰 통과, archive, 다음 Milestone current 지정 여부를 코드레벨 evidence로 확인해야 할 때
|
||||
- Milestone 종료 시점에 `agent-spec` 갱신이 함께 필요할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `target-milestone`: 종료 검토할 Milestone 경로, 이름, slug. 없으면 `agent-roadmap/current.md`의 활성 Milestone 단일 후보를 사용한다. (선택)
|
||||
- `next-milestone`: 종료 후 `current.md`에 둘 다음 Milestone 후보. 없으면 Phase 흐름에서 자동 후보를 찾되 모호하면 보고한다. (선택)
|
||||
- `mode`: `check-only` 또는 `close`. 기본값은 `close`다. (선택)
|
||||
- `evidence`: 완료 판단에 사용할 complete.log, 테스트 결과, 사용자 설명, PR/커밋 등. (선택)
|
||||
- `verification-context`: 환경, 출처, 명령, 기대 결과, precondition, 제약, gap, confidence를 담은 중립 검증 handoff. 있으면 사용하고 현재 checkout과 다시 대조한다. (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-roadmap/current.md`와 대상 활성 Milestone, 대상 Phase `PHASE.md`를 읽는다.
|
||||
- [ ] `agent-roadmap/priority-queue.md`가 있으면 종료 후 다음 후보와 archive 제거 대상 확인을 위해 읽는다.
|
||||
- [ ] 대상 Milestone의 `상태`, `기능`, `구현 잠금`, `완료 리뷰`, `작업 컨텍스트`, SDD gate를 확인한다.
|
||||
- [ ] 완료 근거 동기화가 필요하면 `sync-milestone-workstate` 절차를 확인한다.
|
||||
- [ ] 종료/archive가 가능하면 `update-roadmap` 절차를 확인한다.
|
||||
- [ ] `agent-spec/`가 있으면 `agent-ops/rules/common/rules-agent-spec.md`와 `update-spec` 절차를 확인한다.
|
||||
- [ ] 코드, 계약, 테스트에 닿는 범위는 project/domain/test/contract 규칙을 따른다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **대상 Milestone 확정**
|
||||
- `target-milestone`이 있으면 활성 Milestone에서 정확히 하나를 찾는다.
|
||||
- 없으면 `agent-roadmap/current.md`의 활성 Milestone 단일 후보를 사용한다.
|
||||
- 대상이 archive 경로이거나 둘 이상이면 수정하지 않고 target 불명확으로 보고한다.
|
||||
|
||||
2. **완료 후보 상태 확인**
|
||||
- 대상 Milestone이 `[검토중]`이면 종료 감사로 진행한다.
|
||||
- `[진행중]` 또는 `[계획]`이면 `sync-milestone-workstate` 기준으로 기능 Task/evidence를 동기화할 수 있는지 먼저 확인한다. 동기화 후 `[검토중]` 조건을 충족하지 못하면 종료 감사로 진행하지 않는다.
|
||||
- `[스케치]`, `[보류]`, `[폐기]`, `[완료]`이면 일반 종료 감사를 진행하지 않고 상태 불일치를 보고한다.
|
||||
- `구현 잠금`이 남아 있거나 미완료 `결정 필요`가 있으면 archive하지 않는다.
|
||||
|
||||
3. **코드레벨 종료 감사**
|
||||
- Milestone `기능` Task와 검증 문구, `완료 리뷰`, complete.log, SDD Evidence Map, 관련 코드/계약/테스트를 비교한다.
|
||||
- `agent-task/archive/**`는 같은 `m-<milestone-slug>` complete.log 후보처럼 규칙상 허용된 범위만 좁게 읽는다.
|
||||
- 코드/계약 변경에 닿으면 관련 domain rule과 `agent-contract/index.md` 라우팅을 따른다.
|
||||
- `verification-context`가 있으면 출처 경로, 명령, 기대 결과, precondition, 제약, gap, confidence가 현재 checkout에 맞는지 확인한다.
|
||||
- handoff가 없거나 불완전하면 repository manifest, script, workflow, domain rule, 관련 테스트와 안전한 read-only probe에서 부족한 검증 사실을 보완한다. 선택 handoff 누락만으로 종료 검토를 차단하지 않는다.
|
||||
|
||||
4. **보완 분기**
|
||||
- 작은 문서/코드/테스트 보완으로 바로 해결 가능한 이슈는 직접 수정하고 검증한다.
|
||||
- Milestone 범위 안의 큰 구현 보완이 필요하면 `plan`을 작성하고 종료를 중단한다.
|
||||
- 제품/범위/우선순위/책임 경계 결정이 필요하면 Milestone `구현 잠금 > 결정 필요` 또는 SDD `USER_REVIEW.md`로 분리하고 종료를 중단한다.
|
||||
- 보완이 발생하면 Milestone 완료 리뷰를 `보완 필요`로 남기고 `[완료]` 전환이나 archive를 하지 않는다.
|
||||
|
||||
5. **Spec Sync Gate**
|
||||
- `mode=check-only`이고 `agent-spec/`가 있으면 `update-spec mode=check-only`로 갱신 필요 여부만 확인한다.
|
||||
- `agent-spec/`가 없으면 `Spec sync: skipped-no-agent-spec`으로 기록하고 종료 흐름을 계속할 수 있다.
|
||||
- `agent-spec/`가 있고 `mode=close`이면 `update-spec`을 필수로 수행한다.
|
||||
- 관련 spec이 없고 Milestone 결과가 현재 구현 지도에 영향을 주면 `create-spec` 필요로 보고하고 종료를 중단한다.
|
||||
- 결과는 반드시 `Spec updated`, `Spec update not needed`, `create-spec needed`, `Spec blocked`, `skipped-no-agent-spec` 중 하나로 정리한다.
|
||||
- `Spec blocked` 또는 `create-spec needed`이면 Milestone을 `[완료]`로 전환하거나 archive하지 않는다.
|
||||
- `Spec updated` 또는 `Spec update not needed`이면 Milestone 완료 리뷰에 `Spec sync` 결과와 spec 문서 링크 또는 사유를 남긴다.
|
||||
|
||||
6. **Milestone 완료와 archive**
|
||||
- `mode=check-only`이면 여기서 쓰지 않고 종료 가능 여부만 보고한다.
|
||||
- 모든 기능 Task, 검증, 구현 잠금, SDD gate, code audit, spec sync gate가 충족되면 `update-roadmap` archive 흐름으로 Milestone을 `[완료]`로 전환하고 archive한다.
|
||||
- `.agent-roadmap-sync/locks.yaml`이 있으면 `update-roadmap`의 workspace lock 검사/동기화 규칙을 따른다.
|
||||
- Phase `PHASE.md`에는 archive 링크와 짧은 요약을 남긴다.
|
||||
- `priority-queue.md`가 있으면 완료/archive된 Milestone 항목을 제거하도록 `update-roadmap` archive 흐름에 포함한다.
|
||||
- `agent-roadmap/current.md`에서 완료 Milestone을 제거한다.
|
||||
|
||||
7. **다음 Milestone 지정**
|
||||
- `next-milestone`이 있으면 활성 Milestone에서 정확히 하나인지 확인하고 `current.md`에 반영한다.
|
||||
- 없고 `priority-queue.md`가 있으면 큐의 위에서 아래 순서 중 완료/archive 대상이 아니고 `[폐기]`가 아닌 첫 활성 Milestone을 다음 후보로 찾는다.
|
||||
- `priority-queue.md`가 없으면 같은 Phase의 Milestone 흐름에서 완료/폐기/archive가 아닌 다음 후보를 찾는다.
|
||||
- 후보가 없거나 둘 이상이면 자동 지정하지 않고 후보와 이유를 보고한다.
|
||||
- 다음 후보가 `[스케치]`이면 구현 대상이 아니라 구체화 대상임을 보고한다.
|
||||
|
||||
8. **결과 보고**
|
||||
- 종료 가능 여부, 수정/생성한 파일, 실행 검증, spec sync 결과, roadmap archive 결과, 다음 Milestone을 보고한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] 대상 Milestone이 활성 경로에서 정확히 하나로 확정되었는가
|
||||
- [ ] Milestone 상태, 기능 Task, 구현 잠금, 완료 리뷰, SDD gate를 확인했는가
|
||||
- [ ] 코드/계약/테스트 evidence를 확인했거나 범위 불명확 사유를 보고했는가
|
||||
- [ ] 전달된 verification context와 repository-native fallback의 출처·gap·confidence를 구분했는가
|
||||
- [ ] 작은 보완은 검증까지 수행하고, 큰 보완은 plan으로 넘겼는가
|
||||
- [ ] `agent-spec/`가 있으면 `update-spec` 결과를 확인하고 완료 진행 가능 상태가 `Spec updated` 또는 `Spec update not needed`인지 판단했는가
|
||||
- [ ] `Spec blocked` 또는 `create-spec needed` 상태에서 Milestone 완료/archive를 하지 않았는가
|
||||
- [ ] `update-roadmap` 완료/archive 규칙과 workspace lock 규칙을 따랐는가
|
||||
- [ ] `priority-queue.md`가 있으면 완료/archive된 Milestone이 제거되었고 다음 후보 판단에 큐 순서가 반영되었는가
|
||||
- [ ] 완료 Milestone이 `current.md`에 남아 있지 않은가
|
||||
- [ ] 다음 Milestone 지정이 모호하면 자동 선택하지 않았는가
|
||||
- [ ] `git diff --check`를 실행했는가
|
||||
- 검증 실패 시: archive 이동을 하지 않고 실패 사유와 필요한 후속 작업을 보고한다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```markdown
|
||||
## Milestone 종료 검토 결과
|
||||
|
||||
- 대상 Milestone: [<title>](agent-roadmap/phase/<phase>/milestones/<milestone>.md)
|
||||
- 판정: <종료 완료 | 종료 가능-check-only | 보완 필요 | plan 작성 | 차단>
|
||||
- 코드레벨 감사: <통과 | 보완 내용 | 차단 사유>
|
||||
- 검증:
|
||||
- `<command>` - <PASS | FAIL | BLOCKED>; <요약>
|
||||
- Spec sync: <updated | not-needed | create-spec needed | blocked | skipped-no-agent-spec>
|
||||
- <[spec](agent-spec/<area>/<spec-id>.md) | 사유>
|
||||
- Roadmap: <archive 완료 | 변경 없음 | 차단>
|
||||
- 다음 Milestone: <[title](agent-roadmap/phase/<phase>/milestones/<next>.md) | 미지정: 사유>
|
||||
- 수정 파일:
|
||||
- <없음 | [path](path)>
|
||||
|
||||
## TODO 항목
|
||||
|
||||
- <남은 차단 항목 또는 없음>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- `update-spec`과 `update-roadmap`의 책임을 이 스킬 본문에 합쳐서 재정의하지 않는다.
|
||||
- `Spec blocked` 또는 `create-spec needed`인데 Milestone을 `[완료]`로 전환하거나 archive하지 않는다.
|
||||
- 큰 구현 보완을 종료 검토 중 임의로 처리하지 않는다. `plan`으로 넘긴다.
|
||||
- archive 전체를 일반 탐색하지 않는다.
|
||||
- 구현 잠금이나 미해결 SDD 사용자 리뷰가 남은 Milestone을 완료 처리하지 않는다.
|
||||
- 다음 Milestone 후보가 모호한데 자동으로 선택하지 않는다.
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
---
|
||||
name: create-agent-ui
|
||||
version: 1.1.0
|
||||
description: 프로젝트 코드 또는 문서 근거를 분석해 agent-ui 기본 스캐폴드와 최초 코드 동기화 기준선을 생성하는 스킬
|
||||
---
|
||||
|
||||
# create-agent-ui
|
||||
|
||||
## 목적
|
||||
|
||||
프로젝트의 기존 UI 코드나 컨셉 문서를 근거로 `agent-ui/` 기본 구조와 UI 정의 초안을 생성한다.
|
||||
ops/dev UI를 1차 대상으로 하며, 생성 결과를 최초 agent-ui 기준선으로 보고 `.sync-state.json`을 만든다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 agent-ui 생성, UI 스캐폴드 생성, 화면 정의 구조 생성을 요청할 때
|
||||
- 프로젝트에 `agent-ui/`가 없고 기존 코드 또는 문서에서 UI 정의 문맥을 추출할 때
|
||||
- UI 코드가 있으면 구현 상태와 동기화된 view/component/frame 초안이 필요할 때
|
||||
- UI 코드가 아직 부족하면 README, roadmap, SDD, docs 같은 컨셉 문서 기반 최소 view tree가 필요할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `surface-type`: `ops-dev` 또는 `product`. 기본값은 `ops-dev` (선택)
|
||||
- `source-mode`: `auto`, `code-first`, `concept-first`, `blank` 중 하나. 기본값은 `auto` (선택)
|
||||
- `views`: 초기 생성할 view id 목록, kebab-case (선택)
|
||||
- `components`: 초기 생성할 component id 목록, kebab-case 또는 path id (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/rules/common/rules-agent-ui.md`를 읽는다.
|
||||
- [ ] 생성 대상 `agent-ui/` 존재 여부를 확인한다.
|
||||
- [ ] 기존 `agent-ui/`가 있으면 덮어쓰지 않고 `update-agent-ui` 또는 `validate-agent-ui` 대상인지 보고한다.
|
||||
- [ ] 템플릿 경로 `agent-ops/skills/common/_templates/agent-ui/` 하위 파일을 확인한다.
|
||||
- [ ] `source-mode=auto`이면 UI 코드 후보와 컨셉 문서 후보를 모두 가볍게 확인한다.
|
||||
- [ ] baseline commit/push를 위해 현재 git status와 HEAD를 확인한다.
|
||||
- [ ] unrelated dirty worktree가 있으면 baseline commit 전에 범위를 보고하고, agent-ui 생성 파일만 stage한다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **생성 대상 확정**
|
||||
- 생성 루트는 `agent-ui/`로 고정한다.
|
||||
- `surface-type`이 없으면 `ops-dev`로 둔다.
|
||||
- `source-mode`가 없으면 `auto`로 둔다.
|
||||
- product UI가 명시되어도 기본 구조는 유지하고 product 전용 레이어는 요청된 경우에만 추가 후보로 보고한다.
|
||||
|
||||
2. **근거 수집**
|
||||
- `code-first` 또는 `auto`에서는 UI 구현 후보를 찾는다.
|
||||
- 예: `apps/**/lib/**`, `packages/**/lib/**`, `src/**`, `app/**`, `pages/**`, `screens/**`, `views/**`, `components/**`, `widgets/**`, route/navigation/shell 파일
|
||||
- 프로젝트 규칙에 dedicated UI domain rule이 있으면 먼저 따른다.
|
||||
- 코드가 많으면 전체 정독하지 말고 route, shell, page/view, widget/component 이름 중심으로 후보를 좁힌다.
|
||||
- `concept-first` 또는 `auto`에서는 컨셉 문서 후보를 찾는다.
|
||||
- 예: `README.md`, `docs/**`, `agent-roadmap/current.md`, 활성 Phase/Milestone, 승인된 SDD, `agent-ops/rules/project/rules.md`
|
||||
- roadmap 문서는 `agent-ops/rules/common/rules-roadmap.md`의 loading/archive 접근 규칙을 따른다.
|
||||
- archive 문서는 사용자가 과거 근거를 명시하지 않는 한 읽지 않는다.
|
||||
- 근거가 없거나 사용자가 빈 구조를 요청하면 `blank`로 처리한다.
|
||||
|
||||
3. **source-mode 결정**
|
||||
- `auto`에서 route, shell, page/view, widget/component 후보 중 하나 이상이 실제 파일 경로로 확인되면 `code-first`로 생성한다.
|
||||
- UI 구현 후보가 부족하고 컨셉 문서 후보가 있으면 `concept-first`로 생성한다.
|
||||
- 코드와 문서 근거가 모두 부족하면 `blank`로 생성하고 부족한 근거를 결과에 보고한다.
|
||||
- 명시된 `views` 또는 `components`는 선택된 mode와 함께 생성 후보로 반영한다.
|
||||
|
||||
4. **기본 구조 생성**
|
||||
- 다음 활성 문서를 템플릿 기준으로 만든다.
|
||||
- `agent-ui/README.md`
|
||||
- `agent-ui/definition/index.md`
|
||||
- `agent-ui/definition/views/index.md`
|
||||
- `agent-ui/definition/components/index.md`
|
||||
- `agent-ui/frame/index.md`
|
||||
- 생성하는 활성 Markdown 문서에는 `rules-agent-ui.md`의 Frontmatter Schema를 적용한다.
|
||||
- 다음 archive/user-review 디렉터리가 빈 상태로 필요하면 `.gitkeep`을 둘 수 있다.
|
||||
- `agent-ui/definition/archive/views/`
|
||||
- `agent-ui/definition/archive/components/`
|
||||
- `agent-ui/archive/user-review/`
|
||||
- `USER_REVIEW.md`는 사용자 판단 항목이 있을 때만 만든다.
|
||||
|
||||
5. **초기 view 생성**
|
||||
- `code-first`에서는 구현 코드에서 확인된 route/page/view/shell 단위를 view 후보로 만든다.
|
||||
- `concept-first`에서는 문서에서 확인된 운영 업무, 화면, 콘솔 영역을 view 후보로 만든다.
|
||||
- `blank`에서는 명시 `views`가 있을 때만 view 후보를 만든다.
|
||||
- 각 view 후보마다 다음 문서를 만든다.
|
||||
- `agent-ui/definition/views/<view-id>/index.md`
|
||||
- view 문서에는 `Source Evidence`와 `Status`를 반드시 남긴다.
|
||||
- 코드 근거가 있으면 `status: 구현됨`
|
||||
- 문서 근거만 있으면 `status: 계획`
|
||||
- 명시 입력만 있고 근거가 부족하면 `status: 가정`
|
||||
- 판단 불가하면 `status: 불명확`과 USER_REVIEW 항목을 남긴다.
|
||||
- 실제 근거 파일이 없으면 frontmatter `source_evidence[].path`는 `null`로 둔다.
|
||||
- visual source가 없는 초기 view 문서의 frontmatter `frame`은 `null`로 둔다.
|
||||
- frontmatter의 `status`, `source_evidence`, `regions`와 본문 `Status`, `Source Evidence`, `Regions`가 같은 기준을 말하게 작성한다.
|
||||
- `.excalidraw` 파일은 사용자가 요청했을 때만 빈 visual source로 만들거나 생성 후보로 보고한다.
|
||||
- `.excalidraw` 또는 다른 visual source를 만들거나 연결할 때만 `agent-ui/frame/views/<view-id>/index.md`를 만든다.
|
||||
- `.excalidraw`를 만들거나 연결하면 주요 박스 text label 또는 `customData.region_id`에 region id를 넣는다.
|
||||
- view id는 kebab-case가 아니면 정규화 후보를 보고하고 사용자 확인이 필요하면 생성하지 않는다.
|
||||
|
||||
6. **초기 component 생성**
|
||||
- `code-first`에서는 반복 widget/component/table/filter/log/status/action 단위를 component 후보로 만든다.
|
||||
- `concept-first`에서는 문서상 반복 패턴이 분명한 data table, status badge, filter bar, log viewer 같은 구성요소만 component 후보로 만든다.
|
||||
- `blank`에서는 명시 `components`가 있을 때만 component 후보를 만든다.
|
||||
- 각 component 후보마다 `agent-ui/definition/components/<component-id>/index.md`를 만든다.
|
||||
- component 문서에는 `Source Evidence`와 `Status`를 반드시 남긴다.
|
||||
- 실제 근거 파일이 없으면 frontmatter `source_evidence[].path`는 `null`로 둔다.
|
||||
- component id가 path id이면 하위 디렉터리 구조로 만든다.
|
||||
- view에서 참조하지 않는 component도 사용자가 명시했으면 생성할 수 있다.
|
||||
|
||||
7. **불확실성 분리**
|
||||
- 코드와 문서가 충돌하면 임의로 통합하지 않고 `agent-ui/USER_REVIEW.md`에 남긴다.
|
||||
- view 경계, component 신규 생성 여부, page/drawer/split 같은 UX 판단은 USER_REVIEW로 남긴다.
|
||||
- 문서 근거만 있는 계획 항목을 구현 완료처럼 쓰지 않는다.
|
||||
|
||||
8. **정합성 검증과 baseline 기록**
|
||||
- 생성 직후 `validate-agent-ui`를 실행해 scaffold와 문서 간 정합성을 확인하고 자동 보정한다.
|
||||
- `agent-ui/.sync-state.json`에 기록할 baseline 내용을 준비한다.
|
||||
- `baseline_mode`는 선택된 `source-mode`로 둔다.
|
||||
- `code-first`, `concept-first`, `blank` 모두 생성된 agent-ui를 최초 기준선으로 본다.
|
||||
- baseline commit은 두 단계로 남긴다.
|
||||
- 먼저 `.sync-state.json`을 제외한 agent-ui 생성/보정 파일을 commit한다.
|
||||
- 그 commit hash를 새 `agent-ui/.sync-state.json`의 `last_synced_head`에 기록한 뒤 별도 commit한다.
|
||||
- commit message는 예를 들어 `docs(agent-ui): create baseline`과 `sync: record agent-ui baseline`처럼 목적이 분리되게 쓴다.
|
||||
- 두 commit을 push한다.
|
||||
- USER_REVIEW가 생성되어도 생성 baseline은 남길 수 있다. 단, 이후 `sync-agent-ui`는 관련 USER_REVIEW가 해결될 때까지 실행하지 않는다.
|
||||
|
||||
9. **결과 보고**
|
||||
- 선택된 `source-mode`
|
||||
- 읽은 근거 파일과 생성에 사용한 evidence
|
||||
- 생성한 파일
|
||||
- 적용한 frontmatter schema
|
||||
- 생성한 view/component의 status
|
||||
- USER_REVIEW 생성 여부
|
||||
- `.sync-state.json` 생성 여부와 baseline commit hash
|
||||
- baseline commit/push 결과
|
||||
- product UI 확장 후보
|
||||
- 후속 권장 작업
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `agent-ui/README.md`가 생성되었는가
|
||||
- [ ] `definition/index.md`, `definition/views/index.md`, `definition/components/index.md`, `frame/index.md`가 생성되었는가
|
||||
- [ ] 활성 Markdown 문서가 `ui_doc_type` frontmatter를 포함하는가
|
||||
- [ ] view/component는 folder-first + `index.md` 구조를 사용하는가
|
||||
- [ ] 생성한 view/component에 `Source Evidence`와 `Status`가 있는가
|
||||
- [ ] 구현 근거 없는 항목을 `구현됨`으로 표시하지 않았는가
|
||||
- [ ] visual source가 없는 view에 빈 `frame/views/<view-id>/index.md`를 만들지 않았는가
|
||||
- [ ] 코드/문서 충돌이나 UI 의도 판단이 필요한 항목이 USER_REVIEW에 남았는가
|
||||
- [ ] 같은 레벨에 `<name>.md`와 `<name>/`가 함께 생기지 않았는가
|
||||
- [ ] archive 본문 파일을 불필요하게 생성하지 않았는가
|
||||
- [ ] `validate-agent-ui` 결과가 PASS 또는 자동 보정 완료 WARN으로 보고되었는가
|
||||
- [ ] `.sync-state.json`이 생성되었고 `last_synced_head`가 baseline commit을 가리키는가
|
||||
- [ ] baseline commit/push가 완료되었는가
|
||||
- [ ] unrelated dirty file이 baseline commit에 포함되지 않았는가
|
||||
- 검증 실패 시: 누락된 scaffold만 보완하고 기존 문서를 덮어쓰지 않는다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```md
|
||||
## 생성 완료
|
||||
|
||||
- 루트: agent-ui/
|
||||
- source-mode: <code-first|concept-first|blank>
|
||||
- evidence: <주요 근거 파일 목록>
|
||||
- 생성 파일: <목록>
|
||||
- frontmatter schema: <적용/부분 적용/없음>
|
||||
- views: <view-id=status 목록 또는 없음>
|
||||
- components: <component-id=status 목록 또는 없음>
|
||||
- USER_REVIEW: <생성/없음>
|
||||
- sync state: <생성/없음, last_synced_head>
|
||||
- baseline commit/push: <완료/실패/생략 사유>
|
||||
- 확인 필요: <항목 또는 없음>
|
||||
- 후속 권장: <필요 시 sync-agent-ui 또는 없음>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 기존 `agent-ui/` 문서를 덮어쓰지 않는다.
|
||||
- `.excalidraw` 파일을 현재 UI source of truth로 만들지 않는다.
|
||||
- 코드나 문서 근거 없이 화면 의도를 확정하지 않는다.
|
||||
- 문서 근거만 있는 항목을 구현 완료 상태로 쓰지 않는다.
|
||||
- product UI 전용 레이어를 요청 없이 추가하지 않는다.
|
||||
- `definition/archive/**`나 `archive/user-review/**`에 현재 기준 문서를 만들지 않는다.
|
||||
- baseline commit 없이 `.sync-state.json`의 `last_synced_head`를 추정하지 않는다.
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
---
|
||||
name: create-contract
|
||||
version: 1.0.0
|
||||
description: agent-contract 구조와 inner/outer 계약 문서를 생성한다. 계약 생성해, 프로젝트 계약 생성해, contract 생성, agent-contract 생성, inner/outer 계약 생성 요청에서 사용한다.
|
||||
---
|
||||
|
||||
# create-contract
|
||||
|
||||
## 목적
|
||||
|
||||
프로젝트에 계약 관리가 필요해진 시점에 `agent-contract/` 구조를 생성하고, 흩어진 문서와 코드에서 확인한 계약을 `inner/outer` 기준으로 정리한다.
|
||||
계약 문서는 schema 원본을 복제하지 않고, agent가 읽을 수 있는 라우팅, 원본 경로, 필드 의미, 변경 규칙, 검증 포인터를 한 곳에 모은다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 계약 생성, 프로젝트 계약 생성, contract 생성, agent-contract 생성을 요청할 때
|
||||
- API, runtime 호출, wire protocol, event/config schema 같은 계약을 처음 문서화할 때
|
||||
- 프로젝트에 `agent-contract/`가 없고, 둘 이상의 프로젝트/프로세스/앱/도메인이 맞춰야 하는 요청/응답 경계가 확인될 때
|
||||
- 기존 README/docs/rules/code에 흩어진 계약 설명을 새 계약 구조로 모아야 할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `contract-id`: 계약 식별자, kebab-case 또는 dotted id (선택, 없으면 분석으로 후보 산출)
|
||||
- `boundary`: `inner` 또는 `outer` (선택, 없으면 실제 소비자와 경계로 판정)
|
||||
- `scope`: 계약 범위 요약. 예: public HTTP API, worker-runtime protocol, app-server wire (선택, 없으면 코드/문서에서 산출)
|
||||
- `canonical-path`: proto/OpenAPI/config/code 등 schema 원본 경로 (선택, 없으면 분석으로 찾음)
|
||||
- `trigger-conditions`: 계약 문서를 읽어야 하는 조건 목록 (선택)
|
||||
|
||||
## 분류 기준
|
||||
|
||||
- `outer`: 프로젝트 바깥 caller나 다른 프로젝트가 직접 맞춰야 하는 계약이다. 예: 공개 HTTP API, webhook, 외부 SDK, 외부 agent handoff.
|
||||
- `inner`: 같은 프로젝트 안이어도 프로세스, 앱, 도메인, runtime 경계를 넘는 계약이다. 예: controller-worker proto, service-service wire, app-server WebSocket, runtime request/event/config schema.
|
||||
- 제외: 한 패키지 내부 private interface, 코드만 보면 충분한 DTO, 안정화되지 않은 실험 구조, 단일 구현 내부 helper.
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-contract/` 존재 여부를 확인한다.
|
||||
- [ ] `agent-contract/index.md`가 있으면 읽고 기존 구조와 중복 id를 확인한다.
|
||||
- [ ] 요청 범위와 관련된 코드, proto, config, README/docs/rules를 읽어 원본 경로와 흩어진 계약 설명을 찾는다.
|
||||
- [ ] 계약 원문을 이미 docs/README/rules에 길게 복제하고 있는지 확인한다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **필요성 판정**
|
||||
- 둘 이상의 프로젝트/프로세스/앱/도메인이 맞춰야 하는 안정 경계인지 확인한다.
|
||||
- 단일 패키지 내부 구현이면 계약 문서를 만들지 않고 이유를 보고한다.
|
||||
- 단건 `contract-id`가 없으면 코드와 문서에서 계약 후보를 수집하고, 안정 경계가 확인된 후보만 생성한다.
|
||||
- 후보는 있지만 boundary나 원본 경로가 불명확하면 문서를 억지로 만들지 않고 `확인 필요`로 보고한다.
|
||||
|
||||
2. **구조 생성**
|
||||
- `agent-contract/index.md`가 없으면 생성한다.
|
||||
- `agent-contract/inner/`와 `agent-contract/outer/`가 없으면 생성한다.
|
||||
- legacy `provided/consumed/`가 있으면 덮어쓰지 않고, 이번 생성 결과와 충돌하는지 보고한다.
|
||||
|
||||
3. **코드와 문서 분석**
|
||||
- 관련 schema 원본을 먼저 찾는다. 우선순위는 proto/OpenAPI/schema 파일, config struct, public DTO/interface, handler/parser, 테스트 fixture 순서다.
|
||||
- README/docs/rules에 흩어진 계약 설명을 찾고, 계약 문서에 필요한 내용만 추린다.
|
||||
- 필드 의미는 코드와 테스트에서 확인한 것만 쓴다. 추측은 `확인 필요`로 남긴다.
|
||||
|
||||
4. **계약 문서 작성**
|
||||
- 경로는 `agent-contract/<inner|outer>/<contract-name>.md`로 둔다.
|
||||
- 여러 계약을 생성해야 하면 각 문서는 독립된 경계 단위로 나누고, 공통 설명은 index가 아니라 각 계약의 원본 경로 포인터로 해결한다.
|
||||
- 문서는 짧게 유지하고 다음 항목을 포함한다.
|
||||
- 계약 메타: id, boundary, 원본 경로, status(필요한 경우)
|
||||
- 읽는 조건
|
||||
- 범위와 비범위
|
||||
- 최소 요청/응답 또는 message/event 형태
|
||||
- 필드 의미와 금지 사항
|
||||
- 변경 시 확인할 코드/테스트
|
||||
- 원본 schema 전체를 복제하지 않는다. 긴 schema는 원본 경로와 핵심 필드 의미만 둔다.
|
||||
|
||||
5. **index 갱신**
|
||||
- `Outer Contracts`와 `Inner Contracts` 섹션을 둔다.
|
||||
- outer/inner 표는 `id`, `읽는 조건`, `원본 경로`, `path`를 둔다.
|
||||
- 매칭 조건은 agent가 검색/판단할 수 있는 API 이름, message 이름, field 이름, runtime 이름, protocol 이름을 포함한다.
|
||||
- 프로젝트 전용 path trigger는 공통 rule이 아니라 `agent-contract/index.md`의 `읽는 조건`/`원본 경로` 또는 project/domain rule 포인터로 둔다.
|
||||
|
||||
6. **흩어진 문서 정리**
|
||||
- README/docs/rules에 계약 본문이 중복되어 있으면 원문 경로 포인터로 줄인다.
|
||||
- domain rule에는 소유권, 경계, 금지 사항만 남기고 상세 schema는 계약 문서 또는 원본 경로를 가리킨다.
|
||||
- common rule에는 특정 프로젝트 경로, 계약 id, API 이름을 추가하지 않는다. common rule은 `agent-contract/index.md` 조건부 진입까지만 담당한다.
|
||||
- 사람용 최신 가이드가 필요한 README 문구는 유지하되 계약 원문과 충돌하지 않게 축소한다.
|
||||
|
||||
7. **결과 보고**
|
||||
- 생성한 index와 계약 문서
|
||||
- boundary 판정 근거
|
||||
- 원본 경로
|
||||
- 중복 제거 또는 포인터화한 문서
|
||||
- 확인 필요 항목
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `agent-contract/index.md`가 생성되고 inner/outer 라우팅 표를 포함하는가
|
||||
- [ ] 계약 문서가 `agent-contract/inner/` 또는 `agent-contract/outer/` 아래에 있는가
|
||||
- [ ] 계약 id가 index와 문서 메타에서 일치하는가
|
||||
- [ ] 원본 경로가 실제 존재하거나 외부 원본으로 명확히 적혀 있는가
|
||||
- [ ] README/docs/rules에 계약 본문이 중복 복제되지 않고 포인터만 남았는가
|
||||
- [ ] 코드/proto/config/test 분석 없이 계약을 추정하지 않았는가
|
||||
- 검증 실패 시: 누락된 index, 문서 메타, 포인터, 원본 경로만 보완한다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```md
|
||||
## 계약 생성 완료
|
||||
|
||||
- index: agent-contract/index.md
|
||||
- contracts: agent-contract/<inner|outer>/<contract-name>.md
|
||||
- boundary: <inner|outer> (<근거>)
|
||||
- 원본 경로: <path 또는 외부 원본>
|
||||
- pointers: <갱신한 README/docs/rules 경로 또는 없음>
|
||||
- 확인 필요: <항목 또는 없음>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 모든 내부 interface를 계약 문서로 만들지 않는다.
|
||||
- 원본 schema 전체를 계약 문서에 장황하게 복제하지 않는다.
|
||||
- 코드/proto/config/test 확인 없이 필드 의미를 단정하지 않는다.
|
||||
- README/docs/rules에 계약 본문을 계속 중복 유지하지 않는다.
|
||||
- 프로젝트 전용 path trigger를 common rule에 넣지 않는다.
|
||||
- legacy `provided/consumed/` 구조가 있어도 사용자 요청 없이 대량 이동하지 않는다.
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
---
|
||||
name: create-handoff
|
||||
version: 1.0.0
|
||||
description: 작업을 다른 세션이나 다른 에이전트가 이어받을 수 있도록 핸즈오프 기록을 남기는 공통 스킬. "핸즈오프 남겨", "인수인계 작성", "다른 세션에서 이어가게 정리", "작업을 이어받도록 기록" 같은 요청에 사용한다.
|
||||
---
|
||||
|
||||
# Create Handoff
|
||||
|
||||
## 목적
|
||||
|
||||
현재 작업 상태를 중단 없이 이어받을 수 있도록 짧고 검증 가능한 핸즈오프 기록을 남긴다.
|
||||
핸즈오프는 새 구현 계획이나 코드 변경을 시작하는 절차가 아니라, 현재 상태와 다음 진입점을 보존하는 절차다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 작업을 다른 세션, 다른 에이전트, 또는 이후 자기 자신이 이어가게 정리해 달라고 할 때
|
||||
- 긴 작업 중 현재 판단, 변경 파일, 남은 검증, 차단 사항을 지속 가능한 문서에 남겨야 할 때
|
||||
- 구현을 계속하지 않고 현재 위치만 안전하게 넘겨야 할 때
|
||||
- 실패한 검증이나 외부 환경 상태를 다음 세션이 오해하지 않도록 남겨야 할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `handoff-request`: 사용자가 남기라고 한 핸즈오프 요청 문장 (필수)
|
||||
- `target`: 현재 작업 대상 Phase, Milestone, plan, review, task group, issue, PR, 파일 경로 등 (선택)
|
||||
- `evidence`: 이번 세션에서 확인한 명령, 테스트, 로그, 외부 상태, 사용자 결정 (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] 현재 작업 대상이 명시되어 있으면 해당 활성 문서나 파일을 확인한다.
|
||||
- [ ] 대상이 없으면 로컬 current, 활성 PLAN/CODE_REVIEW/USER_REVIEW, git diff, 최근 대화 맥락 중 가장 좁은 충분한 대상으로 정한다.
|
||||
- [ ] 기존 핸즈오프 섹션이나 `HANDOFF.md`가 있으면 새 위치를 만들기 전에 갱신 후보로 본다.
|
||||
- [ ] archive 경로는 일반 작업에서 읽지 않는다. 사용자가 archive 확인을 명시했거나 활성 문서가 특정 archive evidence를 가리킬 때만 필요한 파일을 좁게 읽는다.
|
||||
- [ ] secret, token, private endpoint 원문, 서명값, 개인 credential은 핸즈오프에 기록하지 않는다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **상태 수집**
|
||||
- `git status --short`로 변경 파일과 untracked 파일을 확인한다.
|
||||
- 필요한 경우 대상 파일의 diff 또는 관련 문서를 읽어 이번 세션에서 실제로 바뀐 내용과 바뀌지 않은 내용을 분리한다.
|
||||
- 실행 중인 서버, 원격 runner, 외부 provider 같은 live 상태가 handoff에 영향을 주면 secret 없이 요약한다.
|
||||
|
||||
2. **기록 위치 선택**
|
||||
- 활성 Milestone이 작업의 장기 기준이면 해당 Milestone의 `작업 컨텍스트` 아래에 `핸즈오프(<YYYY-MM-DD>)` 항목을 추가하거나 갱신한다.
|
||||
- 활성 plan/review/task group이 작업의 실행 기준이면 그 디렉터리의 기존 `PLAN-*.md`, `CODE_REVIEW-*.md`, `USER_REVIEW.md`, 또는 `HANDOFF.md` 중 가장 직접적인 파일에 남긴다.
|
||||
- 적절한 활성 문서가 없으면 새 파일을 만들기보다 최종 답변에만 남길지 판단하고, 지속 기록이 필요하면 가장 좁은 활성 작업 디렉터리 아래 `HANDOFF.md`를 만든다.
|
||||
- 같은 내용을 여러 곳에 중복 기록하지 않는다. 필요하면 한 곳에 기록하고 다른 문서에는 짧은 링크만 남긴다.
|
||||
|
||||
3. **핸즈오프 작성**
|
||||
- 현재 타겟과 다음 세션의 첫 진입 파일을 적는다.
|
||||
- 이번 세션에서 실제로 한 일과 하지 않은 일을 분리한다.
|
||||
- 남은 작업을 실행 순서로 적되, 구현 세부 계획으로 과하게 확장하지 않는다.
|
||||
- 검증한 명령과 결과, 생략한 검증과 사유를 남긴다.
|
||||
- dirty worktree, untracked 파일, 원격 환경, 외부 provider 상태처럼 다음 세션이 오해하기 쉬운 조건을 남긴다.
|
||||
- 사용자 결정이나 명시 금지 사항을 그대로 보존한다.
|
||||
|
||||
4. **검증**
|
||||
- 수정한 Markdown이나 text 파일에 대해 `git diff --check`를 실행한다.
|
||||
- 새 `HANDOFF.md`를 만들었다면 경로가 active 작업 범위 안인지 확인한다.
|
||||
- 핸즈오프가 완료/검토중/통과 같은 상태 전환을 암시하지 않는지 확인한다.
|
||||
|
||||
5. **결과 보고**
|
||||
- 핸즈오프를 남긴 경로를 보고한다.
|
||||
- 다음 세션이 바로 열어야 할 파일 1~3개를 보고한다.
|
||||
- 검증 명령과 결과를 보고한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] 핸즈오프가 지속 가능한 활성 문서나 가장 좁은 작업 디렉터리에 남아 있다.
|
||||
- [ ] 현재 타겟, 실제 변경, 남은 작업, 검증 상태, 주의사항이 구분되어 있다.
|
||||
- [ ] secret 또는 credential 원문이 기록되지 않았다.
|
||||
- [ ] archive 문서를 불필요하게 읽거나 최신 형식으로 재작성하지 않았다.
|
||||
- [ ] `git diff --check`가 통과했다.
|
||||
- 검증 실패 시: 핸즈오프 문서만 보완하고, 본 작업 구현이나 상태 전환은 진행하지 않는다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```markdown
|
||||
## 핸즈오프 완료
|
||||
|
||||
- 위치: `<handoff-path>`
|
||||
- 현재 타겟: `<target>`
|
||||
- 다음 진입점: `<file-or-command>`
|
||||
- 검증: `<command>` PASS
|
||||
- 남은 주의: `<요약 또는 없음>`
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 핸즈오프 요청만 받았는데 새 구현, 테스트 보강, 리팩터링, 원격 배포를 시작하지 않는다.
|
||||
- evidence 없이 완료, 검토중, PASS, archive 같은 상태 전환을 하지 않는다.
|
||||
- secret, token, private signing key, password, 원문 credential을 기록하지 않는다.
|
||||
- 여러 문서에 같은 핸즈오프 전문을 중복 작성하지 않는다.
|
||||
- 사용자 또는 다른 에이전트가 만든 unrelated 변경을 되돌리지 않는다.
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
---
|
||||
name: create-roadmap
|
||||
description: AI-first 개인/소규모 프로젝트의 전체 목표, Phase scaffold, Phase 하위 Milestone 문서, 전역 priority-queue.md 실행 순서 문서, 로컬 current.md 활성 Phase/Milestone 창, archive Phase scaffold를 처음 생성할 때 사용한다.
|
||||
version: 1.16.1
|
||||
description: AI-first 개인/소규모 프로젝트의 전체 목표, Phase scaffold, Phase 하위 Milestone 문서, 로컬 current.md 활성 Phase/Milestone 창, archive Phase scaffold를 처음 생성하는 공통 스킬
|
||||
---
|
||||
|
||||
# 로드맵 생성
|
||||
|
||||
## 목적
|
||||
|
||||
`agent-roadmap/` 하위에 `Roadmap -> priority-queue -> Phase -> Milestone` 기반 한국어 로드맵 구조를 처음 생성한다.
|
||||
`agent-roadmap/` 하위에 `Roadmap -> Phase -> Milestone` 기반 한국어 로드맵 구조를 처음 생성한다.
|
||||
전체 로드맵은 전체 방향과 Phase index만 담당하고, 일반 작업에서는 브랜치별 로컬 `current.md`의 활성 Phase/Milestone 링크와 관련 문서만 읽도록 만든다.
|
||||
`priority-queue.md`는 Phase를 가로지르는 실행 순서만 담당한다.
|
||||
Milestone은 구현 계획이 아니라 방향성, 범위, 위험, 확인 필요 사항을 기록하는 협업 문서다.
|
||||
Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능` 안에서 관리한다. 별도 `완료 기준` 섹션은 만들지 않고, 검증이 필요한 기능에만 같은 Task 안의 `검증:` 문구로 통합한다.
|
||||
|
||||
|
|
@ -32,7 +32,6 @@ Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능
|
|||
```text
|
||||
agent-roadmap/
|
||||
ROADMAP.md
|
||||
priority-queue.md
|
||||
current.md # local, git ignored
|
||||
phase/
|
||||
<phase-slug>/
|
||||
|
|
@ -59,7 +58,6 @@ agent-roadmap/
|
|||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `agent-roadmap/ROADMAP.md` | 전체 목표와 Phase 흐름만 담는 최상위 지도. 로드맵 생성/갱신/Phase 전환 때만 읽는다 |
|
||||
| `agent-roadmap/priority-queue.md` | Phase를 가로지르는 Milestone 실행 순서만 담는 순서 전용 문서 |
|
||||
| `agent-roadmap/current.md` | 활성 Phase와 활성 Milestone 후보, 선택 규칙을 담는 브랜치별 로컬 포인터 |
|
||||
| `agent-roadmap/phase/<phase-slug>/PHASE.md` | Phase 목표, 상태, Milestone 흐름, Phase 경계를 담는 문서 |
|
||||
| `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` | 일반 작업 시 읽는 Milestone 단위 목표, 스케치 승격 조건, 구현 잠금, 범위, 기능 Epic/Task 체크리스트, 범위 제외 항목 |
|
||||
|
|
@ -71,14 +69,12 @@ agent-roadmap/
|
|||
## 템플릿
|
||||
|
||||
- `ROADMAP.md`는 `agent-ops/skills/common/_templates/roadmap-template.md` 형식을 따른다.
|
||||
- `priority-queue.md`는 `agent-ops/skills/common/_templates/roadmap-priority-queue-template.md` 형식을 따른다.
|
||||
- `current.md`는 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식을 따른다.
|
||||
- `PHASE.md`는 `agent-ops/skills/common/_templates/roadmap-phase-template.md` 형식을 따른다.
|
||||
- Milestone 문서는 `agent-ops/skills/common/_templates/roadmap-milestone-template.md` 형식을 따른다.
|
||||
- SDD 본문은 `agent-ops/skills/common/_templates/roadmap-sdd-template.md` 형식을 따른다.
|
||||
- SDD 사용자 리뷰는 `agent-ops/skills/common/_templates/roadmap-sdd-user-review-template.md` 형식을 따른다.
|
||||
- `ROADMAP.md`에는 Milestone 상세 체크리스트를 넣지 않는다.
|
||||
- `priority-queue.md`는 순서 전용 문서이며, Milestone 제목 링크와 식별용 한 줄 설명만 둔다.
|
||||
- `current.md`는 git 추적 대상이 아니며, 예시 파일을 `agent-roadmap/`에 따로 만들지 않는다.
|
||||
- `current.md`는 활성 Phase/Milestone 후보만 담고, 개인별 현재 작업 위치나 완료 상태를 적지 않는다.
|
||||
- archive 경로는 `current.md`의 활성 항목에 넣지 않는다.
|
||||
|
|
@ -90,19 +86,11 @@ agent-roadmap/
|
|||
- `[스케치]`는 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태다. 구현 가능한 계획이 아니므로 구현 계획 생성 대상이 아니다.
|
||||
- `[계획]`은 목표, 범위, 기능 Task, 구현 잠금, 결정 필요 항목이 문서화되어 잠금 해제 후 구현 계획을 만들 수 있는 상태다.
|
||||
- Phase와 Milestone 이름, 파일명에는 `1`, `2`, `M01`, `P1` 같은 순번을 붙이지 않는다.
|
||||
- Phase 흐름은 실행 순서가 아니라 도메인/책임 영역의 구조적 지도다.
|
||||
- Phase를 가로지르는 실제 실행 순서는 `priority-queue.md`의 위에서 아래 순서로 표현한다.
|
||||
- `priority-queue.md`에는 상태, 목표, 범위, 잠금, 기능, 완료 근거, 의존성 필드를 복제하지 않는다.
|
||||
- 실행 후보가 없더라도 `priority-queue.md` 파일과 `실행 순서` 섹션은 생성한다.
|
||||
- 진행 순서는 `ROADMAP.md`와 각 `PHASE.md`의 위에서 아래 순서로 표현한다.
|
||||
- Phase 파일명은 `agent-roadmap/phase/<phase-slug>/PHASE.md`로 만든다.
|
||||
- Milestone 파일명은 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`로 만든다.
|
||||
- `<phase-slug>`와 `<milestone-slug>`는 소문자 영문, 숫자, 하이픈만 사용하고, 공백/언더스코어/순번 prefix를 넣지 않는다.
|
||||
- 중간에 Phase나 Milestone을 끼워 넣을 수 있도록 기존 항목의 이름과 파일명을 불필요하게 바꾸지 않는다.
|
||||
- 로드맵 문서 안에서 다른 로드맵 문서, SDD, `USER_REVIEW.md`, archive 문서를 가리킬 때는 raw path만 쓰지 말고 `[표시 제목](상대경로)` Markdown 링크로 쓴다.
|
||||
- 문서 안의 링크 target은 링크를 작성하는 Markdown 파일 위치 기준 상대경로로 쓴다. 예: `ROADMAP.md`와 `current.md`에서는 `[PHASE.md](phase/<phase-slug>/PHASE.md)`, Phase 문서에서는 `[Milestone](milestones/<milestone-slug>.md)`, Milestone 문서에서는 `[ROADMAP.md](../../../ROADMAP.md)`와 `[PHASE.md](../PHASE.md)`를 쓴다.
|
||||
- `경로:`, `Phase:`, `Milestone:`, `SDD 문서:` 같은 필드명을 유지해야 해도 값은 `경로: [PHASE.md](phase/<phase-slug>/PHASE.md)`처럼 링크로 작성한다.
|
||||
- 실제 생성한 로드맵 문서에는 `<phase-slug>`, `<milestone-slug>`, `<relative-...>` 같은 placeholder가 들어간 링크 target을 남기지 않는다. 템플릿 placeholder는 실제 파일 위치 기준 상대경로 또는 `없음`으로 치환한다.
|
||||
- 코드 경로, 명령 입력, `.agent-roadmap-sync/locks.yaml`의 machine-readable identity는 raw 값이 필요하면 유지할 수 있지만, 사용자에게 보여주는 문서 포인터에는 Markdown 링크를 함께 둔다.
|
||||
|
||||
## Milestone 작성 규칙
|
||||
|
||||
|
|
@ -115,13 +103,11 @@ agent-roadmap/
|
|||
- `구현 잠금`에는 상태, SDD 필요 여부, 잠금 해제 조건, `결정 필요` 체크리스트를 적는다. 결정할 항목이 없으면 `결정 필요: 없음`으로 적는다.
|
||||
- SDD가 필요한 기준: cross-repo 계약, 외부 provider 쓰기, 상태 머신/lifecycle, idempotency/retry/identity map, API/proto/config/env/schema 변경, field smoke, 사용자 승인 gate 영향.
|
||||
- SDD가 불필요한 기준: 단일 repo 내부의 작은 리팩터링, 문서 정리, 테스트 보강, 작은 UI 보강, Milestone Task `검증:`만으로 닫히는 작업.
|
||||
- SDD가 필요한 Milestone은 `SDD 문서` 값을 해당 Milestone 파일 위치 기준 `[SDD.md](../../../sdd/<phase-slug>/<milestone-slug>/SDD.md)` Markdown 링크로 적고, SDD 잠금이 해제될 때까지 `구현 잠금`을 `잠금`으로 둔다.
|
||||
- 로드맵 생성 흐름에서 SDD가 필요한 신규 Milestone은 SDD 문서 링크만 남기지 않고 해당 파일에 SDD 초안을 만든다.
|
||||
- SDD가 필요한 Milestone은 `SDD 문서` 경로를 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`로 적고, SDD 잠금이 해제될 때까지 `구현 잠금`을 `잠금`으로 둔다.
|
||||
- 로드맵 생성 흐름에서 SDD가 필요한 신규 Milestone은 SDD 경로만 남기지 않고 해당 경로에 SDD 초안을 만든다.
|
||||
- 새 Milestone이 다른 프로젝트 Milestone 완료 전까지 잠겨야 하면 `구현 잠금`을 `잠금`으로 두고 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`에 entry를 만든다. 의존 대상 확정과 entry 형식은 `update-roadmap`의 프로젝트 간 잠금 규칙을 따른다.
|
||||
- `기능`은 Epic heading과 Task 체크리스트로 작성한다.
|
||||
- Epic heading은 `### Epic: [epic-id] <이름>` 형식으로 작성한다.
|
||||
- 각 Epic에는 기능 Task를 최대 5개만 둔다. 5개를 초과하는 Task는 허용하지 않는다.
|
||||
- 여섯 번째 Task가 필요하면 capability, 산출물, 의존성, 검증 경계 중 하나로 기존 Epic을 둘 이상으로 분리한다. 분리 후에도 독립 목표가 남으면 새 Milestone 후보로 둔다.
|
||||
- Task는 `- [ ] [item-id] 설명` 형식으로 작성한다.
|
||||
- epic-id와 item-id는 공백 없는 짧은 ASCII 토큰이며, 해당 Milestone 안에서만 유일하면 된다.
|
||||
- 검증이 필요한 Task에만 같은 항목 안에 `검증: <명령/확인 방법/기대 결과>`를 붙인다. 검증이 필요 없는 기능에는 억지 검증을 붙이지 않는다.
|
||||
|
|
@ -134,7 +120,7 @@ agent-roadmap/
|
|||
- [ ] 이미 존재하면 덮어쓰지 말고 `update-roadmap` 스킬 사용을 안내
|
||||
- [ ] `README.md`, `agent-ops/GUIDE.md`, `agent-ops/rules/project/rules.md` 등 프로젝트 방향을 설명하는 문서를 확인
|
||||
- [ ] `rg --files`로 현재 프로젝트의 주요 구조를 가볍게 확인
|
||||
- [ ] `roadmap-template.md`, `roadmap-priority-queue-template.md`, `roadmap-current-template.md`, `roadmap-phase-template.md`, `roadmap-milestone-template.md`를 읽어 최신 형식 확인
|
||||
- [ ] `roadmap-template.md`, `roadmap-current-template.md`, `roadmap-phase-template.md`, `roadmap-milestone-template.md`를 읽어 최신 형식 확인
|
||||
- [ ] SDD가 필요한 Milestone 후보가 있으면 `agent-ops/skills/common/roadmap-sdd/SKILL.md`, `roadmap-sdd-template.md`, `roadmap-sdd-user-review-template.md`를 읽어 최신 절차와 형식 확인
|
||||
- [ ] `agent-ops/rules/common/rules.md`가 로드맵 디렉터리 존재 시 `agent-ops/rules/common/rules-roadmap.md`를 읽도록 라우팅하는지 확인
|
||||
|
||||
|
|
@ -154,35 +140,27 @@ agent-roadmap/
|
|||
- Phase는 큰 진화 단위로 나누고, 각 Phase에 목표와 상태를 둔다.
|
||||
- Milestone은 Phase 안에서 완료 판단이 가능한 단위로 나눈다.
|
||||
- Milestone 내부에서 여러 기능 묶음이 필요하면 Epic으로 선언하고, Epic 아래 flat Task 체크리스트를 둔다.
|
||||
- 각 Epic의 기능 Task 수는 최대 5개로 제한한다. 여섯 번째 Task가 필요하면 책임과 산출물 경계를 기준으로 Epic을 분리한다.
|
||||
|
||||
4. **파일 생성**
|
||||
- `ROADMAP.md`, `priority-queue.md`, 로컬 `current.md`, 각 Phase의 `PHASE.md`, 각 Milestone 문서를 템플릿 순서대로 생성한다.
|
||||
- `ROADMAP.md` 최상단에는 `priority-queue.md`를 먼저 확인하도록 `고정 실행 순서` 섹션을 둔다.
|
||||
- `priority-queue.md`에는 Phase를 가로지르는 실행 후보 Milestone을 위에서 아래 순서로 둔다. 후보가 없으면 `실행 순서` 섹션만 비워 둔다.
|
||||
- `ROADMAP.md`, 로컬 `current.md`, 각 Phase의 `PHASE.md`, 각 Milestone 문서를 템플릿 순서대로 생성한다.
|
||||
- 활성 Phase와 활성 Milestone은 `current.md`에 모두 기록한다.
|
||||
- `.gitignore`의 Agent-Ops 관리 block에 `agent-roadmap/current.md`가 있는지 확인하고 없으면 추가한다.
|
||||
- `ROADMAP.md`의 Phase 흐름에는 완료/검토중/진행중/계획/스케치 Phase 모두를 상태 그룹별로 정리한다. 이 순서는 실행 우선순위가 아니며, 실제 다음 작업 선택은 `priority-queue.md`를 따른다.
|
||||
- `ROADMAP.md`의 Phase 흐름에는 완료/검토중/진행중/계획/스케치 Phase 모두를 위에서 아래 순서로 두고, 계획 Phase는 진행중 Phase보다 아래에, 스케치 Phase는 계획 Phase보다 아래에 둔다.
|
||||
- 완료된 Phase가 초기 구조에 포함되어야 하는 경우 `archive/phase/<phase-slug>/PHASE.md`로 만들고 `ROADMAP.md`에서 archive 경로를 가리킨다.
|
||||
- 완료된 Milestone이 진행중 Phase에 포함되어야 하는 경우 `archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 만들고 해당 활성 `PHASE.md`에서 archive 경로를 가리킨다.
|
||||
- archive `PHASE.md`는 Phase 자체가 완료/폐기된 경우에만 만든다. 진행중 Phase의 완료 Milestone만 archive된 경우 archive Phase 디렉터리에 `milestones/`만 둘 수 있다.
|
||||
- SDD가 필요한 Milestone은 `구현 잠금`에 해당 Milestone 파일 위치 기준 `SDD 문서` Markdown 링크와 잠금 해제 조건을 적고, 같은 흐름에서 `roadmap-sdd`의 `create` 절차를 적용해 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md` 초안을 만든다.
|
||||
- SDD가 필요한 Milestone은 `구현 잠금`에 SDD 경로와 잠금 해제 조건을 적고, 같은 흐름에서 `roadmap-sdd`의 `create` 절차를 적용해 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md` 초안을 만든다.
|
||||
- `roadmap-sdd create` 결과 SDD 결정 항목이 있으면 `roadmap-sdd`의 `review-ready` 절차에 따라 같은 디렉터리에 `USER_REVIEW.md`를 만들고, SDD와 Milestone 구현 잠금을 `잠금`으로 둔다.
|
||||
- 외부 의존 잠금이 있으면 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`을 생성하거나 기존 entry를 upsert한다. 의존 대상이 명시 경로, slug, 제목, 문서 힌트, 로컬 current 단일 후보 중 하나로 확정되지 않으면 lock entry를 만들지 않고 TODO로 남긴다.
|
||||
|
||||
5. **검증**
|
||||
- 생성한 링크가 실제 파일을 가리키는지 확인한다.
|
||||
- `priority-queue.md`가 존재하고 `실행 순서` 섹션이 있는지 확인한다.
|
||||
- `priority-queue.md`의 모든 링크가 활성 Milestone 파일을 가리키는지 확인한다. 실행 후보가 없어서 빈 큐이면 정상으로 보고하되, 활성 실행 후보가 있는데 비어 있으면 큐 동기화 필요로 본다.
|
||||
- 생성한 로드맵 문서의 문서/산출물 포인터가 raw path만 남지 않고 Markdown 링크로 작성되었는지 확인한다.
|
||||
- 생성한 로드맵 문서의 Markdown 링크 target에 템플릿 placeholder가 남지 않았는지 확인한다.
|
||||
- 로컬 `current.md` 활성 항목에 `agent-roadmap/archive/**` 경로가 없는지 확인한다.
|
||||
- Epic heading과 Task 체크리스트 id가 형식을 따르는지 확인한다.
|
||||
- 각 Epic의 기능 Task 수가 최대 5개인지 확인한다. 6개 이상이면 검증 실패로 보고하고 Epic 분리를 요구한다.
|
||||
- 상태 표기가 `[진행중]`처럼 공백 없는 표준값인지 확인한다.
|
||||
- `[스케치]` Milestone에 `승격 조건` 섹션이 있고 `구현 잠금`이 `잠금`인지 확인한다.
|
||||
- 각 Milestone의 `구현 잠금`에 `SDD: 필요|불필요`와 판정 사유가 있는지 확인한다.
|
||||
- `SDD: 필요` Milestone은 SDD 문서 링크와 잠금 해제 조건이 있고, 해당 `SDD.md` 파일이 실제 존재하는지 확인한다.
|
||||
- `SDD: 필요` Milestone은 SDD 경로와 잠금 해제 조건이 있고, 해당 `SDD.md` 파일이 실제 존재하는지 확인한다.
|
||||
- 생성된 각 `SDD.md`는 `roadmap-sdd`의 `check-gate` 절차로 표준 top-level 섹션, 필수 표 컬럼, SDD 상태, SDD 잠금, `USER_REVIEW.md` 존재 여부, Acceptance Scenario와 Milestone 기능 Task 연결, Evidence Map 연결성을 최종 확인한다.
|
||||
- `check-gate` 결과는 `SDD gate` 항목에 `pass`, `review-required`, `blocked`, `invalid` 중 하나로 분리해 남긴다. `review-ready`로 만든 `USER_REVIEW.md` 때문에 막힌 경우는 `review-required`로 보고하고 형식 보완 실패로 보지 않는다.
|
||||
- `[검토중]` Milestone이 있다면 `구현 잠금`이 해제되어 있고 미완료 `결정 필요` 항목이 없는지 확인한다.
|
||||
|
|
@ -193,24 +171,22 @@ agent-roadmap/
|
|||
```markdown
|
||||
## 생성 결과
|
||||
|
||||
- 로드맵: [ROADMAP.md](agent-roadmap/ROADMAP.md)
|
||||
- 전역 실행 순서: [priority-queue.md](agent-roadmap/priority-queue.md)
|
||||
- 로컬 현재 컨텍스트: [current.md](agent-roadmap/current.md)
|
||||
- 로드맵: agent-roadmap/ROADMAP.md
|
||||
- 로컬 현재 컨텍스트: agent-roadmap/current.md
|
||||
- Phase 문서: <N개>
|
||||
- Milestone 문서: <N개>
|
||||
- 활성 Phase: <N개>
|
||||
- 활성 Milestone: <N개>
|
||||
- 구현 잠금: <잠금 Milestone N개 | 해제 Milestone N개>
|
||||
- SDD gate: <필요 N개 | 불필요 N개 | 작성 N개 | pass N개 | review-required N개 | blocked/invalid N개>
|
||||
- 전역 실행 순서: <항목 N개 | 빈 큐 | 동기화 필요>
|
||||
- 최종 확인: <통과 | 사용자 리뷰 필요 | 보완 필요: SDD gate/링크/상태/형식>
|
||||
- Workspace 잠금: <생성/갱신 N개 | 없음>
|
||||
- 공통 로드맵 룰: <확인함 | 설치 필요 | 해당 없음>
|
||||
|
||||
## 활성 항목
|
||||
|
||||
- Phase: <phase-name>: [PHASE.md](agent-roadmap/phase/<phase-slug>/PHASE.md)
|
||||
- Milestone: <milestone-name>: [<milestone-name>](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- Phase: <phase-name>: agent-roadmap/phase/<phase-slug>/PHASE.md
|
||||
- Milestone: <milestone-name>: agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md
|
||||
|
||||
## TODO 항목
|
||||
|
||||
|
|
@ -221,8 +197,6 @@ agent-roadmap/
|
|||
|
||||
- 기존 `agent-roadmap/` 파일을 덮어쓰지 않는다.
|
||||
- 일반 작업마다 전체 `ROADMAP.md`를 읽도록 규칙을 만들지 않는다.
|
||||
- `priority-queue.md`를 두 번째 로드맵처럼 사용하지 않는다. 상태, 목표, 범위, 잠금, 기능, 완료 근거를 복제하지 않는다.
|
||||
- `priority-queue.md`에 archive Milestone 링크를 넣지 않는다.
|
||||
- 로컬 `current.md`에 `agent-roadmap/archive/**` 경로를 넣지 않는다.
|
||||
- `agent-roadmap/current.md`를 git 추적 대상으로 만들지 않는다.
|
||||
- Phase와 Milestone 이름 또는 파일명에 순번을 강제하지 않는다.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
name: create-skill
|
||||
version: 1.0.1
|
||||
version: 1.0.0
|
||||
description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
|
||||
---
|
||||
|
||||
|
|
@ -17,8 +17,7 @@ description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
|
|||
|
||||
### 생성 위치 결정
|
||||
- `.agent-ops-source` 파일이 **있으면** (공통 관리 레포): `agent-ops/skills/common/<skill-name>/SKILL.md`
|
||||
- `.agent-ops-source` 파일이 **없고** 사용자가 private 또는 operator-local을 명시하면 (타겟 프로젝트): `agent-ops/skills/private/<skill-name>/SKILL.md`
|
||||
- `.agent-ops-source` 파일이 **없고** private 요청이 없으면 (타겟 프로젝트): `agent-ops/skills/project/<skill-name>/SKILL.md`
|
||||
- `.agent-ops-source` 파일이 **없으면** (타겟 프로젝트): `agent-ops/skills/project/<skill-name>/SKILL.md`
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
|
|
@ -30,22 +29,19 @@ description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
|
|||
|
||||
- `skill-name`: 생성할 skill 이름, kebab-case (필수)
|
||||
- `purpose`: 이 skill이 해결하는 문제 한 줄 요약 (필수)
|
||||
- `visibility`: `common`, `project`, `private` 중 하나. 사용자가 private 또는 operator-local을 명시했을 때만 `private`을 선택한다. (선택)
|
||||
- `trigger-cases`: 이 skill을 호출해야 하는 상황 목록 (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/skills/common/`, `agent-ops/skills/project/`, `agent-ops/skills/private/` 하위에 동일 이름의 디렉터리가 이미 존재하는지 확인
|
||||
- [ ] `agent-ops/skills/common/` 및 `agent-ops/skills/project/` 하위에 동일 이름의 디렉터리가 이미 존재하는지 확인
|
||||
- [ ] `agent-ops/skills/common/router.md` 및 `agent-ops/rules/project/rules.md` 에 이미 유사한 라우팅 항목이 있는지 확인
|
||||
- [ ] `agent-ops/skills/common/_templates/skill-template.md` 를 읽어 최신 템플릿 형식 파악
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **중복 확인**
|
||||
- 같은 visibility 경로에 이미 있는 skill은 덮어쓰지 않고 중단한다.
|
||||
- private 요청에서 같은 이름의 project skill은 의도된 override 후보이므로 중복으로 중단하지 않는다. common skill과의 같은 이름 또는 다른 기능의 중복은 사용자에게 알리고 중단한다.
|
||||
- private override가 아닌 기능 중복은 사용자에게 알리고 중단한다.
|
||||
- project skill과 같은 이름의 private override는 해당 project skill의 책임을 완전히 대체하는지 확인한다.
|
||||
- `agent-ops/skills/common/<skill-name>/` 및 `agent-ops/skills/project/<skill-name>/` 폴더 존재 여부 확인
|
||||
- 기능이 겹치는 기존 skill이 있으면 사용자에게 알리고 중단한다
|
||||
|
||||
2. **목적 분석**
|
||||
- `purpose` 와 `trigger-cases` 를 바탕으로 아래 항목을 도출한다
|
||||
|
|
@ -57,7 +53,7 @@ description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
|
|||
- 금지 사항
|
||||
|
||||
3. **SKILL.md 생성**
|
||||
- 경로: 생성 위치 결정 규칙에 따라 `common/`, `project/`, 또는 `private/` 하위에 생성
|
||||
- 경로: 생성 위치 결정 규칙에 따라 `common/` 또는 `project/` 하위에 생성
|
||||
- `skill-template.md` 형식을 따른다
|
||||
- agent-ops 내부 스킬은 기존 로컬 관례에 맞춰 `version`을 둘 수 있다. Codex 설치형 스킬로 배포할 목적이면 `version`이나 `depends` 같은 비표준 frontmatter를 넣지 않는다.
|
||||
- 프로젝트 특화 내용보다 범용 절차를 우선한다
|
||||
|
|
@ -65,10 +61,7 @@ description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
|
|||
|
||||
4. **라우팅 업데이트**
|
||||
- `.agent-ops-source` 마커가 **있으면** (공통 관리 레포): `agent-ops/skills/common/router.md`에 라우팅 항목 추가
|
||||
- private skill이 같은 이름의 project skill을 override하면 별도 라우팅 항목을 추가하지 않는다. 공통 규칙의 private 우선순위를 사용한다.
|
||||
- project skill과 짝이 없는 private skill은 `agent-ops/rules/private/rules.md`에만 라우팅 항목을 추가한다. 파일이 없으면 private route만 담은 ignored local rule을 생성한다.
|
||||
- private rule의 trigger는 project router와 중복 등록하지 않는다.
|
||||
- `.agent-ops-source` 마커가 **없고** private skill이 아니면 (타겟 프로젝트): `agent-ops/rules/project/rules.md`의 프로젝트 스킬 라우터 섹션에 라우팅 항목 추가
|
||||
- `.agent-ops-source` 마커가 **없으면** (타겟 프로젝트): `agent-ops/rules/project/rules.md`의 프로젝트 스킬 라우터 섹션에 라우팅 항목 추가
|
||||
- 기존 공통 스킬을 수정해 trigger가 달라졌다면 새 skill을 만들지 말고 `agent-ops/skills/common/router.md`의 기존 행을 갱신한다
|
||||
- 이 skill이 속할 라우팅 축(구조 분석/코드 변경/흐름 추적 등)을 판단한다
|
||||
- 기존 라우팅 구조를 깨지 않는다
|
||||
|
|
@ -83,7 +76,7 @@ description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
|
|||
```
|
||||
## 생성 완료
|
||||
|
||||
- SKILL 경로: agent-ops/skills/{common|project|private}/<skill-name>/SKILL.md
|
||||
- SKILL 경로: agent-ops/skills/{common|project}/<skill-name>/SKILL.md
|
||||
- 라우팅 추가: <대상 파일> → <라우팅 축> → <skill-name>
|
||||
|
||||
## 주의사항 (해당 시)
|
||||
|
|
@ -92,16 +85,15 @@ description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
|
|||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `agent-ops/skills/{common|project|private}/<skill-name>/SKILL.md` 파일이 생성되었는가
|
||||
- [ ] `agent-ops/skills/{common|project}/<skill-name>/SKILL.md` 파일이 생성되었는가
|
||||
- [ ] 생성된 파일이 `skill-template.md`의 필수 섹션(목적, 언제 호출할지, 실행 절차, 실행 결과 검증, 출력 형식, 금지 사항)을 포함하는가
|
||||
- [ ] frontmatter에 name, description이 올바르게 기재되었는가
|
||||
- [ ] agent-ops 내부 스킬이면 version 등 로컬 관례를 따르고, Codex 설치형 스킬이면 시스템 `skill-creator` frontmatter 규칙을 따르는가
|
||||
- [ ] private override는 동일 이름의 project skill보다 우선되고, 짝이 없는 private skill만 private rule에 라우팅되었는가
|
||||
- [ ] 라우팅 대상 파일에 해당 스킬의 라우팅 항목이 추가되었는가
|
||||
- 검증 실패 시: 누락된 섹션 또는 라우팅 항목을 사용자에게 알리고 해당 부분만 보완한다
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- private skill 또는 private rule의 내용을 tracked common·project 경로에 복사하지 않는다
|
||||
- 이미 존재하는 skill 을 덮어쓰지 않는다
|
||||
- 프로젝트 특화 경로(예: `app/screens/`)를 skill 본문에 하드코딩하지 않는다
|
||||
- skill 생성과 무관한 코드 파일을 수정하지 않는다
|
||||
|
|
|
|||
|
|
@ -1,117 +0,0 @@
|
|||
---
|
||||
name: create-spec
|
||||
version: 1.0.0
|
||||
description: agent-spec 최초 생성, 현재 구현 스펙 작성, living spec bootstrap, 완료된 기능의 구현 스펙 신규 문서화 요청에 사용한다. 코드/계약/테스트/로드맵 근거를 바탕으로 agent-spec/index.md와 매칭 spec 문서를 생성한다.
|
||||
---
|
||||
|
||||
# create-spec
|
||||
|
||||
## 목적
|
||||
|
||||
현재 구현된 기능의 living spec을 새로 만든다.
|
||||
스펙은 로드맵 완료 이력이나 계약 원문을 복제하지 않고, 사람과 agent가 구현된 기능, 동작 흐름, 계약/검증 포인터를 함께 확인하는 문서로 유지한다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 "스펙 생성", "구현 스펙 작성", "현재 구현 문서화", "agent-spec 생성"을 요청할 때
|
||||
- agent-spec을 처음 도입해 `agent-spec/index.md`와 초기 spec 문서를 만들 때
|
||||
- 완료된 기능이나 활성 기능에 대응되는 현재 구현 spec 문서가 없고, 새 spec 작성이 필요한 때
|
||||
- `complete-milestone` 또는 `update-spec`에서 관련 spec이 없지만 evidence가 충분해 신규 작성이 필요하다고 판단한 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `mode`: `bootstrap` 또는 `targeted`. 기본값은 요청에서 추론한다. (선택)
|
||||
- `spec-id`: 만들 spec id. `<area>/<spec-id>` 형식을 권장한다. (선택)
|
||||
- `target-milestone`: spec 근거로 삼을 활성 또는 명시 Milestone 경로, 이름, slug. (선택)
|
||||
- `source-paths`: 우선 확인할 코드, 계약, 테스트, docs 경로 목록. (선택)
|
||||
- `evidence`: complete.log, SDD, 사용자 설명, 검증 결과 등 보조 근거. (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/rules/common/rules-agent-spec.md`를 읽는다.
|
||||
- [ ] `agent-spec/` 존재 여부와 `agent-spec/index.md` 존재 여부를 확인한다.
|
||||
- [ ] `agent-ops/skills/common/_templates/agent-spec/index-template.md`와 `spec-template.md`를 확인한다.
|
||||
- [ ] 계약에 닿는 spec이면 `agent-contract/index.md`를 읽고 매칭 계약 문서만 읽는다.
|
||||
- [ ] 로드맵 근거가 필요하면 활성 Milestone/SDD만 우선 읽고, archive는 사용자가 명시했거나 현재 스펙 배경 확인에 꼭 필요한 링크만 좁게 읽는다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **범위 결정**
|
||||
- 요청을 `bootstrap` 또는 `targeted`로 분류한다.
|
||||
- `targeted`이면 spec 하나의 기능 범위와 `spec-id`를 정한다.
|
||||
- `bootstrap`이면 프로젝트 전체를 완성하려 하지 말고, 코드/계약으로 확인 가능한 핵심 축과 spec 후보 목록을 먼저 만든다.
|
||||
- `spec-id`는 소문자 영문, 숫자, 하이픈, `/`만 사용한다.
|
||||
|
||||
2. **근거 수집**
|
||||
- 코드, 계약, 테스트, 설정 예시, README/docs, 활성 roadmap/SDD, complete.log 순서로 현재 동작 근거를 확인한다.
|
||||
- 현재 동작은 코드와 계약으로 재확인한다.
|
||||
- 로드맵 archive 또는 agent-task archive는 일반 탐색하지 않는다.
|
||||
- 확인할 수 없는 내용은 `불명확` 또는 `확인 필요`로 둔다.
|
||||
|
||||
3. **agent-spec 구조 생성**
|
||||
- `agent-spec/`가 없으면 만든다.
|
||||
- `agent-spec/index.md`가 없으면 index template으로 만든다.
|
||||
- 필요한 `<area>/` 디렉터리를 만든다.
|
||||
- 기존 같은 `spec-id` 문서가 있으면 새로 만들지 말고 `update-spec` 대상이라고 보고한다.
|
||||
|
||||
4. **spec 문서 작성**
|
||||
- spec template의 기본 섹션 구조를 따른다.
|
||||
- frontmatter의 `spec_doc_type`, `spec_id`, `status`, `source_evidence`를 채운다.
|
||||
- `status`는 evidence 수준에 따라 `구현됨`, `부분`, `가정`, `불명확` 중 하나로 둔다.
|
||||
- `기능 목록`을 `목적` 다음에 바로 둔다.
|
||||
- 기능 목록은 `기능`과 `설명` 중심으로 작성한다. 기능별 `상태` 칼럼은 기본 생성하지 않는다.
|
||||
- `주요 흐름`은 Mermaid `sequenceDiagram` 또는 `flowchart`를 우선 고려한다. 단순 기능은 짧은 목록으로 둔다.
|
||||
- 책임 경계는 기능 이해에 필요한 최소 수준만 적고, 도메인별 코드 배치나 금지 사항은 domain rule로 넘긴다.
|
||||
- 계약 원문, proto field 전체 목록, config schema 원문은 복제하지 않고 링크한다.
|
||||
- `코드 진입점` 섹션은 만들지 않는다. 코드 근거는 `source_evidence`에 남긴다.
|
||||
- 검증 방법은 실행 가능한 명령 또는 확인 기준으로 남긴다.
|
||||
|
||||
5. **index 갱신**
|
||||
- `Spec Map`에 새 spec id, 상태, 읽는 조건, path, 주요 근거를 추가하거나 보정한다.
|
||||
- 매칭 조건은 agent가 좁게 읽을 수 있도록 기능명, 코드 경로, 계약 id, 운영 표면 중심으로 쓴다.
|
||||
- 기존 행을 삭제하거나 재정렬하지 않는다. 명백히 placeholder인 `없음` 행은 첫 실제 spec 추가 시 제거할 수 있다.
|
||||
|
||||
6. **결과 보고**
|
||||
- 만든 spec 문서와 index 변경 내용을 보고한다.
|
||||
- 불명확하거나 후속 `update-spec`이 필요한 항목을 보고한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `agent-spec/index.md`가 존재하고 Spec Map에 생성한 spec이 들어 있는가
|
||||
- [ ] 생성한 spec 문서가 `rules-agent-spec.md`의 기본 섹션 기준을 따르는가
|
||||
- [ ] 기능 목록이 기능/설명 중심이며 불필요한 상태 칼럼이나 과한 상세 설명을 만들지 않았는가
|
||||
- [ ] 코드 진입점, 패키지 배치, 도메인별 금지 사항을 spec 본문에 반복하지 않았는가
|
||||
- [ ] frontmatter의 `spec_doc_type`, `spec_id`, `status`, `source_evidence`가 채워졌는가
|
||||
- [ ] source evidence path가 실제 파일이거나 `path: null`인 사용자 근거인가
|
||||
- [ ] 계약 원문을 복제하지 않고 `agent-contract/` 또는 코드 링크로 연결했는가
|
||||
- [ ] archive를 무차별로 읽거나 과거 완료 기록을 현재 truth처럼 쓰지 않았는가
|
||||
- [ ] `git diff --check`를 실행했는가
|
||||
- 검증 실패 시: spec 문서와 index만 보완하고 코드 파일은 수정하지 않는다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```markdown
|
||||
## Spec 생성 완료
|
||||
|
||||
- 모드: <bootstrap | targeted>
|
||||
- 생성/갱신 파일:
|
||||
- [index.md](agent-spec/index.md)
|
||||
- [<spec-id>.md](agent-spec/<area>/<spec-id>.md)
|
||||
- 상태: <구현됨 | 부분 | 가정 | 불명확>
|
||||
- 주요 근거:
|
||||
- <path 또는 사용자 근거> - <요약>
|
||||
|
||||
## TODO 항목
|
||||
|
||||
- <확인 필요 또는 없음>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- agent-spec에 계약 원문, proto 전체 필드, config schema 원문을 복제하지 않는다.
|
||||
- 현재 코드/계약으로 확인하지 않은 내용을 구현 사실처럼 쓰지 않는다.
|
||||
- archive 전체를 훑지 않는다.
|
||||
- 기존 spec이 있으면 중복 spec을 만들지 않는다.
|
||||
- 코드 진입점, 구현 배치, 도메인 간 상세 책임 경계, 유지할 패턴, 금지 사항을 domain rule 대신 agent-spec에 길게 쓰지 않는다.
|
||||
- 사람용 공개 가이드를 agent-spec에 장황하게 작성하지 않는다.
|
||||
- spec 생성과 무관한 코드 파일을 수정하지 않는다.
|
||||
|
|
@ -49,7 +49,6 @@ description: agent-test 환경 rules.md와 도메인/검증 시나리오별 테
|
|||
- [ ] 테스트 명령 확인을 위해 프로젝트의 대표 설정 파일을 가볍게 확인한다. 예: `package.json`, `Makefile`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `docker-compose*.yml`, `.github/workflows/**`.
|
||||
- [ ] `agent-ops/rules/common/_templates/test-env-rules-template.md`를 읽는다.
|
||||
- [ ] `agent-ops/rules/common/_templates/test-case-rule-template.md`를 읽는다.
|
||||
- [ ] 프로젝트에 `agent-test/_templates/env-rules-template.md` 또는 `agent-test/_templates/test-profile-template.md`가 있으면 해당 프로젝트 템플릿을 공통 템플릿보다 우선한다.
|
||||
- [ ] `agent-test/<env>/rules.md` 존재 여부를 확인한다.
|
||||
- [ ] `agent-test/<env>/rules.md`가 있으면 읽고 missing / blank-skeleton / structured-incomplete / usable 중 하나로 분류한다.
|
||||
- [ ] 도메인 baseline과 추가 생성 대상 `agent-test/<env>/*.md`의 존재 여부를 확인하고, 있으면 blank-skeleton / structured-incomplete / usable 중 하나로 분류한다.
|
||||
|
|
@ -57,7 +56,7 @@ description: agent-test 환경 rules.md와 도메인/검증 시나리오별 테
|
|||
## 실행 절차
|
||||
|
||||
1. **환경 rules 생성**
|
||||
- `agent-test/<env>/rules.md`가 없으면 프로젝트 `agent-test/_templates/env-rules-template.md`가 있을 때는 그 형식으로 만들고, 없으면 공통 `test-env-rules-template.md` 형식으로 만든다.
|
||||
- `agent-test/<env>/rules.md`가 없으면 `test-env-rules-template.md` 형식으로 만든다.
|
||||
- `agent-test/<env>/rules.md`가 구조적 blank/skeleton이면 기존 구체 값을 보존한 채 빠진 frontmatter, 정독 필수 문구, 필수 섹션, baseline 라우팅 영역만 보완한다.
|
||||
- usable한 기존 env rules는 덮어쓰지 않고 라우팅 추가가 필요한 경우에만 최소 수정한다.
|
||||
- 제목은 `# <env> 테스트 규칙`으로 쓴다.
|
||||
|
|
@ -75,7 +74,7 @@ description: agent-test 환경 rules.md와 도메인/검증 시나리오별 테
|
|||
- 도메인은 새로 발명하지 않는다. 도메인 매핑이나 domain rule에서 확인되지 않은 이름은 `project-wide`로 기록한다.
|
||||
|
||||
3. **도메인/검증 시나리오별 문서 생성**
|
||||
- 생성 대상 문서가 없으면 프로젝트 `agent-test/_templates/test-profile-template.md`가 있을 때는 그 형식으로 만들고, 없으면 공통 `test-case-rule-template.md` 형식으로 만든다.
|
||||
- 생성 대상 문서가 없으면 `agent-test/<env>/<test-profile>.md`를 `test-case-rule-template.md` 형식으로 만든다.
|
||||
- 대상 문서가 이미 있고 usable하면 덮어쓰지 않는다.
|
||||
- 대상 문서가 구조적 blank/skeleton이면 기존 구체 값을 보존한 채 빠진 frontmatter와 필수 섹션을 보완한다.
|
||||
- frontmatter에는 `test_profile`, `domain`, `verification_type`, `last_rule_updated_at`을 채운다.
|
||||
|
|
|
|||
|
|
@ -1,149 +0,0 @@
|
|||
---
|
||||
name: finalize-task-routing
|
||||
description: PLAN/CODE_REVIEW 작성 직전 완성된 build packet을 한 번 평가해 local-first lane, G, canonical filename을 확정한다. 최초 plan과 WARN/FAIL follow-up에서 capability gap, indivisible context, 복합 loop-risk, review rework, evidence integrity에 따른 cloud 경계를 적용할 때 사용한다.
|
||||
---
|
||||
|
||||
# Finalize Task Routing
|
||||
|
||||
## 목표
|
||||
|
||||
완성된 in-memory PLAN 하나를 한 번 평가해 build/review route를 확정한다. routing 전용 문서나 증거 탐색을 만들지 않는다. Build의 기본값은 local이며 아래 표의 cloud 조건에 일치할 때만 승격한다. 공식 review는 항상 cloud의 Codex `gpt-5.6-sol` xhigh다. 이 스킬은 task 파일을 수정하지 않는다.
|
||||
|
||||
## 입력
|
||||
|
||||
- `evaluation_mode`: `first-pass | isolated-reassessment`
|
||||
- `targets.build`: 구현 에이전트가 읽을 PLAN과 PLAN 작성에 이미 사용한 scope, source/test/contract, 불변조건, 검증 근거
|
||||
- `targets.review`: review scope, 영향 경로, 검증 계획과 근거
|
||||
- target별 closure와 근거: `scope_closed`, `context_closed`, `verification_closed`, `evidence_trusted`, `ownership_closed`, `decision_closed`
|
||||
- target별 G 점수: `scope_coupling`, `state_concurrency`, `blast_irreversibility`, `evidence_diagnosis`, `verification_complexity`
|
||||
- build 신호: `large_indivisible_context`, `matched_loop_risk_signatures`, `review_rework_count`, `evidence_integrity_failure`
|
||||
- closure가 false이고 cloud가 해소할 수 있을 때만 `capability_gap`: `observed`, `evidence`, `cloud_resolution`
|
||||
|
||||
이전 lane/G, 점수, route 사유, filename을 입력하지 않는다. `review_rework_count`와 `evidence_integrity_failure`만 route-free 운영 이력으로 전달한다.
|
||||
|
||||
## 판정 순서
|
||||
|
||||
아래 순서를 지키고 종료 조건을 만나면 즉시 멈춘다.
|
||||
|
||||
### 1. Snapshot 고정
|
||||
|
||||
PLAN body, split, verification, evidence, ownership, decision이 완성된 뒤 실행한다.
|
||||
|
||||
- PLAN 자체를 build packet으로 사용한다. 별도 packet 요약을 만들지 않는다.
|
||||
- 이미 읽은 사실만 사용한다. routing 때문에 source/test/log를 다시 읽지 않는다.
|
||||
- split된 packet만 평가한다. parent/sibling의 파일·상태·risk를 합산하지 않는다.
|
||||
- `isolated-reassessment`에서는 이전 route 정보를 제거한다. 제거할 수 없으면 `blocked: isolated-routing-unavailable`로 종료한다.
|
||||
|
||||
### 2. Closure gate
|
||||
|
||||
각 target의 closure를 독립적으로 판정한다.
|
||||
|
||||
- `scope_closed`: 정확성 조건과 영향 경로가 확정됨
|
||||
- `context_closed`: PLAN과 pointer가 구현에 필요한 사실을 제공함
|
||||
- `verification_closed`: 결정적 성공 판정 방법이 있음
|
||||
- `evidence_trusted`: 실제 경로를 실행하는 재현 가능한 근거가 있음
|
||||
- `ownership_closed`: 공유 상태와 외부 소유권이 명확함
|
||||
- `decision_closed`: 사용자·외부 의미 판단 없이 완료 가능함
|
||||
|
||||
첫 번째로 일치하는 규칙을 적용한다.
|
||||
|
||||
| 조건 | 결과 |
|
||||
|------|------|
|
||||
| 어느 target이든 closure 하나라도 `unknown` | `needs_evidence`; 부족한 evidence를 구체적으로 기록하고 종료 |
|
||||
| 어느 target이든 closure 하나라도 `false`이고 구체적인 `cloud_resolution`이 없음 | `blocked`; 해제 조건을 기록하고 종료 |
|
||||
| build closure가 `false`이고 `observed`, `evidence`, `cloud_resolution`이 모두 있음 | build base basis를 `capability-gap`으로 설정 |
|
||||
| review closure만 `false`이고 cloud가 해소함 | review gap만 기록; build basis에는 영향 없음 |
|
||||
| build closure가 모두 `true` | G를 계산해 build base basis 결정 |
|
||||
|
||||
`needs_evidence`는 확인된 모든 missing evidence를 한 번에 나열한다. 입력이 달라진 뒤에만 재평가하고 같은 evidence로 반복하지 않는다.
|
||||
|
||||
### 3. G 계산
|
||||
|
||||
각 target의 다섯 값을 `0`~`2`로 채점하고 `grade=max(1, 합계)`로 계산한다.
|
||||
|
||||
- `scope_coupling`: 국소 / 여러 연결 지점 / 다중 모듈·계약
|
||||
- `state_concurrency`: 무상태 / 상태 전이 / 공유 상태·순서·동시성
|
||||
- `blast_irreversibility`: 내부 가역 / 다중 호출자·지속 상태 / 외부 계약·비가역
|
||||
- `evidence_diagnosis`: 직접 증거 / 복수 증거 조합 / 충돌·불신 증거 진단
|
||||
- `verification_complexity`: 단일 명령 / 복수 단계·통합 / 외부·상호작용·장시간
|
||||
|
||||
capability gap이 없으면 G01~G08은 `local-fit`, G09~G10은 `grade-boundary`다.
|
||||
|
||||
### 4. Build 신호 계산
|
||||
|
||||
`large_indivisible_context=true`는 다음 세 조건을 모두 만족할 때만 사용한다.
|
||||
|
||||
1. 안전한 split을 끝냈다.
|
||||
2. 하나의 correctness/transaction 판단이 여러 독립 source of truth를 동시에 요구한다.
|
||||
3. 명시적 국소 규칙과 결정적 verification oracle로 축약할 수 없다.
|
||||
|
||||
파일이 많다는 이유만으로 true로 두지 않는다.
|
||||
|
||||
아래 signature를 이미 읽은 PLAN/source/test/contract에서 한 번만 확인한다. 양성 조건이 보인 이름만 기록하고, match하지 않은 signature의 부재를 증명하지 않는다. 필요한 범위가 불명확하면 risk를 `unknown`으로 만들지 말고 closure에서 처리한다.
|
||||
|
||||
- `temporal_state`: 상태 3개 이상과 partial/retry/cancel/recovery/stale/duplicate 경로
|
||||
- `concurrent_consistency`: actor 2개 이상과 atomic snapshot/lock order/exactly-once/race-free 제약
|
||||
- `boundary_contract`: component 3개 이상 또는 consumer 2개 이상과 validation/immutability/compatibility 제약
|
||||
- `structured_interpretation`: parser/lexer/protocol assembly/multi-source merge와 nesting/quoting/precedence/deduplication 위험
|
||||
- `variant_product`: 독립 variant 축 2개 이상과 조합 검증
|
||||
|
||||
중복 없는 이름 수를 `loop_risk_count=0..5`로 사용한다.
|
||||
|
||||
- `risk_boundary = large_indivisible_context || loop_risk_count >= 4`
|
||||
- `recovery_boundary = review_rework_count >= 2 || evidence_integrity_failure`
|
||||
|
||||
`review_rework_count`는 같은 task path의 archived `WARN|FAIL` 수에 현재 non-PASS verdict를 더한 값이다. 첫 non-PASS follow-up은 1, 두 번째는 2다.
|
||||
|
||||
### 5. Build route 확정
|
||||
|
||||
첫 번째로 일치하는 규칙을 적용한다.
|
||||
|
||||
| 조건 | `route_basis` | lane |
|
||||
|------|---------------|------|
|
||||
| base basis가 `capability-gap` | `capability-gap` | cloud |
|
||||
| base basis가 `grade-boundary` | `grade-boundary` | cloud |
|
||||
| base basis가 `local-fit`이고 `recovery_boundary` | `recovery-boundary` | cloud |
|
||||
| base basis가 `local-fit`이고 `risk_boundary` | `risk-boundary` | cloud |
|
||||
| 그 외 | `local-fit` | local |
|
||||
|
||||
risk/recovery는 local-fit build의 승격 조건이다. 이미 cloud인 capability/grade basis를 덮어쓰지 않는다. grade는 lane 변경과 무관하게 보존한다. review는 `official-review`, cloud, 실제 G를 사용한다.
|
||||
|
||||
### 6. Finalizer 실행
|
||||
|
||||
`status=routed`일 때만 아래 명령을 정확히 한 번 실행한다.
|
||||
|
||||
```bash
|
||||
agent-ops/skills/common/finalize-task-routing/scripts/finalize-task-policy.sh pair \
|
||||
<build-base-basis> \
|
||||
<large-indivisible-context> <loop-risk-count> \
|
||||
<review-rework-count> <evidence-integrity-failure> \
|
||||
<build-scope> <build-state> <build-blast> <build-evidence> <build-verification> \
|
||||
official-review \
|
||||
<review-scope> <review-state> <review-blast> <review-evidence> <review-verification>
|
||||
```
|
||||
|
||||
finalizer 출력만 사용한다. lane, grade, boundary, filename을 수작업으로 만들지 않는다.
|
||||
|
||||
## 출력 계약
|
||||
|
||||
항상 `status`, `evaluation_mode`, `missing_evidence`, `blocked_reason`을 반환한다. `status=routed`이면 다음 필드를 모두 반환한다.
|
||||
|
||||
- 공통: `finalizer=finalize-task-policy.sh`, `finalizer_mode=pair`
|
||||
- target별: `closures`, `closure_basis`, `capability_gap`, `grade_scores`, `route_basis`, `lane`, `grade`, `filename`
|
||||
- build 전용: `base_route_basis`, `large_indivisible_context`, `matched_loop_risk_signatures`, `loop_risk_count`, `review_rework_count`, `evidence_integrity_failure`, `risk_boundary_matched`, `recovery_boundary_matched`
|
||||
- review 전용: `route_basis=official-review`, `adapter=codex`, `model=gpt-5.6-sol`, `reasoning_effort=xhigh`
|
||||
|
||||
## 완료 확인
|
||||
|
||||
- 기존 PLAN 분석만 사용했고 routing-only 탐색을 하지 않았는가
|
||||
- split packet마다 독립 평가했는가
|
||||
- G01~G08 cloud route가 선택된 `route_basis` 하나와 일치하는 근거를 갖는가
|
||||
- G09~G10은 risk/recovery 신호가 있어도 `grade-boundary`를 유지하는가
|
||||
- finalizer 출력과 active filename이 일치하는가
|
||||
|
||||
## 금지
|
||||
|
||||
- unmatched signature의 부재를 찾기 위해 추가 탐색하지 않는다.
|
||||
- 이전 lane/G나 finding 개수를 승격 근거로 쓰지 않는다.
|
||||
- cloud가 해소할 수 없는 문제를 cloud route로 바꾸지 않는다.
|
||||
- PLAN, CODE_REVIEW, archive, complete.log를 직접 수정하지 않는다.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
interface:
|
||||
display_name: "Finalize Task Routing"
|
||||
short_description: "Route plans once with explicit cloud boundaries"
|
||||
default_prompt: "Use $finalize-task-routing once on the completed plan to select local or cloud from explicit capability, grade, risk, and recovery boundaries."
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
printf '%s\n' \
|
||||
'usage:' \
|
||||
' finalize-task-policy.sh pair <build-base-basis> <large-indivisible-context> <loop-risk-count> <review-rework-count> <evidence-integrity-failure> <build-scope> <build-state> <build-blast> <build-evidence> <build-verification> official-review <review-scope> <review-state> <review-blast> <review-evidence> <review-verification>' \
|
||||
' build-base-basis: local-fit | capability-gap | grade-boundary' \
|
||||
' boolean fields: true | false; loop-risk-count: 0..5; review-rework-count: non-negative integer' >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
formatter="$script_dir/finalize-task-route.sh"
|
||||
|
||||
field() {
|
||||
local output=$1
|
||||
local key=$2
|
||||
local value
|
||||
value=$(sed -n "s/^${key}=//p" <<<"$output")
|
||||
if [[ -z "$value" ]]; then
|
||||
printf 'missing formatter field: %s\n' "$key" >&2
|
||||
exit 3
|
||||
fi
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
finalize_build() {
|
||||
local base_basis=$1
|
||||
shift
|
||||
local scores=("$@")
|
||||
local lane
|
||||
local route
|
||||
|
||||
case "$base_basis" in
|
||||
local-fit|capability-gap|grade-boundary)
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
BUILD_BASE_ROUTE_BASIS=$base_basis
|
||||
BUILD_RISK_BOUNDARY_MATCHED=false
|
||||
BUILD_RECOVERY_BOUNDARY_MATCHED=false
|
||||
if [[ "$BUILD_LARGE_INDIVISIBLE_CONTEXT" == true ||
|
||||
"$BUILD_LOOP_RISK_COUNT" -ge 4 ]]; then
|
||||
BUILD_RISK_BOUNDARY_MATCHED=true
|
||||
fi
|
||||
if [[ "$BUILD_EVIDENCE_INTEGRITY_FAILURE" == true ||
|
||||
"$BUILD_REVIEW_REWORK_COUNT" -ge 2 ]]; then
|
||||
BUILD_RECOVERY_BOUNDARY_MATCHED=true
|
||||
fi
|
||||
|
||||
if [[ "$base_basis" == capability-gap ]]; then
|
||||
BUILD_ROUTE_BASIS=capability-gap
|
||||
elif [[ "$base_basis" == local-fit &&
|
||||
"$BUILD_RECOVERY_BOUNDARY_MATCHED" == true ]]; then
|
||||
BUILD_ROUTE_BASIS=recovery-boundary
|
||||
elif [[ "$base_basis" == local-fit &&
|
||||
"$BUILD_RISK_BOUNDARY_MATCHED" == true ]]; then
|
||||
BUILD_ROUTE_BASIS=risk-boundary
|
||||
else
|
||||
BUILD_ROUTE_BASIS=$base_basis
|
||||
fi
|
||||
|
||||
if [[ "$BUILD_ROUTE_BASIS" == local-fit ]]; then
|
||||
lane=local
|
||||
else
|
||||
lane=cloud
|
||||
fi
|
||||
|
||||
route=$("$formatter" build "$lane" "${scores[@]}")
|
||||
BUILD_GRADE=$(field "$route" grade)
|
||||
if [[ "$base_basis" == local-fit &&
|
||||
( "$BUILD_GRADE" == G09 || "$BUILD_GRADE" == G10 ) ]]; then
|
||||
printf 'local-fit is valid only for G01-G08\n' >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ "$base_basis" == grade-boundary &&
|
||||
"$BUILD_GRADE" != G09 && "$BUILD_GRADE" != G10 ]]; then
|
||||
printf 'grade-boundary is valid only for G09-G10\n' >&2
|
||||
exit 2
|
||||
fi
|
||||
BUILD_LANE=$(field "$route" lane)
|
||||
BUILD_FILENAME=$(field "$route" filename)
|
||||
}
|
||||
|
||||
finalize_review() {
|
||||
local route_basis=$1
|
||||
shift
|
||||
local scores=("$@")
|
||||
local route
|
||||
|
||||
[[ "$route_basis" == official-review ]] || usage
|
||||
route=$("$formatter" review cloud "${scores[@]}")
|
||||
REVIEW_ROUTE_BASIS=$route_basis
|
||||
REVIEW_LANE=$(field "$route" lane)
|
||||
REVIEW_GRADE=$(field "$route" grade)
|
||||
REVIEW_FILENAME=$(field "$route" filename)
|
||||
REVIEW_ADAPTER=codex
|
||||
REVIEW_MODEL=gpt-5.6-sol
|
||||
REVIEW_REASONING_EFFORT=xhigh
|
||||
}
|
||||
|
||||
emit_build() {
|
||||
printf 'build_base_route_basis=%s\n' "$BUILD_BASE_ROUTE_BASIS"
|
||||
printf 'build_route_basis=%s\n' "$BUILD_ROUTE_BASIS"
|
||||
printf 'build_large_indivisible_context=%s\n' "$BUILD_LARGE_INDIVISIBLE_CONTEXT"
|
||||
printf 'build_loop_risk_count=%s\n' "$BUILD_LOOP_RISK_COUNT"
|
||||
printf 'build_risk_boundary_matched=%s\n' "$BUILD_RISK_BOUNDARY_MATCHED"
|
||||
printf 'build_review_rework_count=%s\n' "$BUILD_REVIEW_REWORK_COUNT"
|
||||
printf 'build_evidence_integrity_failure=%s\n' "$BUILD_EVIDENCE_INTEGRITY_FAILURE"
|
||||
printf 'build_recovery_boundary_matched=%s\n' "$BUILD_RECOVERY_BOUNDARY_MATCHED"
|
||||
printf 'build_lane=%s\n' "$BUILD_LANE"
|
||||
printf 'build_grade=%s\n' "$BUILD_GRADE"
|
||||
printf 'build_filename=%s\n' "$BUILD_FILENAME"
|
||||
}
|
||||
|
||||
emit_review() {
|
||||
printf 'review_route_basis=%s\n' "$REVIEW_ROUTE_BASIS"
|
||||
printf 'review_lane=%s\n' "$REVIEW_LANE"
|
||||
printf 'review_grade=%s\n' "$REVIEW_GRADE"
|
||||
printf 'review_filename=%s\n' "$REVIEW_FILENAME"
|
||||
printf 'review_adapter=%s\n' "$REVIEW_ADAPTER"
|
||||
printf 'review_model=%s\n' "$REVIEW_MODEL"
|
||||
printf 'review_reasoning_effort=%s\n' "$REVIEW_REASONING_EFFORT"
|
||||
}
|
||||
|
||||
mode=${1:-}
|
||||
[[ "$mode" == pair && $# -eq 17 ]] || usage
|
||||
|
||||
case "$3" in
|
||||
true|false)
|
||||
BUILD_LARGE_INDIVISIBLE_CONTEXT=$3
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$4" in
|
||||
0|1|2|3|4|5)
|
||||
BUILD_LOOP_RISK_COUNT=$4
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
[[ "$5" =~ ^[0-9]+$ ]] || usage
|
||||
BUILD_REVIEW_REWORK_COUNT=$5
|
||||
|
||||
case "$6" in
|
||||
true|false)
|
||||
BUILD_EVIDENCE_INTEGRITY_FAILURE=$6
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
finalize_build "$2" "${@:7:5}"
|
||||
finalize_review "${12}" "${@:13:5}"
|
||||
|
||||
printf 'finalizer=finalize-task-policy.sh\n'
|
||||
printf 'finalizer_mode=%s\n' "$mode"
|
||||
emit_build
|
||||
emit_review
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
printf '%s\n' \
|
||||
'usage: finalize-task-route.sh <build|review> <local|cloud> <scope> <state> <blast> <evidence> <verification>' >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
if [[ $# -ne 7 ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
target=$1
|
||||
lane=$2
|
||||
scores=("${@:3:5}")
|
||||
|
||||
case "$target" in
|
||||
build)
|
||||
prefix=PLAN
|
||||
;;
|
||||
review)
|
||||
prefix=CODE_REVIEW
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$lane" in
|
||||
local|cloud)
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
sum=0
|
||||
for score in "${scores[@]}"; do
|
||||
case "$score" in
|
||||
0|1|2)
|
||||
sum=$((sum + score))
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $sum -lt 1 ]]; then
|
||||
sum=1
|
||||
fi
|
||||
|
||||
printf 'target=%s\n' "$target"
|
||||
printf 'lane=%s\n' "$lane"
|
||||
printf 'grade=G%02d\n' "$sum"
|
||||
printf 'filename=%s-%s-G%02d.md\n' "$prefix" "$lane" "$sum"
|
||||
|
|
@ -1,364 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
import subprocess
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SKILL_DIR = Path(__file__).resolve().parents[1]
|
||||
FORMATTER = SKILL_DIR / "scripts" / "finalize-task-route.sh"
|
||||
POLICY_FINALIZER = SKILL_DIR / "scripts" / "finalize-task-policy.sh"
|
||||
PLAN_SKILL = SKILL_DIR.parent / "plan" / "SKILL.md"
|
||||
COMMON_SKILLS_DIR = SKILL_DIR.parent
|
||||
COMMON_RULES_DIR = SKILL_DIR.parents[2] / "rules" / "common"
|
||||
|
||||
|
||||
GRADE_VECTORS = {
|
||||
1: (0, 0, 0, 0, 0),
|
||||
2: (2, 0, 0, 0, 0),
|
||||
3: (2, 1, 0, 0, 0),
|
||||
4: (2, 2, 0, 0, 0),
|
||||
5: (2, 2, 1, 0, 0),
|
||||
6: (2, 2, 2, 0, 0),
|
||||
7: (2, 2, 2, 1, 0),
|
||||
8: (2, 2, 2, 2, 0),
|
||||
9: (2, 2, 2, 2, 1),
|
||||
10: (2, 2, 2, 2, 2),
|
||||
}
|
||||
|
||||
|
||||
def run(
|
||||
script: Path, *args: object, check: bool = True
|
||||
) -> subprocess.CompletedProcess[str]:
|
||||
return subprocess.run(
|
||||
[str(script), *(str(arg) for arg in args)],
|
||||
check=check,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5,
|
||||
)
|
||||
|
||||
|
||||
def fields(stdout: str) -> dict[str, str]:
|
||||
return dict(line.split("=", 1) for line in stdout.splitlines())
|
||||
|
||||
|
||||
def expected_build_route(basis: str, grade: int) -> tuple[str, bool]:
|
||||
if basis == "local-fit":
|
||||
return "local", grade <= 8
|
||||
if basis == "capability-gap":
|
||||
return "cloud", True
|
||||
return "cloud", grade >= 9
|
||||
|
||||
|
||||
def pair_args(
|
||||
build_basis: str,
|
||||
build_grade: int,
|
||||
review_grade: int,
|
||||
large_context: str = "false",
|
||||
risk_count: int = 0,
|
||||
review_rework_count: int = 0,
|
||||
evidence_integrity: str = "false",
|
||||
review_basis: str = "official-review",
|
||||
) -> tuple[object, ...]:
|
||||
return (
|
||||
"pair",
|
||||
build_basis,
|
||||
large_context,
|
||||
risk_count,
|
||||
review_rework_count,
|
||||
evidence_integrity,
|
||||
*GRADE_VECTORS[build_grade],
|
||||
review_basis,
|
||||
*GRADE_VECTORS[review_grade],
|
||||
)
|
||||
|
||||
|
||||
class FinalizeTaskRoutingTests(unittest.TestCase):
|
||||
def assert_route(
|
||||
self,
|
||||
result: dict[str, str],
|
||||
target: str,
|
||||
basis: str,
|
||||
lane: str,
|
||||
grade: int,
|
||||
) -> None:
|
||||
prefix = "PLAN" if target == "build" else "CODE_REVIEW"
|
||||
self.assertEqual(result[f"{target}_route_basis"], basis)
|
||||
self.assertEqual(result[f"{target}_lane"], lane)
|
||||
self.assertEqual(result[f"{target}_grade"], f"G{grade:02d}")
|
||||
self.assertEqual(
|
||||
result[f"{target}_filename"], f"{prefix}-{lane}-G{grade:02d}.md"
|
||||
)
|
||||
|
||||
def test_common_workflows_do_not_depend_on_project_runtime(self) -> None:
|
||||
contract_roots = (
|
||||
COMMON_RULES_DIR / "rules-roadmap.md",
|
||||
COMMON_SKILLS_DIR / "create-roadmap",
|
||||
COMMON_SKILLS_DIR / "update-roadmap",
|
||||
COMMON_SKILLS_DIR / "sync-milestone-workstate",
|
||||
COMMON_SKILLS_DIR / "complete-milestone",
|
||||
COMMON_SKILLS_DIR / "plan",
|
||||
COMMON_SKILLS_DIR / "code-review",
|
||||
COMMON_SKILLS_DIR / "refine-local-plans",
|
||||
COMMON_SKILLS_DIR / "finalize-task-routing",
|
||||
)
|
||||
contract_files: list[Path] = []
|
||||
for root in contract_roots:
|
||||
candidates = (root,) if root.is_file() else root.rglob("*")
|
||||
contract_files.extend(
|
||||
path
|
||||
for path in candidates
|
||||
if path.is_file()
|
||||
and path.suffix in {".md", ".sh", ".yaml"}
|
||||
and "tests" not in path.parts
|
||||
)
|
||||
|
||||
forbidden = (
|
||||
"agent-ops/skills/project/",
|
||||
"orchestrate-agent-task-loop",
|
||||
"WORK_LOG.md",
|
||||
"work_log_",
|
||||
"dispatch.py",
|
||||
)
|
||||
for path in sorted(contract_files):
|
||||
text = path.read_text(encoding="utf-8")
|
||||
for needle in forbidden:
|
||||
with self.subTest(path=path, needle=needle):
|
||||
self.assertNotIn(needle, text)
|
||||
|
||||
def test_request_to_worker_contract_is_ordered_and_consistent(self) -> None:
|
||||
routing_skill = (SKILL_DIR / "SKILL.md").read_text(encoding="utf-8")
|
||||
plan_skill = PLAN_SKILL.read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn("`matched_loop_risk_signatures`", routing_skill)
|
||||
self.assertIn("`temporal_state`", routing_skill)
|
||||
self.assertNotIn("`ordered_transitions`", routing_skill)
|
||||
self.assertIn("routing 때문에 source/test/log를 다시 읽지", routing_skill)
|
||||
self.assertIn("첫 번째로 일치하는 규칙", routing_skill)
|
||||
self.assertIn("이미 cloud인 capability/grade basis를 덮어쓰지 않는다", routing_skill)
|
||||
self.assertIn("review gap만 기록; build basis에는 영향 없음", routing_skill)
|
||||
|
||||
markers = (
|
||||
"**Assess split boundaries once**",
|
||||
"**Derive routing signals once**",
|
||||
"## Step 3 - Finalize Task Routing",
|
||||
)
|
||||
positions = [plan_skill.index(marker) for marker in markers]
|
||||
self.assertEqual(positions, sorted(positions))
|
||||
self.assertNotIn("**Extract the request contract**", plan_skill)
|
||||
self.assertNotIn("`요청 계약`", plan_skill)
|
||||
self.assertIn("reuse the values already validated and appended", plan_skill)
|
||||
policy_script = POLICY_FINALIZER.read_text(encoding="utf-8")
|
||||
self.assertNotIn("build_risk_triggered", policy_script)
|
||||
self.assertNotIn("boundary_triggered", policy_script)
|
||||
|
||||
def test_formatter_grade_and_filename_matrix(self) -> None:
|
||||
for target, lane, grade in itertools.product(
|
||||
("build", "review"), ("local", "cloud"), range(1, 11)
|
||||
):
|
||||
with self.subTest(target=target, lane=lane, grade=grade):
|
||||
result = fields(run(FORMATTER, target, lane, *GRADE_VECTORS[grade]).stdout)
|
||||
prefix = "PLAN" if target == "build" else "CODE_REVIEW"
|
||||
self.assertEqual(result["grade"], f"G{grade:02d}")
|
||||
self.assertEqual(
|
||||
result["filename"], f"{prefix}-{lane}-G{grade:02d}.md"
|
||||
)
|
||||
|
||||
def test_formatter_invalid_inputs_are_rejected(self) -> None:
|
||||
valid = list(GRADE_VECTORS[4])
|
||||
invalid_cases: list[tuple[object, ...]] = [
|
||||
("deploy", "local", *valid),
|
||||
("build", "hybrid", *valid),
|
||||
("build", "local", *valid[:-1]),
|
||||
("build", "local", *valid, 1),
|
||||
]
|
||||
for index in range(5):
|
||||
scores = valid.copy()
|
||||
scores[index] = 3
|
||||
invalid_cases.append(("build", "local", *scores))
|
||||
for args in invalid_cases:
|
||||
with self.subTest(args=args):
|
||||
self.assertEqual(run(FORMATTER, *args, check=False).returncode, 2)
|
||||
|
||||
def test_pair_policy_validates_each_build_basis_and_grade(self) -> None:
|
||||
for basis, grade in itertools.product(
|
||||
("local-fit", "capability-gap", "grade-boundary"), range(1, 11)
|
||||
):
|
||||
with self.subTest(basis=basis, grade=grade):
|
||||
completed = run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args(basis, grade, 1),
|
||||
check=False,
|
||||
)
|
||||
lane, valid = expected_build_route(basis, grade)
|
||||
if not valid:
|
||||
self.assertEqual(completed.returncode, 2)
|
||||
continue
|
||||
self.assertEqual(completed.returncode, 0, completed.stderr)
|
||||
result = fields(completed.stdout)
|
||||
self.assertEqual(result["finalizer_mode"], "pair")
|
||||
self.assert_route(result, "build", basis, lane, grade)
|
||||
|
||||
def test_official_review_keeps_grade_and_fixes_execution_target(self) -> None:
|
||||
for grade in range(1, 11):
|
||||
with self.subTest(grade=grade):
|
||||
result = fields(
|
||||
run(POLICY_FINALIZER, *pair_args("local-fit", 1, grade)).stdout
|
||||
)
|
||||
self.assert_route(
|
||||
result, "review", "official-review", "cloud", grade
|
||||
)
|
||||
self.assertEqual(result["review_adapter"], "codex")
|
||||
self.assertEqual(result["review_model"], "gpt-5.6-sol")
|
||||
self.assertEqual(result["review_reasoning_effort"], "xhigh")
|
||||
|
||||
def test_low_grade_cloud_requires_capability_gap_basis(self) -> None:
|
||||
rejected = run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args("grade-boundary", 4, 4),
|
||||
check=False,
|
||||
)
|
||||
self.assertEqual(rejected.returncode, 2)
|
||||
|
||||
accepted = fields(
|
||||
run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args("capability-gap", 4, 4),
|
||||
).stdout
|
||||
)
|
||||
self.assert_route(accepted, "build", "capability-gap", "cloud", 4)
|
||||
|
||||
def test_loop_risk_boundary_routes_four_or_more_signatures_to_cloud(self) -> None:
|
||||
for risk_count in range(6):
|
||||
with self.subTest(risk_count=risk_count):
|
||||
result = fields(
|
||||
run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args("local-fit", 7, 6, risk_count=risk_count),
|
||||
).stdout
|
||||
)
|
||||
self.assertEqual(result["build_loop_risk_count"], str(risk_count))
|
||||
expected_basis = "risk-boundary" if risk_count >= 4 else "local-fit"
|
||||
expected_lane = "cloud" if risk_count >= 4 else "local"
|
||||
self.assertEqual(result["build_base_route_basis"], "local-fit")
|
||||
self.assert_route(result, "build", expected_basis, expected_lane, 7)
|
||||
|
||||
def test_large_indivisible_context_routes_to_cloud(self) -> None:
|
||||
result = fields(
|
||||
run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args("local-fit", 4, 4, large_context="true"),
|
||||
).stdout
|
||||
)
|
||||
self.assertEqual(result["build_risk_boundary_matched"], "true")
|
||||
self.assert_route(result, "build", "risk-boundary", "cloud", 4)
|
||||
|
||||
def test_review_rework_and_evidence_integrity_route_to_cloud(self) -> None:
|
||||
one_rework = fields(
|
||||
run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args("local-fit", 4, 4, review_rework_count=1),
|
||||
).stdout
|
||||
)
|
||||
self.assert_route(one_rework, "build", "local-fit", "local", 4)
|
||||
|
||||
two_reworks = fields(
|
||||
run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args("local-fit", 4, 4, review_rework_count=2),
|
||||
).stdout
|
||||
)
|
||||
self.assert_route(
|
||||
two_reworks, "build", "recovery-boundary", "cloud", 4
|
||||
)
|
||||
|
||||
evidence_failure = fields(
|
||||
run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args("local-fit", 4, 4, evidence_integrity="true"),
|
||||
).stdout
|
||||
)
|
||||
self.assert_route(
|
||||
evidence_failure, "build", "recovery-boundary", "cloud", 4
|
||||
)
|
||||
|
||||
recovery_over_risk = fields(
|
||||
run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args(
|
||||
"local-fit",
|
||||
4,
|
||||
4,
|
||||
large_context="true",
|
||||
review_rework_count=2,
|
||||
),
|
||||
).stdout
|
||||
)
|
||||
self.assertEqual(recovery_over_risk["build_base_route_basis"], "local-fit")
|
||||
self.assert_route(
|
||||
recovery_over_risk, "build", "recovery-boundary", "cloud", 4
|
||||
)
|
||||
|
||||
def test_grade_boundary_is_not_relabelled_by_escalation_signals(self) -> None:
|
||||
result = fields(
|
||||
run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args(
|
||||
"grade-boundary",
|
||||
9,
|
||||
4,
|
||||
large_context="true",
|
||||
risk_count=5,
|
||||
review_rework_count=2,
|
||||
evidence_integrity="true",
|
||||
),
|
||||
).stdout
|
||||
)
|
||||
self.assertEqual(result["build_base_route_basis"], "grade-boundary")
|
||||
self.assertEqual(result["build_risk_boundary_matched"], "true")
|
||||
self.assertEqual(result["build_recovery_boundary_matched"], "true")
|
||||
self.assert_route(result, "build", "grade-boundary", "cloud", 9)
|
||||
|
||||
def test_capability_gap_has_precedence_over_other_cloud_triggers(self) -> None:
|
||||
result = fields(
|
||||
run(
|
||||
POLICY_FINALIZER,
|
||||
*pair_args(
|
||||
"capability-gap",
|
||||
4,
|
||||
4,
|
||||
large_context="true",
|
||||
risk_count=5,
|
||||
review_rework_count=2,
|
||||
evidence_integrity="true",
|
||||
),
|
||||
).stdout
|
||||
)
|
||||
self.assertEqual(result["build_base_route_basis"], "capability-gap")
|
||||
self.assert_route(result, "build", "capability-gap", "cloud", 4)
|
||||
|
||||
def test_policy_invalid_inputs_are_rejected(self) -> None:
|
||||
valid = GRADE_VECTORS[4]
|
||||
invalid_cases = (
|
||||
("pair", "local-fit", "unknown", 0, 0, "false", *valid, "official-review", *valid),
|
||||
("pair", "local-fit", "false", 6, 0, "false", *valid, "official-review", *valid),
|
||||
("pair", "local-fit", "false", 0, -1, "false", *valid, "official-review", *valid),
|
||||
("pair", "local-fit", "false", 0, 0, "unknown", *valid, "official-review", *valid),
|
||||
("pair", "local", "false", 0, 0, "false", *valid, "official-review", *valid),
|
||||
("pair", "local-fit", "false", 0, 0, "false", *valid, "cloud", *valid),
|
||||
("build", "local-fit", "false", 0, 0, "false", *valid),
|
||||
("pair", "local-fit", "false", 0, 0, "false", *valid, "official-review", *valid[:-1]),
|
||||
)
|
||||
for args in invalid_cases:
|
||||
with self.subTest(args=args):
|
||||
self.assertEqual(
|
||||
run(POLICY_FINALIZER, *args, check=False).returncode,
|
||||
2,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -72,8 +72,7 @@ description: 프로젝트 상태를 판별하고 agent-ops 기본 스캐폴드
|
|||
| `agent-ops/rules/project/rules.md` | 프로젝트 분석 후 생성 |
|
||||
| `agent-ops/rules/project/domain/<domain>/rules.md` | 도메인 분석 후 생성 |
|
||||
| `agent-ops/rules/private/` | 폴더만 생성 (내용은 개인이 작성) |
|
||||
| `agent-ops/skills/private/` | 폴더만 생성 (내용은 개인이 작성) |
|
||||
| `.gitignore`에 `agent-ops/rules/private/`, `agent-ops/skills/private/` 추가 | git 추적 제외 |
|
||||
| `.gitignore`에 `agent-ops/rules/private/` 추가 | git 추적 제외 |
|
||||
| `.gitignore`의 Agent-Ops 관리 block | `*.log` 같은 전역 ignore가 있어도 `agent-task/**/*.md`, `agent-task/**/*.log` task 산출물이 추적되도록 unignore하고 `agent-roadmap/current.md`는 로컬 포인터로 ignore |
|
||||
| `agent-test/local/rules.md` | `init-agent-ops.sh`가 최소 내용으로 생성 |
|
||||
| `agent-test/local/project-smoke.md` | 도메인이 아직 없으면 `init-agent-ops.sh`가 fallback baseline으로 생성 |
|
||||
|
|
@ -255,7 +254,7 @@ common/rules.md와 내용이 중복되지 않도록 한다.
|
|||
- [ ] `agent-ops/rules/project/rules.md`가 생성되었고, 필수 항목(응답 언어, 프로젝트 개요, 기술 스택)이 포함되어 있는가
|
||||
- [ ] 생성된 domain rules.md가 `domain-rule-template.md` 형식을 따르는가
|
||||
- [ ] `rules/project/rules.md`의 도메인 매핑 테이블에 생성된 도메인이 모두 등록되어 있는가
|
||||
- [ ] `agent-ops/rules/private/`, `agent-ops/skills/private/`가 생성되고 `.gitignore`에 각각의 항목이 추가되어 있는가
|
||||
- [ ] `.gitignore`에 `agent-ops/rules/private/` 항목이 추가되어 있는가
|
||||
- [ ] `.gitignore`에 Agent-Ops 관리 block이 있고 `!agent-task/`, `!agent-task/**/`, `!agent-task/**/*.md`, `!agent-task/**/*.log`, `agent-roadmap/current.md`가 포함되어 있는가
|
||||
- [ ] `agent-test/local/rules.md`가 생성되었는가
|
||||
- [ ] 생성되었거나 기존에 있던 모든 domain rule에 대응하는 `agent-test/local/<domain>-smoke.md`가 있는가
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
name: plan
|
||||
description: Analyze the current repository and write a detailed PLAN-{build_lane}-GNN.md plus CODE_REVIEW-{review_lane}-GNN.md stub for implementation work. Use for every feature, refactor, bug fix, and code-review WARN/FAIL follow-up that enters the plan-code-review loop. Every initial or follow-up pair must run finalize-task-routing after analysis and before routed filenames are chosen. Milestone-linked work uses a reserved m-prefixed task group so runtime can route PASS completion events to update-roadmap.
|
||||
description: Analyze the current repository and write a detailed PLAN-{build_lane}-GNN.md for implementation work. Also writes the CODE_REVIEW-{review_lane}-GNN.md stub that the implementing agent will fill in after coding. Use for any feature, refactor, bug fix, or follow-up fix that should enter the plan-code-review loop. Milestone-linked work uses a reserved m-prefixed task group so runtime can route PASS completion events to update-roadmap. A separate implementing agent, or the same agent in an implementation pass, reads the plan file and does the coding.
|
||||
---
|
||||
|
||||
# Plan
|
||||
|
|
@ -10,30 +10,20 @@ description: Analyze the current repository and write a detailed PLAN-{build_lan
|
|||
Create the planning artifacts for the implementation loop:
|
||||
|
||||
```text
|
||||
plan skill -> analysis -> finalize-task-routing -> PLAN-{build_lane}-GNN.md + CODE_REVIEW-{review_lane}-GNN.md stub
|
||||
implementation -> code changes + filled implementation evidence in CODE_REVIEW-{review_lane}-GNN.md
|
||||
code-review skill -> verdict + archive, complete.log and task-directory archive move, USER_REVIEW.md, or mandatory plan-skill follow-up
|
||||
plan skill -> PLAN-{build_lane}-GNN.md + CODE_REVIEW-{review_lane}-GNN.md stub
|
||||
implementation -> code changes + filled CODE_REVIEW-{review_lane}-GNN.md, or blocked-state user-review request recorded in the review stub
|
||||
code-review skill -> verdict + archive, complete.log, and PASS/user-review-resolved task-directory archive move, new follow-up plan/review files, or USER_REVIEW.md
|
||||
runtime -> for m-prefixed PASS completion events, state check and optional update-roadmap call
|
||||
```
|
||||
|
||||
`code-review` may stop the automatic loop with `USER_REVIEW.md` only when a selected Milestone `구현 잠금 > 결정 필요` item blocks implementation. Repeated non-PASS reviews, test environment blockers, external environment/secret/service setup, generic scope changes, and verification evidence gaps are not user-review reasons by themselves; they should become normal follow-up plans or unresolved verification evidence. Plan creation after `USER_REVIEW.md` requires the linked Milestone decision to be resolved. If the decision closes the task as complete/PASS, code-review resolves `USER_REVIEW.md`, writes `complete.log`, and archives the task instead of creating a new plan.
|
||||
`code-review` may stop the automatic loop with `USER_REVIEW.md` only when a selected SDD decision or selected Milestone `구현 잠금 > 결정 필요` item blocks implementation. Repeated non-PASS reviews, test environment blockers, external environment/secret/service setup, generic scope changes, and verification evidence gaps are not user-review reasons by themselves; they should become normal follow-up plans or unresolved verification evidence. Plan creation after `USER_REVIEW.md` requires the linked SDD/Milestone decision to be resolved. If the decision closes the task as complete/PASS, code-review resolves `USER_REVIEW.md`, writes `complete.log`, and archives the task instead of creating a new plan.
|
||||
|
||||
The plan file and review stub must be self-sufficient for implementation agents that do not read this skill. Implementing agents fill the active review's implementation evidence. They never decide whether user review is needed, write a user-review request, ask the user for a decision, create `USER_REVIEW.md`, or modify runtime-owned artifacts; those control-plane responsibilities belong to the official code-review skill and runtime.
|
||||
The plan file and review stub must be self-sufficient for implementation agents that do not read this skill. If implementation discovers a selected SDD decision or selected Milestone `구현 잠금 > 결정 필요` item that blocks safe progress, the implementing agent records a `사용자 리뷰 요청` in the active `CODE_REVIEW-*-G??.md`, leaves active files in place, and reports ready for review. This stop path is file-based only during implementation: the implementing agent must not interrupt the loop by asking the user directly, presenting choices in chat, or calling a user-input tool such as `request_user_input`. The code-review skill validates that request and writes `USER_REVIEW.md` when the stop is justified. Use `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` as the shared section template.
|
||||
|
||||
## Workflow Contract
|
||||
|
||||
This skill intentionally uses routed active files under an active task directory as the state protocol. Do not change this directory or filename contract unless the paired code-review skill is updated together.
|
||||
|
||||
Invocation modes:
|
||||
|
||||
- `write` is the default for initial plans and explicit replans. After routing, this skill archives any prior active pair and writes the new pair.
|
||||
- `prepare-follow-up` is used only when code-review has appended WARN/FAIL but has not archived the active pair. This skill completes analysis, final routing, and exact PLAN/review-stub rendering in memory without mutating repository files. It returns `prepared_plan`, `prepared_review`, their routed basenames, the current pair's predicted archive names/numbers, and the post-archive log counts used by the new pair.
|
||||
- Both modes execute the same mandatory Step 3. `prepare-follow-up` is not a route-only shortcut.
|
||||
|
||||
Optional context:
|
||||
|
||||
- `verification_context` is a neutral handoff containing environment, source paths, commands, expected results, preconditions, read-only preflight results, constraints, gaps, and confidence. Consume it when supplied, but verify that its paths and commands still match the current checkout. The plan remains responsible for repository-native fallback analysis when it is absent or incomplete.
|
||||
|
||||
Task path terms:
|
||||
|
||||
- `{task_group}` is the top-level work category under `agent-task/`. Normal task groups use a short snake_case name such as `refactoring`.
|
||||
|
|
@ -42,7 +32,7 @@ Task path terms:
|
|||
- `{subtask_name}` is the short snake_case name after the index or dependency prefix inside `{subtask_dir}`.
|
||||
- `{task_name}` in headers and templates means the active task path relative to `agent-task/`: either `{task_group}` for a single-plan task or `{task_group}/{subtask_dir}` for a split subtask.
|
||||
- A single-plan task stores active files directly under `agent-task/{task_group}/`.
|
||||
- Split work stores active files under `agent-task/{task_group}/{subtask_dir}/`; the parent `agent-task/{task_group}/` contains no active plan/review files.
|
||||
- Split work stores active files under `agent-task/{task_group}/{subtask_dir}/`; the parent `agent-task/{task_group}/` is only the grouping folder and must not contain active plan/review files.
|
||||
|
||||
Filename rules:
|
||||
|
||||
|
|
@ -50,30 +40,31 @@ Filename rules:
|
|||
- Review stub: `CODE_REVIEW-{review_lane}-GNN.md`
|
||||
- `{lane}` is only `local` or `cloud`; never put model names in filenames.
|
||||
- `GNN` is a two-digit capability grade from `G01` to `G10`; the runtime maps lane+grade to current models externally.
|
||||
- Lane, grade, and both canonical basenames come only from `agent-ops/skills/common/finalize-task-routing/SKILL.md`.
|
||||
|
||||
Role boundary rules:
|
||||
|
||||
- Implementing agents fill implementation-owned `CODE_REVIEW-*-G??.md` sections, keep active files in place, and report ready for review.
|
||||
- If implementation cannot continue, implementing agents record the exact blocker, attempted commands/output, and resume condition only in `Verification Results` or `Deviations from Plan` (legacy: `검증 결과` or `계획 대비 변경 사항`), then leave the active files in place for official review.
|
||||
- During implementation, do not ask the user directly, present choices, call user-input tools, or create control-plane stop files. The official reviewer owns all next-state classification.
|
||||
- Required UI evidence capture that needs a user-owned device, emulator, permission, secret, or interactive access unavailable to the agent is a verification blocker, not a user-review reason by itself. Record attempted commands and blocker evidence in `Verification Results` or `Deviations from Plan` (legacy: `검증 결과` or `계획 대비 변경 사항`) so code-review can write a normal follow-up or unresolved verification report.
|
||||
- Finalization (`Code Review Result` [legacy: `코드리뷰 결과`], plan/review log rename, `complete.log`, task artifact archive moves, review-only checklist) is code-review-skill only.
|
||||
- If implementation cannot continue because a selected SDD decision or selected Milestone `구현 잠금 > 결정 필요` item is unresolved, implementing agents fill the review stub's `사용자 리뷰 요청` section with the exact linked decision, evidence, commands/output, and resume condition, then stop with active files in place.
|
||||
- During implementation, do not ask the user directly, present multiple-choice prompts in chat, or call `request_user_input`/equivalent input tools. SDD/Milestone lock choices belong in the review stub's `사용자 리뷰 요청` section so code-review can validate and create `USER_REVIEW.md` only when justified.
|
||||
- Required UI evidence capture that needs a user-owned device, emulator, permission, secret, or interactive access unavailable to the agent is a verification blocker, not a user-review reason by itself. Record attempted commands and blocker evidence in `검증 결과` or `계획 대비 변경 사항` so code-review can write a normal follow-up or unresolved verification report.
|
||||
- Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, review-only checklist) is code-review-skill only.
|
||||
|
||||
Split decision policy:
|
||||
|
||||
- Split only by behavior/contract boundaries whose children each have a stable intermediate contract and deterministic PASS verification.
|
||||
- Keep every production change with its required tests; use a test-only child only for additional integration evidence.
|
||||
- Keep one plan when the work is compact or split would sever one correctness/transaction invariant. Never split to lower lane, grade, context, or signature count.
|
||||
- If the existing analysis cannot prove that children independently PASS, keep the atomic work together and route it as one packet.
|
||||
- Record either each child's contract/dependency or the invariant that makes one plan indivisible.
|
||||
- Default to multiple subtask directories under one task group. Before writing any plan, decide whether the work has smaller independently reviewable implementation units.
|
||||
- If there is any natural dependency boundary, ownership boundary, subsystem boundary, API-vs-call-site phase, test strategy split, or independently reviewable risk, write multiple subtask directories under one task group.
|
||||
- A single plan is an exception. Use one only when all of these are true: the work is one coherent implementation unit, it has one primary ownership boundary, it has no prerequisite subtask, splitting would create artificial coordination overhead, and the whole change remains easy to review at once.
|
||||
- When uncertain, split. Do not choose a single plan merely because it is shorter to write.
|
||||
- Record the split decision in the plan. For a single plan, explicitly state why each applicable split boundary does not require a separate task. For multi-plan output, list the shared `{task_group}`, each sibling `{subtask_dir}`, and its dependency relationship.
|
||||
|
||||
Split gates:
|
||||
|
||||
- Separate foundation from rollout only when the foundation preserves compatibility and independently passes.
|
||||
- Split domains, verification profiles, or risk slices only when each independently passes.
|
||||
- Split work that can produce a useful earlier `complete.log` without invalid intermediate state.
|
||||
- Isolate mobile/UI/external verification that can block otherwise completed implementation.
|
||||
- Split when the work combines shared API/foundation changes with broad call-site rollout. Put the API/foundation in an earlier task and the rollout in dependent task(s).
|
||||
- Split when the work touches multiple domains or ownership boundaries, unless the change is purely mechanical and trivially reviewable.
|
||||
- Split when different parts can be verified with different focused tests or have different risk profiles.
|
||||
- Split when a likely failure in one part would force rewriting unrelated parts of the plan.
|
||||
- Split when one part can produce a useful `complete.log` before another part starts.
|
||||
- Split when mobile/UI verification can hang on emulator/device state, modal, permission dialog, animation, or external runner; isolate evidence recovery from feature implementation.
|
||||
|
||||
Task directory naming rules:
|
||||
|
||||
|
|
@ -84,8 +75,6 @@ Task directory naming rules:
|
|||
- When split gates require decomposition, create one shared category folder and multiple subtask directories under it. Each subtask directory owns exactly one normal active plan file and one normal active review stub.
|
||||
- Multi-plan output is a set of independent `PLAN-{build_lane}-GNN.md` + `CODE_REVIEW-{review_lane}-GNN.md` pairs across `agent-task/{task_group}/{subtask_dir}/` folders, not multiple plan files inside one folder.
|
||||
- Multi-plan subtask directory names must start with a stable two-digit task index. The index must increase across sibling subtask directories for sorting, but it is not a serial execution dependency.
|
||||
- Assign new sibling indices in topological dependency order so every producer precedes its consumers. For ties, keep the planned sibling order; assign each task the lowest collision-free two-digit index greater than all of its predecessors.
|
||||
- Before writing the pairs, verify that the sibling dependency graph has no cycle and every predecessor index is lower than its consumer index. Skip an index only when it is not greater than an unchanged existing predecessor or is already occupied by an active/archived sibling.
|
||||
- Use `NN_{subtask_name}` for a task with no runtime dependencies, e.g. `01_core`, `04_docs`, `05_ui`.
|
||||
- Use `NN+PP[,QQ...]_{subtask_name}` for a task that depends on earlier task indices, e.g. `02+01_db`, `03+01,02_api`, `06+05_integration`.
|
||||
- Valid independent pattern: `^[0-9]{2}_[a-z0-9_]+$`.
|
||||
|
|
@ -102,16 +91,20 @@ Task directory naming rules:
|
|||
- Example: split a refactoring common core plus two app integrations under `agent-task/refactoring/` as `01_core`, `02+01_edge_integration`, `03+01_node_integration`. Both integrations depend only on `01_core` and may run in parallel after `01_core` has `complete.log`.
|
||||
- Example: split three sequential tasks under one task group as `01_schema`, `02+01_migration`, `03+02_api`.
|
||||
- Example: split independent docs/UI plus an integration under one task group as `01_core`, `02+01_db`, `03+02_api`, `04_docs`, `05_ui`, `06+05_integration`; `01_core`, `04_docs`, and `05_ui` can start together, and `06+05_integration` waits only for `05_ui`.
|
||||
- After a pair is written, preserve its task group and subtask directory name verbatim. Only an explicit `refine-local-plans` run may rename eligible unstarted local siblings by its dependency-order rules.
|
||||
- Preserve task group and subtask directory names verbatim; do not normalize, reinterpret, or choose execution order by agent judgment.
|
||||
|
||||
Final routing boundary:
|
||||
Routing rules:
|
||||
|
||||
- Keep the task `unrouted` until split, PLAN body, verification, evidence, ownership, and decisions are complete.
|
||||
- Treat each final in-memory PLAN as its build packet. Derive `large_indivisible_context` and positive loop-risk signatures once from analysis already required to write that PLAN; do not create a separate packet summary or search for negative risk evidence.
|
||||
- Execute `finalize-task-routing` once for build/review and use only its lane/G/filenames. Apply it to first-pass, follow-up, USER_REVIEW replan, and each split subtask independently.
|
||||
- Quarantine previous lane/G/score/rationale. Carry only revalidated code, findings, command output, `review_rework_count`, and `evidence_integrity_failure`.
|
||||
- `needs_evidence` names genuinely missing closure evidence; `blocked` stops file creation. Changed plan facts invalidate the route.
|
||||
- Only `refine-local-plans` may retain an unstarted local pair's route while splitting it into strict-subset local children.
|
||||
- Prefer `local` whenever the scope is bounded and verifiable; high local usage is fine. Do not choose `cloud` just to balance lane usage.
|
||||
- `local` is for bounded, explicit, locally verifiable work: required behavior is explicit in task evidence, contracts, or existing pattern; relevant context fits in edited files plus nearby types/helpers, direct call sites, and existing or planned targeted tests/fixtures; correctness can be checked by code inspection plus type/build/unit tests or deterministic commands; no open-ended product/design judgment, live external provider/runtime semantics, or broad cross-domain context is decisive.
|
||||
- Use `cloud` when any local condition is false, including when a plausible but wrong implementation could pass local checks while breaking behavior promised outside the bounded context.
|
||||
- `local-G01` through `local-G10` and `cloud-G01` through `cloud-G10` are valid. Lane is capability fit; grade is complexity within the chosen lane. Do not raise `local-GNN` to compensate for missing judgment, missing context, weak verification, or a previous loop failure.
|
||||
- Use `cloud-G07` or higher only when terminal-agent or external interactive behavior is central and cannot be made deterministic for local handling, or when the task requires more source/test/diff/log context than local can hold without omitting material evidence: shell/CLI workflow implementation, bin script orchestration, process control, stdout/stderr parsing, exit-status contracts, long-running command diagnosis, terminal benchmark-style tasks, TUI/PTY/browser/screen repaint/cursor stream behavior, real bin/smoke/integration failures after unit tests passed, or very large cross-module/cross-domain changes that cannot be safely split.
|
||||
- For follow-ups from a review with 5+ `Required` findings, reassess lane/grade and default to `cloud-G07` or higher unless all findings are one narrow mechanical fix pattern; if keeping `local`, record why local conditions still hold.
|
||||
- Previous loop lane does not matter. Recompute lane from the current plan or follow-up scope using these rules.
|
||||
- Treat non-behavioral review artifact drift as reviewer-repairable unless it prevents judging implementation correctness, tests, or contracts.
|
||||
- Treat obvious non-behavioral source nits as reviewer-repairable too: typos, stale comments, docs, or formatting only, with no behavior/test/API contract change.
|
||||
- Raise `GNN` with scope, ambiguity, missing tests, irreversible behavior, and blast radius after lane selection; keep grade model-independent.
|
||||
|
||||
Directory states:
|
||||
|
||||
|
|
@ -119,12 +112,12 @@ Directory states:
|
|||
|-------|---------|
|
||||
| `PLAN-*-G??.md` only | Invalid; plan skill always writes both active files |
|
||||
| `PLAN-*-G??.md` + `CODE_REVIEW-*-G??.md` stub | Implementation is pending/in progress |
|
||||
| `PLAN-*-G??.md` + filled `CODE_REVIEW-*-G??.md` without verdict | Ready for code-review skill |
|
||||
| `PLAN-*-G??.md` + `CODE_REVIEW-*-G??.md` with appended verdict | Review finalization is pending. Continue only when code-review invokes `prepare-follow-up`; `write` mode must not overwrite this state. |
|
||||
| `PLAN-*-G??.md` + `CODE_REVIEW-*-G??.md` with filled `사용자 리뷰 요청` | Implementation claims a selected SDD or Milestone lock decision blocker; ready for code-review to validate and create `USER_REVIEW.md` only if justified |
|
||||
| `PLAN-*-G??.md` + filled `CODE_REVIEW-*-G??.md` | Ready for code-review skill |
|
||||
| `complete.log` + `*.log` files | Task complete (PASS or user-review-resolved PASS), before final task-directory archive move |
|
||||
| `USER_REVIEW.md` + `*.log` files | Automatic loop stopped; linked Milestone lock decision must be resolved before creating another plan |
|
||||
| `USER_REVIEW.md` + `*.log` files | Automatic loop stopped; linked SDD/Milestone lock decision must be resolved before creating another plan |
|
||||
| `agent-task/archive/YYYY/MM/{task_name}/complete.log` + `*.log` files | Archived completed task path (PASS or user-review-resolved PASS); not active |
|
||||
| Only `*.log` files (no `complete.log`) | Inspect the newest review log. A verdict with no required next state is post-archive finalization pending; otherwise the task is terminated mid-loop or abandoned. |
|
||||
| Only `*.log` files (no `complete.log`) | Task terminated mid-loop or abandoned |
|
||||
|
||||
## Step 1 - Determine Task
|
||||
|
||||
|
|
@ -148,36 +141,31 @@ Also note active user-review stops, excluding `agent-task/archive/**`:
|
|||
|
||||
The routed plan file is the loop entry point. A missing active plan normally means only that no plan has been started for a new task; do not create task files for casual analysis, status, or review requests unless the user explicitly asks for a plan.
|
||||
|
||||
If no active plan exists but one or more `USER_REVIEW.md` files exist, report that the linked Milestone decision is required and list the paths unless one path is explicitly selected for resolution or replanning. If a selected active task directory contains `USER_REVIEW.md`, read it before planning. Do not write a new follow-up plan unless the linked Milestone decision has been resolved or the new plan explicitly replans around that recorded decision. When planning resumes from `USER_REVIEW.md`, archive it to `user_review_N.log` in the same task directory before writing the new active plan/review pair, and record the resolved decision in the new plan `Background` or `Analysis` (legacy: `배경` or `분석 결과`).
|
||||
If no active plan exists but one or more `USER_REVIEW.md` files exist, report that the linked SDD/Milestone decision is required and list the paths unless one path is explicitly selected for resolution or replanning. If a selected active task directory contains `USER_REVIEW.md`, read it before planning. Do not write a new follow-up plan unless the linked SDD/Milestone decision has been resolved or the new plan explicitly replans around that recorded decision. When planning resumes from `USER_REVIEW.md`, archive it to `user_review_N.log` in the same task directory before writing the new active plan/review pair, and record the resolved decision in the new plan `배경` or `분석 결과`.
|
||||
|
||||
If a selected task directory contains both `USER_REVIEW.md` and active `PLAN-*-G??.md` or `CODE_REVIEW-*-G??.md`, report an inconsistent loop state and do not overwrite either state until a later explicit command selects either user-review resolution or the active plan/review path.
|
||||
|
||||
If the selected review already has an appended verdict, accept it only in `prepare-follow-up` mode invoked by code-review. In every other mode, leave the pair unchanged and report that code-review finalization must resume.
|
||||
|
||||
로드맵 확인:
|
||||
|
||||
- `agent-roadmap/current.md`는 브랜치별 로컬 포인터다. 있으면 구현 계획 파일을 만들기 전에 읽고, 사용자 요청, 브랜치, 변경 경로를 기준으로 관련 Phase와 Milestone을 선택한다.
|
||||
- `agent-roadmap/priority-queue.md`가 있으면 명시 target이 없는 구현 계획에서 Phase를 가로지르는 후보 순서를 확인하기 위해 읽는다. 큐 순서는 우선순위 참고이며, 상태/잠금/기능 원본은 각 Milestone 문서다.
|
||||
- 사용자가 target Milestone을 명시하지 않았고 요청이 "다음 작업" 또는 일반 구현 계획이면 `priority-queue.md`의 위에서 아래 순서 중 요청과 맞고 활성 경로에 존재하는 첫 Milestone을 우선 후보로 둔다.
|
||||
- `priority-queue.md` 링크가 깨졌으면 Milestone을 추측해 계획하지 말고 `update-roadmap`으로 큐 재정렬/재생성이 필요하다고 보고한다.
|
||||
- `agent-roadmap/`이 있는데 `current.md`가 없으면 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식으로 로컬 파일을 만들거나, `ROADMAP.md`의 Phase 흐름과 관련 `PHASE.md`에서 후보를 고른 뒤 로컬 current를 채운다. current 없음만으로 일반 task routing으로 빠지지 않는다.
|
||||
- `current.md`가 `agent-roadmap/archive/**`를 가리키면 해당 문서는 읽지 말고 활성 Phase/Milestone이 아니라고 보고한다.
|
||||
- 선택한 Phase를 한 번 읽어 Phase 목표, Milestone 흐름, Phase 경계를 확인한다.
|
||||
- 선택한 Milestone을 한 번 읽어 목표, 상태, 승격 조건, 범위, 기능 Task, 완료 리뷰, 범위 제외, 구현 잠금을 확인한다. `승격 조건`은 `[스케치]`에서만 필수이며, `[계획]` 이상에서 섹션이 없으면 `없음`으로 본다. `구현 잠금` 섹션이 없거나, 상태가 `잠금`이거나, 미완료 `결정 필요` 항목이 하나라도 있으면 실구현 계획을 만들지 않는다.
|
||||
- 구현 잠금에 걸린 Milestone에서는 `PLAN-*-G??.md`, `CODE_REVIEW-*-G??.md`, task directory, file/API/package 수준 구현 단계를 확정하지 말고 `구현 잠금 차단`으로 보고한다. 보고에는 Milestone 경로, 잠금 상태, 남은 `결정 필요` 항목, 다음에 필요한 `update-roadmap` 조치를 적는다.
|
||||
- 선택한 Milestone을 한 번 읽어 목표, 상태, 승격 조건, 범위, 기능 Task, 완료 리뷰, 범위 제외, 구현 잠금, SDD 필요 여부를 확인한다. `승격 조건`은 `[스케치]`에서만 필수이며, `[계획]` 이상에서 섹션이 없으면 `없음`으로 본다. `구현 잠금` 섹션이 없거나, 상태가 `잠금`이거나, 미완료 `결정 필요` 항목이 하나라도 있으면 실구현 계획을 만들지 않는다.
|
||||
- 구현 잠금에 걸린 Milestone에서는 `PLAN-*-G??.md`, `CODE_REVIEW-*-G??.md`, task directory, file/API/package 수준 구현 단계를 확정하지 말고 `구현 잠금 차단`으로 보고한다. 보고에는 Milestone 경로, 잠금 상태, 남은 `결정 필요` 항목, 다음에 필요한 `update-roadmap` 또는 SDD 조치를 적는다.
|
||||
- 남은 `결정 필요` 항목이 현재 실구현 범위가 아니라고 판단되더라도 같은 plan 요청 안에서 구현 계획을 계속 쓰지 않는다. 먼저 roadmap-only 갱신으로 해당 항목을 `범위 제외`, 후속 Milestone, 또는 `작업 컨텍스트`로 옮기고 `구현 잠금`을 `해제`한 뒤 새 plan 요청에서 진행한다.
|
||||
- 선택한 Milestone에 `SDD: 필요`가 있으면 승인된 SDD를 구현 계획 작성의 입력으로 읽는다. SDD 문서가 없거나, 상태가 `[승인됨]`이 아니거나, `SDD 잠금`이 `잠금`이거나, 같은 디렉터리에 `USER_REVIEW.md`가 있으면 plan 파일을 만들지 말고 `roadmap-sdd` 또는 `update-roadmap` 조치가 필요하다고 보고한다.
|
||||
- `SDD: 필요` Milestone의 구현 계획은 Milestone 기능 Task만 보고 작성하지 않는다. 요청 대상 Task id에 연결된 SDD Acceptance Scenario와 Evidence Map을 먼저 매핑하고, 그 결과에서 구현 범위, checklist, 검증 명령, 완료 evidence를 역산한다. 매핑이 없거나 SDD와 Milestone Task가 어긋나면 plan 생성을 멈추고 SDD와 Milestone의 정합성 갱신이 필요하다고 보고한다.
|
||||
- 선택한 Milestone에 legacy `필수 기능`/`완료 기준`이 분리되어 있으면 plan 파일을 만들지 말고 `update-roadmap` 정규화가 필요하다고 보고한다.
|
||||
- 선택한 Milestone에 `SDD: 필요`가 있으면 SDD 문서와 같은 디렉터리의 `USER_REVIEW.md` 존재 여부를 확인한다. SDD 문서가 없거나 gate 정보가 부족하면 같은 요청 안에서 `roadmap-sdd`의 `create` 또는 `check-gate` 절차를 pre-plan gate로 먼저 적용해 SDD와 Milestone 구현 잠금 정보를 보강한다. SDD 결정 항목이 나오면 `roadmap-sdd review-ready` 방식으로 `USER_REVIEW.md`를 남기고 plan 파일을 만들지 않는다. 기존 `USER_REVIEW.md`가 있거나 SDD 상태가 `[승인됨]`이 아니거나 `SDD 잠금`이 `잠금`이면 `resolve-review` 또는 SDD 잠금 해제가 필요하다고 보고하고 멈춘다. SDD가 `[승인됨]`, `SDD 잠금: 해제`, 사용자 리뷰 없음 상태일 때만 plan 파일을 만든다.
|
||||
- 선택한 Milestone에 legacy `필수 기능`/`완료 기준`이 분리되어 있으면 plan 작성 전에 roadmap preflight로 정규화한다. 흡수 가능한 기준은 관련 기능 Task 안의 선택적 `검증:` 또는 Task 설명으로 즉시 흡수하고, 어느 기능에도 붙지 않는 기준이 남으면 plan 파일을 만들지 말고 남은 기준을 `구현 잠금 > 결정 필요`, SDD `USER_REVIEW.md`, 또는 작업 컨텍스트로 분리한다고 보고한다.
|
||||
- 선택한 Phase 또는 Milestone 상태가 `[스케치]`이면 구현 계획 파일을 만들지 않는다. `[스케치]`는 컨셉 상태이므로 `update-roadmap`의 concretize 흐름으로 승격 조건, 결정 필요, 범위, 기능 Task를 정리해 `[계획]`으로 전환해야 한다고 보고한다.
|
||||
- Phase 또는 Milestone 후보가 여럿이면 요청 문장, 변경 경로 직접성, Milestone 상태, 구현 잠금, 선후 의존성, Phase/Milestone 흐름상 위치를 기준으로 1순위와 2순위를 추천하고 필요한 후보 문서만 읽어 범위를 좁힌다.
|
||||
- 로드맵 current가 있고 활성 Phase/Milestone 밖 작업이면 `ROADMAP.md`의 Phase 흐름을 확인하고 전환, 신규 Phase/Milestone, 또는 기존 활성 범위 내 배치 필요성을 보고한다.
|
||||
- 사용자가 선택한 Milestone의 작업, 구현, 계획 작성을 명시했더라도 `구현 잠금`이 완전히 해제되어 있지 않으면 계획 작성을 이어가지 않는다. Milestone 전체에서 에이전트가 확정할 수 없는 결정 항목이 더 이상 없을 때만 roadmap update 흐름으로 `구현 잠금` 상태를 `해제`로 갱신할 수 있다.
|
||||
- 제품 선택, 우선순위 결정처럼 에이전트가 확정할 수 없는 항목은 구현 계획의 실행 checklist로 쓰지 않는다. 그런 항목이 남아 있으면 plan 생성을 멈추고 `구현 잠금 > 결정 필요`로 분리한다.
|
||||
- 제품 선택, 우선순위 결정처럼 에이전트가 확정할 수 없는 항목은 구현 계획의 실행 checklist로 쓰지 않는다. 그런 항목이 남아 있으면 plan 생성을 멈추고 `구현 잠금 > 결정 필요` 또는 SDD `USER_REVIEW.md`로 분리한다.
|
||||
- 기능 Task에 `검증:`이 있으면 구현 계획의 같은 plan item 안에 해당 검증을 포함한다. 검증이 명시되지 않은 기능 Task에는 억지 검증 항목을 만들지 말고, 필요한 일반 빌드/회귀 확인만 최종 검증에 둔다.
|
||||
- 선택한 활성 Milestone 범위에 속하는 구현 계획이면 `{task_group}`을 `m-<milestone-slug>`로 정한다. `<milestone-slug>`는 선택한 Milestone 경로의 파일명에서 `.md`를 제거한 값이다.
|
||||
- 같은 Milestone에서 split work가 필요하면 기존 split 규칙 그대로 `agent-task/m-<milestone-slug>/<subtask_dir>/` 아래에 계획 파일을 만든다.
|
||||
- Milestone 기능 Task 완료를 목표로 하는 계획이면 `Roadmap Targets` 섹션에 활성 Milestone 경로와 완료 대상 Task id를 고정한다. 이 섹션은 `complete.log`의 `Roadmap Completion` 근거로 복사되어 `update-roadmap`이 해당 Task만 체크하는 anchor가 된다. 이 섹션은 `{task_group}`이 해당 Milestone slug의 `m-<milestone-slug>`일 때만 쓴다.
|
||||
- 승인된 SDD가 있는 Milestone 기능 Task 완료 계획이면 `Spec Targets` 섹션도 쓴다. SDD 경로, Acceptance Scenario id, Evidence Map 기대 근거를 고정한다. 이 섹션은 `complete.log`의 `Spec Completion` 근거로 복사된다.
|
||||
- Milestone 작업이 아니거나, Milestone 안의 조사/하위 구현처럼 특정 기능 Task 완료를 주장하지 않는 계획이면 `Roadmap Targets` 섹션을 쓰지 않는다. 섹션이 없으면 PASS 후에도 roadmap Task 체크를 하지 않는다.
|
||||
- `agent-roadmap/` 디렉터리가 없으면 기존 task routing 규칙대로 진행한다.
|
||||
|
||||
|
|
@ -187,97 +175,101 @@ Before choosing plan files or task directory names, apply the split decision pol
|
|||
|
||||
## Step 2 - Analyze Before Writing
|
||||
|
||||
Complete all items below before creating active plan/review files. Work through them in order; do not proceed to the next step until every checkbox is done. Keep the user request as the scope anchor and reconcile derived acceptance conditions before the split decision; do not create a separate routing summary. The only allowed file edits before writing plan/review files are local `agent-roadmap/current.md` creation or `.gitignore` block repair needed for roadmap routing.
|
||||
Complete all items below before creating active plan/review files. Work through them in order; do not proceed to the next step until every checkbox is done. The only allowed pre-plan file edits are local `agent-roadmap/current.md` creation or `.gitignore` block repair needed for roadmap routing, `roadmap-sdd` pre-plan gate edits for a selected `SDD: 필요` Milestone, plus `create-test` or `update-test` edits needed to make test rules usable for this plan.
|
||||
|
||||
- [ ] **Resolve verification context** — because implementation plans include verification, consume supplied `verification_context` when present and confirm its source paths, commands, expected results, preconditions, constraints, gaps, and confidence still apply. When it is absent or incomplete, derive the missing facts from repository manifests, scripts, workflows, domain rules, related tests, user-provided environment facts, and safe read-only probes. Record which facts came from the handoff and which came from repository-native fallback evidence. A missing optional handoff is not a user-review blocker.
|
||||
- [ ] **Load test environment rules** — because implementation plans include verification, determine `test_env` before choosing verification commands. Use the user-specified environment when provided; otherwise use `local`. Check `agent-test/<test_env>/rules.md` and read it in full when present, even if it appears blank or skeleton. If it is absent, or present but structurally blank/skeleton, invoke `create-test` with `env=<test_env>` when this repo can be edited, then re-read the generated or completed rules before writing the plan. If creation is not possible in the current task context, record the gap and fallback source; absence is not a user-review blocker by itself.
|
||||
- [ ] **Read all source files in full** — read every source file the change will touch, whole file. No partial reads.
|
||||
- [ ] **Preflight external verification** — when any required verification leaves the current checkout, including remote runner, field/bootstrap, external provider, Docker/code-server, emulator/device, or shared long-running runtime, confirm or derive a read-only preflight before writing final verification commands. Record runner, repo root/workdir, branch/HEAD/dirty state, source sync status, binary/artifact paths, command help/version output needed by the verification, config path, runtime identity, ports/process state, external hosts, and OS/arch assumptions. If the preflight shows stale artifacts, dirty/divergent checkout, wrong identity, missing command, closed ports, host OS mismatch, or unsynced source, add an explicit setup/sync/rebuild step or report the blocker.
|
||||
- [ ] **Read all test files in full** — read every test file that exercises the changed behavior, including files identified by the verification context and repository test layout.
|
||||
- [ ] **Resolve test profiles** — from the env rules `## 라우팅`, read every matching `agent-test/<test_env>/<test-profile>.md` in full. Use `create-test` for missing or structurally blank routes/profiles when the current task can safely fill the gap. Use `update-test` only when verified command or criteria facts are available or the user asked to maintain test rules. If a profile exists but leaves command/criteria values as `<확인 필요>`, record the incomplete values and choose fallback verification commands from repository manifests or workflows with lower confidence. Do not claim agent-test requires a command that is not written in the env rules or matched profiles.
|
||||
- [ ] **Read all test files in full** — read every test file that exercises the changed behavior, including files implied by the matched agent-test profiles and repository test layout.
|
||||
- [ ] **Assess test coverage** — for each behavior change, explicitly record whether existing tests cover it.
|
||||
- [ ] **Assess split boundaries once** — reconcile request acceptance with source/tests, then split only where every child has a stable contract and independent PASS verification. Otherwise keep the invariant together; do not gather extra evidence solely to lower routing risk.
|
||||
- [ ] **Capture recovery signals once** — first-pass uses `review_rework_count=0` and `evidence_integrity_failure=false`. In `prepare-follow-up`, reuse the values already validated and appended by code-review; do not recount verdict history. For another isolated replan, derive them once from the same-task state already loaded for planning, without a routing-only log pass.
|
||||
- [ ] **Resolve split predecessor completion** — if the selected or proposed subtask directory has `NN+PP[,QQ...]_...`, resolve each predecessor index under the same task group. Check only the active and archive candidate patterns defined in the task directory naming rules. Record found active/archive paths, missing predecessors, or ambiguous matches in `Analysis > Split Judgment` (legacy: `분석 결과 > 분할 판단`) and, when order matters, `Dependencies and Execution Order` (legacy: `의존 관계 및 구현 순서`).
|
||||
- [ ] **Assess split boundaries first** — identify dependency boundaries, ownership boundaries, API-vs-call-site phases, test strategy splits, risk profile splits, and independently verifiable subwork before selecting plan files. If any split gate applies or the decision is uncertain, write multiple subtask directories under one task group instead of one plan.
|
||||
- [ ] **Resolve split predecessor completion** — if the selected or proposed subtask directory has `NN+PP[,QQ...]_...`, resolve each predecessor index under the same task group. Check only the active and archive candidate patterns defined in the task directory naming rules. Record found active/archive paths, missing predecessors, or ambiguous matches in `분석 결과 > 분할 판단` and, when order matters, `의존 관계 및 구현 순서`.
|
||||
- [ ] **Grep all symbol references** — for any renamed or removed symbol, find every call site and import chain.
|
||||
- [ ] **Check dependency manifests** — before adding any new package, verify its presence in go.mod / package manifest.
|
||||
- [ ] **Pre-check compile issues** — identify missing interface implementations, type mismatches, and broken imports.
|
||||
- [ ] **Verify verification commands** — confirm that the final verification commands actually run in this repository layout.
|
||||
- [ ] **Stabilize fragile verification** — for search or generated-output checks, choose deterministic commands up front, such as `rg --sort path`, and decide whether cached test output is acceptable or `-count=1` is required.
|
||||
- [ ] **Derive routing signals once** — treat each completed in-memory PLAN as the worker packet. From facts already collected, record `large_indivisible_context`, positive matched loop-risk names/count, and recovery signals. Do not reread files, prove unmatched signatures false, or aggregate parent/sibling risk for routing.
|
||||
|
||||
## Step 3 - Finalize Task Routing
|
||||
## Step 3 - Determine GXX Grade
|
||||
|
||||
This step is mandatory and must be the last semantic decision before routed filenames are fixed. Complete Step 2 and prepare the full plan structure in memory before starting it.
|
||||
GXX is an output of analysis, not an input. Determine lane and grade only after Step 2 is fully complete.
|
||||
|
||||
- [ ] **Freeze routing input and mode** — use the completed in-memory PLAN and existing analysis facts. Include closure, grade, `large_indivisible_context`, positive risk names/count, and recovery signals; exclude previous route fields. Use `first-pass` with no prior route, otherwise `isolated-reassessment`. Remove prior route fields in memory; do not create a sub-agent, packet document, or routing-only evidence pass.
|
||||
- [ ] **Run routing once** — fully execute `agent-ops/skills/common/finalize-task-routing/SKILL.md` for build/review. Do not duplicate its decision rules in this skill.
|
||||
- [ ] **Stop or accept** — `needs_evidence` may rerun only after collecting all named new evidence; `blocked` stops without task-file mutation. Accept `routed` only when finalizer identity, closure, base/final basis, signals, grade, lane, and filenames satisfy the routing skill.
|
||||
- [ ] **Freeze routed names** — use the returned basenames unchanged in Steps 4-6. If an input fact changes before write, invalidate both routes and perform this step once again on the changed input.
|
||||
- [ ] **Assess change scope** — count affected files, interface impact, call-site count, and the amount of source/test/review context that must stay loaded together.
|
||||
- [ ] **Check risk factors** — mark any that apply: behavior promised outside edited files, persisted-state rule, permission boundary, shared-state risk, irreversible behavior.
|
||||
- [ ] **Evaluate test confidence** — judge whether existing tests sufficiently verify the changed behavior.
|
||||
- [ ] **Decide lane** — apply `Routing rules` as a gate. Use `local` only when all local allowlist conditions are true; otherwise use `cloud`. Ignore previous loop lane.
|
||||
- [ ] **Decide GNN** — assign grade within the selected lane as scope, ambiguity, irreversibility, and blast radius increase. Grade is complexity-based, not model-name-based; both `local-G10` and `cloud-G01` are valid when lane evidence supports them. Do not increment GNN solely because a previous loop failed.
|
||||
|
||||
## Step 4 - Archive Existing Active Files
|
||||
|
||||
In `write` mode, complete this step before writing new active files. In `prepare-follow-up` mode, calculate the same counts and archive names but do not modify any repository file; code-review owns the later archive.
|
||||
Before writing new active files for the chosen active task directory:
|
||||
|
||||
- Validate that the task directory contains at most one active `PLAN-(local|cloud)-G(0[1-9]|10).md`, at most one active `CODE_REVIEW-(local|cloud)-G(0[1-9]|10).md`, and at most one `USER_REVIEW.md`. Reject ambiguous or malformed active names.
|
||||
- In `write` mode, ensure `.gitignore` has the Agent-Ops managed gitignore block before renaming any active file to `*.log` or creating local `agent-roadmap/current.md`. Prefer `source agent-ops/bin/ai-ignore.sh && agent_ops_ensure_gitignore_task_artifact_block .gitignore`; if the helper is unavailable, add or update a block containing `!agent-task/`, `!agent-task/**/`, `!agent-task/**/*.md`, `!agent-task/**/*.log`, and `agent-roadmap/current.md`. In `prepare-follow-up` mode, only inspect the block and return `gitignore_repair_needed: true|false`; code-review performs any repair after preparation.
|
||||
- Count existing `plan_*.log` as `current_plan_archive_number`. If an active plan exists, parse `current_build_lane` and `current_build_grade` from that active filename and set `current_plan_archive_name=plan_{current_build_lane}_{current_build_grade}_{current_plan_archive_number}.log`. Require that destination not to exist. In `write` mode rename that exact active file to the calculated name; in `prepare-follow-up` only return the name and number. Never use the newly routed build lane/grade to archive the old active plan.
|
||||
- Count existing `code_review_*.log` as `current_review_archive_number`. If an active review exists, parse `current_review_lane` and `current_review_grade` from that active filename and set `current_review_archive_name=code_review_{current_review_lane}_{current_review_grade}_{current_review_archive_number}.log`. Require that destination not to exist. In `write` mode rename that exact active file to the calculated name; in `prepare-follow-up` only return the name and number. Never use the newly routed review lane/grade to archive the old active review.
|
||||
- Count existing `user_review_*.log` as `current_user_review_archive_number`. If `USER_REVIEW.md` exists and the linked Milestone decision is resolved for replanning, set `current_user_review_archive_name=user_review_{current_user_review_archive_number}.log`; require that destination not to exist and rename it only in `write` mode.
|
||||
- Compute `post_archive_plan_log_count`, `post_archive_review_log_count`, and `post_archive_user_review_log_count` from the filesystem after actual archive in `write` mode, or from the predicted addition of each current active file in `prepare-follow-up` mode.
|
||||
- Ensure `.gitignore` has the Agent-Ops managed gitignore block before renaming any active file to `*.log` or creating local `agent-roadmap/current.md`. Prefer `source agent-ops/bin/ai-ignore.sh && agent_ops_ensure_gitignore_task_artifact_block .gitignore`; if the helper is unavailable, add or update a block containing `!agent-task/`, `!agent-task/**/`, `!agent-task/**/*.md`, `!agent-task/**/*.log`, and `agent-roadmap/current.md`.
|
||||
- Count existing `agent-task/{task_name}/plan_*.log`; call it `N`. If `PLAN-*-G??.md` exists in that same directory, rename `PLAN-{build_lane}-GNN.md` to `plan_{build_lane}_GNN_N.log`.
|
||||
- Count existing `agent-task/{task_name}/code_review_*.log`; call it `M`. If `CODE_REVIEW-*-G??.md` exists in that same directory, rename `CODE_REVIEW-{review_lane}-GNN.md` to `code_review_{review_lane}_GNN_M.log`.
|
||||
- Count existing `agent-task/{task_name}/user_review_*.log`; call it `U`. If `USER_REVIEW.md` exists in that same directory and the linked SDD/Milestone decision is resolved for replanning, rename `USER_REVIEW.md` to `user_review_U.log`.
|
||||
|
||||
Set `plan_number=post_archive_plan_log_count`. The new pair's future archive suffixes are `plan_log_number=post_archive_plan_log_count` and `review_log_number=post_archive_review_log_count`. These are intentionally different concepts from `current_plan_archive_number` and `current_review_archive_number`.
|
||||
The new plan number is the count of `plan_*.log` after archiving.
|
||||
|
||||
## Step 5 - Write Plan File
|
||||
|
||||
Render the complete plan in memory first. In `write` mode, write it to the routed plan basename. In `prepare-follow-up` mode, return the exact rendered body as `prepared_plan` and do not write it.
|
||||
|
||||
Header line must be exactly:
|
||||
|
||||
```markdown
|
||||
<!-- task={task_name} plan={plan_number} tag={TAG} -->
|
||||
<!-- task={task_name} plan={N} tag={TAG} -->
|
||||
```
|
||||
|
||||
Required sections:
|
||||
|
||||
- Title.
|
||||
- `For the Implementing Agent`: warn that filling implementation-owned `CODE_REVIEW-*-G??.md` sections is mandatory. Tell the implementer to run verification, fill actual notes/output, keep active files in place, and report ready for review; finalization is code-review-skill only. If blocked, the implementer records only exact blocker evidence, attempted commands/output, and resume conditions in implementation-owned evidence fields. It must not ask the user, call user-input tools, create control-plane stop files, classify the next state, archive logs, or write `complete.log`.
|
||||
- `Background`: 2-4 sentences explaining why the work is needed.
|
||||
- `Archive Evidence Snapshot`: include this section only when the plan resumes from `USER_REVIEW.md`, a prior archived review, or any archive evidence. Omit it for first-pass plans with no archive evidence. The section must contain only the archive facts needed to implement without rereading archive by default: prior task/archive paths, verdict, Required/Suggested/Nit summary, affected files, verification evidence, and any roadmap carryover. If exact prior context is still required, cite the specific archive file paths allowed to read; do not ask the implementer to search `agent-task/archive/**` broadly.
|
||||
- `이 파일을 읽는 구현 에이전트에게`: warn that filling implementation-owned `CODE_REVIEW-*-G??.md` sections is mandatory. Tell the implementer to run verification, fill actual notes/output, keep active files in place, and report ready for review; finalization is code-review-skill only. Also state that if implementation is blocked by a selected SDD decision or selected Milestone `구현 잠금 > 결정 필요` item, the implementer must fill the review stub's `사용자 리뷰 요청` section with exact linked evidence and stop for code-review; the implementer must not ask the user directly, present chat choices, call `request_user_input`, create `USER_REVIEW.md`, archive logs, or write `complete.log`. State that environment/secret/service blockers, generic scope changes, and evidence gaps a follow-up agent can close are not user-review requests by themselves.
|
||||
- `배경`: 2-4 sentences explaining why the work is needed.
|
||||
- `사용자 리뷰 요청 흐름`: state that only selected SDD decisions or selected Milestone lock decisions are recorded in the active review stub's `사용자 리뷰 요청` section, copied from `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`; direct user prompts during implementation are forbidden, and code-review owns validation plus the actual `USER_REVIEW.md` file write.
|
||||
- `Archive Evidence Snapshot`: include this section only when the plan resumes from `USER_REVIEW.md`, a prior archived review, or any archive evidence. Omit it for first-pass plans with no archive evidence. The section must contain only the archive facts needed to implement without rereading archive by default: prior task/archive paths, verdict, Required/Suggested/Nit summary, affected files, verification evidence, and any roadmap/spec carryover. If exact prior context is still required, cite the specific archive file paths allowed to read; do not ask the implementer to search `agent-task/archive/**` broadly.
|
||||
- `Roadmap Targets`: include this section only when the plan is intended to complete one or more existing Milestone 기능 Task ids. Omit the section entirely for non-roadmap work or Milestone-adjacent work that should not check a Task on PASS. Format exactly:
|
||||
|
||||
```markdown
|
||||
## Roadmap Targets
|
||||
|
||||
- Milestone: `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`
|
||||
- Milestone link: [Milestone 문서](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- Task ids:
|
||||
- `<task-id>`: <Task text or concise label>
|
||||
- Completion mode: check-on-pass
|
||||
```
|
||||
- `Analysis`: record the findings from Step 2 and the final routed output from Step 3. This section is the written output of the analysis — not a summary, but the actual findings that justify the plan's scope and decisions. Must include all of the following subsections:
|
||||
- `Files Read`: list every source and test file read during analysis, with path. List verification-context source files only when they were actually present and read.
|
||||
- `SDD Criteria`: for `SDD: 필요` Milestones, list the SDD path, status, targeted Acceptance Scenario ids, their Milestone Task ids, and the Evidence Map rows that drive the plan. State explicitly how those rows shaped the implementation checklist and final verification. If the selected Milestone has `SDD: 불필요`, state the recorded reason. If the work is not Milestone-linked, state "not applicable".
|
||||
- `Verification Context`: state whether a handoff was supplied, every source path actually read, concrete commands/criteria applied, preconditions, constraints, gaps, confidence, and repository-native fallback evidence. If required verification leaves the current checkout, include an `External Verification Preflight` record with runner, repo root/workdir, branch/HEAD/dirty state, source sync status, binary/artifact paths, required command help/version output, config path, runtime identity, ports/process state, external hosts, OS/arch assumptions, and the exact setup/sync/rebuild step or blocker derived from mismatches.
|
||||
- `Test Coverage Gaps`: list each behavior change and whether existing tests cover it; explicitly note gaps.
|
||||
- `Symbol References`: list renamed/removed symbols and every call site found, or state "none" if no symbols were changed.
|
||||
- `Split Judgment`: for one plan, name the indivisible invariant or compact boundary; for split plans, list each child's stable contract, PASS evidence, and dependency. For dependent subtask plans, include each predecessor index and whether it is satisfied by an active or archived `complete.log`, missing, or ambiguous.
|
||||
- `Scope Rationale`: state which files or areas were explicitly excluded from this change and why. This is the boundary justification — the implementing agent must not silently expand scope beyond what is recorded here.
|
||||
- `Final Routing`: record `evaluation_mode`, finalizer, both targets' closure/grade/route, `large_indivisible_context`, positive loop-risk names/count, recovery signals, capability-gap evidence, and canonical filenames. Do not include or compare a previous loop's lane/G.
|
||||
- `Implementation Checklist`: a top-level checklist the implementing agent must follow while coding. Include one item per implementation/verification unit; if the roadmap feature Task has `검증:`, keep that verification in the same checklist item instead of making a separate completion-criteria item. Include one item for whole-plan intermediate/final verification only when it is not already covered by the feature items. Make the last item exactly `- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.` Copy this checklist into the review stub's `Implementation Checklist` section with the same item text and order.
|
||||
- `Spec Targets`: include this section only when the selected Milestone has an approved SDD and the plan claims completion for SDD acceptance scenarios. Omit it entirely when there is no SDD target. Format exactly:
|
||||
|
||||
```markdown
|
||||
## Spec Targets
|
||||
|
||||
- SDD: `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`
|
||||
- Acceptance scenarios:
|
||||
- `<scenario-id>`: task=`<task-id>`; evidence=`<Required Evidence summary>`
|
||||
- Completion mode: spec-check-on-pass
|
||||
```
|
||||
- `분석 결과`: record the findings from Step 2 and Step 3. This section is the written output of the analysis — not a summary, but the actual findings that justify the plan's scope and decisions. Must include all of the following subsections:
|
||||
- `읽은 파일`: list every source, test, and agent-test rule/profile file read during analysis, with path.
|
||||
- `테스트 환경 규칙`: state the chosen `test_env`, whether `agent-test/<test_env>/rules.md` was present and read, every matched profile path read, the concrete rules/commands applied, any structural blank/skeleton or missing rules, any `<확인 필요>` values, and any fallback verification source. If agent-test is absent or unusable, explicitly say no agent-test rule was applied and whether `create-test` or `update-test` should later fill the gap.
|
||||
- `테스트 커버리지 공백`: list each behavior change and whether existing tests cover it; explicitly note gaps.
|
||||
- `심볼 참조`: list renamed/removed symbols and every call site found, or state "none" if no symbols were changed.
|
||||
- `분할 판단`: state that the split decision policy was evaluated before choosing plan files. For a single plan, explain why each relevant split gate does not apply and why single-plan coordination is safer than splitting. For multi-plan output, list the shared task group plus each sibling subtask directory and dependency relationship. For dependent subtask plans, include each predecessor index and whether it is satisfied by an active or archived `complete.log`, missing, or ambiguous.
|
||||
- `범위 결정 근거`: state which files or areas were explicitly excluded from this change and why. This is the boundary justification — the implementing agent must not silently expand scope beyond what is recorded here.
|
||||
- `빌드 등급`: state the decided lane and GNN grade with a one-line rationale.
|
||||
- `구현 체크리스트`: a top-level checklist the implementing agent must follow while coding. Include one item per implementation/verification unit; if the roadmap feature Task has `검증:`, keep that verification in the same checklist item instead of making a separate completion-criteria item. Include one item for whole-plan intermediate/final verification only when it is not already covered by the feature items, and make the final item exactly: `- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.` Copy this checklist into the review stub's `구현 체크리스트` section with the same item text and order.
|
||||
- One item per change: `### [TAG-1] Title`, `TAG-2`, etc.
|
||||
- `Modified Files Summary`: table mapping files to item ids.
|
||||
- `Final Verification`: runnable commands and expected outcome. Prefer commands from verified handoff facts when supplied; fill missing coverage from repository manifests, scripts, workflows, domain rules, and related tests, and record the source in `Analysis > Verification Context`. Commands must be exact and deterministic enough for the reviewer to rerun; use stable ordering for searches and state whether cached test output is acceptable. End this section with **"After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`."**
|
||||
- `수정 파일 요약`: table mapping files to item ids.
|
||||
- `최종 검증`: runnable commands and expected outcome. Prefer commands from the matched agent-test env/profile rules. If agent-test is missing, blank, skeleton, or lacks a matching command, use repository manifests/workflows as fallback and record that fallback in `분석 결과 > 테스트 환경 규칙`. Commands must be exact and deterministic enough for the reviewer to rerun; use stable ordering for searches and state whether cached test output is acceptable. The final line of this section must read exactly — **"모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다."**
|
||||
|
||||
Each plan item must include:
|
||||
|
||||
- `Problem`: concrete problem with file:line references.
|
||||
- `Solution`: exact approach and before/after code block for non-trivial changes.
|
||||
- `Modified Files and Checklist`: exhaustive file-level checklist.
|
||||
- `Test Strategy`: explicit write/skip decision. If writing tests, include path, test name, assertion goal, and fixtures. If skipping, justify.
|
||||
- `Verification`: runnable commands and expected result.
|
||||
- `문제`: concrete problem with file:line references.
|
||||
- `해결 방법`: exact approach and before/after code block for non-trivial changes.
|
||||
- `수정 파일 및 체크리스트`: exhaustive file-level checklist.
|
||||
- `테스트 작성`: explicit write/skip decision. If writing tests, include path, test name, assertion goal, and fixtures. If skipping, justify.
|
||||
- `중간 검증`: runnable commands and expected result.
|
||||
|
||||
Include `Dependencies and Execution Order` only when order matters.
|
||||
Include `의존 관계 및 구현 순서` only when order matters.
|
||||
|
||||
For split multi-plan work, the `{subtask_dir}` directory name is the runtime source of truth. If a plan has a `NN+PP[,QQ...]_...` subtask directory name, `Dependencies and Execution Order` (legacy: `의존 관계 및 구현 순서`) must echo the decoded predecessor subtask directories under the same task group that must produce `complete.log` before implementation starts, and it must not add dependencies that are absent from the directory name. If a predecessor already completed, cite the active or archived `complete.log` path that satisfies it.
|
||||
For split multi-plan work, the `{subtask_dir}` directory name is the runtime source of truth. If a plan has a `NN+PP[,QQ...]_...` subtask directory name, `의존 관계 및 구현 순서` must echo the decoded predecessor subtask directories under the same task group that must produce `complete.log` before implementation starts, and it must not add dependencies that are absent from the directory name. If a predecessor already completed, cite the active or archived `complete.log` path that satisfies it.
|
||||
|
||||
Quality rules:
|
||||
|
||||
|
|
@ -302,28 +294,158 @@ Test policy:
|
|||
Verification fidelity rules:
|
||||
|
||||
- Plan verification commands are a contract. The implementing agent must run them exactly as written.
|
||||
- If a command must be changed, the implementing agent must record the replacement command and reason in `Deviations from Plan` (legacy: `계획 대비 변경 사항`), then paste the replacement command's actual stdout/stderr.
|
||||
- If a command must be changed, the implementing agent must record the replacement command and reason in `계획 대비 변경 사항`, then paste the replacement command's actual stdout/stderr.
|
||||
- Before claiming a tool is unavailable, run and record `command -v <tool>` or the project-equivalent check.
|
||||
- Before a remote/field/external verification command assumes a checkout, binary, config, runtime identity, or listening port, the plan must include a preflight command that proves those assumptions or a setup command that makes them true.
|
||||
- Do not download, generate, or leave verification tools inside the repository. Temporary tools belong outside the repo, such as under `/tmp`, and must not become task artifacts.
|
||||
- For search commands whose output order may vary, specify deterministic options in the plan, for example `rg --sort path`.
|
||||
- `Verification Results` (legacy: `검증 결과`) must contain actual stdout/stderr, not summarized or reconstructed output. If output is too long, record the saved output file path and the exact command used to create it.
|
||||
- `검증 결과` must contain actual stdout/stderr, not summarized or reconstructed output. If output is too long, record the saved output file path and the exact command used to create it.
|
||||
- If mobile/UI verification has no progress for 2 minutes or times out, stop blind retries; collect focused stdout plus screenshot/window/UI-tree evidence when available, or record why capture is impossible.
|
||||
- If the plan's pass condition says all leftovers must be intentional exceptions, any `변경 필요` item forces FAIL until resolved or explicitly reclassified with evidence.
|
||||
- Decide in the plan whether Go test cache output is acceptable. If fresh execution matters, use `go test -count=1 ...`.
|
||||
|
||||
## Step 6 - Write Review Stub
|
||||
|
||||
Read `agent-ops/skills/common/plan/templates/review-stub-template.md` in full only after Step 3 returns `status: routed`.
|
||||
Replace every occurrence of each token below:
|
||||
Use the template below exactly. Fill `{…}` placeholders from the plan; everything else is fixed and must not be changed by the implementing agent.
|
||||
Copy `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` into the review stub's `사용자 리뷰 요청` section.
|
||||
|
||||
- Scalar tokens: `{date}`, `{task_group}`, `{task_name}`, `{plan_number}`, `{TAG}`, `{build_lane}`, `{build_grade}`, `{review_lane}`, `{review_grade}`, `{plan_log_number}`, `{review_log_number}`.
|
||||
- Plan-copy tokens: `{roadmap_targets_or_omit}`, `{archive_evidence_snapshot_or_omit}`, `{implementation_checklist}`, `{review_checkpoints}`.
|
||||
- Generated row/section tokens: `{implementation_completion_rows}` contains one row for every plan item, and `{verification_result_sections}` contains the fixed verification instructions plus every intermediate/final command from the plan.
|
||||
```markdown
|
||||
<!-- task={task_name} plan={N} tag={TAG} -->
|
||||
|
||||
Use the routed build/review grades independently. Remove optional plan-copy content by replacing its token with an empty string, not by leaving template instructions.
|
||||
In `write` mode, write the rendered stub to the routed review basename. In `prepare-follow-up` mode, return it as `prepared_review` without writing.
|
||||
Do not write or return a prepared pair when either routing target is not `routed`. After rendering, scan for the exact template-token inventory above and reject the output if any known token remains; do not reject unrelated braces in copied commands or code.
|
||||
# Code Review Reference - {TAG}
|
||||
|
||||
> **[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 selected SDD decision or selected Milestone `구현 잠금 > 결정 필요` item, fill `사용자 리뷰 요청` with linked evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Environment/secret/service blockers, generic scope changes, repeated failures, and evidence gaps that a follow-up agent can close 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 only SDD/Milestone lock decisions 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={YYYY-MM-DD}
|
||||
task={task_name}, plan={N}, tag={TAG}
|
||||
|
||||
{copy the plan's Roadmap Targets section exactly if present; omit this block if the plan has no Roadmap Targets}
|
||||
{copy the plan's Spec Targets section exactly if present; omit this block if the plan has no Spec Targets}
|
||||
{copy the plan's Archive Evidence Snapshot section exactly if present; omit this block if the plan has no Archive Evidence Snapshot}
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[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`가 연결된 SDD/Milestone 결정으로 완료/PASS 해소되면 code-review가 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log` 작성 후 archive 이동한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [{TAG}-1] {item description} | [ ] |
|
||||
| [{TAG}-2] {item description} | [ ] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
{copy the plan's 구현 체크리스트 items exactly, preserving order and checkbox text}
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[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하는지 확인한다.
|
||||
- [ ] 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`를 작성하지 않는다.
|
||||
- [ ] 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가 연결된 SDD/Milestone 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 새 결정이 필요해 보여도 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 이 섹션은 선택된 SDD 결정 또는 선택된 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 차단할 때만 채운다. 외부 환경/secret/서비스 준비, 검증 증거 공백, 반복 실패, 일반 범위 조정은 사용자 리뷰 요청이 아니며 `검증 결과`, `계획 대비 변경 사항`, 또는 code-review의 일반 follow-up plan으로 처리한다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 연결 대상: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
{pre-filled from plan — one bullet per review focus area}
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
|
||||
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.
|
||||
|
||||
### {TAG}-1 중간 검증
|
||||
```
|
||||
$ {verification command from plan}
|
||||
(output)
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```
|
||||
$ {final verification command from plan}
|
||||
(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.
|
||||
```
|
||||
|
||||
Sections and their ownership:
|
||||
|
||||
| Section | Owner | Note |
|
||||
|---------|-------|------|
|
||||
| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) |
|
||||
| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS |
|
||||
| Spec Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Spec Completion` only on PASS |
|
||||
| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required |
|
||||
| 구현 항목별 완료 여부 (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only |
|
||||
| 구현 체크리스트 (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only; final checkbox is mandatory before saving |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | Replace placeholder text with actual content |
|
||||
| 사용자 리뷰 요청 | Implementing agent | Keep `상태: 없음` unless a selected SDD decision or selected Milestone `구현 잠금 > 결정 필요` item blocks implementation; do not ask the user directly during implementation; environment/secret/service blockers, generic scope changes, and evidence gaps are not user-review requests |
|
||||
| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Pre-filled from plan |
|
||||
| 검증 결과 (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `계획 대비 변경 사항` entry |
|
||||
| 코드리뷰 결과 | Review agent appends | Not included in stub |
|
||||
|
||||
## Naming
|
||||
|
||||
|
|
@ -336,27 +458,24 @@ Do not write or return a prepared pair when either routing target is not `routed
|
|||
|
||||
## Final Checklist
|
||||
|
||||
- In `write` mode, the routed `PLAN-{build_lane}-GNN.md` and `CODE_REVIEW-{review_lane}-GNN.md` both exist under `agent-task/{task_name}/`. In `prepare-follow-up` mode, neither routed file was written; both exact bodies and basenames were returned while the verdict-appended current pair remained active.
|
||||
- In `write` mode, `.gitignore` has the Agent-Ops managed block that unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores local `agent-roadmap/current.md`. In `prepare-follow-up` mode, the block was only inspected and any needed repair was returned as `gitignore_repair_needed`.
|
||||
- `PLAN-{build_lane}-GNN.md` and `CODE_REVIEW-{review_lane}-GNN.md` both exist under the active task directory `agent-task/{task_name}/`.
|
||||
- `.gitignore` has the Agent-Ops managed gitignore block that unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores local `agent-roadmap/current.md`, so active files and archived `*.log` task artifacts are trackable even when the project ignores `*.log`.
|
||||
- Single-plan work stores active files directly under `agent-task/{task_group}/`.
|
||||
- Split work, if any, uses one shared `agent-task/{task_group}/` parent and one subtask directory per plan/review pair with names like `01_core`, `02+01_edge_integration`, `03+01_node_integration`; dependency details live in the subtask directory name as `NN+PP[,QQ...]_subtask_name`.
|
||||
- Split sibling indices follow topological dependency order: every predecessor is lower than its consumer, and every gap is explained by an unchanged existing predecessor or an occupied active/archive index.
|
||||
- Milestone-linked work uses `agent-task/m-<milestone-slug>/` as the task group; non-roadmap task groups do not start with `m-`.
|
||||
- Both first lines match `<!-- task={task_name} plan={plan_number} tag={TAG} -->`.
|
||||
- The review stub was rendered from `agent-ops/skills/common/plan/templates/review-stub-template.md` after routing and has no unresolved known template token.
|
||||
- In `write` mode, previous active files, if any, were archived with lane/grade parsed from their own basenames and the correct current archive suffixes. In `prepare-follow-up` mode, those archive names were only predicted.
|
||||
- In `write` mode when resuming from `USER_REVIEW.md`, it was archived to the calculated `current_user_review_archive_name` and the resolved linked Milestone decision was recorded in the new plan.
|
||||
- Both first lines match `<!-- task={task_name} plan={N} tag={TAG} -->`.
|
||||
- Previous active files, if any, were archived with correct numeric suffixes.
|
||||
- If resuming from `USER_REVIEW.md`, it was archived to `user_review_N.log` and the resolved linked SDD/Milestone decision was recorded in the new plan.
|
||||
- `Roadmap Targets` exists only when PASS should check explicit Milestone Task ids, the task group is `m-<milestone-slug>` for the listed Milestone path, and every listed Task id exists in the selected active Milestone.
|
||||
- If `Roadmap Targets` exists in the plan, the review stub contains the identical section. If it does not exist in the plan, the review stub omits it too.
|
||||
- If the selected Milestone has `SDD: 필요`, the plan's `Analysis > SDD Criteria` (legacy: `분석 결과 > SDD 기준`) proves that the implementation checklist and final verification were derived from the approved SDD Acceptance Scenarios and Evidence Map. Missing SDD mapping blocks plan creation.
|
||||
- If the selected Milestone has `SDD: 필요`, the SDD gate was checked before writing files. Missing or incomplete SDD was first routed through the `roadmap-sdd` pre-plan flow; active `USER_REVIEW.md`, non-approved SDD, or locked SDD blocks plan creation.
|
||||
- `Spec Targets` exists only when the selected SDD is approved and the plan claims completion for explicit Acceptance Scenario ids. If `Spec Targets` exists in the plan, the review stub contains the identical section.
|
||||
- If the plan is a follow-up or resumes from prior archive evidence, it has `Archive Evidence Snapshot` and the review stub contains the identical section.
|
||||
- `Analysis > Verification Context` records supplied handoff facts, source paths actually read, external preflight, gaps, confidence, and repository-native fallback evidence.
|
||||
- `분석 결과 > 테스트 환경 규칙` records the selected test env, env rules read/missing/structural-blank state, matched profiles read, and any fallback verification source.
|
||||
- Dependent split plans record predecessor completion using active sibling `complete.log` or matching archived `complete.log`; ambiguous archive matches are not guessed.
|
||||
- Every plan item has problem, solution, checklist, test decision, and intermediate verification.
|
||||
- The plan and review stub have matching `Implementation Checklist` (legacy: `구현 체크리스트`) item text/order; their final checkbox is the mandatory `CODE_REVIEW-*-G??.md` evidence item.
|
||||
- `finalize-task-routing` ran once after the PLAN body was complete, used no routing-only evidence pass, counted only positive packet-local risk, kept capability/grade basis from being relabeled by escalation signals, and produced matching filenames.
|
||||
- Review WARN/FAIL follow-ups entered through this plan skill and did not inherit or compare the archived lane/G.
|
||||
- The plan's implementer instructions and review stub limit local implementation agents to implementation/test/evidence work and keep user-review classification plus control-plane stop files out of their input and ownership.
|
||||
- The review stub has a clearly marked `Review-Only Checklist` (legacy: `코드리뷰 전용 체크리스트`) owned only by the review agent.
|
||||
- The plan and review stub have matching `구현 체크리스트` item text/order, and the final checkbox is the mandatory `CODE_REVIEW-*-G??.md` completion item.
|
||||
- The plan's implementer instructions and review stub both forbid direct user prompts during implementation and explain the implementation-time `사용자 리뷰 요청` stop path.
|
||||
- The review stub includes the `사용자 리뷰 요청` section from `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`.
|
||||
- The review stub has a clearly marked `코드리뷰 전용 체크리스트` owned only by the review agent.
|
||||
- Routed review file completion table lists every plan item.
|
||||
- In `prepare-follow-up`, no repository file was mutated and the returned prepared basenames/bodies, `plan_number`, current archive names/numbers, post-archive log counts, and `gitignore_repair_needed` are complete; in `write`, prior active state was archived with its own parsed route and both new active files were written.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
interface:
|
||||
display_name: "Plan"
|
||||
short_description: "Write implementation plans"
|
||||
default_prompt: "Use $plan to analyze this repository change, collect current routing evidence, run $finalize-task-routing with local-first capability-gap policy, and create the routed PLAN/CODE_REVIEW pair."
|
||||
default_prompt: "Use $plan to create grouped PLAN/CODE_REVIEW task files for this repository change."
|
||||
|
|
|
|||
|
|
@ -1,98 +0,0 @@
|
|||
<!-- task={task_name} plan={plan_number} tag={TAG} -->
|
||||
|
||||
# Code Review Reference - {TAG}
|
||||
|
||||
> **[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 `Implementation Checklist`; 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, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields.
|
||||
> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state.
|
||||
> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume.
|
||||
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||
|
||||
## Overview
|
||||
|
||||
date={date}
|
||||
task={task_name}, plan={plan_number}, tag={TAG}
|
||||
|
||||
{roadmap_targets_or_omit}
|
||||
{archive_evidence_snapshot_or_omit}
|
||||
|
||||
## For the Review Agent
|
||||
|
||||
> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section.
|
||||
|
||||
Compare implementation of each item against source files and verify that output in `Verification Results` matches code.
|
||||
Review completion means the following steps are finished:
|
||||
|
||||
1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals.
|
||||
2. Archive `CODE_REVIEW-{review_lane}-{review_grade}.md` → `code_review_{review_lane}_{review_grade}_{review_log_number}.log` and `PLAN-{build_lane}-{build_grade}.md` → `plan_{build_lane}_{build_grade}_{plan_log_number}.log`.
|
||||
3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/{task_name}/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill.
|
||||
4. If PASS and task group is `m-<milestone-slug>`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities.
|
||||
5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Item Completion
|
||||
|
||||
| Item | Status |
|
||||
|------|---------|
|
||||
{implementation_completion_rows}
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
{implementation_checklist}
|
||||
|
||||
## Review-Only Checklist
|
||||
|
||||
> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent.
|
||||
> Implementing agents must not modify or check this section.
|
||||
|
||||
- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`.
|
||||
- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match.
|
||||
- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_{review_lane}_{review_grade}_{review_log_number}.log`.
|
||||
- [ ] Archive active `PLAN-*-G??.md` to `plan_{build_lane}_{build_grade}_{plan_log_number}.log`.
|
||||
- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`.
|
||||
- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files.
|
||||
- [ ] If PASS, move active task directory `agent-task/{task_name}/` to `agent-task/archive/YYYY/MM/{task_name}/` and update this checklist at the final archive path.
|
||||
- [ ] If PASS and task group is `m-<milestone-slug>`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`.
|
||||
- [ ] If PASS for split work, remove empty active parent `agent-task/{task_group}/` or verify it was kept due to remaining siblings/files.
|
||||
- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
_Record any deviations from the plan and the rationale here._
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
_Record key design decisions here._
|
||||
|
||||
## Reviewer Checkpoints
|
||||
|
||||
{review_checkpoints}
|
||||
|
||||
## Verification Results
|
||||
|
||||
{verification_result_sections}
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
## Section Ownership
|
||||
|
||||
| Section | Owner | Note |
|
||||
|---------|-------|------|
|
||||
| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) |
|
||||
| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS |
|
||||
| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required |
|
||||
| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only |
|
||||
| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only |
|
||||
| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section |
|
||||
| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content |
|
||||
| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan |
|
||||
| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry |
|
||||
| Code Review Result | Review agent appends | Not included in stub |
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
---
|
||||
name: refine-local-plans
|
||||
description: 현재 plan들 세분화해, 현재 plan 세분화, 기존 plan 더 나눠, local plan 분리해 같은 요청에서 이미 생성된 미착수 PLAN-local-G??/CODE_REVIEW pair를 최대 3개의 작은 local sibling pair로 나누고 같은 task group의 미착수 index를 의존성 순서로 함께 정렬할 때 사용한다.
|
||||
---
|
||||
|
||||
# Refine Local Plans
|
||||
|
||||
## 목표
|
||||
|
||||
이미 생성된 미착수 local pair를 로컬 모델이 수행하기 쉬운 응집된 단위로 이번 실행에서 한 단계만 나눈다. Source/test를 다시 조사하거나 검증을 실행하지 않는다.
|
||||
|
||||
## 대상
|
||||
|
||||
- 사용자가 지정한 active task group, task path, 또는 `PLAN-local-G??.md`를 사용한다. 대상을 생략하면 미착수 local pair가 있는 task group이 정확히 하나일 때만 진행한다.
|
||||
- `PLAN-local-G??.md`와 matching `CODE_REVIEW-*-G??.md`가 모두 있고 verdict가 없어야 한다.
|
||||
- Review의 구현 완료표·구현 체크리스트가 모두 미체크이고, 구현 소유 기록과 검증 출력이 아직 채워지지 않은 pair만 미착수로 본다.
|
||||
- `complete.log` 또는 `USER_REVIEW.md`가 있거나 구현이 시작된 pair는 수정하지 않는다.
|
||||
- 대상 pair, 같은 task group의 미착수 active sibling pair, active directory basename과 archived sibling directory basename만 읽는다. Archive 내부 파일은 읽지 않는다. 새 구현 조사를 위해 source/test/roadmap/archive 본문을 읽지 않는다.
|
||||
|
||||
## 절차
|
||||
|
||||
1. **범위를 고정한다**
|
||||
- 기존 PLAN의 checklist, plan item, 수정 파일, 검증 명령을 원본 범위로 고정한다.
|
||||
- Plan에 없는 구현 범위나 검증을 추가하지 않는다.
|
||||
|
||||
2. **유지 또는 분리를 결정한다**
|
||||
- 서로 독립적으로 구현·검증 가능한 behavior slice가 정확히 2개 또는 3개일 때만 나눈다.
|
||||
- 각 child는 하나의 응집된 결과와 필요한 production 변경을 가진다.
|
||||
- Production 변경의 PASS에 필요한 기존 PLAN의 테스트는 같은 child에 둔다. 추가 통합/closure 검증만 별도 test child가 될 수 있다.
|
||||
- 경계가 불명확하거나 공유 write set·상태·순서 때문에 coordination이 커지면 원본을 유지한다.
|
||||
- 원본 유지로 결정하면 파일을 바꾸지 않고 결과만 보고한다.
|
||||
- 이번 실행에서 만든 child를 다시 분할하지 않는다.
|
||||
|
||||
3. **경로와 dependency를 정한다**
|
||||
- 이름은 `NN_{subtask_name}` 또는 `NN+PP[,QQ...]_{subtask_name}`만 사용하며 모든 predecessor는 `NN`보다 작아야 한다.
|
||||
- Target children과 같은 task group의 active sibling으로 DAG를 만든다. 시작·완료 sibling은 고정 anchor로 두고, 나머지는 producer가 consumer보다 먼저 오도록 topological sort한다.
|
||||
- 같은 단계에서는 기존 sibling의 index와 새 child의 원본 PLAN item 순서를 유지하고 basename으로 마지막 tie를 정한다.
|
||||
- 검사 시작 시 구현이 시작됐거나 `complete.log`, `USER_REVIEW.md`, 기존 `*.log`가 있는 sibling의 `NN`은 고정한다. Archived sibling의 `NN`도 예약된 번호로 취급한다.
|
||||
- 나머지 node에는 모든 predecessor보다 크면서 충돌하지 않는 가장 낮은 두 자리 index를 topological 순서대로 배정한다. 고정 predecessor 이하이거나 예약된 번호만 건너뛴다.
|
||||
- Reindex 후 각 basename의 predecessor를 새 index로 치환하고 오름차순으로 기록한다. 독립 node는 `NN_`, dependent node는 `NN+PP[,QQ...]_`를 사용한다.
|
||||
- 기존 dependent의 원래 predecessor를 실제 소비하는 child로 바꾼다. 전체 결과를 필요로 하면 마지막 closure child를 사용하고, 소비 child를 판단할 수 없으면 분리하지 않는다.
|
||||
- 고정 index 때문에 dependency 순서를 만들 수 없거나 cycle, `99` 초과, 시작된 sibling 이동이 필요하면 분리하지 않는다.
|
||||
- 예: 미착수 `01_core`, `03+01_api`, `04+01,03_integration`은 `01_core`, `02+01_api`, `03+01,02_integration`으로 정렬한다. 기존 `03`이 시작된 상태면 `03`은 이동하지 않는다.
|
||||
- Reindex되는 sibling은 directory basename과 PLAN/review 안의 기존 task path·index·dependency 참조를 새 값으로 바꾼다. 구현 scope, checklist, 검증, routing은 바꾸지 않는다.
|
||||
|
||||
4. **현재 PLAN/CODE_REVIEW 형식을 유지한다**
|
||||
- 각 child는 기존 PLAN을 복제한 뒤 자신의 scope만 남긴다. Header/task, title, background, `구현 체크리스트`, plan item, `수정 파일 요약`, `최종 검증`을 child 경계에 맞게 갱신한다. 기존 PLAN에 `분석 결과`가 있으면 읽은 파일·테스트 공백·심볼 참조·분할 판단·범위 결정 근거도 child 범위로 줄인다.
|
||||
- `Roadmap Targets`는 전체 결과를 닫는 closure child 하나에만 둔다.
|
||||
- 각 review는 기존 CODE_REVIEW를 복제한 뒤 header/task, 완료표, 구현 checklist, checkpoint, 검증 section을 matching PLAN과 맞춘다. 고정 안내와 review 전용 section의 문구는 유지하되 child task path와 future archive suffix 참조는 갱신한다.
|
||||
- PLAN과 review는 입력에 이미 있는 section 구조를 유지하며 없는 section을 새로 만들지 않는다. 첫 task header 외의 HTML metadata comment는 출력에서 제거한다.
|
||||
- PLAN과 review의 첫 줄은 동일한 `task`, `plan`, `tag`를 사용한다. Checklist 문구·순서와 검증 명령을 서로 일치시킨다.
|
||||
- 기존 build/review lane, G, canonical basename과 `최종 라우팅` 값을 child에 그대로 유지한다. Strict-subset local refinement에서는 `finalize-task-routing`을 다시 실행하지 않는다.
|
||||
|
||||
5. **최종 pair로 직접 교체한다**
|
||||
- 모든 child pair, sibling reindex, directory rename map을 먼저 메모리에서 완성하고 최종 경로·archive log 충돌을 확인한다.
|
||||
- 원본 active review와 PLAN을 각 파일 basename의 lane/G와 다음 monotonic suffix를 사용해 같은 task directory의 `code_review_*.log`, `plan_*.log`로 archive한다.
|
||||
- Reindex가 필요한 미착수 directory는 목적지가 비는 순서로 최종 basename으로 이동한다. 임시 directory나 별도 상태 파일이 필요한 충돌이면 분리하지 않는다.
|
||||
- Indexed target은 첫 child가 최종 basename으로 재사용한다. Task-group root의 single-plan target은 원본 log를 root에 남기고 모든 child directory를 새로 만든다.
|
||||
- 재사용 directory의 `plan` 번호와 future archive suffix는 원본 pair archive 후 log count를 사용한다. 새 child directory는 기존 log가 없으면 `0`을 사용한다.
|
||||
- Child PLAN/CODE_REVIEW를 최종 routed basename에 직접 쓴다. 임시 상태나 복구용 Markdown을 만들지 않는다.
|
||||
- 기존 파일이나 log를 덮어쓰지 않는다. 모든 최종 pair의 header, checklist, 검증 명령과 `predecessor NN < consumer NN`을 확인한다.
|
||||
|
||||
6. **Readiness를 보고한다**
|
||||
- 각 child directory의 encoded predecessor만 확인한다.
|
||||
- 모두 충족되면 `implementation-ready`, 하나라도 미충족이면 `dependency-waiting`으로 보고한다.
|
||||
- Worker, Review, 다음 sibling을 시작하지 않는다.
|
||||
|
||||
## 출력
|
||||
|
||||
```text
|
||||
Local plan refinement
|
||||
- targets: <원본 PLAN 경로>
|
||||
- decisions: <유지 | 원본 -> child 목록>
|
||||
- dependency updates: <변경 내용 또는 없음>
|
||||
- readiness: <pair path = implementation-ready | dependency-waiting>
|
||||
- document check: passed
|
||||
```
|
||||
|
||||
## 금지
|
||||
|
||||
- Source/test 재분석, compile, build, test, lint, formatter, smoke/E2E, live/remote 검증을 실행하지 않는다.
|
||||
- Package 설치, dependency 다운로드, cache warming을 하지 않는다.
|
||||
- Child 재귀 분리, cloud pair 분리, 다른 task group 또는 시작·완료 sibling 재인덱싱을 하지 않는다.
|
||||
- 별도 상태 파일, 임시 pair, repository 밖 복구 파일을 만들지 않는다.
|
||||
|
|
@ -9,8 +9,7 @@ description: 로드맵 Milestone에 녹아 있는 SDD 설계 게이트를 판정
|
|||
## 목적
|
||||
|
||||
큰 Milestone에서 로드맵만으로 부족한 계약, 상태 전이, 수용 시나리오, 검증 근거를 `agent-roadmap/sdd/` 아래에 기록한다.
|
||||
SDD는 로드맵과 분리된 별도 운영물이 아니라 Milestone `구현 잠금`을 해제하고, 이후 Milestone 구현 계획이 따라야 할 설계 입력을 고정하는 하위 설계 게이트다.
|
||||
`SDD: 필요` Milestone의 구현 계획은 승인된 SDD의 Acceptance Scenario와 Evidence Map에서 구현 범위, 검증, 완료 evidence를 역산해야 한다.
|
||||
SDD는 로드맵과 분리된 별도 운영물이 아니라 Milestone `구현 잠금`을 해제하기 위한 하위 설계 게이트다.
|
||||
|
||||
## 모드
|
||||
|
||||
|
|
@ -51,12 +50,8 @@ agent-roadmap/
|
|||
- `Source of Truth`, `State Machine`, `Acceptance Scenarios`, `Evidence Map` 표는 템플릿의 컬럼을 유지한다.
|
||||
- 값이 아직 없으면 섹션을 삭제하지 말고 `없음`, `확인 필요`, 또는 잠금 항목으로 남긴다.
|
||||
- `update`는 기존 SDD의 내용을 갱신하더라도 표준 섹션과 순서를 유지한다. 누락된 표준 섹션이 있으면 먼저 복원한 뒤 변경을 반영한다.
|
||||
- `check-gate`는 표준 섹션이나 필수 표 컬럼이 누락된 SDD를 `invalid`로 보고하고, Milestone 구현 잠금 해제 대상으로 보지 않는다.
|
||||
- `check-gate`는 표준 섹션이나 필수 표 컬럼이 누락된 SDD를 `invalid`로 보고하고, plan gate 통과 대상으로 보지 않는다.
|
||||
- SDD별 추가 설명은 `작업 컨텍스트` 또는 해당 표준 섹션 안에 넣고 임의 top-level 섹션을 늘리지 않는다.
|
||||
- SDD 안에서 Milestone, Phase, 계약 문서, `USER_REVIEW.md`, 후속 SDD 같은 문서 포인터를 남길 때는 raw path만 쓰지 말고 `[표시 제목](상대경로)` Markdown 링크로 쓴다.
|
||||
- SDD 링크 target은 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/` 디렉터리 기준 상대경로로 쓴다. 예: `[Milestone 문서](../../../phase/<phase-slug>/milestones/<milestone-slug>.md)`, `[PHASE.md](../../../phase/<phase-slug>/PHASE.md)`, `[USER_REVIEW.md](USER_REVIEW.md)`.
|
||||
- 실제 생성/갱신한 SDD에는 `<phase-slug>`, `<milestone-slug>`, `<path>` 같은 placeholder가 들어간 링크 target을 남기지 않는다. 템플릿 placeholder는 실제 파일 위치 기준 상대경로 또는 `없음`으로 치환한다.
|
||||
- 코드 source path나 machine-readable identity는 raw 값이 필요하면 유지할 수 있다.
|
||||
|
||||
## SDD 대상 판정
|
||||
|
||||
|
|
@ -84,12 +79,12 @@ SDD가 필요한 Milestone은 `구현 잠금`에 아래 필드를 둔다.
|
|||
```md
|
||||
- 상태: 잠금
|
||||
- SDD: 필요
|
||||
- SDD 문서: [SDD.md](../../../sdd/<phase-slug>/<milestone-slug>/SDD.md)
|
||||
- SDD 문서: `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`
|
||||
- 잠금 해제 조건:
|
||||
- [ ] SDD 잠금이 해제되어 있다
|
||||
- [ ] SDD 사용자 리뷰가 없거나 승인/해결되었다
|
||||
- [ ] Acceptance Scenario가 Milestone 기능 Task와 연결되어 있다
|
||||
- [ ] Evidence Map이 완료 시 `Roadmap Completion`과 최종 검증 evidence로 검증 가능하게 연결되어 있다
|
||||
- [ ] Evidence Map이 plan의 `Spec Targets`와 완료 시 `Spec Completion`으로 검증 가능하게 연결되어 있다
|
||||
- 결정 필요: 없음
|
||||
```
|
||||
|
||||
|
|
@ -104,7 +99,7 @@ SDD가 불필요한 Milestone은 사유를 남긴다.
|
|||
|
||||
SDD 문서는 자체 잠금을 가진다.
|
||||
|
||||
- `SDD 잠금: 잠금`이면 Milestone `구현 잠금` 해제 대상이 아니다.
|
||||
- `SDD 잠금: 잠금`이면 `plan`은 구현 계획을 만들지 않는다.
|
||||
- `USER_REVIEW.md`가 존재하면 사용자 답변 전까지 SDD 잠금을 해제하지 않는다.
|
||||
- 사용자 결정이 필요 없는 기술 세부는 agent가 코드, 규칙, 기존 계약을 근거로 채우고 잠금 항목으로 만들지 않는다.
|
||||
- 모든 잠금 항목이 해결되고 사용자 리뷰가 없으면 SDD 상태를 `[승인됨]`, SDD 잠금을 `해제`로 둔다.
|
||||
|
|
@ -135,8 +130,7 @@ SDD 문서는 자체 잠금을 가진다.
|
|||
1. 관련 Milestone 또는 신규 작업 설명을 읽는다.
|
||||
2. SDD 대상 판정 기준을 적용한다.
|
||||
3. 결과를 `필요`, `불필요`, `불명확` 중 하나로 보고한다.
|
||||
4. `필요`이면 Milestone `구현 잠금`에 해당 Milestone 파일 위치 기준 `SDD 문서` Markdown 링크와 잠금 해제 조건을 갱신한다.
|
||||
5. 신규 Milestone 생성 또는 `[스케치] -> [계획]` 승격 흐름에서 호출된 경우, `classify`에서 멈추지 않고 같은 턴에 `create`까지 이어간다. 사용자만 결정할 항목이 없으면 승인 가능한 SDD로 만들고, 사용자 결정이 있으면 SDD 초안과 `USER_REVIEW.md`를 함께 만든다.
|
||||
4. `필요`이면 Milestone `구현 잠금`에 SDD 경로와 잠금 해제 조건을 남기도록 안내하거나 갱신한다.
|
||||
|
||||
### create
|
||||
|
||||
|
|
@ -145,7 +139,6 @@ SDD 문서는 자체 잠금을 가진다.
|
|||
3. 필요하면 `agent-contract/index.md`를 읽고 매칭 계약 원문을 링크한다. 계약 본문을 SDD에 복제하지 않는다.
|
||||
4. 표준 템플릿의 top-level 섹션, 섹션 순서, 필수 표 컬럼을 유지해 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`를 만든다.
|
||||
5. 사용자 결정이 필요한 항목이 있으면 `review-ready`를 수행한다. 없으면 SDD 상태를 `[승인됨]`, SDD 잠금을 `해제`로 둘 수 있다.
|
||||
6. SDD가 `[승인됨]`이고 SDD 잠금이 `해제`이며 `USER_REVIEW.md`가 없으면 같은 흐름의 `update-roadmap` 갱신에서 Milestone `구현 잠금` 해제 후보로 반영한다.
|
||||
|
||||
### update
|
||||
|
||||
|
|
@ -164,7 +157,7 @@ SDD 문서는 자체 잠금을 가진다.
|
|||
5. SDD 상태가 `[승인됨]`이 아니거나 `SDD 잠금`이 `잠금`이면 `blocked`로 보고한다.
|
||||
6. `USER_REVIEW.md`가 있으면 `blocked`로 보고한다.
|
||||
7. Acceptance Scenario가 Milestone 기능 Task id와 연결되어 있는지 확인한다.
|
||||
8. Evidence Map이 완료 시 `Roadmap Completion`과 최종 검증 evidence로 검증될 수 있도록 scenario, task, evidence가 매핑되어 있는지 확인한다.
|
||||
8. Evidence Map이 plan의 `Spec Targets`에 고정되고 완료 시 `Spec Completion`으로 검증될 수 있도록 scenario, task, evidence가 매핑되어 있는지 확인한다.
|
||||
9. 모두 충족하면 `pass`로 보고한다.
|
||||
|
||||
### review-ready
|
||||
|
|
@ -196,11 +189,11 @@ SDD 문서는 자체 잠금을 가진다.
|
|||
## SDD 결과
|
||||
|
||||
- mode: `<classify|create|update|check-gate|review-ready|resolve-review|archive>`
|
||||
- milestone: <[Milestone 문서](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md) | 해당 없음>
|
||||
- sdd: <[SDD.md](agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md) | 없음>
|
||||
- milestone: `<path>`
|
||||
- sdd: `<path | 없음>`
|
||||
- 결과: `<pass | blocked | not-required | created | updated | review-required | archived | invalid>`
|
||||
- 잠금: `<해제 | 잠금 | 해당 없음>`
|
||||
- 사용자 리뷰: <없음 | [USER_REVIEW.md](agent-roadmap/sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md) | [user_review_N.log](agent-roadmap/sdd/<phase-slug>/<milestone-slug>/user_review_N.log)>
|
||||
- 사용자 리뷰: `<없음 | USER_REVIEW.md | user_review_N.log>`
|
||||
- 다음 단계: `<없음 | 사용자 리뷰 필요 | Milestone 구현 잠금 해제 가능 | SDD 작성 필요>`
|
||||
```
|
||||
|
||||
|
|
@ -210,4 +203,4 @@ SDD 문서는 자체 잠금을 가진다.
|
|||
- 사용자 결정이 필요한 항목을 chat 질문으로 바로 던지지 않는다. `USER_REVIEW.md`로 남긴다.
|
||||
- 작은 작업에 SDD를 강제하지 않는다.
|
||||
- `USER_REVIEW.md`가 남아 있는데 SDD 상태를 `[승인됨]`으로 두지 않는다.
|
||||
- SDD gate가 막힌 Milestone의 구현 잠금을 해제하지 않는다.
|
||||
- SDD gate가 막힌 Milestone에 대해 구현 plan을 만들지 않는다.
|
||||
|
|
|
|||
|
|
@ -2,60 +2,28 @@
|
|||
|
||||
라우팅 우선순위:
|
||||
|
||||
- project skill 경로를 선택한 뒤 같은 이름의 `agent-ops/skills/private/<skill-name>/SKILL.md`가 있으면 private skill을 우선한다. 없으면 선택한 project skill을 사용한다.
|
||||
- project skill과 짝이 없는 private skill은 `agent-ops/rules/private/rules.md`에 명시적으로 라우팅한다. private skill 전체를 탐색하지 않는다.
|
||||
- SDD/spec gate 자체의 작성, 갱신, gate 확인, 사용자 리뷰, 잠금 해제는 `roadmap-sdd`로 보낸다.
|
||||
- 로드맵/마일스톤 생성 또는 갱신 요청 안에 SDD 필요 여부와 gate 연결이 포함되면 `create-roadmap` 또는 `update-roadmap`을 진입점으로 삼고, 해당 흐름에서 `roadmap-sdd` create/check를 처리한다.
|
||||
- agent-spec은 구현 후 현재 상태를 설명하는 living spec이다. SDD/spec gate와 구분하며, 현재 구현 스펙 생성은 `create-spec`, 갱신은 `update-spec`으로 보낸다.
|
||||
- "마일스톤 완료해도 될지 검토", "현 마일스톤 종료 검토", "현재 마일스톤 닫고 다음 마일스톤 지정"처럼 종료 판단, spec sync, roadmap archive, 다음 Milestone 지정을 함께 요구하는 요청은 `complete-milestone`으로 보낸다. 이 흐름 안에서 `update-spec`을 필수 gate로 수행한다. 사용할 테스트 환경 규칙이 있으면 먼저 `update-test mode=resolve-context`의 중립 `Verification Context`를 전달하고, 없거나 불완전하면 complete-milestone의 repository-native fallback을 사용한다.
|
||||
- 구현 계획 요청에서 선택 Milestone의 구현 잠금이 남아 있으면 `plan`은 구현 계획을 만들지 않고 잠금 차단을 보고한다.
|
||||
- SDD 생성/갱신/잠금 해제는 `roadmap-sdd` 또는 `update-roadmap` 요청으로 처리한다.
|
||||
- 런타임이 `origin-task`/`complete-log` 단건 완료 이벤트를 전달한 경우는 `update-roadmap`으로 처리한다.
|
||||
- active/archive `complete.log`, 관련 파일, git history를 종합해 Milestone 작업 상태를 복구하거나 확인하는 요청은 `sync-milestone-workstate`로 처리한다.
|
||||
- plan 요청에 사용할 테스트 환경 규칙이 있으면 `update-test mode=resolve-context`로 read-only `Verification Context`를 만든 뒤 `plan`에 전달한다. 규칙이 없거나 매칭되지 않으면 파일을 생성하지 않고 plan의 repository-native fallback을 사용한다.
|
||||
- `sync-agent-ui`가 `plan-required`로 라우팅한 작업은 plan pair 생성 뒤 `sync-agent-ui mode=prepare-code-work`로 task/UI 매핑을 기록한다. 일반 code-review PASS와 exact `complete.log` 생성 뒤에는 원래 `task-path`와 `completion-log`를 `sync-agent-ui mode=reconcile-completion`에 전달해 해당 매핑만 정합화한다.
|
||||
- pending UI task가 WARN/FAIL follow-up plan으로 교체되면 새 pair 생성 뒤 `prepare-code-work`를 다시 실행한다. 매핑 범위가 실제로 달라진 경우에만 검증 후 state helper의 `--replace`를 사용한다.
|
||||
- pending UI task를 `refine-local-plans`로 분할하거나 sibling reindex해 경로를 바꾼 경우에는 refine 완료 뒤 `sync-agent-ui mode=prepare-code-work`를 호출한다. 기존 경로는 `previous-task-path`, status 대상 전체를 닫는 child 하나는 새 `task-path`로 넘겨 매핑을 rebind하고, scope/evidence가 달라질 때만 검증 후 `--replace`를 사용한다.
|
||||
- `sync-agent-ui`가 `milestone-required`로 라우팅한 작업은 `update-roadmap`이 exact active Milestone을 확정한 뒤 `sync-agent-ui mode=prepare-milestone-work`로 Milestone/UI 매핑을 기록한다. 일반 Milestone 문서에는 agent-ui 전용 완료 필드를 넣지 않는다.
|
||||
- Milestone 종료 요청에서 exact target이 `.sync-state.json.pending_milestone_work`에 있으면 `complete-milestone mode=check-only`를 먼저 실행한다. 종료 가능 근거를 `sync-agent-ui mode=reconcile-milestone-completion`에 전달해 성공 또는 동일 evidence의 already-reconciled를 확인한 뒤에만 `complete-milestone mode=close`를 실행한다. UI 정합화가 실패하면 close하지 않는다.
|
||||
- 로드맵/마일스톤 생성 또는 갱신 요청 안에 SDD 필요 여부와 gate 연결이 포함되면 `create-roadmap` 또는 `update-roadmap`을 진입점으로 삼고, 해당 흐름에서 `roadmap-sdd`를 preflight로 적용한다.
|
||||
- 구현 계획 요청에서 선택 Milestone의 SDD 잠금이 감지되면 `plan`을 진입점으로 삼되, plan 작성 전에 `roadmap-sdd` pre-plan gate를 먼저 통과해야 한다.
|
||||
|
||||
| 요청 키워드 | SKILL.md |
|
||||
|------------|----------|
|
||||
| agent-ops 세팅해줘, scaffold 만들어줘, 초기화해줘 | `agent-ops/skills/common/init-agent-ops/SKILL.md` |
|
||||
| domain rule 만들어줘, rules.md 생성, 새 도메인 규칙 | `agent-ops/skills/common/create-domain-rule/SKILL.md` |
|
||||
| skill 만들어줘, SKILL.md 생성, 새 스킬 추가 | `agent-ops/skills/common/create-skill/SKILL.md` |
|
||||
| agent-ui 생성, UI 스캐폴드 생성, UI 정의 구조 생성, 화면 정의 구조 생성, agent-ui scaffold | `agent-ops/skills/common/create-agent-ui/SKILL.md` |
|
||||
| agent-ui 갱신, agent-ui 업데이트, view 추가, component 추가, frame 추가, wireframe 추가, 화면 정의 갱신, 화면 정의서 갱신, 화면정의서 수정, 화면 정의서에 추가, 화면 정의서에서 제거, 와이어프레임 수정, 와이어프레임에 추가, wireframe 수정, wireframe에 추가, agent-ui USER_REVIEW 해결, UIR 결정 반영 | `agent-ops/skills/common/update-agent-ui/SKILL.md` |
|
||||
| agent-ui 검증, agent-ui validate, UI 정의 정합성 확인, wireframe 정합성 확인, 화면정의서와 wireframe 맞춰, 화면 정의서와 와이어프레임 정합성 확인, 화면정의서와 코드가 안 맞아, UI 스캐폴드 검사 | `agent-ops/skills/common/validate-agent-ui/SKILL.md` |
|
||||
| agent-ui와 코드 동기화, agent-ui와 코드 전체 동기화, 화면정의서대로 코드 반영, 화면 정의서 변경사항 구현, wireframe 변경사항 구현, agent-ui 코드 작업 준비, agent-ui 완료 정합화 | `agent-ops/skills/common/sync-agent-ui/SKILL.md` |
|
||||
| create-test, 테스트 룰 작성, 테스트 룰 생성, 테스트 규칙 작성, 테스트 규칙 생성, 테스트 환경 생성, 상황별 테스트 문서 생성, 도메인별 테스트 문서 생성, 검증 시나리오별 테스트 문서 생성, test rule 생성, agent-test 생성 | `agent-ops/skills/common/create-test/SKILL.md` |
|
||||
| update-test, 테스트 룰 수정, 테스트 룰 갱신, 테스트 규칙 수정, 테스트 규칙 갱신, 테스트 환경 수정, 상황별 테스트 문서 수정, 도메인별 테스트 문서 수정, 검증 시나리오별 테스트 문서 수정, test rule 수정, agent-test 수정, 테스트 컨텍스트 해석, Verification Context 생성 | `agent-ops/skills/common/update-test/SKILL.md` |
|
||||
| 계약 생성해, 프로젝트 계약 생성해, 프로젝트 계약 생성, contract 생성, agent-contract 생성, 계약 문서 생성, inner 계약 생성, outer 계약 생성 | `agent-ops/skills/common/create-contract/SKILL.md` |
|
||||
| 계약 업데이트해, 프로젝트 계약 업데이트해, 프로젝트 계약 업데이트, 계약 갱신해, 계약 갱신, 계약 수정, 계약 정리, contract update, agent-contract 갱신, inner 계약 갱신, outer 계약 갱신 | `agent-ops/skills/common/update-contract/SKILL.md` |
|
||||
| 스펙 생성, 구현 스펙 생성, 현재 구현 문서화, agent-spec 생성, living spec 생성, 완료된 기능 스펙 작성 | `agent-ops/skills/common/create-spec/SKILL.md` |
|
||||
| 스펙 업데이트, 스펙 갱신, 구현 스펙 갱신, 구현 스펙 업데이트, 완료 기능 스펙 반영, agent-spec 갱신, 스펙 동기화 | `agent-ops/skills/common/update-spec/SKILL.md` |
|
||||
| update-test, 테스트 룰 수정, 테스트 룰 갱신, 테스트 규칙 수정, 테스트 규칙 갱신, 테스트 환경 수정, 상황별 테스트 문서 수정, 도메인별 테스트 문서 수정, 검증 시나리오별 테스트 문서 수정, test rule 수정, agent-test 수정 | `agent-ops/skills/common/update-test/SKILL.md` |
|
||||
| agent-contract 생성, agent-contract 갱신, 계약 문서 작성, 계약 문서 정리, 제공 계약 추가, 소비 계약 추가, 외부 계약 포인터 관리 | `agent-ops/skills/common/agent-contract/SKILL.md` |
|
||||
| README 작성해줘, README 만들어줘, 프로젝트 설명 문서 만들어줘 | `agent-ops/skills/common/create-readme/SKILL.md` |
|
||||
| 핸즈오프 남겨, handoff 작성, 인수인계 작성, 다른 세션에서 이어가게 정리, 작업을 이어받도록 기록 | `agent-ops/skills/common/create-handoff/SKILL.md` |
|
||||
| 로드맵 만들어줘, roadmap 생성, 마일스톤 설계, goal/phase 구조 잡아줘 | `agent-ops/skills/common/create-roadmap/SKILL.md` |
|
||||
| 현 마일스톤과 작업현황 동기화, 현재 마일스톤 작업현황 동기화, 마일스톤 작업현황 동기화, 마일스톤 완료내역 동기화, agent-task 완료를 마일스톤에 반영, complete.log 후보 스캔, 누락된 Roadmap Completion 복구, 파일/git 기준 작업 상태 확인, 작은 작업 완료 반영, 마일스톤 체크박스 재동기화, 로드맵 작업 완료 상태 동기화 | `agent-ops/skills/common/sync-milestone-workstate/SKILL.md` |
|
||||
| 마일스톤 완료해도 될지 검토해봐, 현 마일스톤 종료 검토, 현재 마일스톤 닫고 다음 마일스톤 지정, 마일스톤 종료해, 마일스톤 완료 검토, 종료 검토 | `agent-ops/skills/common/complete-milestone/SKILL.md` |
|
||||
| 로드맵 업데이트, roadmap 갱신, 로드맵에 추가, 로드맵 작업 추가, 로드맵 기능 추가, 로드맵 Epic 추가, 로드맵 에픽 추가, 로드맵 Task 추가, 로드맵 태스크 추가, 로드맵 테스크 추가, 로드맵 TODO 추가, 마일스톤에 추가, 마일스톤 추가, 마일스톤 갱신, 마일스톤 아카이브, phase 추가, phase 변경, 페이즈 추가, 페이즈 변경, 현재 마일스톤 변경, 로드맵 한국어 전환, 로드맵 번역 | `agent-ops/skills/common/update-roadmap/SKILL.md` |
|
||||
| SDD 작성, SDD 생성, SDD 갱신, SDD 필요 여부, SDD gate 확인, SDD 사용자 리뷰, SDD 잠금 해제, SDD 승인 준비, SDD archive, spec gate, 설계 게이트 | `agent-ops/skills/common/roadmap-sdd/SKILL.md` |
|
||||
| 이 마일스톤은 X가 끝나야 가능해, A 전까지 B 잠가둬, 잠금 해제 조건은 X야, X 프로젝트 작업 뒤에 현재 마일스톤 진행, 의존성 설정해, 외부 의존 잠금 | `agent-ops/skills/common/update-roadmap/SKILL.md` |
|
||||
| roadmap dependency 확인, locks.yaml 판별, 외부 의존 잠금 확인, unlock-ready 판별, 잠금 해제 조건 충족 여부 확인, roadmap-dependency-checker.sh | `agent-ops/skills/common/check-roadmap-dependency/SKILL.md` |
|
||||
| 지금 작업이 뭐지?, 현재 작업 분석, 어디까지 했지?, 로드맵상 현 위치, 현재 마일스톤 위치, current 기준 breadcrumb | `agent-ops/skills/common/analyze-roadmap-position/SKILL.md` |
|
||||
| 계획 세워줘, 계획 작성해, 계획 만들어줘, 구현 계획, PLAN.md, plan, plan 작성해, plan 만들어줘 | `agent-ops/skills/common/plan/SKILL.md` |
|
||||
| 현재 plan들 세분화해, 현재 plan 세분화, 기존 plan 더 나눠, local plan 분리해 | `agent-ops/skills/common/refine-local-plans/SKILL.md` |
|
||||
| 최종 라우팅, task routing, cloud/local 재평가, lane/G 판단, G 등급 재평가, routed filename 결정 | `agent-ops/skills/common/finalize-task-routing/SKILL.md` |
|
||||
| 코드 리뷰해줘, 리뷰 진행해, 리뷰해줘, code review, CODE_REVIEW.md, 리뷰 루프 | `agent-ops/skills/common/code-review/SKILL.md` |
|
||||
| 커밋해줘, 푸시해줘, commit, push, 반영해줘 | `agent-ops/skills/common/commit-push/SKILL.md` |
|
||||
| agent-ops 싱크해, agent-ops 동기화해, agentic-framework에 올려줘, agent-ops를 [프로젝트]로 싱크해 | `agent-ops/skills/common/sync-push/SKILL.md` |
|
||||
| agent-ops pull해, agent-ops 가져와, agentic-framework에서 가져와, agent-ops 내려받아 | `agent-ops/skills/common/sync-pull/SKILL.md` |
|
||||
| 도메인 업데이트, domain rule 갱신, 도메인 검토, domain 스캔 | `agent-ops/skills/common/update-domain-rule/SKILL.md` |
|
||||
|
||||
라우팅 우선순위:
|
||||
|
||||
- 이미 생성된 미착수 local pair의 분할만 요청하면 `refine-local-plans`를 선택한다. 새 plan 작성이나 구현 범위 재분석이 포함되면 `plan`을 선택한다.
|
||||
- `refine-local-plans` 대상이 아닌 PLAN/CODE_REVIEW 작성 또는 재작성이 요청 범위에 포함되면 `plan`을 선택한다. `plan`이 최종 단계에서 `finalize-task-routing`을 필수 호출한다.
|
||||
- lane/G/canonical filename 판단만 요청되고 plan 문서 작성은 요청되지 않았을 때만 `finalize-task-routing`을 직접 선택한다.
|
||||
- 코드 리뷰 요청은 `code-review`를 선택한다. WARN/FAIL follow-up은 `code-review -> plan -> finalize-task-routing` 순서를 유지한다.
|
||||
|
|
|
|||
|
|
@ -1,364 +0,0 @@
|
|||
---
|
||||
name: sync-agent-ui
|
||||
description: 정합화된 agent-ui 변경분을 코드에 직접 반영하거나 plan/roadmap으로 라우팅하고 plan·Milestone 작업 매핑과 완료 후 상태 정합화를 소유한다. agent-ui와 코드 동기화, 화면정의서대로 코드 반영, agent-ui 코드 작업 준비·완료 정합화 요청에 사용한다.
|
||||
---
|
||||
|
||||
# sync-agent-ui
|
||||
|
||||
## 목적
|
||||
|
||||
정합화된 `agent-ui/` 변경분을 실제 UI 코드에 반영한다.
|
||||
기본 동작은 `.sync-state.json`의 `last_synced_head` 이후 agent-ui 변경분만 반영하며, 사용자가 전체 동기화를 명시한 경우에만 현재 agent-ui 전체를 코드와 대조한다.
|
||||
코드 반영 전에 코드 작업 규모를 판정해 작은 작업은 직접 반영하고, 중간 작업은 `plan` 루프로, Milestone이 필요한 큰 코드 작업은 `update-roadmap`의 Milestone/Epic/Task 갱신으로 넘긴다.
|
||||
`plan-required` 작업은 일반 plan/code-review 문서에 agent-ui 전용 section을 넣지 않는다. 대신 plan pair 생성 직후 `prepare-code-work`로 task와 agent-ui 문서를 매핑하고, 일반 code-review PASS와 `complete.log` 생성 뒤 `reconcile-completion`으로 status/code evidence를 정합화한다.
|
||||
`milestone-required` 작업도 일반 Milestone 문서에 agent-ui 전용 완료 필드를 넣지 않는다. `update-roadmap`이 확정한 활성 Milestone을 `prepare-milestone-work`로 매핑하고, 종료 직전 `complete-milestone check-only` 근거를 받은 `reconcile-milestone-completion`이 status/code evidence를 정합화한다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 "agent-ui와 코드 동기화", "화면정의서대로 코드 반영", "wireframe 변경사항 구현"을 요청할 때
|
||||
- `update-agent-ui` 또는 `validate-agent-ui`가 code sync 필요성을 판단했고 현재 범위에 미해결 USER_REVIEW가 없을 때
|
||||
- 사용자가 "agent-ui와 코드 전체 동기화"처럼 full sync를 명시할 때
|
||||
- `plan-required`로 생성된 task와 agent-ui 문서의 연결을 기록할 때
|
||||
- 일반 code-review PASS 뒤 생성된 `complete.log`를 agent-ui status/code evidence에 반영할 때
|
||||
- `milestone-required`로 확정된 활성 Milestone과 agent-ui 문서를 연결할 때
|
||||
- Milestone 종료 감사 통과 후보의 agent-ui 상태를 실제 종료 전에 정합화할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `mode`: `incremental`, `full`, `prepare-code-work`, `reconcile-completion`, `prepare-milestone-work`, `reconcile-milestone-completion` 중 하나. 기본값은 `incremental` (선택)
|
||||
- `scope`: `all`, `view:<view-id>`, `component:<component-id>` 중 하나. 기본값은 `all` (선택)
|
||||
- `validated`: `true` 또는 `false`. 기본값은 `false` (선택)
|
||||
- `sync-intent-source`: `manual`, `update-agent-ui`, `validate-agent-ui` 중 하나 (선택)
|
||||
- `execution-route`: `auto`, `direct-sync`, `plan-required`, `milestone-required` 중 하나. 기본값은 `auto` (선택)
|
||||
- `task-path`: `agent-task/` 기준 원래 active task 경로. `prepare-code-work`와 `reconcile-completion`에서 필수
|
||||
- `previous-task-path`: plan refinement/reindex 전에 pending entry가 가리키던 active task 경로. `prepare-code-work` rebind에서만 선택
|
||||
- `milestone-path`: `agent-roadmap/phase/*/milestones/*.md`의 정확한 활성 Milestone 경로. Milestone prepare/reconcile에서 필수
|
||||
- `agent-ui-docs`: 완료 시 `구현됨`으로 전환할 활성 view/component 문서 목록. `prepare-code-work`에서 필수
|
||||
- `frame-docs`: 함께 검증할 활성 frame-view 문서 목록. `prepare-code-work`에서 선택
|
||||
- `code-paths`: 구현 후보 또는 완료 evidence 코드 경로 목록. `prepare-code-work`에서 필수
|
||||
- `verification-requirements`: 완료 정합화 전에 확인할 명령/기대 결과 목록. `prepare-code-work`에서 선택
|
||||
- `completion-log`: 일반 code-review가 만든 정확한 `complete.log` 경로. `reconcile-completion`에서 필수
|
||||
- `closure-evidence`: 같은 Milestone에 대해 `complete-milestone mode=check-only`가 반환한 종료 가능 근거와 검증 요약. `reconcile-milestone-completion`에서 필수
|
||||
- `validation-evidence`: `update-agent-ui` 후 실행한 `validate-agent-ui` PASS 근거. `reconcile-completion`에서 필수
|
||||
- `sync-result-head`: agent-ui와 코드 결과를 모두 포함한다고 검증된 commit hash. `reconcile-completion`에서 선택
|
||||
- `push`: `true` 또는 `false`. `incremental|full`에서만 사용하며 기본값은 `true` (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/rules/common/rules-agent-ui.md`를 읽는다.
|
||||
- [ ] `agent-ui/`와 `agent-ui/definition/index.md` 존재 여부를 확인한다.
|
||||
- [ ] `mode=incremental|full|prepare-code-work|prepare-milestone-work`이고 `validated=true`가 아니면 먼저 `validate-agent-ui`를 실행한다.
|
||||
- [ ] `agent-ui/USER_REVIEW.md`가 있으면 현재 sync 범위와 관련된 미해결 항목이 없는지 확인한다.
|
||||
- [ ] `agent-ui/.sync-state.json`을 읽는다. 없고 `mode=incremental|prepare-code-work|reconcile-completion|prepare-milestone-work|reconcile-milestone-completion`이면 legacy baseline migration 필요로 보고 중단한다.
|
||||
- [ ] `schema_version: 1|2|3`이면 bundled state helper가 기존 필드와 pending 매핑을 보존·정규화하고 `schema_version: 4`로 올리게 한다.
|
||||
- [ ] `.sync-state.json`을 갱신하는 모든 모드에서 `agent-ops/skills/common/sync-agent-ui/scripts/sync_state.py`를 사용한다. shared state를 수동 read-modify-write하지 않는다.
|
||||
- [ ] `mode=incremental|full`이면 현재 sync 대상 agent-ui 경로 또는 그 상·하위 경로가 code/Milestone pending entry의 `status_paths` 또는 `frame_paths`와 겹치지 않는지 확인한다. 겹치면 direct sync를 시작하지 않고 기존 pending owner 흐름으로 돌린다.
|
||||
- [ ] `mode=incremental|full`이면 수정할 UI 코드 경로에 해당하는 project/domain rule을 먼저 읽는다.
|
||||
- [ ] `mode=incremental|full`이고 코드 변경 검증이 필요하면 작업 환경의 `agent-test/<env>/rules.md`를 읽는다. 환경 미지정은 `local`로 본다.
|
||||
- [ ] `mode=prepare-code-work`이면 exact active `PLAN-*-G??.md`와 matching `CODE_REVIEW-*-G??.md`가 `task-path`에 존재하는지 확인한다.
|
||||
- [ ] `mode=reconcile-completion`이면 원래 `task-path`, exact `completion-log`가 존재하고 matching pending entry가 정확히 하나인지 확인한다.
|
||||
- [ ] `mode=prepare-milestone-work`이면 `update-roadmap`이 확정한 exact active `milestone-path`가 존재하는지 확인한다.
|
||||
- [ ] `mode=reconcile-milestone-completion`이면 같은 `milestone-path`의 pending entry와 `complete-milestone check-only` closure evidence가 있는지 확인한다.
|
||||
- [ ] `git status --short`와 현재 `HEAD`를 확인한다.
|
||||
- [ ] unrelated dirty worktree가 있으면 sync commit 전에 범위를 보고하고, agent-ui와 관련 코드 파일만 stage한다.
|
||||
- [ ] 이전 sync 실패로 남은 관련 작업트리 변경이 있으면 보존할지, 사용자 결정과 충돌하는지 확인한다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
### prepare-code-work 절차
|
||||
|
||||
1. **task 매핑 검증**
|
||||
- `task-path`의 active PLAN/review pair가 같은 task header를 갖고 아직 verdict가 없는지 확인한다.
|
||||
- `agent-ui-docs`는 현재 활성 view/component 문서이고 status가 `계획`인지 확인한다. `가정`, `불명확`, 이미 archive 된 문서는 매핑하지 않는다.
|
||||
- `frame-docs`는 visual source가 있는 활성 frame-view 문서인지 확인하고 대응 view가 `agent-ui-docs`에 포함됐는지 확인한다. frame-view 자체에는 status를 요구하거나 `구현됨` 전환을 적용하지 않는다.
|
||||
- `code-paths`는 실제 구현 후보로 좁혀진 경로만 기록한다. 존재하지 않는 새 파일 후보는 경로와 생성 의도가 plan에 명시된 경우에만 허용한다.
|
||||
- 기존 pending task가 `refine-local-plans`로 분할되거나 sibling reindex로 경로가 바뀌었으면 원래 매핑을 그대로 둘 수 없다. status 대상 전체를 닫는 child를 하나만 고르고 기존 경로를 `previous-task-path`, 그 child 경로를 `task-path`로 전달한다.
|
||||
|
||||
2. **pending entry 기록**
|
||||
- `agent-ui/.sync-state.json`의 SHA-256을 계산한 뒤 bundled helper의 `prepare` 명령에 `--expected-sha256`으로 넘긴다. helper는 agent-ui 디렉터리 잠금을 잡은 다음 digest를 다시 확인한다.
|
||||
- 같은 `task_path`와 같은 내용은 idempotent `already_prepared`로 허용한다.
|
||||
- 같은 `task_path`의 내용이 다르면 helper가 중단한다. follow-up plan으로 범위가 실제 바뀐 것을 확인한 경우에만 `--replace`를 사용한다.
|
||||
- `previous-task-path`를 전달하면 helper가 기존 pending entry를 새 `task-path`로 원자적으로 rebind한다. scope/status/frame/code/verification 매핑이 달라지면 전체 결과를 닫는 child인지 검증한 뒤에만 `--replace`를 함께 사용한다.
|
||||
- 하나의 `status_path` 또는 `frame_path`를 둘 이상의 pending task가 소유하려 하면 helper가 중단한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"task_path": "agent-task/<task-name>",
|
||||
"scope": "<scope>",
|
||||
"status_paths": ["agent-ui/definition/views/.../index.md"],
|
||||
"frame_paths": ["agent-ui/frame/views/.../index.md"],
|
||||
"code_paths": ["<code path>"],
|
||||
"verification_requirements": ["<command>: <expected result>"],
|
||||
"prepared_at": "<ISO-8601>",
|
||||
"state": "pending"
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
python3 agent-ops/skills/common/sync-agent-ui/scripts/sync_state.py prepare \
|
||||
--state agent-ui/.sync-state.json \
|
||||
--expected-sha256 <sha256> \
|
||||
--task-path agent-task/<task-name> \
|
||||
--scope <scope> \
|
||||
--status-path agent-ui/definition/views/<view-id>/index.md \
|
||||
--frame-path agent-ui/frame/views/<view-id>/index.md \
|
||||
--code-path <code-path> \
|
||||
--verification-requirement '<command>: <expected result>' \
|
||||
--prepared-at <ISO-8601>
|
||||
```
|
||||
|
||||
- `--status-path`와 `--code-path`는 필요한 만큼 반복하고, frame이 없으면 `--frame-path`를 생략한다.
|
||||
- refinement/reindex rebind에서는 `--previous-task-path agent-task/<old-task-name>`을 추가한다.
|
||||
|
||||
3. **state 경계 유지**
|
||||
- helper가 `schema_version`을 `4`로 올리고 code/Milestone pending·reconciled 기록과 baseline 필드를 보존하게 한다.
|
||||
- 이 모드는 `last_synced_head`, agent-ui status, code evidence를 바꾸지 않고 commit/push하지 않는다.
|
||||
- 일반 plan/review 문서에는 agent-ui 전용 completion section이나 review 전용 status 전환 지시를 추가하지 않는다.
|
||||
|
||||
### reconcile-completion 절차
|
||||
|
||||
1. **완료 이벤트 매칭**
|
||||
- exact `completion-log`가 `agent-task/archive/**/complete.log`에 있고 header task가 원래 `task-path`와 일치하며 loop history에 terminal PASS/RESOLVED가 있는지 확인한다.
|
||||
- 입력된 원래 `task-path`를 `pending_code_work[].task_path`와 exact match한다. archive destination suffix나 `completion-log` 경로에서 원래 task path를 역추정하지 않는다.
|
||||
- zero/multiple match이면 agent-ui 문서를 추측해 갱신하지 않는다.
|
||||
|
||||
2. **완료 evidence 검증**
|
||||
- pending entry의 모든 `code_paths`가 실제 존재하고 agent-ui 정의를 구현한 근거인지 확인한다.
|
||||
- `completion-log`의 최종 검증과 `verification_requirements`가 충족됐는지 확인한다.
|
||||
- generic `complete.log`에 agent-ui 전용 section이 없어도 정상으로 본다. 필요한 매핑은 pending entry에서만 읽는다.
|
||||
- evidence가 부족하면 entry를 `pending`으로 유지하고 일반 plan/review artifact를 수정하지 않는다.
|
||||
|
||||
3. **agent-ui 상태 반영**
|
||||
- pending entry의 `status_paths`에 있는 view/component 문서마다 `update-agent-ui`를 `status=구현됨`, 실제 code evidence, `post-validate=false`, `post-sync=false`로 실행한다.
|
||||
- `frame_paths`에는 status를 쓰지 않는다. 대응 definition과 visual source 연결을 검증 대상으로만 사용한다.
|
||||
- 모든 문서 갱신 뒤 `validate-agent-ui`를 matching scope, `sync-intent=skip`으로 실행하고 PASS 근거를 `validation-evidence`로 고정한다.
|
||||
- 갱신이나 검증이 실패하면 pending entry를 제거하지 않고 `agent-ui/USER_REVIEW.md`에 `Source Skill: sync-agent-ui`, `Stage: completion-reconcile`로 차단 근거를 남긴다.
|
||||
|
||||
4. **pending entry 종료**
|
||||
- 갱신과 검증이 모두 통과한 뒤 `.sync-state.json`의 최신 SHA-256을 다시 계산하고 bundled helper의 `reconcile` 명령을 실행한다.
|
||||
- helper가 matching pending entry를 제거하고 `reconciled_code_work`에 `task_path`, exact `completion_log`, scope, status/frame/code paths, validation evidence를 기록하게 한다.
|
||||
- helper가 `last_sync_mode`을 `plan-reconcile`, `last_synced_at`, `agent_ui_paths`, `code_paths`, `notes`를 완료 근거로 갱신하게 한다.
|
||||
- `sync-result-head`가 실제 commit이고 matching agent-ui/code 결과를 모두 포함하는지 검증된 경우에만 `last_synced_head`를 그 값으로 갱신한다. 그렇지 않으면 기존 `last_synced_head`를 보존하고 notes에 기준점 미갱신 사유를 남긴다.
|
||||
- 이미 같은 `task_path`와 `completion-log`가 `reconciled_code_work`에 있으면 helper의 idempotent `already_reconciled` 결과를 사용한다.
|
||||
- 이 모드는 일반 plan/review/complete.log를 수정하거나 commit/push하지 않는다.
|
||||
|
||||
```bash
|
||||
python3 agent-ops/skills/common/sync-agent-ui/scripts/sync_state.py reconcile \
|
||||
--state agent-ui/.sync-state.json \
|
||||
--expected-sha256 <sha256> \
|
||||
--task-path agent-task/<task-name> \
|
||||
--completion-log agent-task/archive/<YYYY>/<MM>/<task-path>/complete.log \
|
||||
--validation-evidence '<validate-agent-ui PASS evidence>' \
|
||||
--reconciled-at <ISO-8601>
|
||||
```
|
||||
|
||||
- 검증된 결과 commit이 있을 때만 `--sync-result-head <commit>`을 추가한다.
|
||||
|
||||
### Milestone 매핑과 완료 정합화 절차
|
||||
|
||||
1. **Milestone 작업 준비**
|
||||
- `execution-route=milestone-required`이면 코드 구현을 시작하지 않고 먼저 `update-roadmap`으로 활성 Milestone을 생성하거나 정확히 하나를 선택한다.
|
||||
- 일반 Milestone 문서에는 agent-ui 전용 완료 필드나 status 전환 지시를 쓰지 않는다.
|
||||
- `agent-ui-docs`, `frame-docs`, `code-paths`, `verification-requirements`를 `prepare-code-work`와 같은 기준으로 검증한다.
|
||||
- `.sync-state.json`의 최신 SHA-256과 exact active `milestone-path`를 bundled helper의 `prepare-milestone`에 전달한다.
|
||||
- 같은 Milestone과 같은 매핑은 `already_prepared`로 허용하고, 실제 scope/evidence 변경을 확인한 경우에만 `--replace`를 사용한다.
|
||||
|
||||
```bash
|
||||
python3 agent-ops/skills/common/sync-agent-ui/scripts/sync_state.py prepare-milestone \
|
||||
--state agent-ui/.sync-state.json \
|
||||
--expected-sha256 <sha256> \
|
||||
--milestone-path agent-roadmap/phase/<phase>/milestones/<milestone>.md \
|
||||
--scope <scope> \
|
||||
--status-path agent-ui/definition/views/<view-id>/index.md \
|
||||
--frame-path agent-ui/frame/views/<view-id>/index.md \
|
||||
--code-path <code-path> \
|
||||
--verification-requirement '<command>: <expected result>' \
|
||||
--prepared-at <ISO-8601>
|
||||
```
|
||||
|
||||
2. **종료 직전 정합화**
|
||||
- caller/router는 Milestone 종료 요청에서 먼저 `complete-milestone mode=check-only`를 실행한다. 종료 가능 판정과 실제 검증 근거가 없으면 이 모드를 실행하지 않는다.
|
||||
- `closure-evidence`에는 exact `milestone-path`, check-only 판정, 코드레벨 감사, 실행한 검증 결과, spec check-only 결과를 식별 가능하게 요약한다. 재시도 idempotency를 위해 실행 시각처럼 의미 없는 가변 값은 넣지 않는다.
|
||||
- pending entry의 모든 `code_paths`와 `verification_requirements`가 check-only 근거와 현재 checkout에서 충족되는지 다시 확인한다.
|
||||
- `status_paths`의 view/component만 `update-agent-ui status=구현됨`과 실제 code evidence로 갱신하고, `frame_paths`는 연결 정합성만 검증한다.
|
||||
- 모든 문서 갱신 뒤 `validate-agent-ui sync-intent=skip`을 실행한다. 실패하면 pending entry를 유지하고 Milestone close를 호출하지 않는다.
|
||||
|
||||
3. **Milestone pending 종료**
|
||||
- 갱신과 검증이 통과한 뒤 최신 state SHA-256과 closure/validation evidence를 helper의 `reconcile-milestone`에 전달한다.
|
||||
- helper가 matching entry를 `pending_milestone_work`에서 `reconciled_milestone_work`로 이동하고 완료 근거를 기록한다.
|
||||
- 성공 또는 같은 evidence의 `already_reconciled` 뒤에만 caller/router가 `complete-milestone mode=close`를 실행한다. close가 다시 감사를 통과하지 못하면 roadmap 상태를 추측해 바꾸지 않는다.
|
||||
- 이 모드는 일반 Milestone 문서와 complete-milestone 결과를 수정하지 않고 commit/push하지 않는다.
|
||||
|
||||
```bash
|
||||
python3 agent-ops/skills/common/sync-agent-ui/scripts/sync_state.py reconcile-milestone \
|
||||
--state agent-ui/.sync-state.json \
|
||||
--expected-sha256 <sha256> \
|
||||
--milestone-path agent-roadmap/phase/<phase>/milestones/<milestone>.md \
|
||||
--closure-evidence '<complete-milestone check-only closure evidence>' \
|
||||
--validation-evidence '<validate-agent-ui PASS evidence>' \
|
||||
--reconciled-at <ISO-8601>
|
||||
```
|
||||
|
||||
- 검증된 결과 commit이 있을 때만 `--sync-result-head <commit>`을 추가한다.
|
||||
|
||||
### incremental/full 절차
|
||||
|
||||
1. **동기화 범위 확정**
|
||||
- `.sync-state.json`이 없고 `mode=incremental`이면 현재 agent-ui를 legacy baseline 후보로 본다.
|
||||
- legacy baseline 후보는 `validate-agent-ui` 통과 후 agent-ui baseline commit과 `.sync-state.json` commit을 남기는 migration으로 처리하고, 같은 실행에서 코드 반영은 하지 않는다.
|
||||
- `mode=incremental`이면 `.sync-state.json.last_synced_head` 이후 현재 `HEAD`/worktree까지의 agent-ui 변경분을 확인한다.
|
||||
- 변경분 판정에서 `agent-ui/.sync-state.json` 자체는 제외한다.
|
||||
- `mode=full`이면 현재 활성 `agent-ui/definition/**`과 `agent-ui/frame/**` 전체를 코드와 대조한다.
|
||||
- `mode=full`에서 `.sync-state.json`이 없으면 code sync 성공 후 새 sync state를 만든다.
|
||||
- `가정` 또는 `불명확` 상태 항목은 코드 반영 대상에서 제외하고 USER_REVIEW로 남긴다.
|
||||
- 현재 범위에 미해결 USER_REVIEW가 있으면 중단한다.
|
||||
- 확정된 sync 대상 agent-ui 경로 트리가 `pending_code_work` 또는 `pending_milestone_work`의 `status_paths`/`frame_paths`와 하나라도 겹치면 direct sync 대상으로 가져오지 않는다. 해당 pending task/Milestone의 완료 정합화 흐름을 사용한다.
|
||||
|
||||
2. **코드 반영 방식 판정**
|
||||
- 이 판정은 agent-ui 문서 작업의 크기가 아니라, 정합화된 agent-ui 변경분을 코드에 반영하는 구현 작업의 크기와 위험만 대상으로 한다.
|
||||
- `execution-route=auto`이면 코드 반영 대상의 크기와 위험을 `direct-sync`, `plan-required`, `milestone-required` 중 하나로 판정한다.
|
||||
- `direct-sync`는 다음 조건을 모두 만족할 때만 사용한다.
|
||||
- 단일 view/component/frame 또는 한 화면 안의 국소 변경이다.
|
||||
- 기존 route, shell, navigation, shared state, design token, package boundary를 그대로 사용한다.
|
||||
- 새 정보구조, 새 주요 workflow, 새 공통 component 체계, 제품 방향 결정이 필요 없다.
|
||||
- 변경 후보 코드가 소수 파일로 좁혀지고 검증 명령이 명확하다.
|
||||
- `plan-required`는 목표와 범위는 명확하지만 독립 리뷰 가능한 구현 루프가 필요할 때 사용한다.
|
||||
- 여러 view/component에 걸친 반영, shared component 추출, route/shell 조정, 테스트/검증 보강, UI 상태와 코드 변경을 함께 다루는 작업이 여기에 속한다.
|
||||
- 이 경우 직접 코드 반영을 시작하지 않고 `plan` 스킬로 전환한다.
|
||||
- plan에는 일반 구현 범위, 코드 후보, 검증 기준만 넘긴다.
|
||||
- plan pair가 생성되면 이 스킬의 `prepare-code-work`를 실행해 반영 대상 agent-ui 문서, 코드 후보, verification requirement를 task에 매핑한다.
|
||||
- 일반 code-review PASS와 `complete.log` 생성 뒤 caller/router/runtime가 `reconcile-completion`을 실행해 mapped agent-ui 문서를 `구현됨`으로 전환한다.
|
||||
- `milestone-required`는 코드 구현이 제품 UI 구조나 장기 작업 단위까지 바꾸는 경우 사용한다.
|
||||
- navigation/information architecture 재정렬, 외부 제품 UI 분석 기반 재설계, 여러 workflow/role/surface를 묶는 작업, 활성 Milestone 범위 밖 작업이 여기에 속한다.
|
||||
- 이 경우 직접 코드 반영과 plan 생성을 시작하지 않고 `update-roadmap`으로 Milestone/Epic/Task 배치를 먼저 남긴다.
|
||||
- exact active Milestone이 확정되면 `prepare-milestone-work`로 UI 매핑을 `.sync-state.json`에 남긴다. Milestone 문서에는 agent-ui 전용 완료 필드를 추가하지 않는다.
|
||||
- `plan-required` 판정 시 `prepare-code-work` pending entry 외에는 agent-ui 문서 status, baseline sync state, commit/push를 갱신하지 않는다.
|
||||
- `milestone-required` 판정 시 agent-ui 문서 status와 baseline sync state, commit/push를 갱신하지 않고 `pending_milestone_work` 매핑만 기록한다.
|
||||
|
||||
3. **코드 반영**
|
||||
- 이 단계는 `execution-route=direct-sync`일 때만 수행한다. `plan-required` 또는 `milestone-required` 판정이면 Step 2의 라우팅 결과를 보고하고 해당 스킬 흐름으로 전환한다.
|
||||
- `계획` 상태의 view/component 요구사항과 연결된 frame의 layout 근거를 UI 코드에 반영한다.
|
||||
- existing component, route, shell, widget 구조를 우선하고 새 구조를 임의로 만들지 않는다.
|
||||
- definition이 요구하는 정보 우선순위, region, action, state, component 참조를 코드 반영 기준으로 삼는다.
|
||||
- wireframe/frame은 layout, density, visual relationship 보조 근거로만 사용하고 definition을 대체하지 않는다.
|
||||
|
||||
4. **검증**
|
||||
- 관련 domain rule과 agent-test rule에 맞는 최소 검증을 실행한다.
|
||||
- 검증 실패가 명확하고 에이전트가 해결 가능하면 수정과 검증을 반복한다.
|
||||
- 구현 방향 충돌, 환경/권한 차단, 반복 실패, 사용자 판단이 필요한 시각 결과는 `agent-ui/USER_REVIEW.md`에 남기고 중단한다.
|
||||
- USER_REVIEW로 중단하면 commit/push하지 않고 `.sync-state.json`도 갱신하지 않는다.
|
||||
- USER_REVIEW로 중단할 때 관련 작업트리 변경은 사용자 결정과 충돌하지 않으면 보존하고, 재개 진입점과 변경 파일을 USER_REVIEW에 남긴다.
|
||||
- `execution-route=direct-sync`에서 코드 반영과 검증이 모두 통과한 항목은 이 스킬 실행 안에서 agent-ui 문서의 `status`를 `구현됨`으로 갱신하고 Source Evidence에 코드 경로를 남긴다.
|
||||
|
||||
5. **sync state와 commit/push**
|
||||
- 이 단계는 `execution-route=direct-sync`에서 코드 반영, 검증, agent-ui status/code evidence 갱신이 모두 통과한 경우에만 수행한다.
|
||||
- commit 전에 state를 다시 읽어 direct sync 대상이 새 pending entry의 소유 경로와 겹치지 않는지 재확인한다. 겹치면 commit하지 않고 충돌 경로와 pending owner를 보고한다.
|
||||
- 검증이 통과하면 agent-ui/code 변경을 먼저 commit한다.
|
||||
- `.sync-state.json`이 없으면 `agent-ops/skills/common/_templates/agent-ui/sync-state-template.json` 기준으로 새로 만든다.
|
||||
- 방금 만든 sync 결과 commit hash와 `.sync-state.json`의 최신 SHA-256을 bundled helper `record-sync`에 넘긴다.
|
||||
- helper가 lock 안에서 pending 소유 경로와의 겹침을 다시 거부한 뒤 `last_sync_mode`, `last_synced_head`, `last_synced_at`, `agent_ui_paths`, `code_paths`, `notes`를 갱신하고 기존 code/Milestone pending·reconciled 기록을 보존하게 한다.
|
||||
|
||||
```bash
|
||||
python3 agent-ops/skills/common/sync-agent-ui/scripts/sync_state.py record-sync \
|
||||
--state agent-ui/.sync-state.json \
|
||||
--expected-sha256 <sha256> \
|
||||
--sync-mode <incremental|full> \
|
||||
--sync-result-head <sync-result-commit> \
|
||||
--synced-at <ISO-8601> \
|
||||
--agent-ui-path <agent-ui-path> \
|
||||
--code-path <code-path> \
|
||||
--note '<sync evidence>'
|
||||
```
|
||||
|
||||
- agent-ui/code 경로와 note는 필요한 만큼 옵션을 반복한다.
|
||||
- legacy baseline migration은 `--sync-mode migration`을 사용하고 code 반영이 없으면 `--code-path`를 생략한다.
|
||||
- `.sync-state.json` 변경을 별도 commit한다.
|
||||
- commit message는 예를 들어 `sync: apply agent-ui to code`와 `sync: record agent-ui sync state`처럼 목적이 분리되게 쓴다.
|
||||
- `push=true`이면 두 commit을 push한다.
|
||||
|
||||
6. **결과 보고**
|
||||
- sync mode와 scope
|
||||
- execution route와 판정 근거
|
||||
- 반영한 agent-ui 파일과 코드 파일
|
||||
- 변경한 status
|
||||
- 실행한 검증
|
||||
- sync 결과 commit hash와 sync-state commit/push 결과
|
||||
- USER_REVIEW 생성/갱신 여부
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `validate-agent-ui`가 먼저 실행되었거나 `validated=true` 근거가 있는가
|
||||
- [ ] 현재 sync 범위에 미해결 USER_REVIEW가 없는가
|
||||
- [ ] 코드 반영 전에 `direct-sync`, `plan-required`, `milestone-required` 중 하나로 판정했는가
|
||||
- [ ] `plan-required` 판정에서 직접 코드 변경, status 구현됨 전환, baseline sync state 갱신, commit/push를 하지 않고 pending entry만 기록했는가
|
||||
- [ ] `milestone-required` 판정에서 직접 코드 변경, status 구현됨 전환, baseline sync state 갱신, commit/push를 하지 않고 exact Milestone pending mapping만 기록했는가
|
||||
- [ ] `direct-sync` 판정에서 코드 반영과 검증이 통과한 항목은 같은 실행 안에서 agent-ui 문서 status를 `구현됨`으로 바꾸고 code evidence를 남겼는가
|
||||
- [ ] `direct-sync` 대상이 code/Milestone pending owner의 status/frame path와 겹치지 않는지 코드 변경 전과 commit 전 확인했는가
|
||||
- [ ] `prepare-code-work`가 exact task path와 활성 agent-ui 문서를 unique pending entry로 기록했는가
|
||||
- [ ] refinement/reindex된 pending task는 전체 결과를 닫는 child 하나로 rebind되어 이전 task path가 남지 않았는가
|
||||
- [ ] view/component는 `status_paths`, frame-view는 validation-only `frame_paths`로 분리했는가
|
||||
- [ ] 하나의 status/frame path가 둘 이상의 pending task에 배정되지 않았는가
|
||||
- [ ] state helper에 inspection 시점 SHA-256을 전달해 directory lock 안에서 concurrent/stale write를 차단했는가
|
||||
- [ ] `prepare-code-work`가 일반 plan/review 문서에 agent-ui 전용 completion section을 요구하지 않았는가
|
||||
- [ ] `reconcile-completion`이 exact completion log, code path, verification requirement를 확인했는가
|
||||
- [ ] `reconcile-completion`이 `update-agent-ui` 다음 `validate-agent-ui sync-intent=skip` 순서로 실행했는가
|
||||
- [ ] reconcile 실패 시 pending entry를 유지하고 성공 시에만 제거했는가
|
||||
- [ ] reconcile 성공과 idempotency를 `reconciled_code_work`로 판정했는가
|
||||
- [ ] Milestone mapping은 roadmap 문서가 아니라 `pending_milestone_work`에만 기록했는가
|
||||
- [ ] Milestone reconcile 전에 `complete-milestone check-only`의 closure-ready 근거를 확인했는가
|
||||
- [ ] Milestone reconcile 성공 뒤에만 caller/router가 `complete-milestone close`로 진행하는가
|
||||
- [ ] 검증되지 않은 `sync-result-head`로 `last_synced_head`를 바꾸지 않았는가
|
||||
- [ ] `가정` 또는 `불명확` 항목을 코드로 반영하지 않았는가
|
||||
- [ ] `direct-sync`로 코드 반영된 항목의 status가 `구현됨`이고 code evidence가 있는가
|
||||
- [ ] `direct-sync` 관련 검증이 통과했는가
|
||||
- [ ] 실패 또는 차단 시 commit/push와 `.sync-state.json` 갱신을 하지 않았는가
|
||||
- [ ] 실패 또는 차단 시 재개 진입점과 남은 변경 파일이 USER_REVIEW에 기록되었는가
|
||||
- [ ] `direct-sync` 성공 시 sync 결과 commit과 `.sync-state.json` commit이 분리되었는가
|
||||
- [ ] `direct-sync` 성공 시 `.sync-state.json.last_synced_head`가 sync 결과 commit hash를 가리키는가
|
||||
- [ ] direct-sync/baseline state 갱신도 helper를 사용해 code/Milestone pending·reconciled 기록을 보존했는가
|
||||
- [ ] unrelated dirty file이 sync commit에 포함되지 않았는가
|
||||
- 검증 실패 시: 에이전트가 해결할 수 없으면 `agent-ui/USER_REVIEW.md`에 남기고 중단한다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```md
|
||||
## agent-ui 코드 동기화 결과: <PASS|PLAN_REQUIRED|MILESTONE_REQUIRED|PREPARED|RECONCILED|ALREADY_RECONCILED|USER_REVIEW|FAIL>
|
||||
|
||||
- Mode: <incremental|full|prepare-code-work|reconcile-completion|prepare-milestone-work|reconcile-milestone-completion>
|
||||
- Scope: <scope>
|
||||
- Execution Route: <direct-sync|plan-required|milestone-required|not-applicable>
|
||||
- Task Mapping: <task-path와 pending 상태 또는 없음>
|
||||
- Milestone Mapping: <milestone-path와 pending 상태 또는 없음>
|
||||
- Completion Log: <path 또는 없음>
|
||||
- Closure Evidence: <Milestone check-only 근거 또는 없음>
|
||||
- Agent UI Changes: <파일 목록 또는 없음>
|
||||
- Code Changes: <파일 목록 또는 없음>
|
||||
- Status Updates: <구현됨 전환 목록 또는 없음>
|
||||
- Verification: <명령과 결과>
|
||||
- Sync Commit: <hash 또는 없음>
|
||||
- Sync State Commit/Push: <완료/생략/실패>
|
||||
- State Transition: <prepared|already_prepared|replaced|rebound|reconciled|already_reconciled|없음>
|
||||
- USER_REVIEW: <생성/갱신/없음>
|
||||
- Remaining Issues: <목록 또는 없음>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- `validate-agent-ui`를 거치지 않고 코드 동기화를 시작하지 않는다.
|
||||
- 미해결 USER_REVIEW가 있는 범위를 코드에 반영하지 않는다.
|
||||
- `가정` 또는 `불명확` 상태 항목을 코드로 구현하지 않는다.
|
||||
- `plan-required` 또는 `milestone-required`로 판정된 작업을 같은 `sync-agent-ui` 실행에서 직접 구현하지 않는다.
|
||||
- 일반 plan/review/complete.log에 agent-ui 전용 completion schema나 status 전환 책임을 추가하지 않는다.
|
||||
- 일반 Milestone 문서나 roadmap 스킬에 agent-ui 전용 완료 필드나 status 전환 책임을 추가하지 않는다.
|
||||
- code/Milestone pending entry가 소유한 status/frame path를 direct sync로 반영하거나 `record-sync`하지 않는다.
|
||||
- matching pending entry 없이 `complete.log`만 보고 agent-ui 문서를 추측해 갱신하지 않는다.
|
||||
- frame-view 문서에 `status`를 추가하거나 `구현됨` 전환을 적용하지 않는다.
|
||||
- `.sync-state.json`을 bundled helper 밖에서 수동 read-modify-write하지 않는다.
|
||||
- refinement/reindex 뒤 이전 task path의 pending entry를 남기거나 같은 status/frame path를 여러 pending task에 중복 배정하지 않는다.
|
||||
- reconcile 실패 시 pending entry를 제거하거나 `last_synced_head`를 추정하지 않는다.
|
||||
- `complete-milestone check-only` 종료 가능 근거 없이 Milestone pending entry를 reconcile하거나 close를 계속하지 않는다.
|
||||
- `execution-route=milestone-required`로 라우팅된 agent-ui 코드 작업의 일반 plan 완료만으로 agent-ui status를 일괄 `구현됨`으로 바꾸지 않는다. 종료 감사와 code evidence가 있는 항목만 반영한다.
|
||||
- 검증 실패나 사용자 판단 차단 상태에서 commit/push하지 않는다.
|
||||
- `.sync-state.json`을 agent-ui 변경분 판정 대상으로 삼지 않는다.
|
||||
- 정의서와 충돌하는 wireframe만을 근거로 코드 구현을 확정하지 않는다.
|
||||
- 실패한 sync의 작업트리 변경을 사용자 결정 없이 되돌리지 않는다.
|
||||
|
|
@ -1,903 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Atomically manage plan- and Milestone-required agent-ui work mappings."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import fcntl
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import stat
|
||||
import tempfile
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime
|
||||
from functools import wraps
|
||||
from pathlib import Path, PurePosixPath
|
||||
from typing import Any
|
||||
|
||||
|
||||
SCHEMA_VERSION = 4
|
||||
SHA_PATTERN = re.compile(r"^(?:[0-9a-f]{40}|[0-9a-f]{64})$")
|
||||
STATUS_PATH_PATTERN = re.compile(
|
||||
r"^agent-ui/definition/(?:views|components)/[a-z0-9][a-z0-9/-]*/index\.md$"
|
||||
)
|
||||
FRAME_PATH_PATTERN = re.compile(
|
||||
r"^agent-ui/frame/views/[a-z0-9][a-z0-9/-]*/index\.md$"
|
||||
)
|
||||
SCOPE_PATTERN = re.compile(r"^(?:all|view:[a-z0-9][a-z0-9-]*|component:[a-z0-9][a-z0-9/-]*)$")
|
||||
MILESTONE_PATH_PATTERN = re.compile(
|
||||
r"^agent-roadmap/phase/[a-z0-9][a-z0-9-]*/milestones/"
|
||||
r"[a-z0-9][a-z0-9-]*\.md$"
|
||||
)
|
||||
|
||||
|
||||
class StateError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
@contextmanager
|
||||
def _state_lock(path: Path):
|
||||
directory_fd = os.open(path.parent, os.O_RDONLY | os.O_DIRECTORY)
|
||||
try:
|
||||
fcntl.flock(directory_fd, fcntl.LOCK_EX)
|
||||
yield
|
||||
finally:
|
||||
fcntl.flock(directory_fd, fcntl.LOCK_UN)
|
||||
os.close(directory_fd)
|
||||
|
||||
|
||||
def _locked_state_command(handler):
|
||||
@wraps(handler)
|
||||
def wrapped(args: argparse.Namespace) -> dict[str, Any]:
|
||||
with _state_lock(args.state):
|
||||
return handler(args)
|
||||
|
||||
return wrapped
|
||||
|
||||
|
||||
def _stable_unique(values: list[str]) -> list[str]:
|
||||
return list(dict.fromkeys(values))
|
||||
|
||||
|
||||
def _path_trees_overlap(left: str, right: str) -> bool:
|
||||
left_path = PurePosixPath(left)
|
||||
right_path = PurePosixPath(right)
|
||||
return (
|
||||
left_path == right_path
|
||||
or left_path in right_path.parents
|
||||
or right_path in left_path.parents
|
||||
)
|
||||
|
||||
|
||||
def _require_relative_path(value: str, *, prefix: str | None = None) -> str:
|
||||
path = PurePosixPath(value)
|
||||
if not value or path.is_absolute() or ".." in path.parts or "." in path.parts:
|
||||
raise StateError(f"invalid repository-relative path: {value!r}")
|
||||
normalized = path.as_posix()
|
||||
if prefix and not normalized.startswith(prefix):
|
||||
raise StateError(f"path must start with {prefix!r}: {value!r}")
|
||||
return normalized
|
||||
|
||||
|
||||
def _require_task_path(value: str) -> str:
|
||||
normalized = _require_relative_path(value, prefix="agent-task/")
|
||||
if normalized == "agent-task" or normalized.startswith("agent-task/archive/"):
|
||||
raise StateError(f"task path must be the original active path: {value!r}")
|
||||
return normalized.rstrip("/")
|
||||
|
||||
|
||||
def _require_milestone_path(value: str) -> str:
|
||||
normalized = _require_relative_path(value, prefix="agent-roadmap/phase/")
|
||||
if not MILESTONE_PATH_PATTERN.fullmatch(normalized):
|
||||
raise StateError(f"milestone path must be an active Milestone document: {value!r}")
|
||||
return normalized
|
||||
|
||||
|
||||
def _require_timestamp(value: str) -> str:
|
||||
try:
|
||||
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
|
||||
except ValueError as exc:
|
||||
raise StateError(f"invalid ISO-8601 timestamp: {value!r}") from exc
|
||||
if parsed.tzinfo is None:
|
||||
raise StateError(f"timestamp must include a timezone: {value!r}")
|
||||
return value
|
||||
|
||||
|
||||
def _require_string_list(value: Any, *, field: str) -> list[str]:
|
||||
if not isinstance(value, list) or not all(isinstance(item, str) and item for item in value):
|
||||
raise StateError(f"{field} must be a list of non-empty strings")
|
||||
return _stable_unique(value)
|
||||
|
||||
|
||||
def _require_object_list(value: Any, *, field: str) -> list[dict[str, Any]]:
|
||||
if not isinstance(value, list) or not all(isinstance(item, dict) for item in value):
|
||||
raise StateError(f"{field} must be a list of objects")
|
||||
return value
|
||||
|
||||
|
||||
def _normalize_pending_entry(raw: Any) -> dict[str, Any]:
|
||||
if not isinstance(raw, dict):
|
||||
raise StateError("pending_code_work entries must be objects")
|
||||
|
||||
legacy_paths = _require_string_list(raw.get("agent_ui_paths", []), field="agent_ui_paths")
|
||||
status_paths = _require_string_list(raw.get("status_paths", []), field="status_paths")
|
||||
frame_paths = _require_string_list(raw.get("frame_paths", []), field="frame_paths")
|
||||
if legacy_paths:
|
||||
status_paths.extend(path for path in legacy_paths if not path.startswith("agent-ui/frame/"))
|
||||
frame_paths.extend(path for path in legacy_paths if path.startswith("agent-ui/frame/"))
|
||||
|
||||
status_paths = [
|
||||
_require_relative_path(path, prefix="agent-ui/definition/")
|
||||
for path in _stable_unique(status_paths)
|
||||
]
|
||||
frame_paths = [
|
||||
_require_relative_path(path, prefix="agent-ui/frame/")
|
||||
for path in _stable_unique(frame_paths)
|
||||
]
|
||||
if not status_paths:
|
||||
raise StateError("pending_code_work requires at least one status_path")
|
||||
if not all(STATUS_PATH_PATTERN.fullmatch(path) for path in status_paths):
|
||||
raise StateError("status_paths must be active view/component index.md paths")
|
||||
if not all(FRAME_PATH_PATTERN.fullmatch(path) for path in frame_paths):
|
||||
raise StateError("frame_paths must be active frame-view index.md paths")
|
||||
if set(status_paths) & set(frame_paths):
|
||||
raise StateError("status_paths and frame_paths must be disjoint")
|
||||
|
||||
code_paths = [
|
||||
_require_relative_path(path)
|
||||
for path in _require_string_list(raw.get("code_paths", []), field="code_paths")
|
||||
]
|
||||
if not code_paths:
|
||||
raise StateError("pending_code_work requires at least one code_path")
|
||||
if any(path.startswith(("agent-ui/", "agent-task/")) for path in code_paths):
|
||||
raise StateError("code_paths must not point to agent-ui or agent-task artifacts")
|
||||
|
||||
scope = str(raw.get("scope", "")).strip() or "all"
|
||||
if not SCOPE_PATTERN.fullmatch(scope):
|
||||
raise StateError(f"invalid sync scope: {scope!r}")
|
||||
|
||||
return {
|
||||
"task_path": _require_task_path(str(raw.get("task_path", ""))),
|
||||
"scope": scope,
|
||||
"status_paths": status_paths,
|
||||
"frame_paths": frame_paths,
|
||||
"code_paths": code_paths,
|
||||
"verification_requirements": _require_string_list(
|
||||
raw.get("verification_requirements", []),
|
||||
field="verification_requirements",
|
||||
),
|
||||
"prepared_at": _require_timestamp(str(raw.get("prepared_at", ""))),
|
||||
"state": "pending",
|
||||
}
|
||||
|
||||
|
||||
def _normalize_pending_milestone_entry(raw: Any) -> dict[str, Any]:
|
||||
if not isinstance(raw, dict):
|
||||
raise StateError("pending_milestone_work entries must be objects")
|
||||
entry = _normalize_pending_entry(
|
||||
{
|
||||
**raw,
|
||||
"task_path": "agent-task/milestone-placeholder",
|
||||
}
|
||||
)
|
||||
return {
|
||||
"milestone_path": _require_milestone_path(str(raw.get("milestone_path", ""))),
|
||||
"scope": entry["scope"],
|
||||
"status_paths": entry["status_paths"],
|
||||
"frame_paths": entry["frame_paths"],
|
||||
"code_paths": entry["code_paths"],
|
||||
"verification_requirements": entry["verification_requirements"],
|
||||
"prepared_at": entry["prepared_at"],
|
||||
"state": "pending",
|
||||
}
|
||||
|
||||
|
||||
def _normalize_reconciled_entry(raw: Any) -> dict[str, Any]:
|
||||
if not isinstance(raw, dict):
|
||||
raise StateError("reconciled_code_work entries must be objects")
|
||||
scope = str(raw.get("scope", "")).strip() or "all"
|
||||
if not SCOPE_PATTERN.fullmatch(scope):
|
||||
raise StateError(f"invalid reconciled sync scope: {scope!r}")
|
||||
entry = {
|
||||
"task_path": _require_task_path(str(raw.get("task_path", ""))),
|
||||
"completion_log": _require_relative_path(
|
||||
str(raw.get("completion_log", "")),
|
||||
prefix="agent-task/archive/",
|
||||
),
|
||||
"scope": scope,
|
||||
"status_paths": [
|
||||
_require_relative_path(path, prefix="agent-ui/definition/")
|
||||
for path in _require_string_list(raw.get("status_paths", []), field="status_paths")
|
||||
],
|
||||
"frame_paths": [
|
||||
_require_relative_path(path, prefix="agent-ui/frame/")
|
||||
for path in _require_string_list(raw.get("frame_paths", []), field="frame_paths")
|
||||
],
|
||||
"code_paths": [
|
||||
_require_relative_path(path)
|
||||
for path in _require_string_list(raw.get("code_paths", []), field="code_paths")
|
||||
],
|
||||
"validation_evidence": str(raw.get("validation_evidence", "")).strip(),
|
||||
"reconciled_at": _require_timestamp(str(raw.get("reconciled_at", ""))),
|
||||
"sync_result_head": raw.get("sync_result_head"),
|
||||
}
|
||||
if not entry["status_paths"] or not entry["code_paths"] or not entry["validation_evidence"]:
|
||||
raise StateError("reconciled_code_work entry is incomplete")
|
||||
if not all(STATUS_PATH_PATTERN.fullmatch(path) for path in entry["status_paths"]):
|
||||
raise StateError("reconciled status_paths must be active view/component index.md paths")
|
||||
if not all(FRAME_PATH_PATTERN.fullmatch(path) for path in entry["frame_paths"]):
|
||||
raise StateError("reconciled frame_paths must be active frame-view index.md paths")
|
||||
if any(path.startswith(("agent-ui/", "agent-task/")) for path in entry["code_paths"]):
|
||||
raise StateError("reconciled code_paths must not point to agent-ui or agent-task artifacts")
|
||||
if entry["sync_result_head"] is not None and not SHA_PATTERN.fullmatch(
|
||||
str(entry["sync_result_head"])
|
||||
):
|
||||
raise StateError("sync_result_head must be a 40- or 64-character lowercase hex hash")
|
||||
return entry
|
||||
|
||||
|
||||
def _normalize_reconciled_milestone_entry(raw: Any) -> dict[str, Any]:
|
||||
if not isinstance(raw, dict):
|
||||
raise StateError("reconciled_milestone_work entries must be objects")
|
||||
synthetic = _normalize_reconciled_entry(
|
||||
{
|
||||
**raw,
|
||||
"task_path": "agent-task/milestone-placeholder",
|
||||
"completion_log": "agent-task/archive/2000/01/milestone-placeholder/complete.log",
|
||||
}
|
||||
)
|
||||
closure_evidence = str(raw.get("closure_evidence", "")).strip()
|
||||
if not closure_evidence:
|
||||
raise StateError("reconciled_milestone_work requires closure_evidence")
|
||||
return {
|
||||
"milestone_path": _require_milestone_path(str(raw.get("milestone_path", ""))),
|
||||
"closure_evidence": closure_evidence,
|
||||
"scope": synthetic["scope"],
|
||||
"status_paths": synthetic["status_paths"],
|
||||
"frame_paths": synthetic["frame_paths"],
|
||||
"code_paths": synthetic["code_paths"],
|
||||
"validation_evidence": synthetic["validation_evidence"],
|
||||
"reconciled_at": synthetic["reconciled_at"],
|
||||
"sync_result_head": synthetic["sync_result_head"],
|
||||
}
|
||||
|
||||
|
||||
def _normalize_state(raw: Any) -> dict[str, Any]:
|
||||
if not isinstance(raw, dict):
|
||||
raise StateError("sync state must be a JSON object")
|
||||
version = raw.get("schema_version")
|
||||
if version not in {1, 2, 3, 4}:
|
||||
raise StateError(f"unsupported schema_version: {version!r}")
|
||||
|
||||
state = dict(raw)
|
||||
state["schema_version"] = SCHEMA_VERSION
|
||||
state["pending_code_work"] = [
|
||||
_normalize_pending_entry(entry)
|
||||
for entry in _require_object_list(
|
||||
raw.get("pending_code_work", []),
|
||||
field="pending_code_work",
|
||||
)
|
||||
]
|
||||
state["reconciled_code_work"] = [
|
||||
_normalize_reconciled_entry(entry)
|
||||
for entry in _require_object_list(
|
||||
raw.get("reconciled_code_work", []),
|
||||
field="reconciled_code_work",
|
||||
)
|
||||
]
|
||||
state["pending_milestone_work"] = [
|
||||
_normalize_pending_milestone_entry(entry)
|
||||
for entry in _require_object_list(
|
||||
raw.get("pending_milestone_work", []),
|
||||
field="pending_milestone_work",
|
||||
)
|
||||
]
|
||||
state["reconciled_milestone_work"] = [
|
||||
_normalize_reconciled_milestone_entry(entry)
|
||||
for entry in _require_object_list(
|
||||
raw.get("reconciled_milestone_work", []),
|
||||
field="reconciled_milestone_work",
|
||||
)
|
||||
]
|
||||
pending_keys = [entry["task_path"] for entry in state["pending_code_work"]]
|
||||
if len(pending_keys) != len(set(pending_keys)):
|
||||
raise StateError("pending_code_work contains duplicate task_path values")
|
||||
milestone_keys = [
|
||||
entry["milestone_path"] for entry in state["pending_milestone_work"]
|
||||
]
|
||||
if len(milestone_keys) != len(set(milestone_keys)):
|
||||
raise StateError("pending_milestone_work contains duplicate milestone_path values")
|
||||
pending_entries = state["pending_code_work"] + state["pending_milestone_work"]
|
||||
pending_status_paths = [
|
||||
path for entry in pending_entries for path in entry["status_paths"]
|
||||
]
|
||||
if len(pending_status_paths) != len(set(pending_status_paths)):
|
||||
raise StateError("pending work assigns one status_path to multiple owners")
|
||||
pending_frame_paths = [
|
||||
path for entry in pending_entries for path in entry["frame_paths"]
|
||||
]
|
||||
if len(pending_frame_paths) != len(set(pending_frame_paths)):
|
||||
raise StateError("pending work assigns one frame_path to multiple owners")
|
||||
reconciled_keys = [
|
||||
(entry["task_path"], entry["completion_log"])
|
||||
for entry in state["reconciled_code_work"]
|
||||
]
|
||||
if len(reconciled_keys) != len(set(reconciled_keys)):
|
||||
raise StateError("reconciled_code_work contains duplicate task/completion pairs")
|
||||
reconciled_milestone_keys = [
|
||||
(entry["milestone_path"], entry["closure_evidence"])
|
||||
for entry in state["reconciled_milestone_work"]
|
||||
]
|
||||
if len(reconciled_milestone_keys) != len(set(reconciled_milestone_keys)):
|
||||
raise StateError(
|
||||
"reconciled_milestone_work contains duplicate milestone/evidence pairs"
|
||||
)
|
||||
notes = raw.get("notes", [])
|
||||
state["notes"] = _require_string_list(notes, field="notes")
|
||||
return state
|
||||
|
||||
|
||||
def _load_state(path: Path, expected_sha256: str) -> tuple[dict[str, Any], str]:
|
||||
if not path.is_file():
|
||||
raise StateError(f"sync state does not exist: {path}")
|
||||
if not re.fullmatch(r"[0-9a-f]{64}", expected_sha256):
|
||||
raise StateError("expected_sha256 must be a 64-character lowercase hex digest")
|
||||
payload = path.read_bytes()
|
||||
actual_sha256 = hashlib.sha256(payload).hexdigest()
|
||||
if actual_sha256 != expected_sha256:
|
||||
raise StateError(
|
||||
"sync state changed after inspection: "
|
||||
f"expected={expected_sha256} actual={actual_sha256}"
|
||||
)
|
||||
try:
|
||||
raw = json.loads(payload)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise StateError(f"invalid sync state JSON: {exc}") from exc
|
||||
return _normalize_state(raw), actual_sha256
|
||||
|
||||
|
||||
def _write_state(path: Path, state: dict[str, Any]) -> str:
|
||||
payload = (json.dumps(state, ensure_ascii=False, indent=2) + "\n").encode()
|
||||
mode = stat.S_IMODE(path.stat().st_mode)
|
||||
temporary: Path | None = None
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(dir=path.parent, delete=False) as handle:
|
||||
temporary = Path(handle.name)
|
||||
handle.write(payload)
|
||||
handle.flush()
|
||||
os.fsync(handle.fileno())
|
||||
os.chmod(temporary, mode)
|
||||
os.replace(temporary, path)
|
||||
temporary = None
|
||||
directory_fd = os.open(path.parent, os.O_RDONLY | os.O_DIRECTORY)
|
||||
try:
|
||||
os.fsync(directory_fd)
|
||||
finally:
|
||||
os.close(directory_fd)
|
||||
finally:
|
||||
if temporary is not None:
|
||||
temporary.unlink(missing_ok=True)
|
||||
return hashlib.sha256(payload).hexdigest()
|
||||
|
||||
|
||||
def _pending_entry_from_args(args: argparse.Namespace) -> dict[str, Any]:
|
||||
return _normalize_pending_entry(
|
||||
{
|
||||
"task_path": args.task_path,
|
||||
"scope": args.scope,
|
||||
"status_paths": args.status_path,
|
||||
"frame_paths": args.frame_path,
|
||||
"code_paths": args.code_path,
|
||||
"verification_requirements": args.verification_requirement,
|
||||
"prepared_at": args.prepared_at,
|
||||
"state": "pending",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _pending_milestone_entry_from_args(args: argparse.Namespace) -> dict[str, Any]:
|
||||
return _normalize_pending_milestone_entry(
|
||||
{
|
||||
"milestone_path": args.milestone_path,
|
||||
"scope": args.scope,
|
||||
"status_paths": args.status_path,
|
||||
"frame_paths": args.frame_path,
|
||||
"code_paths": args.code_path,
|
||||
"verification_requirements": args.verification_requirement,
|
||||
"prepared_at": args.prepared_at,
|
||||
"state": "pending",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@_locked_state_command
|
||||
def _prepare(args: argparse.Namespace) -> dict[str, Any]:
|
||||
state, before_sha256 = _load_state(args.state, args.expected_sha256)
|
||||
requested = _pending_entry_from_args(args)
|
||||
previous_task_path = (
|
||||
_require_task_path(args.previous_task_path) if args.previous_task_path else None
|
||||
)
|
||||
if previous_task_path == requested["task_path"]:
|
||||
raise StateError("previous_task_path must differ from task_path")
|
||||
matches = [
|
||||
index
|
||||
for index, entry in enumerate(state["pending_code_work"])
|
||||
if entry["task_path"] == requested["task_path"]
|
||||
]
|
||||
if len(matches) > 1:
|
||||
raise StateError(f"multiple pending entries for {requested['task_path']}")
|
||||
|
||||
if previous_task_path is not None:
|
||||
previous_matches = [
|
||||
index
|
||||
for index, entry in enumerate(state["pending_code_work"])
|
||||
if entry["task_path"] == previous_task_path
|
||||
]
|
||||
if len(previous_matches) != 1:
|
||||
raise StateError(
|
||||
f"expected exactly one previous pending entry for {previous_task_path}, "
|
||||
f"found {len(previous_matches)}"
|
||||
)
|
||||
if matches:
|
||||
raise StateError(f"new task_path already has a pending entry: {requested['task_path']}")
|
||||
existing = state["pending_code_work"][previous_matches[0]]
|
||||
semantic_fields = (
|
||||
"scope",
|
||||
"status_paths",
|
||||
"frame_paths",
|
||||
"code_paths",
|
||||
"verification_requirements",
|
||||
"state",
|
||||
)
|
||||
changed = any(existing[field] != requested[field] for field in semantic_fields)
|
||||
if changed and not args.replace:
|
||||
raise StateError(
|
||||
"rebound mapping changes scope or evidence; verify the closure child "
|
||||
"and rerun with --replace"
|
||||
)
|
||||
del state["pending_code_work"][previous_matches[0]]
|
||||
state["pending_code_work"].append(requested)
|
||||
status = "rebound"
|
||||
elif matches:
|
||||
index = matches[0]
|
||||
existing = state["pending_code_work"][index]
|
||||
semantic_fields = (
|
||||
"task_path",
|
||||
"scope",
|
||||
"status_paths",
|
||||
"frame_paths",
|
||||
"code_paths",
|
||||
"verification_requirements",
|
||||
"state",
|
||||
)
|
||||
if all(existing[field] == requested[field] for field in semantic_fields):
|
||||
status = "already_prepared"
|
||||
elif args.replace:
|
||||
state["pending_code_work"][index] = requested
|
||||
status = "replaced"
|
||||
else:
|
||||
raise StateError(
|
||||
f"pending entry differs for {requested['task_path']}; "
|
||||
"verify the new plan scope and rerun with --replace"
|
||||
)
|
||||
else:
|
||||
state["pending_code_work"].append(requested)
|
||||
status = "prepared"
|
||||
|
||||
state = _normalize_state(state)
|
||||
after_sha256 = _write_state(args.state, state)
|
||||
return {
|
||||
"status": status,
|
||||
"task_path": requested["task_path"],
|
||||
"previous_task_path": previous_task_path,
|
||||
"before_sha256": before_sha256,
|
||||
"after_sha256": after_sha256,
|
||||
}
|
||||
|
||||
|
||||
@_locked_state_command
|
||||
def _prepare_milestone(args: argparse.Namespace) -> dict[str, Any]:
|
||||
state, before_sha256 = _load_state(args.state, args.expected_sha256)
|
||||
requested = _pending_milestone_entry_from_args(args)
|
||||
if not Path(requested["milestone_path"]).is_file():
|
||||
raise StateError(
|
||||
f"active Milestone does not exist: {requested['milestone_path']}"
|
||||
)
|
||||
matches = [
|
||||
index
|
||||
for index, entry in enumerate(state["pending_milestone_work"])
|
||||
if entry["milestone_path"] == requested["milestone_path"]
|
||||
]
|
||||
if len(matches) > 1:
|
||||
raise StateError(
|
||||
f"multiple pending entries for {requested['milestone_path']}"
|
||||
)
|
||||
|
||||
if matches:
|
||||
index = matches[0]
|
||||
existing = state["pending_milestone_work"][index]
|
||||
semantic_fields = (
|
||||
"milestone_path",
|
||||
"scope",
|
||||
"status_paths",
|
||||
"frame_paths",
|
||||
"code_paths",
|
||||
"verification_requirements",
|
||||
"state",
|
||||
)
|
||||
if all(existing[field] == requested[field] for field in semantic_fields):
|
||||
status = "already_prepared"
|
||||
elif args.replace:
|
||||
state["pending_milestone_work"][index] = requested
|
||||
status = "replaced"
|
||||
else:
|
||||
raise StateError(
|
||||
f"pending entry differs for {requested['milestone_path']}; "
|
||||
"verify the Milestone scope and rerun with --replace"
|
||||
)
|
||||
else:
|
||||
state["pending_milestone_work"].append(requested)
|
||||
status = "prepared"
|
||||
|
||||
state = _normalize_state(state)
|
||||
after_sha256 = _write_state(args.state, state)
|
||||
return {
|
||||
"status": status,
|
||||
"milestone_path": requested["milestone_path"],
|
||||
"before_sha256": before_sha256,
|
||||
"after_sha256": after_sha256,
|
||||
}
|
||||
|
||||
|
||||
def _completion_log_location(path: Path) -> tuple[Path, str]:
|
||||
workspace = Path.cwd().resolve()
|
||||
resolved = path.resolve()
|
||||
try:
|
||||
relative = resolved.relative_to(workspace)
|
||||
except ValueError as exc:
|
||||
raise StateError(f"completion log is outside the current workspace: {path}") from exc
|
||||
normalized = _require_relative_path(relative.as_posix(), prefix="agent-task/archive/")
|
||||
return resolved, normalized
|
||||
|
||||
|
||||
def _validate_completion_log(path: Path, task_path: str) -> str:
|
||||
resolved, normalized = _completion_log_location(path)
|
||||
if not resolved.is_file():
|
||||
raise StateError(f"completion log does not exist: {path}")
|
||||
|
||||
archive_parts = PurePosixPath(normalized).parts
|
||||
if len(archive_parts) < 6 or archive_parts[-1] != "complete.log":
|
||||
raise StateError("completion log must be under agent-task/archive/YYYY/MM/<task>/")
|
||||
if not re.fullmatch(r"[0-9]{4}", archive_parts[2]) or not re.fullmatch(
|
||||
r"(?:0[1-9]|1[0-2])",
|
||||
archive_parts[3],
|
||||
):
|
||||
raise StateError("completion log archive path must contain YYYY/MM")
|
||||
archived_task_parts = archive_parts[4:-1]
|
||||
original_task_parts = PurePosixPath(task_path.removeprefix("agent-task/")).parts
|
||||
same_parent = archived_task_parts[:-1] == original_task_parts[:-1]
|
||||
final_name = archived_task_parts[-1] if archived_task_parts else ""
|
||||
original_final_name = original_task_parts[-1]
|
||||
suffix_match = re.fullmatch(re.escape(original_final_name) + r"(?:_[0-9]+)?", final_name)
|
||||
if not same_parent or suffix_match is None:
|
||||
raise StateError("completion log archive path does not match task_path")
|
||||
|
||||
text = resolved.read_text()
|
||||
task_name = task_path.removeprefix("agent-task/")
|
||||
if f"# Complete - {task_name}" not in text.splitlines()[:3]:
|
||||
raise StateError("completion log task header does not match task_path")
|
||||
if "## 루프 이력" not in text:
|
||||
raise StateError("completion log has no loop history")
|
||||
terminal = re.compile(r"^\|[^|]*\|[^|]*\|\s*(?:PASS|RESOLVED|PASS/RESOLVED)\s*\|", re.MULTILINE)
|
||||
if not terminal.search(text):
|
||||
raise StateError("completion log has no terminal PASS/RESOLVED row")
|
||||
return normalized
|
||||
|
||||
|
||||
@_locked_state_command
|
||||
def _reconcile(args: argparse.Namespace) -> dict[str, Any]:
|
||||
state, before_sha256 = _load_state(args.state, args.expected_sha256)
|
||||
task_path = _require_task_path(args.task_path)
|
||||
completion_log = _validate_completion_log(args.completion_log, task_path)
|
||||
|
||||
completed = [
|
||||
entry
|
||||
for entry in state["reconciled_code_work"]
|
||||
if entry["task_path"] == task_path and entry["completion_log"] == completion_log
|
||||
]
|
||||
if completed:
|
||||
state = _normalize_state(state)
|
||||
after_sha256 = _write_state(args.state, state)
|
||||
return {
|
||||
"status": "already_reconciled",
|
||||
"task_path": task_path,
|
||||
"before_sha256": before_sha256,
|
||||
"after_sha256": after_sha256,
|
||||
}
|
||||
|
||||
matches = [
|
||||
index
|
||||
for index, entry in enumerate(state["pending_code_work"])
|
||||
if entry["task_path"] == task_path
|
||||
]
|
||||
if len(matches) != 1:
|
||||
raise StateError(f"expected exactly one pending entry for {task_path}, found {len(matches)}")
|
||||
pending = state["pending_code_work"][matches[0]]
|
||||
|
||||
sync_result_head = args.sync_result_head
|
||||
if sync_result_head is not None and not SHA_PATTERN.fullmatch(sync_result_head):
|
||||
raise StateError("sync_result_head must be a 40- or 64-character lowercase hex hash")
|
||||
reconciled = _normalize_reconciled_entry(
|
||||
{
|
||||
"task_path": task_path,
|
||||
"completion_log": completion_log,
|
||||
"scope": pending["scope"],
|
||||
"status_paths": pending["status_paths"],
|
||||
"frame_paths": pending["frame_paths"],
|
||||
"code_paths": pending["code_paths"],
|
||||
"validation_evidence": args.validation_evidence,
|
||||
"reconciled_at": args.reconciled_at,
|
||||
"sync_result_head": sync_result_head,
|
||||
}
|
||||
)
|
||||
|
||||
del state["pending_code_work"][matches[0]]
|
||||
state["reconciled_code_work"].append(reconciled)
|
||||
state["last_sync_mode"] = "plan-reconcile"
|
||||
state["last_synced_at"] = args.reconciled_at
|
||||
state["agent_ui_paths"] = pending["status_paths"] + pending["frame_paths"]
|
||||
state["code_paths"] = pending["code_paths"]
|
||||
if sync_result_head is not None:
|
||||
state["last_synced_head"] = sync_result_head
|
||||
baseline_evidence = f"baseline=updated:{sync_result_head}"
|
||||
else:
|
||||
baseline_evidence = "baseline=preserved:no validated sync_result_head"
|
||||
state["notes"].append(
|
||||
f"plan reconcile: task={task_path}; completion={completion_log}; "
|
||||
f"validation={args.validation_evidence}; {baseline_evidence}"
|
||||
)
|
||||
|
||||
state = _normalize_state(state)
|
||||
after_sha256 = _write_state(args.state, state)
|
||||
return {
|
||||
"status": "reconciled",
|
||||
"task_path": task_path,
|
||||
"before_sha256": before_sha256,
|
||||
"after_sha256": after_sha256,
|
||||
}
|
||||
|
||||
|
||||
@_locked_state_command
|
||||
def _reconcile_milestone(args: argparse.Namespace) -> dict[str, Any]:
|
||||
state, before_sha256 = _load_state(args.state, args.expected_sha256)
|
||||
milestone_path = _require_milestone_path(args.milestone_path)
|
||||
closure_evidence = args.closure_evidence.strip()
|
||||
if not closure_evidence:
|
||||
raise StateError("closure_evidence must be non-empty")
|
||||
|
||||
matches = [
|
||||
index
|
||||
for index, entry in enumerate(state["pending_milestone_work"])
|
||||
if entry["milestone_path"] == milestone_path
|
||||
]
|
||||
if not matches:
|
||||
completed = [
|
||||
entry
|
||||
for entry in state["reconciled_milestone_work"]
|
||||
if entry["milestone_path"] == milestone_path
|
||||
and entry["closure_evidence"] == closure_evidence
|
||||
]
|
||||
if completed:
|
||||
state = _normalize_state(state)
|
||||
after_sha256 = _write_state(args.state, state)
|
||||
return {
|
||||
"status": "already_reconciled",
|
||||
"milestone_path": milestone_path,
|
||||
"before_sha256": before_sha256,
|
||||
"after_sha256": after_sha256,
|
||||
}
|
||||
if len(matches) != 1:
|
||||
raise StateError(
|
||||
f"expected exactly one pending entry for {milestone_path}, "
|
||||
f"found {len(matches)}"
|
||||
)
|
||||
if not Path(milestone_path).is_file():
|
||||
raise StateError(f"active Milestone does not exist: {milestone_path}")
|
||||
pending = state["pending_milestone_work"][matches[0]]
|
||||
|
||||
sync_result_head = args.sync_result_head
|
||||
if sync_result_head is not None and not SHA_PATTERN.fullmatch(sync_result_head):
|
||||
raise StateError("sync_result_head must be a 40- or 64-character lowercase hex hash")
|
||||
reconciled = _normalize_reconciled_milestone_entry(
|
||||
{
|
||||
"milestone_path": milestone_path,
|
||||
"closure_evidence": closure_evidence,
|
||||
"scope": pending["scope"],
|
||||
"status_paths": pending["status_paths"],
|
||||
"frame_paths": pending["frame_paths"],
|
||||
"code_paths": pending["code_paths"],
|
||||
"validation_evidence": args.validation_evidence,
|
||||
"reconciled_at": args.reconciled_at,
|
||||
"sync_result_head": sync_result_head,
|
||||
}
|
||||
)
|
||||
|
||||
del state["pending_milestone_work"][matches[0]]
|
||||
state["reconciled_milestone_work"].append(reconciled)
|
||||
state["last_sync_mode"] = "milestone-reconcile"
|
||||
state["last_synced_at"] = args.reconciled_at
|
||||
state["agent_ui_paths"] = pending["status_paths"] + pending["frame_paths"]
|
||||
state["code_paths"] = pending["code_paths"]
|
||||
if sync_result_head is not None:
|
||||
state["last_synced_head"] = sync_result_head
|
||||
baseline_evidence = f"baseline=updated:{sync_result_head}"
|
||||
else:
|
||||
baseline_evidence = "baseline=preserved:no validated sync_result_head"
|
||||
state["notes"].append(
|
||||
f"milestone reconcile: milestone={milestone_path}; "
|
||||
f"closure={closure_evidence}; validation={args.validation_evidence}; "
|
||||
f"{baseline_evidence}"
|
||||
)
|
||||
|
||||
state = _normalize_state(state)
|
||||
after_sha256 = _write_state(args.state, state)
|
||||
return {
|
||||
"status": "reconciled",
|
||||
"milestone_path": milestone_path,
|
||||
"before_sha256": before_sha256,
|
||||
"after_sha256": after_sha256,
|
||||
}
|
||||
|
||||
|
||||
@_locked_state_command
|
||||
def _record_sync(args: argparse.Namespace) -> dict[str, Any]:
|
||||
state, before_sha256 = _load_state(args.state, args.expected_sha256)
|
||||
if not SHA_PATTERN.fullmatch(args.sync_result_head):
|
||||
raise StateError("sync_result_head must be a 40- or 64-character lowercase hex hash")
|
||||
synced_at = _require_timestamp(args.synced_at)
|
||||
agent_ui_paths = [
|
||||
_require_relative_path(path, prefix="agent-ui/")
|
||||
for path in _stable_unique(args.agent_ui_path)
|
||||
]
|
||||
code_paths = [
|
||||
_require_relative_path(path) for path in _stable_unique(args.code_path)
|
||||
]
|
||||
if not agent_ui_paths:
|
||||
raise StateError("record-sync requires agent_ui_paths")
|
||||
if args.sync_mode in {"incremental", "full"} and not code_paths:
|
||||
raise StateError("incremental/full record-sync requires code_paths")
|
||||
if any(path.startswith(("agent-ui/", "agent-task/")) for path in code_paths):
|
||||
raise StateError("record-sync code_paths must not point to agent-ui or agent-task artifacts")
|
||||
if args.sync_mode in {"incremental", "full"}:
|
||||
pending_paths = {
|
||||
path
|
||||
for entry in state["pending_code_work"] + state["pending_milestone_work"]
|
||||
for path in entry["status_paths"] + entry["frame_paths"]
|
||||
}
|
||||
overlapping_paths = sorted(
|
||||
pending_path
|
||||
for pending_path in pending_paths
|
||||
if any(
|
||||
_path_trees_overlap(pending_path, sync_path)
|
||||
for sync_path in agent_ui_paths
|
||||
)
|
||||
)
|
||||
if overlapping_paths:
|
||||
raise StateError(
|
||||
"incremental/full record-sync overlaps pending work paths: "
|
||||
+ ", ".join(overlapping_paths)
|
||||
)
|
||||
|
||||
state["last_sync_mode"] = args.sync_mode
|
||||
state["last_synced_head"] = args.sync_result_head
|
||||
state["last_synced_at"] = synced_at
|
||||
state["agent_ui_paths"] = agent_ui_paths
|
||||
state["code_paths"] = code_paths
|
||||
state["notes"] = _stable_unique(state["notes"] + args.note)
|
||||
state = _normalize_state(state)
|
||||
after_sha256 = _write_state(args.state, state)
|
||||
return {
|
||||
"status": "sync_recorded",
|
||||
"before_sha256": before_sha256,
|
||||
"after_sha256": after_sha256,
|
||||
"sync_result_head": args.sync_result_head,
|
||||
}
|
||||
|
||||
|
||||
def _parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser()
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
prepare = subparsers.add_parser("prepare")
|
||||
prepare.add_argument("--state", type=Path, required=True)
|
||||
prepare.add_argument("--expected-sha256", required=True)
|
||||
prepare.add_argument("--task-path", required=True)
|
||||
prepare.add_argument("--previous-task-path")
|
||||
prepare.add_argument("--scope", default="all")
|
||||
prepare.add_argument("--status-path", action="append", default=[], required=True)
|
||||
prepare.add_argument("--frame-path", action="append", default=[])
|
||||
prepare.add_argument("--code-path", action="append", default=[], required=True)
|
||||
prepare.add_argument("--verification-requirement", action="append", default=[])
|
||||
prepare.add_argument("--prepared-at", required=True)
|
||||
prepare.add_argument("--replace", action="store_true")
|
||||
prepare.set_defaults(handler=_prepare)
|
||||
|
||||
prepare_milestone = subparsers.add_parser("prepare-milestone")
|
||||
prepare_milestone.add_argument("--state", type=Path, required=True)
|
||||
prepare_milestone.add_argument("--expected-sha256", required=True)
|
||||
prepare_milestone.add_argument("--milestone-path", required=True)
|
||||
prepare_milestone.add_argument("--scope", default="all")
|
||||
prepare_milestone.add_argument(
|
||||
"--status-path",
|
||||
action="append",
|
||||
default=[],
|
||||
required=True,
|
||||
)
|
||||
prepare_milestone.add_argument("--frame-path", action="append", default=[])
|
||||
prepare_milestone.add_argument(
|
||||
"--code-path",
|
||||
action="append",
|
||||
default=[],
|
||||
required=True,
|
||||
)
|
||||
prepare_milestone.add_argument(
|
||||
"--verification-requirement",
|
||||
action="append",
|
||||
default=[],
|
||||
)
|
||||
prepare_milestone.add_argument("--prepared-at", required=True)
|
||||
prepare_milestone.add_argument("--replace", action="store_true")
|
||||
prepare_milestone.set_defaults(handler=_prepare_milestone)
|
||||
|
||||
reconcile = subparsers.add_parser("reconcile")
|
||||
reconcile.add_argument("--state", type=Path, required=True)
|
||||
reconcile.add_argument("--expected-sha256", required=True)
|
||||
reconcile.add_argument("--task-path", required=True)
|
||||
reconcile.add_argument("--completion-log", type=Path, required=True)
|
||||
reconcile.add_argument("--validation-evidence", required=True)
|
||||
reconcile.add_argument("--reconciled-at", required=True)
|
||||
reconcile.add_argument("--sync-result-head")
|
||||
reconcile.set_defaults(handler=_reconcile)
|
||||
|
||||
reconcile_milestone = subparsers.add_parser("reconcile-milestone")
|
||||
reconcile_milestone.add_argument("--state", type=Path, required=True)
|
||||
reconcile_milestone.add_argument("--expected-sha256", required=True)
|
||||
reconcile_milestone.add_argument("--milestone-path", required=True)
|
||||
reconcile_milestone.add_argument("--closure-evidence", required=True)
|
||||
reconcile_milestone.add_argument("--validation-evidence", required=True)
|
||||
reconcile_milestone.add_argument("--reconciled-at", required=True)
|
||||
reconcile_milestone.add_argument("--sync-result-head")
|
||||
reconcile_milestone.set_defaults(handler=_reconcile_milestone)
|
||||
|
||||
record_sync = subparsers.add_parser("record-sync")
|
||||
record_sync.add_argument("--state", type=Path, required=True)
|
||||
record_sync.add_argument("--expected-sha256", required=True)
|
||||
record_sync.add_argument(
|
||||
"--sync-mode",
|
||||
choices=("incremental", "full", "baseline", "migration"),
|
||||
required=True,
|
||||
)
|
||||
record_sync.add_argument("--sync-result-head", required=True)
|
||||
record_sync.add_argument("--synced-at", required=True)
|
||||
record_sync.add_argument("--agent-ui-path", action="append", default=[], required=True)
|
||||
record_sync.add_argument("--code-path", action="append", default=[])
|
||||
record_sync.add_argument("--note", action="append", default=[])
|
||||
record_sync.set_defaults(handler=_record_sync)
|
||||
return parser
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = _parser().parse_args()
|
||||
try:
|
||||
result = args.handler(args)
|
||||
except (OSError, StateError) as exc:
|
||||
print(json.dumps({"status": "error", "error": str(exc)}, ensure_ascii=False))
|
||||
return 2
|
||||
print(json.dumps(result, ensure_ascii=False, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
|
@ -1,490 +0,0 @@
|
|||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SCRIPT = Path(__file__).parents[1] / "scripts" / "sync_state.py"
|
||||
SPEC = importlib.util.spec_from_file_location("sync_state", SCRIPT)
|
||||
sync_state = importlib.util.module_from_spec(SPEC)
|
||||
assert SPEC.loader is not None
|
||||
SPEC.loader.exec_module(sync_state)
|
||||
|
||||
|
||||
def write_json(path: Path, value: dict) -> str:
|
||||
payload = (json.dumps(value, indent=2) + "\n").encode()
|
||||
path.write_bytes(payload)
|
||||
return hashlib.sha256(payload).hexdigest()
|
||||
|
||||
|
||||
class SyncStateTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temporary = tempfile.TemporaryDirectory()
|
||||
self.root = Path(self.temporary.name)
|
||||
self.original_cwd = Path.cwd()
|
||||
os.chdir(self.root)
|
||||
self.state_path = self.root / "agent-ui" / ".sync-state.json"
|
||||
self.state_path.parent.mkdir(parents=True)
|
||||
self.base_state = {
|
||||
"schema_version": 1,
|
||||
"surface_type": "ops-dev",
|
||||
"baseline_mode": "migration",
|
||||
"last_sync_mode": "baseline",
|
||||
"last_synced_head": "a" * 40,
|
||||
"last_synced_at": "2026-01-01T00:00:00Z",
|
||||
"agent_ui_paths": [],
|
||||
"code_paths": [],
|
||||
"notes": [],
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(self.original_cwd)
|
||||
self.temporary.cleanup()
|
||||
|
||||
def prepare_args(self, digest: str, **overrides):
|
||||
values = {
|
||||
"state": self.state_path,
|
||||
"expected_sha256": digest,
|
||||
"task_path": "agent-task/ui_work",
|
||||
"previous_task_path": None,
|
||||
"scope": "view:dashboard",
|
||||
"status_path": ["agent-ui/definition/views/dashboard/index.md"],
|
||||
"frame_path": ["agent-ui/frame/views/dashboard/index.md"],
|
||||
"code_path": ["src/dashboard.py"],
|
||||
"verification_requirement": ["python -m unittest: PASS"],
|
||||
"prepared_at": "2026-07-29T00:00:00Z",
|
||||
"replace": False,
|
||||
}
|
||||
values.update(overrides)
|
||||
return type("Args", (), values)
|
||||
|
||||
def reconcile_args(self, digest: str, completion_log: Path, **overrides):
|
||||
values = {
|
||||
"state": self.state_path,
|
||||
"expected_sha256": digest,
|
||||
"task_path": "agent-task/ui_work",
|
||||
"completion_log": completion_log,
|
||||
"validation_evidence": "validate-agent-ui scope=view:dashboard PASS",
|
||||
"reconciled_at": "2026-07-29T01:00:00Z",
|
||||
"sync_result_head": None,
|
||||
}
|
||||
values.update(overrides)
|
||||
return type("Args", (), values)
|
||||
|
||||
def prepare_milestone_args(self, digest: str, **overrides):
|
||||
values = {
|
||||
"state": self.state_path,
|
||||
"expected_sha256": digest,
|
||||
"milestone_path": (
|
||||
"agent-roadmap/phase/product/milestones/dashboard-refresh.md"
|
||||
),
|
||||
"scope": "view:dashboard",
|
||||
"status_path": ["agent-ui/definition/views/dashboard/index.md"],
|
||||
"frame_path": ["agent-ui/frame/views/dashboard/index.md"],
|
||||
"code_path": ["src/dashboard.py"],
|
||||
"verification_requirement": ["python -m unittest: PASS"],
|
||||
"prepared_at": "2026-07-29T00:00:00Z",
|
||||
"replace": False,
|
||||
}
|
||||
values.update(overrides)
|
||||
return type("Args", (), values)
|
||||
|
||||
def reconcile_milestone_args(self, digest: str, **overrides):
|
||||
values = {
|
||||
"state": self.state_path,
|
||||
"expected_sha256": digest,
|
||||
"milestone_path": (
|
||||
"agent-roadmap/phase/product/milestones/dashboard-refresh.md"
|
||||
),
|
||||
"closure_evidence": "complete-milestone check-only: closure-ready",
|
||||
"validation_evidence": "validate-agent-ui scope=view:dashboard PASS",
|
||||
"reconciled_at": "2026-07-29T01:00:00Z",
|
||||
"sync_result_head": None,
|
||||
}
|
||||
values.update(overrides)
|
||||
return type("Args", (), values)
|
||||
|
||||
def record_sync_args(self, digest: str, **overrides):
|
||||
values = {
|
||||
"state": self.state_path,
|
||||
"expected_sha256": digest,
|
||||
"sync_mode": "incremental",
|
||||
"sync_result_head": "b" * 40,
|
||||
"synced_at": "2026-07-29T02:00:00Z",
|
||||
"agent_ui_path": ["agent-ui/definition/views/dashboard/index.md"],
|
||||
"code_path": ["src/dashboard.py"],
|
||||
"note": ["direct sync"],
|
||||
}
|
||||
values.update(overrides)
|
||||
return type("Args", (), values)
|
||||
|
||||
def test_prepare_migrates_v1_and_records_typed_paths(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
result = sync_state._prepare(self.prepare_args(digest))
|
||||
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual("prepared", result["status"])
|
||||
self.assertEqual(4, state["schema_version"])
|
||||
self.assertEqual(
|
||||
["agent-ui/definition/views/dashboard/index.md"],
|
||||
state["pending_code_work"][0]["status_paths"],
|
||||
)
|
||||
self.assertEqual(
|
||||
["agent-ui/frame/views/dashboard/index.md"],
|
||||
state["pending_code_work"][0]["frame_paths"],
|
||||
)
|
||||
self.assertEqual([], state["reconciled_code_work"])
|
||||
self.assertEqual([], state["pending_milestone_work"])
|
||||
self.assertEqual([], state["reconciled_milestone_work"])
|
||||
|
||||
def test_prepare_is_idempotent_and_requires_replace_for_scope_change(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
first = sync_state._prepare(self.prepare_args(digest))
|
||||
second = sync_state._prepare(
|
||||
self.prepare_args(
|
||||
first["after_sha256"],
|
||||
prepared_at="2026-07-29T00:05:00Z",
|
||||
)
|
||||
)
|
||||
self.assertEqual("already_prepared", second["status"])
|
||||
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._prepare(
|
||||
self.prepare_args(
|
||||
second["after_sha256"],
|
||||
code_path=["src/other.py"],
|
||||
)
|
||||
)
|
||||
|
||||
replaced = sync_state._prepare(
|
||||
self.prepare_args(
|
||||
second["after_sha256"],
|
||||
code_path=["src/other.py"],
|
||||
replace=True,
|
||||
)
|
||||
)
|
||||
self.assertEqual("replaced", replaced["status"])
|
||||
|
||||
def test_prepare_rejects_stale_digest(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._prepare(self.prepare_args("0" * 64))
|
||||
self.assertEqual(digest, hashlib.sha256(self.state_path.read_bytes()).hexdigest())
|
||||
|
||||
def test_prepare_rejects_malformed_digest(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._prepare(self.prepare_args("not-a-sha256"))
|
||||
self.assertEqual(digest, hashlib.sha256(self.state_path.read_bytes()).hexdigest())
|
||||
|
||||
def test_prepare_rebinds_refined_task_path(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
prepared = sync_state._prepare(self.prepare_args(digest))
|
||||
rebound = sync_state._prepare(
|
||||
self.prepare_args(
|
||||
prepared["after_sha256"],
|
||||
previous_task_path="agent-task/ui_work",
|
||||
task_path="agent-task/ui_work/01_closure",
|
||||
)
|
||||
)
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual("rebound", rebound["status"])
|
||||
self.assertEqual(
|
||||
"agent-task/ui_work/01_closure",
|
||||
state["pending_code_work"][0]["task_path"],
|
||||
)
|
||||
|
||||
def test_prepare_rejects_status_path_owned_by_another_task(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
prepared = sync_state._prepare(self.prepare_args(digest))
|
||||
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._prepare(
|
||||
self.prepare_args(
|
||||
prepared["after_sha256"],
|
||||
task_path="agent-task/other_ui_work",
|
||||
frame_path=[],
|
||||
code_path=["src/other.py"],
|
||||
)
|
||||
)
|
||||
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual(1, len(state["pending_code_work"]))
|
||||
self.assertEqual(
|
||||
"agent-task/ui_work",
|
||||
state["pending_code_work"][0]["task_path"],
|
||||
)
|
||||
|
||||
def test_prepare_rebind_requires_replace_for_changed_scope(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
prepared = sync_state._prepare(self.prepare_args(digest))
|
||||
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._prepare(
|
||||
self.prepare_args(
|
||||
prepared["after_sha256"],
|
||||
previous_task_path="agent-task/ui_work",
|
||||
task_path="agent-task/ui_work/01_closure",
|
||||
code_path=["src/closure.py"],
|
||||
)
|
||||
)
|
||||
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual(
|
||||
"agent-task/ui_work",
|
||||
state["pending_code_work"][0]["task_path"],
|
||||
)
|
||||
|
||||
def test_prepare_milestone_records_mapping_and_blocks_shared_ui_owner(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
milestone = self.root / (
|
||||
"agent-roadmap/phase/product/milestones/dashboard-refresh.md"
|
||||
)
|
||||
milestone.parent.mkdir(parents=True)
|
||||
milestone.write_text("# Milestone: Dashboard refresh\n")
|
||||
prepared = sync_state._prepare_milestone(
|
||||
self.prepare_milestone_args(digest)
|
||||
)
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual("prepared", prepared["status"])
|
||||
self.assertEqual(1, len(state["pending_milestone_work"]))
|
||||
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._prepare(
|
||||
self.prepare_args(
|
||||
prepared["after_sha256"],
|
||||
frame_path=[],
|
||||
)
|
||||
)
|
||||
|
||||
def test_reconcile_milestone_moves_mapping_and_is_idempotent(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
milestone = self.root / (
|
||||
"agent-roadmap/phase/product/milestones/dashboard-refresh.md"
|
||||
)
|
||||
milestone.parent.mkdir(parents=True)
|
||||
milestone.write_text("# Milestone: Dashboard refresh\n")
|
||||
prepared = sync_state._prepare_milestone(
|
||||
self.prepare_milestone_args(digest)
|
||||
)
|
||||
|
||||
reconciled = sync_state._reconcile_milestone(
|
||||
self.reconcile_milestone_args(prepared["after_sha256"])
|
||||
)
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual("reconciled", reconciled["status"])
|
||||
self.assertEqual([], state["pending_milestone_work"])
|
||||
self.assertEqual(1, len(state["reconciled_milestone_work"]))
|
||||
self.assertEqual("a" * 40, state["last_synced_head"])
|
||||
|
||||
milestone.unlink()
|
||||
repeated = sync_state._reconcile_milestone(
|
||||
self.reconcile_milestone_args(reconciled["after_sha256"])
|
||||
)
|
||||
self.assertEqual("already_reconciled", repeated["status"])
|
||||
|
||||
def test_v2_legacy_pending_paths_are_typed_during_migration(self):
|
||||
state = dict(self.base_state)
|
||||
state["schema_version"] = 2
|
||||
state["pending_code_work"] = [
|
||||
{
|
||||
"task_path": "agent-task/ui_work",
|
||||
"scope": "all",
|
||||
"agent_ui_paths": [
|
||||
"agent-ui/definition/views/dashboard/index.md",
|
||||
"agent-ui/frame/views/dashboard/index.md",
|
||||
],
|
||||
"code_paths": ["src/dashboard.py"],
|
||||
"verification_requirements": [],
|
||||
"prepared_at": "2026-07-29T00:00:00Z",
|
||||
"state": "pending",
|
||||
}
|
||||
]
|
||||
normalized = sync_state._normalize_state(state)
|
||||
entry = normalized["pending_code_work"][0]
|
||||
self.assertEqual(
|
||||
["agent-ui/definition/views/dashboard/index.md"],
|
||||
entry["status_paths"],
|
||||
)
|
||||
self.assertEqual(
|
||||
["agent-ui/frame/views/dashboard/index.md"],
|
||||
entry["frame_paths"],
|
||||
)
|
||||
|
||||
def test_normalize_rejects_non_list_and_duplicate_pending_entries(self):
|
||||
invalid = dict(self.base_state)
|
||||
invalid["pending_code_work"] = {}
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._normalize_state(invalid)
|
||||
|
||||
entry = {
|
||||
"task_path": "agent-task/ui_work",
|
||||
"scope": "all",
|
||||
"status_paths": ["agent-ui/definition/views/dashboard/index.md"],
|
||||
"frame_paths": [],
|
||||
"code_paths": ["src/dashboard.py"],
|
||||
"verification_requirements": [],
|
||||
"prepared_at": "2026-07-29T00:00:00Z",
|
||||
"state": "pending",
|
||||
}
|
||||
duplicate = dict(self.base_state)
|
||||
duplicate["schema_version"] = 3
|
||||
duplicate["pending_code_work"] = [entry, dict(entry)]
|
||||
duplicate["reconciled_code_work"] = []
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._normalize_state(duplicate)
|
||||
|
||||
second_owner = dict(entry)
|
||||
second_owner["task_path"] = "agent-task/other"
|
||||
duplicate_owner = dict(self.base_state)
|
||||
duplicate_owner["schema_version"] = 3
|
||||
duplicate_owner["pending_code_work"] = [entry, second_owner]
|
||||
duplicate_owner["reconciled_code_work"] = []
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._normalize_state(duplicate_owner)
|
||||
|
||||
def test_reconcile_moves_pending_entry_and_is_idempotent(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
prepared = sync_state._prepare(self.prepare_args(digest))
|
||||
completion_log = Path("agent-task/archive/2026/07/ui_work/complete.log")
|
||||
(self.root / completion_log).parent.mkdir(parents=True)
|
||||
(self.root / completion_log).write_text(
|
||||
"# Complete - ui_work\n\n"
|
||||
"## 루프 이력\n\n"
|
||||
"| Plan | Review | Verdict | 메모 |\n"
|
||||
"|---|---|---|---|\n"
|
||||
"| `plan.log` | `review.log` | PASS | done |\n"
|
||||
)
|
||||
|
||||
reconciled = sync_state._reconcile(
|
||||
self.reconcile_args(prepared["after_sha256"], self.root / completion_log)
|
||||
)
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual("reconciled", reconciled["status"])
|
||||
self.assertEqual([], state["pending_code_work"])
|
||||
self.assertEqual(1, len(state["reconciled_code_work"]))
|
||||
self.assertEqual("a" * 40, state["last_synced_head"])
|
||||
self.assertIn(
|
||||
"baseline=preserved:no validated sync_result_head",
|
||||
state["notes"][-1],
|
||||
)
|
||||
|
||||
repeated = sync_state._reconcile(
|
||||
self.reconcile_args(reconciled["after_sha256"], self.root / completion_log)
|
||||
)
|
||||
self.assertEqual("already_reconciled", repeated["status"])
|
||||
|
||||
def test_reconcile_rejects_completion_log_for_another_task(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
prepared = sync_state._prepare(self.prepare_args(digest))
|
||||
completion_log = Path("agent-task/archive/2026/07/other/complete.log")
|
||||
(self.root / completion_log).parent.mkdir(parents=True)
|
||||
(self.root / completion_log).write_text(
|
||||
"# Complete - other\n\n"
|
||||
"## 루프 이력\n\n"
|
||||
"| Plan | Review | Verdict | 메모 |\n"
|
||||
"|---|---|---|---|\n"
|
||||
"| `plan.log` | `review.log` | PASS | done |\n"
|
||||
)
|
||||
with self.assertRaises(sync_state.StateError):
|
||||
sync_state._reconcile(
|
||||
self.reconcile_args(prepared["after_sha256"], completion_log)
|
||||
)
|
||||
|
||||
def test_record_sync_preserves_pending_and_reconciled_state(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
prepared = sync_state._prepare(self.prepare_args(digest))
|
||||
recorded = sync_state._record_sync(
|
||||
self.record_sync_args(
|
||||
prepared["after_sha256"],
|
||||
agent_ui_path=[
|
||||
"agent-ui/definition/views/other-dashboard/index.md"
|
||||
],
|
||||
code_path=["src/other_dashboard.py"],
|
||||
)
|
||||
)
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual("sync_recorded", recorded["status"])
|
||||
self.assertEqual("incremental", state["last_sync_mode"])
|
||||
self.assertEqual("b" * 40, state["last_synced_head"])
|
||||
self.assertEqual(1, len(state["pending_code_work"]))
|
||||
self.assertEqual([], state["reconciled_code_work"])
|
||||
|
||||
def test_record_sync_preserves_pending_milestone_state(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
milestone = self.root / (
|
||||
"agent-roadmap/phase/product/milestones/dashboard-refresh.md"
|
||||
)
|
||||
milestone.parent.mkdir(parents=True)
|
||||
milestone.write_text("# Milestone: Dashboard refresh\n")
|
||||
prepared = sync_state._prepare_milestone(
|
||||
self.prepare_milestone_args(digest)
|
||||
)
|
||||
state_before = self.state_path.read_bytes()
|
||||
|
||||
with self.assertRaisesRegex(
|
||||
sync_state.StateError,
|
||||
"overlaps pending work paths",
|
||||
):
|
||||
sync_state._record_sync(
|
||||
self.record_sync_args(prepared["after_sha256"])
|
||||
)
|
||||
self.assertEqual(state_before, self.state_path.read_bytes())
|
||||
|
||||
recorded = sync_state._record_sync(
|
||||
self.record_sync_args(
|
||||
prepared["after_sha256"],
|
||||
agent_ui_path=[
|
||||
"agent-ui/definition/views/other-dashboard/index.md"
|
||||
],
|
||||
code_path=["src/other_dashboard.py"],
|
||||
)
|
||||
)
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual("sync_recorded", recorded["status"])
|
||||
self.assertEqual(1, len(state["pending_milestone_work"]))
|
||||
self.assertEqual([], state["reconciled_milestone_work"])
|
||||
|
||||
def test_record_sync_rejects_paths_owned_by_pending_work(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
prepared = sync_state._prepare(self.prepare_args(digest))
|
||||
state_before = self.state_path.read_bytes()
|
||||
|
||||
for agent_ui_path in (
|
||||
"agent-ui/definition/views/dashboard/index.md",
|
||||
"agent-ui/definition/views/dashboard",
|
||||
):
|
||||
with self.subTest(agent_ui_path=agent_ui_path):
|
||||
with self.assertRaisesRegex(
|
||||
sync_state.StateError,
|
||||
"overlaps pending work paths",
|
||||
):
|
||||
sync_state._record_sync(
|
||||
self.record_sync_args(
|
||||
prepared["after_sha256"],
|
||||
agent_ui_path=[agent_ui_path],
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(state_before, self.state_path.read_bytes())
|
||||
|
||||
def test_record_migration_allows_no_code_paths(self):
|
||||
digest = write_json(self.state_path, self.base_state)
|
||||
recorded = sync_state._record_sync(
|
||||
self.record_sync_args(
|
||||
digest,
|
||||
sync_mode="migration",
|
||||
code_path=[],
|
||||
)
|
||||
)
|
||||
state = json.loads(self.state_path.read_text())
|
||||
self.assertEqual("sync_recorded", recorded["status"])
|
||||
self.assertEqual("migration", state["last_sync_mode"])
|
||||
self.assertEqual([], state["code_paths"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
---
|
||||
name: sync-milestone-workstate
|
||||
version: 1.1.0
|
||||
description: 현 마일스톤과 작업현황 동기화, 현재 마일스톤 작업현황 동기화, 마일스톤 완료내역 동기화, agent-task 완료를 마일스톤에 반영, active/archive complete.log 후보 스캔, 누락된 Roadmap Completion 복구, 작은 작업처럼 agent-task 기록이 없는 완료 내역을 관련 파일과 git 기록까지 종합 확인, 마일스톤 체크박스 재동기화 요청에서 Milestone Task, 상태, Phase/current 라벨을 실제 evidence와 맞추는 절차
|
||||
---
|
||||
|
||||
# sync-milestone-workstate
|
||||
|
||||
## 목적
|
||||
|
||||
현재 또는 지정 Milestone의 기능 Task 상태를 실제 작업 evidence와 동기화한다.
|
||||
새 작업을 배치하거나 구현 계획을 수정하지 않는다.
|
||||
`complete.log`의 `Roadmap Completion`은 가장 강한 직접 근거로 사용하되, 그 파일이 있더라도 관련 파일과 git history로 최소 sanity pass를 수행한다.
|
||||
`complete.log`가 없거나 불완전해도 완료가 없다고 단정하지 않는다.
|
||||
작은 작업이나 수동 수정처럼 `agent-task` 기록이 없을 수 있으므로 Milestone의 관련 경로, 실제 파일 내용, git history, 테스트/검증 흔적을 함께 확인한다.
|
||||
런타임이 `origin-task`와 `complete-log`를 단건 완료 이벤트로 전달한 일반 반영은 `update-roadmap`을 사용한다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 "현 마일스톤과 작업현황 동기화", "현재 마일스톤 작업현황 동기화", "마일스톤 작업현황 동기화"라고 요청할 때
|
||||
- 사용자가 "마일스톤 완료내역 동기화", "agent-task 완료를 마일스톤에 반영", "complete.log 후보 스캔"이라고 요청할 때
|
||||
- 사용자가 "누락된 Roadmap Completion 복구", "마일스톤 체크박스 재동기화", "로드맵 작업 완료 상태 동기화"라고 요청할 때
|
||||
- 사용자가 agent-task에는 없지만 실제 파일/git 기준으로는 완료된 것 같다고 지적할 때
|
||||
- code-review PASS/archive 이후 runtime completion event 반영이 누락되었는지 확인하고 file-based fallback으로 복구해야 할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `target-milestone`: 동기화할 Milestone 이름, slug, 또는 경로. 없으면 `agent-roadmap/current.md`의 활성 Milestone 단일 후보를 사용한다. (선택)
|
||||
- `complete-log`: 특정 `complete.log` 경로. 지정되면 이 파일을 우선 검증하되, 같은 Milestone slug의 active/archive 후보도 함께 확인한다. (선택)
|
||||
- `mode`: `sync` 또는 `check-only`. 기본값은 `sync`다. (선택)
|
||||
- `check-only`: 어떤 파일도 수정하지 않는다. Milestone, Phase, `current.md`, `.agent-roadmap-sync/locks.yaml` 모두 쓰기 금지이며 반영 후보만 보고한다.
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-roadmap/current.md`를 읽어 활성 Milestone 후보를 확인한다.
|
||||
- [ ] 대상 Milestone 문서의 `상태`, `구현 잠금`, `기능`, `완료 리뷰`, `작업 컨텍스트`를 확인한다.
|
||||
- [ ] 대상 Phase `PHASE.md`의 `Milestone 흐름`에 대상 Milestone 항목이 있는지 확인한다.
|
||||
- [ ] 대상 Milestone의 `SDD: 필요` 여부와 `SDD 문서`, `USER_REVIEW.md` 존재 여부를 확인한다.
|
||||
- [ ] 같은 slug의 active task와 archive task `complete.log` 후보를 모두 탐색한다. active만 보고 no-op으로 끝내지 않는다.
|
||||
- [ ] 관련 파일과 git history를 최소 확인한다. `complete.log`가 없거나 일부 Task만 설명하면 더 깊게 감사한다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **대상 Milestone 확정**
|
||||
- `target-milestone`이 있으면 활성 `agent-roadmap/phase/*/milestones/*.md`에서 정확히 하나를 찾는다.
|
||||
- `target-milestone`이 없으면 `agent-roadmap/current.md`의 활성 Milestone이 정확히 하나인지 확인한다.
|
||||
- 대상이 없거나 둘 이상이면 Milestone을 수정하지 않고 target 불명확으로 보고한다.
|
||||
- 대상 경로가 `agent-roadmap/archive/**`이면 수정하지 않고 archive target 불가로 보고한다.
|
||||
|
||||
2. **Milestone Task와 evidence scope 읽기**
|
||||
- Milestone `기능` 섹션의 Task id만 완료 후보로 본다.
|
||||
- Task id는 `- [ ] [item-id]` 또는 `- [x] [item-id]` 형식에서 추출한다.
|
||||
- 각 Task의 설명과 `검증:` 문구를 기록한다.
|
||||
- `구현 잠금`의 상태, `결정 필요`, `SDD: 필요|불필요`, SDD 문서 링크/경로를 확인한다.
|
||||
- `작업 컨텍스트`의 관련 경로, Milestone 범위, Task 설명의 코드/문서 키워드를 evidence scope로 삼는다.
|
||||
- 관련 경로가 전혀 없으면 Task 설명에서 검색어를 만들되, 후보가 넓거나 모호하면 Task를 자동 완료하지 않고 scope 불명확으로 보고한다.
|
||||
|
||||
3. **complete.log 후보 수집**
|
||||
- 대상 Milestone slug를 `<milestone-slug>`로 두고 task group은 `m-<milestone-slug>`로 고정한다.
|
||||
- active 후보를 찾는다: `agent-task/m-<milestone-slug>/complete.log`, `agent-task/m-<milestone-slug>/**/complete.log`
|
||||
- archive 후보를 찾는다: `agent-task/archive/*/*/m-<milestone-slug>/complete.log`, `agent-task/archive/*/*/m-<milestone-slug>/**/complete.log`
|
||||
- `complete-log` 입력이 있으면 그 파일도 후보에 포함하되, `Roadmap Completion`의 Milestone 경로가 대상과 일치해야 직접 반영한다.
|
||||
- 일반 `agent-task/archive/**` 전체를 훑지 말고 위 패턴에 맞는 같은 milestone task group만 읽는다.
|
||||
|
||||
4. **Roadmap Completion 직접 근거 검증**
|
||||
- 각 `complete.log`에 `Roadmap Completion` 섹션이 없으면 직접 Task 체크 근거로 쓰지 않는다. 파일/git evidence를 찾기 위한 힌트로만 사용하고 no-op 사유에 남긴다.
|
||||
- `Milestone:` 경로가 대상 Milestone 경로와 정확히 일치하지 않으면 해당 파일을 직접 반영하지 않고 mismatch로 보고한다.
|
||||
- `Completed task ids`의 id가 대상 Milestone의 기존 Task id와 정확히 일치하지 않으면 직접 반영하지 않고 unknown task id로 보고한다.
|
||||
- 완료 근거는 `PASS` 또는 동등한 완료 판정과 검증 evidence가 있는 항목만 직접 인정한다.
|
||||
- 같은 Task id에 여러 `complete.log`가 있으면 PASS 근거가 있는 항목을 모으고, 서로 충돌하는 `Not completed task ids`가 있으면 충돌을 보고한다.
|
||||
|
||||
5. **파일/git evidence 감사**
|
||||
- 항상 대상 Milestone의 관련 파일과 git history를 최소 확인한다.
|
||||
- `Roadmap Completion`으로 확인되지 않은 Task가 있거나 사용자가 실제 구현 완료를 지적하면 Task별 상세 감사를 수행한다.
|
||||
- 관련 파일을 `rg --files <관련 경로>`와 Task 키워드 `rg`로 찾고, 필요한 파일 본문을 읽어 Task 설명과 직접 대응되는 구현/문서/테스트 변경을 확인한다.
|
||||
- `git log --oneline -- <관련 경로>`와 필요한 경우 `git show --stat --name-only <commit>`로 Milestone 관련 커밋을 확인한다.
|
||||
- 커밋 메시지만으로 Task를 완료 처리하지 않는다. 커밋이 변경한 파일과 현재 파일 내용이 Task 설명을 충족해야 한다.
|
||||
- Task 완료 인정 기준:
|
||||
- 구현/산출물 evidence가 Task 설명과 직접 대응한다.
|
||||
- Task에 `검증:`이 있으면 해당 검증 명령의 기록, 현재 테스트 실행 결과, 또는 같은 범위를 검증하는 명시 evidence가 있다.
|
||||
- `validation-tests` 같은 테스트 Task는 테스트 코드와 검증 실행 evidence가 모두 있어야 한다.
|
||||
- evidence가 의미상 유사하지만 Task id와 연결이 불분명하면 `[x]` 처리하지 않고 `검토 필요`로 보고한다.
|
||||
|
||||
6. **SDD Evidence Map 확인**
|
||||
- `SDD: 필요`인 Milestone은 direct evidence와 file/git evidence 모두 SDD gate를 통과해야 한다.
|
||||
- SDD `Acceptance Scenarios`와 `Evidence Map`에서 각 완료 후보 Task id와 연결된 scenario가 있는지 확인한다.
|
||||
- 연결된 scenario의 evidence가 확인한 complete log, 파일 변경, git commit, verification 중 하나로 설명 가능해야 한다.
|
||||
- SDD 파일이 없거나 `USER_REVIEW.md`가 남아 있거나 Evidence Map 연결이 비어 있으면 Task 체크 또는 `[검토중]` 전환을 하지 않고 차단 사유로 보고한다.
|
||||
|
||||
7. **Milestone 문서 반영**
|
||||
- `mode=check-only`이면 어떤 파일도 수정하지 않고 반영 후보만 보고한다.
|
||||
- 검증된 완료 Task id만 `[x]`로 바꾼다. 이미 `[x]`인 항목은 유지한다.
|
||||
- 일부 Task만 완료되었고 미완료 Task가 남으면 Milestone 상태는 `[진행중]`으로 둔다. 단, 기존 상태가 `[검토중]`, `[보류]`, `[폐기]`이면 자동으로 낮추지 않고 차이만 보고한다.
|
||||
- 모든 기능 Task가 `[x]`이고 `구현 잠금`이 `해제`, `결정 필요: 없음`, SDD 사용자 리뷰 없음, SDD evidence 충족이면 Milestone 상태를 `[검토중]`으로 바꾼다.
|
||||
- `[검토중]`으로 바꾸면 `완료 리뷰` 섹션을 만들거나 갱신하고, 사용한 `complete.log`, 파일/git evidence 요약, 완료 Task id, 남은 차단 항목 없음 또는 요약을 1~3줄로 남긴다.
|
||||
- 모든 Task가 `[x]`여도 구현 잠금이나 SDD gate가 남으면 `[검토중]`으로 바꾸지 않고 `완료 리뷰` 또는 `작업 컨텍스트`에 차단 항목을 남긴다.
|
||||
- 이 스킬은 Milestone을 `[완료]`로 바꾸거나 archive로 이동하지 않는다.
|
||||
|
||||
8. **Phase와 current 라벨 동기화**
|
||||
- `mode=check-only`이면 이 단계를 쓰기 없이 확인만 한다.
|
||||
- 대상 Phase `PHASE.md`의 `Milestone 흐름`에서 대상 Milestone 상태 라벨을 Milestone 본문 상태와 맞춘다.
|
||||
- `agent-roadmap/current.md`에 대상 Milestone이 있으면 상태 라벨을 Milestone 본문 상태와 맞춘다.
|
||||
- `current.md`에는 `[완료]` 또는 `[폐기]`를 남기지 않는다. 이 스킬은 `[검토중]`까지 유지할 수 있다.
|
||||
|
||||
9. **workspace lock 확인**
|
||||
- `mode=check-only`이면 관련 lock 여부와 필요한 동기화 후보만 보고하고 `locks.yaml`을 수정하지 않는다.
|
||||
- `.agent-roadmap-sync/locks.yaml`이 있으면 대상 Milestone identity로 `agent-ops/bin/roadmap-dependency-checker.sh --find-milestone "<project>:<milestone-path>" both "<locks-file>"`를 실행한다.
|
||||
- 관련 lock이 없으면 결과에 `Workspace 잠금: 관련 lock 없음`을 남긴다.
|
||||
- 대상 Milestone identity가 어느 entry의 `rely-on.target`과 일치하면 대상 Milestone 상태 기준으로 해당 `rely-on.status`를 동기화한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태면 `disable`이다.
|
||||
- 대상 Milestone identity가 어느 entry의 `locked`와 일치하면 모든 `rely-on.status`가 `enable`인지 결과에 남긴다.
|
||||
- 이 스킬에서 새 lock을 만들거나 다른 Milestone의 구현 잠금을 직접 해제하지 않는다.
|
||||
|
||||
10. **결과 보고**
|
||||
- 수정 파일과 변경 전/후 상태를 보고한다.
|
||||
- 읽은 active/archive `complete.log` 후보 수, 확인한 관련 파일/git 범위, 반영한 Task id를 보고한다.
|
||||
- 반영하지 않은 `complete.log`나 Task가 있으면 이유를 보고한다.
|
||||
- SDD gate, 완료 리뷰, Workspace lock, 남은 미완료 Task, 검토 필요 Task를 보고한다.
|
||||
- 대상 Milestone, 수정 파일, `complete.log`, SDD, 사용자 리뷰 같은 문서/산출물 포인터는 raw path만 쓰지 말고 `[표시 제목](상대경로)` Markdown 링크로 보고한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] 대상 Milestone이 활성 경로에서 정확히 하나로 확정되었는가
|
||||
- [ ] 같은 `m-<milestone-slug>`의 active/root/nested `complete.log`와 archive/root/nested `complete.log` 후보를 모두 확인했는가
|
||||
- [ ] archive 확인을 생략하고 active task만 근거로 no-op 처리하지 않았는가
|
||||
- [ ] `complete.log` 부재만으로 완료 Task 없음이라고 단정하지 않았는가
|
||||
- [ ] 관련 파일과 git history를 확인했거나, scope 불명확 사유를 보고했는가
|
||||
- [ ] `Roadmap Completion`의 Milestone 경로와 Task id가 대상 Milestone과 exact match였는가
|
||||
- [ ] `SDD: 필요`인 경우 SDD 파일, `USER_REVIEW.md` 부재, Acceptance Scenario, Evidence Map 연결을 확인했는가
|
||||
- [ ] 완료 근거가 있는 Task만 `[x]`로 바꾸었는가
|
||||
- [ ] 모든 Task 완료와 구현 잠금 해제 조건이 충족된 경우에만 `[검토중]`으로 전환했는가
|
||||
- [ ] `[검토중]`으로 전환했다면 `완료 리뷰`에 complete.log, 파일/git evidence, 남은 차단 항목이 남았는가
|
||||
- [ ] Phase `PHASE.md`와 `agent-roadmap/current.md`의 상태 라벨이 Milestone 본문과 일치하는가
|
||||
- [ ] `[검토중]` 전환만 수행하고 `[완료]` 전환 또는 archive 이동을 하지 않았는가
|
||||
- [ ] `.agent-roadmap-sync/locks.yaml`이 있으면 관련 lock 여부와 필요한 `rely-on.status` 동기화를 결과에 반영했는가
|
||||
- [ ] 결과 보고의 문서/산출물 포인터가 raw path만 남지 않고 Markdown 링크로 작성되었는가
|
||||
- [ ] `git diff --check`를 실행했는가
|
||||
- 검증 실패 시: 파일을 추가로 추정 수정하지 말고 실패한 항목, 차단 사유, 필요한 evidence 경로를 보고한다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```markdown
|
||||
## 동기화 완료
|
||||
|
||||
- 대상 Milestone: [<milestone-name>](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||
- 모드: <sync | check-only>
|
||||
- 수정 파일:
|
||||
- <없음 | [문서명](path)>
|
||||
|
||||
## 반영 내용
|
||||
|
||||
- 상태: <변경 없음 | 이전 -> 이후>
|
||||
- 완료 Task: <id 목록 또는 없음>
|
||||
- 미완료 Task: <id 목록 또는 없음>
|
||||
- 검토 필요 Task: <id 목록 또는 없음>
|
||||
- complete.log 후보: active <N>개, archive <N>개
|
||||
- 반영한 complete.log:
|
||||
- <[complete.log](path)>
|
||||
- 반영 제외 complete.log:
|
||||
- <[complete.log](path)> - <사유>
|
||||
- 파일/git evidence:
|
||||
- <task-id 또는 범위> - <파일/커밋/검증 요약>
|
||||
- SDD gate: <불필요 | 충족 | 차단: 사유>
|
||||
- 완료 리뷰: <변경 없음 | 검토중 갱신 | 잠금 차단 기록>
|
||||
- Workspace 잠금: <관련 lock 없음 | 상태 요약 | 미확인 사유>
|
||||
|
||||
## TODO 항목
|
||||
|
||||
- <남은 차단 항목 또는 없음>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- active `agent-task/m-<milestone-slug>`만 확인하고 archive `complete.log` 확인 없이 no-op 처리하지 않는다.
|
||||
- `complete.log` 부재만으로 Task 미완료를 단정하지 않는다.
|
||||
- 대상 slug와 다른 `agent-task/archive/**` 문서를 일반 탐색하지 않는다.
|
||||
- 커밋 메시지, 파일명, plan/review log만으로 Task를 `[x]` 처리하지 않는다.
|
||||
- `complete.log`의 Task id를 의미 유사도, 순서, 파일명으로 보정하지 않는다.
|
||||
- 파일/git evidence가 있어도 Task 설명과 직접 대응되지 않으면 완료 처리하지 않는다.
|
||||
- SDD gate가 필요한데 Evidence Map 연결을 확인하지 않고 `[검토중]`으로 전환하지 않는다.
|
||||
- 구현 잠금이 남아 있거나 `결정 필요`가 있으면 `[검토중]`, `[완료]`, archive를 수행하지 않는다.
|
||||
- 이 스킬에서 새 Milestone/Epic/Task를 만들거나 기존 id를 바꾸지 않는다.
|
||||
- 이 스킬에서 Milestone을 `[완료]`로 전환하거나 archive 이동하지 않는다.
|
||||
|
|
@ -33,25 +33,21 @@ description: 현재 프로젝트의 agent-ops를 공통 원본 repo로 올리거
|
|||
2. **있으면**: `agent-ops/bin/sync.sh` 실행 또는 `agent-ops/bin/sync.sh agentic-framework` 실행
|
||||
3. **없으면**: 사용자에게 agentic-framework 경로 입력을 안내하고, 입력받은 경로로 실행
|
||||
4. 공통 관리 파일 변경 없이 `agent-ops/.version`만 다른 경우 `sync.sh`는 버전 갱신과 commit/push를 건너뛴다
|
||||
5. 공통 관리 파일 변경이 없어도 현재 프로젝트 또는 공통 원본 repo의 진입 파일이 `agent-ops/rules/common/rules.md`와 다르면 진입 파일만 재적용하고 commit/push 한다
|
||||
6. 공통 관리 파일 변경이 있으면 `sync.sh`가 버전을 한 단계 올리고 현재 프로젝트와 공통 원본 repo에 같은 버전을 반영한다
|
||||
7. 이때 현재 프로젝트와 공통 원본 repo의 진입 파일은 각각 자기 `agent-ops/rules/common/rules.md` 내용으로 재적용한다
|
||||
8. 일반 프로젝트에서 공통 원본 repo로 올릴 때는 AI ignore / permission 파일을 보강하거나 stage하지 않는다. 단, `agent-ops/rules/private/`와 `agent-ops/skills/private/` ignore 항목만 보장하기 위해 `.gitignore`은 함께 stage한다.
|
||||
5. 공통 관리 파일 변경이 있으면 `sync.sh`가 버전을 한 단계 올리고 현재 프로젝트와 공통 원본 repo에 같은 버전을 반영한다
|
||||
6. 일반 프로젝트에서 공통 원본 repo로 올릴 때는 AI ignore / permission 파일을 보강하거나 stage하지 않는다
|
||||
|
||||
### 현 프로젝트가 공통 원본 repo인 경우 (`.agent-ops-source` 있음)
|
||||
|
||||
1. 사용자 요청에서 target 프로젝트명 또는 경로를 추출한다
|
||||
2. 공통 원본 repo 자신의 진입 파일이 `agent-ops/rules/common/rules.md`와 다르면 먼저 재적용하고 commit/push 한다
|
||||
3. **명시된 경우**: `agent-ops/bin/sync.sh <target>` 실행
|
||||
4. **명시되지 않은 경우**: `agent-ops/bin/sync.sh` 실행
|
||||
5. target이 없으면 `sync.sh`가 현재 프로젝트 기준 상위 폴더(`../`)의 하위 디렉터리 중 `agent-ops/` 폴더가 있는 프로젝트를 모두 대상으로 삼는다
|
||||
6. `sync.sh`는 현재 공통 원본 repo의 `agent-ops/rules/common/rules.md` 내용을 대상 프로젝트 루트의 진입 파일에 덮어쓴다
|
||||
7. 적용 후 각 대상 repo에서 agent-ops 공통 관리 경로(`rules/common/rules.md` 포함), 진입 파일, `.gitignore`, AI ignore / permission 파일을 stage 하여 commit/push 한다
|
||||
8. `.gitignore`와 AI ignore / permission 파일은 대상 프로젝트의 기존 내용을 덮어쓰지 않고, Agent-Ops 관리 block 또는 Agent-Ops 전용 permission key만 보강한다
|
||||
9. 이 과정에서는 버전을 새로 올리지 않고 현재 공통 원본 repo의 `agent-ops/.version` 값을 그대로 대상 프로젝트에 반영한다
|
||||
2. **명시된 경우**: `agent-ops/bin/sync.sh <target>` 실행
|
||||
3. **명시되지 않은 경우**: `agent-ops/bin/sync.sh` 실행
|
||||
4. target이 없으면 `sync.sh`가 현재 프로젝트 기준 상위 폴더(`../`)의 하위 디렉터리 중 `agent-ops/` 폴더가 있는 프로젝트를 모두 대상으로 삼는다
|
||||
5. `sync.sh`는 현재 공통 원본 repo의 `agent-ops/rules/common/rules.md` 내용을 대상 프로젝트 루트의 진입 파일에 덮어쓴다
|
||||
6. 적용 후 각 대상 repo에서 agent-ops 공통 관리 경로(`rules/common/rules.md` 포함), 진입 파일, `.gitignore`, AI ignore / permission 파일을 stage 하여 commit/push 한다
|
||||
7. `.gitignore`와 AI ignore / permission 파일은 대상 프로젝트의 기존 내용을 덮어쓰지 않고, Agent-Ops 관리 block 또는 Agent-Ops 전용 permission key만 보강한다
|
||||
8. 이 과정에서는 버전을 새로 올리지 않고 현재 공통 원본 repo의 `agent-ops/.version` 값을 그대로 대상 프로젝트에 반영한다
|
||||
|
||||
덮어쓰기 대상은 `init-agent-ops` 초기 세팅과 동일하며, 실제 목록은 `agent-ops/bin/entry-files.sh`의 `AGENT_OPS_ENTRY_FILES`를 단일 기준으로 사용한다.
|
||||
모든 repo에서 진입 파일 내용은 해당 repo의 `agent-ops/rules/common/rules.md`와 같아야 한다.
|
||||
|
||||
| 에이전트 | 파일명 |
|
||||
|---------|--------|
|
||||
|
|
@ -66,15 +62,7 @@ description: 현재 프로젝트의 agent-ops를 공통 원본 repo로 올리거
|
|||
## Gitignore / AI Ignore / Permission 재적용
|
||||
|
||||
- 이 절차는 `.agent-ops-source`가 있는 공통 원본 repo에서 대상 프로젝트로 push할 때와 `--pull`로 공통 원본 repo에서 현재 프로젝트로 내려받을 때만 적용한다.
|
||||
- 일반 프로젝트에서 공통 원본 repo로 올리는 push에서는 AI ignore / permission 파일을 수정하거나 stage하지 않는다. 단, private 규칙·스킬의 로컬 전용 경로를 보장하는 아래 두 `.gitignore` 항목은 추가·stage할 수 있다.
|
||||
|
||||
```text
|
||||
# Agent-Ops Private Rules
|
||||
agent-ops/rules/private/
|
||||
|
||||
# Agent-Ops Private Skills
|
||||
agent-ops/skills/private/
|
||||
```
|
||||
- 일반 프로젝트에서 공통 원본 repo로 올리는 push에서는 `.gitignore`와 AI ignore / permission 파일을 수정하거나 stage하지 않는다.
|
||||
- `.gitignore`는 사용자 영역을 수정하지 않고 아래 관리 block만 추가하거나 교체한다. 이 예외는 `*.log` 같은 전역 ignore가 있어도 plan/review/archive task 산출물이 git에 잡히도록 하고, `agent-roadmap/current.md`는 브랜치별 로컬 포인터로 남긴다.
|
||||
|
||||
```text
|
||||
|
|
@ -106,21 +94,20 @@ agent-roadmap/archive/**
|
|||
agent-ops/bin/sync.sh [target]
|
||||
```
|
||||
|
||||
푸시 대상 path는 항상 `agent-ops/.version`, `agent-ops/bin`, `agent-ops/rules/common`, `agent-ops/skills/common`, `AGENT_OPS_ENTRY_FILES`의 진입 파일로 제한한다. 예외적으로 `agent-roadmap/current.md`가 이미 추적 중이고 `.gitignore`에 로컬 current ignore가 있으면 파일을 보존한 채 git 추적에서 제거하는 삭제만 함께 commit할 수 있다. `.gitignore`와 AI ignore / permission 파일은 `.agent-ops-source`가 있는 공통 원본 repo에서 일반 프로젝트로 내려보내는 경우에만 대상 repo에서 추가 stage한다. 일반 프로젝트에서 공통 원본 repo로 올릴 때에는 private 규칙·스킬 ignore 두 항목을 반영하는 `.gitignore`만 추가 stage할 수 있다.
|
||||
푸시 대상 path는 항상 `agent-ops/.version`, `agent-ops/bin`, `agent-ops/rules/common`, `agent-ops/skills/common`, `AGENT_OPS_ENTRY_FILES`의 진입 파일로 제한한다. 예외적으로 `agent-roadmap/current.md`가 이미 추적 중이고 `.gitignore`에 로컬 current ignore가 있으면 파일을 보존한 채 git 추적에서 제거하는 삭제만 함께 commit할 수 있다. `.gitignore`와 AI ignore / permission 파일은 `.agent-ops-source`가 있는 공통 원본 repo에서 일반 프로젝트로 내려보내는 경우에만 대상 repo에서 추가 stage한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] sync.sh 가 오류 없이 완료됐는가
|
||||
- [ ] 버전 충돌 경고가 없었는가 — 있었다면 사용자에게 수동 머지 필요함을 알린다
|
||||
- [ ] 대상 repo의 `agent-ops/rules/common/rules.md`가 현재 공통 원본 repo의 `agent-ops/rules/common/rules.md`와 일치하는가
|
||||
- [ ] 현재 repo와 대상 repo의 `AGENT_OPS_ENTRY_FILES` 진입 파일이 각각 자기 repo의 `agent-ops/rules/common/rules.md`와 일치하는가
|
||||
- [ ] 공통 원본 repo에서 대상 프로젝트로 push한 경우, `agent-ops/bin/entry-files.sh`의 모든 진입 파일 내용이 현재 공통 원본 repo의 `agent-ops/rules/common/rules.md`와 일치하는가
|
||||
- [ ] 공통 원본 repo에서 대상 프로젝트로 push한 경우, `.gitignore`에 Agent-Ops 관리 gitignore block이 있고 `!agent-task/`, `!agent-task/**/`, `!agent-task/**/*.md`, `!agent-task/**/*.log`, `agent-roadmap/current.md`가 포함되어 있는가
|
||||
- [ ] 대상 프로젝트에서 `agent-roadmap/current.md`가 있으면 파일은 보존되고 git 추적 대상에서는 제거됐는가
|
||||
- [ ] 공통 원본 repo에서 대상 프로젝트로 push한 경우, `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에 Agent-Ops 관리 block이 있고 그 안에 `agent-task/archive/**`와 `agent-roadmap/archive/**`가 포함되어 있는가
|
||||
- [ ] 공통 원본 repo에서 대상 프로젝트로 push한 경우, `.claude/settings.json`과 `opencode.json`에 `agent-task/archive/**` 또는 `agent-roadmap/archive/**` hard read/glob deny가 남아 있지 않은가
|
||||
- [ ] 대상 프로젝트에 기존 archive hard deny가 있으면 init-agent-ops 표준에 맞게 제거했는가
|
||||
- [ ] 일반 프로젝트에서 공통 원본 repo로 push한 경우, private 규칙·스킬 ignore 두 항목 외의 `.gitignore` 변경과 AI ignore / permission 파일이 공통 원본 repo에 유입되지 않았는가
|
||||
- [ ] 일반 프로젝트에서 공통 원본 repo로 push한 경우, `.gitignore`와 AI ignore / permission 파일이 공통 원본 repo에 유입되지 않았는가
|
||||
- [ ] 대상 repo에 commit/push 된 path가 방향별 허용 범위로 제한되었는가
|
||||
|
||||
## 금지 사항
|
||||
|
|
|
|||
|
|
@ -1,156 +0,0 @@
|
|||
---
|
||||
name: update-agent-ui
|
||||
version: 1.1.1
|
||||
description: 화면정의서, view, component, frame, wireframe 내용을 agent로 수정하고 후속 validate 필요성과 sync intent 전달 여부를 판단하는 스킬
|
||||
---
|
||||
|
||||
# update-agent-ui
|
||||
|
||||
## 목적
|
||||
|
||||
기존 `agent-ui/`의 화면정의서와 wireframe 관련 문서를 갱신한다.
|
||||
사용자가 "화면정의서에 X 추가", "wireframe에 사이드바 추가"처럼 agent-ui 명사를 쓰지 않아도 UI 정의 문서 수정 요청이면 이 스킬을 사용한다.
|
||||
오래된 결정이 현재 기준을 흐리면 archive log로 분리하고, 변경 후 `validate-agent-ui` 필요성과 code sync intent 전달 여부를 판단한다.
|
||||
코드 구현 규모 판정, plan 라우팅, roadmap/milestone 라우팅은 `sync-agent-ui` 책임이며 이 스킬에서 수행하지 않는다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 화면 정의서, view 정의, component 정의를 추가하거나 수정할 때
|
||||
- wireframe 또는 Excalidraw visual source 연결을 추가하거나 수정할 때
|
||||
- 기존 구현 코드 또는 컨셉 문서 변화에 맞춰 Source Evidence와 Status를 갱신할 때
|
||||
- agent-ui 문서의 decision history, open question, user review를 갱신할 때
|
||||
- ops/dev UI 정의를 제품 진행 상황에 맞춰 동기화할 때
|
||||
- 사용자가 "화면정의서에 ... 추가/수정/삭제", "와이어프레임에 ... 추가/수정/삭제", "wireframe에 ... 반영"처럼 요청할 때
|
||||
- 사용자가 `UIR-NNN` 결정, agent-ui USER_REVIEW 해결, 화면정의서와 코드 불일치 보정을 요청할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `change`: 갱신할 내용 요약 (필수)
|
||||
- `view-id`: 대상 view id (선택)
|
||||
- `component-id`: 대상 component id 또는 path id (선택)
|
||||
- `frame-source`: 예: `wire.excalidraw`, `overview.png` (선택)
|
||||
- `evidence`: 코드, 문서, 사용자 입력 근거 경로 또는 요약 (선택)
|
||||
- `status`: `구현됨`, `계획`, `가정`, `불명확` 중 하나 (선택)
|
||||
- `mode`: `definition`, `frame`, `component`, `mixed` 중 하나. 기본값은 `mixed` (선택)
|
||||
- `post-validate`: `auto`, `true`, `false` 중 하나. 기본값은 `auto` (선택)
|
||||
- `post-sync`: `auto`, `true`, `false` 중 하나. 기본값은 `auto` (선택)
|
||||
- `review-resolution`: 해결할 `UIR-NNN`과 결정 내용 (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/rules/common/rules-agent-ui.md`를 읽는다.
|
||||
- [ ] `agent-ui/` 존재 여부를 확인한다. 없으면 `create-agent-ui` 대상이라고 보고하고 중단한다.
|
||||
- [ ] `agent-ui/definition/index.md`와 `agent-ui/frame/index.md`를 읽는다.
|
||||
- [ ] 대상 view/component/frame 문서가 있으면 해당 활성 문서만 읽는다.
|
||||
- [ ] `agent-ui/USER_REVIEW.md`가 있으면 현재 변경과 관련된 항목만 확인한다.
|
||||
- [ ] `definition/archive/**`와 `archive/user-review/**`는 사용자가 과거 확인, 복원, 비교를 요청한 경우가 아니면 읽지 않는다.
|
||||
- [ ] 필요한 템플릿만 `agent-ops/skills/common/_templates/agent-ui/`에서 읽는다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **대상 분류**
|
||||
- `view-id`가 있으면 view 정의를 대상으로 삼고, frame 문서가 있거나 `frame-source`가 입력된 경우에만 frame 문서를 대상으로 삼는다.
|
||||
- `component-id`가 있으면 component 정의를 대상으로 삼는다.
|
||||
- `frame-source`가 있으면 대응 `frame/views/<view-id>/index.md`에 visual source를 연결한다.
|
||||
- 대상이 모호하면 추정으로 새 문서를 만들지 않고 `agent-ui/USER_REVIEW.md`에 결정 항목을 남긴다.
|
||||
|
||||
2. **정의 갱신**
|
||||
- 현재 기준은 `definition/**` 활성 문서에 반영한다.
|
||||
- 활성 Markdown 문서의 frontmatter를 유지하고, 새 문서는 `rules-agent-ui.md`의 Frontmatter Schema를 적용한다.
|
||||
- view 문서에는 status, source evidence, purpose, tasks, information priority, regions, actions, states, open questions, decision history를 유지한다.
|
||||
- component 문서에는 status, source evidence, purpose, used by, anatomy, variants, states, rules, decision history를 유지한다.
|
||||
- 구현 코드 반영 완료 항목은 `구현됨`, 문서 기준으로 정합화됐지만 코드 반영 전이거나 재작업 대상인 항목은 `계획`, 사용자 입력/추정만 있는 항목은 `가정`, 판단 불가 항목은 `불명확`으로 둔다.
|
||||
- 실제 근거 파일이 없으면 frontmatter `source_evidence[].path`는 `null`로 둔다.
|
||||
- frontmatter의 `status`, `source_evidence`, `regions`와 본문 `Status`, `Source Evidence`, `Regions`가 충돌하지 않게 함께 갱신한다.
|
||||
- `status`가 입력되었더라도 evidence와 맞지 않으면 임의로 확정하지 않고 USER_REVIEW로 남긴다.
|
||||
- 새 view/component를 만들 때는 `Source Evidence`와 `Status`를 반드시 채운다.
|
||||
- 오래된 결정이 현재 기준을 흐리면 대응되는 `definition/archive/**.log`로 이동하거나 추가한다. 단순 변경 이벤트를 모두 archive로 남기지 않는다.
|
||||
|
||||
3. **frame 갱신**
|
||||
- `frame-source`가 있고 대응되는 `frame/views/<view-id>/index.md`가 없으면 템플릿으로 만든다.
|
||||
- visual source가 있으면 frontmatter `visual_source`와 본문 `Visual Source`에 함께 기록한다.
|
||||
- visual source가 없으면 새 frame-view 문서를 만들지 않는다.
|
||||
- 기존 frame-view 문서의 visual source가 제거되고 더 이상 연결할 visual source가 없으면 frame-view 삭제 후보로 보고한다. 판단이 명확하면 삭제하고 view 문서의 `frame`을 `null`로 둔다.
|
||||
- Excalidraw visual source의 기본 후보 파일명은 `wire.excalidraw`다.
|
||||
- `.excalidraw`를 만들거나 수정하면 주요 박스 text label 또는 `customData.region_id`에 region id를 넣는다.
|
||||
- frame-view가 있으면 required region id는 view definition의 region id와 맞춘다.
|
||||
- 정의에 없는 region이 frame-view에 필요하면 바로 확정하지 않고 open question 또는 USER_REVIEW로 분리한다.
|
||||
|
||||
4. **USER_REVIEW 처리**
|
||||
- agent가 확정할 수 없는 화면 의도, region 추가/삭제, component 신규 생성 여부, page/drawer/split 선택은 `agent-ui/USER_REVIEW.md`에 남긴다.
|
||||
- USER_REVIEW 항목에는 `Source Skill: update-agent-ui`, `Stage: definition-edit`, `Blocking Step`을 남긴다.
|
||||
- 기존 USER_REVIEW 항목을 해결하는 변경이면 항목 상태를 갱신하고, 필요하면 `agent-ui/archive/user-review/user_review_N.log`로 이동한다.
|
||||
- 해결 로그를 만들 때는 현재 변경과 직접 관련된 항목만 이동한다.
|
||||
- `review-resolution`이 있으면 결정 내용을 관련 활성 definition/frame/component 문서에 먼저 반영한다.
|
||||
- 해결된 항목은 `agent-ui/archive/user-review/user_review_N.log`로 이동하고, 활성 `USER_REVIEW.md`에는 미해결 항목만 남긴다. 남은 항목이 없으면 활성 `USER_REVIEW.md`를 제거할 수 있다.
|
||||
- sync 실패 후 남은 작업트리 변경이 있고 사용자 결정과 충돌하지 않으면 보존한 채 후속 validate/sync에서 이어간다.
|
||||
|
||||
5. **후속 validate와 sync intent 판단**
|
||||
- `post-validate=false`가 아니고 view/component/frame/wireframe/source evidence/status 중 하나라도 바뀌었으면 `validate-agent-ui`를 실행한다.
|
||||
- `post-validate=true`이면 변경 크기와 무관하게 `validate-agent-ui`를 실행한다.
|
||||
- `post-sync=true` 또는 코드 반영이 필요한 `계획` 상태 변경이 있으면 sync intent를 `validate-agent-ui`에 전달한다.
|
||||
- `post-sync=false`이면 sync intent를 전달하지 않는다.
|
||||
- 후속 단계가 실행되면 순서는 항상 `validate-agent-ui` 다음 `sync-agent-ui`다.
|
||||
- 현재 변경 범위에 미해결 USER_REVIEW가 있으면 `sync-agent-ui`를 실행하지 않고 차단 항목을 보고한다.
|
||||
- 사용자가 "화면정의서와 코드가 안 맞아"처럼 불일치를 보고하면 관련 항목을 `계획`으로 되돌릴지 확인하고 validate/sync intent를 만든다.
|
||||
- sync intent를 만들더라도 코드 반영 방식이 direct-sync, plan-required, milestone-required 중 무엇인지는 판단하지 않는다.
|
||||
|
||||
6. **결과 보고**
|
||||
- 수정한 활성 정의 문서
|
||||
- 수정한 frame 문서와 visual source
|
||||
- frontmatter schema 변경 여부
|
||||
- archive log 변경 여부
|
||||
- USER_REVIEW 생성/갱신 여부
|
||||
- validate-agent-ui 실행 여부와 결과
|
||||
- sync-agent-ui 필요 여부와 실행/보류 사유
|
||||
- 남은 정합성 확인 항목
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] view/component는 folder-first + `index.md` 구조를 유지하는가
|
||||
- [ ] 새로 만들거나 수정한 활성 Markdown 문서가 `ui_doc_type` frontmatter를 포함하는가
|
||||
- [ ] 새로 만들거나 수정한 view/component에 `Source Evidence`와 `Status`가 있는가
|
||||
- [ ] 구현 근거 또는 sync 완료 없이 항목을 `구현됨`으로 표시하지 않았는가
|
||||
- [ ] frame-view가 있으면 view region id와 frame region id가 충돌하지 않는가
|
||||
- [ ] view에서 참조한 component id가 존재하거나 USER_REVIEW에 남았는가
|
||||
- [ ] visual source가 있으면 대응 frame index에 기록되었는가
|
||||
- [ ] visual source가 없는데 빈 frame-view 문서만 남아 있지 않은가
|
||||
- [ ] 현재 기준이 archive에만 남지 않았는가
|
||||
- [ ] 확정할 수 없는 UI 결정이 임의로 확정되지 않았는가
|
||||
- [ ] 후속 단계가 필요할 때 `validate-agent-ui`가 `sync-agent-ui`보다 먼저 실행되었는가
|
||||
- [ ] USER_REVIEW 해결 요청이면 결정이 활성 문서에 반영되고 해결 로그가 archive 되었는가
|
||||
- [ ] sync 실패 후 남은 작업트리를 임의로 버리지 않았는가
|
||||
- 검증 실패 시: 자동 보정 가능한 것은 보완하고, 판단이 필요한 것은 `agent-ui/USER_REVIEW.md`에 남긴다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```md
|
||||
## 갱신 완료
|
||||
|
||||
- 수정 파일: <목록>
|
||||
- view: <view-id 또는 없음>
|
||||
- component: <component-id 또는 없음>
|
||||
- frame source: <파일 또는 없음>
|
||||
- evidence/status: <요약 또는 없음>
|
||||
- frontmatter schema: <변경/유지/없음>
|
||||
- archive 변경: <내용 또는 없음>
|
||||
- USER_REVIEW: <생성/갱신/없음>
|
||||
- USER_REVIEW resolution: <해결/부분 해결/없음>
|
||||
- validate-agent-ui: <실행/PASS/WARN/FAIL/생략 사유>
|
||||
- sync-agent-ui: <실행/보류/생략 사유>
|
||||
- 확인 필요: <항목 또는 없음>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- `definition/archive/**`를 현재 기준으로 사용하지 않는다.
|
||||
- 코드나 문서 근거 없이 status를 확정하지 않는다.
|
||||
- 문서 근거만 있는 항목을 구현 완료 상태로 쓰지 않는다.
|
||||
- 사용자 판단이 필요한 UI 의도를 임의로 확정하지 않는다.
|
||||
- view/component id를 명시적 요청 없이 바꾸지 않는다.
|
||||
- `.excalidraw` 파일만 만들고 frame index를 생략하지 않는다.
|
||||
- visual source 없이 빈 frame-view 문서를 만들지 않는다.
|
||||
- agent-ui 갱신과 무관한 앱 구현 파일을 수정하지 않는다.
|
||||
- 코드 구현 규모에 따라 plan 또는 roadmap/milestone 라우팅을 확정하지 않는다.
|
||||
- `validate-agent-ui`를 거치지 않고 `sync-agent-ui`를 실행하지 않는다.
|
||||
- sync 실패 후 남은 코드 변경을 사용자 결정 없이 되돌리지 않는다.
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
---
|
||||
name: update-contract
|
||||
version: 1.0.0
|
||||
description: agent-contract inner/outer 계약 문서를 갱신하고 흩어진 계약 설명을 정리한다. 계약 업데이트해, 프로젝트 계약 업데이트해, 계약 갱신/수정/정리, contract update 요청에서 사용한다.
|
||||
---
|
||||
|
||||
# update-contract
|
||||
|
||||
## 목적
|
||||
|
||||
기존 `agent-contract/`의 inner/outer 계약 문서를 최신 코드와 문서 기준으로 갱신한다.
|
||||
계약 원문은 한 곳에 모으고, README/docs/rules에는 포인터와 경계 규칙만 남긴다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 계약 업데이트, 프로젝트 계약 업데이트, 계약 갱신, 계약 수정, 계약 정리를 요청할 때
|
||||
- API, runtime 호출, wire protocol, event/config schema 변경이 기존 계약에 영향을 줄 때
|
||||
- 계약 설명이 README/docs/rules/code review 과정에서 다시 흩어진 것을 정리할 때
|
||||
- legacy `provided/consumed` 계약을 `inner/outer` 모델로 점진 정리할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `contract-id`: 갱신할 계약 식별자 (선택, 없으면 index와 변경 diff에서 탐색)
|
||||
- `change`: 바뀐 내용 또는 정리할 문제 요약 (선택, 없으면 최근 변경/요청 맥락에서 산출)
|
||||
- `boundary`: `inner` 또는 `outer` (선택, 기존 문서 우선)
|
||||
- `canonical-path`: 갱신 기준이 되는 proto/OpenAPI/config/code 원본 경로 (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-contract/index.md` 존재 여부를 확인한다. 없으면 create-contract 흐름으로 전환할지 판단한다.
|
||||
- [ ] index에서 대상 계약 문서를 찾는다. 없으면 새 계약 생성 대상인지 판단한다.
|
||||
- [ ] 대상 계약 문서와 원본 경로를 읽는다.
|
||||
- [ ] 변경 범위와 관련된 코드, proto, config, 테스트를 읽어 실제 동작을 확인한다.
|
||||
- [ ] README/docs/rules에 계약 본문이 새로 중복 작성되었는지 검색한다.
|
||||
- [ ] legacy `provided/consumed/` 구조가 남아 있으면 현재 요청이 구조 migration인지 단순 계약 갱신인지 구분한다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **대상 확정**
|
||||
- index의 `Outer Contracts`/`Inner Contracts`에서 계약을 찾는다.
|
||||
- `contract-id`가 없으면 요청 키워드, 변경 파일, 코드 diff, README/docs/rules의 계약 설명을 기준으로 영향을 받는 계약을 좁힌다.
|
||||
- legacy index만 있으면 `provided`는 outer 후보, 프로젝트 내부 runtime/wire 계약은 inner 후보로 분류하되 즉시 이동하지 말고 변경 범위와 함께 판단한다.
|
||||
- 대상이 없고 요청이 계약 생성/정리까지 허용하면 create-contract 흐름으로 전환한다.
|
||||
- 대상이 없고 사용자가 특정 기존 계약 갱신만 요청했다면 대상 부재를 보고한다.
|
||||
|
||||
2. **코드 우선 분석**
|
||||
- 원본 경로를 먼저 확인한다.
|
||||
- 실제 parser/handler/DTO/interface/test에서 필드 의미와 허용/거부 동작을 확인한다.
|
||||
- 문서와 코드가 다르면 코드를 근거로 계약 문서를 갱신하고, 코드가 틀렸을 가능성이 있으면 사용자에게 후보를 제시한다.
|
||||
|
||||
3. **계약 문서 갱신**
|
||||
- 필드 의미, 금지 사항, 읽는 조건, 변경 시 테스트를 최신 상태로 맞춘다.
|
||||
- schema 원본 전체를 복제하지 않고 핵심 의미와 원본 경로를 유지한다.
|
||||
- 불확실한 값은 단정하지 않고 `확인 필요`로 남긴다.
|
||||
- `last updated` 같은 날짜 메타가 이미 있는 문서에서만 갱신한다. 없는 문서에 날짜 관례를 새로 만들지 않는다.
|
||||
|
||||
4. **index 갱신**
|
||||
- 읽는 조건이 새 API/field/message/protocol 이름을 포함하는지 확인한다.
|
||||
- path, 원본 경로, boundary가 실제 문서와 일치하는지 확인한다.
|
||||
- 중복 id, dead path, 존재하지 않는 원본 경로를 제거하거나 수정한다.
|
||||
- 프로젝트 전용 path trigger가 필요하면 `agent-contract/index.md` 또는 project/domain rule 포인터에 둔다. common rule에는 넣지 않는다.
|
||||
|
||||
5. **흩어진 문서 정리**
|
||||
- README/docs/rules에 계약 본문이 들어간 경우 계약 문서 포인터로 축소한다.
|
||||
- domain rule에는 책임 경계와 금지 사항만 남기고 상세 요청/응답 schema를 반복하지 않는다.
|
||||
- 테스트 문서에는 검증 기준만 남기고 계약 본문을 복제하지 않는다.
|
||||
- common rule에 특정 프로젝트 경로, 계약 id, API 이름이 새로 들어갔으면 제거하고 프로젝트 문서로 옮긴다.
|
||||
|
||||
6. **검증 판단**
|
||||
- 계약 문서만 바꿨으면 링크/path/index 정합성을 확인한다.
|
||||
- 원본 schema 또는 runtime 코드를 함께 바꿨으면 해당 domain/test rule의 검증 기준을 따른다.
|
||||
- proto/config schema를 바꿨으면 생성물 갱신 명령과 관련 테스트를 실행한다.
|
||||
|
||||
7. **결과 보고**
|
||||
- 수정한 계약 문서와 index
|
||||
- 코드 분석 근거
|
||||
- 중복 제거한 문서
|
||||
- 실행한 검증
|
||||
- 남은 확인 필요 항목
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] index가 대상 계약의 최신 path와 읽는 조건을 가리키는가
|
||||
- [ ] 계약 문서의 원본 경로가 실제 코드/proto/config와 맞는가
|
||||
- [ ] README/docs/rules에 같은 계약 본문이 중복 남아 있지 않은가
|
||||
- [ ] inner/outer boundary가 계약의 실제 소비자와 맞는가
|
||||
- [ ] 코드 분석 없이 문서만 추측해 갱신하지 않았는가
|
||||
- [ ] 변경 범위에 필요한 테스트 또는 링크 검증을 실행했는가
|
||||
- 검증 실패 시: index/path/원본 경로/중복 문서/테스트 누락을 보완한다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```md
|
||||
## 계약 업데이트 완료
|
||||
|
||||
- contract: agent-contract/<inner|outer>/<contract-name>.md
|
||||
- index: agent-contract/index.md
|
||||
- code evidence: <확인한 코드/proto/config/test>
|
||||
- pointers: <갱신한 README/docs/rules 경로 또는 없음>
|
||||
- verification: <실행한 명령 또는 생략 사유>
|
||||
- 확인 필요: <항목 또는 없음>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 코드와 원본 경로를 확인하지 않고 계약 문서만 고치지 않는다.
|
||||
- README/docs/rules에 계약 본문을 새로 복제하지 않는다.
|
||||
- 프로젝트 전용 path trigger를 common rule에 넣지 않는다.
|
||||
- 사용자 요청 없이 전체 계약 구조를 대량 migration하지 않는다.
|
||||
- 한 패키지 내부 구현 세부를 inner 계약으로 승격하지 않는다.
|
||||
- 계약 갱신과 무관한 리팩터링을 함께 수행하지 않는다.
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
name: update-roadmap
|
||||
description: 로드맵 업데이트, 로드맵에 추가, 마일스톤 추가·갱신, phase 변경, 전역 Milestone 실행 순서 갱신 요청에 사용한다. 기존 항목 upsert, runtime 완료 반영, 완료 후보 전환과 archive, workspace 외부 의존 잠금 동기화를 처리한다.
|
||||
version: 1.21.0
|
||||
description: 로드맵 업데이트, 로드맵에 추가, 마일스톤 추가/갱신, phase/페이즈 변경 요청에 사용한다. Roadmap-Phase-Milestone scaffold에서 target 없는 신규 작업의 규모를 판정하고 기존 Phase/Milestone/Epic/Task를 검색해 upsert한 뒤, 없을 때만 새 항목을 만들고 로컬 current.md 동기화, runtime m-task 완료 이벤트 반영, 완료 후보 검토중 전환, 완료 근거 충족 archive 이동, workspace 외부 의존 잠금 양방향 동기화를 처리한다.
|
||||
---
|
||||
|
||||
# 로드맵 업데이트
|
||||
|
|
@ -8,10 +9,10 @@ description: 로드맵 업데이트, 로드맵에 추가, 마일스톤 추가·
|
|||
## 목적
|
||||
|
||||
기존 `agent-roadmap/` 구조를 현재 프로젝트 방향과 진행 상태에 맞게 갱신한다.
|
||||
표준 구조는 `ROADMAP.md -> priority-queue.md -> phase/<phase-slug>/PHASE.md -> phase/<phase-slug>/milestones/<milestone-slug>.md`다.
|
||||
표준 구조는 `ROADMAP.md -> phase/<phase-slug>/PHASE.md -> phase/<phase-slug>/milestones/<milestone-slug>.md`다.
|
||||
archive도 같은 Phase scaffold를 유지하며 `archive/phase/<phase-slug>/...` 아래에 둔다.
|
||||
로드맵 전체를 매 작업마다 읽지 않도록 유지하면서, 브랜치별 로컬 `current.md`의 활성 Phase와 활성 Milestone 창이 실제 작업 후보 목록으로 동작하게 한다.
|
||||
`priority-queue.md`는 Phase를 가로지르는 실행 순서만 담당하며, Milestone 상세 정보는 복제하지 않는다.
|
||||
|
||||
Milestone은 구현 계획이 아니라 방향성, 범위, 위험, 확인 필요 사항을 기록하는 협업 문서로 유지한다.
|
||||
Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능` 안에서 관리한다. 별도 `완료 기준` 섹션은 만들지 않고, 검증이 필요한 기능에만 같은 Task 안의 `검증:` 문구로 통합한다.
|
||||
|
||||
|
|
@ -26,9 +27,6 @@ Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능
|
|||
- 특정 기능이나 작업을 새 Milestone, 기존 Milestone의 Epic, 기존 Epic의 Task 중 적절한 위치에 추가해야 할 때
|
||||
- 활성 Phase/Milestone 창에 포함할 목록이 달라졌을 때
|
||||
- 기존 로드맵을 `phase/<phase-slug>/PHASE.md` scaffold로 마이그레이션하거나 표준화해야 할 때
|
||||
- 사용자가 "순서 바꿔", "이거 먼저", "이거 뒤로", "우선순위 재정렬"처럼 전역 Milestone 실행 순서 변경을 요청할 때
|
||||
- `priority-queue.md`에 있는 Milestone이 archive, 폐기, 경로 변경, split/merge, 또는 실행 의미가 바뀔 정도로 수정되어 큐 정리가 필요할 때
|
||||
- `priority-queue.md` 링크가 깨져 활성 Milestone 문서 기준으로 큐를 재정렬하거나 재생성해야 할 때
|
||||
- 사용자가 "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"처럼 외부 의존 잠금을 말할 때
|
||||
|
||||
## 입력
|
||||
|
|
@ -54,14 +52,12 @@ Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능
|
|||
- `origin-task`: 런타임 완료 이벤트가 전달한 `agent-task/m-<milestone-slug>` 또는 `agent-task/m-<milestone-slug>/<subtask_dir>` 형식의 원래 active task 경로. 이벤트가 최종 archive 경로만 갖고 있으면 런타임이 이 형식으로 정규화해 전달한다 (선택)
|
||||
- `archive-date`: Phase/Milestone 아카이브 날짜. 없으면 현재 날짜를 사용한다 (선택)
|
||||
- `workspace-lock`: 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`에 기록하거나 동기화할 외부 의존 잠금 설명 (선택)
|
||||
- `priority-queue-order`: `agent-roadmap/priority-queue.md`에 반영할 Milestone 경로/제목 순서 목록. 사용자가 순서 조정을 명시한 경우에만 사용한다 (선택)
|
||||
|
||||
## 표준 구조
|
||||
|
||||
```text
|
||||
agent-roadmap/
|
||||
ROADMAP.md
|
||||
priority-queue.md
|
||||
current.md # local, git ignored
|
||||
phase/
|
||||
<phase-slug>/
|
||||
|
|
@ -85,8 +81,7 @@ agent-roadmap/
|
|||
SDD.md
|
||||
```
|
||||
|
||||
- `ROADMAP.md`는 전체 목표와 Phase 흐름, `priority-queue.md` 고정 라우팅만 담는다.
|
||||
- `priority-queue.md`는 Phase를 가로지르는 Milestone 실행 순서만 담는다. 항목은 Milestone 제목 링크와 식별용 한 줄 설명만 둔다.
|
||||
- `ROADMAP.md`는 전체 목표와 Phase 흐름만 담는다.
|
||||
- `PHASE.md`는 해당 Phase의 목표, 상태, Milestone 흐름, Phase 경계를 담는다.
|
||||
- Milestone 문서는 해당 Phase 하위 `milestones/`에 둔다.
|
||||
- 완료된 Phase는 `archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
|
||||
|
|
@ -100,7 +95,6 @@ agent-roadmap/
|
|||
- `current.md`는 git 추적 대상이 아니며, 공유 진행 상태는 `ROADMAP.md`, `PHASE.md`, Milestone 문서, `.agent-roadmap-sync/locks.yaml`에 기록한다.
|
||||
- `current.md`에는 archive 경로를 넣지 않는다.
|
||||
- `current.md`에는 `[완료]` 또는 `[폐기]` Phase/Milestone을 남기지 않는다. 완료 후보는 완료 근거와 archive 전환이 정리될 때까지 `[검토중]`으로 둔다.
|
||||
- `priority-queue.md`에는 archive 경로를 넣지 않는다. 완료 Milestone은 archive 시 제거하고, 폐기 Milestone은 큐에서 제거한다.
|
||||
|
||||
## 상태와 id
|
||||
|
||||
|
|
@ -114,12 +108,8 @@ agent-roadmap/
|
|||
- `[검토중]`은 모든 기능 Task와 Task 안에 명시된 검증이 충족되고 `구현 잠금`이 해제되었으나, 완료 근거 정리와 archive 전환이 남은 완료 후보 상태다.
|
||||
- 검토 결과 보완이 필요하면 별도 reopen 상태를 만들지 않고 `[진행중]`으로 되돌린 뒤 `완료 리뷰` 또는 `작업 컨텍스트`에 보완 방향을 남긴다.
|
||||
- 검토 결과 보류 또는 폐기 결정이 나면 `[보류]` 또는 `[폐기]`로 전환한다.
|
||||
- `ROADMAP.md`의 Phase 흐름은 실행 순서가 아니라 도메인/책임 영역의 구조적 지도다. 상태 그룹은 완료, 검토중, 진행중, 계획, 스케치 순서를 기본으로 하되 실제 다음 작업 선택은 `priority-queue.md`를 우선한다.
|
||||
- `PHASE.md`의 Milestone 흐름은 해당 Phase 안의 상태 정리 흐름이다. Phase를 가로지르는 실행 순서로 해석하지 않는다.
|
||||
- `ROADMAP.md`의 Phase 흐름과 `PHASE.md`의 Milestone 흐름은 완료, 검토중, 진행중, 계획, 스케치 순서를 기본으로 하며 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||
- Epic heading은 `### Epic: [epic-id] <이름>` 형식으로 작성한다.
|
||||
- 새 Epic과 기능 Task를 추가하거나 구조를 갱신하는 기존 Epic에는 기능 Task를 최대 5개만 둔다. 갱신 범위 밖 기존 Epic은 자동으로 재구성하지 않는다.
|
||||
- 여섯 번째 Task가 필요하면 capability, 산출물, 의존성, 검증 경계 중 하나로 기존 Epic을 둘 이상으로 분리한다. 분리 후에도 독립 목표가 남으면 새 Milestone 후보로 둔다.
|
||||
- 갱신 범위에 포함된 기존 Epic이 이미 6개 이상이면 같은 기준으로 분리한다. 이때 기존 item-id는 사용자가 명시하지 않는 한 바꾸지 않는다.
|
||||
- Task는 `- [ ] [item-id] 설명` 또는 `- [x] [item-id] 설명` 형식으로 작성한다.
|
||||
- epic-id와 item-id는 공백 없는 짧은 ASCII 토큰이며, 해당 Milestone 안에서만 유일하면 된다.
|
||||
- 사용자가 epic-id 또는 item-id를 언급하면 해당 항목을 우선 anchor로 삼고, 기존 id는 명시적 요청 없이 바꾸지 않는다.
|
||||
|
|
@ -129,7 +119,6 @@ agent-roadmap/
|
|||
- 일반 갱신은 로컬 `current.md`, 관련 활성 Phase, 관련 활성 Milestone을 우선 읽는다.
|
||||
- `current.md`가 없고 활성 창 갱신이 필요하면 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식으로 로컬 파일을 만든다.
|
||||
- `ROADMAP.md`는 Phase 흐름, 전체 구조, 활성 범위 밖 작업, 전체 재계획, archive 링크 갱신이 필요할 때 읽는다.
|
||||
- `priority-queue.md`는 Phase를 가로지르는 다음 작업 후보 선택, 사용자가 요청한 순서 조정, archive/폐기/경로 변경/split/merge 후 큐 정리, 깨진 링크 복구가 필요할 때 읽고 갱신한다.
|
||||
- `agent-roadmap/archive/**`는 일반 작업이나 sync에서 읽지 않는다.
|
||||
- archive 모드에서 이동 대상이 아직 활성 경로에 있으면 그 대상 문서는 읽을 수 있다.
|
||||
- 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 요청이면 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라 필요한 archive 문서만 읽는다.
|
||||
|
|
@ -137,37 +126,22 @@ agent-roadmap/
|
|||
## 템플릿
|
||||
|
||||
- `ROADMAP.md`: `agent-ops/skills/common/_templates/roadmap-template.md`
|
||||
- `priority-queue.md`: `agent-ops/skills/common/_templates/roadmap-priority-queue-template.md`
|
||||
- `current.md`: `agent-ops/skills/common/_templates/roadmap-current-template.md`
|
||||
- `PHASE.md`: `agent-ops/skills/common/_templates/roadmap-phase-template.md`
|
||||
- Milestone: `agent-ops/skills/common/_templates/roadmap-milestone-template.md`
|
||||
- SDD: `agent-ops/skills/common/_templates/roadmap-sdd-template.md`
|
||||
- SDD 사용자 리뷰: `agent-ops/skills/common/_templates/roadmap-sdd-user-review-template.md`
|
||||
|
||||
## 링크 표기
|
||||
|
||||
- 사용자에게 보여주는 결과 보고와 새로 생성/갱신하는 로드맵 문서에서 `ROADMAP.md`, `priority-queue.md`, `current.md`, `PHASE.md`, Milestone 문서, SDD, `USER_REVIEW.md`, archive 문서, `complete.log` 같은 문서/산출물 포인터는 raw path만 쓰지 말고 `[표시 제목](상대경로)` Markdown 링크로 쓴다.
|
||||
- 로드맵 문서 안의 링크 target은 링크를 작성하는 Markdown 파일 위치 기준 상대경로로 쓴다. 예: `ROADMAP.md`와 `current.md`에서는 `[PHASE.md](phase/<phase-slug>/PHASE.md)`, Phase 문서에서는 `[Milestone](milestones/<milestone-slug>.md)`, Milestone 문서에서는 `[ROADMAP.md](../../../ROADMAP.md)`와 `[PHASE.md](../PHASE.md)`를 쓴다.
|
||||
- 채팅 결과 보고처럼 저장 위치가 없는 출력은 repo root 기준 상대경로를 쓸 수 있다. 예: `[PHASE.md](agent-roadmap/phase/<phase-slug>/PHASE.md)`.
|
||||
- `경로:`, `Phase:`, `Milestone:`, `SDD 문서:`, `수정 파일:` 같은 필드명을 유지해야 해도 값은 Markdown 링크로 작성한다.
|
||||
- 실제 갱신한 활성 로드맵 문서에는 `<phase-slug>`, `<milestone-slug>`, `<relative-...>` 같은 placeholder가 들어간 링크 target을 남기지 않는다. 템플릿 placeholder는 실제 파일 위치 기준 상대경로 또는 `없음`으로 치환한다.
|
||||
- 기존 문서에 남아 있는 raw path나 backtick path는 읽기/마이그레이션 입력으로 허용한다. 갱신 범위에 포함된 활성 문서 포인터만 Markdown 링크로 보정하고, archive 스냅샷은 링크 표기만을 이유로 재포맷하지 않는다.
|
||||
- `.agent-roadmap-sync/locks.yaml`의 `locked`, `rely-on.target`, Milestone identity(`<project>:agent-roadmap/...`), 명령 입력값처럼 machine-readable 계약 값은 raw 값을 유지할 수 있다. 다만 사용자-facing 설명에는 가능한 경우 별도 Markdown 문서 링크를 함께 붙인다.
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- `구현 잠금`은 승인 절차가 아니라 에이전트가 확정할 수 없는 결정이 필요한지 표시하는 얇은 상태다.
|
||||
- 제품 방향, 범위, 우선순위, 책임 경계처럼 에이전트가 확정할 수 없는 항목이 남아 있으면 `잠금`으로 두고 `결정 필요` 목록에 남긴다.
|
||||
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 합리적으로 정할 수 있는 항목은 `결정 필요`가 아니라 `작업 컨텍스트`의 표준선으로 기록한다.
|
||||
- Milestone 전체에서 에이전트가 확정할 수 없는 결정 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
|
||||
- `구현 잠금` 섹션이 없거나, 상태가 `잠금`이거나, 미완료 `결정 필요` 항목이 하나라도 있으면 실구현 계획, 코드 구현, Milestone 완료 후보 전환을 차단한다.
|
||||
- `구현 잠금` 섹션이 없거나, 상태가 `잠금`이거나, 미완료 `결정 필요` 항목이 하나라도 있으면 실구현 plan, 코드 구현, Milestone 완료 후보 전환을 차단한다.
|
||||
- 잠금 상태에서 허용되는 갱신은 잠금 해소, SDD gate 처리, 범위 제외/후속 Milestone 이동, 작업 컨텍스트 정리 같은 roadmap-only 변경뿐이다.
|
||||
- 남은 `결정 필요` 항목이 현재 Milestone 실구현 범위가 아니면 먼저 그 항목을 `범위 제외`, 후속 Milestone, 또는 `작업 컨텍스트`로 옮긴 뒤 `구현 잠금`을 `해제`한다. 잠금 해제 전에는 기능 Task 완료 근거가 있어도 `[검토중]`으로 올리지 않는다.
|
||||
- SDD gate가 필요한 Milestone은 `구현 잠금`에 `SDD: 필요`, 해당 Milestone 파일 위치 기준 `SDD 문서` Markdown 링크, 잠금 해제 조건을 남기고 SDD 잠금이 해제될 때까지 `잠금`으로 둔다.
|
||||
- 새 Milestone을 만들거나 `[스케치]`를 `[계획]`으로 승격하면서 `SDD: 필요`로 판정한 경우, 같은 `update-roadmap` 흐름 안에서 `roadmap-sdd create`까지 수행해 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`를 만든다. `SDD: 필요`와 SDD 문서 링크만 남기고 파일이 없는 상태로 종료하지 않는다.
|
||||
- SDD 작성에 필요한 목표, 범위, 기능 Task, Acceptance Scenario 후보를 이미 판단했고 사용자만 결정할 항목이 없으면 SDD 상태를 `[승인됨]`, SDD 잠금을 `해제`로 두고 Milestone `구현 잠금`도 `해제`한다.
|
||||
- 사용자만 결정할 항목이 있으면 SDD 초안을 만들고 `roadmap-sdd review-ready` 방식으로 `USER_REVIEW.md`를 남긴다. 이 경우 Milestone `구현 잠금`은 `잠금`으로 둔다.
|
||||
- SDD 파일을 만들 수 없는 예외는 사용자가 명시적으로 SDD 생성을 뒤로 미룬 경우뿐이다. 이때 결과 보고에 `SDD gate: 필요-작성 전`과 구체적인 지연 사유를 남긴다.
|
||||
- SDD gate가 필요한 Milestone은 `구현 잠금`에 `SDD: 필요`, SDD 경로, 잠금 해제 조건을 남기고 SDD 잠금이 해제될 때까지 `잠금`으로 둔다.
|
||||
- SDD gate가 불필요한 Milestone은 `SDD: 불필요`과 짧은 사유를 남긴다.
|
||||
- SDD가 필요한 기준: cross-repo 계약, 외부 provider 쓰기, 상태 머신/lifecycle, idempotency/retry/identity map, API/proto/config/env/schema 변경, field smoke, 사용자 승인 gate 영향.
|
||||
- SDD 사용자 리뷰가 필요한 결정은 chat으로 즉시 묻지 않고 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md`에 남긴다.
|
||||
|
|
@ -224,7 +198,7 @@ agent-roadmap/
|
|||
- target이 없거나 둘 이상이면 Milestone 내용을 추정해 수정하지 말고 target 불명확으로 보고한다.
|
||||
- target이 확정되어도 `complete-log` 입력이 없거나 해당 파일에 `Roadmap Completion` 섹션이 없으면 Milestone 기능 Task를 체크하지 않고 no-op으로 보고한다. 일반 `m-*` 완료 이벤트만으로 Task를 추정해 체크하지 않는다.
|
||||
- `Roadmap Completion` 섹션이 있으면 Milestone 경로가 target과 일치하는지, Completed task ids의 각 id가 해당 Milestone의 기존 기능 Task id 하나와 정확히 일치하는지 확인한다. 하나라도 일치하지 않으면 수정하지 말고 target 불일치로 보고한다.
|
||||
- target Milestone이 `SDD: 필요`이면 런타임 완료 이벤트의 `complete-log`에 있는 `Roadmap Completion`과 최종 검증 evidence가 SDD `Evidence Map`을 충족해야 한다. 사용자가 `update-roadmap` 요청에 별도 evidence를 명시해 수동 반영을 요구한 경우에만 Evidence Map 충족 근거를 보조 근거로 사용할 수 있다. 근거가 없으면 `Roadmap Completion`이 있어도 Task를 체크하지 않고 SDD evidence 부족으로 보고한다.
|
||||
- target Milestone이 `SDD: 필요`이면 런타임 완료 이벤트의 `complete-log`에 `Spec Completion` 섹션이 있어야 한다. SDD `Evidence Map`은 `Spec Completion`이 무엇을 증명해야 하는지 판단하는 기준이며, 런타임 완료 이벤트에서는 단독 대체 근거로 쓰지 않는다. 사용자가 `update-roadmap` 요청에 별도 evidence를 명시해 수동 반영을 요구한 경우에만 Evidence Map 충족 근거를 보조 근거로 사용할 수 있다. 근거가 없으면 `Roadmap Completion`이 있어도 Task를 체크하지 않고 SDD evidence 부족으로 보고한다.
|
||||
- 일치하면 PASS evidence, `complete.log`, final archive path, archived plan/review log 경로, code-review 결과 요약을 근거로 `Roadmap Completion`에 적힌 기능 Task만 `[x]`로 갱신한다. target routing 자체는 완료 이벤트의 `m-<milestone-slug>` task group과 `complete.log`의 `Roadmap Completion` 섹션으로 결정한다.
|
||||
- 갱신 후 모든 기능 Task와 Task 안에 명시된 검증이 충족되어도 `구현 잠금`이 해제되어 있지 않으면 `[검토중]` 전환을 하지 않고 잠금 차단으로 보고한다. 기능 Task와 구현 잠금이 모두 충족될 때만 `[검토중]` 전환과 `완료 리뷰` 요청 규칙을 적용한다.
|
||||
- target Milestone이 `[스케치]`이면 완료 이벤트를 반영하지 말고 상태 불일치로 보고한다. `[스케치]`는 Milestone 기반 `agent-task` 완료 이벤트의 target이 될 수 없다.
|
||||
|
|
@ -244,7 +218,6 @@ agent-roadmap/
|
|||
- 요청이 방향성, 문제의식, 컨셉, 운영 원칙 수준이고 기능 Task나 실행 범위가 아직 부족하면 새 항목의 상태는 `[스케치]`로 둔다.
|
||||
- `[스케치]` Phase/Milestone을 만들 때는 `승격 조건`에 `[계획]`으로 전환하기 위해 필요한 정의, 결정, 경계, 후속 구현 Milestone 후보를 체크리스트로 남긴다.
|
||||
- 가장 작은 충분한 단위 원칙을 따른다. 애매하면 새 Phase나 새 Milestone으로 키우지 말고, 기존 Milestone의 Epic/Task에 넣을 수 있는지 먼저 확인한다.
|
||||
- 기존 Epic에 기능 Task가 5개 있으면 새 Task를 추가하지 않는다. 여섯 번째 Task는 capability, 산출물, 의존성, 검증 경계 중 하나로 분리한 새 Epic에 배치하고, 분리된 Epic이 독립 목표면 새 Milestone 후보로 재판정한다.
|
||||
- 위치 지정이 있으면 anchor의 레벨을 먼저 확인한다.
|
||||
- `<epic-id> 아래`는 해당 Epic 아래 Task로 넣는다.
|
||||
- `<item-id> 앞/뒤`는 같은 Epic 안의 형제 Task로 넣는다.
|
||||
|
|
@ -304,7 +277,6 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- 대상 파일을 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`에서 `agent-roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 이동한다.
|
||||
- 활성 SDD 디렉터리 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/`가 있으면 `agent-roadmap/archive/sdd/<phase-slug>/<milestone-slug>/`로 이동한다. `USER_REVIEW.md`가 남아 있으면 archive하지 말고 해결 필요로 보고한다.
|
||||
- 활성 `PHASE.md`의 Milestone 흐름에는 `[완료]` 또는 `[폐기]` 항목을 남기고, 경로는 archive 경로로 바꾼다.
|
||||
- `priority-queue.md`가 있으면 대상 Milestone의 활성 경로 항목을 제거한다. archive 경로로 바꿔 남기지 않는다.
|
||||
- 로컬 `current.md`의 활성 Milestone에서는 제거한다.
|
||||
- `ROADMAP.md`는 Phase 상태나 경로가 바뀌지 않으면 수정하지 않는다.
|
||||
- 이동한 archive 문서는 스냅샷으로 보존하고 최신 템플릿에 맞춰 재포맷하지 않는다.
|
||||
|
|
@ -316,7 +288,6 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- `agent-roadmap/phase/<phase-slug>/PHASE.md`를 `agent-roadmap/archive/phase/<phase-slug>/PHASE.md`로 이동한다.
|
||||
- 해당 Phase의 하위 Milestone도 `archive/phase/<phase-slug>/milestones/` 아래로 이동한다.
|
||||
- `ROADMAP.md`의 Phase 흐름에는 해당 Phase 항목을 남기고, 상태와 경로를 archive `PHASE.md`로 바꾼다.
|
||||
- `priority-queue.md`가 있으면 해당 Phase 하위 활성 Milestone 항목을 모두 제거한다. archive 경로로 바꿔 남기지 않는다.
|
||||
- 로컬 `current.md`의 활성 Phase와 활성 Milestone에서는 해당 Phase와 하위 Milestone을 제거한다.
|
||||
- archive 문서는 스냅샷으로 보존하고 최신 템플릿에 맞춰 재포맷하지 않는다.
|
||||
|
||||
|
|
@ -325,9 +296,8 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
1. **갱신 범위 결정**
|
||||
- 요청에서 mode, 대상 Phase/Milestone, placement, placement-unit을 추론한다.
|
||||
- 런타임 완료 이벤트의 `origin-task` task group이 `m-<milestone-slug>`이면 `target-milestone`을 활성 Milestone 경로 매칭으로 확정한다.
|
||||
- 런타임 완료 이벤트가 `complete-log`를 전달하면 파일을 읽고 `Roadmap Completion` 섹션 유무와 Completed task ids를 확인한다. 섹션이 없으면 Milestone 기능 Task 체크는 no-op이다. SDD 대상 Milestone이면 SDD `Evidence Map` 충족 여부도 확인한다.
|
||||
- 런타임 완료 이벤트가 `complete-log`를 전달하면 파일을 읽고 `Roadmap Completion` 섹션 유무와 Completed task ids를 확인한다. 섹션이 없으면 Milestone 기능 Task 체크는 no-op이다. SDD 대상 Milestone이면 `Spec Completion`도 확인한다.
|
||||
- 구조 전환, 템플릿 보정, current 동기화는 `sync`로 본다.
|
||||
- `priority-queue.md` 생성, 순서 조정, 깨진 링크 복구, archive/폐기/경로 변경/split/merge 후 큐 정리는 `sync` 또는 `replan`으로 본다.
|
||||
- 완료/폐기 근거가 충족된 이동은 `archive`로 본다.
|
||||
- 새 기능 배치, Epic/Task 추가는 `milestone` 또는 `phase`로 본다.
|
||||
- "로드맵에 추가"처럼 target이 없는 신규 작업 요청은 `placement=auto`, `placement-unit=auto`, `new-feature=<요청 내용>`으로 본다.
|
||||
|
|
@ -346,11 +316,10 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- 로컬 `current.md`의 활성 Phase와 활성 Milestone 후보를 확인한다.
|
||||
- target이 명시된 경우 대상 Phase의 `PHASE.md`를 읽고 Milestone 흐름과 Phase 경계를 확인한다.
|
||||
- target이 없거나 활성 창 밖 배치 가능성이 있으면 `ROADMAP.md`의 Phase 흐름을 확인하고, 관련성이 높은 Phase 문서를 읽는다.
|
||||
- 대상 또는 후보 Milestone 문서의 목표, 상태, 승격 조건, 범위, 기능 Task, 완료 리뷰, 범위 제외, 구현 잠금을 확인한다. SDD가 필요한 Milestone이면 SDD 문서 링크와 사용자 리뷰 상태도 확인한다. 기존 문서에 `필수 기능`/`완료 기준`이 분리되어 있으면 갱신 범위에서 `기능` Task로 흡수할 후보를 기록한다.
|
||||
- 대상 또는 후보 Milestone 문서의 목표, 상태, 승격 조건, 범위, 기능 Task, 완료 리뷰, 범위 제외, 구현 잠금을 확인한다. SDD가 필요한 Milestone이면 SDD 경로와 사용자 리뷰 상태도 확인한다. 기존 문서에 `필수 기능`/`완료 기준`이 분리되어 있으면 갱신 범위에서 `기능` Task로 흡수할 후보를 기록한다.
|
||||
- Phase -> Milestone -> Epic -> Task 순서로 내려가며 같은 레벨의 동일/유사 후보를 먼저 찾는다.
|
||||
- 로컬 `current.md`에 archive 경로가 있으면 읽지 말고 제거 대상으로 기록한다.
|
||||
- 필요한 경우에만 `ROADMAP.md`를 읽어 전체 Phase 흐름을 확인한다.
|
||||
- Phase를 가로지르는 다음 작업 후보를 고르거나 큐 정리가 필요하면 `priority-queue.md`를 읽는다. 링크가 깨진 항목은 추측하지 말고 활성 `phase/*/milestones/*.md` 후보를 기준으로 재정렬 또는 재생성 대상으로 기록한다.
|
||||
|
||||
4. **스케치 승격 판단**
|
||||
- `target-status=[계획]`, `mode=concretize`, 또는 사용자가 "구체화", "계획으로 올려"처럼 요청하면 `[스케치] -> [계획]` 승격 검토로 본다.
|
||||
|
|
@ -362,22 +331,17 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
|
||||
5. **변경 내용 작성**
|
||||
- `ROADMAP.md`는 전체 목표, Phase 흐름, 로딩 정책이 바뀔 때만 수정한다.
|
||||
- `priority-queue.md`가 없고 로드맵 구조를 표준화하거나 생성/동기화하는 요청이면 `roadmap-priority-queue-template.md` 형식으로 만든다.
|
||||
- `priority-queue.md`는 사용자 순서 조정 요청, archive/폐기 제거, 경로 변경, split/merge, 실행 의미 변경, 깨진 링크 복구 때만 수정한다.
|
||||
- `priority-queue.md`를 수정할 때는 Milestone 제목 링크와 식별용 한 줄 설명만 남기고, 상태, 목표, 범위, 잠금, 기능, 완료 근거, 의존성 필드를 복제하지 않는다.
|
||||
- 로컬 `current.md`는 활성 Phase/Milestone 창이 바뀔 때 수정한다.
|
||||
- `.gitignore`의 Agent-Ops 관리 block에 `agent-roadmap/current.md`가 있는지 확인하고 없으면 추가한다.
|
||||
- `PHASE.md`는 Phase 목표, 상태, Milestone 흐름, Phase 경계가 바뀔 때 수정한다.
|
||||
- Milestone 문서는 목표, 상태, 승격 조건, 구현 잠금, 범위, Epic/Task, Task 안의 검증 문구, 완료 리뷰, 범위 제외, 작업 컨텍스트가 바뀔 때 수정한다.
|
||||
- 신규 또는 갱신 Milestone이 SDD 대상이면 `구현 잠금`에 `SDD: 필요`, 해당 Milestone 파일 위치 기준 `SDD 문서` Markdown 링크, 잠금 해제 조건을 남기고 같은 흐름에서 `roadmap-sdd create`로 SDD 본문을 작성한다. 사용자 결정이 필요 없고 gate가 충족되면 SDD와 Milestone 잠금을 함께 해제한다.
|
||||
- 신규 또는 갱신 Milestone이 SDD 대상이면 `구현 잠금`에 `SDD: 필요`, SDD 경로, 잠금 해제 조건을 남긴다. SDD 본문 작성은 `roadmap-sdd` 스킬 책임이다.
|
||||
- SDD 대상이 아니면 `구현 잠금`에 `SDD: 불필요`와 짧은 사유를 남긴다.
|
||||
- 동일/유사 후보가 있으면 기존 항목을 업데이트하고 중복 항목을 만들지 않는다.
|
||||
- 새 Milestone은 해당 Phase의 `milestones/` 아래에 만든다.
|
||||
- 새 `[스케치]` Milestone은 `승격 조건` 섹션을 포함하고 `구현 잠금`은 `잠금`으로 둔다.
|
||||
- 새 Epic은 `기능` 아래 `### Epic: [epic-id] <이름>`으로 만든다.
|
||||
- 새 Task는 관련 Epic의 기능 Task가 5개 미만일 때만 `- [ ] [item-id] 설명`으로 만든다. 검증이 필요한 경우에만 같은 항목에 `검증: <명령/확인 방법/기대 결과>`를 붙인다.
|
||||
- 관련 Epic에 여섯 번째 Task가 필요하면 capability, 산출물, 의존성, 검증 경계 중 하나로 Epic을 분리한 뒤 새 Task를 배치한다. 분리된 Epic이 독립 목표면 새 Milestone 후보로 재판정한다.
|
||||
- 갱신 범위에 포함된 기존 Epic이 6개 이상이면 새 Task를 쓰기 전에 같은 기준으로 Epic을 분리한다. 기존 item-id는 사용자가 명시하지 않는 한 유지한다.
|
||||
- 새 Task는 관련 Epic 아래 `- [ ] [item-id] 설명`으로 만든다. 검증이 필요한 경우에만 같은 항목에 `검증: <명령/확인 방법/기대 결과>`를 붙인다.
|
||||
- 새 항목은 레벨별 탐색에서 적절한 기존 후보가 없을 때만 만든다.
|
||||
- 완료 체크는 evidence가 있을 때만 `[x]`로 바꾼다.
|
||||
- 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`이어도 `구현 잠금`이 `해제`가 아니거나 미완료 `결정 필요` 항목이 있으면 Milestone 상태를 `[검토중]`으로 바꾸지 않는다. `완료 리뷰` 또는 `작업 컨텍스트`에 잠금 차단 항목을 남긴다.
|
||||
|
|
@ -395,16 +359,12 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- archive 모드에서 보존한 active Milestone identity와 일치하는 `rely-on.target`도 archive 이동 전에 Milestone 상태 기준으로 `enable` 또는 `disable`을 동기화한다.
|
||||
- 갱신하거나 선택한 Milestone identity와 일치하는 `locked` entry가 있으면 모든 `rely-on.status`가 `enable`인지 확인하고 결과 보고에 남긴다.
|
||||
- archive 모드에서 보존한 active Milestone identity와 일치하는 `locked` entry도 archive 이동 전에 모든 `rely-on.status`가 `enable`인지 확인하고 결과 보고에 남긴다.
|
||||
- archive, 폐기, 경로 변경, split/merge 결과로 `priority-queue.md`를 수정했다면 제거/갱신된 항목을 결과 보고에 남긴다.
|
||||
|
||||
6. **검증**
|
||||
- 로컬 `current.md`의 활성 Phase/Milestone 경로가 실제 파일을 가리키는지 확인한다.
|
||||
- 로컬 `current.md`의 활성 항목이 archive 경로를 가리키지 않는지 확인한다.
|
||||
- 로컬 `current.md`의 활성 항목이 `[완료]` 또는 `[폐기]` 상태로 남아 있지 않은지 확인한다.
|
||||
- `agent-roadmap/current.md`가 git 추적 대상으로 남아 있지 않은지 확인한다.
|
||||
- `agent-roadmap/priority-queue.md`가 있으면 `실행 순서` 섹션이 있고 모든 링크가 실제 활성 Milestone 파일을 가리키는지 확인한다.
|
||||
- `priority-queue.md`에 archive 경로, `[완료]` archive 대상, `[폐기]` Milestone 항목이 남아 있지 않은지 확인한다.
|
||||
- `priority-queue.md`가 비어 있는데 활성 실행 후보가 있으면 큐 동기화 필요로 보고한다. 실행 후보가 없으면 빈 큐를 허용한다.
|
||||
- `ROADMAP.md`의 Phase 경로가 실제 `PHASE.md` 파일을 가리키는지 확인한다.
|
||||
- 각 `PHASE.md`의 Milestone 경로가 실제 파일을 가리키는지 확인한다.
|
||||
- 상태 표기가 표준값인지 확인한다.
|
||||
|
|
@ -415,8 +375,8 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- 모든 기능 Task와 Task 안에 명시된 검증이 `[x]`인 Milestone은 `구현 잠금`이 해제되어야 `[검토중]`이 될 수 있다. 잠금이 남아 있으면 `완료 리뷰` 또는 `작업 컨텍스트`에 잠금 차단 항목이 있는지 확인한다.
|
||||
- `[검토중]` Milestone에는 `완료 리뷰` 섹션과 완료 근거/남은 차단 항목이 있는지 확인한다.
|
||||
- 각 Milestone의 `구현 잠금`에 SDD 필요 여부와 사유가 있는지 확인한다.
|
||||
- `SDD: 필요` Milestone은 SDD 문서 링크, SDD 파일 존재, 잠금 해제 조건, SDD 사용자 리뷰 상태가 일관되는지 확인한다. 사용자가 명시적으로 SDD 생성을 뒤로 미루지 않았는데 SDD 파일이 없으면 검증 실패로 본다.
|
||||
- Epic heading과 Task id 형식이 맞고, 새 Epic과 갱신 범위에 포함된 기존 Epic의 기능 Task 수가 최대 5개인지 확인한다. 6개 이상이면 검증 실패로 보고하고 Epic 분리를 요구한다.
|
||||
- `SDD: 필요` Milestone은 SDD 경로, 잠금 해제 조건, SDD 사용자 리뷰 상태가 일관되는지 확인한다.
|
||||
- Epic heading과 Task id 형식이 맞는지 확인한다.
|
||||
- 요청 규모가 판정되었고 결과 보고에 남았는지 확인한다.
|
||||
- 동일/유사 기존 항목을 검색했고 신규/업데이트 판정이 결과 보고에 남았는지 확인한다.
|
||||
- 자동 배치한 신규 작업이면 선택한 후보와 밀린 후보의 근거가 결과 보고에 포함되는지 확인한다.
|
||||
|
|
@ -425,8 +385,6 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- 갱신 대상 Milestone identity가 `locked` 또는 `rely-on.target` 어느 쪽에 있든 결과 보고의 `Workspace 잠금`에 반영했는지 확인한다.
|
||||
- `locks.yaml`이 있는데 갱신 대상 Milestone identity가 `locked`와 `rely-on.target` 어느 쪽에도 없으면 `Workspace 잠금: 관련 lock 없음`으로 보고했는지 확인한다.
|
||||
- archive 모드이면 이동 전 active Milestone identity로 `locks.yaml`을 검사하고 필요한 `rely-on.status` 동기화 또는 `관련 lock 없음` 보고를 수행했는지 확인한다.
|
||||
- 결과 보고와 갱신한 활성 로드맵 문서의 문서/산출물 포인터가 raw path만 남지 않고 Markdown 링크로 작성되었는지 확인한다.
|
||||
- 갱신한 활성 로드맵 문서의 Markdown 링크 target에 템플릿 placeholder가 남지 않았는지 확인한다.
|
||||
- `git diff --check`로 공백 오류를 확인한다.
|
||||
|
||||
7. **결과 보고**
|
||||
|
|
@ -437,7 +395,6 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- 변경된 Phase / Milestone / 상태
|
||||
- 신규 작업의 삽입 단위와 배치 위치
|
||||
- 자동 배치한 경우 비교한 후보와 선택 근거
|
||||
- 전역 실행 순서 변경 사항
|
||||
- 로컬 current.md 활성 창 변경 사항
|
||||
- 완료 리뷰 상태와 남은 차단 항목
|
||||
- SDD gate 상태와 사용자 리뷰 필요 여부
|
||||
|
|
@ -451,11 +408,20 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
## 업데이트 완료
|
||||
|
||||
- 모드: <status | milestone | phase | replan | sync | concretize | archive>
|
||||
- 수정 파일: <실제로 변경한 ROADMAP/queue/current/Phase/Milestone/SDD/archive Markdown 링크 목록>
|
||||
- 수정 파일:
|
||||
- agent-roadmap/ROADMAP.md
|
||||
- agent-roadmap/current.md (local)
|
||||
- agent-roadmap/phase/<phase-slug>/PHASE.md
|
||||
- agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md
|
||||
- agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md (SDD 작성/갱신 시)
|
||||
- agent-roadmap/sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md (SDD 사용자 리뷰 요청 시)
|
||||
- agent-roadmap/archive/phase/<phase-slug>/... (archive 모드)
|
||||
- agent-roadmap/archive/sdd/<phase-slug>/<milestone-slug>/... (SDD archive 시)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
- Phase / Milestone: <변경 없음 | 요약>
|
||||
- Phase: <변경 없음 | 요약>
|
||||
- Milestone: <변경 없음 | 요약>
|
||||
- 삽입 단위: <Phase | Milestone | Epic | Task | 하위 작업 | 작업 컨텍스트/TODO | 변경 없음>
|
||||
- 규모 판정: <phase | milestone | epic | task | subtask | context | 변경 없음> - <근거>
|
||||
- 탐색 경로: <Phase 후보 -> Milestone 후보 -> Epic 후보 -> Task 후보 | 해당 없음>
|
||||
|
|
@ -463,7 +429,6 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- 배치: <사용자 지정 위치 반영 | 자동 배치 위치와 근거 | 변경 없음>
|
||||
- 배치 후보: <자동 배치 시 1순위/2순위 후보와 선택/제외 근거 | 해당 없음>
|
||||
- 템플릿 보정: <ROADMAP | local current.md | PHASE | Milestone | 이미 일치 | 변경 없음>
|
||||
- 전역 실행 순서: <변경 없음 | 생성 | 순서 조정 | archive/폐기 항목 제거 | 경로 갱신 | 재생성 필요>
|
||||
- 구현 잠금: <잠금 유지 | 잠금 추가 | 해제 | 잠금 차단 | 변경 없음>; 결정 필요: <없음 | 항목 요약>
|
||||
- SDD gate: <불필요 | 필요-작성 전 | 필요-잠금 | 필요-사용자 리뷰 | 필요-승인됨 | 변경 없음>
|
||||
- 승격 조건: <해당 없음 | 추가/수정/미충족 유지/충족 요약>
|
||||
|
|
@ -471,7 +436,7 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- runtime m-task 라우팅: <해당 없음 | origin-task -> target Milestone | target 불명확>
|
||||
- Workspace 잠금: <변경 없음 | 관련 lock 없음 | entry 생성/갱신 | rely-on enable | rely-on disable | 미충족 | 런타임 해제 대기>
|
||||
- 활성 항목: <변경 없음 | Phase/Milestone 추가/제거 요약>
|
||||
- 아카이브: <변경 없음 | 이동 링크와 남긴 링크>
|
||||
- 아카이브: <변경 없음 | 이동 경로와 남긴 링크>
|
||||
- 상태: <변경 없음 | 이전 -> 이후>
|
||||
- Epic/Task: <추가/수정/완료/제거 요약>
|
||||
|
||||
|
|
@ -486,9 +451,6 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
|||
- evidence 없이 Phase, Milestone, Epic, Task를 `[완료]` 또는 `[검토중]`으로 처리하지 않는다.
|
||||
- 전체 `ROADMAP.md`를 모든 작업의 필수 로딩 파일로 만들지 않는다.
|
||||
- `ROADMAP.md`에 Milestone 상세 작업 체크리스트를 남기지 않는다.
|
||||
- `priority-queue.md`에 상태, 목표, 범위, 잠금, 기능, 완료 근거, 의존성 필드를 복제하지 않는다.
|
||||
- `priority-queue.md`에 archive 경로를 남기지 않는다.
|
||||
- 사용자 순서 조정 요청 없이 `priority-queue.md`의 순서를 에이전트 판단만으로 바꾸지 않는다. 단, archive/폐기 제거, 경로 변경, split/merge, 실행 의미 변경, 깨진 링크 복구는 예외다.
|
||||
- 로컬 `current.md`에 개인별 현재 작업 위치나 완료 상태를 남기지 않는다.
|
||||
- 로컬 `current.md`에 `agent-roadmap/archive/**` 경로를 남기지 않는다.
|
||||
- `agent-roadmap/current.md`를 git 추적 대상으로 만들지 않는다.
|
||||
|
|
|
|||
|
|
@ -1,124 +0,0 @@
|
|||
---
|
||||
name: update-spec
|
||||
version: 1.0.0
|
||||
description: agent-spec 갱신, 구현 스펙 업데이트, 완료 기능 스펙 반영, 코드/계약/테스트 변경 후 living spec 동기화 요청에 사용한다. agent-spec/index.md에서 관련 spec을 찾아 현재 코드와 계약 기준으로 갱신하고 Spec updated, Spec update not needed, create-spec needed, Spec blocked 결과를 남긴다.
|
||||
---
|
||||
|
||||
# update-spec
|
||||
|
||||
## 목적
|
||||
|
||||
기존 agent-spec 문서를 현재 코드, 계약, 테스트, 완료 evidence에 맞게 갱신한다.
|
||||
이 스킬은 spec 문서만 책임지며 roadmap 상태 전환, Milestone archive, 코드 구현 계획 생성을 수행하지 않는다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 "스펙 업데이트", "구현 스펙 갱신", "완료 기능 스펙 반영", "agent-spec 갱신"을 요청할 때
|
||||
- 코드, 계약, config, event, runtime flow, 테스트가 바뀌어 현재 구현 spec이 달라질 수 있을 때
|
||||
- `complete-milestone`이 Milestone 종료 전에 spec sync gate를 수행할 때
|
||||
- `create-spec` 이후 불명확/부분 상태의 spec을 추가 evidence로 보강할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `target-spec`: 갱신할 spec id 또는 문서 경로. 없으면 index와 변경 근거에서 추론한다. (선택)
|
||||
- `target-milestone`: spec 갱신 근거가 되는 Milestone 경로, 이름, slug. (선택)
|
||||
- `changed-files`: spec 영향 판단에 사용할 코드/계약/테스트 파일 목록. (선택)
|
||||
- `complete-log`: 완료 근거로 사용할 `complete.log` 경로. (선택)
|
||||
- `mode`: `update` 또는 `check-only`. 기본값은 `update`다. (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/rules/common/rules-agent-spec.md`를 읽는다.
|
||||
- [ ] `agent-spec/index.md`가 있는지 확인한다. 없으면 `create-spec` 필요 또는 `skipped-no-agent-spec`으로 보고한다.
|
||||
- [ ] 매칭 spec 문서만 읽는다.
|
||||
- [ ] 계약에 닿는 변경이면 `agent-contract/index.md`를 읽고 매칭 계약 문서만 읽는다.
|
||||
- [ ] Milestone 또는 complete.log 근거가 있으면 해당 활성 Milestone, SDD gate, complete.log의 관련 섹션만 확인한다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **대상 spec 확정**
|
||||
- `target-spec`이 있으면 해당 문서가 활성 `agent-spec/**` 아래에 정확히 존재하는지 확인한다.
|
||||
- `target-spec`이 없으면 `agent-spec/index.md`의 읽는 조건, spec id, path, evidence와 `changed-files`/Milestone/complete.log를 비교한다.
|
||||
- 매칭 spec이 없고 구현 스펙 영향이 명확하면 `create-spec` 필요로 보고한다. 이 스킬에서 새 spec 문서를 직접 만들지 않는다.
|
||||
- 매칭 spec이 없고 변경이 spec 대상이 아니면 `Spec update not needed`로 보고한다.
|
||||
- 둘 이상의 spec이 매칭되면 모두 갱신 대상 후보로 두되, 각 spec별 영향 근거를 분리한다.
|
||||
|
||||
2. **현재 구현 재확인**
|
||||
- spec 본문만 믿지 말고 관련 코드, 계약, 테스트, 설정 예시를 다시 확인한다.
|
||||
- complete.log와 roadmap은 변경 근거로 쓰되 현재 동작은 코드/계약으로 검증한다.
|
||||
- SDD가 있으면 acceptance/evidence가 현재 spec과 어긋나는지 확인한다.
|
||||
- spec과 코드/계약이 충돌하면 코드/계약을 우선하고 spec을 수정한다.
|
||||
|
||||
3. **영향 판정**
|
||||
- 기능 목록, 범위, 주요 흐름, 계약 링크, 설정/데이터/이벤트, 검증, 한계 중 바뀐 항목을 식별한다.
|
||||
- 기능 이해에 필요한 최소 책임 설명이 바뀐 경우만 spec에 반영한다.
|
||||
- 코드 배치, 구현 진입점, 유지할 패턴, 금지 사항 변경은 domain rule 갱신 대상으로 본다.
|
||||
- 변경이 테스트 fixture, 내부 리팩터링, 문구 정리처럼 현재 구현 spec에 영향을 주지 않으면 `Spec update not needed: <사유>`를 남긴다.
|
||||
- 판단 불가이면 spec을 추정 갱신하지 않고 `Spec blocked: <필요 evidence>`로 보고한다.
|
||||
|
||||
4. **문서 갱신**
|
||||
- `mode=check-only`이면 쓰지 않고 갱신 후보만 보고한다.
|
||||
- 영향이 있는 spec 문서만 수정한다.
|
||||
- frontmatter `status`와 `source_evidence`를 현재 evidence에 맞게 보강한다.
|
||||
- `rules-agent-spec.md`의 기본 섹션 기준을 따른다.
|
||||
- 기능 목록은 `기능`과 `설명` 중심으로 유지한다. 기능별 `상태` 칼럼은 기본 추가하지 않는다.
|
||||
- `주요 흐름`은 긴 텍스트보다 Mermaid `sequenceDiagram` 또는 `flowchart`를 우선 고려한다.
|
||||
- `코드 진입점` 섹션은 추가하지 않는다. 기존 spec에 있으면 현재 기준에 맞춰 제거하거나 `source_evidence`로 옮긴다.
|
||||
- 계약 원문을 복제하지 않고 링크만 보강한다.
|
||||
- 변경 기록에 날짜, 변경 근거, 관련 Milestone/complete.log/코드 경로를 남긴다.
|
||||
|
||||
5. **index 동기화**
|
||||
- spec 상태, 읽는 조건, path, 주요 근거가 바뀌었으면 `agent-spec/index.md`의 Spec Map을 갱신한다.
|
||||
- 새 spec 문서가 필요하면 `create-spec` 대상으로 보고하고 index를 추정 갱신하지 않는다.
|
||||
- 폐기된 spec은 활성 문서에 남기지 않고 archive log로 이동할 후보로 보고한다. 명시 요청 없이 archive 이동하지 않는다.
|
||||
|
||||
6. **결과 분류**
|
||||
- 갱신한 문서가 있으면 `Spec updated`로 보고한다.
|
||||
- 영향 없음이 확인되면 `Spec update not needed: <사유>`로 보고한다.
|
||||
- 매칭 spec이 없고 신규 작성이 필요하면 `create-spec needed: <사유>`로 보고한다.
|
||||
- evidence 부족, 대상 모호, 사용자 결정 필요이면 `Spec blocked: <사유>`로 보고한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `agent-spec/index.md`에서 관련 spec만 읽었는가
|
||||
- [ ] 코드/계약/테스트 기준으로 현재 동작을 재확인했는가
|
||||
- [ ] spec 문서의 기본 섹션 기준과 frontmatter가 유지되는가
|
||||
- [ ] 기능 목록이 기능/설명 중심이며 불필요한 상태 칼럼이나 과한 상세 설명을 만들지 않았는가
|
||||
- [ ] 코드 진입점, 패키지 배치, 도메인별 금지 사항을 spec 본문에 반복하지 않았는가
|
||||
- [ ] index의 Spec Map이 갱신한 spec 상태와 일치하는가
|
||||
- [ ] 계약 원문을 복제하지 않았는가
|
||||
- [ ] 갱신/불필요/create 필요/차단 중 하나의 결과가 명확한가
|
||||
- [ ] `complete-milestone`에서 호출된 경우 Milestone 완료 리뷰에 남길 spec sync 문구를 제공했는가
|
||||
- [ ] `git diff --check`를 실행했는가
|
||||
- 검증 실패 시: roadmap이나 코드 파일을 수정하지 말고 spec 갱신 실패 사유를 보고한다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```markdown
|
||||
## Spec 동기화 결과
|
||||
|
||||
- 결과: <Spec updated | Spec update not needed | create-spec needed | Spec blocked | skipped-no-agent-spec>
|
||||
- 대상 spec:
|
||||
- <없음 | [spec-id](agent-spec/<area>/<spec-id>.md)>
|
||||
- 수정 파일:
|
||||
- <없음 | [index.md](agent-spec/index.md) | [spec](agent-spec/<area>/<spec-id>.md)>
|
||||
- 근거:
|
||||
- <코드/계약/테스트/complete.log/Milestone 요약>
|
||||
- Milestone 완료 리뷰 문구:
|
||||
- `Spec sync: <완료 | 해당 없음 | create-spec 필요: 사유 | 차단: 사유>`
|
||||
|
||||
## TODO 항목
|
||||
|
||||
- <남은 확인 필요 또는 없음>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- roadmap 상태 전환이나 archive 이동을 수행하지 않는다.
|
||||
- 새 spec 문서를 생성하지 않는다. 신규 작성이 필요하면 `create-spec`으로 넘긴다.
|
||||
- 코드 구현이나 테스트 코드를 수정하지 않는다.
|
||||
- spec과 코드가 충돌할 때 spec을 그대로 신뢰하지 않는다.
|
||||
- 매칭되지 않는 spec을 광범위하게 읽거나 전부 갱신하지 않는다.
|
||||
- archive spec을 명시 요청 없이 읽거나 갱신하지 않는다.
|
||||
- complete.log나 roadmap 문구만으로 현재 동작을 단정하지 않는다.
|
||||
- 코드 진입점, 구현 배치, 도메인 간 상세 책임 경계, 유지할 패턴, 금지 사항을 domain rule 대신 agent-spec에 길게 쓰지 않는다.
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
name: update-test
|
||||
description: 기존 agent-test 환경 rules.md 또는 테스트 profile을 수정하고 파일 수정 없는 Verification Context를 제공한다. 테스트 규칙 수정·갱신, 테스트 컨텍스트 해석, Verification Context 생성 요청에 사용한다.
|
||||
version: 1.1.0
|
||||
description: 기존 agent-test 환경 rules.md 또는 도메인/검증 시나리오별 테스트 rule 문서를 수정하는 스킬
|
||||
---
|
||||
|
||||
# update-test
|
||||
|
|
@ -9,7 +10,6 @@ description: 기존 agent-test 환경 rules.md 또는 테스트 profile을 수
|
|||
|
||||
기존 `agent-test/<env>/rules.md` 또는 `agent-test/<env>/<test-profile>.md`를 최신 테스트 기준에 맞게 갱신한다.
|
||||
라우팅은 3홉 안에 유지하고, 도메인/검증 시나리오별 문서는 자체 완결되게 보완한다.
|
||||
`resolve-context` 모드에서는 해당 문서를 수정하지 않고 현재 task에 적용할 명령, 판정 기준, 제약, 외부 환경 preflight를 중립 `Verification Context`로 반환한다.
|
||||
|
||||
`test-case`는 기존 호출과의 호환을 위한 alias이며, 새 문서 기준 이름은 `test-profile`이다.
|
||||
|
||||
|
|
@ -18,42 +18,30 @@ description: 기존 agent-test 환경 rules.md 또는 테스트 profile을 수
|
|||
- 기존 테스트 환경 규칙을 수정할 때
|
||||
- 도메인/검증 시나리오별 테스트 기준, 명령, 판정 기준을 보완할 때
|
||||
- 테스트 라우팅을 추가, 제거, 정리할 때
|
||||
- plan 또는 다른 소비자가 구현 범위에 맞는 테스트 환경/profile 정보를 필요로 할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `mode`: `update` 또는 `resolve-context`. 기본값은 `update` (선택)
|
||||
- `env`: `local`, `dev`, `qa`, `prod` 중 하나. 기본값은 `local` (선택)
|
||||
- `env`: `local`, `dev`, `qa`, `prod` 중 하나 (필수)
|
||||
- `test-profile`: 수정할 도메인/검증 시나리오별 테스트 문서 이름, kebab-case (선택)
|
||||
- `test-case`: `test-profile`의 호환 alias (선택)
|
||||
- `domain`: 대상 도메인 이름, kebab-case (선택)
|
||||
- `change`: 수정할 내용 요약. `mode=update`에서 필수 (선택)
|
||||
- `task-summary`: 검증할 동작과 완료 조건 요약. `mode=resolve-context`에서 필수 (선택)
|
||||
- `scope-paths`: 변경 후보 source/test 경로 목록. `mode=resolve-context`에서 선택
|
||||
- `verification-type`: 예: `unit`, `smoke`, `integration`, `e2e`. `mode=resolve-context`에서 선택
|
||||
- `change`: 수정할 내용 요약 (필수)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/rules/common/rules.md`의 스킬 규칙과 테스트 규칙이 분리되어 있는지 확인한다.
|
||||
- [ ] `agent-ops/skills/common/router.md`에 `update-test` 라우팅이 있는지 확인한다.
|
||||
- [ ] `test-case`가 있고 `test-profile`이 없으면 `test-profile`로 취급한다.
|
||||
- [ ] `mode=update`이면 `change`가 있는지, `mode=resolve-context`이면 `task-summary`가 있는지 확인한다.
|
||||
- [ ] `agent-test/<env>/rules.md` 존재 여부를 확인한다. `mode=update`에서 없으면 `create-test` 대상으로 보고 중단하고, `mode=resolve-context`에서는 `rules_state: missing`으로 반환한다.
|
||||
- [ ] `agent-test/<env>/rules.md` 존재 여부를 확인하고, 없으면 `create-test` 대상으로 보고 중단한다.
|
||||
- [ ] `agent-test/<env>/rules.md`가 있으면 읽는다.
|
||||
- [ ] `test-profile`이 있으면 `agent-test/<env>/<test-profile>.md` 존재 여부를 확인한다. `mode=update`에서 없으면 `create-test` 대상으로 보고 중단하고, `mode=resolve-context`에서는 gap으로 기록한다.
|
||||
- [ ] `test-profile`이 있으면 `agent-test/<env>/<test-profile>.md` 존재 여부를 확인하고, 없으면 `create-test` 대상으로 보고 중단한다.
|
||||
- [ ] `test-profile` 문서가 있으면 읽는다.
|
||||
- [ ] `test-profile`이 없으면 `domain`, `change`, `task-summary`, `scope-paths`, `verification-type`을 env rules의 `## 라우팅`과 대조해 모든 matching profile을 찾는다.
|
||||
- [ ] `test-profile`이 없고 `domain` 또는 `change`가 특정 도메인/검증 시나리오를 가리키면 env rules의 라우팅에서 대상 문서를 찾는다.
|
||||
- [ ] 템플릿 구조 확인이 필요하면 `agent-ops/rules/common/_templates/`의 테스트 템플릿을 읽는다.
|
||||
- [ ] 기존 라우팅이 3홉 안에 있는지 확인한다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **모드 확정**
|
||||
- `mode=resolve-context`이면 아래 `resolve-context 절차`만 수행하고 파일, `.gitignore`, `last_rule_updated_at`을 수정하지 않는다.
|
||||
- `mode=update`이면 아래 `update 절차`를 수행한다.
|
||||
|
||||
### update 절차
|
||||
|
||||
1. **대상 확정**
|
||||
- 환경 공통 규칙 변경이면 `agent-test/<env>/rules.md`만 수정한다.
|
||||
- 특정 도메인/검증 기준 변경이면 해당 `test-profile` 문서를 수정한다.
|
||||
|
|
@ -81,34 +69,6 @@ description: 기존 agent-test 환경 rules.md 또는 테스트 profile을 수
|
|||
- 보존한 환경값
|
||||
- 남은 확인 필요 항목
|
||||
|
||||
### resolve-context 절차
|
||||
|
||||
1. **환경 규칙 상태 판정**
|
||||
- env rules를 `missing`, `blank-skeleton`, `structured-incomplete`, `usable` 중 하나로 판정한다.
|
||||
- `missing` 또는 `blank-skeleton`이어도 생성하거나 보완하지 않는다.
|
||||
- 실제 파일에 없는 명령, endpoint, credential, 판정 기준을 추측하지 않는다.
|
||||
|
||||
2. **matching profile 해석**
|
||||
- 명시된 `test-profile` 또는 env rules의 `## 라우팅`에서 `domain / verification-type / scope`가 맞는 모든 profile을 선택한다.
|
||||
- 매칭 근거가 없는 profile은 읽거나 반환하지 않는다.
|
||||
- route가 가리키는 profile이 없거나 구조적으로 비어 있으면 gap으로 기록한다.
|
||||
|
||||
3. **검증 사실 추출**
|
||||
- env rules와 matching profile에서 실행 위치, 명령, 필수 순서, 기대 결과, 차단 기준, cache 허용 여부, 외부 서비스/secret 요구 여부를 원문 의미를 바꾸지 않고 추출한다.
|
||||
- 명령이 여러 profile에 걸치면 profile별 출처와 적용 범위를 유지한다.
|
||||
- `<확인 필요>` 또는 서로 충돌하는 값은 확정하지 않고 gap으로 기록한다.
|
||||
- env rules와 matching profile이 usable이고 적용 명령·판정 기준에 gap이 없으면 confidence를 `high`, 일부 값에 repository-native 확인이 더 필요하면 `medium`, rules가 missing/blank이거나 핵심 값이 unresolved이면 `low`로 판정한다.
|
||||
|
||||
4. **외부 환경 preflight 구성**
|
||||
- 현재 checkout 밖의 runner, field/bootstrap, external provider, Docker/code-server, emulator/device, shared runtime이 필요한 검증만 read-only preflight 대상으로 삼는다.
|
||||
- env/profile에 적힌 범위 안에서 repo root/workdir, branch/HEAD/dirty state, source sync, binary/artifact, command help/version, config path, runtime identity, ports/process, external host, OS/arch 확인 항목을 구성한다.
|
||||
- 안전한 read-only probe를 현재 환경에서 실행할 수 있으면 실제 결과를 반환하고, 실행할 수 없으면 필요한 probe와 blocker를 구분해 반환한다.
|
||||
- secret, token, credential 원문은 읽거나 출력하지 않는다.
|
||||
|
||||
5. **중립 handoff 반환**
|
||||
- 소비 스킬 이름이나 문서 section 이름에 결합하지 않고 아래 출력 형식을 그대로 반환한다.
|
||||
- test rule 유지보수는 사용자가 요청했거나 확인된 구조 결함이 있을 때만 `create-test` 또는 `update-test` 후보로 표시한다. `resolve-context` 실행 중 직접 호출하거나 수정하지 않는다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] 수정 대상 문서가 여전히 필수 섹션을 포함하는가
|
||||
|
|
@ -116,10 +76,6 @@ description: 기존 agent-test 환경 rules.md 또는 테스트 profile을 수
|
|||
- [ ] env rules 라우팅이 3홉 제한을 넘기지 않는가
|
||||
- [ ] 도메인/검증 시나리오별 문서가 다른 테스트 문서로 라우팅하지 않는가
|
||||
- [ ] local 수정 시 `.gitignore`에 local 경로가 반영되었는가
|
||||
- [ ] `resolve-context`에서 파일과 `.gitignore`를 수정하지 않았는가
|
||||
- [ ] `resolve-context`가 읽은 env/profile 경로와 각 명령의 출처를 정확히 반환하는가
|
||||
- [ ] 외부 검증이 있으면 read-only preflight 결과 또는 실행 불가 blocker가 구분되어 있는가
|
||||
- [ ] 누락, `<확인 필요>`, 충돌 값을 확정된 명령이나 기준으로 반환하지 않았는가
|
||||
- [ ] secret, token, 개인 endpoint 원문이 tracked 파일에 추가되지 않았는가
|
||||
- 검증 실패 시: 문제 문서만 다시 보완한다.
|
||||
|
||||
|
|
@ -135,36 +91,9 @@ description: 기존 agent-test 환경 rules.md 또는 테스트 profile을 수
|
|||
- 확인 필요: <항목 또는 없음>
|
||||
```
|
||||
|
||||
`mode=resolve-context`:
|
||||
|
||||
```md
|
||||
## Verification Context
|
||||
|
||||
- Environment: <env>
|
||||
- Rules State: <missing|blank-skeleton|structured-incomplete|usable>
|
||||
- Sources Read:
|
||||
- <env rules/profile path 또는 없음>
|
||||
- Scope Match:
|
||||
- <domain / verification-type / scope와 매칭 근거 또는 없음>
|
||||
- Commands:
|
||||
- `<command>`: source=`<path>`; scope=`<scope>`; expected=`<result>`; cache=`<allowed|fresh|required|unspecified>`
|
||||
- Preconditions:
|
||||
- <필수 순서, 실행 위치, config/runtime 요구 또는 없음>
|
||||
- Read-only Preflight:
|
||||
- `<probe>`: <PASS|BLOCKED|NOT_RUN>; <actual result or reason>
|
||||
- Constraints:
|
||||
- <금지 사항, 외부 서비스/secret 요구 여부 또는 없음>
|
||||
- Gaps:
|
||||
- <missing profile, blank value, `<확인 필요>`, conflict 또는 없음>
|
||||
- Confidence: <high|medium|low>; <판정 근거>
|
||||
- Maintenance: <not-needed|create-test-candidate|update-test-candidate>; <근거>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 기존 local 환경값을 추측으로 바꾸지 않는다.
|
||||
- 확인되지 않은 테스트 명령을 필수 검증으로 단정하지 않는다.
|
||||
- 도메인/검증 시나리오별 문서를 router처럼 쓰지 않는다.
|
||||
- `resolve-context`에서 테스트 문서 생성, 수정, `.gitignore` 갱신을 수행하지 않는다.
|
||||
- `resolve-context` 출력에 특정 소비 스킬 전용 필드나 파일명을 강제하지 않는다.
|
||||
- secret, token, 개인 endpoint 원문을 tracked 파일에 기록하지 않는다.
|
||||
|
|
|
|||
|
|
@ -1,194 +0,0 @@
|
|||
---
|
||||
name: validate-agent-ui
|
||||
description: agent-ui scaffold, definition/frame/component/wireframe/source evidence/status 정합성을 맞추고 필요한 USER_REVIEW와 code sync intent를 분리하는 스킬
|
||||
---
|
||||
|
||||
# validate-agent-ui
|
||||
|
||||
## 목적
|
||||
|
||||
`agent-ui/` 구조와 문서 그래프 정합성을 검사하고 자동 보정한다.
|
||||
definition, component, frame, visual source, USER_REVIEW, archive가 서로 뒤처진 상태를 같은 수준으로 맞추며, UI 의도 판단이 필요한 문제는 `agent-ui/USER_REVIEW.md`에 남긴다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- agent-ui 구조 검증, UI 정의 정합성 확인, wireframe 정합성 확인을 요청할 때
|
||||
- view/component/frame 문서가 서로 어긋났는지 확인할 때
|
||||
- view/component의 Source Evidence와 Status가 근거와 맞는지 확인할 때
|
||||
- Excalidraw visual source와 frame index 연결을 검사할 때
|
||||
- agent-ui 갱신 후 자동 보정과 사용자 리뷰 분리가 필요할 때
|
||||
- 수동 호출에서 정합성 통과 후 code sync가 필요한지 판단할 때
|
||||
- 사용자가 "화면정의서와 코드가 안 맞아"처럼 UI 정의와 코드 결과물의 불일치를 보고할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `scope`: `all`, `internal`, `implementation`, `view:<view-id>`, `component:<component-id>`, `frame:<view-id>` 중 하나. 기본값은 `all` (선택)
|
||||
- `repair`: `true` 또는 `false`. 기본값은 `true` (선택)
|
||||
- `sync-intent`: `auto`, `required`, `skip`, `inherited` 중 하나. 기본값은 수동 호출에서 `auto`, `update-agent-ui` 후속 호출에서 `inherited` (선택)
|
||||
- `sync-mode`: `incremental` 또는 `full`. 기본값은 `incremental` (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/rules/common/rules-agent-ui.md`를 읽는다.
|
||||
- [ ] `agent-ui/` 존재 여부를 확인한다. 없으면 `create-agent-ui` 대상이라고 보고하고 중단한다.
|
||||
- [ ] `agent-ui/definition/index.md`, `definition/views/index.md`, `definition/components/index.md`, `frame/index.md` 존재 여부를 확인한다.
|
||||
- [ ] scope에 해당하는 활성 definition/frame 문서만 읽는다.
|
||||
- [ ] `scope=view:<view-id>` 또는 `scope=component:<component-id>`이면 해당 문서의 Source Evidence code path를 확인한다.
|
||||
- [ ] `scope=all`, `scope=implementation` 또는 sync intent가 있으면 Source Evidence의 code path와 UI 구현 후보 파일을 확인한다.
|
||||
- [ ] `agent-ui/.sync-state.json`이 있으면 읽고, 없으면 sync 기준 없음으로 보고한다.
|
||||
- [ ] archive는 경로와 tree 대응만 확인하고, 사용자가 과거 내용 확인을 요청하지 않았으면 본문을 읽지 않는다.
|
||||
- [ ] 필요한 템플릿만 `agent-ops/skills/common/_templates/agent-ui/`에서 읽는다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **인벤토리 작성**
|
||||
- `definition/views/**/index.md`에서 view 목록을 만든다.
|
||||
- `definition/components/**/index.md`에서 component 목록을 만든다.
|
||||
- `frame/views/**/index.md`에서 frame 목록을 만든다. frame이 없는 view는 visual source가 없는 정상 상태로 본다.
|
||||
- 활성 Markdown 문서의 frontmatter에서 `ui_doc_type`과 문서 유형별 필드를 수집한다.
|
||||
- view: `view_id`, `status`, `frame`, `source_evidence`, `regions`
|
||||
- component: `component_id`, `status`, `source_evidence`
|
||||
- frame-view: `view_id`, `definition`, `visual_source`, `regions`
|
||||
- definition-index: `surface_type`, `source_evidence`
|
||||
- 같은 레벨의 `<name>.md`와 `<name>/` 혼재 여부를 확인한다.
|
||||
|
||||
2. **구조 검증과 자동 보정**
|
||||
- 필수 루트 문서가 없고 `repair=true`이면 템플릿으로 생성한다.
|
||||
- view/component 디렉터리에 `index.md`가 없고 의도가 명확하면 템플릿으로 생성한다.
|
||||
- frame 디렉터리는 visual source가 있을 때만 `index.md` 생성 대상으로 삼는다.
|
||||
- `.excalidraw` 파일이 하나 있고 frame index의 visual source가 비어 있으면 해당 파일을 등록한다.
|
||||
- archive/user-review 디렉터리가 없고 필요하면 생성한다.
|
||||
- `<name>.md`와 `<name>/`가 모두 있고 둘 다 의미 있는 내용이면 자동 병합하지 않고 USER_REVIEW로 남긴다.
|
||||
|
||||
3. **definition 정합성 검사**
|
||||
- 활성 Markdown 문서에 `ui_doc_type` frontmatter가 있는지 확인한다.
|
||||
- `ui_doc_type`이 경로와 맞는지 확인한다. 예: `definition/views/<view-id>/index.md`는 `view`다.
|
||||
- view/component/frame id가 경로 id와 일치하는지 확인한다.
|
||||
- view/component 문서에 `Source Evidence`와 `Status`가 있는지 확인한다.
|
||||
- view/component/definition-index의 frontmatter `source_evidence`는 list이고 각 항목은 `type`, `path`, `notes`를 가져야 한다.
|
||||
- 이 문서들의 `source_evidence.type`은 `code`, `docs`, `user` 중 하나여야 한다.
|
||||
- 근거 파일이 없으면 `path: null`이어야 하며, placeholder 문자열을 근거로 보지 않는다.
|
||||
- view는 frontmatter의 `status`, `source_evidence`, `regions`와 본문 `Status`, `Source Evidence`, `Regions`가 충돌하는지 확인한다.
|
||||
- component는 frontmatter의 `status`, `source_evidence`와 본문 `Status`, `Source Evidence`가 충돌하는지 확인한다.
|
||||
- frame-view는 frontmatter `regions`와 본문 `Required Regions`가 충돌하는지 확인한다. frame-view에는 `status`나 `Source Evidence`를 요구하지 않는다.
|
||||
- view/component의 `Status`는 `구현됨`, `계획`, `가정`, `불명확` 중 하나여야 한다.
|
||||
- `구현됨` 항목은 코드 반영 완료 상태여야 한다. 코드 근거가 있으면 실제 존재하는 code evidence path를 가져야 한다.
|
||||
- `구현됨`의 code evidence 경로가 명시되어 있고 실제 존재하지 않으면 `repair=true`일 때 `계획`으로 낮추고 USER_REVIEW를 남길 수 있다.
|
||||
- `가정`, `불명확` 항목이 코드 동기화 가능한 정의처럼 설명되면 자동 의미 변경하지 않고 USER_REVIEW로 남긴다.
|
||||
- view와 frame-view의 region id가 `<view-id>.<region>` 또는 `<view-id>.<region>.<subregion>` 형식인지 확인한다.
|
||||
- view 문서에서 참조한 component id가 component 목록에 있는지 확인한다.
|
||||
- 없는 component가 단순 누락이고 생성 의도가 명확하면 `repair=true`일 때 component skeleton을 만들고 `Status`와 `Source Evidence`를 채운다.
|
||||
- 새 component로 만들지 기존 component로 바꿀지 판단이 필요하면 USER_REVIEW로 남긴다.
|
||||
|
||||
4. **frame 정합성 검사**
|
||||
- view가 있는데 대응 frame index가 없어도 visual source가 없으면 정상으로 본다.
|
||||
- visual source 파일이 있는데 대응 frame index가 없으면 `repair=true`일 때 만든다.
|
||||
- frame index가 있는데 `visual_source: null`이고 해당 view 아래 visual source 파일도 없으면 `repair=true`일 때 빈 frame index 삭제 후보로 본다.
|
||||
- frame index가 가리키는 definition 경로가 실제 존재하는지 확인한다.
|
||||
- `visual_source`가 `null`이면 legacy/empty frame 후보로 보고 visual source 파일 존재 여부를 함께 확인한다.
|
||||
- `visual_source`가 값이면 해당 파일이 실제 존재하는지 확인한다.
|
||||
- `visual_source`가 `.excalidraw`이면 JSON으로 읽고 `elements`의 text label 또는 `customData.region_id`에서 region id 후보를 수집한다.
|
||||
- Excalidraw region id 후보가 있으면 frame required region, view definition region과 비교한다.
|
||||
- Excalidraw region id 후보가 없고 frame required region이 있으면 USER_REVIEW로 남긴다.
|
||||
- Excalidraw에 정의되지 않은 region label이 있거나 필수 region label이 없으면 자동 수정하지 않고 USER_REVIEW로 남긴다.
|
||||
- Excalidraw가 JSON으로 파싱되지 않으면 visual source 손상 또는 형식 불일치로 보고한다.
|
||||
- frame required region과 view definition region을 비교한다.
|
||||
- visual source가 있는 frame index에서 definition region이 빠진 경우 `repair=true`이면 frame index의 required region을 보완할 수 있다.
|
||||
- 기존 frame에만 있는 region은 definition에 자동 추가하지 않고 USER_REVIEW로 남긴다.
|
||||
- region 추가/삭제 의도 판단이 필요하면 USER_REVIEW로 남긴다.
|
||||
|
||||
5. **구현 정합성 검사**
|
||||
- `scope=view:<view-id>` 또는 `scope=component:<component-id>`이면 해당 문서의 `source_evidence` 중 `type: code` 경로만 확인하고 전체 코드 후보 스캔은 하지 않는다.
|
||||
- `scope=all` 또는 `scope=implementation`이면 전체 view/component의 `source_evidence` 중 `type: code` 경로가 실제 존재하는지 확인한다.
|
||||
- 실제 UI 구현 후보를 찾는다.
|
||||
- 이 후보 스캔은 `scope=all` 또는 `scope=implementation`일 때만 수행한다.
|
||||
- 예: `apps/**/lib/**`, `packages/**/lib/**`, `src/**`, `app/**`, `pages/**`, `screens/**`, `views/**`, `components/**`, `widgets/**`, route/navigation/shell 파일
|
||||
- 프로젝트 규칙에 dedicated UI domain rule이 있으면 먼저 따른다.
|
||||
- 코드가 많으면 route, shell, page/view, widget/component 이름 중심으로 후보를 좁힌다.
|
||||
- 운영 단계에서는 코드 후보만 보고 agent-ui view/component를 새로 만들지 않는다.
|
||||
- 코드 후보가 명확한 route/page/view/shell인데 agent-ui에 대응 view가 없으면 USER_REVIEW로 남기거나, 사용자가 코드 기준 반영을 명시한 경우 `update-agent-ui`로 돌린다.
|
||||
- 코드 후보가 명확한 반복 widget/component/table/filter/log/status/action인데 agent-ui에 대응 component가 없으면 USER_REVIEW로 남기거나, 사용자가 코드 기준 반영을 명시한 경우 `update-agent-ui`로 돌린다.
|
||||
- 코드 결과물이 `구현됨` 상태의 agent-ui 정의와 어긋난다는 사용자 보고가 있으면 해당 항목을 `계획`으로 낮추고 sync intent를 만든다.
|
||||
- 후보가 임시/dev/debug 용도인지, view인지 component인지, region인지 판단이 필요하면 USER_REVIEW로 남긴다.
|
||||
- 코드에서 사라진 evidence는 자동 삭제하지 않고, 명시된 code evidence 경로가 깨진 경우에만 `구현됨`을 `계획`으로 낮출 수 있다.
|
||||
|
||||
6. **USER_REVIEW 생성 또는 갱신**
|
||||
- active review 파일은 `agent-ui/USER_REVIEW.md`를 사용한다.
|
||||
- 새 항목 id는 기존 최대 `UIR-NNN` 다음 번호를 사용한다.
|
||||
- 같은 경로와 같은 질문의 중복 항목은 만들지 않는다.
|
||||
- 항목에는 `Source Skill: validate-agent-ui`, `Stage: document-consistency`, `Blocking Step`, Context, Options, Needed For를 포함한다.
|
||||
|
||||
7. **code sync intent 판정**
|
||||
- `sync-intent=inherited`이면 `update-agent-ui`가 전달한 판단을 그대로 사용하고 재판단하지 않는다.
|
||||
- 수동 호출이거나 `sync-intent=auto`이면 agent-ui 변경분과 `계획` 상태 항목을 보고 `sync-agent-ui` 필요 여부를 판단한다.
|
||||
- `sync-intent=required`이면 validate 결과가 PASS 또는 자동 보정 완료 WARN이고 현재 범위에 미해결 USER_REVIEW가 없을 때 `sync-agent-ui`를 실행한다.
|
||||
- `sync-intent=skip`이면 code sync 필요 여부를 보고만 하고 실행하지 않는다.
|
||||
- 현재 범위에 `가정` 또는 `불명확` 항목이 있거나 미해결 USER_REVIEW가 있으면 `sync-agent-ui`를 실행하지 않는다.
|
||||
- `sync-agent-ui`를 실행할 때는 이 스킬의 보정 결과를 입력으로 넘기고, 순서를 바꾸지 않는다.
|
||||
|
||||
8. **결과 판정**
|
||||
- `PASS`: 자동 수정도 USER_REVIEW도 필요 없는 상태
|
||||
- `WARN`: 자동 수정이 있었거나 USER_REVIEW가 생성/갱신된 상태
|
||||
- `FAIL`: 구조가 너무 모호해서 자동 보정과 리뷰 작성 모두 불완전한 상태
|
||||
|
||||
## 자동 수정 허용 범위
|
||||
|
||||
- 누락된 필수 디렉터리와 index 문서 생성
|
||||
- 명확한 단일 후보 visual source 등록
|
||||
- 명확한 단일 후보 상대 링크 보정
|
||||
- visual source가 있는 frame index의 region 누락 보완
|
||||
- 빈 archive/user-review 디렉터리 생성
|
||||
- 템플릿 필수 섹션과 frontmatter 누락 보완. 모든 문서의 `ui_doc_type`, view/component의 `Source Evidence`와 `Status`, 문서 유형별 필수 필드 누락 포함
|
||||
- 명시된 code evidence 경로가 실제 존재하지 않는 `구현됨`을 `계획`으로 낮추고 USER_REVIEW를 남기는 보정
|
||||
|
||||
## USER_REVIEW 대상
|
||||
|
||||
- 정의에는 없는 region이 기존 frame-view에 있고 추가/삭제 의도 판단이 필요한 경우
|
||||
- frame-view가 있는데 frame에는 없는 region이 정의에 있고 layout 반영 여부 판단이 필요한 경우
|
||||
- component 참조가 없으며 새 component 생성 또는 기존 component 재사용 판단이 필요한 경우
|
||||
- 운영 단계에서 코드 후보가 view, component, region, 임시/dev/debug UI 중 무엇인지 판단이 필요한 경우
|
||||
- 운영 단계에서 코드에만 있는 view/component를 agent-ui에 반영할지 판단이 필요한 경우
|
||||
- 코드와 agent-ui 정의가 충돌하지만 어느 쪽을 기준으로 삼을지 제품 판단이 필요한 경우
|
||||
- `계획` 항목을 코드로 반영하려 했지만 구현 방향, 환경, 권한, 검증 실패를 에이전트가 해결하지 못한 경우
|
||||
- `<name>.md`와 `<name>/`가 모두 있고 둘 다 의미 있는 내용이 있는 경우
|
||||
- drawer/page/split, 테이블/리스트, modal/page 같은 UX 방향 결정이 필요한 경우
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] 필수 루트 문서가 존재하거나 누락 사유가 보고되었는가
|
||||
- [ ] 활성 Markdown 문서가 유효한 `ui_doc_type` frontmatter를 갖는가
|
||||
- [ ] folder-first + `index.md` 구조가 유지되는가
|
||||
- [ ] view/component에 `Source Evidence`와 유효한 `Status`가 있는가
|
||||
- [ ] 명시된 code evidence 경로가 깨진 `구현됨`이 남아 있지 않은가
|
||||
- [ ] `scope=implementation` 또는 `all`이면 명확한 UI 코드 후보와 agent-ui 불일치가 sync intent 또는 USER_REVIEW로 분리되었는가
|
||||
- [ ] view/component/frame 참조가 끊기지 않는가
|
||||
- [ ] visual source가 없는 view는 frame 참조가 `null`이거나 비어 있는 frame-view가 없는가
|
||||
- [ ] 자동 수정한 파일 목록이 보고되는가
|
||||
- [ ] 사용자 판단이 필요한 항목이 `agent-ui/USER_REVIEW.md`에 남는가
|
||||
- [ ] archive 본문을 일반 검증에서 읽지 않았는가
|
||||
- 검증 실패 시: 판정을 `FAIL`로 보고하고 자동 수정하지 못한 이유를 남긴다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```md
|
||||
## agent-ui 검증 결과: <PASS|WARN|FAIL>
|
||||
|
||||
- Scope: <scope>
|
||||
- Auto Fixed: <파일/항목 목록 또는 없음>
|
||||
- User Review: <agent-ui/USER_REVIEW.md 생성/갱신/없음>
|
||||
- Remaining Issues: <목록 또는 없음>
|
||||
- Checked Files: <활성 파일 목록>
|
||||
- Sync Intent: <inherited|required|skip|auto 판단 결과>
|
||||
- sync-agent-ui: <실행/보류/생략 사유>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- UI 의도 판단이 필요한 문제를 자동 수정하지 않는다.
|
||||
- archive 본문을 일반 검증 컨텍스트로 읽지 않는다.
|
||||
- `.excalidraw` 내용을 현재 UI 기준으로 단독 확정하지 않는다.
|
||||
- 사용자 확인 없이 의미 있는 문서를 병합하거나 삭제하지 않는다.
|
||||
- agent-ui 검증과 무관한 앱 구현 파일을 수정하지 않는다.
|
||||
- 전달받은 sync intent가 있으면 같은 내용을 재판단하지 않는다.
|
||||
- `sync-agent-ui`보다 뒤에 실행되어서는 안 된다.
|
||||
- 운영 단계에서 코드 후보만 근거로 agent-ui view/component skeleton을 자동 생성하지 않는다.
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
NomadCode는 Flutter 기반 앱, core 서비스, 공유 계약, agent-operation 규칙을 하나의 원레포로 묶어 AI-assisted development workflow를 조율하는 프로젝트다.
|
||||
|
||||
현재 로드맵은 [ROADMAP.md](ROADMAP.md) -> [Agent-Ops Work Item Lifecycle PHASE.md](phase/agent-ops-work-item-lifecycle/PHASE.md) -> [Milestone Execution Lifecycle Sync](phase/agent-ops-work-item-lifecycle/milestones/milestone-execution-lifecycle-sync.md) 같은 scaffold를 기준으로 관리한다. React/Vite 웹 콘솔 제거, 서버/Plane/provider 기반 작업, Flutter-first 클라이언트 정리, Mattermost push plugin extraction, client integration 표준화, workspace 포트/환경 표준화, External Integration, Milestone Work Item Creation Sync, Plane Work Item Webhook Intake, Gito Branch Event Creation Sync Bridge, Gito proto-socket consumer wire readiness, Gito HTTP Webhook Consumer Readiness, Plane-Origin Authoring Roundtrip Sync, Roadmap Driven Agent-Ops Automation, Agent-Origin Milestone Creation Sync는 완료되었다. Agent-Ops Work Item Lifecycle에서는 다음 후보인 Milestone Execution Lifecycle Sync로 Todo 이후 실행 lifecycle을 다룬다. 외부 agent 제어 표면과 MCP 여부는 현재 ops 작업과 섞지 않고 별도 MCP Control Surface Phase로 분리해 가장 뒤의 스케치로 미룬다.
|
||||
현재 로드맵은 `ROADMAP.md -> phase/<phase-slug>/PHASE.md -> phase/<phase-slug>/milestones/<milestone-slug>.md` scaffold를 기준으로 관리한다. React/Vite 웹 콘솔 제거, 서버/Plane/provider 기반 작업, Flutter-first 클라이언트 정리, Mattermost push plugin extraction, client integration 표준화, workspace 포트/환경 표준화, External Integration, Milestone Work Item Creation Sync, Plane Work Item Webhook Intake, Gito Branch Event Creation Sync Bridge, Gito proto-socket consumer wire readiness, Gito HTTP Webhook Consumer Readiness는 완료되었다. Agent-Ops MCP Control Plane의 활성 Milestone은 Roadmap Driven Agent-Ops Automation으로, roadmap/action core와 provider sync domain의 상위 방향을 정리한다.
|
||||
|
||||
IOP 외부 실행 호출은 OpenAI-compatible Responses API 방식을 기본 계약으로 채택하고, NomadCode/IOP 고유의 task, workspace, session, approval, artifact, notification 문맥은 별도 `iop` wrapper field가 아니라 `metadata` 확장으로 전달한다. A2A는 agent-to-agent delegation이 명확히 필요할 때 재검토하며, IOP native protocol은 NomadCode의 기본 외부 실행 호출 표면으로 쓰지 않는다.
|
||||
|
||||
|
|
@ -15,52 +15,49 @@ IOP 외부 실행 호출은 OpenAI-compatible Responses API 방식을 기본 계
|
|||
검토중 또는 진행중 Phase는 계획 Phase보다 위에 두어, 아래로 갈수록 미래 계획에 가까워지게 정렬한다.
|
||||
|
||||
- [완료] Server Skeleton
|
||||
- 경로: [Server Skeleton PHASE.md](archive/phase/server-skeleton/PHASE.md)
|
||||
- 경로: `agent-roadmap/archive/phase/server-skeleton/PHASE.md`
|
||||
- 요약: core 서버 실행 골격, task 저장 구조, 비동기 job 실행, Adapter stub을 구성했다.
|
||||
- [완료] Plane Communication Foundation
|
||||
- 경로: [Plane Communication Foundation PHASE.md](archive/phase/plane-communication-foundation/PHASE.md)
|
||||
- 경로: `agent-roadmap/archive/phase/plane-communication-foundation/PHASE.md`
|
||||
- 요약: Plane self-hosted 인스턴스와 통신하기 위한 인증, API client, 외부 참조 저장, smoke 검증 토대를 만들었다.
|
||||
- [완료] Client Platform Consolidation
|
||||
- 경로: [Client Platform Consolidation PHASE.md](archive/phase/client-platform-consolidation/PHASE.md)
|
||||
- 경로: `agent-roadmap/archive/phase/client-platform-consolidation/PHASE.md`
|
||||
- 요약: React/Vite 웹 콘솔을 제품 UI 경로에서 걷어내고 Flutter 앱을 NomadCode 클라이언트 source of truth로 정리했다.
|
||||
- [완료] Work Item Provider Pipeline Design
|
||||
- 경로: [Work Item Provider Pipeline Design PHASE.md](archive/phase/work-item-provider-pipeline-design/PHASE.md)
|
||||
- 경로: `agent-roadmap/archive/phase/work-item-provider-pipeline-design/PHASE.md`
|
||||
- 요약: Plane/Jira 등 work item provider와 core task 사이의 생성, enqueue, 상태 투영, 결과 발행 계약을 provider-neutral하게 정리했다.
|
||||
- [완료] Mattermost Push Plugin Extraction
|
||||
- 경로: [Mattermost Push Plugin Extraction PHASE.md](archive/phase/mattermost-push-plugin-extraction/PHASE.md)
|
||||
- 경로: `agent-roadmap/archive/phase/mattermost-push-plugin-extraction/PHASE.md`
|
||||
- 요약: Flutter 앱에 섞인 Mattermost push notification migration을 분리했고, 현재 package 경로는 `../nexo/packages/messaging_flutter`다.
|
||||
- [완료] Workflow Core
|
||||
- 경로: [Workflow Core PHASE.md](archive/phase/workflow-core/PHASE.md)
|
||||
- 경로: `agent-roadmap/archive/phase/workflow-core/PHASE.md`
|
||||
- 요약: proto-socket 내부 통신 레일을 정리한 뒤 client-core 통신과 실제 e2e 흐름을 기준으로 task lifecycle, retry, timeout, notification event를 안정화한다.
|
||||
- [완료] External Integration
|
||||
- 경로: [External Integration PHASE.md](archive/phase/external-integration/PHASE.md)
|
||||
- 경로: `agent-roadmap/archive/phase/external-integration/PHASE.md`
|
||||
- 요약: Plane 확장, Jira-compatible provider 추상화, Mattermost, Agent Integrator, IOP OpenAI-compatible Responses 호출 경계를 실제 통합 adapter 흐름으로 확장했고, metadata 실행 문맥 전달, IOP Edge `/v1/responses`, NomadCode Core 원격 create/enqueue/poll smoke를 완료했다.
|
||||
- [진행중] Agent-Ops Work Item Lifecycle
|
||||
- 경로: [Agent-Ops Work Item Lifecycle PHASE.md](phase/agent-ops-work-item-lifecycle/PHASE.md)
|
||||
- 요약: 로드맵 기반 agent-ops 운영 자동화와 Plane/Jira 같은 work item provider의 Todo 이후 실행 lifecycle을 다룬다. 다음 후보는 Milestone Execution Lifecycle Sync이며, MCP와 외부 agent 제어 표면은 이 Phase 범위에서 제외한다.
|
||||
- [진행중] Agent-Ops MCP Control Plane
|
||||
- 경로: `agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md`
|
||||
- 요약: 로드맵 기반 agent-ops 운영 자동화, Plane/Jira 같은 work item provider와 Milestone item의 양방향 동기화 도메인, 외부 agent용 MCP 제어 표면을 다루며, 현재 Roadmap Driven Agent-Ops Automation에서 roadmap/action core와 provider sync domain의 상위 방향을 정리한다.
|
||||
- [계획] Project Workspace Management UX
|
||||
- 경로: [Project Workspace Management UX PHASE.md](phase/project-workspace-management-ux/PHASE.md)
|
||||
- 경로: `agent-roadmap/phase/project-workspace-management-ux/PHASE.md`
|
||||
- 요약: client integration 표준화, core workflow, 외부 통합 기준 이후 프로젝트 단위 앱 UX를 다루며, provider slot 기반 외부 console composition은 계획 후보로 둔다.
|
||||
- [스케치] MCP Control Surface
|
||||
- 경로: [MCP Control Surface PHASE.md](phase/mcp-control-surface/PHASE.md)
|
||||
- 요약: 외부 agent 제어 표면을 MCP로 둘지 여부, tool policy, 권한, side effect 경계를 현재 ops lifecycle과 분리해 마지막 후보로 검토한다.
|
||||
|
||||
## 로딩 정책
|
||||
|
||||
- 일반 작업에서는 [ROADMAP.md](ROADMAP.md)를 매번 읽지 않는다.
|
||||
- 기능 추가, 구조 변경, 스킬 추가/수정, 문서 구조 변경 작업을 수행할 때는 [current.md](current.md)를 먼저 읽는다.
|
||||
- 일반 작업에서는 `agent-roadmap/ROADMAP.md`를 매번 읽지 않는다.
|
||||
- 기능 추가, 구조 변경, 스킬 추가/수정, 문서 구조 변경 작업을 수행할 때는 `agent-roadmap/current.md`를 먼저 읽는다.
|
||||
- `current.md`는 현재 작업 위치가 아니라 활성 Phase와 활성 Milestone 후보 목록이다.
|
||||
- `current.md`에는 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
|
||||
- `current.md`의 활성 Phase는 [Agent-Ops Work Item Lifecycle PHASE.md](phase/agent-ops-work-item-lifecycle/PHASE.md)를 가리킨다.
|
||||
- `current.md`의 활성 Milestone은 [Milestone Execution Lifecycle Sync](phase/agent-ops-work-item-lifecycle/milestones/milestone-execution-lifecycle-sync.md)를 가리킨다.
|
||||
- `current.md`의 활성 Phase는 `agent-roadmap/phase/<phase-slug>/PHASE.md`를 가리킨다.
|
||||
- `current.md`의 활성 Milestone은 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`를 가리킨다.
|
||||
- `current.md`는 `agent-roadmap/archive/**` 경로를 활성 항목으로 포함하지 않는다.
|
||||
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 활성 Phase와 Milestone 문서를 같은 세션에서 1회 읽는다.
|
||||
- 활성 Phase 또는 Milestone 밖의 작업이면 이 문서의 Phase 흐름을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
|
||||
- 이 문서는 로드맵 생성/갱신, Phase 전환, Phase 추가/수정, 전체 구조 변경 요청이 있을 때만 읽는다.
|
||||
- 상세 작업은 각 Milestone 문서의 `기능`으로 관리한다. 검증이 필요한 기능만 같은 Task 안에 `검증:`으로 통합한다.
|
||||
- 모든 기능 Task와 Task 안에 명시된 검증이 충족된 Milestone은 먼저 `[검토중]`으로 두고, 사용자 완료 확인과 archive 승인을 받은 뒤 `[완료]`로 전환한다.
|
||||
- 완료된 Phase는 archive의 해당 PHASE 문서로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
|
||||
- 진행중 Phase 안에서 완료된 Milestone은 활성 Phase 문서에 짧은 링크를 남기고, 상세 문서는 해당 archive milestones 디렉터리로 이동한다.
|
||||
- 완료된 Phase는 `agent-roadmap/archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
|
||||
- 진행중 Phase 안에서 완료된 Milestone은 활성 Phase 문서에 짧은 링크를 남기고, 상세 문서는 `agent-roadmap/archive/phase/<phase-slug>/milestones/`로 이동한다.
|
||||
- archive `PHASE.md`는 Phase 자체가 완료 또는 폐기될 때만 만들며, 진행중 Phase의 완료 Milestone만 archive된 경우 archive Phase 디렉터리에 `milestones/`만 있을 수 있다.
|
||||
- `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라가서 읽는다.
|
||||
- 아카이브된 Phase/Milestone 문서는 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.
|
||||
|
|
|
|||
|
|
@ -1,82 +0,0 @@
|
|||
# Milestone: Agent-Origin Milestone Creation Sync
|
||||
|
||||
## 위치
|
||||
|
||||
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||
- Phase: `agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md`
|
||||
|
||||
## 목표
|
||||
|
||||
agent 또는 사람이 `agent-roadmap` active Milestone을 직접 수정해 `develop`에 push한 경우에도 NomadCode가 Gito branch revision을 검증한 뒤 Plane work item을 생성하거나 갱신하고, 생성된 provider identity를 다시 roadmap 파일에 backfill commit으로 남긴다. Plane-origin 흐름과 같은 identity ledger, revision guard, retry/idempotency 기준을 사용해 양방향 생성 동기화의 빈 경로를 닫는다.
|
||||
|
||||
## 상태
|
||||
|
||||
[완료]
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 해제
|
||||
- SDD: 필요
|
||||
- SDD 문서: `agent-roadmap/archive/sdd/agent-ops-mcp-control-plane/agent-origin-milestone-creation-sync/SDD.md`
|
||||
- SDD 사유: Gito webhook, Plane provider 쓰기, git identity backfill push, revision/idempotency/identity map을 함께 다루는 sync state machine이다.
|
||||
- 잠금 해제 조건:
|
||||
- [x] SDD 잠금이 해제되어 있다
|
||||
- [x] SDD 사용자 리뷰가 없거나 승인/해결되었다
|
||||
- [x] Acceptance Scenario가 Milestone 기능 Task와 연결되어 있다
|
||||
- [x] Evidence Map이 완료 시 Roadmap Completion과 최종 검증 evidence로 검증 가능하게 연결되어 있다
|
||||
- 결정 필요: 없음
|
||||
|
||||
## 범위
|
||||
|
||||
- Gito `branch.updated` webhook을 wakeup으로 받아 `develop` branch의 target revision을 fetch/scan하는 agent-origin sync 경로
|
||||
- active Milestone 파일 중 provider identity가 없는 신규/변경 Milestone을 Plane work item 생성 대상으로 판별하는 기준
|
||||
- Plane work item 생성 후 `roadmap_sync_identities` ledger에 canonical filename slug와 provider work item id를 저장하는 흐름
|
||||
- 생성된 provider identity block을 원래 Milestone markdown에 backfill하고 별도 commit/push로 `develop`에 반영하는 흐름
|
||||
- Core가 만든 identity-only backfill commit이 다시 들어왔을 때 self-loop와 중복 provider mutation을 막는 idempotency guard
|
||||
- 기존 provider identity가 있는 Milestone 변경은 Plane 본문/제목 갱신으로 수렴하고, identity 충돌/rename/reuse는 conflict로 멈추는 정책
|
||||
|
||||
## 기능
|
||||
|
||||
### Epic: [agent-origin-sync] Agent-origin Milestone creation sync
|
||||
|
||||
agent-origin roadmap push를 Plane work item 생성/갱신과 provider identity backfill까지 수렴시킨다.
|
||||
|
||||
- [x] [scan-diff] Gito webhook의 `before..after` 변경 목록을 wakeup 힌트로 사용하되, `after` SHA를 fetch/검증한 뒤 active Milestone diff와 전체 active index를 함께 스캔한다. 검증: `changed_files`만 신뢰하지 않고 `origin/develop`의 `after` SHA가 일치할 때만 sync job이 enqueue된다.
|
||||
- [x] [missing-create] provider identity가 없는 active Milestone을 agent-origin 생성 후보로 판별하고 Plane work item을 생성한다. 검증: 같은 milestone slug와 revision을 재처리해도 중복 Plane work item을 만들지 않는다.
|
||||
- [x] [identity-ledger] 생성된 Plane work item id를 `roadmap_sync_identities`에 filename slug 기준으로 upsert하고 revision/idempotency conflict를 구분한다. 검증: 기존 slug가 다른 provider work item에 묶여 있으면 provider mutation 없이 conflict로 멈춘다.
|
||||
- [x] [identity-backfill] Plane 생성 직후 Milestone markdown에 `Provider identity` block을 주입하고 Core-authored backfill commit을 `develop`에 push한다. 검증: backfill commit에는 identity block 외의 unrelated roadmap 변경이 포함되지 않는다.
|
||||
- [x] [self-loop] Core-authored identity backfill webhook은 provider 생성/갱신을 반복하지 않고 ledger와 markdown identity 일치 여부만 확인한다. 검증: backfill commit 재전달과 Core 재시작 후 재전달 모두 no-op 또는 complete로 수렴한다.
|
||||
- [x] [identity-update] provider identity가 이미 있는 Milestone의 agent-origin 본문/제목 변경은 Plane 본문/제목 갱신으로 수렴한다. 검증: `develop` revision guard와 completed-step ledger로 부분 실패를 재시도할 수 있다.
|
||||
- [x] [conflict-policy] rename, filename slug reuse, provider identity mismatch, stale Plane work item, duplicate active slug를 안전하게 분류한다. 검증: destructive overwrite 없이 conflict/not-ready/skip 결과와 로그가 구분된다.
|
||||
- [x] [field-smoke] dev 환경에서 agent가 active Milestone을 직접 추가해 push한 뒤 Plane ticket 생성, identity backfill commit, 재전달 no-op까지 확인한다. 검증: secret을 남기지 않은 DB/log/Plane/git evidence가 `complete.log`에 기록된다.
|
||||
|
||||
## 완료 리뷰
|
||||
|
||||
- 상태: 통과
|
||||
- 요청일: 2026-07-03
|
||||
- 완료 근거: `agent-task/archive/2026/07/m-agent-origin-milestone-creation-sync/` 아래 4개 `complete.log`의 `Roadmap Completion`이 S01-S08 Task id와 정확히 일치하고 모두 PASS다.
|
||||
- 추가 확인: 핵심 파일 sanity pass에서 `gitosync` changed_files hint scan, `roadmapsyncpipeline` GitBackfiller/identity_backfilled/self-loop, storage/scheduler retry evidence가 현재 코드와 최근 커밋에 남아 있음을 확인했다.
|
||||
- 추가 확인: 코드 레벨 종료 감사에서 `Scan`이 trim 검증한 revision을 실제 `git show`에도 쓰도록 보강했고, `TestScanUsesTrimmedVerifiedRevisionForShow`를 추가했다. `go test -count=1 ./...`, `go vet ./...` 통과.
|
||||
- 검토 항목:
|
||||
- [x] 모든 기능 Task와 검증이 `Roadmap Completion` evidence로 충족되었다
|
||||
- [x] SDD Evidence Map이 최종 검증 evidence와 일치한다
|
||||
- [x] 사용자가 완료 결과를 확인했다
|
||||
- [x] archive 이동을 승인했다
|
||||
- agent-ui 상태 반영: 해당 없음
|
||||
- 리뷰 코멘트: 종료 차단 항목 없음. 코드 레벨 감사와 최종 검증 통과 후 archive 이동한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- Plane `Todo -> In Progress` 이후 실행 lifecycle과 하위 티켓 생성
|
||||
- agent-task plan/code-review 결과를 Plane 하위 티켓 상태로 동기화하는 흐름
|
||||
- MCP control surface와 외부 agent tool permission 정책
|
||||
- 사용자 승인 없는 자동 archive 이동
|
||||
- provider native API schema 일반화 또는 Jira 구현
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/core/internal/gitosync/`, `services/core/internal/roadmapsync/`, `services/core/internal/roadmapsyncpipeline/`, `services/core/internal/authoring/`, `services/core/internal/workitem/`, `services/core/internal/scheduler/`, `agent-contract/outer/gito-branch-webhook-consumer-v1.md`, `agent-roadmap/`
|
||||
- 표준선: Gito webhook은 wakeup signal이며, Plane/roadmap mutation 전에는 반드시 `origin/develop`의 target SHA를 fetch/scan해 검증한다. filename slug가 canonical milestone id이고, provider identity block은 repo portable anchor로 유지한다.
|
||||
- 선행 작업: Plane-Origin Authoring Roundtrip Sync, Roadmap Driven Agent-Ops Automation
|
||||
- 후속 작업: Milestone Execution Lifecycle Sync
|
||||
- 확인 필요: 없음
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
# SDD: Agent-Origin Milestone Creation Sync
|
||||
|
||||
## 위치
|
||||
|
||||
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/agent-origin-milestone-creation-sync.md`
|
||||
- Phase: `agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md`
|
||||
|
||||
## 상태
|
||||
|
||||
[승인됨]
|
||||
|
||||
## SDD 잠금
|
||||
|
||||
- 상태: 해제
|
||||
- 사용자 리뷰: 없음
|
||||
- 잠금 항목:
|
||||
- 없음
|
||||
|
||||
## 문제 / 비목표
|
||||
|
||||
- 문제: Plane-origin 흐름은 Plane 요청에서 시작해 pushed develop SHA를 확인한 뒤 Plane Todo projection까지 수렴하지만, agent 또는 사람이 `agent-roadmap` active Milestone을 직접 수정해 push한 경우 provider identity가 없는 Milestone을 Plane work item과 안정적으로 연결하고 그 identity를 repo에 되돌려 쓰는 경로가 부족하다.
|
||||
- 비목표:
|
||||
- Todo 이후 실행 lifecycle과 Plane 하위 티켓 동기화
|
||||
- MCP control surface 또는 외부 agent tool permission 정책
|
||||
- provider native API schema 일반화 또는 Jira 구현
|
||||
- 사용자 승인 없는 archive 이동
|
||||
|
||||
## Source of Truth
|
||||
|
||||
| 영역 | 기준 | 메모 |
|
||||
|------|------|------|
|
||||
| Roadmap | `agent-roadmap/phase/**/milestones/*.md` on `develop` | active Milestone markdown이 Plane projection의 본문/제목 기준이며 filename slug가 canonical milestone id다. |
|
||||
| Code | `services/core/internal/gitosync/`, `services/core/internal/roadmapsyncpipeline/`, `services/core/internal/roadmapsync/` | Gito revision scan, identity matching, provider mutation, ledger/retry orchestration을 소유한다. |
|
||||
| External Provider | Plane | Plane work item id와 state는 provider side effect 결과이며 raw token/secret은 tracked 문서에 기록하지 않는다. |
|
||||
| User Decision | 없음 | 사용자는 agent-origin identity backfill 방향을 승인했고, 남은 항목은 기존 sync/domain rule로 구현 가능하다. |
|
||||
|
||||
## State Machine
|
||||
|
||||
| 상태 | 진입 조건 | 다음 상태 | 근거 |
|
||||
|------|-----------|-----------|------|
|
||||
| `branch_event_received` | Gito `branch.updated` webhook이 target repo/branch로 들어온다. | `revision_verified` 또는 `not_ready` | `agent-contract/outer/gito-branch-webhook-consumer-v1.md` |
|
||||
| `revision_verified` | local develop checkout fetch 후 `origin/develop`이 event `after` SHA와 일치한다. | `milestone_scanned` | `git fetch`, `git rev-parse`, `git ls-tree`, `git show` |
|
||||
| `milestone_scanned` | active Milestone diff와 active index를 읽고 identity 유무를 분류한다. | `missing_identity_candidate`, `identity_matched`, `conflict` | roadmap parser, duplicate slug guard |
|
||||
| `missing_identity_candidate` | provider identity가 없는 active Milestone이 생성 후보로 판별된다. | `plane_created` 또는 `conflict` | filename slug, project sync config, ledger lookup |
|
||||
| `plane_created` | Plane work item 생성과 DB identity upsert가 성공한다. | `identity_backfilled` | Plane adapter, `roadmap_sync_identities` |
|
||||
| `identity_backfilled` | Milestone markdown에 `Provider identity` block을 주입한 commit이 `develop`에 push된다. | `self_loop_checked` | Core-authored git commit/push |
|
||||
| `identity_matched` | provider identity가 있는 Milestone 변경이다. | `plane_projected`, `complete`, `conflict` | roadmap revision guard, completed-step ledger |
|
||||
| `self_loop_checked` | identity-only backfill commit webhook이 재수신된다. | `complete` 또는 `conflict` | actor/commit marker, markdown identity, ledger |
|
||||
| `conflict` | slug reuse, identity mismatch, duplicate active slug, destructive overwrite 위험이 감지된다. | `conflict` | no provider mutation, operator/user review evidence |
|
||||
|
||||
## Interface Contract
|
||||
|
||||
- 계약 원문: `agent-contract/outer/gito-branch-webhook-consumer-v1.md`
|
||||
- 입력:
|
||||
- `repo_id`: target repository id. `GITO_REPO_ID`와 일치해야 한다.
|
||||
- `branch`: target branch. 기본값은 `develop`이다.
|
||||
- `before`: 이전 git SHA. diff 후보 산정에 사용하되 source-of-truth로 단정하지 않는다.
|
||||
- `after`: 새 git SHA. fetch/scan 및 idempotency 기준이다.
|
||||
- `changed_files`: wakeup relevance 힌트. 실제 sync는 target revision scan으로 확인한다.
|
||||
- 출력:
|
||||
- Plane work item 생성/갱신 결과
|
||||
- `roadmap_sync_identities` identity row와 completed step ledger
|
||||
- provider identity block backfill commit SHA
|
||||
- conflict/not-ready/complete/projected 로그와 job result
|
||||
- 금지:
|
||||
- `changed_files`만 믿고 Plane 또는 roadmap 파일을 mutation하지 않는다.
|
||||
- provider identity가 충돌하는 Milestone을 덮어쓰지 않는다.
|
||||
- Core-authored backfill commit 재전달로 Plane work item을 중복 생성하지 않는다.
|
||||
- raw secret, token, provider credential을 tracked evidence나 로그에 남기지 않는다.
|
||||
|
||||
## Acceptance Scenarios
|
||||
|
||||
| ID | Milestone Task | Given | When | Then |
|
||||
|----|----------------|-------|------|------|
|
||||
| S01 | `scan-diff` | Gito event가 `before`, `after`, `changed_files`를 포함한다. | Core가 fetch 후 `origin/develop`과 `after` SHA를 비교한다. | SHA가 일치할 때만 active Milestone scan이 진행되고, 불일치하면 not-ready로 남는다. |
|
||||
| S02 | `missing-create` | active Milestone 파일이 추가됐고 provider identity가 없다. | `after` revision scan에서 생성 후보로 분류된다. | Plane work item이 1개만 생성되고 같은 revision 재처리는 중복 생성하지 않는다. |
|
||||
| S03 | `identity-ledger` | 생성된 Plane work item id와 milestone slug가 있다. | identity row를 upsert한다. | 같은 slug/provider key는 재시도 가능하고, 다른 provider work item과 충돌하면 conflict로 멈춘다. |
|
||||
| S04 | `identity-backfill` | Plane 생성과 identity ledger 기록이 완료됐다. | Core가 Milestone markdown에 provider identity block을 추가한다. | identity-only backfill commit이 `develop`에 push되고 unrelated 변경은 포함되지 않는다. |
|
||||
| S05 | `self-loop` | backfill commit으로 다시 Gito webhook이 들어온다. | Core가 actor/commit marker, markdown identity, ledger를 비교한다. | Plane 생성/갱신이 반복되지 않고 complete/no-op으로 수렴한다. |
|
||||
| S06 | `identity-update` | provider identity가 있는 Milestone markdown이 agent-origin으로 수정됐다. | Core가 target revision을 scan한다. | Plane 제목/본문 갱신이 ledger step으로 재시도 가능하게 수행된다. |
|
||||
| S07 | `conflict-policy` | rename, slug reuse, stale provider item, duplicate active slug 중 하나가 발생한다. | Core가 sync를 시도한다. | destructive overwrite 없이 conflict/not-ready/skip 중 하나로 분류하고 provider mutation을 제한한다. |
|
||||
| S08 | `field-smoke` | dev Plane/Gito/NomadCode/IOP 환경이 준비되어 있다. | agent가 identity 없는 active Milestone을 직접 push한다. | Plane ticket 생성, identity backfill commit, 재전달 no-op, secret-redacted evidence가 확인된다. |
|
||||
|
||||
## Evidence Map
|
||||
|
||||
| Scenario | Required Evidence | `agent-task` 연결 | 완료 Evidence 기대 |
|
||||
|----------|-------------------|------------------|---------------------------|
|
||||
| S01 | gitosync scanner/bridge unit test and webhook handler test | `agent-task/m-agent-origin-milestone-creation-sync/...` | `scan-diff` Roadmap Completion, test output, revision mismatch/not-ready evidence |
|
||||
| S02 | roadmapsyncpipeline missing-create idempotency test | `agent-task/m-agent-origin-milestone-creation-sync/...` | `missing-create` Roadmap Completion, duplicate retry evidence |
|
||||
| S03 | storage identity conflict/upsert test | `agent-task/m-agent-origin-milestone-creation-sync/...` | `identity-ledger` Roadmap Completion, conflict evidence |
|
||||
| S04 | identity backfill writer test and git commit scope check | `agent-task/m-agent-origin-milestone-creation-sync/...` | `identity-backfill` Roadmap Completion, commit diff evidence |
|
||||
| S05 | self-loop/redelivery test across process restart or durable ledger | `agent-task/m-agent-origin-milestone-creation-sync/...` | `self-loop` Roadmap Completion, no-op/complete evidence |
|
||||
| S06 | provider identity update projection test | `agent-task/m-agent-origin-milestone-creation-sync/...` | `identity-update` Roadmap Completion, Plane body/title projection evidence |
|
||||
| S07 | conflict classification tests | `agent-task/m-agent-origin-milestone-creation-sync/...` | `conflict-policy` Roadmap Completion, no destructive provider mutation evidence |
|
||||
| S08 | dev field smoke with redacted logs/DB/Plane/git evidence | `agent-task/m-agent-origin-milestone-creation-sync/...` | `field-smoke` Roadmap Completion, final dev cycle evidence without secrets |
|
||||
|
||||
## Cross-repo Dependencies
|
||||
|
||||
- Gito provides `gito.forgejo-branch-events.v1`; NomadCode consumes it through `agent-contract/outer/gito-branch-webhook-consumer-v1.md`.
|
||||
|
||||
## Drift Check
|
||||
|
||||
- [x] Milestone 기능 Task와 Acceptance Scenario가 일치한다.
|
||||
- [x] Evidence Map이 code-review/complete.log에서 검증 가능하다.
|
||||
- [x] agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
|
||||
- [x] 사용자 리뷰가 필요한 항목은 `USER_REVIEW.md`에만 남겼다.
|
||||
|
||||
## 사용자 리뷰 이력
|
||||
|
||||
- 없음
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 표준선: `develop` branch의 active Milestone markdown이 roadmap source of truth이며, Gito webhook은 wakeup으로만 사용한다. Provider identity block은 repo portable anchor이고, DB ledger는 runtime idempotency/retry state다.
|
||||
- 후속 SDD: Milestone Execution Lifecycle Sync에서 하위 티켓/agent-task lifecycle을 다룰 때 별도 SDD 필요 여부를 다시 판정한다.
|
||||
56
agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md
Normal file
56
agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Phase: Agent-Ops MCP Control Plane
|
||||
|
||||
## 상태
|
||||
|
||||
[진행중]
|
||||
|
||||
## 목표
|
||||
|
||||
로드맵 기반 agent-ops 운영 루프, Plane/Jira 같은 work item provider와 Milestone item의 양방향 동기화 도메인, 외부 agent 제어 표면을 Core action과 MCP tool 계층으로 분리한다. 현재는 Gito HTTP Webhook Consumer Readiness까지 완료/archive했고, Roadmap Driven Agent-Ops Automation을 활성 Milestone으로 두어 roadmap/action core와 provider sync domain의 상위 방향을 정리한다.
|
||||
|
||||
## Milestone 흐름
|
||||
|
||||
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
|
||||
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||
|
||||
- [완료] 워크스페이스 포트/환경 표준화
|
||||
- 경로: `agent-roadmap/archive/phase/agent-ops-mcp-control-plane/milestones/workspace-port-env-standardization.md`
|
||||
- 요약: NomadCode client/core/compose/test runner 포트와 IOP Edge 연동 endpoint를 workspace 공통 대역과 remote runner 문서 기준으로 정리하고, remote code-server preview 정상 노출 확인 후 archive했다.
|
||||
|
||||
- [완료] Milestone Work Item Creation Sync
|
||||
- 경로: `agent-roadmap/archive/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
|
||||
- 요약: Plane-origin 방식으로 Milestone을 생성하고 Plane Todo 티켓까지 동기화한 뒤 멈추는 마일스톤이다. 12/13/14번 task group의 `Roadmap Completion` 근거로 live-cycle gate 보완 Task까지 완료했고, 사용자 승인 후 archive했다.
|
||||
|
||||
- [완료] Plane Work Item Webhook Intake
|
||||
- 경로: `agent-roadmap/archive/phase/agent-ops-mcp-control-plane/milestones/plane-work-item-webhook-intake.md`
|
||||
- 요약: Plane work item 생성, 상태 변경, assignee 변경 webhook을 NomadCode Core가 받아 `Backlog + AGENT assignee` 조건을 재검증하고 기존 Milestone creation sync pipeline을 시작하도록 연결했다. 코드 레벨 재검토와 사용자 종료 승인 후 archive했다.
|
||||
|
||||
- [완료] Gito Branch Event Creation Sync Bridge
|
||||
- 경로: `agent-roadmap/archive/phase/agent-ops-mcp-control-plane/milestones/gito-branch-event-creation-sync-bridge.md`
|
||||
- 요약: Gito `branch.updated` wakeup을 NomadCode core가 소비하고 target branch 재검증/스캔 뒤 creation sync job으로 enqueue하는 bridge를 구현했다. 코드 레벨 종료 검토에서 roadmap milestone path가 없는 event drop을 보강하고 archive했다.
|
||||
|
||||
- [완료] Gito Proto-Socket Consumer Wire Readiness
|
||||
- 경로: `agent-roadmap/archive/phase/agent-ops-mcp-control-plane/milestones/gito-protosocket-consumer-wire-readiness.md`
|
||||
- 요약: NomadCode/Gito 연동 MVP의 Gito `/proto-socket` binary transport/decode, bridge e2e, failure/reconnect 운영 기준 검증을 완료했고, 사용자 승인 후 archive했다.
|
||||
|
||||
- [완료] Gito HTTP Webhook Consumer Readiness
|
||||
- 경로: `agent-roadmap/archive/phase/agent-ops-mcp-control-plane/milestones/gito-http-webhook-consumer-readiness.md`
|
||||
- 요약: Gito `gito.forgejo-branch-events.v1` signed HTTP webhook delivery를 NomadCode Core가 소비하고 branch revision 재검증/creation sync enqueue로 수렴하는 구현을 코드 레벨 종료 감사와 소규모 계약 보강 후 archive했다.
|
||||
|
||||
- [진행중] Roadmap Driven Agent-Ops Automation
|
||||
- 경로: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/roadmap-driven-agent-ops-automation.md`
|
||||
- 요약: roadmap/action core와 Plane/Jira 기반 Milestone item 동기화의 상위 방향과 계약을 정리하는 활성 설계 마일스톤이며, 실제 구현은 slice 마일스톤으로 진행한다.
|
||||
|
||||
- [계획] Milestone Execution Lifecycle Sync
|
||||
- 경로: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-execution-lifecycle-sync.md`
|
||||
- 요약: Todo 이후 In Progress 실행, 하위 티켓, plan/code-review, 완료/폐기 흐름은 사용자가 명시적으로 해제할 때까지 구현 잠금 상태로 둔다.
|
||||
|
||||
## Phase 경계
|
||||
|
||||
- 이 Phase는 현재 Workflow Core 구현의 선행 조건이 아니다.
|
||||
- Core task lifecycle, proto-socket client-core 통신, provider adapter 기본 통합, Flutter workbench UX가 먼저 닫힌 뒤 진행한다.
|
||||
- Plane/Jira work item과 agent-roadmap Milestone item의 양방향 동기화는 별도 Core sync domain이 소유하며, provider adapter 세부 구현과 분리한다.
|
||||
- Sync는 Plane/Jira provider project 단위 project sync 설정을 통해 provider project target, git remote, 실제 작업 workspace를 확정한 뒤 진행한다.
|
||||
- MCP 서버, 외부 agent tool policy, roadmap/action side effect 제어는 이 Phase에서 다룬다.
|
||||
- IOP 내부 모델 라우팅, RAG, context compression, output validation은 NomadCode 범위에서 제외한다.
|
||||
|
|
@ -1,10 +1,16 @@
|
|||
|
||||
# Milestone: Milestone Execution Lifecycle Sync
|
||||
|
||||
## 위치
|
||||
|
||||
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
|
||||
- Phase: [Agent-Ops Work Item Lifecycle PHASE.md](../PHASE.md)
|
||||
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||
- Phase: `agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md`
|
||||
|
||||
|
||||
## Provider identity
|
||||
|
||||
- Provider: `plane`
|
||||
- Work item id: `6945a5e7-b2ef-4d48-a037-00fa2b6ab99b`
|
||||
- Roadmap item id: `milestone-execution-lifecycle-sync`
|
||||
|
||||
## 목표
|
||||
|
||||
|
|
@ -18,7 +24,7 @@ Plane `Todo` 검토 이후 사용자가 `In Progress`로 옮긴 상위 티켓을
|
|||
|
||||
- 상태: 잠금
|
||||
- 결정 필요:
|
||||
- [ ] 사용자가 `Agent-Origin Milestone Creation Sync` 종료 확인 후 이 마일스톤의 잠금 해제를 명시한다.
|
||||
- [ ] 사용자가 `Milestone Work Item Creation Sync` 확인 후 이 마일스톤의 잠금 해제를 명시한다.
|
||||
|
||||
## 범위
|
||||
|
||||
|
|
@ -62,9 +68,8 @@ Todo 이후 실행 lifecycle을 Plane 하위 티켓, Milestone Task, agent-task
|
|||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/core/internal/workitem/`, `services/core/internal/scheduler/`, `services/core/internal/workflow/`, `agent-task/`, `packages/contracts/`, `agent-roadmap/`
|
||||
- 선행 작업: `Roadmap Driven Agent-Ops Automation`, `Agent-Origin Milestone Creation Sync`
|
||||
- 선행 작업: `Milestone Work Item Creation Sync`
|
||||
- 잠금 해제 조건: 사용자가 명시적으로 이 마일스톤의 잠금 해제를 요청한다.
|
||||
- 현재 지점: agent-origin 생성 동기화가 닫히고 사용자가 명시적으로 잠금 해제를 요청하기 전까지 실행하지 않는 후속 마일스톤이다.
|
||||
- MCP 분리: 외부 agent 제어 표면과 MCP 채택 여부는 [MCP Control Surface PHASE.md](../../mcp-control-surface/PHASE.md)로 분리했으며 이 마일스톤의 실행 lifecycle 범위에 포함하지 않는다.
|
||||
- 현재 지점: 사용자 확인과 명시적 잠금 해제 전까지 실행하지 않는 후속 마일스톤이다.
|
||||
- 확인 필요:
|
||||
- [ ] 잠금 해제 후 `Todo -> In Progress` 이후 범위를 다시 확인한다.
|
||||
|
|
@ -11,7 +11,7 @@ Plane `Backlog + AGENT assignee` 상위 티켓에서 시작한 Milestone authori
|
|||
|
||||
## 상태
|
||||
|
||||
[완료]
|
||||
[진행중]
|
||||
|
||||
## 승격 조건
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ Plane `Backlog + AGENT assignee` 상위 티켓에서 시작한 Milestone authori
|
|||
|
||||
- 상태: 해제
|
||||
- SDD: 필요
|
||||
- SDD 문서: `agent-roadmap/archive/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md`
|
||||
- SDD 문서: `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md`
|
||||
- SDD 사유: 외부 provider 쓰기, IOP 실행 호출, git push, Gito webhook, identity map, retry/timeout, live smoke가 모두 걸린 runtime sync 마일스톤이다.
|
||||
- 잠금 해제 조건:
|
||||
- [x] SDD 잠금이 해제되어 있다.
|
||||
|
|
@ -82,25 +82,21 @@ Gito HTTP webhook wakeup 이후 Core sync pipeline이 active Milestone reconcile
|
|||
|
||||
이 마일스톤은 unit/fake seam만으로 닫지 않고 실제 dev 환경에서 한 사이클 증거를 남긴다.
|
||||
|
||||
- [x] [remote-baseline] standard remote runner, Core compose, IOP workspace clone, Gito service, Forgejo webhook, project sync DB 설정을 현재 요청 기준으로 reset/clean/reclone 또는 rebuild해 맞춘다. 검증: dirty runner 상태를 차단 사유로 삼지 않고 최신 local 작업 범위와 같은 테스트 환경으로 만든다.
|
||||
- [x] [full-cycle] 새 Plane Backlog 티켓을 AGENT에 assign한 authoring roundtrip과, Git에만 있는 active Milestone을 Plane에 생성하는 reconcile roundtrip을 함께 확인한다. 검증: `agent-test/live-cycle-smoke.md` 절차에 따라 secret redaction 상태의 live evidence가 남는다.
|
||||
- [ ] [remote-baseline] standard remote runner, Core compose, IOP workspace clone, Gito service, Forgejo webhook, project sync DB 설정을 현재 요청 기준으로 reset/clean/reclone 또는 rebuild해 맞춘다. 검증: dirty runner 상태를 차단 사유로 삼지 않고 최신 local 작업 범위와 같은 테스트 환경으로 만든다.
|
||||
- [ ] [full-cycle] 새 Plane Backlog 티켓을 AGENT에 assign한 authoring roundtrip과, Git에만 있는 active Milestone을 Plane에 생성하는 reconcile roundtrip을 함께 확인한다. 검증: `agent-test/live-cycle-smoke.md` 절차에 따라 secret redaction 상태의 live evidence가 남는다.
|
||||
- [x] [regression-doc] 이번 회귀 원인과 방지 기준을 `agent-test/live-cycle-smoke.md` 또는 core README의 비밀 없는 운영 규칙에 반영한다. 검증: filename slug canonical id, archive 제외, provider identity 누락, IOP queue timeout, push-only 단계 누락, Gito delivery-only 성공을 각각 완료 조건으로 오인하지 않는 기준이 문서화된다.
|
||||
|
||||
## 완료 리뷰
|
||||
|
||||
- 상태: 통과
|
||||
- 요청일: 2026-06-22
|
||||
- 완료 근거:
|
||||
- 모든 기능 Task와 Task 검증은 `Roadmap Completion`이 있는 `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/*/complete.log` 근거로 충족되었다.
|
||||
- `remote-baseline`은 `12_remote_baseline/complete.log`의 PASS 근거로 완료되었다.
|
||||
- `full-cycle`은 `13+12_full_cycle/complete.log`의 PASS 근거로 완료되었다.
|
||||
- 종료 전 코드 레벨 감사에서 Gito active Milestone scan, filename slug identity, Plane projection ledger, authoring push-only gate, terminal metadata guard 구현과 테스트를 재확인했다.
|
||||
- 상태: 없음
|
||||
- 요청일: 없음
|
||||
- 완료 근거: 없음
|
||||
- 검토 항목:
|
||||
- [x] SDD gate가 해제되었다.
|
||||
- [x] 모든 기능 Task와 검증이 충족되었다.
|
||||
- [x] 실제 dev Plane-origin full-cycle smoke에서 Plane `Todo` projection까지 확인했다.
|
||||
- [x] 사용자 완료 확인과 archive 승인을 받았다.
|
||||
- 리뷰 코멘트: 코드 레벨 종료 감사에서 차단 이슈가 없어 `[완료]`로 전환하고 archive한다.
|
||||
- [ ] 모든 기능 Task와 검증이 충족되었다.
|
||||
- [ ] 실제 dev Plane-origin full-cycle smoke에서 Plane `Todo` projection까지 확인했다.
|
||||
- [ ] 사용자 완료 확인과 archive 승인을 받았다.
|
||||
- 리뷰 코멘트: 없음
|
||||
|
||||
## 범위 제외
|
||||
|
||||
|
|
@ -173,19 +169,19 @@ Gito HTTP webhook wakeup 이후 Core sync pipeline이 active Milestone reconcile
|
|||
- `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/10+09_plane_todo/complete.log`
|
||||
- `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/11+10_slot_finalize/complete.log`
|
||||
- `agent-test/live-cycle-smoke.md`
|
||||
- `remote-baseline` Task는 standard remote runner baseline 복구, secret-free evidence scan, `git diff --check`, focused remote Go test PASS 근거로 완료 처리했다.
|
||||
- `full-cycle` Task는 Plane-origin authoring roundtrip, Git-only active Milestone missing-create/reconcile evidence, terminal metadata overwrite race regression fix와 remote `go test -count=1 ./...` PASS 근거로 완료 처리했다.
|
||||
- 완료 근거:
|
||||
- `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/12_remote_baseline/complete.log`
|
||||
- `agent-task/archive/2026/06/m-plane-origin-authoring-roundtrip-sync/13+12_full_cycle/complete.log`
|
||||
- 현재 활성 `agent-task` plan/review/user-review/complete 파일은 없다.
|
||||
- 현재 남은 실구현/검증 후보는 없다. 사용자 완료 확인과 archive 승인을 받으면 `[완료]` 및 archive 전환 후보가 된다.
|
||||
- 작업 현황 동기화(2026-06-22):
|
||||
- 로컬 `agent-task/` 활성 디렉터리에는 진행중 plan/review 파일이 없다.
|
||||
- 마일스톤의 모든 기능 Task는 완료 체크 상태이며, 구현 잠금은 해제되어 있다.
|
||||
- 상태를 `[검토중]`으로 전환했고, archive 이동은 수행하지 않았다.
|
||||
- 종료 감사(2026-06-22):
|
||||
- 코드 레벨 검토에서 `services/core/internal/gitosync`, `roadmapsync`, `roadmapsyncpipeline`, `scheduler`, `workflow`, `storage`, `authoring`, `adapters/openai`, `adapters/plane`의 마일스톤 관련 구현과 테스트를 확인했다.
|
||||
- 검증 근거: `cd services/core && go test ./internal/gitosync ./internal/roadmapsync ./internal/roadmapsyncpipeline ./internal/scheduler ./internal/workflow ./internal/storage ./internal/authoring ./internal/adapters/openai ./internal/adapters/plane`, `cd services/core && go test ./...`, `cd services/core && go vet ./...`, `git diff --check` 통과.
|
||||
- standard remote runner 검증은 SSH host key mismatch로 실행하지 못했다. 이전 live-cycle 완료 로그의 remote PASS 근거와 현재 로컬 전체 테스트를 종료 판단 보조 근거로 사용했다.
|
||||
- `remote-baseline`과 `full-cycle`은 큰 live runtime 작업으로 분류해 plan-loop에 진입시켰다.
|
||||
- 활성 plan/review:
|
||||
- `agent-task/m-plane-origin-authoring-roundtrip-sync/12_remote_baseline/PLAN-cloud-G07.md`
|
||||
- `agent-task/m-plane-origin-authoring-roundtrip-sync/12_remote_baseline/CODE_REVIEW-cloud-G07.md`
|
||||
- `agent-task/m-plane-origin-authoring-roundtrip-sync/13+12_full_cycle/PLAN-cloud-G08.md`
|
||||
- `agent-task/m-plane-origin-authoring-roundtrip-sync/13+12_full_cycle/CODE_REVIEW-cloud-G08.md`
|
||||
- 현재 남은 실구현/검증 후보는 `remote-baseline`, `full-cycle`이며, 둘 다 active plan 상태다.
|
||||
- 확인 필요: 없음
|
||||
|
||||
|
||||
## Provider identity
|
||||
- provider: plane
|
||||
- tenant: general
|
||||
- project: a6beb42f-7a8a-410c-b50f-ea3ca94828f3
|
||||
- work item id: aade6b05-49f8-491b-8e23-d938c578958d
|
||||
- milestone id: plane-origin-authoring-roundtrip-sync
|
||||
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
## 목표
|
||||
|
||||
NomadCode가 로드맵을 중심으로 사용자 입력, 실행 상태, 출력 검토, 완료 승인까지 한 흐름에서 운영하도록 Roadmap Operations Control Plane의 방향을 정한다. Plane/Jira 같은 work item provider는 사용자가 작업 상태를 움직이는 primary control UI가 될 수 있으며, NomadCode Core는 provider command와 agent-roadmap 변경을 같은 sync domain에서 검증해 Milestone item과 work item이 동일한 구조로 수렴하도록 한다. agent-roadmap은 장기 원장으로 유지하고, agent-ops 스킬은 문서 작성, 의미 해석, 변경 제안 계층으로 낮춘다. 외부 agent 제어 표면은 이 마일스톤의 확정 범위가 아니며 후속 스케치에서 별도로 검토한다.
|
||||
NomadCode가 로드맵을 중심으로 사용자 입력, 실행 상태, 출력 검토, 완료 승인까지 한 흐름에서 운영하도록 Roadmap Operations Control Plane의 방향을 정한다. Plane/Jira 같은 work item provider는 사용자가 작업 상태를 움직이는 primary control UI가 될 수 있으며, NomadCode Core는 provider command와 agent-roadmap 변경을 같은 sync domain에서 검증해 Milestone item과 work item이 동일한 구조로 수렴하도록 한다. agent-roadmap은 장기 원장으로 유지하고, 외부 에이전트는 MCP-first 제어 표면을 통해 Core를 호출하며, agent-ops 스킬은 문서 작성, 의미 해석, 변경 제안, MCP 호출 준비 계층으로 낮춘다.
|
||||
|
||||
## 상태
|
||||
|
||||
[완료]
|
||||
[진행중]
|
||||
|
||||
## 승격 조건
|
||||
|
||||
|
|
@ -26,7 +26,8 @@ NomadCode가 로드맵을 중심으로 사용자 입력, 실행 상태, 출력
|
|||
## 범위
|
||||
|
||||
- NomadCode Core가 품을 roadmap/action core 책임 정의
|
||||
- HTTP API, provider webhook, internal integration의 역할 경계 정의
|
||||
- MCP-first 외부 agent 제어 표면 방향 정의
|
||||
- HTTP API와 MCP의 역할 분리
|
||||
- 사용자 입력, 출력 검토, 승인, 보완, archive 확인을 NomadCode 라인에서 처리하는 흐름 정의
|
||||
- Plane 상위 티켓 1개를 Milestone 1개로 보고, Plane 하위 티켓을 Milestone 기능 Task로 투영하는 사용자 플로우 계약 정의
|
||||
- Plane/Jira 같은 provider work item과 agent-roadmap Milestone item 사이의 양방향 동기화 도메인 책임, 변경 감지, 수렴 정책 정의
|
||||
|
|
@ -34,58 +35,59 @@ NomadCode가 로드맵을 중심으로 사용자 입력, 실행 상태, 출력
|
|||
- Plane-origin authoring에서 workspace agent를 IOP CLI 1차 통로로 실행하는 기준 정의
|
||||
- Plane 상태 `Backlog`, `Todo`, `In Progress`, `User Review`, `Done`, `Cancelled`를 roadmap/agent-task lifecycle command로 해석하는 기준 정의
|
||||
- `Backlog + AGENT assignee`에서 Milestone 초안을 작성하고 Plane 티켓을 `Todo` 검토 상태로 옮긴 뒤, 사용자가 `In Progress`로 옮길 때 실제 실행과 하위 티켓 생성을 시작하는 gate 정의
|
||||
- agent-ops roadmap skills를 작성/제안 계층으로 낮추는 방향 정의
|
||||
- agent-ops roadmap skills를 작성/제안/MCP 호출 준비 계층으로 낮추는 방향 정의
|
||||
- completion event, `USER_REVIEW.md`, 완료 리뷰, dependency lock을 Core action으로 다루는 기준 정의
|
||||
|
||||
## 기능
|
||||
|
||||
### Epic: [control-plane] Roadmap operations control plane
|
||||
|
||||
NomadCode 내부 core logic이 roadmap 기반 작업 운영을 소유하고, provider/UI/agent 입력을 검증 가능한 Core action으로 수렴시키는 구조를 정리한다.
|
||||
NomadCode 내부 core logic이 roadmap 기반 작업 운영을 소유하고, 외부 agent는 MCP를 통해 제어하는 구조를 정리한다.
|
||||
|
||||
- [x] [core-state] roadmap, Phase, Milestone, plan, code-review, completion event, approval 상태를 Core가 다루는 state model과 revision/idempotency 계약으로 정리한다.
|
||||
- [x] [core-actions] validate, position, propose/apply change, transition, archive, dependency check, completion event ingest를 Core action 후보로 정의한다.
|
||||
- [x] [http-role] HTTP API는 Flutter UI, webhook, internal integration용 표면으로 유지하고, 실행 side effect는 Core action의 revision/idempotency 계약을 거치도록 하는 기준을 정한다.
|
||||
- [x] [review-gates] 사용자 입력, 출력 검토, `USER_REVIEW.md`, 완료 승인, archive 승인을 NomadCode workflow 안의 review gate로 처리하는 흐름을 정한다.
|
||||
- [x] [plane-control-flow] Plane을 primary control UI로 쓰는 lifecycle을 정리한다. 검증: `Backlog + AGENT assignee -> Todo -> In Progress -> User Review -> Done/Cancelled` 상태가 Milestone 초안, 사용자 검토, 실행 시작, 사용자 검토, 완료/archive 또는 폐기로 어떻게 연결되는지 문서에서 일관되게 읽힌다.
|
||||
- [x] [plane-identity] Plane 상위 티켓을 Milestone, 하위 티켓을 Milestone 기능 Task로 매핑하는 id 계약을 정한다. 검증: Milestone id는 파일명으로 유지하고, Plane work item id는 외부 provider id로 보존하는 기준이 명확하다.
|
||||
- [x] [todo-draft-gate] `Backlog + AGENT assignee`를 Milestone 초안 생성/갱신 trigger로 정의하고, `develop` branch의 agent-roadmap에 반영된 뒤 Plane 티켓을 `Todo`로 이동하는 gate를 정한다. 검증: Todo 진입은 자동 실행이 아니라 `develop`에 존재하는 Milestone의 사용자 검토 단계임이 명확하다.
|
||||
- [x] [in-progress-exec-gate] 사용자가 Plane 상위 티켓을 `In Progress`로 옮길 때 실제 실행과 하위 티켓 전환을 시작하는 기준을 정한다. 검증: Milestone Task가 Plane 하위 티켓으로 생성되고 plan/code-review 루프로 들어가는 시점이 명확하다.
|
||||
- [x] [cancelled-discard] 사용자가 Plane 상위 티켓을 `Cancelled`로 옮길 때 Milestone 초안 폐기 또는 보류를 처리하는 기준을 정한다. 검증: Plane 폐기 상태가 agent-roadmap의 `[폐기]` 또는 `[보류]` 중 어느 상태로 연결되는지와 사용자 승인 없는 archive 이동 금지가 설명된다.
|
||||
- [x] [child-task-review-policy] Milestone에서 만들어진 하위 작업은 막혔을 때만 `User Review`로 보내고, 정상 PASS 시 기본적으로 `Done`으로 보내는 정책을 정한다. 검증: 하위 작업의 기본 완료 흐름과 blocker review 흐름이 구분된다.
|
||||
- [x] [milestone-review-loop] 모든 하위 작업이 완료되면 상위 Milestone 티켓을 `User Review`로 보내고, 사용자가 `Done`으로 옮기면 완료/archive, `Todo`로 되돌리면 보완 루프로 처리하는 기준을 정한다.
|
||||
- [x] [first-slice] 첫 구현 단위를 `roadmap.validate`, `roadmap.get_position`, `roadmap.ingest_completion_event` 중 어떤 순서로 자를지 정한다.
|
||||
- [ ] [core-state] roadmap, Phase, Milestone, plan, code-review, completion event, approval 상태를 Core가 다루는 state model과 revision/idempotency 계약으로 정리한다.
|
||||
- [ ] [core-actions] validate, position, propose/apply change, transition, archive, dependency check, completion event ingest를 Core action 후보로 정의한다.
|
||||
- [ ] [mcp-tools] 외부 agent용 MCP tool 표면을 Core action wrapper로 정의하고 `dry_run`, `expected_revision`, `idempotency_key`, `actor`, `reason` 입력 원칙을 정한다.
|
||||
- [ ] [http-role] HTTP API는 Flutter UI, webhook, internal integration용 표면으로 유지하고, 외부 agent 제어는 MCP-first로 여는 기준을 정한다.
|
||||
- [ ] [review-gates] 사용자 입력, 출력 검토, `USER_REVIEW.md`, 완료 승인, archive 승인을 NomadCode workflow 안의 review gate로 처리하는 흐름을 정한다.
|
||||
- [ ] [plane-control-flow] Plane을 primary control UI로 쓰는 lifecycle을 정리한다. 검증: `Backlog + AGENT assignee -> Todo -> In Progress -> User Review -> Done/Cancelled` 상태가 Milestone 초안, 사용자 검토, 실행 시작, 사용자 검토, 완료/archive 또는 폐기로 어떻게 연결되는지 문서에서 일관되게 읽힌다.
|
||||
- [ ] [plane-identity] Plane 상위 티켓을 Milestone, 하위 티켓을 Milestone 기능 Task로 매핑하는 id 계약을 정한다. 검증: Milestone id는 파일명으로 유지하고, Plane work item id는 외부 provider id로 보존하는 기준이 명확하다.
|
||||
- [ ] [todo-draft-gate] `Backlog + AGENT assignee`를 Milestone 초안 생성/갱신 trigger로 정의하고, `develop` branch의 agent-roadmap에 반영된 뒤 Plane 티켓을 `Todo`로 이동하는 gate를 정한다. 검증: Todo 진입은 자동 실행이 아니라 `develop`에 존재하는 Milestone의 사용자 검토 단계임이 명확하다.
|
||||
- [ ] [in-progress-exec-gate] 사용자가 Plane 상위 티켓을 `In Progress`로 옮길 때 실제 실행과 하위 티켓 전환을 시작하는 기준을 정한다. 검증: Milestone Task가 Plane 하위 티켓으로 생성되고 plan/code-review 루프로 들어가는 시점이 명확하다.
|
||||
- [ ] [cancelled-discard] 사용자가 Plane 상위 티켓을 `Cancelled`로 옮길 때 Milestone 초안 폐기 또는 보류를 처리하는 기준을 정한다. 검증: Plane 폐기 상태가 agent-roadmap의 `[폐기]` 또는 `[보류]` 중 어느 상태로 연결되는지와 사용자 승인 없는 archive 이동 금지가 설명된다.
|
||||
- [ ] [child-task-review-policy] Milestone에서 만들어진 하위 작업은 막혔을 때만 `User Review`로 보내고, 정상 PASS 시 기본적으로 `Done`으로 보내는 정책을 정한다. 검증: 하위 작업의 기본 완료 흐름과 blocker review 흐름이 구분된다.
|
||||
- [ ] [milestone-review-loop] 모든 하위 작업이 완료되면 상위 Milestone 티켓을 `User Review`로 보내고, 사용자가 `Done`으로 옮기면 완료/archive, `Todo`로 되돌리면 보완 루프로 처리하는 기준을 정한다.
|
||||
- [ ] [skill-adapter] agent-ops roadmap skills가 action owner가 아니라 semantic authoring/proposal layer와 MCP call preparation layer가 되도록 축소 기준을 정한다.
|
||||
- [ ] [first-slice] 첫 구현 단위를 `roadmap.validate`, `roadmap.get_position`, `roadmap.ingest_completion_event` 중 어떤 순서로 자를지 정한다.
|
||||
|
||||
### Epic: [sync-domain] Milestone/work item sync domain
|
||||
|
||||
Plane/Jira 같은 provider work item과 agent-roadmap Milestone item을 동일한 작업 구조로 유지하는 별도 Core sync domain을 정의한다.
|
||||
|
||||
- [x] [sync-owner] sync domain의 소유 책임을 정의한다. 검증: provider adapter는 native API read/write만 담당하고, Milestone/work item identity mapping, revision 비교, 수렴 적용은 Core sync domain 책임으로 읽힌다.
|
||||
- [x] [sync-identity] Milestone, Epic/Task item id, provider work item id, parent-child 관계, provider revision, roadmap revision을 묶는 identity 계약을 정한다. 검증: Plane/Jira 어느 쪽에서 시작해도 같은 Milestone item 구조로 매핑되는 기준이 명확하다.
|
||||
- [x] [sync-project-config] provider project 단위 sync 설정 모델과 저장 경계를 정한다. 검증: provider project target, git remote URL, source-of-truth branch, workspace id/path가 Core DB에 저장되는 project sync 설정으로 정의되고, 설정 누락 또는 중복 시 생성 동기화를 진행하지 않는 기준이 있다.
|
||||
- [x] [sync-detection] provider webhook, provider polling, roadmap file/index scan, agent-task completion event를 같은 변경 감지 입력으로 정리한다. 검증: 양쪽 중 어느 쪽에서 변경이 발생해도 sync event로 정규화되는 흐름이 문서화되어 있다.
|
||||
- [x] [sync-convergence] 한쪽 변경을 다른 쪽에 반영해 Milestone item과 work item이 동일 형태로 수렴하는 apply 정책을 정한다. 검증: 생성, 제목/설명, 상태, parent-child, 완료/검토 흐름이 양방향으로 어떻게 반영되는지 설명된다.
|
||||
- [x] [sync-conflict] 동시 수정, revision mismatch, 삭제/archive, 사용자 승인 필요 변경의 conflict 처리 정책을 정한다. 검증: Core가 조용히 덮어쓰지 않고 review gate 또는 dry-run proposal로 멈추는 기준이 있다.
|
||||
- [x] [sync-schedule] sync domain의 scheduler 책임을 정한다. 검증: webhook이 없는 provider나 누락 이벤트를 주기 polling으로 보정하고, 같은 idempotency/revision 계약을 쓰는 방향이 명확하다.
|
||||
- [x] [sync-contract] `packages/contracts`에 sync event/action 후보를 남긴다. 검증: `roadmap_sync.inspect`, `roadmap_sync.apply`, `roadmap_sync.changed` 같은 후보 표면과 필수 입력 필드가 compatibility note에 정리되어 있다.
|
||||
- [x] [plane-origin-flow] Plane-origin Milestone 생성 시나리오를 정한다. 검증: Backlog 티켓 본문을 입력으로 IOP CLI 1차 통로를 통해 실행된 workspace agent가 같은 Milestone 파일 작성/push 경로에서 roadmap skill로 Milestone 초안을 만들고, `develop` 반영 후 sync layer가 pushed Milestone의 provider/work item identity를 검증한 뒤 원본 본문은 `사용자 요청:` 댓글로 보존하며, Plane 본문은 `develop`의 Milestone 내용으로 치환하고, 제목은 `[milestone-id] 제목` 형식으로 바꾼 뒤 Todo로 이동하는 순서가 문서화되어 있다.
|
||||
- [x] [agent-origin-flow] Agent-origin Milestone 생성 시나리오를 정한다. 검증: 에이전트 대화로 생성된 Milestone이 `develop` branch에 반영되었을 때 Plane parent ticket을 Todo 상태로 생성하고 identity map을 연결하는 흐름이 문서화되어 있다.
|
||||
- [x] [sync-idempotency] Plane-origin과 Agent-origin 생성의 중복 방지와 부분 실패 복구 정책을 정한다. 검증: 같은 Plane 티켓 또는 같은 Milestone path가 재처리되어도 중복 Milestone/티켓을 만들지 않고, 댓글 보존/본문 치환/제목 변경/상태 이동 중 실패한 단계를 재시도할 수 있다.
|
||||
- [ ] [sync-owner] sync domain의 소유 책임을 정의한다. 검증: provider adapter는 native API read/write만 담당하고, Milestone/work item identity mapping, revision 비교, 수렴 적용은 Core sync domain 책임으로 읽힌다.
|
||||
- [ ] [sync-identity] Milestone, Epic/Task item id, provider work item id, parent-child 관계, provider revision, roadmap revision을 묶는 identity 계약을 정한다. 검증: Plane/Jira 어느 쪽에서 시작해도 같은 Milestone item 구조로 매핑되는 기준이 명확하다.
|
||||
- [ ] [sync-project-config] provider project 단위 sync 설정 모델과 저장 경계를 정한다. 검증: provider project target, git remote URL, source-of-truth branch, workspace id/path가 Core DB에 저장되는 project sync 설정으로 정의되고, 설정 누락 또는 중복 시 생성 동기화를 진행하지 않는 기준이 있다.
|
||||
- [ ] [sync-detection] provider webhook, provider polling, roadmap file/index scan, agent-task completion event를 같은 변경 감지 입력으로 정리한다. 검증: 양쪽 중 어느 쪽에서 변경이 발생해도 sync event로 정규화되는 흐름이 문서화되어 있다.
|
||||
- [ ] [sync-convergence] 한쪽 변경을 다른 쪽에 반영해 Milestone item과 work item이 동일 형태로 수렴하는 apply 정책을 정한다. 검증: 생성, 제목/설명, 상태, parent-child, 완료/검토 흐름이 양방향으로 어떻게 반영되는지 설명된다.
|
||||
- [ ] [sync-conflict] 동시 수정, revision mismatch, 삭제/archive, 사용자 승인 필요 변경의 conflict 처리 정책을 정한다. 검증: Core가 조용히 덮어쓰지 않고 review gate 또는 dry-run proposal로 멈추는 기준이 있다.
|
||||
- [ ] [sync-schedule] sync domain의 scheduler 책임을 정한다. 검증: webhook이 없는 provider나 누락 이벤트를 주기 polling으로 보정하고, 같은 idempotency/revision 계약을 쓰는 방향이 명확하다.
|
||||
- [ ] [sync-contract] `packages/contracts`에 sync event/action 후보를 남긴다. 검증: `roadmap_sync.inspect`, `roadmap_sync.apply`, `roadmap_sync.changed` 같은 후보 표면과 필수 입력 필드가 compatibility note에 정리되어 있다.
|
||||
- [ ] [plane-origin-flow] Plane-origin Milestone 생성 시나리오를 정한다. 검증: Backlog 티켓 본문을 입력으로 IOP CLI 1차 통로를 통해 실행된 workspace agent가 같은 Milestone 파일 작성/push 경로에서 roadmap skill로 Milestone 초안을 만들고, `develop` 반영 후 sync layer가 pushed Milestone의 provider/work item identity를 검증한 뒤 원본 본문은 `사용자 요청:` 댓글로 보존하며, Plane 본문은 `develop`의 Milestone 내용으로 치환하고, 제목은 `[milestone-id] 제목` 형식으로 바꾼 뒤 Todo로 이동하는 순서가 문서화되어 있다.
|
||||
- [ ] [agent-origin-flow] Agent-origin Milestone 생성 시나리오를 정한다. 검증: 에이전트 대화로 생성된 Milestone이 `develop` branch에 반영되었을 때 Plane parent ticket을 Todo 상태로 생성하고 identity map을 연결하는 흐름이 문서화되어 있다.
|
||||
- [ ] [sync-idempotency] Plane-origin과 Agent-origin 생성의 중복 방지와 부분 실패 복구 정책을 정한다. 검증: 같은 Plane 티켓 또는 같은 Milestone path가 재처리되어도 중복 Milestone/티켓을 만들지 않고, 댓글 보존/본문 치환/제목 변경/상태 이동 중 실패한 단계를 재시도할 수 있다.
|
||||
|
||||
## 완료 리뷰
|
||||
|
||||
- 상태: 통과
|
||||
- 요청일: 2026-06-23
|
||||
- 완료 근거: Roadmap Operations Control Plane과 Milestone/work item sync domain의 상위 계약 후보가 `packages/contracts/notes/flutter-core-api-candidates.md`에 compatibility note로 정리되었고, 관련 core sync 경계 테스트가 통과했다. 이 문서의 기능 Task가 모두 충족되었고, 구현 잠금은 해제 상태이며 SDD는 불필요로 판정되어 있다.
|
||||
- 상태: 없음
|
||||
- 요청일: 없음
|
||||
- 완료 근거: 없음
|
||||
- 리뷰 필요:
|
||||
- [x] 사용자가 완료 결과를 확인했다
|
||||
- [x] archive 이동을 승인했다
|
||||
- 리뷰 코멘트: 2026-06-23 코드 레벨 종료 검토에서 stale README 표현을 보정했고, 관련 core packages 테스트와 문서 diff 검증이 통과해 archive했다.
|
||||
- [ ] 사용자가 완료 결과를 확인했다
|
||||
- [ ] archive 이동을 승인했다
|
||||
- 리뷰 코멘트: 없음
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- IOP 내부 모델 라우팅, output validation, RAG, context compression 구현
|
||||
- 외부 agent 제어 표면과 tool policy 확정 또는 구현
|
||||
- IOP 내부 모델 라우팅, MCP/tool policy, output validation, RAG, context compression 구현
|
||||
- 전체 Flutter UI 구현
|
||||
- Project sync 설정 관리 UI/UX 실제 구현
|
||||
- Plane/Jira/Mattermost provider projection 세부 구현, Plane webhook/하위 티켓 생성 adapter 실제 구현. 단, Milestone/work item sync domain의 provider-neutral 책임과 계약 후보 정의는 포함한다.
|
||||
|
|
@ -95,20 +97,12 @@ Plane/Jira 같은 provider work item과 agent-roadmap Milestone item을 동일
|
|||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/core/internal/workflow/`, `services/core/internal/scheduler/`, `services/core/internal/http/`, `services/core/internal/workitem/`, `services/core/internal/db/`, `services/core/migrations/`, `services/core/queries/`, `packages/contracts/`, `agent-roadmap/`, `agent-ops/skills/common/update-roadmap/SKILL.md`, `agent-ops/skills/common/plan/SKILL.md`, `agent-ops/skills/common/code-review/SKILL.md`
|
||||
- 표준선(선택): `develop` branch의 `agent-roadmap`을 Milestone sync의 source of truth로 둔다. Plane/Jira 같은 work item provider는 사용자의 primary control UI와 projection 표면이 될 수 있고, provider 상태 변화와 agent-roadmap 변경은 NomadCode Core sync domain이 검증해 실행하는 command로 본다. NomadCode Core는 roadmap/action side effect, Milestone/work item identity mapping, idempotency/revision 검증, conflict review gate를 소유하고, agent-ops 스킬은 사용자의 자연어와 문서 초안을 Core action 제안 입력으로 정리한다.
|
||||
- 표준선(선택): `develop` branch의 `agent-roadmap`을 Milestone sync의 source of truth로 둔다. Plane/Jira 같은 work item provider는 사용자의 primary control UI와 projection 표면이 될 수 있고, provider 상태 변화와 agent-roadmap 변경은 NomadCode Core sync domain이 검증해 실행하는 command로 본다. NomadCode Core는 roadmap/action side effect, Milestone/work item identity mapping, idempotency/revision 검증, conflict review gate를 소유하고, agent-ops 스킬은 사용자의 자연어와 문서 초안을 Core/MCP 호출 입력으로 정리한다.
|
||||
- 프로젝트 설정 기준: Sync는 Plane/Jira provider project 단위로 묶으며, 각 project sync 설정은 provider project target, git remote URL, source-of-truth branch, 실제 작업 workspace를 Core DB에 저장한다. 이 설정은 이후 Project settings UI/UX에서 확인/수정할 수 있어야 한다.
|
||||
- 로컬 제어 표면 후보: `http://127.0.0.1:8080/v1`
|
||||
- 선행 작업: Workflow Core, External Integration, Project Workspace Management UX, 로드맵 스킬 운영 복잡도 평가
|
||||
- 후속 작업: `Milestone Execution Lifecycle Sync`, 외부 agent 제어 표면 스케치
|
||||
- 현재 지점: 이 Phase의 `Milestone Work Item Creation Sync`, `Plane Work Item Webhook Intake`, Gito branch/webhook wakeup 연동은 완료되어 archive에 남아 있다. 이 마일스톤은 roadmap/action core 책임과 Milestone/work item sync domain을 구현 가능한 Core action 후보로 정리하는 상위 설계/계약 문서이며, Milestone/work item sync domain의 후보 계약은 `packages/contracts/notes/flutter-core-api-candidates.md`까지 반영되어 있다.
|
||||
- 완료 체크 근거:
|
||||
- `[plane-control-flow]`, `[plane-identity]`, `[todo-draft-gate]`, `[plane-origin-flow]`: Phase 흐름에 완료로 남은 `Milestone Work Item Creation Sync`와 `Plane Work Item Webhook Intake`가 Plane-origin Milestone 작성, Todo projection, provider identity 보존, Backlog+AGENT webhook intake까지 닫은 근거다.
|
||||
- `[in-progress-exec-gate]`, `[cancelled-discard]`, `[child-task-review-policy]`, `[milestone-review-loop]`: 이 문서의 Plane 제어 플로우가 `Todo -> In Progress -> User Review -> Done/Cancelled` 이후 실행 시작, 하위 티켓 기본 완료/차단 리뷰, 상위 Milestone 완료/보완/폐기 루프를 설명한다.
|
||||
- `[sync-owner]`: 현재 문서의 동기화 도메인 방향이 provider adapter와 Core sync domain 책임을 분리하고, 완료된 Plane/Gito sync slice가 이 경계를 따라 구현되어 있다.
|
||||
- `[sync-project-config]`: project sync 설정 기준이 현재 문서에 남아 있고, Core 내부 경로 `services/core/internal/projectsync/`, `services/core/internal/roadmapsync/`, `services/core/internal/roadmapsyncpipeline/`가 provider project target, repository, workspace 기반 동기화 경계를 구현한다.
|
||||
- `[core-state]`, `[core-actions]`, `[http-role]`, `[review-gates]`, `[first-slice]`: `packages/contracts/notes/flutter-core-api-candidates.md`의 `Roadmap Operations Control Plane 계약 후보`가 roadmap state model, `roadmap.validate/get_position/propose_change/apply_change/transition/archive/dependency_check/ingest_completion_event`, HTTP wrapper 원칙, review gate, 첫 구현 순서를 compatibility note로 정리한다.
|
||||
- `[sync-identity]`, `[sync-detection]`, `[sync-convergence]`, `[sync-conflict]`, `[sync-schedule]`, `[sync-contract]`: `packages/contracts/notes/flutter-core-api-candidates.md`의 `Roadmap / Work Item Sync 계약 후보`가 identity field, `roadmap_sync.changed`, `roadmap_sync.inspect/apply/reconcile`, convergence, conflict, polling 보정 기준을 compatibility note로 정리한다.
|
||||
- `[agent-origin-flow]`, `[sync-idempotency]`: 이 문서의 Agent-origin 생성 플로우와 시나리오 점검, contracts note의 idempotency/revision 원칙이 develop 반영 후 Plane Todo 생성, identity map 연결, 중복 적용 방지, 단계별 재시도 경계를 설명한다.
|
||||
- 후속 작업: `Milestone Work Item Creation Sync`, MCP tool contract 작성
|
||||
- 현재 지점: Agent-Ops MCP Control Plane이 진행중 Phase가 되었고, 실제 구현은 `Milestone Work Item Creation Sync` slice부터 시작한다. 이 마일스톤은 roadmap/action core 책임, Milestone/work item sync domain, MCP-first 제어 표면을 구현 가능한 Core action 후보로 정리하는 상위 설계/계약 문서다.
|
||||
- 실행 경계: 이 마일스톤은 상위 방향과 계약 정리용이다. 실제 구현은 `Milestone Work Item Creation Sync`부터 진행하고, `Milestone Execution Lifecycle Sync`는 사용자가 해제할 때까지 잠근다.
|
||||
- 동기화 도메인 방향:
|
||||
- Sync domain은 provider adapter보다 위에 위치하며, provider native DTO를 직접 소유하지 않는다.
|
||||
|
|
@ -130,7 +124,7 @@ Plane/Jira 같은 provider work item과 agent-roadmap Milestone item을 동일
|
|||
- 하위 티켓: Milestone에서 만들어진 작업은 정상 PASS 시 기본적으로 `Done`으로 이동한다. 작업 중 사용자 결정, 외부 환경, 범위 충돌처럼 자동 진행이 막힐 때만 `User Review`로 이동한다.
|
||||
- `User Review`: 상위 Milestone 티켓은 모든 하위 작업이 완료되었거나 사용자 판단이 필요한 경우 이동한다. 사용자가 `Done`으로 옮기면 `[완료]`와 archive를 수행하고, `Todo`로 되돌리면 내부 Milestone을 `[진행중]`/보완 필요로 되돌려 추가 요구사항을 반영하는 루프로 처리한다.
|
||||
- `Done`: 사용자 최종 완료 승인이다.
|
||||
- `Cancelled`: 기본적으로 폐기 후보 루트이며, 일시 중단으로 해석해야 하는 경우에는 `[보류]` 후보로 사용자 review gate에 올린다. archive 이동은 사용자의 명시 승인 전에는 수행하지 않는다.
|
||||
- `Cancelled`: 폐기 또는 중단 루트다.
|
||||
- Agent-origin 생성 플로우:
|
||||
- 에이전트와의 대화 중 사용자가 Milestone 생성을 요청하면 현재 roadmap 규칙에 따라 프로젝트 안에 Milestone 문서를 만든다.
|
||||
- 생성된 Milestone이 `develop` branch에 반영되면 sync domain은 해당 Milestone을 Plane 상위 티켓으로 생성하고 `Todo` 상태에 둔다.
|
||||
|
|
@ -145,5 +139,12 @@ Plane/Jira 같은 provider work item과 agent-roadmap Milestone item을 동일
|
|||
- Agent-origin sync는 feature branch 초안이 아니라 `develop` branch에 반영된 Milestone만 Plane에 Todo 티켓으로 만든다.
|
||||
- Plane-origin과 Agent-origin 모두 project sync 설정을 통해 provider project, git repository, workspace를 확정하며, 설정이 없거나 둘 이상이면 생성 동기화를 멈추고 사용자 설정 또는 운영자 조치를 요구한다.
|
||||
- Cancelled는 사용자 폐기 신호지만 archive 이동은 사용자 승인 경계를 지켜야 하므로, 우선 `[폐기]` 후보 또는 review gate로 처리한다.
|
||||
- 남은 작업: 없음.
|
||||
- 확인 필요: 없음
|
||||
|
||||
|
||||
## Provider identity
|
||||
- provider: plane
|
||||
- tenant: general
|
||||
- project: a6beb42f-7a8a-410c-b50f-ea3ca94828f3
|
||||
- work item id: 37bcf61f-3dfc-445d-8104-9d2497c5e266
|
||||
- milestone id: roadmap-driven-agent-ops-automation
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
# Phase: Agent-Ops Work Item Lifecycle
|
||||
|
||||
## 상태
|
||||
|
||||
[진행중]
|
||||
|
||||
## 목표
|
||||
|
||||
로드맵 기반 agent-ops 운영 루프에서 Plane/Jira 같은 work item provider의 `Todo` 이후 실행 lifecycle을 Core action 경계로 정리한다. Milestone Task, provider 하위 티켓, `agent-task/m-<milestone-id>` plan/code-review 결과, 사용자 리뷰와 종료 흐름을 연결하되, MCP와 외부 agent 제어 표면은 이 Phase 범위에서 제외한다.
|
||||
|
||||
## Milestone 흐름
|
||||
|
||||
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
|
||||
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||
|
||||
- [완료] 워크스페이스 포트/환경 표준화
|
||||
- 경로: [워크스페이스 포트/환경 표준화](../../archive/phase/agent-ops-mcp-control-plane/milestones/workspace-port-env-standardization.md)
|
||||
- 요약: NomadCode client/core/compose/test runner 포트와 IOP Edge 연동 endpoint를 workspace 공통 대역과 remote runner 문서 기준으로 정리하고, remote code-server preview 정상 노출 확인 후 archive했다.
|
||||
|
||||
- [완료] Milestone Work Item Creation Sync
|
||||
- 경로: [Milestone Work Item Creation Sync](../../archive/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md)
|
||||
- 요약: Plane-origin 방식으로 Milestone을 생성하고 Plane Todo 티켓까지 동기화한 뒤 멈추는 마일스톤이다. 12/13/14번 task group의 `Roadmap Completion` 근거로 live-cycle gate 보완 Task까지 완료했고, 사용자 승인 후 archive했다.
|
||||
|
||||
- [완료] Plane Work Item Webhook Intake
|
||||
- 경로: [Plane Work Item Webhook Intake](../../archive/phase/agent-ops-mcp-control-plane/milestones/plane-work-item-webhook-intake.md)
|
||||
- 요약: Plane work item 생성, 상태 변경, assignee 변경 webhook을 NomadCode Core가 받아 `Backlog + AGENT assignee` 조건을 재검증하고 기존 Milestone creation sync pipeline을 시작하도록 연결했다. 코드 레벨 재검토와 사용자 종료 승인 후 archive했다.
|
||||
|
||||
- [완료] Gito Branch Event Creation Sync Bridge
|
||||
- 경로: [Gito Branch Event Creation Sync Bridge](../../archive/phase/agent-ops-mcp-control-plane/milestones/gito-branch-event-creation-sync-bridge.md)
|
||||
- 요약: Gito `branch.updated` wakeup을 NomadCode core가 소비하고 target branch 재검증/스캔 뒤 creation sync job으로 enqueue하는 bridge를 구현했다. 코드 레벨 종료 검토에서 roadmap milestone path가 없는 event drop을 보강하고 archive했다.
|
||||
|
||||
- [완료] Gito Proto-Socket Consumer Wire Readiness
|
||||
- 경로: [Gito Proto-Socket Consumer Wire Readiness](../../archive/phase/agent-ops-mcp-control-plane/milestones/gito-protosocket-consumer-wire-readiness.md)
|
||||
- 요약: NomadCode/Gito 연동 MVP의 Gito `/proto-socket` binary transport/decode, bridge e2e, failure/reconnect 운영 기준 검증을 완료했고, 사용자 승인 후 archive했다.
|
||||
|
||||
- [완료] Gito HTTP Webhook Consumer Readiness
|
||||
- 경로: [Gito HTTP Webhook Consumer Readiness](../../archive/phase/agent-ops-mcp-control-plane/milestones/gito-http-webhook-consumer-readiness.md)
|
||||
- 요약: Gito `gito.forgejo-branch-events.v1` signed HTTP webhook delivery를 NomadCode Core가 소비하고 branch revision 재검증/creation sync enqueue로 수렴하는 구현을 코드 레벨 종료 감사와 소규모 계약 보강 후 archive했다.
|
||||
|
||||
- [완료] Plane-Origin Authoring Roundtrip Sync
|
||||
- 경로: [Plane-Origin Authoring Roundtrip Sync](../../archive/phase/agent-ops-mcp-control-plane/milestones/plane-origin-authoring-roundtrip-sync.md)
|
||||
- 요약: 최신 dev IOP Responses, workspace slot, Gito HTTP webhook, filename slug canonical id, active Milestone reconcile, Plane 생성/갱신 기준의 기능 Task와 live 검증을 완료했고 코드 레벨 종료 감사 후 archive했다.
|
||||
|
||||
- [완료] Roadmap Driven Agent-Ops Automation
|
||||
- 경로: [Roadmap Driven Agent-Ops Automation](../../archive/phase/agent-ops-mcp-control-plane/milestones/roadmap-driven-agent-ops-automation.md)
|
||||
- 요약: roadmap/action core와 Plane/Jira 기반 Milestone item 동기화의 상위 방향과 계약 후보를 정리했고, 코드 레벨 종료 검토 후 archive했다.
|
||||
|
||||
- [완료] Agent-Origin Milestone Creation Sync
|
||||
- 경로: [Agent-Origin Milestone Creation Sync](../../archive/phase/agent-ops-mcp-control-plane/milestones/agent-origin-milestone-creation-sync.md)
|
||||
- 요약: agent 또는 사람이 active Milestone을 직접 수정해 `develop`에 push한 경우 Gito revision 검증 후 Plane work item 생성/갱신, provider identity ledger 기록, identity backfill commit/push, self-loop guard까지 닫고 코드 레벨 종료 감사 후 archive했다.
|
||||
|
||||
- [계획] Milestone Execution Lifecycle Sync
|
||||
- 경로: [Milestone Execution Lifecycle Sync](milestones/milestone-execution-lifecycle-sync.md)
|
||||
- 요약: Todo 이후 In Progress 실행, 하위 티켓, plan/code-review, 완료/폐기 흐름은 사용자가 명시적으로 해제할 때까지 구현 잠금 상태로 둔다.
|
||||
|
||||
## Phase 경계
|
||||
|
||||
- 이 Phase는 Plane/Jira work item과 agent-roadmap Milestone Task의 실행 lifecycle 동기화만 다룬다.
|
||||
- `Todo -> In Progress` 실행 승인, 하위 티켓 identity, `agent-task/m-<milestone-id>` plan/code-review 결과 반영, 사용자 리뷰와 종료 흐름이 이 Phase의 책임이다.
|
||||
- 완료된 선행 Milestone의 archive 파일은 Phase 분리 전 historical path인 [agent-ops-mcp-control-plane milestones archive](../../archive/phase/agent-ops-mcp-control-plane/milestones/)에 보존한다.
|
||||
- MCP, 외부 agent 제어 표면, tool policy, 외부 호출 권한, side effect 승인 경계는 `MCP Control Surface` Phase에서 별도로 다룬다.
|
||||
- 프로젝트/워크스페이스 UX와 provider console composition은 `Project Workspace Management UX` Phase에서 다룬다.
|
||||
- IOP 내부 모델 라우팅, RAG, context compression, output validation은 NomadCode 범위에서 제외한다.
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# Phase: MCP Control Surface
|
||||
|
||||
## 상태
|
||||
|
||||
[스케치]
|
||||
|
||||
## 목표
|
||||
|
||||
외부 agent가 NomadCode Core를 제어하는 표면을 MCP로 둘지 여부를 현재 agent-ops lifecycle 작업과 분리해 나중에 검토한다. 이 Phase는 현재 실행 후보가 아니며, ops lifecycle과 프로젝트 UX가 정리된 뒤 tool policy, 권한, side effect, audit 경계를 독립적으로 판단하기 위한 마지막 스케치 후보로 둔다.
|
||||
|
||||
## Milestone 흐름
|
||||
|
||||
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
|
||||
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||
|
||||
- [스케치] MCP Control Surface Sketch
|
||||
- 경로: [MCP Control Surface Sketch](milestones/mcp-control-surface-sketch.md)
|
||||
- 요약: 외부 agent 제어 표면을 MCP로 둘지 여부와 tool policy, 권한, side effect 경계를 현재 ops 작업과 분리해 가장 뒤에서 검토한다.
|
||||
|
||||
## Phase 경계
|
||||
|
||||
- 이 Phase는 MCP 채택 여부와 외부 agent 제어 표면의 책임 경계만 다룬다.
|
||||
- 현재 `Agent-Ops Work Item Lifecycle` Phase의 실행 lifecycle, provider 하위 티켓, plan/code-review 상태 동기화 범위와 섞지 않는다.
|
||||
- MCP server 구현, Core action API 확정, 인증/권한 구현은 스케치 승격 전에는 진행하지 않는다.
|
||||
- MCP, HTTP, CLI/internal command 같은 후보를 비교하고, 채택 시 별도 계획 Milestone으로 자를 수 있을 때만 구현 후보로 승격한다.
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
# Milestone: MCP Control Surface Sketch
|
||||
|
||||
## 위치
|
||||
|
||||
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
|
||||
- Phase: [MCP Control Surface PHASE.md](../PHASE.md)
|
||||
|
||||
## 목표
|
||||
|
||||
외부 agent가 NomadCode Core를 제어하는 표면을 MCP로 둘지 여부를 현재 agent-ops lifecycle 작업과 분리해 나중에 검토할 스케치로 보류한다. 현재 확정된 구현 범위가 아니며, ops lifecycle과 프로젝트 UX가 정리된 뒤 채택 여부와 구현 단위를 판단한다.
|
||||
|
||||
## 상태
|
||||
|
||||
[스케치]
|
||||
|
||||
## 승격 조건
|
||||
|
||||
- [ ] 외부 agent 제어 표면이 실제 제품/운영 흐름에서 필요한 사용 사례를 정리한다.
|
||||
- [ ] MCP, HTTP, CLI/internal command 같은 후보 표면을 비교하고 채택/비채택 결정 기준을 남긴다.
|
||||
- [ ] tool 권한, side effect, dry-run, expected revision, idempotency, actor/audit 경계를 정의한다.
|
||||
- [ ] 구현이 필요하다고 판단될 경우 하나의 계획 Milestone으로 자를 수 있는 후속 slice를 정한다.
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 잠금
|
||||
- SDD: 확인 필요 - 외부 agent 제어 표면은 API/tool 계약, 권한, side effect, audit 경계를 바꿀 수 있으므로 계획 승격 시 SDD 필요 여부를 다시 판단한다.
|
||||
- 결정 필요:
|
||||
- [ ] 외부 agent 제어 표면을 MCP로 채택할지 여부
|
||||
- [ ] 외부 agent가 호출할 수 있는 Core action 범위
|
||||
- [ ] 인증, 권한, audit, side effect 승인 경계
|
||||
|
||||
## 범위
|
||||
|
||||
- 외부 agent 제어 표면 후보 비교
|
||||
- MCP 채택/비채택 기준 정리
|
||||
- tool policy, 권한, side effect, idempotency 질문 정리
|
||||
- Core action 모델이 안정된 뒤 구현 Milestone으로 승격할지 판단
|
||||
|
||||
## 기능
|
||||
|
||||
### Epic: [surface-sketch] External agent control surface sketch
|
||||
|
||||
외부 agent 제어 표면을 확정하지 않고 후보와 승격 조건만 정리한다.
|
||||
|
||||
- [ ] [surface-use-cases] 외부 agent가 Core action을 직접 호출해야 하는 사용 사례와 호출하지 않아도 되는 사용 사례를 구분한다.
|
||||
- [ ] [surface-options] MCP, HTTP, CLI/internal command 후보를 같은 기준으로 비교한다.
|
||||
- [ ] [tool-policy] 권한, actor, audit, side effect 승인, idempotency, revision mismatch 처리 질문을 정리한다.
|
||||
- [ ] [promotion-slice] 채택 시 첫 구현 단위와 선행 조건을 계획 Milestone 후보로 나눈다.
|
||||
|
||||
## 완료 리뷰
|
||||
|
||||
- 상태: 없음
|
||||
- 요청일: 없음
|
||||
- 완료 근거: 없음
|
||||
- 리뷰 필요:
|
||||
- [ ] 사용자가 완료 결과를 확인했다
|
||||
- [ ] archive 이동을 승인했다
|
||||
- 리뷰 코멘트: 없음
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- MCP server 구현
|
||||
- Core action 구현 또는 HTTP API 변경
|
||||
- provider sync 동작 변경
|
||||
- 현재 진행중 ops lifecycle Milestone의 완료 조건 변경
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 이 항목은 현재 [Agent-Ops Work Item Lifecycle PHASE.md](../../agent-ops-work-item-lifecycle/PHASE.md)와 분리한 MCP 관련 내용을 가장 뒤에서 검토하기 위한 스케치다.
|
||||
- 선행 후보: [Milestone Execution Lifecycle Sync](../../agent-ops-work-item-lifecycle/milestones/milestone-execution-lifecycle-sync.md), [Project Workspace Management UX](../../project-workspace-management-ux/milestones/project-workspace-management-ux.md)
|
||||
- 관련 경로 후보: `services/core/internal/http/`, `packages/contracts/`, `agent-roadmap/`
|
||||
- 확인 필요: 외부 agent 제어 표면이 실제로 필요한지, 필요하다면 MCP가 NomadCode의 기본 표면이어야 하는지
|
||||
|
|
@ -14,15 +14,15 @@ Flutter-first 클라이언트 구조 위에서 `apps/client` 모듈, web/mobile
|
|||
완료, 검토중, 진행중, 계획 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||
|
||||
- [완료] Client Integration Standardization
|
||||
- 경로: [Client Integration Standardization](../../archive/phase/project-workspace-management-ux/milestones/client-integration-standardization.md)
|
||||
- 경로: `agent-roadmap/archive/phase/project-workspace-management-ux/milestones/client-integration-standardization.md`
|
||||
- 요약: NomadCode client를 기준으로 `apps/client` 모듈명, Web + Android 우선 bootstrap, proto-socket, Mattermost push host integration, cloning handoff를 표준화했다.
|
||||
|
||||
- [계획] Workbench Provider Slot Composition
|
||||
- 경로: [Workbench Provider Slot Composition](milestones/workbench-provider-slot-composition.md)
|
||||
- 경로: `agent-roadmap/phase/project-workspace-management-ux/milestones/workbench-provider-slot-composition.md`
|
||||
- 요약: 상단 titlebar와 우측 icon rail 기반 workbench를 유지하면서 IOP/OTO 같은 외부 Flutter console을 provider slot으로 등록, 삽입, 제거할 수 있는 구조로 정리한다.
|
||||
|
||||
- [계획] Project Workspace Management UX
|
||||
- 경로: [Project Workspace Management UX](milestones/project-workspace-management-ux.md)
|
||||
- 경로: `agent-roadmap/phase/project-workspace-management-ux/milestones/project-workspace-management-ux.md`
|
||||
- 요약: 프로젝트 단위 제어 UX의 desktop/mobile 역할, parity 기준, IOP/task 결과 표시 기준을 정리하는 계획 후보다.
|
||||
|
||||
## Phase 경계
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
## 위치
|
||||
|
||||
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
|
||||
- Phase: [Project Workspace Management UX PHASE.md](../PHASE.md)
|
||||
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||
- Phase: `agent-roadmap/phase/project-workspace-management-ux/PHASE.md`
|
||||
|
||||
## 목표
|
||||
|
||||
|
|
@ -66,5 +66,13 @@ Flutter-first 앱에서 project/session/workspace 제어 표면과 desktop/mobil
|
|||
- 전환 참고 경로: [Legacy/Retired] `apps/web/` (제거됨)
|
||||
- 선행 작업: Flutter-first Client Consolidation, Client Integration Standardization, External Integration
|
||||
- 후속 작업: 확인 필요
|
||||
- 현재 지점: [Workbench Provider Slot Composition](workbench-provider-slot-composition.md)을 최우선 진행중 마일스톤으로 전환하면서 이 마일스톤은 계획 후보로 내려둔다. `구현 잠금`은 유지되며, 프로젝트 단위 제어 화면의 공통 기능/우선순위, desktop/mobile 역할 경계, IOP/task 결과 UX 투영 기준 결정이 선행되어야 한다.
|
||||
- 현재 지점: Workbench Provider Slot Composition을 최우선 진행중 마일스톤으로 전환하면서 이 마일스톤은 계획 후보로 내려둔다. `구현 잠금`은 유지되며, 프로젝트 단위 제어 화면의 공통 기능/우선순위, desktop/mobile 역할 경계, IOP/task 결과 UX 투영 기준 결정이 선행되어야 한다.
|
||||
- 확인 필요: `구현 잠금`의 결정 필요 항목 참고.
|
||||
|
||||
|
||||
## Provider identity
|
||||
- provider: plane
|
||||
- tenant: general
|
||||
- project: a6beb42f-7a8a-410c-b50f-ea3ca94828f3
|
||||
- work item id: 6276a5b2-ef76-4544-9d39-e68b7df49797
|
||||
- milestone id: project-workspace-management-ux
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
## 위치
|
||||
|
||||
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
|
||||
- Phase: [Project Workspace Management UX PHASE.md](../PHASE.md)
|
||||
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||
- Phase: `agent-roadmap/phase/project-workspace-management-ux/PHASE.md`
|
||||
|
||||
## 목표
|
||||
|
||||
|
|
@ -90,7 +90,15 @@ IOP와 OTO 관리는 webview나 별도 앱이 아니라 각 repository의 embedd
|
|||
- 표준선(선택): 외부 제품 UI는 provider adapter/composition layer에서만 import하고, default build는 외부 제품 package 없이 빌드 가능해야 한다.
|
||||
- 표준선(선택): Agent shell은 공통 package, NomadCode/IOP/OTO는 각각 capability pack으로 조립한다.
|
||||
- 완료 근거(2026-06-07): `[workbench-shell]`은 `apps/client/lib/src/app/nomadcode_workbench_shell.dart`와 `apps/client/test/widget_test.dart`의 right rail, Agent dock, IOP/Workflow section 전환, narrow/wide layout rect 검증으로 확인했다. 검증: `cd apps/client && flutter test` PASS.
|
||||
- 선행 작업: [Client Integration Standardization](../../../archive/phase/project-workspace-management-ux/milestones/client-integration-standardization.md), [Project Workspace Management UX](project-workspace-management-ux.md)
|
||||
- 선행 작업: Client Integration Standardization, Project Workspace Management UX
|
||||
- 선행 확인 대상: `../iop/packages/flutter/iop_console/`, `../oto/packages/flutter/oto_console/`
|
||||
- 후속 작업: 실제 desktop/mobile project workspace 화면 구현, workflow/provider 관리 탭별 세부 content 구현
|
||||
- 확인 필요: 후속 구현 계획에서 app/flavor/package 중 어떤 optional composition 방식을 택할지 확정한다.
|
||||
|
||||
|
||||
## Provider identity
|
||||
- provider: plane
|
||||
- tenant: general
|
||||
- project: a6beb42f-7a8a-410c-b50f-ea3ca94828f3
|
||||
- work item id: dce4fb12-62ad-459a-821b-fdbb0a6dd5a4
|
||||
- milestone id: workbench-provider-slot-composition
|
||||
|
|
|
|||
|
|
@ -1,150 +0,0 @@
|
|||
<!-- task=m-plane-origin-authoring-roundtrip-sync/01_iop_long_run plan=0 tag=AUTHORING_RUNTIME -->
|
||||
|
||||
# Code Review Reference - AUTHORING_RUNTIME
|
||||
|
||||
> **[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 selected SDD decision or selected Milestone `구현 잠금 > 결정 필요` item, fill `사용자 리뷰 요청` with linked 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 (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-20
|
||||
task=m-plane-origin-authoring-roundtrip-sync/01_iop_long_run, plan=0, tag=AUTHORING_RUNTIME
|
||||
|
||||
## Roadmap Targets
|
||||
|
||||
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/plane-origin-authoring-roundtrip-sync.md`
|
||||
- Task ids:
|
||||
- `iop-long-run`: IOP Responses 호출이 10분 이상 걸릴 수 있는 작업을 실패로 조기 확정하지 않도록 timeout, retry, queue timeout, stale 판단 기준을 재정의한다.
|
||||
- Completion mode: check-on-pass
|
||||
|
||||
## Spec Targets
|
||||
|
||||
- SDD: `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md`
|
||||
- Acceptance scenarios:
|
||||
- `S02`: task=`iop-long-run`; evidence=`core config/scheduler test or smoke evidence for long-running timeout/retry/stale metadata behavior`
|
||||
- Completion mode: spec-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-plane-origin-authoring-roundtrip-sync/01_iop_long_run/`로 이동한다.
|
||||
4. PASS이고 task group이 `m-plane-origin-authoring-roundtrip-sync`이면 완료 이벤트 메타데이터를 보고한다. roadmap 수정이나 `update-roadmap` 직접 호출은 하지 않는다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [AUTHORING_RUNTIME-1] Authoring long-run timeout foundation | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [x] `iop-long-run` 기준으로 authoring 작업은 generic `WORKFLOW_TASK_TIMEOUT_SEC`로 조기 `failed` 처리되지 않고, `MODEL_TIMEOUT_SEC`/helper/docs는 10분 이상 실행 가능한 기본선으로 정리한다. 검증: focused Go tests에서 generic timeout은 유지되고 authoring은 관찰 가능한 in-progress/stale metadata를 남긴다.
|
||||
- [x] `services/core/README.md`, `services/core/Makefile`, `services/core/bin/run`, `services/core/docker-compose.yml`의 timeout 설명/기본값이 code default와 충돌하지 않게 갱신한다.
|
||||
- [x] `cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...`와 `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하는지 확인한다.
|
||||
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [ ] PASS이면 active task 디렉터리 `agent-task/m-plane-origin-authoring-roundtrip-sync/01_iop_long_run/`를 `agent-task/archive/YYYY/MM/m-plane-origin-authoring-roundtrip-sync/01_iop_long_run/`로 이동한다.
|
||||
- [ ] PASS이고 task group이 `m-plane-origin-authoring-roundtrip-sync`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-plane-origin-authoring-roundtrip-sync/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [x] WARN/FAIL이면 다음 active plan/review 파일 또는 `USER_REVIEW.md` 필요 여부를 판단한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
없음. 계획에 명시된 모든 파일과 접근 방식을 그대로 따랐다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- **RunTimeout 면제 판별**: `authoring.TaskCheckoutMetadata(task)`로 checkout slot이 있는 Plane-origin 태스크를 식별한다. 이미 `Work` 내부에서 `in_progress` 메타데이터 기록 시 동일 함수를 쓰고 있어 경계가 일관된다.
|
||||
- **MODEL_TIMEOUT_SEC 기본값 900**: plan에서 "최소 900초" 기준을 명시했고, IOP Responses long-run 호출이 10분 이상 걸릴 수 있어 15분(900초)을 기본선으로 설정했다. WORKFLOW_TASK_TIMEOUT_SEC(300)는 generic worker 전용으로 유지한다.
|
||||
- **openai.defaultTimeoutSec 동기화**: config default와 client fallback이 따로 분기되는 것을 막기 위해 동일하게 900으로 맞췄다. `NewClient`는 `cfg.TimeoutSec <= 0`일 때만 fallback을 사용하므로 env override 동작에는 영향 없다.
|
||||
- **회귀 테스트 방식**: `done` 채널을 사용해 모델 응답을 `RunTimeout`(1ms) 이후에 반환한다. authoring 태스크가 timeout 면제를 받지 못하면 `context.DeadlineExceeded`로 실패하므로 회귀를 정확히 감지한다.
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 새 결정이 필요해 보여도 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 이 섹션은 선택된 SDD 결정 또는 선택된 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 차단할 때만 채운다. 외부 환경/secret/서비스 준비, 검증 증거 공백, 반복 실패, 일반 범위 조정은 사용자 리뷰 요청이 아니며 `검증 결과`, `계획 대비 변경 사항`, 또는 code-review의 일반 follow-up plan으로 처리한다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 연결 대상: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- Generic task timeout behavior remains covered and unchanged.
|
||||
- Plane-origin authoring does not get marked failed by generic `RunTimeout`.
|
||||
- Timeout defaults/docs/helpers are internally consistent and secret-free.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
### AUTHORING_RUNTIME-1 중간 검증
|
||||
|
||||
```sh
|
||||
$ cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...
|
||||
ok github.com/nomadcode/nomadcode-core/internal/config 0.002s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/scheduler 2.039s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/openai 0.013s
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
|
||||
```sh
|
||||
$ cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...
|
||||
ok github.com/nomadcode/nomadcode-core/internal/config 0.002s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/scheduler 2.039s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/openai 0.013s
|
||||
```
|
||||
|
||||
```sh
|
||||
$ git diff --check
|
||||
(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?**
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- 종합 판정: FAIL
|
||||
- 차원별 평가:
|
||||
- Correctness: Pass
|
||||
- Completeness: Fail
|
||||
- Test coverage: Fail
|
||||
- API contract: Pass
|
||||
- Code quality: Pass
|
||||
- Plan deviation: Fail
|
||||
- Verification trust: Pass
|
||||
- Spec conformance: Fail
|
||||
- 발견된 문제:
|
||||
- Required: `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md:83`와 `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md:103`의 `S02/iop-long-run`은 timeout, retry, queue 대기/stale 판단 기준과 그 evidence를 요구하지만, 현재 구현은 `services/core/internal/scheduler/jobs.go:69`에서 `authoring_run_state`/`authoring_run_updated_at`을 기록하고 `services/core/internal/scheduler/jobs.go:93`에서 generic `RunTimeout`만 우회한다. `workflow.MetadataKeyAuthoringRunUpdatedAt`의 주석은 configured staleness threshold를 전제로 하지만 실제 config/default/docs/test에는 stale threshold, queue timeout 판단, retry 판단 기준이 닫혀 있지 않다. 이 상태로 PASS하면 `Roadmap Targets`/`Spec Targets`에 의해 `iop-long-run`과 `S02` 완료가 과대 기록된다. 수정: Plane-origin authoring의 queue/in-progress stale threshold와 retry/timeout 판단 기준을 코드 또는 명시적 설정/문서로 닫고, focused tests에서 generic timeout 유지, authoring non-premature failure, stale/queue/retry metadata 판단 evidence를 함께 검증한다.
|
||||
- 다음 단계: FAIL 후속 `PLAN-cloud-G07.md`와 `CODE_REVIEW-cloud-G07.md`를 작성한다.
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
<!-- task=m-plane-origin-authoring-roundtrip-sync/01_iop_long_run plan=1 tag=REVIEW_AUTHORING_RUNTIME -->
|
||||
|
||||
# Code Review Reference - REVIEW_AUTHORING_RUNTIME
|
||||
|
||||
> **[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 selected SDD decision or selected Milestone `구현 잠금 > 결정 필요` item, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Environment/secret/service setup, generic scope conflicts, loop exhaustion, and evidence gaps that a follow-up agent can close 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 only the linked SDD/Milestone lock 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-20
|
||||
task=m-plane-origin-authoring-roundtrip-sync/01_iop_long_run, plan=1, tag=REVIEW_AUTHORING_RUNTIME
|
||||
|
||||
## Roadmap Targets
|
||||
|
||||
- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/plane-origin-authoring-roundtrip-sync.md`
|
||||
- Task ids:
|
||||
- `iop-long-run`: IOP Responses 호출이 10분 이상 걸릴 수 있는 작업을 실패로 조기 확정하지 않도록 timeout, retry, queue timeout, stale 판단 기준을 재정의한다.
|
||||
- Completion mode: check-on-pass
|
||||
|
||||
## Spec Targets
|
||||
|
||||
- SDD: `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md`
|
||||
- Acceptance scenarios:
|
||||
- `S02`: task=`iop-long-run`; evidence=`core config/scheduler test or smoke evidence for long-running timeout/retry/stale metadata behavior`
|
||||
- Completion mode: spec-check-on-pass
|
||||
|
||||
## Archive Evidence Snapshot
|
||||
|
||||
- Current archived plan: `agent-task/m-plane-origin-authoring-roundtrip-sync/01_iop_long_run/plan_cloud_G07_0.log`
|
||||
- Current archived review: `agent-task/m-plane-origin-authoring-roundtrip-sync/01_iop_long_run/code_review_cloud_G07_0.log`
|
||||
- Verdict: FAIL
|
||||
- Required summary:
|
||||
- `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md:83` and `:103` require `S02/iop-long-run` evidence for timeout, retry, queue waiting, and stale behavior. The implemented code only records `authoring_run_state`/`authoring_run_updated_at` and skips generic `RunTimeout`; it does not close configured stale threshold, queue timeout, or retry decision evidence.
|
||||
- Affected files from prior loop:
|
||||
- `services/core/internal/scheduler/jobs.go`
|
||||
- `services/core/internal/scheduler/jobs_test.go`
|
||||
- `services/core/internal/config/config.go`
|
||||
- `services/core/internal/config/config_test.go`
|
||||
- `services/core/internal/adapters/openai/client.go`
|
||||
- `services/core/internal/adapters/openai/client_test.go`
|
||||
- `services/core/README.md`
|
||||
- `services/core/Makefile`
|
||||
- `services/core/bin/run`
|
||||
- `services/core/docker-compose.yml`
|
||||
- Verification evidence:
|
||||
- `cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...` passed in the review checkout.
|
||||
- `git diff --check` passed with no output in the review checkout.
|
||||
- Roadmap/spec carryover:
|
||||
- Keep the same `Roadmap Targets` and `Spec Targets` only if this follow-up closes the full `iop-long-run`/`S02` completion evidence. If implementation intentionally remains a foundation-only slice, remove completion claims and explain why in `범위 결정 근거`; do not PASS with over-broad completion targets.
|
||||
- Narrow reread allowed:
|
||||
- The next implementer may read only the archived files named above if exact prior-loop wording is needed. Do not search `agent-task/archive/**`.
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[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-plane-origin-authoring-roundtrip-sync/01_iop_long_run/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
|
||||
4. PASS이고 task group이 `m-plane-origin-authoring-roundtrip-sync`이면 완료 이벤트 메타데이터를 보고한다. roadmap 수정이나 `update-roadmap` 직접 호출은 하지 않는다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [REVIEW_AUTHORING_RUNTIME-1] Complete S02 timeout/retry/stale policy evidence | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [x] `iop-long-run`/`S02` 완료 주장에 맞게 Plane-origin authoring의 timeout, retry, queue 대기 timeout, stale 판단 기준을 코드 또는 명시적 config/docs로 닫는다. 검증: focused tests에서 generic timeout 유지, authoring non-premature failure, stale/queue/retry metadata 또는 판단 evidence가 함께 확인된다.
|
||||
- [x] `services/core/README.md`와 관련 config/helper/docs가 `MODEL_TIMEOUT_SEC`, `WORKFLOW_TASK_TIMEOUT_SEC`, River retry, authoring stale/queue 기준을 서로 충돌 없이 설명한다.
|
||||
- [x] `cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...`와 `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-plane-origin-authoring-roundtrip-sync/01_iop_long_run/`를 `agent-task/archive/YYYY/MM/m-plane-origin-authoring-roundtrip-sync/01_iop_long_run/`로 이동한다.
|
||||
- [x] PASS이고 task group이 `m-plane-origin-authoring-roundtrip-sync`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-plane-origin-authoring-roundtrip-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가 연결된 SDD/Milestone 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
없음. 계획의 "config/default 상수 또는 helper로 stale threshold를 드러낸다" 방향을 그대로 따랐다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- **`AuthoringStaleAfterSec` config field** (`AUTHORING_STALE_AFTER_SEC`, default 1200초): `MODEL_TIMEOUT_SEC=900`보다 넉넉한 20분으로 설정해 정상 완료된 IOP 호출이 stale로 오탐되지 않게 한다. Makefile/bin/run/docker-compose.yml에 동기화.
|
||||
- **`IsAuthoringStale(observedAt, thresholdSec)` helper** (`scheduler/stale.go`): running 태스크는 `authoring_run_updated_at` parsed 값, queue 대기 태스크는 `task.UpdatedAt`을 넘겨 동일 함수로 판단한다. 실제 stale 조치(알림·재-Enqueue)는 후속 모니터링 컴포넌트 책임이고 이 구현은 관찰 가능성만 제공한다.
|
||||
- **`ParseAuthoringRunUpdatedAt(meta)` helper**: RFC3339 파싱 실패를 zero time으로 처리해 호출자가 nil 체크 없이 `IsAuthoringStale`에 바로 전달할 수 있다.
|
||||
- **retry**: `FailTaskWithMetadata`는 lifecycle에서 `retryable` 메타데이터를 이미 기록하며 authoring 태스크도 동일 경로를 통과한다. 신규 코드 불필요.
|
||||
- **queue wait**: queue 대기 중 `WORKFLOW_TASK_TIMEOUT_SEC`가 적용되지 않음은 이미 `TestWorkAuthoringSkipsGenericRunTimeout`으로 증명됨. `IsAuthoringStale(task.UpdatedAt, ...)` 패턴으로 queue stale도 관찰 가능함을 `TestIsAuthoringStaleAppliesToQueueWait`으로 커버.
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 새 결정이 필요해 보여도 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 이 섹션은 선택된 SDD 결정 또는 선택된 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 차단할 때만 채운다. 외부 환경/secret/서비스 준비, 검증 증거 공백, 반복 실패, 일반 범위 조정은 사용자 리뷰 요청이 아니며 `검증 결과`, `계획 대비 변경 사항`, 또는 code-review의 일반 follow-up plan으로 처리한다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 연결 대상: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `S02/iop-long-run` completion evidence가 timeout, retry, queue waiting, stale 판단을 모두 포함하는지 확인한다.
|
||||
- Generic task timeout behavior remains covered and unchanged.
|
||||
- Plane-origin authoring does not get marked failed by generic `RunTimeout`.
|
||||
- Docs/helper defaults are internally consistent and secret-free.
|
||||
- If the implementation intentionally narrows scope, `Roadmap Targets`/`Spec Targets` are not left overclaiming completion.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
|
||||
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.
|
||||
|
||||
### REVIEW_AUTHORING_RUNTIME-1 중간 검증
|
||||
|
||||
```sh
|
||||
$ cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...
|
||||
ok github.com/nomadcode/nomadcode-core/internal/config 0.005s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/scheduler 2.036s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/openai 0.007s
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
|
||||
```sh
|
||||
$ cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...
|
||||
ok github.com/nomadcode/nomadcode-core/internal/config 0.005s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/scheduler 2.036s
|
||||
ok github.com/nomadcode/nomadcode-core/internal/adapters/openai 0.007s
|
||||
```
|
||||
|
||||
```sh
|
||||
$ git diff --check
|
||||
(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?**
|
||||
|
||||
Sections and their ownership:
|
||||
|
||||
| 섹션 | 소유자 | 설명 |
|
||||
|------|--------|------|
|
||||
| 헤더 주석, 개요(date/task/plan/tag), 리뷰 에이전트 지시 | 스텁 생성 시 고정 | 구현 에이전트가 수정하거나 실행하지 않음 |
|
||||
| Roadmap Targets | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 수정하지 않음; PASS 시 code-review가 `complete.log`의 `Roadmap Completion`으로 복사 |
|
||||
| Spec Targets | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 수정하지 않음; PASS 시 code-review가 `complete.log`의 `Spec Completion`으로 복사 |
|
||||
| Archive Evidence Snapshot | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트의 기본 이전 루프 컨텍스트; 추가 확인이 필요할 때 여기에 명시된 archive 파일만 좁게 읽음 |
|
||||
| 구현 항목별 완료 여부 (항목명) | 스텁 생성 시 고정 | `[ ]` -> `[x]` 체크만 구현 에이전트가 수행 |
|
||||
| 구현 체크리스트 (항목 텍스트/순서) | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 `[ ]` -> `[x]` 체크만 수행; 마지막 체크박스는 저장 전 필수 |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | 구현 에이전트가 채움 | placeholder 텍스트를 실제 내용으로 교체 |
|
||||
| 사용자 리뷰 요청 | 구현 에이전트가 채움 | 선택된 SDD 결정 또는 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 차단할 때만 채움; 환경/secret/서비스/검증 공백/일반 범위 조정은 사용자 리뷰 요청으로 쓰지 않음 |
|
||||
| 리뷰어를 위한 체크포인트 | 스텁 생성 시 고정 | 계획에서 추출한 리뷰 포인트 |
|
||||
| 검증 결과 (섹션 제목 + 명령) | 스텁 생성 시 고정 | 실행 출력만 구현 에이전트가 채움; 명령 변경은 `계획 대비 변경 사항`에 기록 |
|
||||
| 코드리뷰 결과 | 리뷰 에이전트가 append | 스텁에 포함하지 않음 |
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- 종합 판정: PASS
|
||||
- 차원별 평가:
|
||||
- Correctness: Pass
|
||||
- Completeness: Pass
|
||||
- Test coverage: Pass
|
||||
- API contract: Pass
|
||||
- Code quality: Pass
|
||||
- Plan deviation: Pass
|
||||
- Verification trust: Pass
|
||||
- Spec conformance: Pass
|
||||
- 발견된 문제: 없음
|
||||
- 다음 단계: PASS 종결. `complete.log` 작성 후 task directory를 archive로 이동한다.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue