init: agent-ops, agent-roadmap, cursorrules, and project configuration files
This commit is contained in:
parent
e2bc7aa8b6
commit
ecd8a8df37
73 changed files with 6830 additions and 56 deletions
4
.aiexclude
Normal file
4
.aiexclude
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# BEGIN Agent-Ops managed ignore
|
||||||
|
agent-task/archive/**
|
||||||
|
agent-roadmap/archive/**
|
||||||
|
# END Agent-Ops managed ignore
|
||||||
8
.claude/settings.json
Normal file
8
.claude/settings.json
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
||||||
|
"permissions": {
|
||||||
|
"deny": [
|
||||||
|
"Read(./agent-task/archive/**)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
4
.clineignore
Normal file
4
.clineignore
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# BEGIN Agent-Ops managed ignore
|
||||||
|
agent-task/archive/**
|
||||||
|
agent-roadmap/archive/**
|
||||||
|
# END Agent-Ops managed ignore
|
||||||
44
.clinerules
Normal file
44
.clinerules
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 공통 규칙
|
||||||
|
|
||||||
|
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||||
|
|
||||||
|
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||||
|
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||||
|
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||||
|
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||||
|
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||||
|
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다. 예외: plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인할 때는 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||||
|
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||||
|
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||||
|
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||||
|
|
||||||
|
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||||
|
|
||||||
|
1. `agent-ops/rules/project/rules.md`
|
||||||
|
2. `agent-ops/rules/private/rules.md`
|
||||||
|
3. `agent-roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||||
|
|
||||||
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
|
|
||||||
|
# 스킬 규칙
|
||||||
|
|
||||||
|
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||||
|
- agent-ops 초기화
|
||||||
|
- domain rule 생성
|
||||||
|
- skill 생성
|
||||||
|
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||||
|
- README 생성
|
||||||
|
- 로드맵/마일스톤 생성·갱신
|
||||||
|
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||||
|
- 계획 작성 / plan 생성
|
||||||
|
- 코드 리뷰 / review 진행
|
||||||
|
- git commit / push
|
||||||
|
- agent-ops 업데이트 / 진입 파일 재적용
|
||||||
|
|
||||||
|
# 테스트 규칙
|
||||||
|
|
||||||
|
**테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.**
|
||||||
|
|
||||||
|
- local: `agent-test/local/rules.md` (없으면 `create-test`)
|
||||||
4
.cursorignore
Normal file
4
.cursorignore
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# BEGIN Agent-Ops managed ignore
|
||||||
|
agent-task/archive/**
|
||||||
|
agent-roadmap/archive/**
|
||||||
|
# END Agent-Ops managed ignore
|
||||||
44
.cursorrules
Normal file
44
.cursorrules
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 공통 규칙
|
||||||
|
|
||||||
|
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||||
|
|
||||||
|
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||||
|
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||||
|
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||||
|
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||||
|
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||||
|
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다. 예외: plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인할 때는 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||||
|
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||||
|
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||||
|
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||||
|
|
||||||
|
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||||
|
|
||||||
|
1. `agent-ops/rules/project/rules.md`
|
||||||
|
2. `agent-ops/rules/private/rules.md`
|
||||||
|
3. `agent-roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||||
|
|
||||||
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
|
|
||||||
|
# 스킬 규칙
|
||||||
|
|
||||||
|
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||||
|
- agent-ops 초기화
|
||||||
|
- domain rule 생성
|
||||||
|
- skill 생성
|
||||||
|
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||||
|
- README 생성
|
||||||
|
- 로드맵/마일스톤 생성·갱신
|
||||||
|
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||||
|
- 계획 작성 / plan 생성
|
||||||
|
- 코드 리뷰 / review 진행
|
||||||
|
- git commit / push
|
||||||
|
- agent-ops 업데이트 / 진입 파일 재적용
|
||||||
|
|
||||||
|
# 테스트 규칙
|
||||||
|
|
||||||
|
**테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.**
|
||||||
|
|
||||||
|
- local: `agent-test/local/rules.md` (없으면 `create-test`)
|
||||||
4
.geminiignore
Normal file
4
.geminiignore
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# BEGIN Agent-Ops managed ignore
|
||||||
|
agent-task/archive/**
|
||||||
|
agent-roadmap/archive/**
|
||||||
|
# END Agent-Ops managed ignore
|
||||||
15
.gitignore
vendored
15
.gitignore
vendored
|
|
@ -17,3 +17,18 @@ build/
|
||||||
.gito/
|
.gito/
|
||||||
tmp/
|
tmp/
|
||||||
|
|
||||||
|
|
||||||
|
# BEGIN Agent-Ops managed gitignore
|
||||||
|
!agent-task/
|
||||||
|
!agent-task/**/
|
||||||
|
!agent-task/**/*.md
|
||||||
|
!agent-task/**/*.log
|
||||||
|
agent-roadmap/current.md
|
||||||
|
# END Agent-Ops managed gitignore
|
||||||
|
|
||||||
|
# Agent-Ops Private Rules
|
||||||
|
agent-ops/rules/private/
|
||||||
|
|
||||||
|
# Agent-Test Local Environment
|
||||||
|
agent-test/local/
|
||||||
|
agent-test/runs/
|
||||||
|
|
|
||||||
56
AGENTS.md
56
AGENTS.md
|
|
@ -1,34 +1,44 @@
|
||||||
# Gito Agent Instructions
|
# 공통 규칙
|
||||||
|
|
||||||
Read this file before making changes in this repository.
|
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||||
|
|
||||||
## Common Rules
|
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||||
|
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||||
|
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||||
|
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||||
|
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||||
|
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다. 예외: plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인할 때는 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||||
|
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||||
|
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||||
|
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||||
|
|
||||||
- Prefer the existing structure over creating new top-level patterns.
|
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||||
- Keep user-facing final answers in Korean unless the user asks otherwise.
|
|
||||||
- Check the relevant domain rule before code changes.
|
|
||||||
- Do not expand scope beyond the current request.
|
|
||||||
- Do not write secrets, tokens, passwords, private endpoints, or raw credentials to tracked files.
|
|
||||||
- Use `rg` or `rg --files` for searches when available.
|
|
||||||
- Use root helpers under `bin/` before ad hoc commands when they cover the task.
|
|
||||||
|
|
||||||
## Required First Reads
|
|
||||||
|
|
||||||
Read these files once per session when they exist:
|
|
||||||
|
|
||||||
1. `agent-ops/rules/project/rules.md`
|
1. `agent-ops/rules/project/rules.md`
|
||||||
2. `agent-ops/rules/private/rules.md`
|
2. `agent-ops/rules/private/rules.md`
|
||||||
|
3. `agent-roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||||
|
|
||||||
## Domain Rules
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
| Path | Domain | Rules |
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
| --- | --- | --- |
|
|
||||||
| `services/core/**` | core | `agent-ops/rules/project/domain/core/rules.md` |
|
|
||||||
| `apps/client/**` | client | `agent-ops/rules/project/domain/client/rules.md` |
|
|
||||||
| `packages/contracts/**` | contracts | `agent-ops/rules/project/domain/contracts/rules.md` |
|
|
||||||
| `bin/**`, `docs/**`, `AGENTS.md`, `README.md`, `agent-ops/**`, `agent-test/**` | workspace-ops | `agent-ops/rules/project/domain/workspace-ops/rules.md` |
|
|
||||||
|
|
||||||
## Test Rules
|
# 스킬 규칙
|
||||||
|
|
||||||
When validation is part of the task, read `agent-test/local/rules.md` first.
|
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||||
|
- agent-ops 초기화
|
||||||
|
- domain rule 생성
|
||||||
|
- skill 생성
|
||||||
|
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||||
|
- README 생성
|
||||||
|
- 로드맵/마일스톤 생성·갱신
|
||||||
|
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||||
|
- 계획 작성 / plan 생성
|
||||||
|
- 코드 리뷰 / review 진행
|
||||||
|
- git commit / push
|
||||||
|
- agent-ops 업데이트 / 진입 파일 재적용
|
||||||
|
|
||||||
|
# 테스트 규칙
|
||||||
|
|
||||||
|
**테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.**
|
||||||
|
|
||||||
|
- local: `agent-test/local/rules.md` (없으면 `create-test`)
|
||||||
|
|
|
||||||
44
CLAUDE.md
Normal file
44
CLAUDE.md
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 공통 규칙
|
||||||
|
|
||||||
|
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||||
|
|
||||||
|
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||||
|
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||||
|
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||||
|
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||||
|
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||||
|
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다. 예외: plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인할 때는 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||||
|
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||||
|
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||||
|
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||||
|
|
||||||
|
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||||
|
|
||||||
|
1. `agent-ops/rules/project/rules.md`
|
||||||
|
2. `agent-ops/rules/private/rules.md`
|
||||||
|
3. `agent-roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||||
|
|
||||||
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
|
|
||||||
|
# 스킬 규칙
|
||||||
|
|
||||||
|
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||||
|
- agent-ops 초기화
|
||||||
|
- domain rule 생성
|
||||||
|
- skill 생성
|
||||||
|
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||||
|
- README 생성
|
||||||
|
- 로드맵/마일스톤 생성·갱신
|
||||||
|
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||||
|
- 계획 작성 / plan 생성
|
||||||
|
- 코드 리뷰 / review 진행
|
||||||
|
- git commit / push
|
||||||
|
- agent-ops 업데이트 / 진입 파일 재적용
|
||||||
|
|
||||||
|
# 테스트 규칙
|
||||||
|
|
||||||
|
**테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.**
|
||||||
|
|
||||||
|
- local: `agent-test/local/rules.md` (없으면 `create-test`)
|
||||||
44
GEMINI.md
Normal file
44
GEMINI.md
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 공통 규칙
|
||||||
|
|
||||||
|
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||||
|
|
||||||
|
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||||
|
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||||
|
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||||
|
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||||
|
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||||
|
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다. 예외: plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인할 때는 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||||
|
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||||
|
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||||
|
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||||
|
|
||||||
|
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||||
|
|
||||||
|
1. `agent-ops/rules/project/rules.md`
|
||||||
|
2. `agent-ops/rules/private/rules.md`
|
||||||
|
3. `agent-roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||||
|
|
||||||
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
|
|
||||||
|
# 스킬 규칙
|
||||||
|
|
||||||
|
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||||
|
- agent-ops 초기화
|
||||||
|
- domain rule 생성
|
||||||
|
- skill 생성
|
||||||
|
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||||
|
- README 생성
|
||||||
|
- 로드맵/마일스톤 생성·갱신
|
||||||
|
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||||
|
- 계획 작성 / plan 생성
|
||||||
|
- 코드 리뷰 / review 진행
|
||||||
|
- git commit / push
|
||||||
|
- agent-ops 업데이트 / 진입 파일 재적용
|
||||||
|
|
||||||
|
# 테스트 규칙
|
||||||
|
|
||||||
|
**테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.**
|
||||||
|
|
||||||
|
- local: `agent-test/local/rules.md` (없으면 `create-test`)
|
||||||
178
README.md
178
README.md
|
|
@ -1,23 +1,100 @@
|
||||||
# Gito
|
# Gito
|
||||||
|
|
||||||
Gito is a platformless Git control plane for agent-driven development workflows.
|
Gito는 agent-driven development를 위한 platformless Git control plane이다.
|
||||||
|
여러 Git repository를 등록하고, workspace lease, Git operation, agent-shell,
|
||||||
|
IOP 실행, provider adapter, normalized event를 하나의 제어 흐름으로 묶는다.
|
||||||
|
|
||||||
It manages registered repositories, workspace leases, Git operations, agent-shell
|
Git 자체 작업은 GitHub/GitLab/Gitea 같은 플랫폼을 몰라도 동작해야 한다.
|
||||||
execution, provider adapters, and normalized events. Git itself stays
|
PR/MR, review, checks, webhook 같은 플랫폼 기능은 provider adapter 뒤에 둔다.
|
||||||
platform-neutral; GitHub, GitLab, Gitea, Plane, Jira, and similar systems are
|
|
||||||
integrated through adapters.
|
|
||||||
|
|
||||||
## Direction
|
## 현재 상태
|
||||||
|
|
||||||
- Server: Go
|
초기 scaffold 단계다. Go core는 build/test 가능한 최소 골격을 갖고 있고,
|
||||||
- Control surface: Flutter app and `gitoctl` in future slices
|
Flutter client는 control surface 경계만 잡혀 있다.
|
||||||
- State: PostgreSQL as source of truth
|
|
||||||
- Event acceleration: Redis optional, not required for the first slice
|
|
||||||
- Internal transport: proto-socket first
|
|
||||||
- REST: health/readiness, smoke/curl, provider callbacks, simple admin bootstrap
|
|
||||||
- gRPC: intentionally excluded from the initial design
|
|
||||||
|
|
||||||
## Runtime Shape
|
현재 가능한 범위:
|
||||||
|
|
||||||
|
- Go `server`, `worker`, `shell` command build
|
||||||
|
- health/readiness REST placeholder
|
||||||
|
- platformless `gitengine` 최소 테스트
|
||||||
|
- core domain DTO 후보
|
||||||
|
- provider-neutral `ChangeRequest` adapter 경계
|
||||||
|
- Postgres migration 초기안
|
||||||
|
- `agent-ops` 규칙/스킬 기반 작업 진입점
|
||||||
|
|
||||||
|
아직 구현 전인 범위:
|
||||||
|
|
||||||
|
- 실제 proto-socket channel/action
|
||||||
|
- 실제 PostgreSQL store wiring
|
||||||
|
- agent-shell outbound 연결과 command streaming
|
||||||
|
- IOP CLI 실행 orchestration
|
||||||
|
- GitHub/GitLab/Gitea provider adapter
|
||||||
|
- Flutter 화면 구성과 operation event 구독
|
||||||
|
|
||||||
|
## 빠른 시작
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bin/test
|
||||||
|
bin/lint
|
||||||
|
bin/build
|
||||||
|
```
|
||||||
|
|
||||||
|
빌드가 끝나면 root `bin/` 아래에 아래 실행 파일이 생성된다.
|
||||||
|
|
||||||
|
```text
|
||||||
|
bin/gito-server
|
||||||
|
bin/gito-worker
|
||||||
|
bin/gito-shell
|
||||||
|
```
|
||||||
|
|
||||||
|
서버 scaffold 실행:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
HTTP_ADDR=:8080 bin/gito-server
|
||||||
|
```
|
||||||
|
|
||||||
|
확인:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl http://127.0.0.1:8080/healthz
|
||||||
|
curl http://127.0.0.1:8080/readyz
|
||||||
|
```
|
||||||
|
|
||||||
|
## 주요 명령
|
||||||
|
|
||||||
|
| 목적 | 명령 | 비고 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 전체 테스트 | `bin/test` | Go test 실행, Flutter test scaffold가 없으면 client test는 skip |
|
||||||
|
| lint | `bin/lint` | `go vet ./...`, Flutter가 있으면 `flutter analyze --no-fatal-infos` |
|
||||||
|
| build | `bin/build` | `gito-server`, `gito-worker`, `gito-shell` 생성 |
|
||||||
|
| Core test | `cd services/core && go test ./...` | Go module 기준 직접 실행 |
|
||||||
|
| Core lint | `cd services/core && go vet ./...` | Go vet 직접 실행 |
|
||||||
|
|
||||||
|
## 구조
|
||||||
|
|
||||||
|
| 경로 | 역할 |
|
||||||
|
| --- | --- |
|
||||||
|
| `services/core/cmd/server/` | control plane server entrypoint |
|
||||||
|
| `services/core/cmd/worker/` | operation worker entrypoint |
|
||||||
|
| `services/core/cmd/shell/` | agent-shell runner entrypoint |
|
||||||
|
| `services/core/internal/controlplane/` | REST/proto-socket surface, auth/policy gate 후보 |
|
||||||
|
| `services/core/internal/core/` | provider-neutral domain model |
|
||||||
|
| `services/core/internal/gitengine/` | platformless Git operation layer |
|
||||||
|
| `services/core/internal/worker/` | operation 실행 orchestration 후보 |
|
||||||
|
| `services/core/internal/agentshell/` | local command/IOP execution boundary |
|
||||||
|
| `services/core/internal/provider/` | GitHub/GitLab/Gitea/Plane/Jira adapter boundary |
|
||||||
|
| `services/core/internal/events/` | normalized event model |
|
||||||
|
| `services/core/internal/storage/` | PostgreSQL store boundary |
|
||||||
|
| `services/core/migrations/` | database schema migration |
|
||||||
|
| `apps/client/` | Flutter control surface scaffold |
|
||||||
|
| `packages/contracts/` | proto-socket, REST, event, DTO contract notes |
|
||||||
|
| `docs/` | 사람용 architecture/operation 문서 |
|
||||||
|
| `agent-ops/` | agent rules, skills, roadmap helper |
|
||||||
|
| `agent-test/` | local validation rules |
|
||||||
|
|
||||||
|
## 설계 방향
|
||||||
|
|
||||||
|
Gito는 처음에는 modular monolith로 시작하되, 실행 역할은 분리 가능하게 둔다.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Flutter UI / gitoctl
|
Flutter UI / gitoctl
|
||||||
|
|
@ -33,27 +110,62 @@ Agent Shell / IOP / Git Engine
|
||||||
Provider Adapters
|
Provider Adapters
|
||||||
```
|
```
|
||||||
|
|
||||||
## Repository Layout
|
원칙:
|
||||||
|
|
||||||
```text
|
- `controlplane`은 요청, 정책, 관찰, event stream을 소유한다.
|
||||||
apps/client/ Flutter control surface scaffold
|
- `core`는 repo, workspace lease, operation, revision cursor, event 원장을 소유한다.
|
||||||
services/core/ Go control plane, worker, shell commands
|
- `worker`는 operation 실행을 조율한다.
|
||||||
packages/contracts/ proto-socket, REST, event, and provider contract notes
|
- `agentshell`은 실제 workspace command, Git CLI, IOP CLI 실행을 맡는다.
|
||||||
docs/ Architecture and operation notes
|
- `gitengine`은 platformless여야 하며 local bare repo만으로 테스트 가능해야 한다.
|
||||||
bin/ Root test/lint/build helpers
|
- `provider`는 PR/MR/review/checks/webhook 같은 플랫폼 기능만 맡는다.
|
||||||
agent-ops/ Agent operating rules
|
- PostgreSQL은 source of truth이고, Redis는 필요할 때 fanout/stream 가속 계층으로만 둔다.
|
||||||
agent-test/ Local validation rules
|
|
||||||
```
|
|
||||||
|
|
||||||
## First Commands
|
## 통신 정책
|
||||||
|
|
||||||
```sh
|
- 내부 runtime 통신은 proto-socket을 우선한다.
|
||||||
bin/test
|
- REST는 health/readiness, provider callback, smoke/curl, 단순 bootstrap에만 둔다.
|
||||||
bin/lint
|
- gRPC는 초기 설계에서 제외한다.
|
||||||
bin/build
|
- webhook은 빠른 wakeup signal로만 보고, 최종 판정은 Git revision/diff 또는 provider read API로 재검증한다.
|
||||||
```
|
|
||||||
|
|
||||||
The initial Go scaffold is intentionally small but buildable. Flutter platform
|
## 작업 맥락
|
||||||
directories are not generated yet; `apps/client` currently records the control
|
|
||||||
surface boundary and a minimal Dart entry point.
|
|
||||||
|
|
||||||
|
작업을 시작할 때는 먼저 [AGENTS.md](AGENTS.md)를 읽고, 변경 경로에 맞는 domain rule을 확인한다.
|
||||||
|
|
||||||
|
주요 문서:
|
||||||
|
|
||||||
|
- [Project rules](agent-ops/rules/project/rules.md)
|
||||||
|
- [Core domain rules](agent-ops/rules/project/domain/core/rules.md)
|
||||||
|
- [Client domain rules](agent-ops/rules/project/domain/client/rules.md)
|
||||||
|
- [Contracts domain rules](agent-ops/rules/project/domain/contracts/rules.md)
|
||||||
|
- [Workspace ops rules](agent-ops/rules/project/domain/workspace-ops/rules.md)
|
||||||
|
- [Local test rules](agent-test/local/rules.md)
|
||||||
|
- [Architecture](docs/architecture.md)
|
||||||
|
- [Control plane contract candidates](packages/contracts/notes/gito-control-plane.md)
|
||||||
|
|
||||||
|
## 개발 흐름
|
||||||
|
|
||||||
|
1. 변경 전에 관련 domain rule을 읽는다.
|
||||||
|
2. core 변경은 `cd services/core && go test ./...` 또는 `bin/test`로 확인한다.
|
||||||
|
3. contracts 변경은 README/notes의 transport 정책과 맞는지 확인한다.
|
||||||
|
4. client 변경은 Flutter toolchain이 있으면 `flutter analyze --no-fatal-infos`와 `flutter test`를 실행한다.
|
||||||
|
5. 생성된 binary, `.dart_tool/`, local secret 파일은 commit하지 않는다.
|
||||||
|
|
||||||
|
## 환경 변수
|
||||||
|
|
||||||
|
| 이름 | 설명 | 필수 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `APP_ENV` | runtime 환경 이름, 기본값 `local` | 아니오 |
|
||||||
|
| `HTTP_ADDR` | server listen address, 기본값 `:8080` | 아니오 |
|
||||||
|
| `DATABASE_URL` | PostgreSQL connection string | 실제 storage wiring 이후 필요 |
|
||||||
|
| `REDIS_URL` | optional Redis endpoint | 아니오 |
|
||||||
|
| `PROTO_SOCKET_PATH` | proto-socket endpoint path, 기본값 `/proto-socket` | 아니오 |
|
||||||
|
| `WORKER_ENABLED` | worker 실행 여부, 기본값 `true` | 아니오 |
|
||||||
|
| `GITO_SHELL_ID` | agent-shell 식별자, 기본값 `local-shell` | 아니오 |
|
||||||
|
|
||||||
|
Credential 값은 tracked 파일에 쓰지 않는다. 필요한 경우 `credential_ref`나 ignored local secret file로 연결한다.
|
||||||
|
|
||||||
|
## 참고 문서
|
||||||
|
|
||||||
|
- [docs/architecture.md](docs/architecture.md)
|
||||||
|
- [packages/contracts/notes/gito-control-plane.md](packages/contracts/notes/gito-control-plane.md)
|
||||||
|
- [agent-ops/skills/common/create-readme/SKILL.md](agent-ops/skills/common/create-readme/SKILL.md)
|
||||||
|
|
|
||||||
1
agent-ops/.version
Normal file
1
agent-ops/.version
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
1.1.136
|
||||||
268
agent-ops/bin/ai-ignore.sh
Executable file
268
agent-ops/bin/ai-ignore.sh
Executable file
|
|
@ -0,0 +1,268 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Shared AI ignore / permission defaults for init and sync flows.
|
||||||
|
AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN="agent-task/archive/**"
|
||||||
|
AGENT_ROADMAP_ARCHIVE_IGNORE_PATTERN="agent-roadmap/archive/**"
|
||||||
|
AGENT_ROADMAP_CURRENT_LOCAL_PATTERN="agent-roadmap/current.md"
|
||||||
|
AGENT_OPS_AI_IGNORE_BLOCK_BEGIN="# BEGIN Agent-Ops managed ignore"
|
||||||
|
AGENT_OPS_AI_IGNORE_BLOCK_END="# END Agent-Ops managed ignore"
|
||||||
|
AGENT_OPS_GITIGNORE_BLOCK_BEGIN="# BEGIN Agent-Ops managed gitignore"
|
||||||
|
AGENT_OPS_GITIGNORE_BLOCK_END="# END Agent-Ops managed gitignore"
|
||||||
|
AGENT_OPS_AI_IGNORE_FILES=(".geminiignore" ".aiexclude" ".cursorignore" ".clineignore")
|
||||||
|
AGENT_OPS_AI_PERMISSION_FILES=(".claude/settings.json" "opencode.json")
|
||||||
|
AGENT_OPS_AI_SYNC_FILES=(".gitignore" "${AGENT_OPS_AI_IGNORE_FILES[@]}" "${AGENT_OPS_AI_PERMISSION_FILES[@]}")
|
||||||
|
|
||||||
|
agent_ops_ensure_gitignore_task_artifact_block() {
|
||||||
|
local file="$1"
|
||||||
|
local tmp
|
||||||
|
|
||||||
|
touch "$file"
|
||||||
|
if grep -qxF "$AGENT_OPS_GITIGNORE_BLOCK_BEGIN" "$file" \
|
||||||
|
&& grep -qxF "$AGENT_OPS_GITIGNORE_BLOCK_END" "$file"; then
|
||||||
|
tmp="$(mktemp "$file.tmp.XXXXXX")"
|
||||||
|
awk \
|
||||||
|
-v begin="$AGENT_OPS_GITIGNORE_BLOCK_BEGIN" \
|
||||||
|
-v end="$AGENT_OPS_GITIGNORE_BLOCK_END" \
|
||||||
|
-v current="$AGENT_ROADMAP_CURRENT_LOCAL_PATTERN" '
|
||||||
|
$0 == begin {
|
||||||
|
print begin
|
||||||
|
print "!agent-task/"
|
||||||
|
print "!agent-task/**/"
|
||||||
|
print "!agent-task/**/*.md"
|
||||||
|
print "!agent-task/**/*.log"
|
||||||
|
print current
|
||||||
|
print end
|
||||||
|
in_block = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
$0 == end && in_block {
|
||||||
|
in_block = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
!in_block { print }
|
||||||
|
' "$file" > "$tmp"
|
||||||
|
mv "$tmp" "$file"
|
||||||
|
else
|
||||||
|
if [[ -s "$file" ]]; then
|
||||||
|
printf "\n" >> "$file"
|
||||||
|
fi
|
||||||
|
printf "%s\n" "$AGENT_OPS_GITIGNORE_BLOCK_BEGIN" >> "$file"
|
||||||
|
printf "%s\n" "!agent-task/" >> "$file"
|
||||||
|
printf "%s\n" "!agent-task/**/" >> "$file"
|
||||||
|
printf "%s\n" "!agent-task/**/*.md" >> "$file"
|
||||||
|
printf "%s\n" "!agent-task/**/*.log" >> "$file"
|
||||||
|
printf "%s\n" "$AGENT_ROADMAP_CURRENT_LOCAL_PATTERN" >> "$file"
|
||||||
|
printf "%s\n" "$AGENT_OPS_GITIGNORE_BLOCK_END" >> "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
agent_ops_ensure_ai_ignore_block() {
|
||||||
|
local file="$1"
|
||||||
|
local tmp
|
||||||
|
|
||||||
|
touch "$file"
|
||||||
|
if grep -qxF "$AGENT_OPS_AI_IGNORE_BLOCK_BEGIN" "$file" \
|
||||||
|
&& grep -qxF "$AGENT_OPS_AI_IGNORE_BLOCK_END" "$file"; then
|
||||||
|
tmp="$(mktemp "$file.tmp.XXXXXX")"
|
||||||
|
awk \
|
||||||
|
-v begin="$AGENT_OPS_AI_IGNORE_BLOCK_BEGIN" \
|
||||||
|
-v end="$AGENT_OPS_AI_IGNORE_BLOCK_END" \
|
||||||
|
-v task="$AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN" \
|
||||||
|
-v roadmap="$AGENT_ROADMAP_ARCHIVE_IGNORE_PATTERN" '
|
||||||
|
$0 == begin {
|
||||||
|
print begin
|
||||||
|
print task
|
||||||
|
print roadmap
|
||||||
|
print end
|
||||||
|
in_block = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
$0 == end && in_block {
|
||||||
|
in_block = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
!in_block { print }
|
||||||
|
' "$file" > "$tmp"
|
||||||
|
mv "$tmp" "$file"
|
||||||
|
else
|
||||||
|
if [[ -s "$file" ]]; then
|
||||||
|
printf "\n" >> "$file"
|
||||||
|
fi
|
||||||
|
printf "%s\n" "$AGENT_OPS_AI_IGNORE_BLOCK_BEGIN" >> "$file"
|
||||||
|
printf "%s\n" "$AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN" >> "$file"
|
||||||
|
printf "%s\n" "$AGENT_ROADMAP_ARCHIVE_IGNORE_PATTERN" >> "$file"
|
||||||
|
printf "%s\n" "$AGENT_OPS_AI_IGNORE_BLOCK_END" >> "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
agent_ops_merge_json_with_jq() {
|
||||||
|
local file="$1"
|
||||||
|
local filter="$2"
|
||||||
|
local fallback_note="$3"
|
||||||
|
local tmp
|
||||||
|
|
||||||
|
if ! command -v jq >/dev/null 2>&1; then
|
||||||
|
echo "$fallback_note"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
tmp="$(mktemp "$file.tmp.XXXXXX")"
|
||||||
|
if jq "$filter" "$file" > "$tmp"; then
|
||||||
|
mv "$tmp" "$file"
|
||||||
|
else
|
||||||
|
rm -f "$tmp"
|
||||||
|
echo "$fallback_note"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
agent_ops_merge_claude_settings() {
|
||||||
|
local file="$1"
|
||||||
|
local filter='
|
||||||
|
def append_unique($item):
|
||||||
|
if index($item) then . else . + [$item] end;
|
||||||
|
def as_array:
|
||||||
|
if type == "array" then . elif . == null then [] else [.] end;
|
||||||
|
def as_object:
|
||||||
|
if type == "object" then . else {} end;
|
||||||
|
|
||||||
|
.permissions = ((.permissions // {}) | as_object)
|
||||||
|
| .permissions.deny = (
|
||||||
|
(.permissions.deny | as_array)
|
||||||
|
| map(select(. != "Read(./agent-roadmap/archive/**)"))
|
||||||
|
| append_unique("Read(./agent-task/archive/**)")
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
agent_ops_merge_json_with_jq \
|
||||||
|
"$file" \
|
||||||
|
"$filter" \
|
||||||
|
"Note: .claude/settings.json exists; add Read(./agent-task/archive/**) and remove Read(./agent-roadmap/archive/**) manually."
|
||||||
|
}
|
||||||
|
|
||||||
|
agent_ops_claude_settings_complete() {
|
||||||
|
local file="$1"
|
||||||
|
local filter='
|
||||||
|
def as_array:
|
||||||
|
if type == "array" then . elif . == null then [] else [.] end;
|
||||||
|
|
||||||
|
(.permissions.deny | as_array)
|
||||||
|
as $deny
|
||||||
|
| (($deny | index("Read(./agent-task/archive/**)")) != null)
|
||||||
|
and (($deny | index("Read(./agent-roadmap/archive/**)")) == null)
|
||||||
|
'
|
||||||
|
|
||||||
|
if command -v jq >/dev/null 2>&1; then
|
||||||
|
jq -e "$filter" "$file" >/dev/null 2>&1
|
||||||
|
else
|
||||||
|
grep -q "agent-task/archive" "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
agent_ops_merge_opencode_config() {
|
||||||
|
local file="$1"
|
||||||
|
local filter='
|
||||||
|
def append_unique($item):
|
||||||
|
if index($item) then . else . + [$item] end;
|
||||||
|
def as_array:
|
||||||
|
if type == "array" then . elif . == null then [] else [.] end;
|
||||||
|
def as_object:
|
||||||
|
if type == "object" then . else {} end;
|
||||||
|
|
||||||
|
.permission = ((.permission // {}) | as_object)
|
||||||
|
| .permission.read = ((.permission.read // {}) | as_object)
|
||||||
|
| .permission.read["agent-task/archive/**"] = "deny"
|
||||||
|
| del(.permission.read["agent-roadmap/archive/**"])
|
||||||
|
| .permission.glob = ((.permission.glob // {}) | as_object)
|
||||||
|
| .permission.glob["agent-task/archive/**"] = "deny"
|
||||||
|
| del(.permission.glob["agent-roadmap/archive/**"])
|
||||||
|
| .watcher = ((.watcher // {}) | as_object)
|
||||||
|
| .watcher.ignore = (
|
||||||
|
(.watcher.ignore | as_array)
|
||||||
|
| append_unique("agent-task/archive/**")
|
||||||
|
| append_unique("agent-roadmap/archive/**")
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
agent_ops_merge_json_with_jq \
|
||||||
|
"$file" \
|
||||||
|
"$filter" \
|
||||||
|
"Note: opencode.json exists; add agent-task/archive/** read/glob deny, remove agent-roadmap/archive/** read/glob hard deny, and add agent-task/archive/** plus agent-roadmap/archive/** watcher ignore manually."
|
||||||
|
}
|
||||||
|
|
||||||
|
agent_ops_opencode_config_complete() {
|
||||||
|
local file="$1"
|
||||||
|
local filter='
|
||||||
|
def as_array:
|
||||||
|
if type == "array" then . elif . == null then [] else [.] end;
|
||||||
|
|
||||||
|
(.permission.read["agent-task/archive/**"] == "deny")
|
||||||
|
and (.permission.glob["agent-task/archive/**"] == "deny")
|
||||||
|
and (.permission.read["agent-roadmap/archive/**"] != "deny")
|
||||||
|
and (.permission.glob["agent-roadmap/archive/**"] != "deny")
|
||||||
|
and ((.watcher.ignore | as_array) as $ignore | (($ignore | index("agent-task/archive/**")) != null) and (($ignore | index("agent-roadmap/archive/**")) != null))
|
||||||
|
'
|
||||||
|
|
||||||
|
if command -v jq >/dev/null 2>&1; then
|
||||||
|
jq -e "$filter" "$file" >/dev/null 2>&1
|
||||||
|
else
|
||||||
|
grep -q "agent-task/archive" "$file" && grep -q "agent-roadmap/archive" "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_agent_ops_ai_ignore_config() {
|
||||||
|
local target_dir="$1"
|
||||||
|
local ignore_file
|
||||||
|
|
||||||
|
if [[ -f "$target_dir/.agent-ops-source" ]]; then
|
||||||
|
echo " AI ignore 보강 건너뜀: .agent-ops-source repo"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
agent_ops_ensure_gitignore_task_artifact_block "$target_dir/.gitignore"
|
||||||
|
|
||||||
|
for ignore_file in "${AGENT_OPS_AI_IGNORE_FILES[@]}"; do
|
||||||
|
agent_ops_ensure_ai_ignore_block "$target_dir/$ignore_file"
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p "$target_dir/.claude"
|
||||||
|
if [[ ! -f "$target_dir/.claude/settings.json" ]]; then
|
||||||
|
cat > "$target_dir/.claude/settings.json" <<'EOF'
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
||||||
|
"permissions": {
|
||||||
|
"deny": [
|
||||||
|
"Read(./agent-task/archive/**)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
elif ! agent_ops_claude_settings_complete "$target_dir/.claude/settings.json"; then
|
||||||
|
agent_ops_merge_claude_settings "$target_dir/.claude/settings.json"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$target_dir/opencode.json" ]]; then
|
||||||
|
cat > "$target_dir/opencode.json" <<'EOF'
|
||||||
|
{
|
||||||
|
"$schema": "https://opencode.ai/config.json",
|
||||||
|
"permission": {
|
||||||
|
"read": {
|
||||||
|
"agent-task/archive/**": "deny"
|
||||||
|
},
|
||||||
|
"glob": {
|
||||||
|
"agent-task/archive/**": "deny"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"watcher": {
|
||||||
|
"ignore": [
|
||||||
|
"agent-task/archive/**",
|
||||||
|
"agent-roadmap/archive/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
elif ! agent_ops_opencode_config_complete "$target_dir/opencode.json"; then
|
||||||
|
agent_ops_merge_opencode_config "$target_dir/opencode.json"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " AI permission 표준 적용: roadmap archive hard deny 제거"
|
||||||
|
}
|
||||||
28
agent-ops/bin/bump-version.sh
Executable file
28
agent-ops/bin/bump-version.sh
Executable file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# bump-version.sh <version>
|
||||||
|
# patch +1, 999 초과 시 minor 올림. major는 수동 관리.
|
||||||
|
# 결과 버전을 stdout으로 출력.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
YELLOW='\033[1;33m'; RESET='\033[0m'
|
||||||
|
|
||||||
|
VERSION="${1:-}"
|
||||||
|
if [[ -z "$VERSION" ]]; then
|
||||||
|
echo "사용법: $0 <major.minor.patch>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS='.' read -r major minor patch <<< "$VERSION"
|
||||||
|
|
||||||
|
patch=$((patch + 1))
|
||||||
|
if [[ $patch -gt 999 ]]; then
|
||||||
|
patch=0
|
||||||
|
minor=$((minor + 1))
|
||||||
|
fi
|
||||||
|
if [[ $minor -gt 999 ]]; then
|
||||||
|
minor=0
|
||||||
|
echo -e "${YELLOW}⚠ minor 버전이 999를 초과했습니다. major 버전을 수동으로 올려주세요.${RESET}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$major.$minor.$patch"
|
||||||
24
agent-ops/bin/entry-files.sh
Normal file
24
agent-ops/bin/entry-files.sh
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Shared entry-point file list for init/sync scripts.
|
||||||
|
AGENT_OPS_ENTRY_FILES=("GEMINI.md" "CLAUDE.md" "AGENTS.md" ".cursorrules" ".clinerules")
|
||||||
|
|
||||||
|
apply_agent_ops_entry_files() {
|
||||||
|
local rules_md="$1"
|
||||||
|
local target_root="$2"
|
||||||
|
|
||||||
|
if [[ ! -f "$rules_md" ]]; then
|
||||||
|
if [[ -n "${YELLOW:-}" && -n "${RESET:-}" ]]; then
|
||||||
|
echo -e "${YELLOW} rules.md 없음, 진입 파일 재적용 건너뜀${RESET}"
|
||||||
|
else
|
||||||
|
echo " rules.md 없음, 진입 파일 재적용 건너뜀"
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local f
|
||||||
|
for f in "${AGENT_OPS_ENTRY_FILES[@]}"; do
|
||||||
|
cp "$rules_md" "$target_root/$f"
|
||||||
|
echo " 진입 파일 적용: $f"
|
||||||
|
done
|
||||||
|
}
|
||||||
343
agent-ops/bin/init-agent-ops.sh
Executable file
343
agent-ops/bin/init-agent-ops.sh
Executable file
|
|
@ -0,0 +1,343 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# agent-ops/bin/init-agent-ops.sh
|
||||||
|
# 프로젝트에 agent-ops 스캐폴드를 초기화하는 스크립트
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR=$(realpath "$(dirname "$0")")
|
||||||
|
SOURCE_DIR=$(realpath "$SCRIPT_DIR/..")
|
||||||
|
source "$SCRIPT_DIR/entry-files.sh"
|
||||||
|
source "$SCRIPT_DIR/ai-ignore.sh"
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "Usage: $0 <target_directory>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TARGET_DIR=$(realpath "$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"
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_common_agent_ops() {
|
||||||
|
local source_dir="$1"
|
||||||
|
local target_agent_ops_dir="$2"
|
||||||
|
|
||||||
|
mkdir -p "$target_agent_ops_dir/rules"
|
||||||
|
mkdir -p "$target_agent_ops_dir/skills"
|
||||||
|
|
||||||
|
cp "$source_dir/.version" "$target_agent_ops_dir/"
|
||||||
|
rm -rf "$target_agent_ops_dir/bin"
|
||||||
|
rm -rf "$target_agent_ops_dir/rules/common"
|
||||||
|
rm -rf "$target_agent_ops_dir/skills/common"
|
||||||
|
cp -r "$source_dir/bin" "$target_agent_ops_dir/"
|
||||||
|
cp -r "$source_dir/rules/common" "$target_agent_ops_dir/rules/"
|
||||||
|
cp -r "$source_dir/skills/common" "$target_agent_ops_dir/skills/"
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_common_rules_file() {
|
||||||
|
local source_dir="$1"
|
||||||
|
local target_agent_ops_dir="$2"
|
||||||
|
local source_rules="$source_dir/rules/common/rules.md"
|
||||||
|
local target_rules="$target_agent_ops_dir/rules/common/rules.md"
|
||||||
|
|
||||||
|
if [ ! -f "$source_rules" ]; then
|
||||||
|
echo "Error: common rules file not found: $source_rules" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$target_rules")"
|
||||||
|
cp "$source_rules" "$target_rules"
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_gitignore_entry() {
|
||||||
|
local gitignore_file="$1"
|
||||||
|
local entry="$2"
|
||||||
|
|
||||||
|
if ! grep -qxF "$entry" "$gitignore_file"; then
|
||||||
|
printf '%s\n' "$entry" >> "$gitignore_file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
discover_agent_test_domains() {
|
||||||
|
local target_dir="$1"
|
||||||
|
local domain_root="$target_dir/agent-ops/rules/project/domain"
|
||||||
|
local project_rules="$target_dir/agent-ops/rules/project/rules.md"
|
||||||
|
|
||||||
|
if [ -d "$domain_root" ]; then
|
||||||
|
find "$domain_root" -mindepth 2 -maxdepth 2 -name rules.md -print \
|
||||||
|
| while IFS= read -r rule_file; do
|
||||||
|
basename "$(dirname "$rule_file")"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$project_rules" ]; then
|
||||||
|
grep -Eo 'agent-ops/rules/project/domain/[^/`[:space:]]+/rules\.md' "$project_rules" \
|
||||||
|
| awk -F/ '{ print $(NF-1) }'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_agent_test_route() {
|
||||||
|
local rules_file="$1"
|
||||||
|
local route_line="$2"
|
||||||
|
local placeholder="- 현재 등록된 도메인/검증 시나리오별 테스트 문서 없음."
|
||||||
|
local tmp
|
||||||
|
|
||||||
|
if grep -qxF -- "$route_line" "$rules_file"; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
tmp="$(mktemp "$rules_file.tmp.XXXXXX")"
|
||||||
|
if grep -qxF -- "$placeholder" "$rules_file"; then
|
||||||
|
awk -v placeholder="$placeholder" -v route_line="$route_line" '
|
||||||
|
$0 == placeholder { print route_line; next }
|
||||||
|
{ print }
|
||||||
|
' "$rules_file" > "$tmp"
|
||||||
|
else
|
||||||
|
awk -v route_line="$route_line" '
|
||||||
|
BEGIN { added = 0 }
|
||||||
|
{ print }
|
||||||
|
!added && $0 == "## 라우팅" {
|
||||||
|
print ""
|
||||||
|
print route_line
|
||||||
|
added = 1
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!added) {
|
||||||
|
print ""
|
||||||
|
print "## 라우팅"
|
||||||
|
print ""
|
||||||
|
print route_line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$rules_file" > "$tmp"
|
||||||
|
fi
|
||||||
|
mv "$tmp" "$rules_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_agent_test_profile() {
|
||||||
|
local target_dir="$1"
|
||||||
|
local env="$2"
|
||||||
|
local profile="$3"
|
||||||
|
local domain="$4"
|
||||||
|
local verification_type="$5"
|
||||||
|
local scope="$6"
|
||||||
|
local today="$7"
|
||||||
|
local profile_file="$target_dir/agent-test/$env/$profile.md"
|
||||||
|
local rules_file="$target_dir/agent-test/$env/rules.md"
|
||||||
|
local route_line
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$profile_file")"
|
||||||
|
|
||||||
|
if [ ! -f "$profile_file" ]; then
|
||||||
|
cat > "$profile_file" <<EOF
|
||||||
|
---
|
||||||
|
test_env: $env
|
||||||
|
test_profile: $profile
|
||||||
|
domain: $domain
|
||||||
|
verification_type: $verification_type
|
||||||
|
last_rule_updated_at: $today
|
||||||
|
---
|
||||||
|
|
||||||
|
# $profile $env 테스트
|
||||||
|
|
||||||
|
## 읽기 조건
|
||||||
|
|
||||||
|
- $domain 도메인 또는 $scope 검증 기준이 필요한 경우
|
||||||
|
|
||||||
|
## 적용 범위
|
||||||
|
|
||||||
|
- <확인 필요>
|
||||||
|
|
||||||
|
## 분류
|
||||||
|
|
||||||
|
- domain: $domain
|
||||||
|
- verification_type: $verification_type
|
||||||
|
- scope: $scope
|
||||||
|
|
||||||
|
## 환경
|
||||||
|
|
||||||
|
- host:
|
||||||
|
- port:
|
||||||
|
- runtime:
|
||||||
|
- package manager:
|
||||||
|
- docker:
|
||||||
|
- external service:
|
||||||
|
- model endpoint:
|
||||||
|
- credential:
|
||||||
|
|
||||||
|
## 명령
|
||||||
|
|
||||||
|
- setup:
|
||||||
|
- lint:
|
||||||
|
- unit:
|
||||||
|
- smoke:
|
||||||
|
- e2e:
|
||||||
|
- model:
|
||||||
|
- full-cycle:
|
||||||
|
|
||||||
|
## 필수 검증
|
||||||
|
|
||||||
|
- <확인 필요>
|
||||||
|
|
||||||
|
## 보조 검증
|
||||||
|
|
||||||
|
- <확인 필요>
|
||||||
|
|
||||||
|
## 판정 기준
|
||||||
|
|
||||||
|
- <확인 필요>
|
||||||
|
|
||||||
|
## 기준 출력 예시
|
||||||
|
|
||||||
|
\`\`\`text
|
||||||
|
<필요한 경우 기대 출력 예시>
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## 차단 기준
|
||||||
|
|
||||||
|
- <확인 필요>
|
||||||
|
|
||||||
|
## 보고 항목
|
||||||
|
|
||||||
|
- 실행한 명령:
|
||||||
|
- 성공한 검증:
|
||||||
|
- 실패/차단된 검증:
|
||||||
|
- 생략 사유:
|
||||||
|
- 남은 위험:
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 확인되지 않은 host, port, token, endpoint를 추측해 쓰지 않는다.
|
||||||
|
- secret, token, 개인 endpoint 원문은 tracked 파일에 기록하지 않는다.
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
route_line="- $domain / $verification_type / $scope: \`agent-test/$env/$profile.md\`"
|
||||||
|
ensure_agent_test_route "$rules_file" "$route_line"
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_agent_test_local() {
|
||||||
|
local target_dir="$1"
|
||||||
|
local local_rules="$target_dir/agent-test/local/rules.md"
|
||||||
|
local today
|
||||||
|
local domain
|
||||||
|
local created_domain_profile="0"
|
||||||
|
|
||||||
|
today="$(date +%F)"
|
||||||
|
mkdir -p "$(dirname "$local_rules")"
|
||||||
|
mkdir -p "$target_dir/agent-test/runs"
|
||||||
|
|
||||||
|
if [ ! -f "$local_rules" ]; then
|
||||||
|
cat > "$local_rules" <<EOF
|
||||||
|
---
|
||||||
|
test_env: local
|
||||||
|
last_rule_updated_at: $today
|
||||||
|
---
|
||||||
|
|
||||||
|
# local 테스트 규칙
|
||||||
|
|
||||||
|
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||||
|
|
||||||
|
## 공통 규칙
|
||||||
|
|
||||||
|
- local 테스트/검증은 이 파일을 기준으로 판단한다.
|
||||||
|
- 작업 완료 검증은 변경 범위 기준으로 선택한다.
|
||||||
|
- 필수 검증을 실행하지 못하면 차단 사유로 보고한다.
|
||||||
|
- 최종 보고에는 실행 명령, 결과, 생략 사유, 남은 위험을 남긴다.
|
||||||
|
- 환경값, secret, 개인 endpoint는 tracked docs/roadmap에 쓰지 않는다.
|
||||||
|
|
||||||
|
## 기본 환경
|
||||||
|
|
||||||
|
- host:
|
||||||
|
- port:
|
||||||
|
- runtime:
|
||||||
|
- package manager:
|
||||||
|
- docker:
|
||||||
|
- external service:
|
||||||
|
- model endpoint:
|
||||||
|
- credential:
|
||||||
|
|
||||||
|
## 라우팅
|
||||||
|
|
||||||
|
- 현재 등록된 도메인/검증 시나리오별 테스트 문서 없음.
|
||||||
|
|
||||||
|
## 라우팅 규칙
|
||||||
|
|
||||||
|
- 여러 항목이 맞으면 모두 읽는다.
|
||||||
|
- 도메인 매핑이나 domain rule이 있으면 각 도메인의 <domain>-smoke 문서를 기본 baseline으로 둔다.
|
||||||
|
- 도메인이 아직 없을 때만 project-smoke를 fallback baseline으로 둔다.
|
||||||
|
- 도메인/검증 시나리오별 문서는 다른 테스트 문서로 라우팅하지 않는다.
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS= read -r domain; do
|
||||||
|
[ -n "$domain" ] || continue
|
||||||
|
created_domain_profile="1"
|
||||||
|
ensure_agent_test_profile \
|
||||||
|
"$target_dir" \
|
||||||
|
"local" \
|
||||||
|
"$domain-smoke" \
|
||||||
|
"$domain" \
|
||||||
|
"smoke" \
|
||||||
|
"도메인 기본 smoke 검증" \
|
||||||
|
"$today"
|
||||||
|
done < <(discover_agent_test_domains "$target_dir" | sort -u)
|
||||||
|
|
||||||
|
if [ "$created_domain_profile" = "0" ]; then
|
||||||
|
ensure_agent_test_profile \
|
||||||
|
"$target_dir" \
|
||||||
|
"local" \
|
||||||
|
"project-smoke" \
|
||||||
|
"project-wide" \
|
||||||
|
"smoke" \
|
||||||
|
"프로젝트 기본 smoke 검증" \
|
||||||
|
"$today"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Initializing agent-ops in: $TARGET_DIR"
|
||||||
|
echo "Source agent-ops: $SOURCE_DIR"
|
||||||
|
|
||||||
|
# 1. 대상 폴더 생성 (프로젝트 전용 폴더는 내용 복사 없이 폴더만 생성)
|
||||||
|
create_project_agent_ops_dirs "$TARGET_DIR/agent-ops"
|
||||||
|
|
||||||
|
# 2. 공통 요소 복사 (프로젝트 전용 설정은 제외)
|
||||||
|
copy_common_agent_ops "$SOURCE_DIR" "$TARGET_DIR/agent-ops"
|
||||||
|
|
||||||
|
# 3. 에이전트 진입 파일 생성 (common/rules.md 복사)
|
||||||
|
COMMON_RULES="$SOURCE_DIR/rules/common/rules.md"
|
||||||
|
apply_agent_ops_entry_files "$COMMON_RULES" "$TARGET_DIR"
|
||||||
|
ensure_common_rules_file "$SOURCE_DIR" "$TARGET_DIR/agent-ops"
|
||||||
|
|
||||||
|
# 4. AI ignore / permission 설정
|
||||||
|
ensure_agent_ops_ai_ignore_config "$TARGET_DIR"
|
||||||
|
|
||||||
|
# 5. .gitignore 설정
|
||||||
|
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"
|
||||||
|
fi
|
||||||
|
ensure_gitignore_entry "$TOUCH_GITIGNORE" "agent-test/local/"
|
||||||
|
ensure_gitignore_entry "$TOUCH_GITIGNORE" "agent-test/runs/"
|
||||||
|
|
||||||
|
# 6. local 테스트 환경 생성
|
||||||
|
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-test/local rules and baseline test profiles are initialized and ignored by git."
|
||||||
370
agent-ops/bin/roadmap-dependency-checker.sh
Executable file
370
agent-ops/bin/roadmap-dependency-checker.sh
Executable file
|
|
@ -0,0 +1,370 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
AGENT_OPS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
PROJECT_ROOT="$(cd "$AGENT_OPS_DIR/.." && pwd)"
|
||||||
|
WORKSPACE_ROOT="$(cd "$PROJECT_ROOT/.." && pwd)"
|
||||||
|
LOCKS_FILE="${AGENT_ROADMAP_LOCKS_FILE:-$WORKSPACE_ROOT/.agent-roadmap-sync/locks.yaml}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: roadmap-dependency-checker.sh <lock-id> [locks.yaml]
|
||||||
|
roadmap-dependency-checker.sh --find-milestone <identity> [locked|rely-on|both] [locks.yaml]
|
||||||
|
|
||||||
|
Validates locked, rely-on.target, and rely-on.status for <lock-id>.
|
||||||
|
Prints true when every rely-on.status is enable.
|
||||||
|
Prints false when at least one rely-on.status is disable.
|
||||||
|
With --find-milestone, prints matching lock ids as locked:<id> or rely-on:<id>,
|
||||||
|
or none when the milestone identity is not referenced.
|
||||||
|
|
||||||
|
Exit codes:
|
||||||
|
0 all dependencies are enabled
|
||||||
|
1 at least one dependency is still disabled
|
||||||
|
2 configuration, input, or parse error
|
||||||
|
For --find-milestone, exit code 0 means the lookup completed; stdout is either
|
||||||
|
matching entries or none.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
MODE="check"
|
||||||
|
LOCK_ID=""
|
||||||
|
FIND_IDENTITY=""
|
||||||
|
FIND_DIRECTION="both"
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "--find-milestone" ]]; then
|
||||||
|
MODE="find"
|
||||||
|
if [[ $# -lt 2 || $# -gt 4 ]]; then
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
FIND_IDENTITY="$2"
|
||||||
|
if [[ -z "$FIND_IDENTITY" ]]; then
|
||||||
|
echo "error: milestone identity is required" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if [[ $# -ge 3 ]]; then
|
||||||
|
case "$3" in
|
||||||
|
locked|rely-on|both)
|
||||||
|
FIND_DIRECTION="$3"
|
||||||
|
if [[ $# -eq 4 ]]; then
|
||||||
|
LOCKS_FILE="$4"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ $# -eq 3 ]]; then
|
||||||
|
LOCKS_FILE="$3"
|
||||||
|
else
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
elif [[ $# -lt 1 || $# -gt 2 ]]; then
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
else
|
||||||
|
LOCK_ID="$1"
|
||||||
|
if [[ -n "${2:-}" ]]; then
|
||||||
|
LOCKS_FILE="$2"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$MODE" == "check" && -z "$LOCK_ID" ]]; then
|
||||||
|
echo "error: lock id is required" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -r "$LOCKS_FILE" ]]; then
|
||||||
|
echo "error: locks file not readable: $LOCKS_FILE" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$MODE" == "find" ]]; then
|
||||||
|
awk -v identity="$FIND_IDENTITY" -v direction="$FIND_DIRECTION" '
|
||||||
|
function trim(value) {
|
||||||
|
gsub(/\r/, "", value)
|
||||||
|
sub(/^[[:space:]]+/, "", value)
|
||||||
|
sub(/[[:space:]]+$/, "", value)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
function unquote(value) {
|
||||||
|
value = trim(value)
|
||||||
|
sub(/[[:space:]]+#.*$/, "", value)
|
||||||
|
value = trim(value)
|
||||||
|
if (value ~ /^".*"$/ || value ~ /^'\''.*'\''$/) {
|
||||||
|
return substr(value, 2, length(value) - 2)
|
||||||
|
}
|
||||||
|
return trim(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset_entry() {
|
||||||
|
entry_id = ""
|
||||||
|
locked = ""
|
||||||
|
in_rely_on = 0
|
||||||
|
rely_count = 0
|
||||||
|
delete rely_targets
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish_entry( i) {
|
||||||
|
if (entry_id == "") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ((direction == "both" || direction == "locked") && locked == identity) {
|
||||||
|
print "locked:" entry_id
|
||||||
|
found = 1
|
||||||
|
}
|
||||||
|
if (direction == "both" || direction == "rely-on") {
|
||||||
|
for (i = 1; i <= rely_count; i++) {
|
||||||
|
if (rely_targets[i] == identity) {
|
||||||
|
print "rely-on:" entry_id
|
||||||
|
found = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
found = 0
|
||||||
|
reset_entry()
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[[:space:]]*($|#)/ {
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[[:space:]]*-[[:space:]]*id:[[:space:]]*/ {
|
||||||
|
finish_entry()
|
||||||
|
reset_entry()
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*-[[:space:]]*id:[[:space:]]*/, "", value)
|
||||||
|
entry_id = unquote(value)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_id != "" && /^[[:space:]]*locked:[[:space:]]*/ {
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*locked:[[:space:]]*/, "", value)
|
||||||
|
locked = unquote(value)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_id != "" && /^[[:space:]]*rely-on:[[:space:]]*/ {
|
||||||
|
in_rely_on = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_id != "" && in_rely_on && /^[[:space:]]*-[[:space:]]*target:[[:space:]]*/ {
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*-[[:space:]]*target:[[:space:]]*/, "", value)
|
||||||
|
rely_targets[++rely_count] = unquote(value)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_id != "" && in_rely_on && /^[[:space:]]*target:[[:space:]]*/ {
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*target:[[:space:]]*/, "", value)
|
||||||
|
rely_targets[++rely_count] = unquote(value)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
finish_entry()
|
||||||
|
if (!found) {
|
||||||
|
print "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$LOCKS_FILE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
awk -v wanted="$LOCK_ID" '
|
||||||
|
function trim(value) {
|
||||||
|
gsub(/\r/, "", value)
|
||||||
|
sub(/^[[:space:]]+/, "", value)
|
||||||
|
sub(/[[:space:]]+$/, "", value)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
function unquote(value) {
|
||||||
|
value = trim(value)
|
||||||
|
sub(/[[:space:]]+#.*$/, "", value)
|
||||||
|
value = trim(value)
|
||||||
|
if (value ~ /^".*"$/ || value ~ /^'\''.*'\''$/) {
|
||||||
|
return substr(value, 2, length(value) - 2)
|
||||||
|
}
|
||||||
|
return trim(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(message) {
|
||||||
|
error = message
|
||||||
|
printf "error: %s\n", error > "/dev/stderr"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish_dependency() {
|
||||||
|
if (!selected || !in_dependency) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!dependency_has_target) {
|
||||||
|
fail("missing rely-on.target for lock id: " wanted)
|
||||||
|
}
|
||||||
|
if (!dependency_has_status) {
|
||||||
|
fail("missing rely-on.status for lock id: " wanted)
|
||||||
|
}
|
||||||
|
in_dependency = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish_entry() {
|
||||||
|
if (!selected) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
finish_dependency()
|
||||||
|
if (!entry_has_locked) {
|
||||||
|
fail("missing locked for lock id: " wanted)
|
||||||
|
}
|
||||||
|
if (total == 0) {
|
||||||
|
fail("no rely-on.status entries for lock id: " wanted)
|
||||||
|
}
|
||||||
|
selected = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
selected = 0
|
||||||
|
matches = 0
|
||||||
|
total = 0
|
||||||
|
enabled = 0
|
||||||
|
error = ""
|
||||||
|
entry_has_locked = 0
|
||||||
|
in_rely_on = 0
|
||||||
|
in_dependency = 0
|
||||||
|
dependency_has_target = 0
|
||||||
|
dependency_has_status = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[[:space:]]*($|#)/ {
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[[:space:]]*-[[:space:]]*id:[[:space:]]*/ {
|
||||||
|
finish_entry()
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*-[[:space:]]*id:[[:space:]]*/, "", value)
|
||||||
|
id = unquote(value)
|
||||||
|
if (id == wanted) {
|
||||||
|
if (matches > 0) {
|
||||||
|
fail("duplicate lock id: " wanted)
|
||||||
|
}
|
||||||
|
selected = 1
|
||||||
|
matches++
|
||||||
|
total = 0
|
||||||
|
enabled = 0
|
||||||
|
entry_has_locked = 0
|
||||||
|
in_rely_on = 0
|
||||||
|
in_dependency = 0
|
||||||
|
dependency_has_target = 0
|
||||||
|
dependency_has_status = 0
|
||||||
|
}
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
selected && /^[[:space:]]*locked:[[:space:]]*/ {
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*locked:[[:space:]]*/, "", value)
|
||||||
|
locked = unquote(value)
|
||||||
|
if (locked == "") {
|
||||||
|
fail("empty locked for lock id: " wanted)
|
||||||
|
}
|
||||||
|
entry_has_locked = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
selected && /^[[:space:]]*rely-on:[[:space:]]*/ {
|
||||||
|
in_rely_on = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
selected && in_rely_on && /^[[:space:]]*-[[:space:]]*target:[[:space:]]*/ {
|
||||||
|
finish_dependency()
|
||||||
|
in_dependency = 1
|
||||||
|
dependency_has_target = 0
|
||||||
|
dependency_has_status = 0
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*-[[:space:]]*target:[[:space:]]*/, "", value)
|
||||||
|
target = unquote(value)
|
||||||
|
if (target == "") {
|
||||||
|
fail("empty rely-on.target for lock id: " wanted)
|
||||||
|
}
|
||||||
|
dependency_has_target = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
selected && in_rely_on && /^[[:space:]]*target:[[:space:]]*/ {
|
||||||
|
if (!in_dependency) {
|
||||||
|
fail("rely-on.target outside dependency item for lock id: " wanted)
|
||||||
|
}
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*target:[[:space:]]*/, "", value)
|
||||||
|
target = unquote(value)
|
||||||
|
if (target == "") {
|
||||||
|
fail("empty rely-on.target for lock id: " wanted)
|
||||||
|
}
|
||||||
|
dependency_has_target = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
selected && in_rely_on && /^[[:space:]]*status:[[:space:]]*/ {
|
||||||
|
if (!in_dependency) {
|
||||||
|
fail("rely-on.status outside dependency item for lock id: " wanted)
|
||||||
|
}
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*status:[[:space:]]*/, "", value)
|
||||||
|
status = unquote(value)
|
||||||
|
if (status != "enable" && status != "disable") {
|
||||||
|
fail("invalid rely-on.status for " wanted ": " status)
|
||||||
|
}
|
||||||
|
if (dependency_has_status) {
|
||||||
|
fail("duplicate rely-on.status for lock id: " wanted)
|
||||||
|
}
|
||||||
|
dependency_has_status = 1
|
||||||
|
total++
|
||||||
|
if (status == "enable") {
|
||||||
|
enabled++
|
||||||
|
}
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
selected && in_rely_on && /^[[:space:]]*-[[:space:]]*/ {
|
||||||
|
finish_dependency()
|
||||||
|
fail("missing rely-on.target for lock id: " wanted)
|
||||||
|
}
|
||||||
|
|
||||||
|
selected && /^[[:space:]]*status:[[:space:]]*/ {
|
||||||
|
fail("status outside rely-on for lock id: " wanted)
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
if (error != "") {
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
if (matches == 0) {
|
||||||
|
printf "error: lock id not found: %s\n", wanted > "/dev/stderr"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
finish_entry()
|
||||||
|
if (total == enabled) {
|
||||||
|
print "true"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
print "false"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
' "$LOCKS_FILE"
|
||||||
338
agent-ops/bin/sync.sh
Executable file
338
agent-ops/bin/sync.sh
Executable file
|
|
@ -0,0 +1,338 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── 경로 설정 ────────────────────────────────────────────────────────────────
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
AGENT_OPS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
PROJECT_ROOT="$(cd "$AGENT_OPS_DIR/.." && pwd)"
|
||||||
|
|
||||||
|
# ── 색상 ─────────────────────────────────────────────────────────────────────
|
||||||
|
RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; RESET='\033[0m'
|
||||||
|
|
||||||
|
# ── 진입 파일 공통 관리 ──────────────────────────────────────────────────────
|
||||||
|
source "$SCRIPT_DIR/entry-files.sh"
|
||||||
|
source "$SCRIPT_DIR/ai-ignore.sh"
|
||||||
|
|
||||||
|
# ── 대상 경로 해석 (폴더명 / 상대경로 / 절대경로) ────────────────────────────
|
||||||
|
resolve_target() {
|
||||||
|
local input="$1"
|
||||||
|
if [[ "$input" == /* ]]; then
|
||||||
|
[[ -d "$input" ]] && echo "$input" || echo ""
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ "$input" == */* ]]; then
|
||||||
|
local resolved
|
||||||
|
resolved="$(cd "$input" 2>/dev/null && pwd)" || { echo ""; return; }
|
||||||
|
echo "$resolved"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local sibling="$(dirname "$PROJECT_ROOT")/$input"
|
||||||
|
[[ -d "$sibling" ]] && echo "$sibling" || echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── 버전 비교: v1 > v2 이면 0 반환 ───────────────────────────────────────────
|
||||||
|
version_gt() {
|
||||||
|
local v1="$1" v2="$2"
|
||||||
|
[[ "$v1" == "$v2" ]] && return 1
|
||||||
|
[[ "$(printf '%s\n%s' "$v1" "$v2" | sort -V | head -1)" == "$v2" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── 버전 +1 ──────────────────────────────────────────────────────────────────
|
||||||
|
bump_version() {
|
||||||
|
bash "$SCRIPT_DIR/bump-version.sh" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── 폴더 동기화 (삭제된 파일도 반영) ────────────────────────────────────────
|
||||||
|
sync_folder() {
|
||||||
|
local src="$1" dst="$2" exclude="${3:-}"
|
||||||
|
mkdir -p "$dst"
|
||||||
|
# dst에서 src에 없는 항목 제거 (exclude 파일 보존)
|
||||||
|
find "$dst" -mindepth 1 -maxdepth 1 | while IFS= read -r item; do
|
||||||
|
local name
|
||||||
|
name="$(basename "$item")"
|
||||||
|
[[ -n "$exclude" && "$name" == "$exclude" ]] && continue
|
||||||
|
if [[ ! -e "$src/$name" ]]; then
|
||||||
|
rm -rf "$item"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# src에서 dst로 복사 (exclude 파일 제외)
|
||||||
|
find "$src" -mindepth 1 -maxdepth 1 | while IFS= read -r item; do
|
||||||
|
local name
|
||||||
|
name="$(basename "$item")"
|
||||||
|
[[ -n "$exclude" && "$name" == "$exclude" ]] && continue
|
||||||
|
rm -rf "$dst/$name"
|
||||||
|
cp -r "$item" "$dst/"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_common() {
|
||||||
|
local src="$1" dst="$2"
|
||||||
|
sync_folder "$src/rules/common" "$dst/rules/common"
|
||||||
|
sync_folder "$src/skills/common" "$dst/skills/common"
|
||||||
|
sync_folder "$src/bin" "$dst/bin"
|
||||||
|
}
|
||||||
|
|
||||||
|
common_differs() {
|
||||||
|
local src="$1" dst="$2"
|
||||||
|
local path
|
||||||
|
|
||||||
|
for path in "rules/common" "skills/common" "bin"; do
|
||||||
|
if [[ ! -d "$src/$path" || ! -d "$dst/$path" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if ! diff -qr "$src/$path" "$dst/$path" >/dev/null; 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"
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_common_scaffold() {
|
||||||
|
local src="$1" dst="$2"
|
||||||
|
mkdir -p "$dst/rules" "$dst/skills"
|
||||||
|
cp "$src/.version" "$dst/"
|
||||||
|
rm -rf "$dst/bin" "$dst/rules/common" "$dst/skills/common"
|
||||||
|
cp -r "$src/bin" "$dst/"
|
||||||
|
cp -r "$src/rules/common" "$dst/rules/"
|
||||||
|
cp -r "$src/skills/common" "$dst/skills/"
|
||||||
|
create_project_agent_ops_dirs "$dst"
|
||||||
|
}
|
||||||
|
|
||||||
|
discover_agent_ops_targets() {
|
||||||
|
local parent
|
||||||
|
parent="$(dirname "$PROJECT_ROOT")"
|
||||||
|
|
||||||
|
find "$parent" -mindepth 1 -maxdepth 1 -type d | sort | while IFS= read -r candidate; do
|
||||||
|
local resolved
|
||||||
|
resolved="$(cd "$candidate" && pwd)"
|
||||||
|
[[ "$resolved" == "$PROJECT_ROOT" ]] && continue
|
||||||
|
[[ -d "$resolved/agent-ops" ]] || continue
|
||||||
|
echo "$resolved"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
agent_ops_git_paths() {
|
||||||
|
local include_ai_config="${1:-1}"
|
||||||
|
|
||||||
|
printf '%s\n' "agent-ops/.version"
|
||||||
|
printf '%s\n' "agent-ops/bin"
|
||||||
|
printf '%s\n' "agent-ops/rules/common"
|
||||||
|
printf '%s\n' "agent-ops/skills/common"
|
||||||
|
|
||||||
|
local f
|
||||||
|
for f in "${AGENT_OPS_ENTRY_FILES[@]}"; do
|
||||||
|
if [[ -e "$f" ]] || git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
|
||||||
|
printf '%s\n' "$f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ "$include_ai_config" != "1" || -f ".agent-ops-source" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
for f in "${AGENT_OPS_AI_SYNC_FILES[@]}"; do
|
||||||
|
if [[ -e "$f" ]] || git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
|
||||||
|
printf '%s\n' "$f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
commit_and_push_agent_ops_scope() {
|
||||||
|
local repo="$1" message="$2"
|
||||||
|
local include_ai_config="${3:-1}"
|
||||||
|
|
||||||
|
if ! git -C "$repo" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||||
|
echo -e "${RED}Error: git 저장소가 아닙니다: $repo${RESET}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "$repo"
|
||||||
|
mapfile -t paths < <(agent_ops_git_paths "$include_ai_config")
|
||||||
|
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
|
||||||
|
git rm --cached --quiet --ignore-unmatch "$AGENT_ROADMAP_CURRENT_LOCAL_PATTERN"
|
||||||
|
paths+=("$AGENT_ROADMAP_CURRENT_LOCAL_PATTERN")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if git diff --cached --quiet -- "${paths[@]}"; then
|
||||||
|
echo " agent-ops 변경 없음: commit 건너뜀"
|
||||||
|
else
|
||||||
|
git commit -m "$message" -- "${paths[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git push
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_framework_to_target() {
|
||||||
|
local target="$1"
|
||||||
|
local dst_ao="$target/agent-ops"
|
||||||
|
local src_ver
|
||||||
|
src_ver="$(cat "$SRC_AO/.version" 2>/dev/null || echo "0.0.0")"
|
||||||
|
|
||||||
|
echo "▶ $(basename "$PROJECT_ROOT") → $(basename "$target")"
|
||||||
|
|
||||||
|
if ! git -C "$target" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||||
|
echo -e "${RED}Error: git 저장소가 아닙니다: $target${RESET}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "$dst_ao" ]]; then
|
||||||
|
echo " 최초 진행: agent-ops 공통 scaffold 복사"
|
||||||
|
copy_common_scaffold "$SRC_AO" "$dst_ao"
|
||||||
|
apply_agent_ops_entry_files "$SRC_AO/rules/common/rules.md" "$target"
|
||||||
|
echo -e "${YELLOW} init-agent-ops 스킬로 초기화를 진행하세요.${RESET}"
|
||||||
|
else
|
||||||
|
echo " 이후 진행: common/ 동기화"
|
||||||
|
sync_common "$SRC_AO" "$dst_ao"
|
||||||
|
cp "$SRC_AO/.version" "$dst_ao/.version"
|
||||||
|
apply_agent_ops_entry_files "$SRC_AO/rules/common/rules.md" "$target"
|
||||||
|
fi
|
||||||
|
ensure_agent_ops_ai_ignore_config "$target"
|
||||||
|
|
||||||
|
commit_and_push_agent_ops_scope "$target" "sync: agent-ops from $(basename "$PROJECT_ROOT") v$src_ver"
|
||||||
|
echo -e "${GREEN}✓ 완료 → $(basename "$target")${RESET}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── 사용법 ────────────────────────────────────────────────────────────────────
|
||||||
|
usage() {
|
||||||
|
echo "사용법: $0 [--pull] [target]"
|
||||||
|
echo ""
|
||||||
|
echo " (기본) push 동기화"
|
||||||
|
echo " --pull target(공통 원본 repo, 기본 agentic-framework) → 현재 프로젝트 로 pull"
|
||||||
|
echo ""
|
||||||
|
echo " target: 폴더명 (동일 레벨 탐색) | 상대경로 | 절대경로"
|
||||||
|
echo " .agent-ops-source 원본 repo에서 target 생략 시 상위 폴더의 agent-ops 적용 프로젝트 전체 동기화"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
PULL_MODE="0"
|
||||||
|
if [[ "${1:-}" == "--pull" ]]; then
|
||||||
|
PULL_MODE="1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
TARGET_INPUT="${1:-}"
|
||||||
|
|
||||||
|
SRC_AO="$AGENT_OPS_DIR"
|
||||||
|
IS_FRAMEWORK="$([[ -f "$PROJECT_ROOT/.agent-ops-source" ]] && echo "1" || echo "0")"
|
||||||
|
|
||||||
|
# ── pull 모드: .agent-ops-source 원본 repo → 현재 프로젝트 ───────────────────
|
||||||
|
if [[ "$PULL_MODE" == "1" ]]; then
|
||||||
|
if [[ -z "$TARGET_INPUT" ]]; then
|
||||||
|
usage; exit 1
|
||||||
|
fi
|
||||||
|
TARGET="$(resolve_target "$TARGET_INPUT")"
|
||||||
|
if [[ -z "$TARGET" ]]; then
|
||||||
|
echo -e "${RED}Error: 대상을 찾을 수 없습니다: $TARGET_INPUT${RESET}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
DST_AO="$TARGET/agent-ops"
|
||||||
|
|
||||||
|
if [[ "$IS_FRAMEWORK" == "1" ]]; then
|
||||||
|
echo -e "${RED}Error: .agent-ops-source가 있는 공통 원본 repo에서는 --pull을 사용할 수 없습니다.${RESET}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$TARGET/.agent-ops-source" ]]; then
|
||||||
|
echo -e "${RED}Error: target이 공통 원본 repo가 아닙니다 (.agent-ops-source 없음)${RESET}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
SRC_VER="$(cat "$SRC_AO/.version" 2>/dev/null || echo "0.0.0")"
|
||||||
|
DST_VER="$(cat "$DST_AO/.version" 2>/dev/null || echo "0.0.0")"
|
||||||
|
echo "▶ $(basename "$TARGET") → $(basename "$PROJECT_ROOT") (pull)"
|
||||||
|
echo " 현재 버전: $SRC_VER | 원본 버전: $DST_VER"
|
||||||
|
sync_common "$DST_AO" "$SRC_AO"
|
||||||
|
cp "$DST_AO/.version" "$SRC_AO/.version"
|
||||||
|
apply_agent_ops_entry_files "$DST_AO/rules/common/rules.md" "$PROJECT_ROOT"
|
||||||
|
ensure_agent_ops_ai_ignore_config "$PROJECT_ROOT"
|
||||||
|
commit_and_push_agent_ops_scope "$PROJECT_ROOT" "sync: pull from agentic-framework v$DST_VER"
|
||||||
|
echo -e "${GREEN}✓ 완료 (pull v$DST_VER)${RESET}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── .agent-ops-source 원본 repo에서 다른 프로젝트로 ──────────────────────────
|
||||||
|
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 [[ -n "$TARGET_INPUT" ]]; then
|
||||||
|
TARGET="$(resolve_target "$TARGET_INPUT")"
|
||||||
|
if [[ -z "$TARGET" ]]; then
|
||||||
|
echo -e "${RED}Error: 대상을 찾을 수 없습니다: $TARGET_INPUT${RESET}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sync_framework_to_target "$TARGET"
|
||||||
|
else
|
||||||
|
mapfile -t TARGETS < <(discover_agent_ops_targets)
|
||||||
|
if [[ "${#TARGETS[@]}" -eq 0 ]]; then
|
||||||
|
echo -e "${YELLOW}agent-ops가 적용된 sibling 프로젝트가 없습니다.${RESET}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
STATUS=0
|
||||||
|
for TARGET in "${TARGETS[@]}"; do
|
||||||
|
if ! sync_framework_to_target "$TARGET"; then
|
||||||
|
STATUS=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit "$STATUS"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── 일반 프로젝트에서 .agent-ops-source 원본 repo로 (push) ───────────────────
|
||||||
|
if [[ -z "$TARGET_INPUT" ]]; then
|
||||||
|
TARGET_INPUT="agentic-framework"
|
||||||
|
fi
|
||||||
|
|
||||||
|
TARGET="$(resolve_target "$TARGET_INPUT")"
|
||||||
|
if [[ -z "$TARGET" ]]; then
|
||||||
|
echo -e "${RED}Error: 대상을 찾을 수 없습니다: $TARGET_INPUT${RESET}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
DST_AO="$TARGET/agent-ops"
|
||||||
|
|
||||||
|
echo "▶ $(basename "$PROJECT_ROOT") → $(basename "$TARGET")"
|
||||||
|
|
||||||
|
if [[ ! -f "$TARGET/.agent-ops-source" ]]; then
|
||||||
|
echo -e "${RED}Error: target이 공통 원본 repo가 아닙니다 (.agent-ops-source 없음)${RESET}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SRC_VER="$(cat "$SRC_AO/.version" 2>/dev/null || echo "0.0.0")"
|
||||||
|
DST_VER="$(cat "$DST_AO/.version" 2>/dev/null || echo "0.0.0")"
|
||||||
|
echo " 현재 버전: $SRC_VER | 원본 버전: $DST_VER"
|
||||||
|
|
||||||
|
COMMON_CHANGED="1"
|
||||||
|
if ! common_differs "$SRC_AO" "$DST_AO"; then
|
||||||
|
COMMON_CHANGED="0"
|
||||||
|
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" ]]; then
|
||||||
|
echo " 공통 파일 변경 없음: .version 차이는 무시하고 버전 갱신/커밋을 건너뜀"
|
||||||
|
echo -e "${GREEN}✓ 완료 (공통 변경 없음)${RESET}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
NEW_VER="$(bump_version "$SRC_VER")"
|
||||||
|
sync_common "$SRC_AO" "$DST_AO"
|
||||||
|
echo "$NEW_VER" > "$SRC_AO/.version"
|
||||||
|
echo "$NEW_VER" > "$DST_AO/.version"
|
||||||
|
|
||||||
|
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}"
|
||||||
35
agent-ops/rules/common/_templates/domain-rule-template.md
Normal file
35
agent-ops/rules/common/_templates/domain-rule-template.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
domain: <domain-name>
|
||||||
|
last_rule_review_commit: <git rev-parse HEAD before editing this file>
|
||||||
|
last_rule_updated_at: <YYYY-MM-DD>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <domain-name>
|
||||||
|
|
||||||
|
## 목적 / 책임
|
||||||
|
|
||||||
|
<이 도메인이 담당하는 책임을 1~2문장으로>
|
||||||
|
|
||||||
|
## 포함 경로
|
||||||
|
|
||||||
|
- `<path>/` — <이 경로가 이 도메인에 속하는 이유>
|
||||||
|
|
||||||
|
## 제외 경로
|
||||||
|
|
||||||
|
- `<path>/` — <왜 이 도메인이 아닌지>
|
||||||
|
|
||||||
|
## 주요 구성 요소
|
||||||
|
|
||||||
|
- `<ClassName>` — <역할>
|
||||||
|
|
||||||
|
## 유지할 패턴
|
||||||
|
|
||||||
|
- <네이밍 규칙 또는 아키텍처 패턴>
|
||||||
|
|
||||||
|
## 다른 도메인과의 경계
|
||||||
|
|
||||||
|
- **<인접 domain>**: <어디까지가 이 도메인이고 어디서부터 저 도메인인지>
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- <이 도메인 코드에서 하면 안 되는 것>
|
||||||
79
agent-ops/rules/common/_templates/test-case-rule-template.md
Normal file
79
agent-ops/rules/common/_templates/test-case-rule-template.md
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
---
|
||||||
|
test_env: <local|dev|qa|prod>
|
||||||
|
test_profile: <test-profile>
|
||||||
|
domain: <domain|project-wide>
|
||||||
|
verification_type: <smoke|unit|integration|e2e|model|migration|manual|full-cycle>
|
||||||
|
last_rule_updated_at: <YYYY-MM-DD>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <test_profile> <test_env> 테스트
|
||||||
|
|
||||||
|
## 읽기 조건
|
||||||
|
|
||||||
|
- <이 도메인/검증 시나리오의 테스트, 검증, 실행 조건 판단이 필요한 경우>
|
||||||
|
|
||||||
|
## 적용 범위
|
||||||
|
|
||||||
|
- <검증 대상 entrypoint, command, API, UX, profile, service>
|
||||||
|
|
||||||
|
## 분류
|
||||||
|
|
||||||
|
- domain: <domain|project-wide>
|
||||||
|
- verification_type: <smoke|unit|integration|e2e|model|migration|manual|full-cycle>
|
||||||
|
- scope: <검증 대상 변경 범위 요약>
|
||||||
|
|
||||||
|
## 환경
|
||||||
|
|
||||||
|
- host:
|
||||||
|
- port:
|
||||||
|
- runtime:
|
||||||
|
- package manager:
|
||||||
|
- docker:
|
||||||
|
- external service:
|
||||||
|
- model endpoint:
|
||||||
|
- credential:
|
||||||
|
|
||||||
|
## 명령
|
||||||
|
|
||||||
|
- setup:
|
||||||
|
- lint:
|
||||||
|
- unit:
|
||||||
|
- smoke:
|
||||||
|
- e2e:
|
||||||
|
- model:
|
||||||
|
- full-cycle:
|
||||||
|
|
||||||
|
## 필수 검증
|
||||||
|
|
||||||
|
- <작업 완료 전 반드시 실행하거나 판단해야 하는 검증>
|
||||||
|
|
||||||
|
## 보조 검증
|
||||||
|
|
||||||
|
- <실행하면 좋지만 필수 검증을 대체하지 않는 smoke/helper 검증>
|
||||||
|
|
||||||
|
## 판정 기준
|
||||||
|
|
||||||
|
- <통과로 판단할 출력, 상태, UX, artifact, endpoint 조건>
|
||||||
|
|
||||||
|
## 기준 출력 예시
|
||||||
|
|
||||||
|
```text
|
||||||
|
<필요한 경우 기대 출력 예시>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 차단 기준
|
||||||
|
|
||||||
|
- <테스트를 계속할 수 없는 환경/권한/도구/서비스 조건>
|
||||||
|
|
||||||
|
## 보고 항목
|
||||||
|
|
||||||
|
- 실행한 명령:
|
||||||
|
- 성공한 검증:
|
||||||
|
- 실패/차단된 검증:
|
||||||
|
- 생략 사유:
|
||||||
|
- 남은 위험:
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- <이 도메인/검증 시나리오에서 하면 안 되는 것>
|
||||||
|
- secret, token, 개인 endpoint 원문은 tracked 파일에 기록하지 않는다.
|
||||||
38
agent-ops/rules/common/_templates/test-env-rules-template.md
Normal file
38
agent-ops/rules/common/_templates/test-env-rules-template.md
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
test_env: <local|dev|qa|prod>
|
||||||
|
last_rule_updated_at: <YYYY-MM-DD>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <test_env> 테스트 규칙
|
||||||
|
|
||||||
|
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||||
|
|
||||||
|
## 공통 규칙
|
||||||
|
|
||||||
|
- <test_env> 테스트/검증은 이 파일을 기준으로 판단한다.
|
||||||
|
- 작업 완료 검증은 변경 범위 기준으로 선택한다.
|
||||||
|
- 필수 검증을 실행하지 못하면 차단 사유로 보고한다.
|
||||||
|
- 최종 보고에는 실행 명령, 결과, 생략 사유, 남은 위험을 남긴다.
|
||||||
|
- 환경값, secret, 개인 endpoint는 tracked docs/roadmap에 쓰지 않는다.
|
||||||
|
|
||||||
|
## 기본 환경
|
||||||
|
|
||||||
|
- host:
|
||||||
|
- port:
|
||||||
|
- runtime:
|
||||||
|
- package manager:
|
||||||
|
- docker:
|
||||||
|
- external service:
|
||||||
|
- model endpoint:
|
||||||
|
- credential:
|
||||||
|
|
||||||
|
## 라우팅
|
||||||
|
|
||||||
|
- <domain 또는 project-wide> / <verification-type> / <scope 요약>: `agent-test/<test_env>/<test-profile>.md`
|
||||||
|
|
||||||
|
## 라우팅 규칙
|
||||||
|
|
||||||
|
- 여러 항목이 맞으면 모두 읽는다.
|
||||||
|
- 도메인 매핑이나 domain rule이 있으면 각 도메인의 `<domain>-smoke` 문서를 기본 baseline으로 둔다.
|
||||||
|
- 도메인이 아직 없을 때만 `project-smoke`를 fallback baseline으로 둔다.
|
||||||
|
- 도메인/검증 시나리오별 문서는 다른 테스트 문서로 라우팅하지 않는다.
|
||||||
98
agent-ops/rules/common/philosophy.md
Normal file
98
agent-ops/rules/common/philosophy.md
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
# Agent-Ops 철학
|
||||||
|
|
||||||
|
이 문서는 agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 읽는다.
|
||||||
|
일반 구현 작업에서는 읽지 않는다.
|
||||||
|
|
||||||
|
## 핵심
|
||||||
|
|
||||||
|
- agent-ops는 AI agent가 작업하기 위한 규칙이자 가이드다.
|
||||||
|
- 사람 문서처럼 장황하게 설명하지 않고, agent가 바로 실행할 수 있게 작성한다.
|
||||||
|
- 필요한 컨텍스트만 읽게 만든다. 모든 문서를 항상 읽게 만들지 않는다.
|
||||||
|
- 애매한 형식을 만들지 않는다. 경로, 상태, id, 입력, 출력은 판별 가능해야 한다.
|
||||||
|
- 문서는 짧고 단단해야 한다. 길어서 이해되는 문서보다 짧아서 헷갈리지 않는 문서가 낫다.
|
||||||
|
|
||||||
|
## 문서 작성
|
||||||
|
|
||||||
|
- 규칙과 스킬은 핵심만 쓴다.
|
||||||
|
- 같은 말을 여러 문서에 반복하지 않는다. 한 곳에 두고 링크한다.
|
||||||
|
- 설명보다 조건, 입력, 행동, 금지 사항을 우선한다.
|
||||||
|
- "적절히", "필요하면", "가능하면" 같은 말은 판별 기준이 없으면 쓰지 않는다.
|
||||||
|
- 예외가 있으면 예외 조건을 같이 쓴다.
|
||||||
|
- 긴 배경 설명은 README나 별도 참조 문서로 보내고, 실행 문서에는 실행 규칙만 남긴다.
|
||||||
|
- 룰 문서는 협업자가 직접 읽는 계약 문서이므로 한국어 `한다`체로 작성한다.
|
||||||
|
- README, GUIDE, roadmap 문서는 사람이 함께 검토하는 협업 문서이므로 한국어 설명체 또는 존댓말을 사용할 수 있다.
|
||||||
|
- 스킬 문서는 실행 안정성을 우선한다. 한국어 또는 영어를 사용할 수 있고, 이미 잘 동작하는 절차 계약은 언어 통일만을 위해 수정하지 않는다.
|
||||||
|
- path, filename, 상태값, id, regex, command, frontmatter key, runtime protocol token은 원문 ASCII 식별자를 유지한다.
|
||||||
|
|
||||||
|
## 라우팅
|
||||||
|
|
||||||
|
- 라우팅은 얕아야 한다.
|
||||||
|
- 1홉은 진입 파일에서 공통/프로젝트 규칙을 읽는 단계다.
|
||||||
|
- 2홉은 규칙에서 domain rule, roadmap rule, router를 따라가는 단계다.
|
||||||
|
- 3홉은 router에서 SKILL.md를 읽는 단계다.
|
||||||
|
- 4홉은 skill이 템플릿이나 참조 문서를 추가로 읽는 단계다.
|
||||||
|
- 4홉 이상이 필요하면 구조가 과하게 쪼개졌는지 먼저 의심한다. 필요하면 앞 문서에 바로 가는 링크를 추가한다.
|
||||||
|
- 깊은 링크 체인을 만들지 않고, 필요한 문서가 무엇인지 앞 문서에서 바로 보이게 한다.
|
||||||
|
- 일반 작업마다 router, 모든 skill, 전체 roadmap, archive를 읽게 만들지 않는다.
|
||||||
|
|
||||||
|
## LLM과 런타임
|
||||||
|
|
||||||
|
- LLM은 의미 판단, 범위 판단, 요약, 설계 선택을 맡는다.
|
||||||
|
- 런타임은 파일명, 폴더명, 상태값, exit code처럼 결정적으로 판별 가능한 일을 맡는다.
|
||||||
|
- LLM 없이 처리할 수 있는 구간은 파일 규약으로 뺀다.
|
||||||
|
- 런타임 신호는 문서 본문보다 경로와 이름에 둔다.
|
||||||
|
- 런타임 신호를 만들 때는 agent가 본문을 읽지 않아도 판별 가능해야 한다.
|
||||||
|
- `m-<milestone-slug>` 같은 prefix는 런타임 판별을 위한 신호다.
|
||||||
|
- code-review는 PASS 산출물을 만들고 완료 이벤트 메타데이터를 남긴다.
|
||||||
|
- roadmap 반영 여부와 호출 타이밍은 런타임이 완료 이벤트를 보고 판단한다.
|
||||||
|
|
||||||
|
## 스킬 그룹 경계
|
||||||
|
|
||||||
|
- 스킬 그룹은 자기 라이프사이클 안에서만 강한 계약을 가진다.
|
||||||
|
- 스킬 그룹끼리는 다른 그룹의 내부 절차를 자동 호출하거나 전제하지 않는다.
|
||||||
|
- 그룹 간 연결은 사용자 명령, 런타임 이벤트, 또는 판별 가능한 파일 상태로만 한다.
|
||||||
|
- 구현 작업 그룹은 `plan`과 `code-review`의 PLAN/CODE_REVIEW 루프를 소유한다.
|
||||||
|
- 로드맵 그룹은 `create-roadmap`과 `update-roadmap`의 문서 작성, 의미 판단, 배치 제안, file-based fallback 갱신 흐름을 소유한다.
|
||||||
|
- 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`에 의존성 동기화 규칙을 넣지 않는다.
|
||||||
|
- 새 스킬을 만들기 전에 기존 그룹의 자연스러운 입력, 상태 전환, 후처리 지점에 넣을 수 있는지 먼저 본다. 다만 다른 그룹 경계를 침범해야 하면 런타임 이벤트로 분리한다.
|
||||||
|
|
||||||
|
## 로드맵
|
||||||
|
|
||||||
|
- roadmap은 장기 기억이고, agent-task는 실행 상태다.
|
||||||
|
- current는 현재 작업 하나가 아니라 브랜치별 로컬 활성 Phase/Milestone 후보 창이다.
|
||||||
|
- Phase와 Milestone은 큰 방향과 기능 단위를 담는다.
|
||||||
|
- 구현 계획은 agent-task의 PLAN/CODE_REVIEW 루프에 둔다.
|
||||||
|
- 완료 후보는 바로 archive하지 말고 `[검토중]`으로 둔다.
|
||||||
|
- archive는 일반 작업에서 읽지 않는다. 과거 근거가 필요할 때만 링크를 따라 읽는다.
|
||||||
|
|
||||||
|
## 스킬
|
||||||
|
|
||||||
|
- skill은 절차 문서다.
|
||||||
|
- skill 하나에 책임 하나만 둔다.
|
||||||
|
- skill이 다른 skill을 자동으로 깊게 호출하는 구조를 만들지 않는다.
|
||||||
|
- skill 본문은 실행에 필요한 규칙만 둔다.
|
||||||
|
- 템플릿은 출력 형식이 흔들릴 때만 둔다.
|
||||||
|
- 스킬 업데이트 시 router, rules, template, 출력 형식이 같은 계약을 말하는지 같이 확인한다.
|
||||||
|
- plan과 code-review처럼 짝 계약을 양쪽에서 반복해 강제하는 구조는 의도된 중복으로 본다. 동작 중인 짝 계약은 일관성 정리만을 위해 합치지 않는다.
|
||||||
|
|
||||||
|
## 좋은 구조
|
||||||
|
|
||||||
|
- 진입 파일은 최소 규칙만 둔다.
|
||||||
|
- common rules는 공통 시작점만 둔다.
|
||||||
|
- project rules는 프로젝트 특화 판단만 둔다.
|
||||||
|
- domain rules는 특정 코드 영역 규칙만 둔다.
|
||||||
|
- skills는 반복 작업 절차만 둔다.
|
||||||
|
- roadmap은 장기 목표와 기능 단위만 둔다.
|
||||||
|
- agent-task는 실행 중인 작업 상태와 완료 산출물만 둔다.
|
||||||
|
|
||||||
|
## 경고 신호
|
||||||
|
|
||||||
|
- 같은 내용을 세 군데 이상 설명하고 있다.
|
||||||
|
- 어떤 문서를 읽어야 할지 문서 안에서 다시 찾아야 한다.
|
||||||
|
- 상태값이 사람은 이해하지만 런타임은 판별하기 어렵다.
|
||||||
|
- skill이 너무 많은 예외를 품고 있다.
|
||||||
|
- README가 내부 규칙 문서처럼 길어지고 있다.
|
||||||
|
- archive를 일반 작업 컨텍스트로 끌어오고 있다.
|
||||||
|
- LLM이 파일명만 봐도 될 일을 본문까지 읽어 판단하고 있다.
|
||||||
158
agent-ops/rules/common/rules-roadmap.md
Normal file
158
agent-ops/rules/common/rules-roadmap.md
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
# 로드맵 규칙
|
||||||
|
|
||||||
|
`agent-roadmap/` 디렉터리가 있는 프로젝트에서만 적용한다.
|
||||||
|
|
||||||
|
## 구조
|
||||||
|
|
||||||
|
- 최상위 로드맵은 `agent-roadmap/ROADMAP.md`다.
|
||||||
|
- 활성 Phase는 `agent-roadmap/phase/<phase-slug>/PHASE.md`에 둔다.
|
||||||
|
- 활성 Milestone은 해당 Phase 아래 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`에 둔다.
|
||||||
|
- `<phase-slug>`와 `<milestone-slug>`는 소문자 영문, 숫자, 하이픈만 사용한다.
|
||||||
|
- 완료된 Phase는 scaffold 그대로 `agent-roadmap/archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 `archive/phase/<phase-slug>/milestones/` 아래에 둔다.
|
||||||
|
- 진행중 Phase 안에서 완료된 Milestone은 활성 `PHASE.md`에 짧은 archive 링크를 남기고, 상세 문서는 `agent-roadmap/archive/phase/<phase-slug>/milestones/`로 이동한다.
|
||||||
|
- archive `PHASE.md`는 Phase 자체가 완료/폐기될 때만 만들며, 진행중 Phase의 완료 Milestone만 archive된 경우 archive Phase 디렉터리에 `milestones/`만 있을 수 있다.
|
||||||
|
|
||||||
|
## Runtime Action Boundary
|
||||||
|
|
||||||
|
- 로드맵 스킬은 기본적으로 로드맵 문서 작성, 의미 판단, 배치 제안, file-based fallback 갱신을 담당한다.
|
||||||
|
- Core/MCP가 있는 프로젝트에서는 Phase/Milestone 상태 전환, archive 이동, 외부 의존 lock 동기화, 완료 이벤트 반영 같은 action을 Core/MCP 또는 런타임이 처리한다.
|
||||||
|
- Core/MCP가 없거나 아직 해당 action을 제공하지 않는 프로젝트에서만 `update-roadmap` 스킬이 file-based fallback으로 직접 문서를 갱신한다.
|
||||||
|
- `update-roadmap`은 fallback 갱신을 수행하더라도 런타임 action 경계를 문서화하고, Core/MCP로 넘길 수 있는 입력과 결과를 함께 남긴다.
|
||||||
|
|
||||||
|
## 로딩
|
||||||
|
|
||||||
|
- 세션 최초 1회 `agent-roadmap/current.md`가 있으면 읽고 활성 Phase, 활성 Milestone의 이름, 경로, 선택 규칙만 짧게 기억한다.
|
||||||
|
- `agent-roadmap/current.md`는 브랜치별 로컬 포인터이며 git 추적 대상이 아니다.
|
||||||
|
- `current.md`가 없고 로드맵 기반 계획 또는 갱신이 필요하면 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식으로 로컬 파일을 만들거나 `ROADMAP.md`와 활성 `PHASE.md`에서 후보를 고른다.
|
||||||
|
- 읽기 전용 로드맵 현지점 확인에서는 `current.md`가 없어도 만들지 않고, 로컬 current 없음으로 보고한 뒤 `ROADMAP.md`의 Phase 흐름만 보여준다.
|
||||||
|
- 일반 작업에서는 `ROADMAP.md`를 읽지 않는다.
|
||||||
|
- 일반 작업에서는 `agent-roadmap/archive/**`를 읽지 않는다.
|
||||||
|
- 기능 추가, 구조 변경, 구현 계획 전에는 요청과 변경 파일에 맞는 활성 Phase와 활성 Milestone 문서를 읽는다.
|
||||||
|
- 로드맵 현지점 확인은 로컬 `current.md`, `ROADMAP.md`의 Phase 흐름, 활성 `PHASE.md`의 Milestone 흐름, 활성 Milestone의 제목/목표/상태만 기본으로 읽는다.
|
||||||
|
- `ROADMAP.md`는 로드맵 생성/갱신, Phase 추가/삭제/전환, 전체 구조 변경, 활성 범위 밖 작업 확인 때만 읽는다.
|
||||||
|
- 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`에 있는 archive 링크를 따라가서 필요한 archive 문서만 읽는다.
|
||||||
|
|
||||||
|
## Phase와 Milestone 선택
|
||||||
|
|
||||||
|
- `current.md`는 현재 작업 위치가 아니라 활성 Phase와 활성 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`만 대상으로 한다.
|
||||||
|
- `current.md`에는 `[완료]` 또는 `[폐기]` Phase/Milestone을 남기지 않는다. 완료 후보는 승인 전까지 `[검토중]`으로 둔다.
|
||||||
|
- "로드맵에 추가", "마일스톤에 추가"처럼 target 없는 신규 작업 추가 요청은 `update-roadmap` 스킬로 배치 제안 또는 file-based fallback 갱신을 처리하고, Phase/Milestone/Epic/Task 배치를 자동 판단한다.
|
||||||
|
- target 없는 신규 추가 요청은 먼저 요청 규모를 `phase`, `milestone`, `epic`, `task`, `subtask`, `context` 중 가장 작은 충분한 단위로 판정한다.
|
||||||
|
- target 없는 신규 추가 요청은 활성 창만으로 결정하지 말고 필요한 경우 `ROADMAP.md`의 Phase 흐름과 관련 Phase/Milestone 문서를 비교한다.
|
||||||
|
- 배치는 Phase -> Milestone -> Epic -> Task 순서로 내려가며 같은 레벨의 동일/유사 후보를 먼저 찾는다.
|
||||||
|
- 동일/유사 항목이 이미 있으면 새로 만들지 말고 기존 항목을 업데이트한다.
|
||||||
|
- 적절한 기존 후보가 없을 때만 판정한 규모에 맞는 새 항목을 만든다.
|
||||||
|
- 부모 후보는 있고 판정 규모의 항목만 없으면 부모 아래에 새 항목을 만들고, 부모도 없을 때만 필요한 부모 항목을 함께 만든다.
|
||||||
|
- 자동 배치할 때는 선택한 Phase/Milestone/Epic/Task와 밀린 후보의 이유를 결과에 남긴다.
|
||||||
|
- `current.md`가 아카이브 경로를 가리키면 해당 항목은 활성 후보로 읽지 말고 로드맵 갱신이 필요하다고 보고한다.
|
||||||
|
- 선택한 Phase/Milestone의 목표 또는 범위 제외와 요청이 충돌하면 구현 전에 사용자에게 확인한다.
|
||||||
|
|
||||||
|
## 상태 표기
|
||||||
|
|
||||||
|
- Phase와 Milestone 상태 표기는 `[스케치]`, `[계획]`, `[진행중]`, `[검토중]`, `[완료]`, `[보류]`, `[폐기]` 중 하나만 사용한다.
|
||||||
|
- `[스케치]`는 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태다. 구현 가능한 계획이 아니므로 `agent-task` 구현 계획 생성과 코드 구현을 시작하지 않는다.
|
||||||
|
- `[스케치]` 항목은 `[계획]`으로 승격하기 위한 `승격 조건`, 사용자 결정, 범위 경계, 후속 Milestone 후보를 정리하는 것이 목적이다.
|
||||||
|
- `[계획]` 이상 상태의 Milestone에서 `승격 조건` 섹션은 선택 사항이다. 섹션이 없거나 `- 없음`이면 템플릿 오류로 보지 않는다.
|
||||||
|
- `[스케치]`를 `[계획]`으로 전환하려면 `승격 조건`의 미정 항목이 해소되고, 목표, 범위, 기능 Task, 직접적인 사용자 결정 항목, 후속 구현 단위가 구현 계획을 만들 수 있을 만큼 정리되어야 한다.
|
||||||
|
- `[계획]`은 목표, 범위, 기능 Task, 구현 잠금, 결정 필요 항목이 정리되어 구현 계획을 만들 수 있는 상태다.
|
||||||
|
- 갱신 범위에 포함된 기존 진행 상태 표기는 `[진행중]`으로 정리한다.
|
||||||
|
- `[검토중]`은 모든 기능 Task와 Task 안에 명시된 검증이 충족된 것으로 보이나, 사용자의 최종 완료 확인과 archive 승인이 아직 남은 완료 후보 상태다.
|
||||||
|
- `[검토중]` 항목은 활성 경로에 남기고 `current.md`의 활성 후보로 유지할 수 있다.
|
||||||
|
- 검토 결과 보완이 필요하면 별도 reopen 상태를 만들지 않고 `[진행중]`으로 되돌린 뒤 `완료 리뷰` 또는 `작업 컨텍스트`에 보완 방향을 남긴다.
|
||||||
|
- 검토 결과 보류 또는 폐기 결정이 나면 `[보류]` 또는 `[폐기]`로 전환한다.
|
||||||
|
- `ROADMAP.md`의 Phase 흐름과 `PHASE.md`의 Milestone 흐름은 완료, 검토중, 진행중, 계획, 스케치 순서를 기본으로 하며 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- `구현 잠금`은 승인 의식이 아니라 사용자 결정이 필요한지 표시하는 얇은 상태다.
|
||||||
|
- 제품 방향, 범위, 우선순위, 책임 경계처럼 사용자만 결정할 수 있는 항목이 남아 있으면 상태를 `잠금`으로 두고 `결정 필요` 체크리스트에 질문을 적는다.
|
||||||
|
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 합리적으로 정할 수 있는 항목은 `결정 필요`가 아니라 `작업 컨텍스트`의 표준선이나 구현 가정으로 기록한다.
|
||||||
|
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
|
||||||
|
- 선택한 Milestone에 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 코드 구현, `agent-task` 구현 계획, 세부 API/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 사용자에게 확인한다.
|
||||||
|
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 표준선으로 처리 가능한 작업을 막지 않는다.
|
||||||
|
- 잠금 상태를 바꾸더라도 `기능` Task를 자동 완료 처리하지 않는다.
|
||||||
|
- `[스케치]` 상태의 Milestone은 `구현 잠금`이 `해제`로 보이더라도 구현 계획과 코드 구현 대상이 아니다. 먼저 `[계획]`으로 승격해야 한다.
|
||||||
|
|
||||||
|
## 프로젝트 간 잠금
|
||||||
|
|
||||||
|
- 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`은 프로젝트 간 Milestone 잠금 인덱스다. 외부 의존 잠금을 생성하거나 동기화해야 하면 Core/MCP가 있으면 그쪽 action이 만들고, 없으면 `update-roadmap` file-based fallback이 디렉터리와 파일을 만든다.
|
||||||
|
- entry는 `id`, `locked`, `rely-on[].target`, `rely-on[].status`, `rely-on[].note`만 사용한다.
|
||||||
|
- `locks.yaml`은 root sequence block style을 기본으로 작성한다. 예: `- id: ...` 아래에 `locked`, `rely-on`을 둔다.
|
||||||
|
- `id`는 기본적으로 `<잠긴-project>:<잠긴-milestone-slug>`로 만든다.
|
||||||
|
- `locked`와 `rely-on[].target`은 `<project>:agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 형식으로 기록한다.
|
||||||
|
- Milestone 경로가 `agent-roadmap/...` 상대 경로이면 현재 프로젝트명을 prefix로 붙인다. workspace 하위 절대/상대 경로이면 workspace 바로 아래 디렉터리명을 project로 삼고, 그 뒤 `agent-roadmap/...` 경로를 붙인다.
|
||||||
|
- `locked`는 잠긴 Milestone, `rely-on.target`은 선행 조건 Milestone이다. 둘 다 같은 workspace의 어느 활성 Phase 하위 Milestone이어도 된다. 의존 대상이 `current.md`에 있어야 한다고 가정하지 않는다.
|
||||||
|
- "현재 마일스톤은 X 프로젝트 작업 뒤에 진행", "X 프로젝트 때문에 현재 작업 잠금", "의존성 설정해"처럼 잠긴 Milestone을 생략한 외부 의존 잠금 요청은 현재 프로젝트 로컬 `current.md`의 활성 Milestone 단일 후보를 잠긴 대상으로 삼는다.
|
||||||
|
- 의존 대상은 명시 경로, 명시 slug, 명시 제목, 잠긴 Milestone 문서의 선행 Milestone 힌트, 대상 프로젝트 로컬 `current.md`가 있을 때의 단일 후보 순서로 확정한다.
|
||||||
|
- 정규화 비교는 소문자 변환, backtick/따옴표 제거, 영문/숫자가 아닌 연속 문자를 `-` 하나로 치환, 앞뒤 `-` 제거 후 Milestone 파일 slug와 정규화한 제목에 대조한다.
|
||||||
|
- 의존 대상 탐색은 대상 프로젝트의 `agent-roadmap/phase/*/milestones/*.md` 활성 문서만 대상으로 한다. archive 문서는 사용자가 archive 경로를 명시한 경우 외에는 읽거나 후보로 삼지 않는다.
|
||||||
|
- 후보가 없거나 둘 이상이면 locks.yaml을 만들거나 고치지 말고 사용자에게 대상 Milestone 선택을 요청한다.
|
||||||
|
- 외부 의존 잠금을 만들 때 대상 Milestone의 `구현 잠금`은 `잠금`으로 둔다.
|
||||||
|
- 새 `rely-on.status`는 선행 Milestone 상태에서 파생한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태거나 상태를 확인할 수 없으면 `disable`이다.
|
||||||
|
- 같은 `id` entry를 upsert할 때 기존 `rely-on` 항목을 삭제하지 않는다. 같은 `rely-on.target`만 status/note를 갱신하고, 없는 target은 추가하며, `locked` 경로가 바뀐 경우에만 `locked`를 갱신한다.
|
||||||
|
- `locks.yaml`이 있고 Milestone을 갱신하거나 archive할 때는 대상 Milestone identity로 `agent-ops/bin/roadmap-dependency-checker.sh --find-milestone "<identity>" both "<locks-file>"`를 먼저 실행한다.
|
||||||
|
- find 결과가 `none`이면 결과 보고의 `Workspace 잠금`에 `관련 lock 없음`을 남긴다. 외부 의존 잠금 생성/동기화 요청이 아니라면 `locks.yaml`을 새로 만들거나 수정하지 않는다.
|
||||||
|
- Core/MCP action 또는 `update-roadmap` fallback이 갱신한 Milestone identity가 어느 entry의 `rely-on.target`과 일치하면 Milestone 상태 기준으로 `status`를 동기화한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태면 `disable`이다.
|
||||||
|
- Core/MCP action 또는 `update-roadmap` fallback이 갱신하거나 선택한 Milestone identity가 어느 entry의 `locked`와 일치하면 모든 `rely-on.status`가 `enable`인지 결과 보고에 남긴다. 모든 조건이 충족되어도 잠금 해제 실행은 Core/MCP 또는 런타임의 별도 action으로 처리한다.
|
||||||
|
- archive 모드에서는 파일 이동 전에 대상 Milestone의 활성 경로 identity를 보존하고, 그 identity로 `--find-milestone "<identity>" both "<locks-file>"`를 먼저 실행한다. 보존한 identity가 어느 entry의 `rely-on.target`과 일치하고 Milestone 상태가 `[완료]`이면 archive 이동 전에 해당 `rely-on.status`를 `enable`로 바꾼다.
|
||||||
|
- archive 모드에서 보존한 identity가 어느 entry의 `locked`와 일치하면 archive 이동 전에 모든 `rely-on.status`가 `enable`인지 결과 보고에 남긴다. 미충족이어도 archive 자체는 막지 않고 `Workspace 잠금: 미충족`으로 보고한다.
|
||||||
|
- 잠금 해제 조건 충족 여부만 확인할 때는 `agent-ops/skills/common/check-roadmap-dependency/SKILL.md`를 읽는다. lock id가 없으면 해당 스킬은 `agent-ops/bin/roadmap-dependency-checker.sh --find-milestone "<identity>" "<direction>" "<locks-file>"`로 현재 Milestone이 `locked`인지 `rely-on.target`인지 양방향으로 찾은 뒤 `agent-ops/bin/roadmap-dependency-checker.sh "<lock-id>" "<locks-file>"`를 사용한다.
|
||||||
|
- checker exit code는 `0=true`, `1=false`, `2=설정/입력/파싱 오류`로 해석한다.
|
||||||
|
|
||||||
|
## Epic과 Task id
|
||||||
|
|
||||||
|
- Milestone 문서의 실행 체크리스트는 `기능` 섹션 하나로 작성한다. 새 Milestone이나 갱신 범위에 포함된 Milestone에는 별도 `완료 기준` 섹션을 만들지 않는다.
|
||||||
|
- 기존 Milestone에 `필수 기능`과 `완료 기준`이 분리되어 있으면, 갱신 시 `완료 기준`을 관련 기능 Task 안의 선택적 `검증:` 문구로 흡수하고 섹션을 제거한다.
|
||||||
|
- 기능 Task는 기능 또는 산출물 단위다. 검증이 필요한 기능만 같은 Task 안에 `검증: <명령/확인 방법/기대 결과>`를 붙인다.
|
||||||
|
- 검증이 명시된 Task의 `[x]`는 기능/산출물과 해당 검증이 모두 충족되었다는 뜻이다. 검증이 명시되지 않은 Task의 `[x]`는 기능/산출물 완료 근거가 충분하다는 뜻이다.
|
||||||
|
- 사용자만 결정할 수 있는 검토/선택/우선순위 항목은 기능 Task로 쓰지 않는다. `구현 잠금`의 `결정 필요` 또는 `작업 컨텍스트`로 분리하고, 현재 구현에 직접 필요하면 plan 생성 전에 사용자 확인을 받는다.
|
||||||
|
- `기능` 섹션의 Task 체크리스트는 Epic 바로 아래의 flat list를 기본으로 한다. 구현 세부, 테스트만 따로 떼어낸 하위 체크박스는 roadmap에 만들지 말고 plan 내부 체크리스트나 같은 Task의 `검증:`으로 흡수한다.
|
||||||
|
- Epic heading은 `### Epic: [epic-id] <이름>` 형식을 사용한다.
|
||||||
|
- Task는 `- [ ] [item-id] 설명` 또는 `- [x] [item-id] 설명` 형식을 사용한다.
|
||||||
|
- epic-id와 item-id는 공백 없는 짧은 ASCII 토큰이며, 영문/숫자 segment 1~4개로 작성하고 segment 구분자는 `-`, `_`, `+`, `=`만 사용한다. 가능하면 1~3 segment를 우선하며, 전체 길이는 32자 이하를 권장한다.
|
||||||
|
- epic-id와 item-id는 해당 Milestone 안에서만 유일하면 된다.
|
||||||
|
- 다른 Milestone에서는 같은 id를 다시 사용할 수 있다. 여러 Milestone 후보에서 같은 id가 발견되면 Milestone 이름이나 문서 경로로 대상을 확정한다.
|
||||||
|
- 사용자가 epic-id 또는 item-id를 언급하면 해당 Milestone의 Epic/Task 항목을 우선 anchor로 삼고, 기존 id는 명시적 요청 없이 바꾸지 않는다.
|
||||||
|
|
||||||
|
## Milestone 기반 agent-task
|
||||||
|
|
||||||
|
- `plan` 스킬이 활성 Milestone 범위의 구현 계획을 만들면 task group은 `agent-task/m-<milestone-slug>/` 형식을 사용한다.
|
||||||
|
- `<milestone-slug>`는 활성 Milestone 파일명에서 `.md`를 제거한 값이며, Phase slug, Epic id, Task id, 별도 task slug를 task group에 넣지 않는다.
|
||||||
|
- split 작업은 기존 규칙 그대로 `agent-task/m-<milestone-slug>/<subtask_dir>/` 아래에 둔다.
|
||||||
|
- `m-<milestone-slug>`는 Milestone 기반 작업 전용 예약 prefix이며, 일반 작업 task group은 `m-`으로 시작하지 않는다.
|
||||||
|
- 런타임은 파일 내부가 아니라 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으로 둔다.
|
||||||
|
- 런타임 완료 이벤트가 최종 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에서 follow-up plan/review를 이어가지만, code-review의 user-review gate가 트리거되면 `USER_REVIEW.md`를 남기고 사용자 판단을 기다린다.
|
||||||
|
- `[스케치]` Milestone은 Milestone 기반 `agent-task` 생성 대상이 아니다. 런타임이나 plan 스킬은 이를 구현 작업으로 라우팅하지 않고 `[계획]` 승격 필요를 보고한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- Task 완료나 Milestone 갱신 시 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`가 되었는지 확인한다.
|
||||||
|
- 모두 충족된 것으로 보이면 Milestone을 `[완료]`로 바로 바꾸거나 archive로 이동하지 말고 `[검토중]`으로 바꾼다.
|
||||||
|
- `[검토중]`으로 바꿀 때는 Milestone 문서에 `완료 리뷰` 섹션을 만들거나 갱신하고, 완료 근거 1~3줄과 사용자에게 필요한 최종 확인 항목을 남긴다.
|
||||||
|
- 사용자가 완료를 승인한 뒤에만 `[완료]`로 전환하고 archive 이동을 수행한다.
|
||||||
|
- Phase도 모든 하위 Milestone이 `[완료]` 또는 `[폐기]`로 정리되어 Phase 완료 후보가 되면 `[검토중]`으로 두고 사용자 최종 확인을 받은 뒤 `[완료]` 또는 `[폐기]`로 전환한다.
|
||||||
|
|
||||||
|
## 로드맵 현지점
|
||||||
|
|
||||||
|
- 현재 작업 지점이나 로드맵상 현 위치 확인 요청은 `analyze-roadmap-position` 스킬로 처리한다.
|
||||||
|
- 답변은 `agent-ops/skills/common/_templates/roadmap-position-report-template.md` 섹션과 필드 순서를 따른다.
|
||||||
|
- 기본 동작에서는 코드, git 상태, diff를 읽지 않고 `로드맵 > Phase > Milestone` breadcrumb와 흐름 목록으로 현재 좌표를 보여준다.
|
||||||
|
- current가 Phase 또는 Milestone 후보를 여럿 가리키면 모두 `현재 후보`로 표시하고 짧은 역할 태그만 붙인다.
|
||||||
|
|
||||||
|
## 아카이브
|
||||||
|
|
||||||
|
- 완료 또는 폐기되어 현재 작업 후보에서 제외할 Phase/Milestone은 Core/MCP action으로 아카이빙한다. Core/MCP action이 없으면 `update-roadmap` file-based fallback으로 아카이빙한다.
|
||||||
|
- `[검토중]` Phase/Milestone은 archive 대상이 아니며, 사용자 승인 전까지 활성 경로에 남긴다.
|
||||||
|
- Phase 아카이브 대상은 `agent-roadmap/archive/phase/<phase-slug>/PHASE.md`와 같은 scaffold로 이동한다.
|
||||||
|
- Milestone 아카이브 대상은 `agent-roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 이동한다.
|
||||||
|
- Milestone 아카이브 전에는 이동 전 활성 경로 identity로 `.agent-roadmap-sync/locks.yaml`을 확인한다. 해당 identity가 `rely-on.target`이면 `[완료]` 상태에서 `enable`로 동기화하고, 해당 identity가 `locked`이면 의존 조건 충족 여부를 보고하며, 어느 쪽에도 없으면 `관련 lock 없음`으로 보고한다.
|
||||||
|
- 아카이빙할 때는 활성 `ROADMAP.md` 또는 활성 `PHASE.md`에 archive 문서 링크와 짧은 요약만 남긴다.
|
||||||
|
- 아카이브된 Phase/Milestone은 로컬 `current.md`에 남기지 않고, 일반 Phase/Milestone 선택이나 위치 분석의 후보로 삼지 않는다.
|
||||||
|
- 아카이브 문서는 과거 기록 스냅샷으로 보고, 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.
|
||||||
44
agent-ops/rules/common/rules.md
Normal file
44
agent-ops/rules/common/rules.md
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 공통 규칙
|
||||||
|
|
||||||
|
**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||||
|
|
||||||
|
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||||
|
- 사용자에게 보이는 최종 답변과 설명은 기본적으로 한국어로 작성한다.
|
||||||
|
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||||
|
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||||
|
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||||
|
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다. 예외: plan/code-review 루프의 split subtask 선행 의존성 충족 여부를 확인할 때는 같은 task group의 후보 `complete.log`만 읽을 수 있다.
|
||||||
|
- `agent-roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
|
||||||
|
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
|
||||||
|
- tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다.
|
||||||
|
|
||||||
|
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||||
|
|
||||||
|
1. `agent-ops/rules/project/rules.md`
|
||||||
|
2. `agent-ops/rules/private/rules.md`
|
||||||
|
3. `agent-roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||||
|
|
||||||
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
|
|
||||||
|
# 스킬 규칙
|
||||||
|
|
||||||
|
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||||
|
- agent-ops 초기화
|
||||||
|
- domain rule 생성
|
||||||
|
- skill 생성
|
||||||
|
- 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test
|
||||||
|
- README 생성
|
||||||
|
- 로드맵/마일스톤 생성·갱신
|
||||||
|
- 로드맵 현지점 / 현재 작업 지점 확인
|
||||||
|
- 계획 작성 / plan 생성
|
||||||
|
- 코드 리뷰 / review 진행
|
||||||
|
- git commit / push
|
||||||
|
- agent-ops 업데이트 / 진입 파일 재적용
|
||||||
|
|
||||||
|
# 테스트 규칙
|
||||||
|
|
||||||
|
**테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.**
|
||||||
|
|
||||||
|
- local: `agent-test/local/rules.md` (없으면 `create-test`)
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
## 사용자 리뷰 요청
|
||||||
|
|
||||||
|
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 사유 유형: 없음
|
||||||
|
- 결정 필요: 없음
|
||||||
|
- 차단 근거: 없음
|
||||||
|
- 실행한 검증/명령: 없음
|
||||||
|
- 자동 후속 불가 이유: 없음
|
||||||
|
- 재개 조건: 없음
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
# 현재 로드맵 컨텍스트
|
||||||
|
|
||||||
|
## 활성 Phase
|
||||||
|
|
||||||
|
- [<스케치 | 계획 | 진행중 | 검토중 | 보류>] <phase-name>
|
||||||
|
- 경로: `agent-roadmap/phase/<phase-slug>/PHASE.md`
|
||||||
|
|
||||||
|
## 활성 Milestone
|
||||||
|
|
||||||
|
- [<스케치 | 계획 | 진행중 | 검토중 | 보류>] <milestone-name>
|
||||||
|
- Phase: `agent-roadmap/phase/<phase-slug>/PHASE.md`
|
||||||
|
- 경로: `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`
|
||||||
|
|
||||||
|
## 선택 규칙
|
||||||
|
|
||||||
|
- 이 문서는 활성 Phase와 활성 Milestone 후보 목록이며, 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
|
||||||
|
- 이 문서는 브랜치별 로컬 포인터이며 git 추적 대상이 아니다.
|
||||||
|
- 활성 Phase는 `agent-roadmap/phase/<phase-slug>/PHASE.md`를 가리킨다.
|
||||||
|
- 활성 Milestone은 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`를 가리킨다.
|
||||||
|
- 활성 항목은 아카이브 경로를 포함하지 않는다.
|
||||||
|
- `[검토중]` 항목은 사용자 완료 확인 전까지 활성 항목으로 남길 수 있다.
|
||||||
|
- `[스케치]` 항목은 활성 후보로 남길 수 있지만 구현 계획 생성 대상은 아니며, `[계획]` 승격 조건을 정리하는 대상으로만 다룬다.
|
||||||
|
- `[완료]` 또는 `[폐기]` 항목은 archive 링크를 남긴 뒤 활성 항목에서 제거한다.
|
||||||
|
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 Phase와 Milestone을 선택하고 같은 세션에서 1회 읽는다.
|
||||||
|
- 활성 Phase 또는 Milestone 둘 이상에 걸치면 필요한 문서를 모두 읽고 작업 범위를 좁힌다.
|
||||||
|
- 활성 범위 밖의 작업이면 `agent-roadmap/ROADMAP.md`의 Phase 흐름을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
|
||||||
|
- 완료된 과거 내용이 필요할 때만 `ROADMAP.md` 또는 `PHASE.md`에 있는 archive 링크를 따라가서 읽는다.
|
||||||
|
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 구현이나 구현 계획을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다. 관련 결정이 없고 표준선으로 처리 가능하면 잠금을 유지한 채 진행할 수 있으며, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없을 때만 `구현 잠금` 상태를 `해제`로 둔다.
|
||||||
|
- 선택된 Milestone 상태가 `[스케치]`이면 `구현 잠금` 상태와 관계없이 구현이나 구현 계획을 시작하지 않고 `[계획]` 승격 필요를 보고한다.
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
# Milestone: <Milestone 이름>
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/<phase-slug>/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
<이 Milestone이 끝났을 때 달성되어야 하는 결과를 1~3문장으로 작성>
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
<!--
|
||||||
|
[스케치] Milestone일 때만 필수다.
|
||||||
|
[스케치]에서는 [계획]으로 전환하기 위해 필요한 정의, 결정, 경계, 후속 구현 Milestone 후보를 체크리스트로 적는다.
|
||||||
|
[계획] 이상 상태에서는 이 섹션을 생략하거나 아래처럼 `- 없음`으로 둔다.
|
||||||
|
-->
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
<!-- [스케치] 예시:
|
||||||
|
- [ ] 구현 가능한 목표와 범위를 확정한다.
|
||||||
|
- [ ] 사용자만 결정할 제품/우선순위/책임 경계를 정리한다.
|
||||||
|
- [ ] 기능 단위와 후속 구현 Milestone 후보를 나눈다.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: <잠금 | 해제>
|
||||||
|
- 결정 필요: <없음 | 아래 체크리스트>
|
||||||
|
- [ ] <사용자만 결정할 수 있는 제품/범위/우선순위/책임 경계 질문>
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- <이 Milestone에 포함되는 제품/기술/문서 범위>
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Epic은 `### Epic: [epic-id] <이름>` 형식을 사용한다.
|
||||||
|
epic-id는 공백 없는 짧은 ASCII 영문/숫자 segment 1~4개로 작성하고 segment 구분자는 -_+= 만 사용한다.
|
||||||
|
Task는 `- [ ] [item-id] 설명` 형식을 사용한다.
|
||||||
|
item-id는 공백 없는 짧은 ASCII 영문/숫자 segment 1~4개로 작성하고 segment 구분자는 -_+= 만 사용한다.
|
||||||
|
epic-id와 item-id는 해당 Milestone 안에서만 유일하면 되고, 다른 Milestone에서는 같은 id를 다시 사용할 수 있다.
|
||||||
|
Task는 기능 또는 산출물 단위다. 검증이 필요한 기능만 같은 Task 안에 `검증: <명령/확인 방법/기대 결과>`를 덧붙인다.
|
||||||
|
Task 체크리스트는 Epic 바로 아래의 flat list로 유지하고, 구현 세부나 테스트만 따로 떼어낸 하위 체크박스는 만들지 않는다.
|
||||||
|
별도 `완료 기준` 섹션은 만들지 않는다.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Epic: [epic-id] <Epic 이름>
|
||||||
|
|
||||||
|
<이 Epic이 묶는 capability 또는 산출물 설명>
|
||||||
|
|
||||||
|
- [ ] [item-id] <구현 세부가 아니라 이 Milestone에서 달성해야 할 capability 또는 산출물>
|
||||||
|
|
||||||
|
<!-- 검증이 필요한 기능 Task 예시:
|
||||||
|
- [ ] [item-id] <기능 설명>. 검증: <명령/확인 방법/기대 결과>
|
||||||
|
-->
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: <없음 | 요청됨 | 승인됨 | 보완 필요 | 보류 | 폐기>
|
||||||
|
- 요청일: <YYYY-MM-DD | 없음>
|
||||||
|
- 완료 근거: <모든 기능 Task와 Task 안에 명시된 검증 충족 여부를 1~3줄로 요약>
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: <없음 | 보완/보류/폐기 방향성>
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- <이 Milestone에서 의도적으로 하지 않는 일>
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `<path>`
|
||||||
|
- 표준선(선택): <기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 진행할 기본 기준>
|
||||||
|
- 선행 작업: <없음 또는 Milestone/태스크 이름>
|
||||||
|
- 후속 작업: <없음 또는 Milestone/태스크 이름>
|
||||||
|
- 확인 필요: <!-- TODO: 확인 필요 -->
|
||||||
23
agent-ops/skills/common/_templates/roadmap-phase-template.md
Normal file
23
agent-ops/skills/common/_templates/roadmap-phase-template.md
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Phase: <Phase 이름>
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>]
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
<이 Phase가 끝났을 때 달성되어야 하는 결과와 책임 경계를 1~3문장으로 작성>
|
||||||
|
|
||||||
|
## Milestone 흐름
|
||||||
|
|
||||||
|
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
|
||||||
|
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||||
|
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||||
|
|
||||||
|
- [<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>] <Milestone 이름>
|
||||||
|
- 경로: `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 또는 `agent-roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md`
|
||||||
|
- 요약: <목표 또는 결과 1문장>
|
||||||
|
|
||||||
|
## Phase 경계
|
||||||
|
|
||||||
|
- <이 Phase에서 유지할 책임 경계 또는 범위 제외 기준>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# 로드맵 현지점
|
||||||
|
|
||||||
|
- [local current.md](agent-roadmap/current.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)
|
||||||
|
- [<상태>] <목표 또는 역할 한 줄>
|
||||||
|
- [Milestone: <milestone-name>](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
|
||||||
|
- [<상태>] <목표 또는 역할 한 줄>
|
||||||
|
|
||||||
|
## 전체 Phase 흐름
|
||||||
|
|
||||||
|
- [<상태>] [<Phase 이름>](<phase-path>)
|
||||||
|
- [<상태>] [<현재 Phase 이름>](<phase-path>) ← 현재
|
||||||
|
- [<상태>] [<Phase 이름>](<phase-path>)
|
||||||
|
|
||||||
|
## 현재 Phase의 Milestone 흐름
|
||||||
|
|
||||||
|
- [<상태>] [<Milestone 이름>](<milestone-path>) ← 현재 후보, <역할 태그>
|
||||||
|
- [<상태>] [<Milestone 이름>](<milestone-path>) ← 현재 후보, <역할 태그>
|
||||||
42
agent-ops/skills/common/_templates/roadmap-template.md
Normal file
42
agent-ops/skills/common/_templates/roadmap-template.md
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# 로드맵
|
||||||
|
|
||||||
|
## 전체 목표
|
||||||
|
|
||||||
|
<프로젝트가 최종적으로 달성하려는 결과를 1~3문장으로 작성>
|
||||||
|
|
||||||
|
## Phase 흐름
|
||||||
|
|
||||||
|
위에서 아래로 진행된 순서와 예정 흐름을 나타낸다.
|
||||||
|
완료된 Phase도 로드맵에서 제거하지 않고, archive의 Phase 문서로 연결한다.
|
||||||
|
검토중 또는 진행중 Phase는 계획 Phase보다 위에 두어, 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||||
|
스케치 Phase는 아직 구현 가능한 계획이 아니므로 계획 Phase보다 아래에 둔다.
|
||||||
|
|
||||||
|
- [<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>] <Phase 이름>
|
||||||
|
- 경로: `agent-roadmap/phase/<phase-slug>/PHASE.md` 또는 `agent-roadmap/archive/phase/<phase-slug>/PHASE.md`
|
||||||
|
- 요약: <이 Phase의 목표와 역할 1문장>
|
||||||
|
|
||||||
|
## 로딩 정책
|
||||||
|
|
||||||
|
- 일반 작업에서는 `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는 `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 안에 `검증:`으로 통합한다.
|
||||||
|
- `[스케치]` Phase/Milestone은 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태이며 구현 계획 생성 대상이 아니다.
|
||||||
|
- `[스케치]` 항목은 `승격 조건`을 정리해 `[계획]`으로 전환한 뒤 구현 계획을 만든다.
|
||||||
|
- 모든 기능 Task와 Task 안에 명시된 검증이 충족된 Milestone은 먼저 `[검토중]`으로 두고, 사용자 완료 확인과 archive 승인을 받은 뒤 `[완료]`로 전환한다.
|
||||||
|
- 완료된 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/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다.
|
||||||
|
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 기존 구조/도메인 rule/플랫폼 관례로 정할 수 있는 작업은 표준선으로 기록하고 진행할 수 있다.
|
||||||
|
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `구현 잠금` 상태를 `해제`로 둔다.
|
||||||
56
agent-ops/skills/common/_templates/skill-template.md
Normal file
56
agent-ops/skills/common/_templates/skill-template.md
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
---
|
||||||
|
name: <skill-name>
|
||||||
|
version: 1.0.0
|
||||||
|
description: <이 skill이 하는 일을 한 줄로 설명. 트리거 키워드 포함 권장>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <skill-name>
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
<이 skill이 해결하는 문제를 1~2문장으로 설명>
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- <이 skill을 호출해야 하는 상황 1>
|
||||||
|
- <이 skill을 호출해야 하는 상황 2>
|
||||||
|
- <이 skill을 호출해야 하는 상황 3>
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `<param-name>`: <설명> (필수)
|
||||||
|
- `<param-name>`: <설명> (선택)
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] <실행 전 반드시 확인해야 할 조건 1>
|
||||||
|
- [ ] <실행 전 반드시 확인해야 할 조건 2>
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **<단계명>**
|
||||||
|
- <세부 행동>
|
||||||
|
- <세부 행동>
|
||||||
|
|
||||||
|
2. **<단계명>**
|
||||||
|
- <세부 행동>
|
||||||
|
|
||||||
|
3. **결과 보고**
|
||||||
|
- <출력할 내용>
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] <실행 후 확인해야 할 성공 조건 1>
|
||||||
|
- [ ] <실행 후 확인해야 할 성공 조건 2>
|
||||||
|
- 검증 실패 시: <실패 시 취할 행동 — 롤백, 사용자 알림, 재시도 등>
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```
|
||||||
|
<출력 예시>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- <절대 하면 안 되는 것>
|
||||||
|
- <절대 하면 안 되는 것>
|
||||||
74
agent-ops/skills/common/analyze-roadmap-position/SKILL.md
Normal file
74
agent-ops/skills/common/analyze-roadmap-position/SKILL.md
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
---
|
||||||
|
name: analyze-roadmap-position
|
||||||
|
version: 1.11.0
|
||||||
|
description: "여러 레포를 전환할 때 코드/git 분석 없이 전체 ROADMAP > Phase > Milestone > current 현지점을 링크 달린 breadcrumb와 흐름 목록으로 빠르게 보여주는 읽기 전용 스킬"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 로드맵 현지점
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
여러 레포를 병렬 운용하다가 돌아왔을 때, 현재 작업이 전체 로드맵의 어느 Phase와 Milestone에 있는지 빠르게 보여준다.
|
||||||
|
기본 출력은 `로드맵 > Phase > Milestone` breadcrumb와 전체 Phase 흐름, 현재 Phase의 Milestone 흐름이다.
|
||||||
|
코드 진행도 감사, git diff 분석, 테스트 근거 확인, 남은 작업 정밀 판정은 기본 책임이 아니다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 사용자가 "지금 작업이 뭐지?", "현재 작업이 뭐야?", "어디까지 했지?"라고 물을 때
|
||||||
|
- 사용자가 레포 전환 직후 로드맵상 현재 좌표를 빠르게 알고 싶어 할 때
|
||||||
|
- "로드맵상 현 위치", "현재 마일스톤 위치", "current 기준 breadcrumb"를 요청할 때
|
||||||
|
- 구현 시작 전 전체 Roadmap > Phase > Milestone 관계만 확인하면 될 때
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] `agent-ops/skills/common/_templates/roadmap-position-report-template.md`를 읽어 최신 답변 템플릿 확인
|
||||||
|
- [ ] `agent-roadmap/` 디렉터리 존재 여부 확인
|
||||||
|
- [ ] 로컬 `agent-roadmap/current.md` 존재 여부 확인
|
||||||
|
- [ ] 로드맵이 있으면 `ROADMAP.md`의 `Phase 흐름`을 확인
|
||||||
|
- [ ] 로컬 `current.md`의 활성 Phase와 활성 Milestone 이름, 상태, 경로 확인
|
||||||
|
- [ ] 활성 Phase 문서의 `Milestone 흐름` 확인
|
||||||
|
- [ ] 활성 Milestone 문서의 제목, `목표`, `상태`만 확인
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. `agent-roadmap/` 존재 여부를 확인한다.
|
||||||
|
- 없으면 로드맵 없음으로 짧게 보고하고 멈춘다.
|
||||||
|
2. `agent-ops/skills/common/_templates/roadmap-position-report-template.md`를 읽는다.
|
||||||
|
3. 로컬 `agent-roadmap/current.md`를 확인한다.
|
||||||
|
- 없으면 로컬 current 없음으로 보고하고, `ROADMAP.md`가 있으면 `Phase 흐름`만 보여준다.
|
||||||
|
4. `ROADMAP.md`의 `Phase 흐름`을 읽어 전체 Phase 목록을 만든다.
|
||||||
|
- 각 Phase는 상태, 이름, 링크만 남긴다.
|
||||||
|
- current의 활성 Phase와 일치하는 항목에 `← 현재` 표시를 붙인다.
|
||||||
|
- 완료된 Phase가 archive 경로를 가리켜도 링크만 표시하고 archive 문서는 읽지 않는다.
|
||||||
|
5. current의 활성 Phase 경로를 열고 `Milestone 흐름`을 읽는다.
|
||||||
|
- 각 Milestone은 상태, 이름, 링크만 남긴다.
|
||||||
|
- current의 활성 Milestone과 일치하는 항목에 `← 현재 후보` 표시를 붙인다.
|
||||||
|
6. current의 활성 Milestone 문서를 열고 제목, `목표`, `상태`만 읽는다.
|
||||||
|
- `기능`, `완료 리뷰`, `범위 제외`, `작업 컨텍스트`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||||
|
7. 결과를 템플릿 형식 그대로 출력한다.
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] `roadmap-position-report-template.md`의 출력 구조를 유지했는가
|
||||||
|
- [ ] 로컬 `current.md`, `ROADMAP.md`, 활성 `PHASE.md`, 활성 Milestone의 제목/목표/상태만 기본으로 읽었는가
|
||||||
|
- [ ] 완료 또는 archive Phase/Milestone은 링크만 표시하고 archive 문서를 읽지 않았는가
|
||||||
|
- [ ] current가 여러 Milestone을 가리키면 모두 `현재 후보`로 표시했는가
|
||||||
|
- [ ] 코드 파일, 테스트 파일, `git status`, `git diff`를 기본 동작에서 읽지 않았는가
|
||||||
|
- [ ] 로드맵 파일을 수정하지 않았는가
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
- 템플릿 경로: `agent-ops/skills/common/_templates/roadmap-position-report-template.md`
|
||||||
|
- 템플릿을 그대로 복사해 placeholder를 채운다.
|
||||||
|
- 섹션 제목과 필드명을 임의로 번역, 축약, 삭제하지 않는다.
|
||||||
|
- current가 여러 Milestone을 가리키면 breadcrumb와 Milestone 흐름에 모두 표시한다.
|
||||||
|
- 현재 후보의 역할 태그는 `선행 스케치`, `다음 구현 계획`, `검토 후보`, `보류 후보`처럼 짧게 쓴다.
|
||||||
|
- 로드맵이 없는 프로젝트에서는 로드맵 없음으로 짧게 보고하고 템플릿을 억지로 채우지 않는다.
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 기본 동작에서 코드 파일, 테스트 파일, `git status`, `git diff`를 읽지 않는다.
|
||||||
|
- 기본 동작에서 Milestone의 `기능` 체크리스트를 감사하지 않는다.
|
||||||
|
- 완료 여부, 남은 작업, 코드와 문서의 동기화 상태를 evidence 기반으로 판정하지 않는다.
|
||||||
|
- 사용자가 명시하지 않은 상태에서 `ROADMAP.md`, 로컬 `current.md`, Phase, Milestone 문서를 수정하지 않는다.
|
||||||
|
- 사용자가 과거 기록 확인을 명시하지 않으면 `agent-roadmap/archive/**`를 읽지 않는다.
|
||||||
91
agent-ops/skills/common/check-roadmap-dependency/SKILL.md
Normal file
91
agent-ops/skills/common/check-roadmap-dependency/SKILL.md
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
---
|
||||||
|
name: check-roadmap-dependency
|
||||||
|
version: 1.2.0
|
||||||
|
description: roadmap dependency lock 상태를 확인한다. 사용자가 roadmap-dependency-checker.sh, locks.yaml, 외부 의존 잠금 충족 여부, unlock-ready 판별, 프로젝트 간 잠금 해제 조건 확인을 요청할 때 사용하며, 현재 Milestone이 locked 쪽인지 rely-on.target 쪽인지 양방향으로 판별한다.
|
||||||
|
---
|
||||||
|
|
||||||
|
# check-roadmap-dependency
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
`.agent-roadmap-sync/locks.yaml`에서 특정 lock `id`의 `locked`, `rely-on.target`, `rely-on.status`가 유효한지 확인하고, 모든 `rely-on.status`가 `enable`인지 판별한다.
|
||||||
|
lock id가 없으면 현재 Milestone identity가 `locked`에 있는지, `rely-on.target`에 있는지 모두 찾아 양방향으로 보고한다.
|
||||||
|
Milestone identity 역검색과 개별 lock 판별은 `agent-ops/bin/roadmap-dependency-checker.sh`에 맡기고, 스킬은 입력 확정, 실행, 결과 해석만 담당한다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 사용자가 특정 roadmap lock id의 의존 조건 충족 여부를 확인할 때
|
||||||
|
- runtime에서 unlock-ready 트리거 전 `locks.yaml` 판별 절차를 확인할 때
|
||||||
|
- `.agent-roadmap-sync/locks.yaml`의 `rely-on.status` 기반 true/false 확인을 요청할 때
|
||||||
|
- 사용자가 현재 Milestone이 다른 Milestone을 잠그는지 또는 다른 Milestone에 의해 잠겼는지 확인할 때
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `lock-id`: 확인할 lock entry id. 예: `oto:oto-agent-registration`. 명시되면 이 id만 판별한다 (선택)
|
||||||
|
- `target-milestone`: 확인할 Milestone path 또는 `<project>:agent-roadmap/phase/.../milestones/<slug>.md`. 없으면 현재 프로젝트 로컬 `current.md`의 활성 Milestone 단일 후보를 사용한다 (선택)
|
||||||
|
- `direction`: `locked` / `rely-on` / `both`. 기본값은 `both`다. `locked`는 대상 Milestone이 잠긴 entry만, `rely-on`은 대상 Milestone을 선행 조건으로 삼는 entry만 확인한다 (선택)
|
||||||
|
- `locks-file`: 기본값은 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`이며, 다른 파일을 검사할 때만 지정한다 (선택)
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] `agent-ops/bin/roadmap-dependency-checker.sh`가 있는지 확인한다.
|
||||||
|
- [ ] `lock-id`가 명시되었거나 `target-milestone` 또는 현재 프로젝트 로컬 `current.md`의 활성 Milestone 하나로 Milestone identity를 추론 가능한지 확인한다.
|
||||||
|
- [ ] 기본 경로 또는 지정된 `locks-file`을 읽을 수 있는지 확인한다.
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **입력 확정**
|
||||||
|
- 사용자 요청에서 `lock-id`를 추출한다.
|
||||||
|
- `locks-file`이 명시되지 않았으면 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`을 사용한다.
|
||||||
|
- `locks-file`이 없거나 읽을 수 없으면 결과를 `error`로 보고한다. 이를 미충족 의존성으로 해석하지 않는다.
|
||||||
|
- `lock-id`가 있으면 그 id만 판별한다.
|
||||||
|
- `lock-id`가 없으면 `target-milestone` 또는 현재 프로젝트 로컬 `agent-roadmap/current.md`의 활성 Milestone 단일 후보로 Milestone identity를 만든다.
|
||||||
|
- Milestone identity는 `<project>:agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 형식이다.
|
||||||
|
- `target-milestone`이 `agent-roadmap/...` 상대 경로이면 현재 프로젝트명을 prefix로 붙인다.
|
||||||
|
- `target-milestone`이 workspace 하위 절대/상대 경로이면 workspace 바로 아래 디렉터리명을 project로 삼고, 그 뒤 `agent-roadmap/...` 경로를 붙인다.
|
||||||
|
- `target-milestone`이 archive 경로이면 일반 의존 판별 후보로 쓰지 말고 사용자에게 활성 Milestone 선택을 요청한다.
|
||||||
|
- 활성 Milestone 후보가 없거나 둘 이상이면 추정하지 말고 사용자에게 lock id 또는 Milestone 선택을 요청한다.
|
||||||
|
- `lock-id`가 없으면 `agent-ops/bin/roadmap-dependency-checker.sh --find-milestone "<identity>" "<direction>" "<locks-file>"`로 Milestone identity와 일치하는 entry를 찾는다.
|
||||||
|
- find 출력의 `locked:<id>`는 locked entries로, `rely-on:<id>`는 rely-on entries로 분류한다.
|
||||||
|
- find 출력이 `none`이면 결과를 `error`가 아니라 `no-lock`으로 보고한다.
|
||||||
|
|
||||||
|
2. **판별 실행**
|
||||||
|
- 확인 대상 lock id마다 `agent-ops/bin/roadmap-dependency-checker.sh "<lock-id>" "<locks-file>"`를 실행한다.
|
||||||
|
- `locked` 방향의 결과는 대상 Milestone의 잠금 해제 조건 충족 여부다.
|
||||||
|
- `rely-on` 방향의 결과는 대상 Milestone이 완료될 때 영향을 받는 downstream lock의 현재 충족 여부다.
|
||||||
|
|
||||||
|
3. **결과 해석**
|
||||||
|
- stdout `true`와 exit code `0`은 모든 의존 조건 충족으로 보고한다.
|
||||||
|
- stdout `false`와 exit code `1`은 아직 충족되지 않은 의존 조건이 있음을 보고한다.
|
||||||
|
- exit code `2`는 설정 오류, 입력 오류, 필수 필드 누락, 파싱 오류로 보고한다.
|
||||||
|
- `rely-on` 방향에서 대상 Milestone이 `[검토중]` 또는 `[완료]`인데 status가 `disable`이면 `update-roadmap` 동기화가 필요한 stale lock으로 보고한다. 이 스킬은 status를 바꾸지 않는다.
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] 각 checker 실행의 stdout이 `true` 또는 `false` 하나로만 출력되었는가
|
||||||
|
- [ ] exit code `0`, `1`, `2` 의미를 구분해 보고했는가
|
||||||
|
- [ ] exit code `2`를 unlock 대기 상태로 해석하지 않았는가
|
||||||
|
- [ ] lock id가 없을 때 대상 Milestone을 `locked`와 `rely-on.target` 양쪽에서 찾았는가
|
||||||
|
- [ ] `locks.yaml`이 없는 경우 `false`가 아니라 `error`로 보고했는가
|
||||||
|
- [ ] 이 스킬이 `locks.yaml`이나 roadmap 문서를 수정하지 않았는가
|
||||||
|
- 검증 실패 시: 오류 메시지와 사용한 `lock-id`, `locks-file` 경로를 보고하고 멈춘다.
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 의존성 판별 결과
|
||||||
|
|
||||||
|
- target-milestone: `<identity | 해당 없음>`
|
||||||
|
- direction: `<locked | rely-on | both>`
|
||||||
|
- locks-file: `<locks-file>`
|
||||||
|
- 결과: `<true | false | error | no-lock>`
|
||||||
|
- locked entries: `<lock-id=result, ... | 없음>`
|
||||||
|
- rely-on entries: `<lock-id=result, ... | 없음>`
|
||||||
|
- 의미: <모든 의존 조건 충족 | 미충족 의존 조건 있음 | 설정/입력/필수 필드/파싱 오류 | 대상 Milestone 관련 lock 없음>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- `locks.yaml`의 `status`를 변경하지 않는다.
|
||||||
|
- roadmap Milestone의 `구현 잠금` 상태를 변경하지 않는다.
|
||||||
|
- `false`와 설정 오류를 같은 상태로 보고하지 않는다.
|
||||||
455
agent-ops/skills/common/code-review/SKILL.md
Normal file
455
agent-ops/skills/common/code-review/SKILL.md
Normal file
|
|
@ -0,0 +1,455 @@
|
||||||
|
---
|
||||||
|
name: code-review
|
||||||
|
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
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Review the implementation phase of the plan-code-review loop:
|
||||||
|
|
||||||
|
```text
|
||||||
|
plan skill -> implementation -> code-review skill
|
||||||
|
^ |
|
||||||
|
+----- issues found: new routed plan/review files
|
||||||
|
```
|
||||||
|
|
||||||
|
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 user-decision path: 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, 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. If it is a genuine user-only decision, user-owned external environment prerequisite, or scope conflict, the user-review gate triggers and this skill writes `USER_REVIEW.md`; if it is vague, unsupported, repo-fixable, 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, 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 for loop-limit exhaustion or user-owned blockers. Default to a normal WARN/FAIL follow-up; the gate requires positive evidence that another implementation/review agent cannot resolve the blocker without user action.
|
||||||
|
|
||||||
|
- Compute `review-number` as `count(agent-task/{task_name}/code_review_*.log) + 1` before archiving the active review.
|
||||||
|
- If `review-number >= 5` and the verdict is `WARN` or `FAIL`, stop the automatic loop and write `USER_REVIEW.md`.
|
||||||
|
- If `review-number == 1`, the verdict is `FAIL`, and the blocking issue is a test environment problem that requires user action rather than repo-owned setup or evidence a follow-up agent can produce by rerunning commands or collecting artifacts, stop the automatic loop and write `USER_REVIEW.md`.
|
||||||
|
- If the active review file has a filled `사용자 리뷰 요청` with `상태` other than `없음`, and the blocker is a user-only decision, user-owned external environment prerequisite, or scope conflict that the repository and a capable next agent cannot safely resolve by code changes or verification reruns, stop the automatic loop and write `USER_REVIEW.md`.
|
||||||
|
- If the active review file records a decision the implementer would otherwise ask as chat choices, treat it as an `implementation-blocked` user-review candidate when it has the required evidence and resume condition; do not ask that choice inline during review.
|
||||||
|
- Treat a first-review failure as a test environment problem only with evidence from an attempted command: missing SDK/tool/runtime, unavailable external service, absent secret/credential, unsupported OS/device/interactive environment, or another prerequisite outside the repository. Record the exact command and stdout/stderr. Before claiming a tool is missing, require `command -v <tool>` or the project-equivalent check. Missing or non-verbatim verification evidence is a verification-trust failure, not a test environment problem.
|
||||||
|
- Treat an implementation-owned `사용자 리뷰 요청` as valid only with specific decision questions, evidence, attempted commands/output or a reason commands could not run, and clear resume conditions. The not-run reason must identify user-owned action or an external prerequisite; agent execution limits, missing handoff evidence, or incomplete verification records become normal WARN/FAIL follow-up plans when a capable follow-up lane can produce the evidence.
|
||||||
|
- Do not classify repo-owned setup bugs or verification evidence gaps as environment problems. If a manifest, bootstrap script, test fixture, documented project entrypoint, or follow-up agent can provide the dependency or evidence, write a normal follow-up plan instead.
|
||||||
|
- `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, and user decision options.
|
||||||
|
|
||||||
|
## User Review Resolution
|
||||||
|
|
||||||
|
When an active `USER_REVIEW.md` exists and the user 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 user 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 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 user has completed and approved the task.
|
||||||
|
|
||||||
|
## Workflow Contract
|
||||||
|
|
||||||
|
Active work must live under an active task directory using routed filenames. This is the state protocol shared with the plan skill.
|
||||||
|
|
||||||
|
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`.
|
||||||
|
- Milestone-linked work uses the reserved task group form `m-<milestone-slug>`, where `<milestone-slug>` is the active Milestone filename without `.md`.
|
||||||
|
- `{subtask_dir}` is used only for split work and follows the indexed directory naming contract, such as `01_core` or `02+01_db`.
|
||||||
|
- `{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}/` is only the grouping folder and must not contain active plan/review files.
|
||||||
|
|
||||||
|
Filename rules:
|
||||||
|
|
||||||
|
- Plan file: `PLAN-{build_lane}-GNN.md`
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
Multi-plan runtime contract:
|
||||||
|
|
||||||
|
- Multi-plan work is represented as multiple subtask directories under one shared `{task_group}`. Each subtask directory owns exactly one normal active plan file and one normal active review file.
|
||||||
|
- Multi-plan subtask directory names encode runtime scheduling metadata:
|
||||||
|
- `NN_{subtask_name}` has no runtime dependencies.
|
||||||
|
- `NN+PP[,QQ...]_{subtask_name}` depends on the listed earlier task indices.
|
||||||
|
- Subtask directory names are the runtime dependency source of truth. Preserve them verbatim; do not normalize, reinterpret, infer extra dependencies from numeric order, or choose execution order by agent judgment.
|
||||||
|
- If the user/runtime names a task group, task path, or subtask directory that identifies exactly one active review file, review that directory even when other active review files exist.
|
||||||
|
|
||||||
|
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 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.
|
||||||
|
|
||||||
|
Review routing rules:
|
||||||
|
|
||||||
|
- Route reviews so a normal mixed backlog can use both lanes substantially. This is not a per-review quota; neither `local` nor `cloud` is the default catch-all.
|
||||||
|
- `local`: first-pass and review-detectable work, including multi-file or API/call-site reviews when scope and required context are bounded and verification can be rerun or reasoned about locally.
|
||||||
|
- `local-G01` through `local-G10` and `cloud-G01` through `cloud-G10` are valid. Do not treat high grade alone as an implicit cloud route; context volume is separate lane evidence.
|
||||||
|
- Repair non-behavioral review artifact drift during review instead of failing solely for it when implementation correctness, tests, and contracts remain judgeable.
|
||||||
|
- `cloud`: reviews requiring stronger-than-local judgment, larger-than-local context, or evidence recovery: weak verification that review cannot compensate for, security/auth, storage/migration, concurrency, protocol/schema, broad cross-domain behavior with hard-to-review failure modes, repeated non-trivial Required issues, or untrusted verification evidence.
|
||||||
|
- `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.
|
||||||
|
|
||||||
|
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` + `CODE_REVIEW-*-G??.md` with filled `사용자 리뷰 요청` | Implementation claims a user-only 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; user decision is required 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`) | Task terminated mid-loop or abandoned |
|
||||||
|
|
||||||
|
The implementing agent never archives or deletes active files; archiving is this skill's responsibility.
|
||||||
|
|
||||||
|
## Step 1 - Find Active Task
|
||||||
|
|
||||||
|
Find active review files with both globs, excluding `agent-task/archive/**`:
|
||||||
|
|
||||||
|
- `agent-task/*/CODE_REVIEW-*-G??.md`
|
||||||
|
- `agent-task/*/*/CODE_REVIEW-*-G??.md`
|
||||||
|
|
||||||
|
Also note active user-review stops, excluding `agent-task/archive/**`:
|
||||||
|
|
||||||
|
- `agent-task/*/USER_REVIEW.md`
|
||||||
|
- `agent-task/*/*/USER_REVIEW.md`
|
||||||
|
|
||||||
|
Classify the combined set of active `CODE_REVIEW-*-G??.md` and `USER_REVIEW.md` paths. Apply the first matching row:
|
||||||
|
|
||||||
|
| Result | Action |
|
||||||
|
|--------|--------|
|
||||||
|
| 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 user-supplied 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 user 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 ask which task to review or resolve; do not choose by agent judgment. |
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Step 2 - Load Context
|
||||||
|
|
||||||
|
Count `agent-task/{task_name}/code_review_*.log` in the selected active task directory:
|
||||||
|
|
||||||
|
- `0`: first review. Read the active review file, active plan file, every planned source file, related tests, and files importing/imported by changed files up to 2 levels deep.
|
||||||
|
- `>=1`: follow-up review. Start with `git diff`, `git diff --cached`, and `git log --oneline -5`, then expand to related callers, implementers, tests, and any planned files missing from the diff.
|
||||||
|
|
||||||
|
The diff is the starting point, not the boundary. Follow behavior and API connections far enough to judge correctness.
|
||||||
|
|
||||||
|
## Step 3 - Pre-Review Checklist
|
||||||
|
|
||||||
|
Before writing the verdict:
|
||||||
|
|
||||||
|
- Compare actual source files against every planned checklist item.
|
||||||
|
- Compare the plan `구현 체크리스트` and review stub `구현 체크리스트`; repair non-behavioral drift when implementation remains judgeable.
|
||||||
|
- 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 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.
|
||||||
|
- 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.
|
||||||
|
- 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.
|
||||||
|
- For follow-up reviews, compare diff against the plan and scan for unplanned changes, debug prints, dead code, TODOs, formatting-only noise, and unrelated edits.
|
||||||
|
|
||||||
|
## Step 4 - Append Verdict
|
||||||
|
|
||||||
|
Append `코드리뷰 결과` to the active `CODE_REVIEW-*-G??.md`.
|
||||||
|
|
||||||
|
Required fields:
|
||||||
|
|
||||||
|
- `종합 판정`: exactly `PASS`, `WARN`, or `FAIL`.
|
||||||
|
- `차원별 평가`: Pass/Warn/Fail for correctness, completeness, test coverage, API contract, code quality, plan deviation, verification trust.
|
||||||
|
- `발견된 문제`: `없음`, 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.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
| Verdict | Meaning | Follow-up plan |
|
||||||
|
|---------|---------|----------------|
|
||||||
|
| `PASS` | No Required/Suggested issues. Nit-only findings may still PASS. | No |
|
||||||
|
| `WARN` | One or more Suggested issues, zero Required. | Yes, unless the user-review gate triggers |
|
||||||
|
| `FAIL` | One or more Required issues. | Yes, unless the user-review gate triggers |
|
||||||
|
|
||||||
|
Issue severity:
|
||||||
|
|
||||||
|
- `Required`: correctness, API contract, missing required test, missing integrated verification, plan-completeness issue, or review artifact gaps that prevent judging implementation quality.
|
||||||
|
- `Suggested`: useful improvement that should enter the loop but does not block correctness.
|
||||||
|
- `Nit`: tiny cleanup; directly repair obvious non-behavioral cases when safe, otherwise record without forcing WARN.
|
||||||
|
|
||||||
|
Verdict consistency:
|
||||||
|
|
||||||
|
- `PASS` requires all dimensions to be Pass and no Required/Suggested issues. Nit-only findings may still PASS only when every dimension remains Pass.
|
||||||
|
- 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 - Archive Active Files
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
Archive order is fixed:
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
For `PASS`, write `agent-task/{task_name}/complete.log` before reporting. If a `USER_REVIEW.md` stop is resolved as complete/PASS, write the same `complete.log` before archiving that task.
|
||||||
|
|
||||||
|
Complete log template:
|
||||||
|
|
||||||
|
- Template path: `agent-ops/skills/common/code-review/templates/complete-log-template.md`
|
||||||
|
- Copy the template's section order and fill every placeholder from the archived plan/review logs and final verdict.
|
||||||
|
- 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.
|
||||||
|
- 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`, apply the user-review gate before writing follow-up files.
|
||||||
|
|
||||||
|
If the user-review gate triggers:
|
||||||
|
|
||||||
|
- Write `agent-task/{task_name}/USER_REVIEW.md` from `agent-ops/skills/common/code-review/templates/user-review-template.md`.
|
||||||
|
- Fill every placeholder. Use `loop-limit`, `environment-blocked`, or `implementation-blocked` 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 user 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; preserve the prior route when it was adequate. Raise `local-GNN` for explicit, deterministic, review-detectable follow-ups, but move `local -> cloud` when the failure exposes reasoning, risk, evidence, or context-volume gaps that local review should not own.
|
||||||
|
- 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.
|
||||||
|
- Before choosing the follow-up route, apply this escalation gate:
|
||||||
|
- If the archived plan was `local-*` and the verdict is `FAIL` for correctness, completeness, test coverage, or verification trust, keep the follow-up on `local` with a higher grade when the issue is explicit, deterministic, and review-detectable; move to `cloud` only when the failure shows local capability or evidence trust is likely insufficient.
|
||||||
|
- 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 `범위 결정 근거`.
|
||||||
|
|
||||||
|
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 user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||||
|
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||||
|
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||||
|
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||||
|
|
||||||
|
## 개요
|
||||||
|
|
||||||
|
date={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}
|
||||||
|
|
||||||
|
## 이 파일을 읽는 리뷰 에이전트에게
|
||||||
|
|
||||||
|
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||||
|
|
||||||
|
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||||
|
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||||
|
|
||||||
|
1. 판정을 append한다.
|
||||||
|
2. `CODE_REVIEW-{review_lane}-GNN.md` → `code_review_{review_lane}_GNN_N.log`, `PLAN-{build_lane}-GNN.md` → `plan_{build_lane}_GNN_M.log`로 아카이브한다.
|
||||||
|
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다. `USER_REVIEW.md`가 사용자 결정으로 완료/PASS 해소되면 `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가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||||
|
|
||||||
|
## 계획 대비 변경 사항
|
||||||
|
|
||||||
|
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||||
|
|
||||||
|
## 주요 설계 결정
|
||||||
|
|
||||||
|
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||||
|
|
||||||
|
## 사용자 리뷰 요청
|
||||||
|
|
||||||
|
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 사유 유형: 없음
|
||||||
|
- 결정 필요: 없음
|
||||||
|
- 차단 근거: 없음
|
||||||
|
- 실행한 검증/명령: 없음
|
||||||
|
- 자동 후속 불가 이유: 없음
|
||||||
|
- 재개 조건: 없음
|
||||||
|
|
||||||
|
## 리뷰어를 위한 체크포인트
|
||||||
|
|
||||||
|
{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`으로 복사 |
|
||||||
|
| 구현 항목별 완료 여부 (항목명) | 스텁 생성 시 고정 | `[ ]` → `[x]` 체크만 구현 에이전트가 수행 |
|
||||||
|
| 구현 체크리스트 (항목 텍스트/순서) | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 `[ ]` → `[x]` 체크만 수행; 마지막 체크박스는 저장 전 필수 |
|
||||||
|
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||||
|
| 계획 대비 변경 사항, 주요 설계 결정 | 구현 에이전트가 채움 | placeholder 텍스트를 실제 내용으로 교체 |
|
||||||
|
| 사용자 리뷰 요청 | 구현 에이전트가 채움 | 진행에 사용자 입력이 필요하지 않으면 `상태: 없음` 유지; 구현 중 직접 질문은 금지; 필요하면 결정 항목, 근거, 명령 출력, 자동 후속 불가 이유, 재개 조건을 기록 |
|
||||||
|
| 리뷰어를 위한 체크포인트 | 스텁 생성 시 고정 | 계획에서 추출한 리뷰 포인트 |
|
||||||
|
| 검증 결과 (섹션 제목 + 명령) | 스텁 생성 시 고정 | 실행 출력만 구현 에이전트가 채움; 명령 변경은 `계획 대비 변경 사항`에 기록 |
|
||||||
|
| 코드리뷰 결과 | 리뷰 에이전트가 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 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 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 user decides how to resume, replan, defer, or abandon the task.
|
||||||
|
- If `USER_REVIEW.md` is later resolved as complete/PASS by user 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}/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 `코드리뷰 전용 체크리스트`; 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`.
|
||||||
|
|
||||||
|
Report Required/Suggested counts, archive names, the final task archive path for `PASS`, the new plan path for normal `WARN`/`FAIL`, the `USER_REVIEW.md` path for user review stops, and any `m-*` runtime completion event metadata.
|
||||||
|
|
||||||
|
## Review Dimensions
|
||||||
|
|
||||||
|
| Dimension | Check |
|
||||||
|
|-----------|-------|
|
||||||
|
| Correctness | Logic, edge cases, concurrency, errors |
|
||||||
|
| Completeness | Planned implementation/verification items are done; review artifact drift is repaired when judgeable |
|
||||||
|
| Test coverage | Required tests present and meaningful |
|
||||||
|
| API contract | Call sites, compatibility, docs |
|
||||||
|
| Code quality | No debug prints, dead code, leftover TODOs |
|
||||||
|
| Plan deviation | Deviations justified, no unrelated risk |
|
||||||
|
| Verification trust | Reported output matches actual code |
|
||||||
|
|
||||||
|
## Quality Rules
|
||||||
|
|
||||||
|
- Lead with findings; use specific `file:line`.
|
||||||
|
- Provide a concrete fix for every Required issue.
|
||||||
|
- Name exact stale symbols or missing tests.
|
||||||
|
- Do not write vague praise or style opinions without a rule.
|
||||||
|
- Every dimension gets Pass/Warn/Fail.
|
||||||
|
- For follow-up plans about verification trust, specify deterministic commands, for example `rg --sort path`, and forbid repo-local tool artifacts.
|
||||||
|
|
||||||
|
## Final Checklist
|
||||||
|
|
||||||
|
- `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 `.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 without `Roadmap Targets`: `complete.log` omits `Roadmap Completion` and reported metadata says `roadmap-completion=none`.
|
||||||
|
- 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`.
|
||||||
|
- 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.
|
||||||
|
- Implementation-requested USER_REVIEW: archived review log preserves the filled `사용자 리뷰 요청` evidence and the generated `USER_REVIEW.md` records the exact user 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.
|
||||||
4
agent-ops/skills/common/code-review/agents/openai.yaml
Normal file
4
agent-ops/skills/common/code-review/agents/openai.yaml
Normal file
|
|
@ -0,0 +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 repository task, archive active files, and create complete.log, follow-up plan/review files, or USER_REVIEW.md."
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
# Complete - {task_name}
|
||||||
|
|
||||||
|
## 완료 일시
|
||||||
|
|
||||||
|
{YYYY-MM-DD or ISO-8601}
|
||||||
|
|
||||||
|
## 요약
|
||||||
|
|
||||||
|
{one-line task summary, loop count, and final verdict; include user-review resolution if applicable}
|
||||||
|
|
||||||
|
## 루프 이력
|
||||||
|
|
||||||
|
| 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` | user decision | PASS/RESOLVED | {only when a user-review stop was resolved as the terminal completion path; remove this row otherwise} |
|
||||||
|
|
||||||
|
## 구현/정리 내용
|
||||||
|
|
||||||
|
- {implemented or cleaned-up change}
|
||||||
|
|
||||||
|
## 최종 검증
|
||||||
|
|
||||||
|
- `{command}` - {PASS/FAIL/BLOCKED}; {actual output summary or saved output path}
|
||||||
|
|
||||||
|
## Roadmap Completion
|
||||||
|
|
||||||
|
{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}`
|
||||||
|
- Completed task ids:
|
||||||
|
- `{task-id}`: PASS; evidence=`{archived-plan-log}`, `{archived-review-log}`; verification=`{command or saved output path}`
|
||||||
|
- Not completed task ids: 없음
|
||||||
|
|
||||||
|
## 잔여 Nit
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 후속 작업
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
# User Review Required - {task_name}
|
||||||
|
|
||||||
|
## 요청 일시
|
||||||
|
|
||||||
|
{YYYY-MM-DD or ISO-8601}
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
USER_REVIEW
|
||||||
|
|
||||||
|
## 사유
|
||||||
|
|
||||||
|
- 유형: {loop-limit, environment-blocked, or implementation-blocked}
|
||||||
|
- 현재 리뷰 회차: {review-number}
|
||||||
|
- 최종 판정: {WARN or FAIL}
|
||||||
|
- 요약: {why automatic follow-up stopped}
|
||||||
|
|
||||||
|
## 루프 이력
|
||||||
|
|
||||||
|
| Plan | Review | Verdict | 메모 |
|
||||||
|
|------|--------|---------|------|
|
||||||
|
| `{plan-log-0}` | `{code-review-log-0}` | {PASS/WARN/FAIL/unknown} | {main issue or blocking reason} |
|
||||||
|
| `{current-archived-plan-log}` | `{current-archived-review-log}` | {WARN/FAIL} | {main issue or blocking reason} |
|
||||||
|
|
||||||
|
## 차단 근거
|
||||||
|
|
||||||
|
- 문제: {review finding summary}
|
||||||
|
- 현재 archive plan: `{current-archived-plan-log}`
|
||||||
|
- 현재 archive review: `{current-archived-review-log}`
|
||||||
|
- 검증 명령: `{command or 없음}`
|
||||||
|
- 실제 출력: {stdout/stderr excerpt or saved output path}
|
||||||
|
- 차단 판단 근거: {why this needs user decision or is outside repo-fixable scope, or 없음}
|
||||||
|
|
||||||
|
## 사용자 결정 필요
|
||||||
|
|
||||||
|
- [ ] 자동 follow-up plan/review를 계속 진행한다.
|
||||||
|
- [ ] 계획을 재작성한다.
|
||||||
|
- [ ] 테스트 환경, secret, 외부 서비스, SDK, 장비 조건을 준비한 뒤 재시도한다.
|
||||||
|
- [ ] 작업 범위를 줄이거나 보류/폐기한다.
|
||||||
|
|
||||||
|
## 재개 조건
|
||||||
|
|
||||||
|
- {what must be true before the next plan/review loop should start}
|
||||||
|
|
||||||
|
## 다음 실행 힌트
|
||||||
|
|
||||||
|
- {suggested command, task path, or user decision needed to resume}
|
||||||
|
|
||||||
|
## 종료 규칙
|
||||||
|
|
||||||
|
- 사용자가 이 stop state를 완료/PASS로 해소하면 `USER_REVIEW.md`를 해소 상태로 갱신하고, `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||||
|
- 새 구현이 필요하면 `plan` 스킬이 `USER_REVIEW.md`를 `user_review_N.log`로 아카이브한 뒤 새 `PLAN-*-G??.md` / `CODE_REVIEW-*-G??.md`를 작성한다.
|
||||||
162
agent-ops/skills/common/commit-push/SKILL.md
Normal file
162
agent-ops/skills/common/commit-push/SKILL.md
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
---
|
||||||
|
name: commit-push
|
||||||
|
version: 1.2.0
|
||||||
|
description: 변경 사항을 커밋하거나 원격에 푸시한다. "커밋해줘", "푸시해줘", "커밋하고 푸시", "올려줘" 요청 시 사용하며 명시된 푸시는 재확인 없이 수행한다.
|
||||||
|
---
|
||||||
|
|
||||||
|
# commit-push
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
현재 변경 내용을 분석하여 Conventional Commits 형식의 한국어 설명 커밋 메시지를 작성하고, 사용자가 요청한 커밋 또는 푸시를 수행한다.
|
||||||
|
일반적인 커밋/푸시는 승인 질문 없이 진행하고, 실제 위험 신호가 있을 때만 사용자 확인을 받는다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- "커밋해줘", "커밋하고 푸시해줘" 요청 시
|
||||||
|
- "변경 사항 올려줘", "푸시해줘" 요청 시
|
||||||
|
- 코드 작업 완료 후 "반영해줘", "올려줘" 요청 시
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `scope`: 커밋 범위 — all(전체) 또는 특정 파일/경로 (선택, 기본값: all)
|
||||||
|
- `push`: 푸시 여부 (선택, 기본값: auto)
|
||||||
|
- auto: 요청에 "푸시", "push", "올려줘", "반영해줘", "커밋하고 푸시"가 있으면 true, "커밋만" 또는 "푸시하지 마"가 있으면 false
|
||||||
|
- true: 푸시 여부를 다시 묻지 않고 현재 브랜치를 원격에 푸시한다
|
||||||
|
- false: 커밋만 수행하고 푸시는 생략한다
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] 커밋할 변경 사항 또는 push할 unpushed commit이 존재하는가 (`git status`로 확인)
|
||||||
|
- [ ] 현재 브랜치, 원격, upstream 상태가 일반 커밋/푸시에 적합한가
|
||||||
|
- [ ] `.env`, 시크릿 파일 등 민감한 파일이 스테이징에 포함되어 있지 않은가
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **변경 사항 파악**
|
||||||
|
- `git status`로 변경/추가/삭제된 파일 목록을 확인한다
|
||||||
|
- `git diff`로 구체적인 변경 내용을 확인한다
|
||||||
|
- 커밋할 변경 사항이 없고 push가 true이며 unpushed commit이 있으면 커밋 단계는 건너뛰고 푸시를 진행한다
|
||||||
|
- 커밋할 변경 사항도 없고 push할 unpushed commit도 없으면 사용자에게 알리고 종료한다
|
||||||
|
|
||||||
|
2. **민감 파일 검사**
|
||||||
|
- 스테이징 대상에 아래 패턴이 포함되면 해당 파일을 제외하고 사용자에게 경고한다
|
||||||
|
- `.env`, `.env.*`
|
||||||
|
- `*secret*`, `*credential*`, `*password*`
|
||||||
|
- `*.pem`, `*.key`, `*.p12`
|
||||||
|
- `.gitignore`에 이미 등록된 파일은 무시한다
|
||||||
|
|
||||||
|
3. **커밋 메시지 작성**
|
||||||
|
- 변경 내용을 분석하여 Conventional Commits 형식으로 커밋 메시지를 작성한다
|
||||||
|
- 아래 메시지 규칙을 따른다
|
||||||
|
|
||||||
|
4. **위험 신호 판단**
|
||||||
|
- 아래 위험 신호가 없으면 사용자 승인 없이 다음 단계로 진행한다
|
||||||
|
- 위험 신호가 있으면 커밋/푸시를 멈추고 대상 파일, 커밋 메시지, 위험 내용을 짧게 보여준 뒤 사용자 확인을 받는다
|
||||||
|
- 민감 파일 패턴이 스테이징 대상에 포함됨
|
||||||
|
- 사용자가 지정한 scope 밖의 변경을 포함해야 함
|
||||||
|
- 현재 브랜치가 사용자 요청이나 작업 맥락과 다를 가능성이 큼
|
||||||
|
- merge/rebase 충돌, detached HEAD, git 작업 중 상태가 감지됨
|
||||||
|
- 원격이 diverged 상태거나 일반 push가 실패해 force push가 필요해 보임
|
||||||
|
- 사용자가 메시지 수정을 요청하면 반영한다
|
||||||
|
|
||||||
|
5. **커밋 실행**
|
||||||
|
- 커밋할 변경 사항이 없고 push할 unpushed commit만 있으면 이 단계를 건너뛴다
|
||||||
|
- scope에 따라 파일을 스테이징한다
|
||||||
|
- all: 변경된 전체 파일을 개별적으로 `git add`
|
||||||
|
- 특정 경로: 해당 파일만 `git add`
|
||||||
|
- 작성한 메시지로 `git commit`을 실행한다
|
||||||
|
|
||||||
|
6. **푸시 실행**
|
||||||
|
- push가 true인 경우에만 실행한다
|
||||||
|
- 사용자가 푸시를 명시했으면 푸시 여부를 다시 묻지 않는다
|
||||||
|
- 현재 브랜치를 원격에 푸시한다
|
||||||
|
- 원격 브랜치가 없으면 `-u origin {branch}`로 설정한다
|
||||||
|
- 일반 push가 실패하거나 충돌이 발생하면 사용자에게 알리고 중단한다
|
||||||
|
- `--force`가 필요해 보여도 자동 실행하지 않고 사용자 확인을 받는다
|
||||||
|
|
||||||
|
7. **결과 보고**
|
||||||
|
- 커밋 해시, 메시지, 변경 파일 수, 푸시 결과를 출력한다
|
||||||
|
|
||||||
|
## 커밋 메시지 규칙
|
||||||
|
|
||||||
|
### 형식
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>(<scope>): <한국어 서술형 요약>
|
||||||
|
|
||||||
|
<왜 변경했는지 설명하는 한국어 본문> (선택)
|
||||||
|
|
||||||
|
<footer> (선택)
|
||||||
|
```
|
||||||
|
|
||||||
|
`scope`는 선택 사항이며 변경 영역을 짧은 ASCII 토큰으로 쓴다. 예: `agent-ops`, `sync`, `docs`, `api`
|
||||||
|
|
||||||
|
### type 목록
|
||||||
|
|
||||||
|
| type | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| feat | 새로운 기능 추가 |
|
||||||
|
| fix | 버그 수정 |
|
||||||
|
| docs | 문서 추가/수정 |
|
||||||
|
| refactor | 동작 변화 없는 구조 개선 |
|
||||||
|
| test | 테스트 추가/수정 |
|
||||||
|
| chore | 잡무성 변경, 저장소 관리 |
|
||||||
|
| build | 빌드, 패키징, 의존성 변경 |
|
||||||
|
| ci | CI/CD 설정 변경 |
|
||||||
|
| perf | 성능 개선 |
|
||||||
|
| revert | 이전 커밋 되돌림 |
|
||||||
|
|
||||||
|
### 작성 원칙
|
||||||
|
|
||||||
|
- `type`과 `scope`는 Conventional Commits 호환을 위해 영어 ASCII 토큰을 사용한다
|
||||||
|
- 요약과 본문은 **한국어**로 작성한다
|
||||||
|
- 요약은 50자 이내로 간결하게 작성한다
|
||||||
|
- 요약은 "~한다" 형태의 서술형으로 끝낸다 (예: "로그인 검증 로직을 추가한다")
|
||||||
|
- 본문은 **무엇을** 변경했는지가 아니라 **왜** 변경했는지를 쓴다
|
||||||
|
- 변경 파일이 3개 이하이면 본문을 생략할 수 있다
|
||||||
|
- 여러 성격의 변경이 섞여 있으면 가장 핵심적인 변경을 기준으로 타입을 정한다
|
||||||
|
- 이슈, PR, 작업 ID가 있으면 footer에 `Refs: #123`, `Closes: #123`처럼 남긴다
|
||||||
|
- breaking change는 `type(scope)!:` 또는 footer의 `BREAKING CHANGE:`로 표시한다
|
||||||
|
|
||||||
|
### 예시
|
||||||
|
|
||||||
|
```text
|
||||||
|
docs(commit-push): 푸시 승인 조건을 명시한다
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
fix(sync): unpushed commit 푸시 흐름을 보강한다
|
||||||
|
|
||||||
|
작업 트리에 변경이 없어도 로컬 커밋이 원격보다 앞서 있으면
|
||||||
|
커밋 단계를 건너뛰고 푸시해야 한다.
|
||||||
|
```
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```
|
||||||
|
## 커밋 완료
|
||||||
|
|
||||||
|
- 브랜치: {브랜치명}
|
||||||
|
- 커밋: {해시} — {커밋 메시지 요약}
|
||||||
|
- 변경 파일: {n}개
|
||||||
|
- {파일 경로}: {변경 유형}
|
||||||
|
- 푸시: {성공/생략/실패}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] `git log -1`로 방금 생성한 커밋이 존재하고, 메시지가 작성한 내용과 일치하는가
|
||||||
|
- [ ] 커밋에 포함된 파일 목록이 의도한 scope와 일치하는가 (`git diff-tree --no-commit-id --name-only -r HEAD`)
|
||||||
|
- [ ] push가 true인 경우, `git status`에서 "Your branch is up to date" 또는 원격과 동기화 상태인가
|
||||||
|
- 검증 실패 시: 실패 원인(커밋 누락, 푸시 실패 등)을 사용자에게 알리고 재시도 여부를 확인한다
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- `git add -A` 또는 `git add .`을 사용하지 않는다 (민감 파일 혼입 방지)
|
||||||
|
- `git push --force`를 사용하지 않는다
|
||||||
|
- 명시적인 커밋/푸시 요청이 있고 위험 신호가 없는데도 습관적으로 사용자 승인을 요구하지 않는다
|
||||||
|
- 위험 신호를 무시하고 커밋하거나 푸시하지 않는다
|
||||||
|
- `type`과 `scope`를 제외한 요약/본문을 영어로 작성하지 않는다
|
||||||
|
- 변경 내용과 무관한 커밋 메시지를 작성하지 않는다
|
||||||
|
- `--no-verify` 옵션을 사용하지 않는다
|
||||||
120
agent-ops/skills/common/create-domain-rule/SKILL.md
Normal file
120
agent-ops/skills/common/create-domain-rule/SKILL.md
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
---
|
||||||
|
name: create-domain-rule
|
||||||
|
version: 1.0.0
|
||||||
|
description: 새로운 도메인 rules.md 파일을 생성하기 위한 범용 스킬
|
||||||
|
---
|
||||||
|
|
||||||
|
# Create Domain Rule
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
`agent-ops/rules/project/domain/<domain-name>/rules.md` 파일을 올바른 형식으로 생성한다.
|
||||||
|
실제 프로젝트 폴더 구조를 분석하여 경로와 구성 요소를 자동으로 채운다.
|
||||||
|
생성 후 `rules/project/rules.md`의 도메인 룰 로딩 안내와 도메인 매핑 테이블을 갱신한다.
|
||||||
|
생성한 domain rule에는 현재 코드 상태를 어디까지 반영했는지 알 수 있도록 기준 커밋 메타데이터를 기록한다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 새로운 도메인 영역의 코드를 처음 변경하기 전에
|
||||||
|
- 기존 domain rule이 없는 경로에 대해 규칙이 필요할 때
|
||||||
|
- 사용자가 특정 도메인의 rule 파일을 만들어 달라고 요청할 때
|
||||||
|
- agent-ops 초기 scaffold 이후 도메인을 추가 확장할 때
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `domain-name`: 생성할 도메인 이름, kebab-case (필수)
|
||||||
|
- `domain-type`: `core` / `supporting` / `generic` 중 하나 (필수)
|
||||||
|
- `path-hints`: 이 도메인에 해당하는 경로 힌트 목록 (선택, 없으면 자동 탐색)
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] `agent-ops/rules/project/domain/<domain-name>/rules.md` 가 이미 존재하는지 확인
|
||||||
|
- [ ] `agent-ops/rules/common/_templates/domain-rule-template.md` 를 읽어 최신 템플릿 형식 파악
|
||||||
|
- [ ] `agent-ops/rules/project/domain/` 하위 기존 domain rule 목록을 확인하여 중복·유사 도메인 여부 판단
|
||||||
|
- [ ] `git rev-parse HEAD` 로 기준 커밋을 확인
|
||||||
|
- 이 값은 생성될 rules.md를 포함하는 미래 커밋 해시가 아니다
|
||||||
|
- 의미: "이 커밋까지의 코드 상태를 보고 domain rule을 생성했다"
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **중복 확인**
|
||||||
|
- `agent-ops/rules/project/domain/<domain-name>/` 폴더 존재 여부 확인
|
||||||
|
- 책임이 겹치는 기존 domain rule 이 있으면 사용자에게 알리고 중단한다
|
||||||
|
|
||||||
|
2. **경로 탐색**
|
||||||
|
- `path-hints` 가 제공된 경우: 해당 경로를 기준으로 폴더 구조 확인
|
||||||
|
- `path-hints` 가 없는 경우: `domain-name` 과 연관된 폴더명·파일명으로 프로젝트를 탐색
|
||||||
|
- 실제로 존재하는 경로만 포함 경로에 기재한다
|
||||||
|
- 존재하지 않는 경로는 기재하지 않는다
|
||||||
|
|
||||||
|
3. **도메인 분석**
|
||||||
|
- 탐색된 경로의 주요 파일·모듈을 읽어 아래를 도출한다
|
||||||
|
- 도메인의 목적 / 책임 한 줄 요약
|
||||||
|
- 포함 경로 목록
|
||||||
|
- 제외 경로 (인접 도메인과 겹칠 수 있는 경로)
|
||||||
|
- 주요 구성 요소 (파일, 모듈, 클래스, 함수 등)
|
||||||
|
- 유지할 패턴 (네이밍 규칙, 아키텍처 패턴 등)
|
||||||
|
- 다른 도메인과의 경계
|
||||||
|
- 금지 사항
|
||||||
|
|
||||||
|
4. **도메인 rules.md 생성**
|
||||||
|
- 경로: `agent-ops/rules/project/domain/<domain-name>/rules.md`
|
||||||
|
- `domain-rule-template.md` 형식을 따른다
|
||||||
|
- frontmatter의 `last_rule_review_commit`에는 생성 직전에 확인한 `git rev-parse HEAD` 값을 기록한다
|
||||||
|
- frontmatter의 `last_rule_updated_at`에는 생성일을 `YYYY-MM-DD` 형식으로 기록한다
|
||||||
|
- 실제 코드에서 확인된 내용만 기재한다
|
||||||
|
- 불확실한 항목은 `<!-- TODO: 확인 필요 -->` 주석으로 남긴다
|
||||||
|
|
||||||
|
5. **rules/project/rules.md 업데이트**
|
||||||
|
- `agent-ops/rules/project/rules.md` 를 읽는다
|
||||||
|
- `## 도메인 룰 로딩` 섹션이 없으면 `## 도메인 매핑` 바로 위에 아래 형식으로 추가한다
|
||||||
|
```
|
||||||
|
## 도메인 룰 로딩
|
||||||
|
|
||||||
|
- 아래 도메인 매핑에 해당하는 작업에서 해당 domain 최초 진입 시 domain rule을 1회 읽는다.
|
||||||
|
- 이미 읽은 domain rule은 같은 세션에서 반복해서 읽지 않는다.
|
||||||
|
```
|
||||||
|
- 도메인 매핑 테이블에 아래 형식으로 추가한다
|
||||||
|
```
|
||||||
|
| `<path-pattern>` | <domain-name> | `agent-ops/rules/project/domain/<domain-name>/rules.md` |
|
||||||
|
```
|
||||||
|
- 경로 패턴은 실제 포함 경로를 기준으로 작성한다
|
||||||
|
- 기존 로딩 섹션과 테이블 항목을 삭제하거나 재정렬하지 않는다
|
||||||
|
|
||||||
|
6. **결과 보고**
|
||||||
|
- 생성한 파일 경로
|
||||||
|
- rules/project/rules.md 에 추가한 항목
|
||||||
|
- 불확실하여 TODO로 남긴 항목 (해당 시)
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```
|
||||||
|
## 생성 완료
|
||||||
|
|
||||||
|
- Domain Rule 경로: agent-ops/rules/project/domain/<domain-name>/rules.md
|
||||||
|
- 도메인 유형: <core | supporting | generic>
|
||||||
|
- 도메인 룰 로딩 섹션: <추가함 | 이미 존재함>
|
||||||
|
- rules/project/rules.md 추가 경로 패턴: <path-pattern>
|
||||||
|
|
||||||
|
## TODO 항목 (확인 필요)
|
||||||
|
- <불확실하여 직접 확인이 필요한 항목> (해당 시)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] `agent-ops/rules/project/domain/<domain-name>/rules.md` 파일이 생성되었는가
|
||||||
|
- [ ] 생성된 파일이 `domain-rule-template.md`의 frontmatter와 모든 섹션(목적, 포함 경로, 제외 경로, 주요 구성 요소, 유지할 패턴, 경계, 금지 사항)을 포함하는가
|
||||||
|
- [ ] `last_rule_review_commit`이 생성 직전 `HEAD`를 가리키는가
|
||||||
|
- [ ] `rules/project/rules.md`에 도메인 룰 로딩 섹션이 존재하는가
|
||||||
|
- [ ] `rules/project/rules.md`의 도메인 매핑 테이블에 해당 도메인 항목이 추가되었는가
|
||||||
|
- [ ] 포함 경로에 기재된 경로가 실제로 프로젝트에 존재하는가
|
||||||
|
- 검증 실패 시: 누락된 섹션 또는 잘못된 경로를 사용자에게 알리고 해당 부분만 보완한다
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 이미 존재하는 rules.md 를 덮어쓰지 않는다
|
||||||
|
- 실제 존재하지 않는 경로를 포함 경로에 넣지 않는다
|
||||||
|
- 추측으로 패턴이나 금지 사항을 채우지 않는다 — 확인된 내용만 기재한다
|
||||||
|
- rules/project/rules.md 의 기존 로딩 섹션과 테이블 항목을 삭제하거나 재정렬하지 않는다
|
||||||
|
- 하나의 domain rule 에 여러 독립 도메인의 책임을 묶지 않는다
|
||||||
|
- 코드 변경을 수행하지 않는다 — 이 skill 은 rule 파일 생성만 담당한다
|
||||||
156
agent-ops/skills/common/create-readme/SKILL.md
Normal file
156
agent-ops/skills/common/create-readme/SKILL.md
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
---
|
||||||
|
name: create-readme
|
||||||
|
version: 1.1.0
|
||||||
|
description: README 작성, README 생성, 프로젝트 설명 문서 작성 요청에 대해 사람이 읽기 쉽고 AI가 다음 작업에 바로 활용할 수 있는 표준형 README.md를 생성하는 공통 스킬
|
||||||
|
---
|
||||||
|
|
||||||
|
# README 생성
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
프로젝트 루트의 `README.md`를 표준형으로 작성한다.
|
||||||
|
README는 사람에게 프로젝트의 목적과 사용법을 설명하면서, AI 에이전트가 다음 작업에서 빠르게 맥락을 파악하고 실행할 수 있는 작업 안내 문서가 되도록 구성한다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 사용자가 "README 작성해줘", "README 만들어줘", "프로젝트 설명 문서 만들어줘"라고 요청할 때
|
||||||
|
- 프로젝트 루트에 `README.md`가 없거나 내용이 비어 있을 때
|
||||||
|
- 기존 README가 제품 설명, 실행 방법, 구조, 검증 명령을 충분히 담지 못해 초기 정리가 필요할 때
|
||||||
|
- AI 에이전트가 프로젝트를 이어서 작업할 수 있도록 핵심 맥락을 한 문서에 모아야 할 때
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `project-name`: README에 사용할 프로젝트 이름 (선택, 없으면 repo 이름 또는 package metadata에서 추론)
|
||||||
|
- `audience`: 주요 독자 또는 사용자 (선택)
|
||||||
|
- `purpose`: 프로젝트 목적 한 줄 요약 (선택)
|
||||||
|
- `scope`: README에 포함할 범위 또는 제외할 범위 (선택)
|
||||||
|
- `overwrite`: 기존 README 덮어쓰기 허용 여부 (선택, 명시 없으면 덮어쓰지 않음)
|
||||||
|
|
||||||
|
## README 표준 구성
|
||||||
|
|
||||||
|
README는 프로젝트 특성에 맞게 필요한 섹션만 사용하되, 기본 순서는 아래를 따른다.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# <project-name>
|
||||||
|
|
||||||
|
<프로젝트 목적 1~3문장>
|
||||||
|
|
||||||
|
## 현재 상태
|
||||||
|
|
||||||
|
<개발 단계, 사용 가능 범위, 중요한 제약>
|
||||||
|
|
||||||
|
## 빠른 시작
|
||||||
|
|
||||||
|
<설치, 실행, 테스트의 최소 명령>
|
||||||
|
|
||||||
|
## 주요 명령
|
||||||
|
|
||||||
|
| 목적 | 명령 | 비고 |
|
||||||
|
|------|------|------|
|
||||||
|
|
||||||
|
## 구조
|
||||||
|
|
||||||
|
| 경로 | 역할 |
|
||||||
|
|------|------|
|
||||||
|
|
||||||
|
## 작업 맥락
|
||||||
|
|
||||||
|
<AI가 다음 작업에서 먼저 알아야 할 규칙, 문서, 로드맵, 주요 경계>
|
||||||
|
|
||||||
|
## 개발 흐름
|
||||||
|
|
||||||
|
<브랜치, 테스트, 검증, 리뷰 또는 배포 흐름>
|
||||||
|
|
||||||
|
## 환경 변수
|
||||||
|
|
||||||
|
| 이름 | 설명 | 필수 |
|
||||||
|
|------|------|------|
|
||||||
|
|
||||||
|
## 참고 문서
|
||||||
|
|
||||||
|
- <관련 문서 경로>
|
||||||
|
```
|
||||||
|
|
||||||
|
## AI-first 작성 기준
|
||||||
|
|
||||||
|
- README 상단에는 프로젝트가 무엇을 해결하는지와 현재 사용할 수 있는 범위를 먼저 쓴다.
|
||||||
|
- AI가 작업을 이어받을 때 필요한 경로, 명령, 검증 방법, 주요 문서를 명확한 제목과 표로 정리한다.
|
||||||
|
- `agent-ops/`가 있으면 규칙, 로드맵, 스킬 문서를 참고 문서나 작업 맥락에 연결한다.
|
||||||
|
- 로컬 `agent-roadmap/current.md`가 있으면 README에 현재 작업 위치를 복사하지 말고, 로드맵을 확인할 문서 경로만 적는다.
|
||||||
|
- README는 제품 소개 문서이면서 작업 진입점이다. 마케팅 문구보다 실행 가능한 정보와 프로젝트 경계를 우선한다.
|
||||||
|
- README의 자연어 설명은 한국어 중심으로 작성한다.
|
||||||
|
- 단, README, API, CLI, SDK, runtime, build, test, lint, deploy, workflow, migration, integration처럼 개발자가 흔히 쓰는 영어 표현과 제품명, 기술명, 패키지명, 명령, 경로, 코드 식별자는 자연스럽게 영어로 유지한다.
|
||||||
|
- 널리 쓰이는 기술 영어를 억지로 번역하지 말고, 사람과 AI가 함께 읽기 쉬운 표현을 우선한다.
|
||||||
|
- 불확실한 내용은 단정하지 않고 `TODO` 또는 "확인 필요"로 남긴다.
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] 루트 `README.md` 존재 여부와 기존 내용 확인
|
||||||
|
- [ ] `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `Makefile`, `docker-compose.yml` 등 실행/검증 명령 근거 확인
|
||||||
|
- [ ] `agent-ops/rules/project/rules.md`가 있으면 프로젝트 개요, 기술 스택, 도메인 매핑 확인
|
||||||
|
- [ ] `agent-roadmap/ROADMAP.md` 또는 로컬 `agent-roadmap/current.md`가 있으면 제품 방향과 활성 Milestone 문서 경로만 확인
|
||||||
|
- [ ] 주요 소스 디렉터리와 테스트 디렉터리를 `rg --files`로 가볍게 확인
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **기존 README 처리 결정**
|
||||||
|
- `README.md`가 없으면 새로 생성한다.
|
||||||
|
- `README.md`가 있고 사용자가 덮어쓰기를 명시하지 않았으면 기존 내용을 보존하고, 필요한 섹션만 보완한다.
|
||||||
|
- 기존 README의 제품 설명, 설치/실행 명령, 경고, 라이선스, 배포 정보를 삭제하지 않는다.
|
||||||
|
|
||||||
|
2. **프로젝트 근거 수집**
|
||||||
|
- metadata 파일에서 프로젝트 이름, 설명, scripts, dependencies, runtime을 확인한다.
|
||||||
|
- Makefile, compose 파일, CI 설정, 테스트 설정에서 실행 명령과 검증 명령을 확인한다.
|
||||||
|
- 소스 구조는 전체 정독하지 않고 README 작성에 필요한 상위 경로와 대표 진입점만 확인한다.
|
||||||
|
- 명령을 추론해야 하면 "추정"으로 쓰지 말고 TODO로 남긴다.
|
||||||
|
|
||||||
|
3. **README 초안 작성**
|
||||||
|
- 표준 구성 순서를 기준으로 프로젝트에 맞는 섹션을 선택한다.
|
||||||
|
- 빠른 시작에는 최소 실행 경로를 짧게 쓴다.
|
||||||
|
- 주요 명령 표에는 실제로 확인한 명령만 넣는다.
|
||||||
|
- 구조 표에는 AI가 작업 범위를 잡는 데 도움이 되는 경로만 넣는다.
|
||||||
|
- 작업 맥락에는 agent-ops 문서, 로드맵, 도메인 규칙, 중요한 작업 경계를 연결한다.
|
||||||
|
|
||||||
|
4. **기존 내용 병합**
|
||||||
|
- 기존 README가 있으면 중복 섹션을 합치고 정보가 더 정확한 쪽을 남긴다.
|
||||||
|
- 확인 근거가 없는 오래된 내용은 삭제하지 말고 "확인 필요"로 표시한다.
|
||||||
|
- 문서의 제목, 명령, 경로 표기가 실제 파일과 맞는지 확인한다.
|
||||||
|
|
||||||
|
5. **결과 보고**
|
||||||
|
- 생성 또는 수정한 README 경로
|
||||||
|
- 확인한 실행/테스트 명령
|
||||||
|
- TODO 또는 확인 필요로 남긴 항목
|
||||||
|
- 덮어쓰지 않고 보존한 기존 주요 내용
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] 루트 `README.md`가 존재하는가
|
||||||
|
- [ ] 프로젝트 목적, 빠른 시작, 주요 명령, 구조, 작업 맥락 중 프로젝트에 필요한 섹션이 포함되어 있는가
|
||||||
|
- [ ] README에 적은 명령이 실제 설정 파일 또는 프로젝트 관례에서 확인된 명령인가
|
||||||
|
- [ ] README에 적은 경로가 실제로 존재하는가
|
||||||
|
- [ ] agent-ops 문서를 복사해 중복하지 않고 필요한 경로만 연결했는가
|
||||||
|
- [ ] 불확실한 내용이 단정 표현이 아니라 TODO 또는 확인 필요로 남아 있는가
|
||||||
|
- 검증 실패 시: README의 해당 항목만 보완하고, 근거 없는 내용을 새로 만들지 않는다.
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## README 작성 완료
|
||||||
|
|
||||||
|
- README: README.md
|
||||||
|
- 처리 방식: <생성 | 보완 | 재작성>
|
||||||
|
- 확인한 명령:
|
||||||
|
- <command>
|
||||||
|
|
||||||
|
## 확인 필요
|
||||||
|
|
||||||
|
- <TODO 또는 확인 필요 항목> (해당 시)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 사용자가 명시하지 않은 상태에서 기존 README를 통째로 덮어쓰지 않는다.
|
||||||
|
- 확인하지 않은 설치, 실행, 테스트, 배포 명령을 사실처럼 쓰지 않는다.
|
||||||
|
- README를 긴 내부 설계 문서로 만들지 않는다. 상세 규칙은 `agent-ops/` 문서로 연결한다.
|
||||||
|
- README에 개인 설정, 비밀값, 로컬 전용 경로를 넣지 않는다.
|
||||||
|
- 로드맵이나 도메인 규칙 내용을 README에 길게 복사하지 않는다.
|
||||||
179
agent-ops/skills/common/create-roadmap/SKILL.md
Normal file
179
agent-ops/skills/common/create-roadmap/SKILL.md
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
---
|
||||||
|
name: create-roadmap
|
||||||
|
version: 1.15.0
|
||||||
|
description: AI-first 개인/소규모 프로젝트의 전체 목표, Phase scaffold, Phase 하위 Milestone 문서, 로컬 current.md 활성 Phase/Milestone 창, archive Phase scaffold를 처음 생성하는 공통 스킬
|
||||||
|
---
|
||||||
|
|
||||||
|
# 로드맵 생성
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
`agent-roadmap/` 하위에 `Roadmap -> Phase -> Milestone` 기반 한국어 로드맵 구조를 처음 생성한다.
|
||||||
|
전체 로드맵은 전체 방향과 Phase index만 담당하고, 일반 작업에서는 브랜치별 로컬 `current.md`의 활성 Phase/Milestone 링크와 관련 문서만 읽도록 만든다.
|
||||||
|
Milestone은 구현 계획이 아니라 방향성, 범위, 위험, 확인 필요 사항을 기록하는 협업 문서다.
|
||||||
|
Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능` 안에서 관리한다. 별도 `완료 기준` 섹션은 만들지 않고, 검증이 필요한 기능에만 같은 Task 안의 `검증:` 문구로 통합한다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 프로젝트에 파일 기반 로드맵을 처음 만들 때
|
||||||
|
- 사용자가 "로드맵 만들어줘", "마일스톤 설계해줘", "goal/phase 구조 잡아줘"라고 요청할 때
|
||||||
|
- 기존 README나 메모에 흩어진 계획을 `agent-roadmap/` 구조로 분리할 때
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `overall-goal`: 프로젝트 전체 목표 한 줄 또는 짧은 문단 (선택, 없으면 README와 현재 구조에서 추론)
|
||||||
|
- `phase-hints`: 예상 Phase 목록 또는 단계 힌트 (선택)
|
||||||
|
- `milestone-hints`: 예상 Milestone 목록 또는 기능 힌트 (선택)
|
||||||
|
- `active-phases`: 현재 열어둘 Phase 목록 (선택, 없으면 현재 구현 상태와 요청에서 추론)
|
||||||
|
- `active-milestones`: 현재 열어둘 Milestone 목록 (선택, 없으면 현재 구현 상태와 요청에서 추론)
|
||||||
|
|
||||||
|
## 생성 구조
|
||||||
|
|
||||||
|
```text
|
||||||
|
agent-roadmap/
|
||||||
|
ROADMAP.md
|
||||||
|
current.md # local, git ignored
|
||||||
|
phase/
|
||||||
|
<phase-slug>/
|
||||||
|
PHASE.md
|
||||||
|
milestones/
|
||||||
|
<milestone-slug>.md
|
||||||
|
archive/
|
||||||
|
phase/
|
||||||
|
<phase-slug>/
|
||||||
|
PHASE.md
|
||||||
|
milestones/
|
||||||
|
<milestone-slug>.md
|
||||||
|
```
|
||||||
|
|
||||||
|
| 파일 | 역할 |
|
||||||
|
|------|------|
|
||||||
|
| `agent-roadmap/ROADMAP.md` | 전체 목표와 Phase 흐름만 담는 최상위 지도. 로드맵 생성/갱신/Phase 전환 때만 읽는다 |
|
||||||
|
| `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 체크리스트, 범위 제외 항목 |
|
||||||
|
| `agent-roadmap/archive/phase/<phase-slug>/...` | 완료 또는 폐기되어 현재 후보에서 제외한 과거 Phase/Milestone. 일반 작업에서는 읽지 않는다 |
|
||||||
|
|
||||||
|
## 템플릿
|
||||||
|
|
||||||
|
- `ROADMAP.md`는 `agent-ops/skills/common/_templates/roadmap-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` 형식을 따른다.
|
||||||
|
- `ROADMAP.md`에는 Milestone 상세 체크리스트를 넣지 않는다.
|
||||||
|
- `current.md`는 git 추적 대상이 아니며, 예시 파일을 `agent-roadmap/`에 따로 만들지 않는다.
|
||||||
|
- `current.md`는 활성 Phase/Milestone 후보만 담고, 개인별 현재 작업 위치나 완료 상태를 적지 않는다.
|
||||||
|
- archive 경로는 `current.md`의 활성 항목에 넣지 않는다.
|
||||||
|
|
||||||
|
## 작성 규칙
|
||||||
|
|
||||||
|
- 기본 작성 언어는 한국어다.
|
||||||
|
- 상태 표기는 `[스케치]`, `[계획]`, `[진행중]`, `[검토중]`, `[완료]`, `[보류]`, `[폐기]` 중 하나만 사용한다.
|
||||||
|
- `[스케치]`는 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태다. 구현 가능한 계획이 아니므로 구현 계획 생성 대상이 아니다.
|
||||||
|
- `[계획]`은 목표, 범위, 기능 Task, 구현 잠금, 결정 필요 항목이 정리되어 구현 계획을 만들 수 있는 상태다.
|
||||||
|
- Phase와 Milestone 이름, 파일명에는 `1`, `2`, `M01`, `P1` 같은 순번을 붙이지 않는다.
|
||||||
|
- 진행 순서는 `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을 끼워 넣을 수 있도록 기존 항목의 이름과 파일명을 불필요하게 바꾸지 않는다.
|
||||||
|
|
||||||
|
## Milestone 작성 규칙
|
||||||
|
|
||||||
|
- Milestone 기본 섹션은 `위치`, `목표`, `상태`, `구현 잠금`, `범위`, `기능`, `완료 리뷰`, `범위 제외`, `작업 컨텍스트`다.
|
||||||
|
- `승격 조건`은 `[스케치]` Milestone에서 필수다. `[계획]` 이상 상태에서는 섹션을 생략하거나 `- 없음`으로 둘 수 있다.
|
||||||
|
- `[스케치]` Milestone은 `승격 조건`을 체크리스트로 작성하고, `[계획]`으로 전환하기 위해 필요한 정의, 결정, 경계, 후속 구현 Milestone 후보를 적는다.
|
||||||
|
- 새 Milestone은 사용자만 결정할 수 있는 제품 방향, 범위, 우선순위, 책임 경계가 남아 있으면 `구현 잠금`을 `잠금`으로 둔다.
|
||||||
|
- 새 `[스케치]` Milestone은 `구현 잠금`을 `잠금`으로 둔다.
|
||||||
|
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
|
||||||
|
- `구현 잠금`에는 상태와 `결정 필요` 체크리스트만 적는다. 결정할 항목이 없으면 `결정 필요: 없음`으로 적는다.
|
||||||
|
- 새 Milestone이 다른 프로젝트 Milestone 완료 전까지 잠겨야 하면 `구현 잠금`을 `잠금`으로 두고 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`에 entry를 만든다. 의존 대상 확정과 entry 형식은 `update-roadmap`의 프로젝트 간 잠금 규칙을 따른다.
|
||||||
|
- `기능`은 Epic heading과 Task 체크리스트로 작성한다.
|
||||||
|
- Epic heading은 `### Epic: [epic-id] <이름>` 형식으로 작성한다.
|
||||||
|
- Task는 `- [ ] [item-id] 설명` 형식으로 작성한다.
|
||||||
|
- epic-id와 item-id는 공백 없는 짧은 ASCII 토큰이며, 해당 Milestone 안에서만 유일하면 된다.
|
||||||
|
- 검증이 필요한 Task에만 같은 항목 안에 `검증: <명령/확인 방법/기대 결과>`를 붙인다. 검증이 필요 없는 기능에는 억지 검증을 붙이지 않는다.
|
||||||
|
- `완료 리뷰`는 새 Milestone에서는 `상태: 없음`, `요청일: 없음`으로 두고, 모든 기능 Task와 Task 안에 명시된 검증이 충족된 뒤 사용자 최종 확인을 요청할 때 갱신한다.
|
||||||
|
- `범위`, `범위 제외`, `작업 컨텍스트`는 설명 목록으로 작성하고, 실행해야 할 작업을 이 섹션에 숨기지 않는다.
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] `agent-roadmap/ROADMAP.md` 또는 로컬 `agent-roadmap/current.md`가 이미 존재하는지 확인
|
||||||
|
- [ ] 이미 존재하면 덮어쓰지 말고 `update-roadmap` 스킬 사용을 안내
|
||||||
|
- [ ] `README.md`, `agent-ops/GUIDE.md`, `agent-ops/rules/project/rules.md` 등 프로젝트 방향을 설명하는 문서를 확인
|
||||||
|
- [ ] `rg --files`로 현재 프로젝트의 주요 구조를 가볍게 확인
|
||||||
|
- [ ] `roadmap-template.md`, `roadmap-current-template.md`, `roadmap-phase-template.md`, `roadmap-milestone-template.md`를 읽어 최신 형식 확인
|
||||||
|
- [ ] `agent-ops/rules/common/rules.md`가 로드맵 디렉터리 존재 시 `agent-ops/rules/common/rules-roadmap.md`를 읽도록 라우팅하는지 확인
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **기존 로드맵 확인**
|
||||||
|
- `agent-roadmap/` 하위 기존 파일 존재 여부를 확인한다.
|
||||||
|
- 기존 로드맵이 있으면 새로 만들지 않고 `update-roadmap`을 사용하도록 안내한다.
|
||||||
|
|
||||||
|
2. **프로젝트 방향 분석**
|
||||||
|
- README와 프로젝트 규칙에서 대상 사용자, 해결하려는 문제, 현재 구현 상태를 파악한다.
|
||||||
|
- 전체 코드를 정독하지 않는다. 로드맵 설계에 필요한 문서와 상위 구조만 확인한다.
|
||||||
|
- 불확실한 제품 방향은 단정하지 않고 "가정" 또는 `<!-- TODO: 확인 필요 -->`로 남긴다.
|
||||||
|
|
||||||
|
3. **목표 / Phase / Milestone 설계**
|
||||||
|
- 전체 목표는 프로젝트가 궁극적으로 만들려는 결과를 1~3문장으로 작성한다.
|
||||||
|
- Phase는 큰 진화 단위로 나누고, 각 Phase에 목표와 상태를 둔다.
|
||||||
|
- Milestone은 Phase 안에서 완료 판단이 가능한 단위로 나눈다.
|
||||||
|
- Milestone 내부에서 여러 기능 묶음이 필요하면 Epic으로 선언하고, Epic 아래 flat Task 체크리스트를 둔다.
|
||||||
|
|
||||||
|
4. **파일 생성**
|
||||||
|
- `ROADMAP.md`, 로컬 `current.md`, 각 Phase의 `PHASE.md`, 각 Milestone 문서를 템플릿 순서대로 생성한다.
|
||||||
|
- 활성 Phase와 활성 Milestone은 `current.md`에 모두 기록한다.
|
||||||
|
- `.gitignore`의 Agent-Ops 관리 block에 `agent-roadmap/current.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/`만 둘 수 있다.
|
||||||
|
- 외부 의존 잠금이 있으면 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`을 생성하거나 기존 entry를 upsert한다. 의존 대상이 명시 경로, slug, 제목, 문서 힌트, 로컬 current 단일 후보 중 하나로 확정되지 않으면 lock entry를 만들지 않고 TODO로 남긴다.
|
||||||
|
|
||||||
|
5. **검증**
|
||||||
|
- 생성한 링크가 실제 파일을 가리키는지 확인한다.
|
||||||
|
- 로컬 `current.md` 활성 항목에 `agent-roadmap/archive/**` 경로가 없는지 확인한다.
|
||||||
|
- Epic heading과 Task 체크리스트 id가 형식을 따르는지 확인한다.
|
||||||
|
- 상태 표기가 `[진행중]`처럼 공백 없는 표준값인지 확인한다.
|
||||||
|
- `[스케치]` Milestone에 `승격 조건` 섹션이 있고 `구현 잠금`이 `잠금`인지 확인한다.
|
||||||
|
- Milestone 문서에 `완료 리뷰` 섹션이 있는지 확인한다.
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 생성 완료
|
||||||
|
|
||||||
|
- 로드맵: agent-roadmap/ROADMAP.md
|
||||||
|
- 로컬 현재 컨텍스트: agent-roadmap/current.md
|
||||||
|
- Phase 문서: <N개>
|
||||||
|
- Milestone 문서: <N개>
|
||||||
|
- 활성 Phase: <N개>
|
||||||
|
- 활성 Milestone: <N개>
|
||||||
|
- 구현 잠금: <잠금 Milestone N개 | 해제 Milestone N개>
|
||||||
|
- Workspace 잠금: <생성/갱신 N개 | 없음>
|
||||||
|
- 공통 로드맵 룰: <확인함 | 설치 필요 | 해당 없음>
|
||||||
|
|
||||||
|
## 활성 항목
|
||||||
|
|
||||||
|
- Phase: <phase-name>: agent-roadmap/phase/<phase-slug>/PHASE.md
|
||||||
|
- Milestone: <milestone-name>: agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md
|
||||||
|
|
||||||
|
## TODO 항목
|
||||||
|
|
||||||
|
- <확인이 필요한 가정 또는 미정 항목> (해당 시)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 기존 `agent-roadmap/` 파일을 덮어쓰지 않는다.
|
||||||
|
- 일반 작업마다 전체 `ROADMAP.md`를 읽도록 규칙을 만들지 않는다.
|
||||||
|
- 로컬 `current.md`에 `agent-roadmap/archive/**` 경로를 넣지 않는다.
|
||||||
|
- `agent-roadmap/current.md`를 git 추적 대상으로 만들지 않는다.
|
||||||
|
- Phase와 Milestone 이름 또는 파일명에 순번을 강제하지 않는다.
|
||||||
|
- `ROADMAP.md`에 Milestone 상세 작업 체크리스트를 넣지 않는다.
|
||||||
|
- Epic과 Task를 별도 파일로 분리하지 않는다.
|
||||||
|
- Milestone 문서에서 `구현 잠금` 섹션을 생략하지 않는다.
|
||||||
|
- 사용자만 결정할 수 있는 항목이 남아 있는데 새 Milestone을 `해제` 상태로 만들지 않는다.
|
||||||
|
- 확정되지 않은 제품 방향을 사실처럼 단정하지 않는다.
|
||||||
101
agent-ops/skills/common/create-skill/SKILL.md
Normal file
101
agent-ops/skills/common/create-skill/SKILL.md
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
---
|
||||||
|
name: create-skill
|
||||||
|
version: 1.0.0
|
||||||
|
description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
|
||||||
|
---
|
||||||
|
|
||||||
|
# Create Skill
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
`agent-ops/skills/` 하위에 올바른 형식의 SKILL.md 파일을 생성한다.
|
||||||
|
기존 skill-template.md 를 기반으로, 요청 목적에 맞는 내용을 채워 넣는다.
|
||||||
|
생성 후 라우팅 항목을 추가한다.
|
||||||
|
|
||||||
|
이 스킬은 프로젝트 내부 `agent-ops` 라우터가 읽는 스킬을 만든다.
|
||||||
|
`$CODEX_HOME/skills`에 설치되어 Codex가 직접 discover하는 스킬을 만들 때는 시스템 `skill-creator` 규칙을 우선하고, frontmatter는 `name`과 `description`만 사용한다.
|
||||||
|
|
||||||
|
### 생성 위치 결정
|
||||||
|
- `.agent-ops-source` 파일이 **있으면** (공통 관리 레포): `agent-ops/skills/common/<skill-name>/SKILL.md`
|
||||||
|
- `.agent-ops-source` 파일이 **없으면** (타겟 프로젝트): `agent-ops/skills/project/<skill-name>/SKILL.md`
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 새로운 반복 작업 패턴이 생겨 skill로 정의해야 할 때
|
||||||
|
- 기존 skill이 없는 작업 유형을 처음 수행하기 전에
|
||||||
|
- 사용자가 특정 작업을 skill로 만들어 달라고 요청할 때
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `skill-name`: 생성할 skill 이름, kebab-case (필수)
|
||||||
|
- `purpose`: 이 skill이 해결하는 문제 한 줄 요약 (필수)
|
||||||
|
- `trigger-cases`: 이 skill을 호출해야 하는 상황 목록 (선택)
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] `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. **중복 확인**
|
||||||
|
- `agent-ops/skills/common/<skill-name>/` 및 `agent-ops/skills/project/<skill-name>/` 폴더 존재 여부 확인
|
||||||
|
- 기능이 겹치는 기존 skill이 있으면 사용자에게 알리고 중단한다
|
||||||
|
|
||||||
|
2. **목적 분석**
|
||||||
|
- `purpose` 와 `trigger-cases` 를 바탕으로 아래 항목을 도출한다
|
||||||
|
- 언제 호출할지 (2~4개)
|
||||||
|
- 필요한 입력 파라미터
|
||||||
|
- 사전 확인 항목
|
||||||
|
- 실행 절차 (3~7단계)
|
||||||
|
- 출력 형식
|
||||||
|
- 금지 사항
|
||||||
|
|
||||||
|
3. **SKILL.md 생성**
|
||||||
|
- 경로: 생성 위치 결정 규칙에 따라 `common/` 또는 `project/` 하위에 생성
|
||||||
|
- `skill-template.md` 형식을 따른다
|
||||||
|
- agent-ops 내부 스킬은 기존 로컬 관례에 맞춰 `version`을 둘 수 있다. Codex 설치형 스킬로 배포할 목적이면 `version`이나 `depends` 같은 비표준 frontmatter를 넣지 않는다.
|
||||||
|
- 프로젝트 특화 내용보다 범용 절차를 우선한다
|
||||||
|
- 절차는 구체적이되 지나치게 세부 구현을 기술하지 않는다
|
||||||
|
|
||||||
|
4. **라우팅 업데이트**
|
||||||
|
- `.agent-ops-source` 마커가 **있으면** (공통 관리 레포): `agent-ops/skills/common/router.md`에 라우팅 항목 추가
|
||||||
|
- `.agent-ops-source` 마커가 **없으면** (타겟 프로젝트): `agent-ops/rules/project/rules.md`의 프로젝트 스킬 라우터 섹션에 라우팅 항목 추가
|
||||||
|
- 기존 공통 스킬을 수정해 trigger가 달라졌다면 새 skill을 만들지 말고 `agent-ops/skills/common/router.md`의 기존 행을 갱신한다
|
||||||
|
- 이 skill이 속할 라우팅 축(구조 분석/코드 변경/흐름 추적 등)을 판단한다
|
||||||
|
- 기존 라우팅 구조를 깨지 않는다
|
||||||
|
|
||||||
|
5. **결과 보고**
|
||||||
|
- 생성한 파일 경로
|
||||||
|
- 라우팅 항목을 추가한 파일과 내용
|
||||||
|
- 이 skill이 다루지 않는 범위(필요 시)
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```
|
||||||
|
## 생성 완료
|
||||||
|
|
||||||
|
- SKILL 경로: agent-ops/skills/{common|project}/<skill-name>/SKILL.md
|
||||||
|
- 라우팅 추가: <대상 파일> → <라우팅 축> → <skill-name>
|
||||||
|
|
||||||
|
## 주의사항 (해당 시)
|
||||||
|
- <이 skill이 다루지 않는 범위 또는 주의할 점>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] `agent-ops/skills/{common|project}/<skill-name>/SKILL.md` 파일이 생성되었는가
|
||||||
|
- [ ] 생성된 파일이 `skill-template.md`의 필수 섹션(목적, 언제 호출할지, 실행 절차, 실행 결과 검증, 출력 형식, 금지 사항)을 포함하는가
|
||||||
|
- [ ] frontmatter에 name, description이 올바르게 기재되었는가
|
||||||
|
- [ ] agent-ops 내부 스킬이면 version 등 로컬 관례를 따르고, Codex 설치형 스킬이면 시스템 `skill-creator` frontmatter 규칙을 따르는가
|
||||||
|
- [ ] 라우팅 대상 파일에 해당 스킬의 라우팅 항목이 추가되었는가
|
||||||
|
- 검증 실패 시: 누락된 섹션 또는 라우팅 항목을 사용자에게 알리고 해당 부분만 보완한다
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 이미 존재하는 skill 을 덮어쓰지 않는다
|
||||||
|
- 프로젝트 특화 경로(예: `app/screens/`)를 skill 본문에 하드코딩하지 않는다
|
||||||
|
- skill 생성과 무관한 코드 파일을 수정하지 않는다
|
||||||
|
- 라우팅 대상 파일의 기존 항목을 삭제하거나 재정렬하지 않는다
|
||||||
|
- 하나의 skill 에 여러 독립적인 책임을 묶지 않는다
|
||||||
137
agent-ops/skills/common/create-test/SKILL.md
Normal file
137
agent-ops/skills/common/create-test/SKILL.md
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
---
|
||||||
|
name: create-test
|
||||||
|
version: 1.1.4
|
||||||
|
description: agent-test 환경 rules.md와 도메인/검증 시나리오별 테스트 rule 문서를 생성하거나 구조적 blank/skeleton baseline을 보완하는 스킬
|
||||||
|
---
|
||||||
|
|
||||||
|
# create-test
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
`agent-test/<env>/rules.md`와 `agent-test/<env>/<test-profile>.md`를 템플릿 기준으로 생성하거나 구조적 blank/skeleton 상태에서 baseline으로 보완한다.
|
||||||
|
공통 진입점은 얇게 유지하고, 실제 테스트 기준은 환경/도메인/검증 시나리오별 문서에 둔다.
|
||||||
|
|
||||||
|
`test-case`는 기존 호출과의 호환을 위한 alias이며, 새 문서 기준 이름은 `test-profile`이다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 새 테스트 환경을 추가할 때
|
||||||
|
- 특정 환경의 `rules.md`가 없을 때
|
||||||
|
- 특정 환경의 `rules.md`가 비어 있거나 템플릿 뼈대만 있어 baseline 보완이 필요할 때
|
||||||
|
- 새 도메인/검증 시나리오별 테스트 문서와 라우팅을 추가할 때
|
||||||
|
- `init-agent-ops` 후 local 테스트 환경 보완이 필요할 때
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `env`: `local`, `dev`, `qa`, `prod` 중 하나 (필수)
|
||||||
|
- `test-profile`: 도메인/검증 시나리오별 테스트 문서 이름, kebab-case (선택)
|
||||||
|
- `test-case`: `test-profile`의 호환 alias (선택)
|
||||||
|
- `domain`: 대상 도메인 이름, kebab-case (선택)
|
||||||
|
- `verification-type`: `smoke`, `unit`, `integration`, `e2e`, `model`, `migration`, `manual`, `full-cycle` 중 하나 (선택)
|
||||||
|
- `scope`: 검증 대상 또는 변경 범위 설명 (선택)
|
||||||
|
|
||||||
|
## 핵심 규칙
|
||||||
|
|
||||||
|
- 도메인 매핑이나 domain rule에서 도메인이 하나 이상 확인되면, 누락된 `agent-test/<env>/<domain>-smoke.md`를 도메인별로 항상 생성한다.
|
||||||
|
- 명시 `test-profile`은 추가 생성 대상이다. 명시 대상만 만들고 도메인 baseline을 생략하지 않는다.
|
||||||
|
- 도메인이 하나도 확인되지 않을 때만 `agent-test/<env>/project-smoke.md`를 fallback baseline으로 만든다.
|
||||||
|
- env rules는 빈 파일, 제목/frontmatter만 있는 파일, 필수 섹션 누락, 또는 `## 라우팅`에 실제 profile 경로가 없으면 구조적 blank/skeleton으로 본다.
|
||||||
|
- test-profile 문서는 빈 파일, 제목/frontmatter만 있는 파일, 필수 섹션 누락, 또는 적용 범위/분류/명령/필수 검증/판정 기준 섹션 자체가 없으면 구조적 blank/skeleton으로 본다.
|
||||||
|
- 필수 섹션은 있고 일부 값이 비어 있거나 `<확인 필요>`인 상태는 구조적 blank/skeleton이 아니다. 이 경우 structured-incomplete로 보고 확인된 구체 값과 미확인 항목을 결과에 남긴다.
|
||||||
|
- 구조적 blank/skeleton env rules나 profile은 기존 완성 문서가 아니라 baseline 보완 대상으로 본다. 확인된 구체 값은 보존하고, 빠진 필수 섹션과 baseline 라우팅만 채운다.
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] `agent-ops/rules/common/rules.md`의 스킬 규칙과 테스트 규칙이 분리되어 있는지 확인한다.
|
||||||
|
- [ ] `agent-ops/skills/common/router.md`에 `create-test` 라우팅이 있는지 확인한다.
|
||||||
|
- [ ] `agent-ops/rules/project/rules.md`가 있으면 도메인 매핑 테이블을 확인한다.
|
||||||
|
- [ ] `agent-ops/rules/project/domain/` 하위 domain rule 목록을 확인한다.
|
||||||
|
- [ ] 테스트 명령 확인을 위해 프로젝트의 대표 설정 파일을 가볍게 확인한다. 예: `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/<env>/rules.md` 존재 여부를 확인한다.
|
||||||
|
- [ ] `agent-test/<env>/rules.md`가 있으면 읽고 missing / blank-skeleton / structured-incomplete / usable 중 하나로 분류한다.
|
||||||
|
- [ ] 도메인 baseline과 추가 생성 대상 `agent-test/<env>/*.md`의 존재 여부를 확인하고, 있으면 blank-skeleton / structured-incomplete / usable 중 하나로 분류한다.
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **환경 rules 생성**
|
||||||
|
- `agent-test/<env>/rules.md`가 없으면 `test-env-rules-template.md` 형식으로 만든다.
|
||||||
|
- `agent-test/<env>/rules.md`가 구조적 blank/skeleton이면 기존 구체 값을 보존한 채 빠진 frontmatter, 정독 필수 문구, 필수 섹션, baseline 라우팅 영역만 보완한다.
|
||||||
|
- usable한 기존 env rules는 덮어쓰지 않고 라우팅 추가가 필요한 경우에만 최소 수정한다.
|
||||||
|
- 제목은 `# <env> 테스트 규칙`으로 쓴다.
|
||||||
|
- 제목 바로 아래 정독 필수 문구를 유지한다.
|
||||||
|
- `last_rule_updated_at`은 생성/보완일 `YYYY-MM-DD`로 쓴다.
|
||||||
|
|
||||||
|
2. **생성 대상 확정**
|
||||||
|
- `test-case`가 있고 `test-profile`이 없으면 `test-profile`로 취급한다.
|
||||||
|
- 도메인 매핑 테이블과 `agent-ops/rules/project/domain/*/rules.md`에서 확인된 전체 도메인 목록을 만든다.
|
||||||
|
- 확인된 도메인이 있으면 전체 도메인의 `<domain>-smoke` 문서를 생성 대상으로 삼는다. 개수가 많아도 생략하지 않는다.
|
||||||
|
- 확인된 도메인이 없으면 `project-smoke` 문서 1개를 fallback baseline으로 생성 대상으로 삼는다.
|
||||||
|
- `test-profile`이 있으면 baseline 생성 대상에 해당 문서 1개를 추가한다.
|
||||||
|
- `test-profile`이 없고 `domain`이 있으면 `<domain>-<verification-type>` 형식의 문서를 추가한다. `verification-type`이 없으면 `smoke`를 기본값으로 둔다.
|
||||||
|
- `test-profile`과 `domain`이 모두 없고 `scope`가 특정 검증 시나리오를 가리키면, 해당 도메인의 `<domain>-<verification-type>` 문서를 baseline 외 추가 생성 대상으로 둘 수 있다.
|
||||||
|
- 도메인은 새로 발명하지 않는다. 도메인 매핑이나 domain rule에서 확인되지 않은 이름은 `project-wide`로 기록한다.
|
||||||
|
|
||||||
|
3. **도메인/검증 시나리오별 문서 생성**
|
||||||
|
- 생성 대상 문서가 없으면 `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`을 채운다.
|
||||||
|
- 파일명은 kebab-case로 쓴다.
|
||||||
|
- 실제 확인된 환경, 명령, 판정 기준만 채운다.
|
||||||
|
- 불확실한 값은 비워 두거나 `<확인 필요>`로 둔다.
|
||||||
|
- 테스트 코드를 생성하는 스킬이 아니라 테스트 판단 기준 문서를 생성하는 스킬임을 유지한다.
|
||||||
|
|
||||||
|
4. **라우팅 갱신**
|
||||||
|
- 새 환경을 만들었고 `agent-ops/rules/common/rules.md`에 해당 env 라인이 없으면 `# 테스트 규칙`에 한 줄을 추가한다.
|
||||||
|
- 생성하거나 보완한 `test-profile` 문서는 `agent-test/<env>/rules.md`의 `## 라우팅`에 한 줄씩 추가한다.
|
||||||
|
- 이미 같은 profile로 향하는 라우팅이 있으면 중복 추가하지 않고 설명만 필요할 때 최소 보정한다.
|
||||||
|
- 라우팅 설명은 `<domain 또는 project-wide> / <verification-type> / <scope 요약>` 형식으로 쓴다.
|
||||||
|
- 도메인/검증 시나리오별 문서에서 다른 테스트 문서로 라우팅하지 않는다.
|
||||||
|
- 공통룰에서 스킬 최종 진입까지의 경로는 `rules.md` -> `router.md` -> `create-test/SKILL.md`로 유지한다.
|
||||||
|
|
||||||
|
5. **local 추적 제외**
|
||||||
|
- `env`가 `local`이면 `.gitignore`에 `agent-test/local/`과 `agent-test/runs/`가 있는지 확인하고 없으면 추가한다.
|
||||||
|
|
||||||
|
6. **결과 보고**
|
||||||
|
- 생성한 파일
|
||||||
|
- 추가한 라우팅
|
||||||
|
- 자동 생성 기준: 도메인 baseline / 명시 입력 / scope 매칭 / project-smoke fallback
|
||||||
|
- 구조적 blank/skeleton 보완 대상
|
||||||
|
- 비워 둔 확인 필요 항목
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] 생성 파일이 해당 템플릿의 필수 섹션을 포함하는가
|
||||||
|
- [ ] `rules.md` -> `router.md` -> `create-test/SKILL.md` 경로가 끊기지 않는가
|
||||||
|
- [ ] `agent-test/<env>/rules.md`가 3홉을 넘는 라우팅을 만들지 않는가
|
||||||
|
- [ ] 새 도메인/검증 시나리오별 문서가 env rules의 라우팅에 연결되었는가
|
||||||
|
- [ ] 확인된 모든 도메인에 `<domain>-smoke` 문서가 생성되었는가
|
||||||
|
- [ ] 도메인이 없을 때 `project-smoke` fallback 문서가 생성되었는가
|
||||||
|
- [ ] 생성/보완 대상에 섹션 누락이나 라우팅 없는 구조적 blank/skeleton 파일이 남아 있지 않고, 불확실한 값은 `<확인 필요>`로 보고되었는가
|
||||||
|
- [ ] local 생성 시 `.gitignore`에 local 경로가 반영되었는가
|
||||||
|
- 검증 실패 시: 누락된 파일/섹션/라우팅만 보완한다.
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```md
|
||||||
|
## 생성 완료
|
||||||
|
|
||||||
|
- 환경: <env>
|
||||||
|
- 환경 rules: agent-test/<env>/rules.md
|
||||||
|
- 테스트 profiles: <agent-test/<env>/<test-profile>.md 목록>
|
||||||
|
- 라우팅 추가: <내용>
|
||||||
|
- 자동 생성 기준: <도메인 baseline | 명시 입력 | scope 매칭 | project-smoke fallback>
|
||||||
|
- 구조적 blank/skeleton 보완: <파일 목록 또는 없음>
|
||||||
|
- 확인 필요: <항목 또는 없음>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- usable한 기존 테스트 문서를 덮어쓰지 않는다.
|
||||||
|
- 구조적 blank/skeleton 보완 시에도 확인된 구체 환경값, 명령, 판정 기준을 추측으로 교체하지 않는다.
|
||||||
|
- 도메인/검증 시나리오별 문서에서 추가 테스트 문서로 라우팅하지 않는다.
|
||||||
|
- 도메인 매핑이나 domain rule에 없는 도메인을 확정값처럼 만들지 않는다.
|
||||||
|
- 확인되지 않은 host, port, token, endpoint를 추측해 쓰지 않는다.
|
||||||
|
- secret, token, 개인 endpoint 원문을 tracked 파일에 기록하지 않는다.
|
||||||
281
agent-ops/skills/common/init-agent-ops/SKILL.md
Normal file
281
agent-ops/skills/common/init-agent-ops/SKILL.md
Normal file
|
|
@ -0,0 +1,281 @@
|
||||||
|
---
|
||||||
|
name: init-agent-ops
|
||||||
|
version: 1.1.9
|
||||||
|
description: 프로젝트 상태를 판별하고 agent-ops 기본 스캐폴드를 생성하기 위한 초기 규칙
|
||||||
|
---
|
||||||
|
|
||||||
|
# init-agent-ops
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
프로젝트에 Agent-Ops 구조가 없거나 불완전할 때,
|
||||||
|
현재 프로젝트 상태를 분석하여 다음을 세팅한다.
|
||||||
|
|
||||||
|
1. 에이전트 진입 파일
|
||||||
|
2. AI ignore / permission 기본 설정
|
||||||
|
3. agent-ops 기본 폴더 구조
|
||||||
|
4. rules/project/rules.md (프로젝트 특화 규칙, 분석 후 생성)
|
||||||
|
5. 초기 domain rule 초안
|
||||||
|
6. 초기 local 테스트 환경
|
||||||
|
7. 초기 skill (필요 시)
|
||||||
|
|
||||||
|
"현재 프로젝트에 맞는 최소 스캐폴드" 생성을 우선한다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 프로젝트에 agent-ops 구조가 없을 때
|
||||||
|
- agent-ops 구조가 불완전하여 재설정이 필요할 때
|
||||||
|
- 사용자가 "agent-ops 초기화해줘", "에이전트 설정해줘" 요청 시
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `project-type`: 신규 / 운영중 (선택, 미지정 시 자동 판별)
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] 프로젝트 루트에 기존 agent-ops 관련 파일(`CLAUDE.md`, `agent-ops/` 등)이 있는지 확인
|
||||||
|
- [ ] `.agent-ops-source` 파일이 있는지 확인 (공통 관리 레포 여부)
|
||||||
|
- [ ] 기존 진입 파일(`CLAUDE.md`, `GEMINI.md` 등)이 있는지 확인
|
||||||
|
- [ ] 기존 AI ignore / permission 파일(`.geminiignore`, `.aiexclude`, `.claude/settings.json`, `opencode.json` 등)이 있는지 확인
|
||||||
|
- [ ] `agent-ops/skills/common/create-test/SKILL.md`가 있는지 확인
|
||||||
|
|
||||||
|
## 핵심 원칙
|
||||||
|
|
||||||
|
- 기존 구조를 우선한다.
|
||||||
|
- 새 파일 생성은 꼭 필요한 최소 범위로 제한한다.
|
||||||
|
- 도메인은 발명하지 말고 현재 구조에서 발견한다.
|
||||||
|
- 처음에는 핵심 도메인만 생성한다.
|
||||||
|
- 반복되는 작업만 초기 skill로 만든다.
|
||||||
|
- 불확실한 내용은 후보로 제시한다.
|
||||||
|
|
||||||
|
## 상태 판별
|
||||||
|
|
||||||
|
### 신규 프로젝트
|
||||||
|
- 코드/폴더 구조가 단순하다
|
||||||
|
- 도메인 경계가 아직 약하다
|
||||||
|
- Agent-Ops 관련 파일이 없다
|
||||||
|
|
||||||
|
### 운영중 프로젝트
|
||||||
|
- 모듈/폴더/패키지 경계가 보인다
|
||||||
|
- 반복 작업이 드러난다
|
||||||
|
- 핵심 책임 경계가 식별된다
|
||||||
|
|
||||||
|
## 생성 대상
|
||||||
|
|
||||||
|
| 파일 | 방법 |
|
||||||
|
|------|------|
|
||||||
|
| `GEMINI.md`, `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.clinerules` 등 진입 파일 | `rules/common/rules.md`를 `agent-ops/bin/entry-files.sh`의 파일 목록으로 프로젝트 루트에 복사 |
|
||||||
|
| `agent-ops/.version` | 공통 관리 레포의 VERSION 파일을 그대로 복사 (프레임워크 버전 추적용) |
|
||||||
|
| `agent-ops/bin/` | 공통 스크립트 전체 복사 (진입 파일 목록의 단일 기준인 `entry-files.sh` 포함) |
|
||||||
|
| `agent-ops/rules/common/` | 공통 폴더 전체 복사 (수정 금지) |
|
||||||
|
| `agent-ops/skills/common/` | 공통 폴더 전체 복사 (수정 금지) |
|
||||||
|
| `agent-ops/rules/project/rules.md` | 프로젝트 분석 후 생성 |
|
||||||
|
| `agent-ops/rules/project/domain/<domain>/rules.md` | 도메인 분석 후 생성 |
|
||||||
|
| `agent-ops/rules/private/` | 폴더만 생성 (내용은 개인이 작성) |
|
||||||
|
| `.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으로 생성 |
|
||||||
|
| `agent-test/local/<domain>-smoke.md` | domain rule 생성 후 각 도메인별 기본 smoke 테스트 뼈대로 생성 |
|
||||||
|
| `.gitignore`에 `agent-test/local/`, `agent-test/runs/` 추가 | `init-agent-ops.sh`가 local 테스트 환경/로그를 git 추적 제외 |
|
||||||
|
| `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore` | 사용자 항목은 보존하고 Agent-Ops 관리 block에 `agent-task/archive/**`, `agent-roadmap/archive/**` 추가 |
|
||||||
|
| `.claude/settings.json`, `opencode.json` | `agent-task/archive/**` 읽기/검색 제외 설정을 생성 또는 병합한다. `agent-roadmap/archive/**`는 필요 시 링크로 읽을 수 있어야 하므로 hard read/glob deny에서 제거한다 |
|
||||||
|
|
||||||
|
에이전트별 파일명:
|
||||||
|
|
||||||
|
실제 생성/동기화 대상 목록은 `agent-ops/bin/entry-files.sh`의 `AGENT_OPS_ENTRY_FILES`를 단일 기준으로 사용한다.
|
||||||
|
|
||||||
|
| 에이전트 | 파일명 |
|
||||||
|
|---------|--------|
|
||||||
|
| Gemini | `GEMINI.md` |
|
||||||
|
| Claude | `CLAUDE.md` |
|
||||||
|
| Kilo Code / OpenCode | `AGENTS.md` |
|
||||||
|
| Cursor | `.cursorrules` |
|
||||||
|
| Cline | `.clinerules` |
|
||||||
|
|
||||||
|
## 에이전트 진입 파일 원칙
|
||||||
|
|
||||||
|
진입 파일은 `rules/common/rules.md` 내용 그대로를 에이전트별 파일명으로 복사한다.
|
||||||
|
별도 내용을 추가하거나 수정하지 않는다.
|
||||||
|
|
||||||
|
## Rule 구조 원칙
|
||||||
|
|
||||||
|
### rules/common/rules.md
|
||||||
|
- 공통 관리 레포에서 제공. 프로젝트에서 직접 수정하지 않는다.
|
||||||
|
- 실제 사용은 진입점 파일들에서 사용된다.
|
||||||
|
|
||||||
|
포함 항목:
|
||||||
|
- 기본 원칙
|
||||||
|
- 공통 스킬 라우팅 (router.md 참조)
|
||||||
|
- project/rules.md 로드 지시
|
||||||
|
|
||||||
|
### rules/project/rules.md
|
||||||
|
init-agent-ops가 프로젝트를 분석하여 생성한다.
|
||||||
|
|
||||||
|
포함 항목:
|
||||||
|
- 응답 언어
|
||||||
|
- 프로젝트 개요 / 주요 구조
|
||||||
|
- 기술 스택
|
||||||
|
- 프로젝트 특화 컨벤션
|
||||||
|
- 도메인 매핑 테이블 (경로 패턴 → domain rules.md)
|
||||||
|
- 프로젝트 스킬 라우팅 (해당 시)
|
||||||
|
|
||||||
|
common/rules.md와 내용이 중복되지 않도록 한다.
|
||||||
|
|
||||||
|
#### 도메인 매핑 테이블 형식
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 도메인 매핑
|
||||||
|
|
||||||
|
| 경로 패턴 | 도메인 | rules.md |
|
||||||
|
|----------|--------|----------|
|
||||||
|
| `src/order/**` | order | `agent-ops/rules/project/domain/order/rules.md` |
|
||||||
|
| `src/payment/**` | payment | `agent-ops/rules/project/domain/payment/rules.md` |
|
||||||
|
| `src/common/**` | common | `agent-ops/rules/project/domain/common/rules.md` |
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 프로젝트 스킬 라우팅 형식
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 스킬 라우팅
|
||||||
|
|
||||||
|
| 요청 키워드 | SKILL.md |
|
||||||
|
|------------|----------|
|
||||||
|
| 테스트 실행해줘 | `agent-ops/skills/project/run-test/SKILL.md` |
|
||||||
|
```
|
||||||
|
|
||||||
|
### domain rule
|
||||||
|
각 도메인 rules.md에는 아래만 둔다.
|
||||||
|
|
||||||
|
- frontmatter metadata
|
||||||
|
- `domain`
|
||||||
|
- `last_rule_review_commit`: 생성 직전 `git rev-parse HEAD`
|
||||||
|
- `last_rule_updated_at`: 생성일 `YYYY-MM-DD`
|
||||||
|
- 목적 / 책임
|
||||||
|
- 포함 경로
|
||||||
|
- 제외 경로
|
||||||
|
- 주요 구성 요소
|
||||||
|
- 유지할 패턴
|
||||||
|
- 다른 도메인과의 경계
|
||||||
|
- 금지 사항
|
||||||
|
|
||||||
|
## DDD 기준
|
||||||
|
|
||||||
|
- **Core Domain**: 핵심 가치와 주요 유즈케이스
|
||||||
|
- **Supporting Domain**: 핵심 도메인을 지원
|
||||||
|
- **Generic / Common**: 여러 도메인이 공통으로 사용
|
||||||
|
|
||||||
|
도메인은 실제 폴더, 모듈, 패키지, 책임 경계와 연결되어야 한다.
|
||||||
|
|
||||||
|
## 실행 (Execution)
|
||||||
|
|
||||||
|
지정한 대상 디렉토리에 agent-ops 기본 스캐폴드와 local 테스트 환경을 생성한다.
|
||||||
|
스크립트 실행 후 이 skill의 실행 절차에 따라 project/domain 분석을 보완한다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./agent-ops/bin/init-agent-ops.sh <target_directory>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **상태 판별**
|
||||||
|
- 프로젝트 구조, 모듈 경계, agent-ops 파일 유무를 분석하여 신규/운영중을 판별한다
|
||||||
|
|
||||||
|
2. **에이전트 진입 파일 생성**
|
||||||
|
- `rules/common/rules.md`를 `agent-ops/bin/entry-files.sh`의 파일 목록으로 프로젝트 루트에 복사한다
|
||||||
|
|
||||||
|
3. **AI ignore / permission 기본 설정**
|
||||||
|
- `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에는 사용자 항목을 건드리지 않고 Agent-Ops 관리 block만 추가하거나 교체한다
|
||||||
|
- Agent-Ops 관리 block에는 `agent-task/archive/**`와 `agent-roadmap/archive/**`를 넣는다
|
||||||
|
- `.claude/settings.json`, `opencode.json`이 없으면 `agent-task/archive/**` 읽기/검색 제외 설정을 생성하고, 있으면 가능한 경우 기존 설정을 보존하며 필요한 제외 설정만 병합한다
|
||||||
|
- `agent-roadmap/archive/**`는 일반 작업에서 읽지 않도록 AI ignore와 로드맵 규칙으로 제한하되, `.claude/settings.json`이나 `opencode.json`의 hard read/glob deny에는 두지 않는다
|
||||||
|
- 기존 `.claude/settings.json`이나 `opencode.json`에 `agent-roadmap/archive/**` hard read/glob deny가 있으면 init-agent-ops 표준에 맞게 제거한다
|
||||||
|
- 대상 루트에 `.agent-ops-source`가 있으면 AI ignore / permission 파일은 보강하지 않는다
|
||||||
|
- `agent-task/archive/**`와 `agent-roadmap/archive/**` ignore 항목은 `.gitignore`에 추가하지 않는다
|
||||||
|
- `.gitignore`에는 Agent-Ops 관리 block으로 `!agent-task/`, `!agent-task/**/`, `!agent-task/**/*.md`, `!agent-task/**/*.log`, `agent-roadmap/current.md`만 추가하거나 갱신한다
|
||||||
|
|
||||||
|
4. **agent-ops 폴더 구조 복사**
|
||||||
|
- 공통 관리 레포의 `agent-ops/` 공통 폴더(bin, rules/common, skills/common)를 복사한다
|
||||||
|
- `agent-ops/.version` 파일을 복사한다
|
||||||
|
|
||||||
|
5. **rules/project/rules.md 생성**
|
||||||
|
- 프로젝트를 분석하여 응답 언어, 프로젝트 개요, 기술 스택 등을 채운다
|
||||||
|
- common/rules.md와 내용이 중복되지 않도록 한다
|
||||||
|
|
||||||
|
6. **도메인 분석 및 domain rule 생성**
|
||||||
|
- 신규 프로젝트: 핵심 domain placeholder 2~4개만 제안한다. domain rules를 과도하게 채우지 않는다
|
||||||
|
- 운영중 프로젝트: Core/Supporting/Generic 도메인을 식별하고 실제 경로를 반영한 초안을 생성한다
|
||||||
|
|
||||||
|
7. **초기 local 테스트 환경 생성**
|
||||||
|
- `init-agent-ops.sh`가 `agent-test/local/rules.md`를 최소 내용으로 자동 생성한다
|
||||||
|
- `init-agent-ops.sh`는 기존 domain rule이 있으면 각 도메인별 `agent-test/local/<domain>-smoke.md`를 생성하고 라우팅한다
|
||||||
|
- 기존 domain rule이 없으면 `agent-test/local/project-smoke.md` fallback 뼈대를 생성하고 라우팅한다
|
||||||
|
- `init-agent-ops.sh`가 `.gitignore`에 `agent-test/local/`과 `agent-test/runs/`를 자동 추가한다
|
||||||
|
- 스크립트 실행 후 누락되었으면 대상 프로젝트의 `agent-ops/skills/common/create-test/SKILL.md`를 읽고 `env=local`, `test-profile` 없음으로 보완한다
|
||||||
|
- domain rule을 새로 생성한 경우, 각 생성 도메인마다 `agent-test/local/<domain>-smoke.md` 기본 뼈대를 만들고 `agent-test/local/rules.md`에 라우팅을 추가한다
|
||||||
|
- 도메인별 테스트 문서는 상세 명령을 모르면 `<확인 필요>`를 남기더라도 생략하지 않는다
|
||||||
|
|
||||||
|
8. **초기 skill 제안**
|
||||||
|
- 신규 프로젝트: 최소 2개만 제안한다
|
||||||
|
- 운영중 프로젝트: 반복 작업 기반으로 필요한 skill을 제안한다
|
||||||
|
|
||||||
|
9. **결과 보고**
|
||||||
|
- 상태 판별 결과, 생성된 파일 목록, 도메인 제안, skill 제안, 주의사항을 출력한다
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
### 상태 판별
|
||||||
|
- Agent-Ops 상태: 없음 / 부분 적용 / 운영중
|
||||||
|
- 프로젝트 상태: 신규 / 운영중
|
||||||
|
- 근거: 짧게 요약
|
||||||
|
|
||||||
|
### 스캐폴드 계획
|
||||||
|
- 생성할 파일
|
||||||
|
- 바로 채울 파일
|
||||||
|
- placeholder로 둘 파일
|
||||||
|
|
||||||
|
### 도메인 제안
|
||||||
|
- Core Domain
|
||||||
|
- Supporting Domain
|
||||||
|
- Generic / Common
|
||||||
|
|
||||||
|
### 초기 skill 제안
|
||||||
|
- skill 이름
|
||||||
|
- 필요한 이유
|
||||||
|
|
||||||
|
### 주의사항
|
||||||
|
- 지금 만들지 말아야 할 것
|
||||||
|
- 아직 확정하면 안 되는 것
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] `agent-ops/bin/entry-files.sh`의 모든 진입 파일이 프로젝트 루트에 존재하고, 내용이 초기화에 사용한 `rules/common/rules.md`와 일치하는가
|
||||||
|
- [ ] `agent-ops/rules/common/rules.md`가 대상 프로젝트에 남아 있고 초기화에 사용한 `rules/common/rules.md`와 일치하는가
|
||||||
|
- [ ] `agent-ops/rules/project/rules.md`가 생성되었고, 필수 항목(응답 언어, 프로젝트 개요, 기술 스택)이 포함되어 있는가
|
||||||
|
- [ ] 생성된 domain rules.md가 `domain-rule-template.md` 형식을 따르는가
|
||||||
|
- [ ] `rules/project/rules.md`의 도메인 매핑 테이블에 생성된 도메인이 모두 등록되어 있는가
|
||||||
|
- [ ] `.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`가 있는가
|
||||||
|
- [ ] domain rule이 아직 없으면 `agent-test/local/project-smoke.md` fallback이 있는가
|
||||||
|
- [ ] `agent-test/local/rules.md`에 생성된 테스트 profile 라우팅이 연결되었는가
|
||||||
|
- [ ] `.gitignore`에 `agent-test/local/`과 `agent-test/runs/`가 추가되어 있는가
|
||||||
|
- [ ] `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에 Agent-Ops 관리 block이 있고 그 안에 `agent-task/archive/**`와 `agent-roadmap/archive/**`가 포함되어 있는가
|
||||||
|
- [ ] `.claude/settings.json`, `opencode.json`에 `agent-task/archive/**` 제외 설정이 있거나, 병합 불가 시 수동 병합 안내를 출력했는가
|
||||||
|
- [ ] `.claude/settings.json`, `opencode.json`에 `agent-roadmap/archive/**` hard read/glob deny가 남아 있지 않은가
|
||||||
|
- [ ] 기존 `agent-roadmap/archive/**` hard deny가 있으면 init-agent-ops 표준에 맞게 제거했는가
|
||||||
|
- [ ] `.gitignore`에 `agent-task/archive/**` 또는 `agent-roadmap/archive/**` ignore 항목을 추가하지 않았는가
|
||||||
|
- 검증 실패 시: 누락된 파일/항목을 사용자에게 알리고 해당 부분만 보완한다
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 진입 파일에 rules/common/rules.md 외 내용을 추가하지 않는다.
|
||||||
|
- `agent-task/archive/**`와 `agent-roadmap/archive/**` ignore 항목을 `.gitignore`에 추가하지 않는다.
|
||||||
|
- `.gitignore`의 Agent-Ops 관리 task 산출물 unignore 예외를 제거하지 않는다.
|
||||||
|
- local 테스트 환경 파일을 git 추적 대상으로 만들지 않는다.
|
||||||
|
- domain rule이 확인된 경우 도메인별 기본 smoke 테스트 문서를 생략하지 않는다.
|
||||||
|
- 실제 구조보다 앞선 추상 구조를 강요하지 않는다.
|
||||||
|
- 처음부터 많은 domain / skill을 만들지 않는다.
|
||||||
|
- rules/common/rules.md를 프로젝트에서 직접 수정하지 않는다.
|
||||||
|
- rules/project/rules.md에 rules/common/rules.md와 중복되는 내용을 넣지 않는다.
|
||||||
469
agent-ops/skills/common/plan/SKILL.md
Normal file
469
agent-ops/skills/common/plan/SKILL.md
Normal file
|
|
@ -0,0 +1,469 @@
|
||||||
|
---
|
||||||
|
name: plan
|
||||||
|
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
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Create the planning artifacts for the implementation loop:
|
||||||
|
|
||||||
|
```text
|
||||||
|
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` when repeated non-PASS reviews or first-review test environment blockers require a user decision. Verification evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are not user decisions by themselves; they should become normal follow-up plans that record the required evidence. Plan creation after `USER_REVIEW.md` requires an explicit user decision. If the user 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. If implementation discovers a user-only decision, user-owned external environment prerequisite, or scope conflict 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.
|
||||||
|
|
||||||
|
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`.
|
||||||
|
- Milestone-linked work uses the reserved task group form `m-<milestone-slug>`, where `<milestone-slug>` is the active Milestone filename without `.md`.
|
||||||
|
- `{subtask_dir}` is used only for split work and follows the existing indexed directory naming rules below, such as `01_core` or `02+01_db`.
|
||||||
|
- `{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}/` is only the grouping folder and must not contain active plan/review files.
|
||||||
|
|
||||||
|
Filename rules:
|
||||||
|
|
||||||
|
- Plan file: `PLAN-{build_lane}-GNN.md`
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
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 without user input, implementing agents fill the review stub's `사용자 리뷰 요청` section with the exact decision needed, evidence, commands/output, and resume condition, then stop with active files in place. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts should be recorded in `검증 결과` or `계획 대비 변경 사항`, not escalated to user review.
|
||||||
|
- During implementation, do not ask the user directly, present multiple-choice prompts in chat, or call `request_user_input`/equivalent input tools. User choices belong in the review stub's `사용자 리뷰 요청` section so code-review can create `USER_REVIEW.md` and preserve the loop state.
|
||||||
|
- If required UI evidence capture needs a user-owned device, emulator, permission, secret, or interactive access unavailable to the agent, fill `사용자 리뷰 요청` with attempted commands, blocker evidence, and resume condition.
|
||||||
|
- Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, review-only checklist) is code-review-skill only.
|
||||||
|
|
||||||
|
Split decision policy:
|
||||||
|
|
||||||
|
- 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:
|
||||||
|
|
||||||
|
- 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:
|
||||||
|
|
||||||
|
- A normal single-plan task uses `agent-task/{task_group}/` with a short snake_case category name, e.g. `agent-task/refactoring/`.
|
||||||
|
- If the plan is based on a selected active Milestone, use `agent-task/m-<milestone-slug>/` as the task group. Do not include the Phase slug, Epic id, Task id, or a separate task slug in the task group.
|
||||||
|
- `m-<milestone-slug>` is a reserved top-level task group namespace for Milestone-linked work. Non-roadmap tasks must not use `m-`.
|
||||||
|
- Runtime completion-event routing for `m-*` reads only the top-level `{task_group}` name. It resolves `<milestone-slug>` by matching exactly one active file at `agent-roadmap/phase/*/milestones/<milestone-slug>.md`; archive paths are not target candidates.
|
||||||
|
- 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.
|
||||||
|
- 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_]+$`.
|
||||||
|
- Valid dependent pattern: `^[0-9]{2}\+[0-9]{2}(,[0-9]{2})*_[a-z0-9_]+$`.
|
||||||
|
- `NN`, `PP`, and `QQ` are two-digit indices. Every predecessor index after `+` must be lower than `NN` and must refer to a sibling multi-plan subtask directory under the same `{task_group}`.
|
||||||
|
- The first `_` after the index or dependency list starts `{subtask_name}`. `{subtask_name}` stays short snake_case and may contain additional underscores.
|
||||||
|
- Runtime scheduling reads only the `{subtask_dir}` name: `_` means `depends_on=[]`; `+` means `depends_on` is the comma-separated index list between `+` and the first `_`.
|
||||||
|
- Subtask directory names are the source of truth for runtime dependencies. Do not hide extra dependencies only in the plan body, and do not create a bare `NN+{subtask_name}` without predecessor indices.
|
||||||
|
- A predecessor index is satisfied by a `complete.log` for the matching predecessor subtask under the same `{task_group}`. Check active siblings first, then matching archived subtasks across all archive month folders. This is a narrow exception to the normal archive skip rule: read only candidate predecessor `complete.log` files needed to prove split dependency completion.
|
||||||
|
- For predecessor index `PP`, the only valid active lookup candidates are `agent-task/{task_group}/PP_*/complete.log` and `agent-task/{task_group}/PP+*/complete.log`.
|
||||||
|
- For predecessor index `PP`, the only valid archive lookup candidates are `agent-task/archive/*/*/{task_group}/PP_*/complete.log` and `agent-task/archive/*/*/{task_group}/PP+*/complete.log`.
|
||||||
|
- Archive lookup matches the predecessor index at the start of the archived subtask directory name, such as `01_...` or `01+...`, under the same `{task_group}`. If multiple candidates match one predecessor index, do not choose by guess; record the ambiguity and require a concrete task path or runtime selection.
|
||||||
|
- Do not treat an archived predecessor as the active task to edit. Archive lookup is only for dependency satisfaction before writing or implementing a dependent split plan.
|
||||||
|
- 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`.
|
||||||
|
- Preserve task group and subtask directory names verbatim; do not normalize, reinterpret, or choose execution order by agent judgment.
|
||||||
|
|
||||||
|
Routing rules:
|
||||||
|
|
||||||
|
- Build routing should be calibrated so a normal mixed backlog can use both lanes substantially. This is not a per-task quota: choose from the task's evidence, but do not let either lane become the default catch-all.
|
||||||
|
- `local-G01` through `local-G10` and `cloud-G01` through `cloud-G10` are valid. Do not treat `G06+` or high complexity alone as an implicit `cloud` threshold; context volume is separate lane evidence.
|
||||||
|
- Use a higher `local-GNN` when risk can be contained by explicit planning, focused code review, deterministic tests, split subtasks, and bounded required context.
|
||||||
|
- Use `cloud-GNN` when the task needs stronger reasoning, larger-than-local context, or evidence recovery than local should be expected to provide: unclear external behavior, weak or missing verification for user-visible behavior, high-risk architecture judgment, security/auth/storage/concurrency/protocol changes with hard-to-review failure modes, repeated local failure, verification trust failures, or required source/test/call-site/log/review context that local cannot hold without omitting material evidence.
|
||||||
|
- 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.
|
||||||
|
- Review uses the same balance: choose `local` for review-detectable work with bounded scope, bounded context, and rerunnable verification, and choose `cloud` for reviews requiring frontier-level judgment, larger-than-local context, weak tests, security/auth, storage/migration, concurrency, protocol/schema, cross-domain behavior, repeated Required issues, or untrusted verification evidence.
|
||||||
|
- 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:
|
||||||
|
|
||||||
|
| State | Meaning |
|
||||||
|
|-------|---------|
|
||||||
|
| `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` + `CODE_REVIEW-*-G??.md` with filled `사용자 리뷰 요청` | Implementation claims a user-only 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; user decision is required 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`) | Task terminated mid-loop or abandoned |
|
||||||
|
|
||||||
|
## Step 1 - Determine Task
|
||||||
|
|
||||||
|
If the user names the task explicitly, use that task group or task path.
|
||||||
|
|
||||||
|
Otherwise, find active plan files with both globs, excluding `agent-task/archive/**`:
|
||||||
|
|
||||||
|
- `agent-task/*/PLAN-*-G??.md`
|
||||||
|
- `agent-task/*/*/PLAN-*-G??.md`
|
||||||
|
|
||||||
|
Also note active user-review stops, excluding `agent-task/archive/**`:
|
||||||
|
|
||||||
|
- `agent-task/*/USER_REVIEW.md`
|
||||||
|
- `agent-task/*/*/USER_REVIEW.md`
|
||||||
|
|
||||||
|
| Result | Action |
|
||||||
|
|--------|--------|
|
||||||
|
| Exactly one | Continue that task |
|
||||||
|
| None | Create a new task only for a feature/refactor/fix/follow-up that belongs in this workflow |
|
||||||
|
| Multiple | If the user/runtime named a task group, task path, or subtask directory that identifies exactly one active plan, use it. Otherwise list paths and ask which task to use; do not choose by agent judgment. |
|
||||||
|
|
||||||
|
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 user decision is required and list the paths unless the user explicitly asked to resume one of them. If a selected active task directory contains `USER_REVIEW.md`, read it before planning. Do not write a new follow-up plan unless the user explicitly decides to continue, replan, retry after preparing the environment, or change the task scope. 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 user 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 the user decides whether to resume from user review or continue the active plan/review.
|
||||||
|
|
||||||
|
로드맵 확인:
|
||||||
|
|
||||||
|
- `agent-roadmap/current.md`는 브랜치별 로컬 포인터다. 있으면 구현 계획 파일을 만들기 전에 읽고, 사용자 요청, 브랜치, 변경 경로를 기준으로 관련 Phase와 Milestone을 선택한다.
|
||||||
|
- `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, 완료 리뷰, 범위 제외, 구현 잠금을 확인한다. `승격 조건`은 `[스케치]`에서만 필수이며, `[계획]` 이상에서 섹션이 없으면 `없음`으로 본다. `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인하고, 그 결정 없이는 `PLAN-*-G??.md`, `CODE_REVIEW-*-G??.md`, file/API/package 수준 구현 단계를 확정하지 않는다.
|
||||||
|
- 선택한 Milestone에 legacy `필수 기능`/`완료 기준`이 분리되어 있으면 plan 작성 전에 roadmap preflight로 정규화한다. 흡수 가능한 기준은 관련 기능 Task 안의 선택적 `검증:` 또는 Task 설명으로 즉시 흡수하고, 어느 기능에도 붙지 않는 기준이 남으면 plan 파일을 만들지 말고 남은 기준과 필요한 사용자 판단을 구체적으로 보고한다.
|
||||||
|
- 선택한 Phase 또는 Milestone 상태가 `[스케치]`이면 구현 계획 파일을 만들지 않는다. `[스케치]`는 컨셉 상태이므로 `update-roadmap`의 concretize 흐름으로 승격 조건, 결정 필요, 범위, 기능 Task를 정리해 `[계획]`으로 전환해야 한다고 보고한다.
|
||||||
|
- Phase 또는 Milestone 후보가 여럿이면 요청 문장, 변경 경로 직접성, Milestone 상태, 구현 잠금, 선후 의존성, Phase/Milestone 흐름상 위치를 기준으로 1순위와 2순위를 추천하고 필요한 후보 문서만 읽어 범위를 좁힌다.
|
||||||
|
- 로드맵 current가 있고 활성 Phase/Milestone 밖 작업이면 `ROADMAP.md`의 Phase 흐름을 확인하고 전환, 신규 Phase/Milestone, 또는 기존 활성 범위 내 배치 필요성을 보고한다.
|
||||||
|
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 기존 구조, 도메인 rule, 플랫폼 관례로 정할 수 있는 세부는 표준선/가정으로 계획에 기록하고 진행할 수 있다.
|
||||||
|
- 사용자가 선택한 Milestone의 작업, 구현, 계획 작성을 명시했고 현재 계획에 필요한 결정이 모두 정해져 있다면 계획 작성을 이어간다. Milestone 전체에서 사용자만 결정할 항목이 더 이상 없을 때만 roadmap update 흐름으로 `구현 잠금` 상태를 `해제`로 갱신한다. 현재 요청에 직접 걸리는 결정이 필요하면 그 항목만 체크리스트로 남기고 사용자에게 확인한다.
|
||||||
|
- 사용자 검토, 제품 선택, 우선순위 결정처럼 사용자가 해야 하는 항목은 구현 계획의 실행 checklist로 쓰지 않는다. 현재 구현에 직접 필요하면 plan 생성을 멈추고 `결정 필요`로 남기며, 직접 필요하지 않으면 `작업 컨텍스트`나 `범위 결정 근거`에만 기록한다.
|
||||||
|
- 기능 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>`일 때만 쓴다.
|
||||||
|
- Milestone 작업이 아니거나, Milestone 안의 조사/하위 구현처럼 특정 기능 Task 완료를 주장하지 않는 계획이면 `Roadmap Targets` 섹션을 쓰지 않는다. 섹션이 없으면 PASS 후에도 roadmap Task 체크를 하지 않는다.
|
||||||
|
- `agent-roadmap/` 디렉터리가 없으면 기존 task routing 규칙대로 진행한다.
|
||||||
|
|
||||||
|
Use short snake_case task group names for non-roadmap work, e.g. `api_refactor`.
|
||||||
|
|
||||||
|
Before choosing plan files or task directory names, apply the split decision policy above. When the policy allows a single plan, write active files directly under `agent-task/{task_group}/` and record the exception rationale. When the policy requires multiple plans, choose one shared `{task_group}` and `{subtask_dir}` names using the task directory naming rules above. Do not put multiple active plan files in one active task directory, and do not mix split subtask directories with active plan/review files directly in the parent task group.
|
||||||
|
|
||||||
|
## 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. The only allowed pre-plan file edits are local `agent-roadmap/current.md` creation or `.gitignore` block repair needed for roadmap routing, plus `create-test` or `update-test` edits needed to make test rules usable for this plan.
|
||||||
|
|
||||||
|
- [ ] **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.
|
||||||
|
- [ ] **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 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.
|
||||||
|
|
||||||
|
## Step 3 - Determine GXX Grade
|
||||||
|
|
||||||
|
GXX is an output of analysis, not an input. Determine lane and grade only after Step 2 is fully complete.
|
||||||
|
|
||||||
|
- [ ] **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: concurrency, storage/migration, protocol/schema, auth, irreversible behavior.
|
||||||
|
- [ ] **Evaluate test confidence** — judge whether existing tests sufficiently verify the changed behavior.
|
||||||
|
- [ ] **Decide lane** — choose between `local` and `cloud` after weighing both sets of signals. Across a normal mixed backlog, both lanes should appear regularly; do not force a quota for one task, and do not let either lane become the catch-all.
|
||||||
|
- Prefer `local` when the task can be made explicit, deterministic, and review-detectable; when affected files, call sites, and required context are bounded; when tests or focused smoke checks can be rerun locally; or when split subtasks can contain risk.
|
||||||
|
- Prefer `cloud` when the task is too large for local context to hold the required source files, tests, call-site graph, generated artifacts, logs, or review evidence without omitting material context.
|
||||||
|
- Prefer `cloud` when split subtasks still require broad cross-module or cross-domain context to be understood safely, even if each edit could be applied locally.
|
||||||
|
- Prefer `cloud` when required behavior depends on unclear external systems or user-visible behavior that cannot be verified deterministically.
|
||||||
|
- Prefer `cloud` when verification is weak or missing in a way that review cannot reliably detect.
|
||||||
|
- Prefer `cloud` when security/auth, storage/migration, concurrency, or protocol/schema risk has hard-to-review failure modes.
|
||||||
|
- Prefer `cloud` when prior local attempts failed for non-trivial reasoning or evidence-trust reasons.
|
||||||
|
- Prefer `cloud` when terminal-agent work is central: shell/CLI workflow implementation, bin script orchestration, process control, stdout/stderr parsing, exit-status contracts, long-running command diagnosis, or terminal benchmark-style tasks.
|
||||||
|
- Prefer `cloud` when real bin/smoke/integration verification failed after unit tests passed.
|
||||||
|
- Prefer `cloud` when interactive TUI/PTY/browser/external CLI automation or screen-rendered output is part of the success condition and cannot be reduced to deterministic evidence.
|
||||||
|
- Prefer `cloud` when a prior review marked verification trust Fail/Warn because recorded command output did not match a rerun.
|
||||||
|
- [ ] **Decide GNN** — assign a higher 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 the lane evidence supports them.
|
||||||
|
|
||||||
|
## Step 4 - Archive Existing Active Files
|
||||||
|
|
||||||
|
Before writing new active files for the chosen active task directory:
|
||||||
|
|
||||||
|
- 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 user explicitly decided to resume planning, rename `USER_REVIEW.md` to `user_review_U.log`.
|
||||||
|
|
||||||
|
The new plan number is the count of `plan_*.log` after archiving.
|
||||||
|
|
||||||
|
## Step 5 - Write Plan File
|
||||||
|
|
||||||
|
Header line must be exactly:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
<!-- task={task_name} plan={N} tag={TAG} -->
|
||||||
|
```
|
||||||
|
|
||||||
|
Required sections:
|
||||||
|
|
||||||
|
- Title.
|
||||||
|
- `이 파일을 읽는 구현 에이전트에게`: 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 user-only decision, user-owned external environment prerequisite, or scope conflict, the implementer must fill the review stub's `사용자 리뷰 요청` section with exact 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 evidence gaps a follow-up agent can close by rerunning commands or collecting artifacts are not user-review requests by themselves.
|
||||||
|
- `배경`: 2-4 sentences explaining why the work is needed.
|
||||||
|
- `사용자 리뷰 요청 흐름`: state that implementation-time blockers 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.
|
||||||
|
- `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`
|
||||||
|
- Task ids:
|
||||||
|
- `<task-id>`: <Task text or concise label>
|
||||||
|
- Completion mode: 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.
|
||||||
|
- `수정 파일 요약`: 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:
|
||||||
|
|
||||||
|
- `문제`: 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 `의존 관계 및 구현 순서` 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, `의존 관계 및 구현 순서` 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:
|
||||||
|
|
||||||
|
- Exact line numbers in every Before snippet.
|
||||||
|
- Use the language's required override annotation/keyword wherever an abstract method is implemented.
|
||||||
|
- Include full import statements for new packages.
|
||||||
|
- List all call sites for renamed/removed symbols.
|
||||||
|
- Never write "add tests as needed"; decide up front.
|
||||||
|
- Do not cite files you did not read.
|
||||||
|
- Be concise. Write the minimum words needed to convey the decision or fact. No preamble, no restatement of context already in the plan, no closing summaries.
|
||||||
|
|
||||||
|
Test policy:
|
||||||
|
|
||||||
|
| Change | Test requirement |
|
||||||
|
|--------|------------------|
|
||||||
|
| Bug fix | Regression test required |
|
||||||
|
| New public API | Normal + boundary tests required |
|
||||||
|
| API rename | Existing test call-site updates usually enough |
|
||||||
|
| Internal refactor | Existing tests may be enough |
|
||||||
|
| Concurrency logic | Race/ordering test recommended |
|
||||||
|
|
||||||
|
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 `계획 대비 변경 사항`, 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.
|
||||||
|
- 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`.
|
||||||
|
- `검증 결과` 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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
```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 user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||||
|
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||||
|
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||||
|
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||||
|
|
||||||
|
## 개요
|
||||||
|
|
||||||
|
date={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}
|
||||||
|
|
||||||
|
## 이 파일을 읽는 리뷰 에이전트에게
|
||||||
|
|
||||||
|
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||||
|
|
||||||
|
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||||
|
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||||
|
|
||||||
|
1. 판정을 append한다.
|
||||||
|
2. `CODE_REVIEW-{review_lane}-GNN.md` → `code_review_{review_lane}_GNN_N.log`, `PLAN-{build_lane}-GNN.md` → `plan_{build_lane}_GNN_M.log`로 아카이브한다.
|
||||||
|
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다. `USER_REVIEW.md`가 사용자 결정으로 완료/PASS 해소되면 code-review가 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log` 작성 후 archive 이동한다.
|
||||||
|
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||||
|
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 구현 항목별 완료 여부
|
||||||
|
|
||||||
|
| 항목 | 완료 여부 |
|
||||||
|
|------|---------|
|
||||||
|
| [{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가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||||
|
|
||||||
|
## 계획 대비 변경 사항
|
||||||
|
|
||||||
|
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||||
|
|
||||||
|
## 주요 설계 결정
|
||||||
|
|
||||||
|
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||||
|
|
||||||
|
## 사용자 리뷰 요청
|
||||||
|
|
||||||
|
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 사유 유형: 없음
|
||||||
|
- 결정 필요: 없음
|
||||||
|
- 차단 근거: 없음
|
||||||
|
- 실행한 검증/명령: 없음
|
||||||
|
- 자동 후속 불가 이유: 없음
|
||||||
|
- 재개 조건: 없음
|
||||||
|
|
||||||
|
## 리뷰어를 위한 체크포인트
|
||||||
|
|
||||||
|
{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 |
|
||||||
|
| 구현 항목별 완료 여부 (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 user input is required to proceed; do not ask the user directly during implementation; when filled, include exact decision, evidence, commands/output, why automatic follow-up cannot resolve it, and resume condition |
|
||||||
|
| 리뷰어를 위한 체크포인트 | 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
|
||||||
|
|
||||||
|
| Tag | Use for |
|
||||||
|
|-----|---------|
|
||||||
|
| `API` | Public API changes |
|
||||||
|
| `REFACTOR` | Internal refactoring |
|
||||||
|
| `TEST` | Test additions/fixes |
|
||||||
|
| `REVIEW_<TAG>` | Follow-up fixes after review |
|
||||||
|
|
||||||
|
## Final Checklist
|
||||||
|
|
||||||
|
- `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`.
|
||||||
|
- 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={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 user 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.
|
||||||
|
- `분석 결과 > 테스트 환경 규칙` 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 `구현 체크리스트` 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.
|
||||||
4
agent-ops/skills/common/plan/agents/openai.yaml
Normal file
4
agent-ops/skills/common/plan/agents/openai.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
interface:
|
||||||
|
display_name: "Plan"
|
||||||
|
short_description: "Write implementation plans"
|
||||||
|
default_prompt: "Use $plan to create grouped PLAN/CODE_REVIEW task files for this repository change."
|
||||||
21
agent-ops/skills/common/router.md
Normal file
21
agent-ops/skills/common/router.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# 공통 스킬 라우터
|
||||||
|
|
||||||
|
| 요청 키워드 | 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` |
|
||||||
|
| create-test, 테스트 룰 작성, 테스트 룰 생성, 테스트 규칙 작성, 테스트 규칙 생성, 테스트 환경 생성, 상황별 테스트 문서 생성, 도메인별 테스트 문서 생성, 검증 시나리오별 테스트 문서 생성, test rule 생성, agent-test 생성 | `agent-ops/skills/common/create-test/SKILL.md` |
|
||||||
|
| update-test, 테스트 룰 수정, 테스트 룰 갱신, 테스트 규칙 수정, 테스트 규칙 갱신, 테스트 환경 수정, 상황별 테스트 문서 수정, 도메인별 테스트 문서 수정, 검증 시나리오별 테스트 문서 수정, test rule 수정, agent-test 수정 | `agent-ops/skills/common/update-test/SKILL.md` |
|
||||||
|
| README 작성해줘, README 만들어줘, 프로젝트 설명 문서 만들어줘 | `agent-ops/skills/common/create-readme/SKILL.md` |
|
||||||
|
| 로드맵 만들어줘, roadmap 생성, 마일스톤 설계, goal/phase 구조 잡아줘 | `agent-ops/skills/common/create-roadmap/SKILL.md` |
|
||||||
|
| 로드맵 업데이트, roadmap 갱신, 로드맵에 추가, 로드맵 작업 추가, 로드맵 기능 추가, 로드맵 Epic 추가, 로드맵 에픽 추가, 로드맵 Task 추가, 로드맵 태스크 추가, 로드맵 테스크 추가, 로드맵 TODO 추가, 마일스톤에 추가, 마일스톤 추가, 마일스톤 갱신, 마일스톤 아카이브, phase 추가, phase 변경, 페이즈 추가, 페이즈 변경, 현재 마일스톤 변경, 로드맵 한국어 전환, 로드맵 번역 | `agent-ops/skills/common/update-roadmap/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` |
|
||||||
|
| 코드 리뷰해줘, 리뷰 진행해, 리뷰해줘, 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` |
|
||||||
43
agent-ops/skills/common/sync-pull/SKILL.md
Normal file
43
agent-ops/skills/common/sync-pull/SKILL.md
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
name: sync-pull
|
||||||
|
description: agentic-framework에서 현재 프로젝트로 agent-ops를 내려받는다. "agent-ops pull해", "agentic-framework에서 가져와" 요청 시 사용한다.
|
||||||
|
---
|
||||||
|
|
||||||
|
# sync-pull
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
`agent-ops/bin/sync.sh --pull`을 호출해 agentic-framework → 현재 프로젝트 방향으로 agent-ops를 내려받는다.
|
||||||
|
내려받기 과정에서 현재 프로젝트의 `.gitignore` Agent-Ops 관리 block과 AI ignore / permission 설정도 보강한다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- "agent-ops pull해", "agent-ops 가져와" 요청 시
|
||||||
|
- "agentic-framework에서 가져와" 요청 시
|
||||||
|
- "agent-ops 내려받아" 요청 시
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. 현재 프로젝트의 **상위 폴더(`../`)** 에 `agentic-framework` 폴더가 있는지 확인한다 (현재 폴더 내부가 아님)
|
||||||
|
2. **있으면**: `agent-ops/bin/sync.sh --pull agentic-framework` 실행
|
||||||
|
3. **없으면**: 사용자에게 agentic-framework 경로 입력을 안내하고, 입력받은 경로로 실행
|
||||||
|
|
||||||
|
```bash
|
||||||
|
agent-ops/bin/sync.sh --pull <target>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] sync.sh 가 오류 없이 완료됐는가
|
||||||
|
- [ ] 현재 프로젝트 버전이 framework 버전과 일치하는가
|
||||||
|
- [ ] `agent-ops/bin/entry-files.sh`의 모든 진입 파일이 갱신됐고, 내용이 framework의 `agent-ops/rules/common/rules.md`와 일치하는가
|
||||||
|
- [ ] `.gitignore`에 Agent-Ops 관리 gitignore block이 있고 `!agent-task/`, `!agent-task/**/`, `!agent-task/**/*.md`, `!agent-task/**/*.log`, `agent-roadmap/current.md`가 포함되어 있는가
|
||||||
|
- [ ] `agent-roadmap/current.md`가 있으면 파일은 보존되고 git 추적 대상에서는 제거됐는가
|
||||||
|
- [ ] `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에 Agent-Ops 관리 block이 있고 그 안에 `agent-task/archive/**`와 `agent-roadmap/archive/**`가 포함되어 있는가
|
||||||
|
- [ ] `.claude/settings.json`, `opencode.json`에 `agent-task/archive/**` hard deny가 있고 `agent-roadmap/archive/**` hard read/glob deny가 남아 있지 않은가
|
||||||
|
- [ ] 현재 프로젝트에 기존 `agent-roadmap/archive/**` hard deny가 있으면 init-agent-ops 표준에 맞게 제거했는가
|
||||||
|
- [ ] agentic-framework의 `.gitignore`와 AI ignore / permission 파일은 수정되거나 stage되지 않았는가
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- sync.sh 를 거치지 않고 직접 파일을 복사하지 않는다
|
||||||
115
agent-ops/skills/common/sync-push/SKILL.md
Normal file
115
agent-ops/skills/common/sync-push/SKILL.md
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
---
|
||||||
|
name: sync-push
|
||||||
|
description: 현재 프로젝트의 agent-ops를 공통 원본 repo로 올리거나, `.agent-ops-source`가 있는 공통 원본 repo의 agent-ops를 대상 프로젝트 또는 상위 폴더의 agent-ops 적용 프로젝트 전체로 push하고 푸시한다. "agent-ops 싱크해", "agent-ops 동기화해", "agentic-framework에 올려줘" 요청 시 사용한다.
|
||||||
|
---
|
||||||
|
|
||||||
|
# sync-push
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
`agent-ops/bin/sync.sh`를 호출해 agent-ops 공통 파일을 push 방향으로 동기화한다.
|
||||||
|
|
||||||
|
- 일반 프로젝트에서는 현재 프로젝트 → `.agent-ops-source`가 있는 공통 원본 repo 방향으로 올린다.
|
||||||
|
- `.agent-ops-source`가 있는 공통 원본 repo에서는 원본 repo → 대상 프로젝트 방향으로 보내고, 대상 repo를 commit/push 한다.
|
||||||
|
- 공통 원본 repo에서 대상이 명시되지 않으면 현재 프로젝트의 상위 폴더에 있는 agent-ops 적용 프로젝트 전체로 보낸다.
|
||||||
|
|
||||||
|
## 버전 정책
|
||||||
|
|
||||||
|
- 현재 프로젝트 루트에 `.agent-ops-source`가 있으면, 대상 프로젝트로 전파하는 push 동기화는 버전을 올리지 않는다.
|
||||||
|
- 이 경우 현재 공통 원본 repo의 `agent-ops/.version` 값을 그대로 대상 repo에 전파한다.
|
||||||
|
- 일반 프로젝트에서 `.agent-ops-source`가 있는 공통 원본 repo로 공통 변경을 올리는 push 동기화는 기존처럼 `sync.sh`가 버전을 한 단계 올린다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- "agent-ops 싱크해", "agent-ops 동기화해" 요청 시
|
||||||
|
- "agentic-framework에 올려줘" 요청 시
|
||||||
|
- "agent-ops를 [프로젝트]로 싱크해" 요청 시
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
### 현 프로젝트가 일반 프로젝트인 경우 (`.agent-ops-source` 없음)
|
||||||
|
|
||||||
|
1. 현재 프로젝트의 **상위 폴더(`../`)** 에 `.agent-ops-source`가 있는 공통 원본 repo가 있는지 확인한다. 기본 후보는 `agentic-framework`다.
|
||||||
|
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. 공통 관리 파일 변경이 있으면 `sync.sh`가 버전을 한 단계 올리고 현재 프로젝트와 공통 원본 repo에 같은 버전을 반영한다
|
||||||
|
6. 일반 프로젝트에서 공통 원본 repo로 올릴 때는 AI ignore / permission 파일을 보강하거나 stage하지 않는다
|
||||||
|
|
||||||
|
### 현 프로젝트가 공통 원본 repo인 경우 (`.agent-ops-source` 있음)
|
||||||
|
|
||||||
|
1. 사용자 요청에서 target 프로젝트명 또는 경로를 추출한다
|
||||||
|
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`를 단일 기준으로 사용한다.
|
||||||
|
|
||||||
|
| 에이전트 | 파일명 |
|
||||||
|
|---------|--------|
|
||||||
|
| Gemini | `GEMINI.md` |
|
||||||
|
| Claude | `CLAUDE.md` |
|
||||||
|
| Kilo Code / OpenCode | `AGENTS.md` |
|
||||||
|
| Cursor | `.cursorrules` |
|
||||||
|
| Cline | `.clinerules` |
|
||||||
|
|
||||||
|
대상 프로젝트에 기존 진입 파일이 있어도 보존하거나 병합하지 않고 `agent-ops/rules/common/rules.md` 내용으로 교체한다.
|
||||||
|
|
||||||
|
## Gitignore / AI Ignore / Permission 재적용
|
||||||
|
|
||||||
|
- 이 절차는 `.agent-ops-source`가 있는 공통 원본 repo에서 대상 프로젝트로 push할 때와 `--pull`로 공통 원본 repo에서 현재 프로젝트로 내려받을 때만 적용한다.
|
||||||
|
- 일반 프로젝트에서 공통 원본 repo로 올리는 push에서는 `.gitignore`와 AI ignore / permission 파일을 수정하거나 stage하지 않는다.
|
||||||
|
- `.gitignore`는 사용자 영역을 수정하지 않고 아래 관리 block만 추가하거나 교체한다. 이 예외는 `*.log` 같은 전역 ignore가 있어도 plan/review/archive task 산출물이 git에 잡히도록 하고, `agent-roadmap/current.md`는 브랜치별 로컬 포인터로 남긴다.
|
||||||
|
|
||||||
|
```text
|
||||||
|
# BEGIN Agent-Ops managed gitignore
|
||||||
|
!agent-task/
|
||||||
|
!agent-task/**/
|
||||||
|
!agent-task/**/*.md
|
||||||
|
!agent-task/**/*.log
|
||||||
|
agent-roadmap/current.md
|
||||||
|
# END Agent-Ops managed gitignore
|
||||||
|
```
|
||||||
|
|
||||||
|
- `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`는 사용자 영역을 수정하지 않고 아래 관리 block만 추가하거나 교체한다.
|
||||||
|
|
||||||
|
```text
|
||||||
|
# BEGIN Agent-Ops managed ignore
|
||||||
|
agent-task/archive/**
|
||||||
|
agent-roadmap/archive/**
|
||||||
|
# END Agent-Ops managed ignore
|
||||||
|
```
|
||||||
|
|
||||||
|
- 관리 block 밖의 기존 ignore 항목은 사용자 소유로 보고 삭제, 정렬, 중복 제거하지 않는다.
|
||||||
|
- `.claude/settings.json`과 `opencode.json`은 기존 사용자 설정을 보존하고 `agent-task/archive/**` hard read/glob deny만 보강한다.
|
||||||
|
- `agent-roadmap/archive/**`는 필요한 경우 링크로 읽을 수 있어야 하므로 `.claude/settings.json`이나 `opencode.json`의 hard read/glob deny로 두지 않는다.
|
||||||
|
- 대상 프로젝트에 기존 `agent-roadmap/archive/**` hard read/glob deny가 있으면 init-agent-ops 표준에 맞게 제거한다.
|
||||||
|
- `opencode.json`의 watcher ignore에는 `agent-task/archive/**`와 `agent-roadmap/archive/**`를 둘 수 있다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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한다.
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] sync.sh 가 오류 없이 완료됐는가
|
||||||
|
- [ ] 버전 충돌 경고가 없었는가 — 있었다면 사용자에게 수동 머지 필요함을 알린다
|
||||||
|
- [ ] 대상 repo의 `agent-ops/rules/common/rules.md`가 현재 공통 원본 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/**` hard deny가 있고 `agent-roadmap/archive/**` hard read/glob deny가 남아 있지 않은가
|
||||||
|
- [ ] 대상 프로젝트에 기존 `agent-roadmap/archive/**` hard deny가 있으면 init-agent-ops 표준에 맞게 제거했는가
|
||||||
|
- [ ] 일반 프로젝트에서 공통 원본 repo로 push한 경우, `.gitignore`와 AI ignore / permission 파일이 공통 원본 repo에 유입되지 않았는가
|
||||||
|
- [ ] 대상 repo에 commit/push 된 path가 방향별 허용 범위로 제한되었는가
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- sync.sh 를 거치지 않고 직접 파일을 복사하지 않는다
|
||||||
117
agent-ops/skills/common/update-domain-rule/SKILL.md
Normal file
117
agent-ops/skills/common/update-domain-rule/SKILL.md
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
---
|
||||||
|
name: update-domain-rule
|
||||||
|
version: 1.0.0
|
||||||
|
description: 기존 도메인 rules.md를 코드 현황에 맞게 갱신. 전체 스캔(full) 또는 지정 도메인(targeted) 두 모드 지원
|
||||||
|
---
|
||||||
|
|
||||||
|
# update-domain-rule
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
프로젝트 코드가 변경되면서 기존 domain rule이 실제 구조와 어긋날 수 있다.
|
||||||
|
이 스킬은 실제 파일 구조를 탐색하여 기존 `rules.md`와 비교하고, 누락·오류·구식 항목을 수정한다.
|
||||||
|
갱신한 domain rule에는 어디까지의 코드 커밋을 검토 기준으로 삼았는지 기록한다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 대규모 리팩터링 또는 외부 패키지 내재화 후 domain rule 동기화가 필요할 때
|
||||||
|
- 특정 도메인 파일 구조가 바뀌어 기존 rule이 맞지 않을 때
|
||||||
|
- 사용자가 "도메인 업데이트", "domain rule 갱신", "domain 검토" 등을 요청할 때
|
||||||
|
- 로컬 모델의 자동 판단 런타임이 frontier 모델에게 domain rule 검토를 위임한 경우
|
||||||
|
- agent-ops 초기 scaffold 이후 코드가 많이 달라진 경우
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `mode`: `full`(전체 도메인 스캔) | `targeted`(지정 도메인만) (필수)
|
||||||
|
- `domain-name`: 업데이트할 도메인 이름 — `targeted` 모드에서만 필수
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] `agent-ops/rules/project/domain/` 하위 기존 도메인 목록 확인
|
||||||
|
- [ ] `agent-ops/rules/common/_templates/domain-rule-template.md` 읽어 최신 템플릿 형식 파악
|
||||||
|
- [ ] `targeted` 모드이면 `agent-ops/rules/project/domain/<domain-name>/rules.md` 존재 여부 확인
|
||||||
|
- 존재하지 않으면 `create-domain-rule` 스킬을 사용하도록 안내하고 중단
|
||||||
|
- [ ] `git rev-parse HEAD` 로 기준 커밋을 확인
|
||||||
|
- 이 값은 이번 domain rule 수정이 들어갈 미래 커밋 해시가 아니다
|
||||||
|
- 의미: "이 커밋까지의 코드 상태를 보고 domain rule을 검토했다"
|
||||||
|
- 코드 변경과 domain rule 변경이 같은 커밋에 섞여 있으면 다음 자동 판단에서 같은 코드 변경이 다시 후보로 잡힐 수 있으므로, 가능하면 코드 변경 커밋 이후 깨끗한 작업 트리에서 실행한다
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **대상 목록 결정**
|
||||||
|
- `full`: `agent-ops/rules/project/domain/` 하위 모든 도메인 디렉터리를 대상으로 한다
|
||||||
|
- `targeted`: 지정된 `domain-name` 하나만 대상으로 한다
|
||||||
|
|
||||||
|
2. **도메인별 코드 탐색**
|
||||||
|
- 기존 `rules.md`의 **포함 경로** 목록을 기준으로 실제 파일 구조 탐색
|
||||||
|
- 포함 경로에 없지만 도메인 이름과 연관된 경로도 함께 탐색
|
||||||
|
- 탐색 시 실제로 존재하는 경로만 수집한다
|
||||||
|
|
||||||
|
3. **비교 및 변경 항목 식별**
|
||||||
|
다음 항목 각각을 현재 `rules.md`와 비교한다:
|
||||||
|
- **포함 경로**: 실제로 존재하지 않는 경로 제거, 새로 생긴 경로 추가
|
||||||
|
- **주요 구성 요소**: 파일/클래스 삭제·이름 변경·신규 추가 반영
|
||||||
|
- **유지할 패턴**: 코드에서 더 이상 사용되지 않는 패턴 제거, 새 패턴 추가
|
||||||
|
- **다른 도메인과의 경계**: 도메인 간 import 관계가 바뀐 경우 반영
|
||||||
|
- **목적/책임**: 도메인 책임이 실질적으로 변경된 경우에만 수정
|
||||||
|
|
||||||
|
4. **rules.md 업데이트**
|
||||||
|
- 변경이 필요한 항목만 수정한다 — 변경 불필요한 섹션은 그대로 둔다
|
||||||
|
- frontmatter가 없으면 `domain-rule-template.md` 형식으로 추가한다
|
||||||
|
- `last_rule_review_commit`에는 실행 초기에 확인한 `git rev-parse HEAD` 값을 기록한다
|
||||||
|
- `last_rule_updated_at`에는 갱신일을 `YYYY-MM-DD` 형식으로 기록한다
|
||||||
|
- 본문 섹션에 반영할 변경이 없더라도 검토가 완료되었다면 기준 커밋 메타데이터는 갱신한다
|
||||||
|
- 확인된 사실만 기재한다; 불확실하면 `<!-- TODO: 확인 필요 -->` 주석 처리
|
||||||
|
- `domain-rule-template.md`의 섹션 구조를 유지한다
|
||||||
|
|
||||||
|
5. **자동 판단 런타임 기준**
|
||||||
|
- 로컬 모델은 각 domain rule의 `last_rule_review_commit..HEAD` 범위를 기준으로 변경 커밋을 확인한다
|
||||||
|
- 판단 대상은 해당 도메인의 코드 경로이며, `agent-ops/rules/project/domain/**` 변경만으로는 다시 위임하지 않는다
|
||||||
|
- `last_rule_review_commit`이 없거나 유효하지 않으면 보수적으로 frontier 모델에게 위임한다
|
||||||
|
|
||||||
|
6. **도메인 매핑 테이블 검토** (`full` 모드 시)
|
||||||
|
- `agent-ops/rules/project/rules.md`의 도메인 매핑 테이블과 실제 포함 경로 비교
|
||||||
|
- 누락된 경로 패턴은 추가, 존재하지 않는 경로 패턴은 제거
|
||||||
|
- 기존 항목 순서는 변경하지 않는다
|
||||||
|
|
||||||
|
7. **결과 보고**
|
||||||
|
- 도메인별로 수정한 항목 목록
|
||||||
|
- `TODO`로 남긴 항목 (해당 시)
|
||||||
|
- 도메인 매핑 테이블 변경 내용 (full 모드 시)
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] 수정된 `rules.md`의 포함 경로가 모두 실제 프로젝트에 존재하는가
|
||||||
|
- [ ] 섹션 구조가 `domain-rule-template.md` 형식을 유지하는가
|
||||||
|
- [ ] `last_rule_review_commit`이 이번 갱신 직전 `HEAD`를 가리키는가
|
||||||
|
- [ ] 변경하지 않아도 되는 섹션이 의도치 않게 바뀌지 않았는가
|
||||||
|
- [ ] `full` 모드에서 도메인 매핑 테이블이 실제 포함 경로와 일치하는가
|
||||||
|
- 검증 실패 시: 실제 존재하지 않는 경로나 누락된 섹션을 사용자에게 알리고 해당 항목만 보완한다
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```
|
||||||
|
## 업데이트 완료
|
||||||
|
|
||||||
|
### <domain-name>
|
||||||
|
- 변경: <수정된 항목 요약>
|
||||||
|
- 추가: <새로 추가된 경로/구성 요소>
|
||||||
|
- 제거: <삭제된 경로/구성 요소>
|
||||||
|
- 유지: 변경 없음 또는 기준 커밋 메타데이터만 갱신
|
||||||
|
- 기준 커밋: <last_rule_review_commit>
|
||||||
|
|
||||||
|
### 도메인 매핑 테이블 (full 모드 시)
|
||||||
|
- 추가: <새 경로 패턴>
|
||||||
|
- 제거: <삭제된 경로 패턴>
|
||||||
|
|
||||||
|
## TODO 항목 (확인 필요)
|
||||||
|
- <불확실하여 직접 확인이 필요한 항목> (해당 시)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 실제 존재하지 않는 경로를 포함 경로에 기재하지 않는다
|
||||||
|
- 추측으로 패턴·금지 사항을 추가하지 않는다 — 코드에서 확인된 내용만 기재한다
|
||||||
|
- 신규 도메인 생성이 필요한 경우 직접 생성하지 않고 `create-domain-rule` 스킬 사용을 안내한다
|
||||||
|
- `rules/project/rules.md`의 기존 항목을 삭제하거나 재정렬하지 않는다
|
||||||
|
- 코드 파일을 수정하지 않는다 — 이 스킬은 rule 파일 갱신만 담당한다
|
||||||
424
agent-ops/skills/common/update-roadmap/SKILL.md
Normal file
424
agent-ops/skills/common/update-roadmap/SKILL.md
Normal file
|
|
@ -0,0 +1,424 @@
|
||||||
|
---
|
||||||
|
name: update-roadmap
|
||||||
|
version: 1.21.0
|
||||||
|
description: 로드맵 업데이트, 로드맵에 추가, 마일스톤 추가/갱신, phase/페이즈 변경 요청에 사용한다. Roadmap-Phase-Milestone scaffold에서 target 없는 신규 작업의 규모를 판정하고 기존 Phase/Milestone/Epic/Task를 검색해 upsert한 뒤, 없을 때만 새 항목을 만들고 로컬 current.md 동기화, runtime m-task 완료 이벤트 반영, 완료 후보 검토중 전환, 승인된 archive 이동, workspace 외부 의존 잠금 양방향 동기화를 처리한다.
|
||||||
|
---
|
||||||
|
|
||||||
|
# 로드맵 업데이트
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
기존 `agent-roadmap/` 구조를 현재 프로젝트 방향과 진행 상태에 맞게 갱신한다.
|
||||||
|
표준 구조는 `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 창이 실제 작업 후보 목록으로 동작하게 한다.
|
||||||
|
|
||||||
|
Milestone은 구현 계획이 아니라 방향성, 범위, 위험, 확인 필요 사항을 기록하는 협업 문서로 유지한다.
|
||||||
|
Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능` 안에서 관리한다. 별도 `완료 기준` 섹션은 만들지 않고, 검증이 필요한 기능에만 같은 Task 안의 `검증:` 문구로 통합한다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 사용자가 "로드맵 업데이트", "마일스톤 갱신", "phase 변경", "현재 활성 마일스톤 바꿔줘"라고 요청할 때
|
||||||
|
- 사용자가 "로드맵에 추가", "로드맵 작업 추가", "로드맵 기능 추가", "로드맵 Epic/Task 추가", "로드맵 에픽/태스크 추가", "마일스톤에 추가", "마일스톤 추가"처럼 로드맵에 새 내용을 넣어 달라고 요청할 때
|
||||||
|
- Milestone 완료, 보류, 폐기, 신규 추가가 필요할 때
|
||||||
|
- Phase 완료, 보류, 폐기, 신규 추가가 필요할 때
|
||||||
|
- 완료 또는 폐기된 Phase/Milestone을 archive로 이동해야 할 때
|
||||||
|
- 런타임이 `m-<milestone-slug>` task group의 PASS 완료 이벤트를 Milestone에 반영해야 할 때
|
||||||
|
- 특정 기능이나 작업을 새 Milestone, 기존 Milestone의 Epic, 기존 Epic의 Task 중 적절한 위치에 추가해야 할 때
|
||||||
|
- 활성 Phase/Milestone 창에 포함할 목록이 달라졌을 때
|
||||||
|
- 기존 로드맵을 `phase/<phase-slug>/PHASE.md` scaffold로 마이그레이션하거나 표준화해야 할 때
|
||||||
|
- 사용자가 "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"처럼 외부 의존 잠금을 말할 때
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `mode`: `status` / `milestone` / `phase` / `replan` / `sync` / `concretize` / `archive` 중 하나 (선택, 요청에서 추론 가능)
|
||||||
|
- `target-phase`: 갱신할 Phase 이름, slug, 파일 경로 (선택)
|
||||||
|
- `target-milestone`: 갱신할 Milestone 이름, slug, 파일 경로 (선택)
|
||||||
|
- `active-phases`: 활성 Phase 창에 둘 Phase 이름, slug, 파일 경로 목록 (선택)
|
||||||
|
- `active-milestones`: 활성 Milestone 창에 둘 Milestone 이름, slug, 파일 경로 목록 (선택)
|
||||||
|
- `new-feature`: 추가할 기능, 작업, 또는 새 Milestone 설명 (선택)
|
||||||
|
- `placement`: 새 작업 배치 위치. 예: `<phase-name> 안`, `<milestone-name> 안`, `<epic-id> 아래`, `<item-id> 앞`, `<item-id> 뒤`, `auto` (선택)
|
||||||
|
- `placement-unit`: 삽입 단위. `phase` / `milestone` / `epic` / `task` / `subtask` / `auto` 중 하나 (선택)
|
||||||
|
- `target-status`: 전환할 Phase/Milestone 상태. `[스케치]` / `[계획]` / `[진행중]` / `[검토중]` / `[완료]` / `[보류]` / `[폐기]` 중 하나 (선택)
|
||||||
|
- `lock-state`: Milestone 구현 잠금 상태. `잠금` / `해제` 중 하나 (선택)
|
||||||
|
- `decision-needed`: `구현 잠금`에 남길 사용자만 결정할 수 있는 질문 목록 (선택)
|
||||||
|
- `evidence`: 완료 판단에 사용할 파일, PR, 테스트, 커밋, 사용자 설명 (선택)
|
||||||
|
- `complete-log`: 런타임 완료 이벤트가 전달한 `complete.log` 경로. `Roadmap Completion` 섹션이 있을 때만 Milestone 기능 Task 체크에 사용한다 (선택)
|
||||||
|
- `review-state`: 완료 리뷰 상태. `요청됨` / `승인됨` / `보완 필요` / `보류` / `폐기` 중 하나 (선택)
|
||||||
|
- `review-comment`: 완료 리뷰에 남길 사용자 확인, 보완, 보류, 폐기 방향성 (선택)
|
||||||
|
- `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`에 기록하거나 동기화할 외부 의존 잠금 설명 (선택)
|
||||||
|
|
||||||
|
## 표준 구조
|
||||||
|
|
||||||
|
```text
|
||||||
|
agent-roadmap/
|
||||||
|
ROADMAP.md
|
||||||
|
current.md # local, git ignored
|
||||||
|
phase/
|
||||||
|
<phase-slug>/
|
||||||
|
PHASE.md
|
||||||
|
milestones/
|
||||||
|
<milestone-slug>.md
|
||||||
|
archive/
|
||||||
|
phase/
|
||||||
|
<phase-slug>/
|
||||||
|
PHASE.md
|
||||||
|
milestones/
|
||||||
|
<milestone-slug>.md
|
||||||
|
```
|
||||||
|
|
||||||
|
- `ROADMAP.md`는 전체 목표와 Phase 흐름만 담는다.
|
||||||
|
- `PHASE.md`는 해당 Phase의 목표, 상태, Milestone 흐름, Phase 경계를 담는다.
|
||||||
|
- Milestone 문서는 해당 Phase 하위 `milestones/`에 둔다.
|
||||||
|
- 완료된 Phase는 `archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
|
||||||
|
- 진행중 Phase 안에서 완료된 Milestone은 `archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 이동하고, 활성 `PHASE.md`에는 짧은 archive 링크를 남긴다.
|
||||||
|
- archive `PHASE.md`는 Phase 자체가 완료/폐기될 때만 만든다. 진행중 Phase의 완료 Milestone만 archive된 경우에는 archive Phase 디렉터리에 `milestones/`만 있을 수 있다.
|
||||||
|
- `<phase-slug>`와 `<milestone-slug>`는 소문자 영문, 숫자, 하이픈만 사용한다.
|
||||||
|
- `current.md`는 브랜치별 로컬 포인터이며 활성 Phase와 활성 Milestone을 모두 가리킨다.
|
||||||
|
- `current.md`는 git 추적 대상이 아니며, 공유 진행 상태는 `ROADMAP.md`, `PHASE.md`, Milestone 문서, `.agent-roadmap-sync/locks.yaml`에 기록한다.
|
||||||
|
- `current.md`에는 archive 경로를 넣지 않는다.
|
||||||
|
- `current.md`에는 `[완료]` 또는 `[폐기]` Phase/Milestone을 남기지 않는다. 완료 후보는 사용자 승인 전까지 `[검토중]`으로 둔다.
|
||||||
|
|
||||||
|
## 상태와 id
|
||||||
|
|
||||||
|
- 상태 표기는 `[스케치]`, `[계획]`, `[진행중]`, `[검토중]`, `[완료]`, `[보류]`, `[폐기]` 중 하나만 사용한다.
|
||||||
|
- 기존 비표준 상태 표기는 갱신 범위에 포함될 때 표준 상태 표기로 정리한다.
|
||||||
|
- `[스케치]`는 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태다. 구현 가능한 계획이 아니므로 `agent-task` 구현 계획 생성과 코드 구현 대상으로 삼지 않는다.
|
||||||
|
- `[스케치]` 항목은 `[계획]`으로 승격하기 위한 `승격 조건`, 사용자 결정, 범위 경계, 후속 Milestone 후보를 정리한다.
|
||||||
|
- `[계획]` 이상 Milestone에서 `승격 조건` 섹션은 선택 사항이다. 섹션이 없거나 `- 없음`이면 템플릿 오류로 보지 않는다.
|
||||||
|
- `[스케치]`를 `[계획]`으로 전환할 때는 `승격 조건`의 미정 항목이 해소되고, 목표, 범위, 기능 Task, 직접적인 사용자 결정 항목, 후속 구현 단위가 구현 계획을 만들 수 있을 만큼 정리되었는지 확인한다.
|
||||||
|
- `[계획]`은 목표, 범위, 기능 Task, 구현 잠금, 결정 필요 항목이 정리되어 구현 계획을 만들 수 있는 상태다.
|
||||||
|
- `[검토중]`은 모든 기능 Task와 Task 안에 명시된 검증이 충족된 것으로 보이나, 사용자 최종 확인과 archive 승인이 남은 완료 후보 상태다.
|
||||||
|
- 검토 결과 보완이 필요하면 별도 reopen 상태를 만들지 않고 `[진행중]`으로 되돌린 뒤 `완료 리뷰` 또는 `작업 컨텍스트`에 보완 방향을 남긴다.
|
||||||
|
- 검토 결과 보류 또는 폐기 결정이 나면 `[보류]` 또는 `[폐기]`로 전환한다.
|
||||||
|
- `ROADMAP.md`의 Phase 흐름과 `PHASE.md`의 Milestone 흐름은 완료, 검토중, 진행중, 계획, 스케치 순서를 기본으로 하며 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||||
|
- Epic heading은 `### Epic: [epic-id] <이름>` 형식으로 작성한다.
|
||||||
|
- Task는 `- [ ] [item-id] 설명` 또는 `- [x] [item-id] 설명` 형식으로 작성한다.
|
||||||
|
- epic-id와 item-id는 공백 없는 짧은 ASCII 토큰이며, 해당 Milestone 안에서만 유일하면 된다.
|
||||||
|
- 사용자가 epic-id 또는 item-id를 언급하면 해당 항목을 우선 anchor로 삼고, 기존 id는 명시적 요청 없이 바꾸지 않는다.
|
||||||
|
|
||||||
|
## 로딩 원칙
|
||||||
|
|
||||||
|
- 일반 갱신은 로컬 `current.md`, 관련 활성 Phase, 관련 활성 Milestone을 우선 읽는다.
|
||||||
|
- `current.md`가 없고 활성 창 갱신이 필요하면 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식으로 로컬 파일을 만든다.
|
||||||
|
- `ROADMAP.md`는 Phase 흐름, 전체 구조, 활성 범위 밖 작업, 전체 재계획, archive 링크 갱신이 필요할 때 읽는다.
|
||||||
|
- `agent-roadmap/archive/**`는 일반 작업이나 sync에서 읽지 않는다.
|
||||||
|
- archive 모드에서 이동 대상이 아직 활성 경로에 있으면 그 대상 문서는 읽을 수 있다.
|
||||||
|
- 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 요청이면 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라 필요한 archive 문서만 읽는다.
|
||||||
|
|
||||||
|
## 템플릿
|
||||||
|
|
||||||
|
- `ROADMAP.md`: `agent-ops/skills/common/_templates/roadmap-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`
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- `구현 잠금`은 승인 절차가 아니라 사용자 결정이 필요한지 표시하는 얇은 상태다.
|
||||||
|
- 사용자만 결정할 수 있는 제품 방향, 범위, 우선순위, 책임 경계가 남아 있으면 `잠금`으로 두고 `결정 필요` 체크리스트에 질문을 적는다.
|
||||||
|
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 합리적으로 정할 수 있는 항목은 `결정 필요`가 아니라 `작업 컨텍스트`의 표준선으로 기록한다.
|
||||||
|
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
|
||||||
|
- 잠금 상태 변경은 Milestone 완료 판정이 아니므로 `기능` Task를 자동 완료 처리하지 않는다.
|
||||||
|
- `[스케치]` Milestone은 `구현 잠금`이 `해제`로 보이더라도 구현 계획과 코드 구현 대상이 아니다. 먼저 승격 조건을 충족해 `[계획]`으로 전환한다.
|
||||||
|
|
||||||
|
## 프로젝트 간 잠금
|
||||||
|
|
||||||
|
- 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`은 프로젝트 간 Milestone 잠금 인덱스다. 외부 의존 잠금을 생성하거나 동기화해야 하면 파일이 없어도 디렉터리와 파일을 만든다.
|
||||||
|
- entry는 `id`, `locked`, `rely-on[].target`, `rely-on[].status`, `rely-on[].note`만 사용한다.
|
||||||
|
- `locks.yaml`은 root sequence block style을 기본으로 작성한다. 예: `- id: ...` 아래에 `locked`, `rely-on`을 둔다.
|
||||||
|
- `id`는 기본적으로 `<잠긴-project>:<잠긴-milestone-slug>`로 만든다.
|
||||||
|
- `locked`와 `rely-on[].target`은 `<project>:agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 형식으로 기록한다.
|
||||||
|
- Milestone 경로가 `agent-roadmap/...` 상대 경로이면 현재 프로젝트명을 prefix로 붙인다. workspace 하위 절대/상대 경로이면 workspace 바로 아래 디렉터리명을 project로 삼고, 그 뒤 `agent-roadmap/...` 경로를 붙인다.
|
||||||
|
- `locked`는 잠긴 Milestone, `rely-on.target`은 선행 조건 Milestone이다. 둘 다 같은 workspace의 어느 활성 Phase 하위 Milestone이어도 된다. 의존 대상이 `current.md`에 있어야 한다고 가정하지 않는다.
|
||||||
|
- 의존 Milestone 확정 순서:
|
||||||
|
1. 사용자가 명시한 `<project>:agent-roadmap/phase/.../milestones/<slug>.md` 또는 파일 경로
|
||||||
|
2. 사용자가 명시한 프로젝트와 Milestone slug
|
||||||
|
3. 사용자가 명시한 프로젝트와 Milestone 제목의 정규화 일치
|
||||||
|
4. 잠긴 Milestone 문서의 `선행 <project> Milestone: ...`, `관련 <project> Milestone: ...`, `외부 의존 잠금: ...`에 적힌 slug/제목 힌트
|
||||||
|
5. 프로젝트명만 있고 Milestone 힌트가 없을 때만 해당 프로젝트 로컬 `current.md`의 활성 Milestone 단일 후보
|
||||||
|
- 정규화 비교는 소문자 변환, backtick/따옴표 제거, 영문/숫자가 아닌 연속 문자를 `-` 하나로 치환, 앞뒤 `-` 제거 후 비교한다. 정규화한 힌트는 Milestone 파일 slug와 정규화한 제목 둘 다에 대조한다.
|
||||||
|
- 2-4번 탐색은 대상 프로젝트의 `agent-roadmap/phase/*/milestones/*.md` 활성 문서만 대상으로 한다. archive 문서는 사용자가 archive 경로를 명시한 경우 외에는 읽거나 후보로 삼지 않는다.
|
||||||
|
- 후보가 없거나 둘 이상이면 `locks.yaml`을 만들거나 고치지 말고 사용자에게 대상 Milestone 선택을 요청한다.
|
||||||
|
- 외부 의존 잠금 요청이 있거나, 갱신 대상 Milestone이 `구현 잠금: 잠금`이며 문서에 외부 의존 잠금/선행 Milestone 컨텍스트가 있으면 `.agent-roadmap-sync/locks.yaml`을 upsert한다. resolvable한 외부 의존 문구를 Milestone에 남기고 lock entry를 누락하지 않는다.
|
||||||
|
- 외부 의존 잠금을 만들 때 대상 Milestone의 `구현 잠금`은 `잠금`으로 둔다.
|
||||||
|
- 새 `rely-on.status`는 선행 Milestone 상태에서 파생한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태거나 상태를 확인할 수 없으면 `disable`이다.
|
||||||
|
- 같은 `id` entry를 upsert할 때 기존 `rely-on` 항목을 삭제하지 않는다. 같은 `rely-on.target`만 status/note를 갱신하고, 없는 target은 추가하며, `locked` 경로가 바뀐 경우에만 `locked`를 갱신한다.
|
||||||
|
- `locks.yaml`이 있고 Milestone을 갱신하거나 archive할 때는 대상 Milestone identity로 `agent-ops/bin/roadmap-dependency-checker.sh --find-milestone "<identity>" both "<locks-file>"`를 먼저 실행한다.
|
||||||
|
- find 결과가 `none`이면 결과 보고의 `Workspace 잠금`에 `관련 lock 없음`을 남긴다. 외부 의존 잠금 생성/동기화 요청이 아니라면 `locks.yaml`을 새로 만들거나 수정하지 않는다.
|
||||||
|
- 이 스킬이 갱신한 Milestone identity가 어느 entry의 `rely-on.target`과 일치하면 해당 `rely-on.status`를 Milestone 상태 기준으로 동기화한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태면 `disable`이다.
|
||||||
|
- 이 스킬이 갱신하거나 선택한 Milestone identity가 어느 entry의 `locked`와 일치하면 모든 `rely-on.status`가 `enable`인지 확인하고 결과 보고의 `Workspace 잠금`에 `런타임 해제 대기` 또는 `미충족`으로 남긴다.
|
||||||
|
- archive 모드에서는 파일 이동 전에 대상 Milestone의 활성 경로 identity를 보존하고, 그 identity로 `--find-milestone "<identity>" both "<locks-file>"`를 먼저 실행한다. 보존한 identity가 어느 entry의 `rely-on.target`과 일치하고 Milestone 상태가 `[완료]`이면 archive 이동 전에 해당 `rely-on.status`를 `enable`로 바꾼다.
|
||||||
|
- archive 모드에서 보존한 identity가 어느 entry의 `locked`와 일치하면 archive 이동 전에 모든 `rely-on.status`가 `enable`인지 확인해 결과 보고에 남긴다. 미충족이면 archive 자체를 막지 않지만 `Workspace 잠금: 미충족`으로 보고한다.
|
||||||
|
- 모든 `rely-on.status`가 `enable`이어도 여기서 다른 프로젝트 Milestone을 직접 해제하지 않는다. 잠금 해제 실행은 런타임이 별도 `update-roadmap` 호출로 처리한다.
|
||||||
|
|
||||||
|
## 완료 리뷰와 검토중 상태
|
||||||
|
|
||||||
|
- Task 완료 또는 Milestone 갱신 후 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`인지 확인한다.
|
||||||
|
- 모두 충족된 것으로 보이면 Milestone을 `[완료]`로 바로 바꾸거나 archive로 이동하지 말고 `[검토중]`으로 바꾼다.
|
||||||
|
- `[검토중]`으로 바꿀 때는 Milestone 문서의 `완료 리뷰` 섹션을 만들거나 갱신한다.
|
||||||
|
- `완료 리뷰`에는 `상태: 요청됨`, `요청일`, 완료 근거 1~3줄, 사용자 최종 확인 항목, 리뷰 코멘트를 남긴다.
|
||||||
|
- 사용자가 승인하면 `완료 리뷰`를 `상태: 승인됨`으로 바꾸고 Milestone 상태를 `[완료]`로 전환한 뒤 archive 모드를 수행한다.
|
||||||
|
- 사용자가 보완을 요구하면 `완료 리뷰`를 `상태: 보완 필요`로 바꾸고 Milestone 상태를 `[진행중]`으로 되돌린다. 이때 보완 방향을 `완료 리뷰` 또는 `작업 컨텍스트`에 남기며 별도 reopen 상태는 만들지 않는다.
|
||||||
|
- 사용자가 보류 또는 폐기를 지시하면 `완료 리뷰`와 Milestone 상태를 각각 `보류`/`[보류]`, `폐기`/`[폐기]`로 맞춘다. `[폐기]`는 archive 대상이 될 수 있다.
|
||||||
|
- Phase는 하위 Milestone이 모두 `[완료]` 또는 `[폐기]`로 정리되고 Phase 목표도 충족된 것으로 보일 때 `[검토중]`으로 두고, 사용자 승인 후 `[완료]` 또는 `[폐기]`로 archive한다.
|
||||||
|
|
||||||
|
## Milestone task group 연동
|
||||||
|
|
||||||
|
- 런타임 완료 이벤트의 `origin-task`에서 `agent-task/` 다음 첫 path segment가 `m-<milestone-slug>`이면 Milestone 기반 plan/review 완료에서 온 요청으로 본다. `origin-task`는 archive 이동 전 active task 경로 또는 런타임이 그 형태로 정규화한 경로를 사용한다.
|
||||||
|
- `<milestone-slug>`는 활성 `agent-roadmap/phase/*/milestones/<milestone-slug>.md`에서 정확히 하나만 찾아야 한다. archive Milestone은 target 후보가 아니다.
|
||||||
|
- 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 불일치로 보고한다.
|
||||||
|
- 일치하면 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 안에 명시된 검증이 충족되면 `[검토중]` 전환과 `완료 리뷰` 요청 규칙을 적용한다.
|
||||||
|
- target Milestone이 `[스케치]`이면 완료 이벤트를 반영하지 말고 상태 불일치로 보고한다. `[스케치]`는 Milestone 기반 `agent-task` 완료 이벤트의 target이 될 수 없다.
|
||||||
|
|
||||||
|
## 삽입 단위 정책
|
||||||
|
|
||||||
|
| 삽입 단위 | 사용 기준 |
|
||||||
|
|-----------|-----------|
|
||||||
|
| 새 Phase | 독립적인 제품 진화 단계와 여러 Milestone 묶음이 필요하다 |
|
||||||
|
| 새 Milestone | 독립적인 목표와 기능 Task 묶음이 필요하고 Phase 흐름에 의미 있는 경계를 만든다 |
|
||||||
|
| 새 Epic | 기존 Milestone 안에서 여러 Task를 묶는 상위 capability 또는 산출물이다 |
|
||||||
|
| 새 Task | 기존 Epic 아래에 들어가는 완료 가능한 capability 또는 산출물이다. 검증이 필요한 경우에만 같은 Task 안에 붙인다 |
|
||||||
|
| 하위 작업 | 기존 Task를 완성하기 위한 구현 세부다. Milestone `기능`에는 하위 체크박스로 만들지 않고, plan 내부 체크리스트나 기존 Task의 `검증:`/설명 보강으로 다룬다 |
|
||||||
|
| 작업 컨텍스트/TODO | 사용자 결정 또는 조사/확인이 먼저 필요해 기능 Task로 확정하기 어렵다 |
|
||||||
|
|
||||||
|
- 먼저 요청 내용의 규모를 판정한다. 배치 위치를 찾기 전에 `phase`, `milestone`, `epic`, `task`, `subtask`, `context` 중 가장 작은 충분한 단위를 고른다.
|
||||||
|
- 요청이 방향성, 문제의식, 컨셉, 운영 원칙 수준이고 기능 Task나 실행 범위가 아직 부족하면 새 항목의 상태는 `[스케치]`로 둔다.
|
||||||
|
- `[스케치]` Phase/Milestone을 만들 때는 `승격 조건`에 `[계획]`으로 전환하기 위해 필요한 정의, 결정, 경계, 후속 구현 Milestone 후보를 체크리스트로 남긴다.
|
||||||
|
- 가장 작은 충분한 단위 원칙을 따른다. 애매하면 새 Phase나 새 Milestone으로 키우지 말고, 기존 Milestone의 Epic/Task에 넣을 수 있는지 먼저 확인한다.
|
||||||
|
- 위치 지정이 있으면 anchor의 레벨을 먼저 확인한다.
|
||||||
|
- `<epic-id> 아래`는 해당 Epic 아래 Task로 넣는다.
|
||||||
|
- `<item-id> 앞/뒤`는 같은 Epic 안의 형제 Task로 넣는다.
|
||||||
|
- `<item-id> 아래`는 해당 Task의 설명 또는 `검증:`을 보강한다. 구현 세부나 테스트만 따로 떼어낸 하위 체크박스는 Milestone `기능` 아래에 만들지 않는다.
|
||||||
|
- `<phase-name> 안`은 새 Milestone 또는 기존 Milestone/Epic/Task 중 작업 성격에 맞는 단위로 배치한다.
|
||||||
|
- 위치 지정이 없으면 `auto`로 본다. 로컬 `current.md`의 활성 창만으로 결정하지 않고, 필요한 경우 `ROADMAP.md`의 Phase 흐름까지 확인해 완료/검토중/진행중/계획/스케치 Phase를 비교한다.
|
||||||
|
- target 없는 신규 추가 요청은 요청 문장, 관련 파일/도메인 힌트, Phase 목표, Milestone 목표, 기존 Epic/Task, 선후 의존성, 상태, 활성 창을 비교해 가장 자연스러운 위치를 자동 판단한다.
|
||||||
|
- 자동 배치 후보가 여러 개이면 1순위와 2순위 후보를 비교하고, 선택한 Phase/Milestone/Epic/Task와 밀린 후보의 이유를 짧게 남긴다.
|
||||||
|
- 관련성이 비슷하면 `[진행중]` Milestone을 `[계획]` Milestone보다 우선하되, `[검토중]` Milestone은 리뷰 보완 요청이 아닌 신규 작업의 기본 배치 대상으로 삼지 않는다.
|
||||||
|
- 자동 배치한 경우 결과 보고에 선택한 삽입 단위, 위치, 판단 근거, 비교한 후보를 짧게 남긴다.
|
||||||
|
- 사용자 지정 위치가 Phase 목표, Milestone 범위 제외, 선후 의존성과 충돌하면 수정 전에 사용자에게 확인한다.
|
||||||
|
|
||||||
|
## 레벨별 탐색과 upsert 정책
|
||||||
|
|
||||||
|
target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다.
|
||||||
|
|
||||||
|
1. **요청 정규화**
|
||||||
|
- 요청 문장에서 기능명, 목표, 산출물, 관련 경로/도메인, 완료 기대, 제약, 명시 anchor를 뽑는다.
|
||||||
|
- 사용자가 Phase/Milestone/Epic/Task/id/path를 명시했으면 그 anchor를 우선 후보로 둔다.
|
||||||
|
|
||||||
|
2. **규모 판정**
|
||||||
|
- 여러 Milestone을 묶는 제품/운영 단계면 Phase 규모다.
|
||||||
|
- 독립 목표, 기능 Task 묶음, 여러 Epic이 필요한 결과면 Milestone 규모다.
|
||||||
|
- 컨셉은 충분히 크지만 구현 가능한 목표/범위/기능 Task가 아직 없으면 `[스케치]` Phase 또는 Milestone 후보로 둔다.
|
||||||
|
- 한 Milestone 안의 capability 묶음이면 Epic 규모다.
|
||||||
|
- Epic 아래에서 완료 가능한 단일 capability 또는 산출물이면 Task 규모다. 검증이 필요한 경우에만 같은 Task 안에 포함한다.
|
||||||
|
- Task를 완성하기 위한 구현 세부면 subtask 규모다. roadmap에는 하위 체크박스로 기록하지 않고, 구현 계획 내부 또는 기존 Task 보강으로 처리한다.
|
||||||
|
- 조사, 결정, 보류 질문이면 작업 컨텍스트/TODO 규모다.
|
||||||
|
|
||||||
|
3. **레벨별 탐색**
|
||||||
|
- Phase 후보를 먼저 찾는다. 로컬 `current.md`의 활성 Phase를 우선 보되, target이 없거나 활성 범위 밖 가능성이 있으면 `ROADMAP.md`의 Phase 흐름도 본다.
|
||||||
|
- 선택한 Phase 안에서 Milestone 후보를 찾는다. 활성 Milestone을 우선 보되, 요청이 계획 Milestone 목표와 더 직접 맞으면 계획 Milestone도 후보로 둔다.
|
||||||
|
- 선택한 Milestone 안에서 Epic 후보를 찾는다. `기능`의 Epic heading, 목표 설명, Task 묶음을 비교한다. 기존 문서가 `필수 기능`을 쓰면 갱신 시 `기능`으로 정규화한다.
|
||||||
|
- 선택한 Epic 안에서 Task 후보를 찾는다. item-id, 문장 의미, Task 안의 검증 문구, 관련 경로를 비교한다.
|
||||||
|
- archive 문서는 기본 탐색 대상이 아니다. 사용자가 과거 기록 비교를 명시했거나 완료 내용 확인이 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라 필요한 문서만 읽는다.
|
||||||
|
|
||||||
|
4. **중복/업데이트 판정**
|
||||||
|
- 같은 id, 같은 제목, 같은 목표, 같은 관련 경로, 같은 Task 안의 검증 문구, 또는 같은 산출물을 다루면 동일/유사 후보로 본다.
|
||||||
|
- 동일 항목이면 새로 만들지 않고 기존 Phase/Milestone/Epic/Task를 업데이트한다.
|
||||||
|
- 기존 항목의 범위를 보강하는 내용이면 해당 항목의 설명, Task 안의 검증 문구, 작업 컨텍스트 중 알맞은 곳에 병합한다.
|
||||||
|
- 기존 항목과 충돌하거나 범위 제외를 건드리면 수정 전에 사용자에게 확인한다.
|
||||||
|
- 같은 레벨에 적절한 후보가 없을 때만 새 항목을 만든다. 새 항목도 판정한 규모보다 크게 만들지 않는다.
|
||||||
|
- 부모 레벨 후보는 있고 판정 규모의 항목만 없으면, 부모 아래에 판정 규모의 새 항목을 만든다. 부모 레벨도 없을 때만 필요한 부모 항목을 함께 만든다.
|
||||||
|
|
||||||
|
## archive 정책
|
||||||
|
|
||||||
|
### Milestone archive
|
||||||
|
|
||||||
|
- 대상 Milestone이 `[완료]` 또는 `[폐기]`인지 확인한다.
|
||||||
|
- `[검토중]` Milestone은 archive하지 않는다. 사용자 완료 승인 또는 폐기 지시가 있으면 먼저 `[완료]` 또는 `[폐기]`로 바꾼 뒤 archive한다.
|
||||||
|
- archive 이동 전에 대상 Milestone의 활성 경로 identity(`<project>:agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`)를 보존한다.
|
||||||
|
- `locks.yaml`이 있으면 보존한 identity로 `--find-milestone "<identity>" both "<locks-file>"`를 실행해 이 Milestone이 `locked`인지, `rely-on.target`인지, 관련 lock이 없는지 먼저 확인한다.
|
||||||
|
- 보존한 identity가 `.agent-roadmap-sync/locks.yaml`의 `rely-on.target`에 있으면 archive 이동 전에 상태를 동기화한다. `[완료]`이면 `enable`, `[폐기]`이면 `disable`이다.
|
||||||
|
- 보존한 identity가 `.agent-roadmap-sync/locks.yaml`의 `locked`에 있으면 archive 이동 전에 의존 조건 충족 여부를 결과 보고에 남긴다.
|
||||||
|
- find 결과가 `none`이면 `Workspace 잠금: 관련 lock 없음`으로 보고한다.
|
||||||
|
- 대상 파일을 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`에서 `agent-roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 이동한다.
|
||||||
|
- 활성 `PHASE.md`의 Milestone 흐름에는 `[완료]` 또는 `[폐기]` 항목을 남기고, 경로는 archive 경로로 바꾼다.
|
||||||
|
- 로컬 `current.md`의 활성 Milestone에서는 제거한다.
|
||||||
|
- `ROADMAP.md`는 Phase 상태나 경로가 바뀌지 않으면 수정하지 않는다.
|
||||||
|
- 이동한 archive 문서는 스냅샷으로 보존하고 최신 템플릿에 맞춰 재포맷하지 않는다.
|
||||||
|
|
||||||
|
### Phase archive
|
||||||
|
|
||||||
|
- Phase 전체가 `[완료]` 또는 `[폐기]`인지 확인한다.
|
||||||
|
- `[검토중]` Phase는 archive하지 않는다. 사용자 완료 승인 또는 폐기 지시가 있으면 먼저 `[완료]` 또는 `[폐기]`로 바꾼 뒤 archive한다.
|
||||||
|
- `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`로 바꾼다.
|
||||||
|
- 로컬 `current.md`의 활성 Phase와 활성 Milestone에서는 해당 Phase와 하위 Milestone을 제거한다.
|
||||||
|
- archive 문서는 스냅샷으로 보존하고 최신 템플릿에 맞춰 재포맷하지 않는다.
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
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이다.
|
||||||
|
- 구조 전환, 템플릿 보정, current 동기화는 `sync`로 본다.
|
||||||
|
- 사용자 승인 이후의 완료/폐기 이동은 `archive`로 본다.
|
||||||
|
- 새 기능 배치, Epic/Task 추가는 `milestone` 또는 `phase`로 본다.
|
||||||
|
- "로드맵에 추가"처럼 target이 없는 신규 작업 요청은 `placement=auto`, `placement-unit=auto`, `new-feature=<요청 내용>`으로 본다.
|
||||||
|
- 외부 의존 잠금 요청이면 `workspace-lock` 갱신으로 본다.
|
||||||
|
- 외부 의존 잠금 요청이 아니어도, 갱신 대상 Milestone이 `구현 잠금: 잠금`이고 외부 의존 잠금/선행 Milestone 컨텍스트가 있으면 `workspace-lock` 동기화 후보로 본다.
|
||||||
|
- 외부 의존 잠금 요청에서 "현재 마일스톤" 또는 target 생략 표현이 있으면 로컬 `current.md`의 활성 Milestone 단일 후보를 잠긴 대상으로 확정한다.
|
||||||
|
- 의존 대상은 명시 경로, 명시 slug, 명시 제목, 잠긴 Milestone 문서의 선행 Milestone 힌트, 대상 프로젝트 로컬 `current.md` 단일 후보 순서로 확정한다.
|
||||||
|
- 잠긴 대상 또는 의존 대상 후보가 없거나 둘 이상이면 `locks.yaml`을 수정하지 말고 사용자에게 Milestone 선택을 요청한다.
|
||||||
|
|
||||||
|
2. **요청 정규화와 규모 판정**
|
||||||
|
- 요청에서 기능명, 목표, 관련 경로, 명시 anchor, 완료 기대, 제약을 추출한다.
|
||||||
|
- `phase`, `milestone`, `epic`, `task`, `subtask`, `context` 중 가장 작은 충분한 규모를 판정한다.
|
||||||
|
- 동일/유사 항목이 이미 있으면 신규 추가가 아니라 업데이트 후보로 기록한다.
|
||||||
|
|
||||||
|
3. **레벨별 후보 탐색**
|
||||||
|
- 로컬 `current.md`의 활성 Phase와 활성 Milestone 후보를 확인한다.
|
||||||
|
- target이 명시된 경우 대상 Phase의 `PHASE.md`를 읽고 Milestone 흐름과 Phase 경계를 확인한다.
|
||||||
|
- target이 없거나 활성 창 밖 배치 가능성이 있으면 `ROADMAP.md`의 Phase 흐름을 확인하고, 관련성이 높은 Phase 문서를 읽는다.
|
||||||
|
- 대상 또는 후보 Milestone 문서의 목표, 상태, 승격 조건, 범위, 기능 Task, 완료 리뷰, 범위 제외, 구현 잠금을 확인한다. 기존 문서에 `필수 기능`/`완료 기준`이 분리되어 있으면 갱신 범위에서 `기능` Task로 흡수할 후보를 기록한다.
|
||||||
|
- Phase -> Milestone -> Epic -> Task 순서로 내려가며 같은 레벨의 동일/유사 후보를 먼저 찾는다.
|
||||||
|
- 로컬 `current.md`에 archive 경로가 있으면 읽지 말고 제거 대상으로 기록한다.
|
||||||
|
- 필요한 경우에만 `ROADMAP.md`를 읽어 전체 Phase 흐름을 확인한다.
|
||||||
|
|
||||||
|
4. **스케치 승격 판단**
|
||||||
|
- `target-status=[계획]`, `mode=concretize`, 또는 사용자가 "구체화", "계획으로 올려"처럼 요청하면 `[스케치] -> [계획]` 승격 검토로 본다.
|
||||||
|
- 대상이 `[스케치]`가 아니면 일반 상태 갱신이나 Milestone 갱신으로 처리한다.
|
||||||
|
- 대상이 `[스케치]`이면 `승격 조건`, `구현 잠금`, `목표`, `범위`, `기능`, `작업 컨텍스트`를 확인한다.
|
||||||
|
- `승격 조건` 체크리스트가 남아 있거나 구현 계획에 직접 필요한 사용자 결정이 남아 있으면 상태를 `[스케치]`로 유지하고, 부족한 항목을 `승격 조건` 또는 `결정 필요`에 보강한다.
|
||||||
|
- 구현 가능한 목표, 범위, 기능 Task, 직접 결정 항목, 후속 구현 단위가 정리되면 상태를 `[계획]`으로 전환하고, `승격 조건`은 충족 요약으로 남기거나 `- 없음`으로 정리한다.
|
||||||
|
- 승격은 구현 완료가 아니므로 `기능` Task를 자동 완료 처리하지 않는다.
|
||||||
|
|
||||||
|
5. **변경 내용 작성**
|
||||||
|
- `ROADMAP.md`는 전체 목표, Phase 흐름, 로딩 정책이 바뀔 때만 수정한다.
|
||||||
|
- 로컬 `current.md`는 활성 Phase/Milestone 창이 바뀔 때 수정한다.
|
||||||
|
- `.gitignore`의 Agent-Ops 관리 block에 `agent-roadmap/current.md`가 있는지 확인하고 없으면 추가한다.
|
||||||
|
- `PHASE.md`는 Phase 목표, 상태, Milestone 흐름, Phase 경계가 바뀔 때 수정한다.
|
||||||
|
- Milestone 문서는 목표, 상태, 승격 조건, 구현 잠금, 범위, Epic/Task, Task 안의 검증 문구, 완료 리뷰, 범위 제외, 작업 컨텍스트가 바뀔 때 수정한다.
|
||||||
|
- 동일/유사 후보가 있으면 기존 항목을 업데이트하고 중복 항목을 만들지 않는다.
|
||||||
|
- 새 Milestone은 해당 Phase의 `milestones/` 아래에 만든다.
|
||||||
|
- 새 `[스케치]` Milestone은 `승격 조건` 섹션을 포함하고 `구현 잠금`은 `잠금`으로 둔다.
|
||||||
|
- 새 Epic은 `기능` 아래 `### Epic: [epic-id] <이름>`으로 만든다.
|
||||||
|
- 새 Task는 관련 Epic 아래 `- [ ] [item-id] 설명`으로 만든다. 검증이 필요한 경우에만 같은 항목에 `검증: <명령/확인 방법/기대 결과>`를 붙인다.
|
||||||
|
- 새 항목은 레벨별 탐색에서 적절한 기존 후보가 없을 때만 만든다.
|
||||||
|
- 완료 체크는 evidence가 있을 때만 `[x]`로 바꾼다.
|
||||||
|
- 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`이면 Milestone 상태를 `[검토중]`으로 바꾸고 `완료 리뷰`에 리뷰 요청과 근거를 남긴다.
|
||||||
|
- `[검토중]` 전환만으로 archive 이동, 로컬 `current.md` 제거, archive 링크 변경을 수행하지 않는다.
|
||||||
|
- 사용자 승인 근거가 있으면 `[검토중]`을 `[완료]`로 전환하고 archive 모드를 수행할 수 있다.
|
||||||
|
- `locks.yaml`이 있으면 갱신 대상 Milestone identity로 `--find-milestone "<identity>" both "<locks-file>"`를 실행해 이 Milestone이 `locked`인지, `rely-on.target`인지, 관련 lock이 없는지 확인한다.
|
||||||
|
- archive 모드이면 파일 이동 전 active Milestone identity를 보존하고, 그 identity로 `--find-milestone "<identity>" both "<locks-file>"`를 먼저 실행한다.
|
||||||
|
- 외부 의존 잠금 요청 또는 외부 의존 컨텍스트 동기화가 필요하면 대상 Milestone의 `구현 잠금`을 `잠금`으로 두고 `.agent-roadmap-sync/locks.yaml`을 upsert한다.
|
||||||
|
- `.agent-roadmap-sync/locks.yaml`이 없으면 `.agent-roadmap-sync/` 디렉터리와 `locks.yaml` 파일을 만든다.
|
||||||
|
- `locks.yaml` entry는 `id=<잠긴-project>:<잠긴-milestone-slug>`, `locked=<잠긴-project>:<잠긴-milestone-path>`, `rely-on.target=<의존-project>:<의존-milestone-path>`, `rely-on.status=<enable|disable>`, `rely-on.note=<사용자 요청 요약>`으로 기록한다.
|
||||||
|
- 같은 `id` entry가 있으면 기존 `rely-on` 목록을 보존하고 같은 `target`만 갱신하거나 새 `target`을 추가한다.
|
||||||
|
- find 결과가 `none`이면 결과 보고의 `Workspace 잠금`에 `관련 lock 없음`을 남긴다.
|
||||||
|
- 갱신한 Milestone identity와 일치하는 `rely-on.target`은 Milestone 상태 기준으로 `enable` 또는 `disable`을 동기화한다.
|
||||||
|
- 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`인지 확인하고 결과 보고에 남긴다.
|
||||||
|
|
||||||
|
6. **검증**
|
||||||
|
- 로컬 `current.md`의 활성 Phase/Milestone 경로가 실제 파일을 가리키는지 확인한다.
|
||||||
|
- 로컬 `current.md`의 활성 항목이 archive 경로를 가리키지 않는지 확인한다.
|
||||||
|
- 로컬 `current.md`의 활성 항목이 `[완료]` 또는 `[폐기]` 상태로 남아 있지 않은지 확인한다.
|
||||||
|
- `agent-roadmap/current.md`가 git 추적 대상으로 남아 있지 않은지 확인한다.
|
||||||
|
- `ROADMAP.md`의 Phase 경로가 실제 `PHASE.md` 파일을 가리키는지 확인한다.
|
||||||
|
- 각 `PHASE.md`의 Milestone 경로가 실제 파일을 가리키는지 확인한다.
|
||||||
|
- 상태 표기가 표준값인지 확인한다.
|
||||||
|
- `[스케치]` Milestone에 `승격 조건`이 있고 `구현 잠금`이 `잠금`인지 확인한다.
|
||||||
|
- `[계획]` 이상 Milestone에 `승격 조건` 섹션이 없더라도 오류로 보지 않는다. 섹션이 있으면 `- 없음` 또는 승격 충족 요약인지 확인한다.
|
||||||
|
- `[스케치] -> [계획]` 전환을 수행했다면 승격 조건 해소 근거가 Milestone 내용이나 결과 보고에 남았는지 확인한다.
|
||||||
|
- `[검토중]` Milestone이 archive 경로로 이동되지 않았는지 확인한다.
|
||||||
|
- 모든 기능 Task와 Task 안에 명시된 검증이 `[x]`인 Milestone에는 `완료 리뷰` 섹션과 사용자 리뷰 요청이 있는지 확인한다.
|
||||||
|
- Epic heading과 Task id 형식이 맞는지 확인한다.
|
||||||
|
- 요청 규모가 판정되었고 결과 보고에 남았는지 확인한다.
|
||||||
|
- 동일/유사 기존 항목을 검색했고 신규/업데이트 판정이 결과 보고에 남았는지 확인한다.
|
||||||
|
- 자동 배치한 신규 작업이면 선택한 후보와 밀린 후보의 근거가 결과 보고에 포함되는지 확인한다.
|
||||||
|
- `.agent-roadmap-sync/locks.yaml`을 갱신했다면 `locked`, `rely-on.target`, `rely-on.status`가 채워졌는지 확인한다.
|
||||||
|
- 갱신 대상 Milestone에 resolvable한 외부 의존 잠금/선행 Milestone 컨텍스트가 있으면 해당 lock entry가 존재하는지 확인한다.
|
||||||
|
- 갱신 대상 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 없음` 보고를 수행했는지 확인한다.
|
||||||
|
- `git diff --check`로 공백 오류를 확인한다.
|
||||||
|
|
||||||
|
7. **결과 보고**
|
||||||
|
- 수정한 파일 목록
|
||||||
|
- 요청 규모 판정과 근거
|
||||||
|
- Phase -> Milestone -> Epic -> Task 탐색 경로와 후보
|
||||||
|
- 신규 추가인지 기존 항목 업데이트인지
|
||||||
|
- 변경된 Phase / Milestone / 상태
|
||||||
|
- 신규 작업의 삽입 단위와 배치 위치
|
||||||
|
- 자동 배치한 경우 비교한 후보와 선택 근거
|
||||||
|
- 로컬 current.md 활성 창 변경 사항
|
||||||
|
- 완료 리뷰 상태와 사용자 확인 필요 항목
|
||||||
|
- 런타임 완료 이벤트의 `origin-task`가 `m-<milestone-slug>`이면 원래 active task 경로와 매칭된 target Milestone, `Roadmap Completion` Task ids 또는 no-op 사유
|
||||||
|
- archive 모드이면 이동 경로와 남긴 링크
|
||||||
|
- 확인 필요로 남긴 항목
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 업데이트 완료
|
||||||
|
|
||||||
|
- 모드: <status | milestone | phase | replan | sync | concretize | archive>
|
||||||
|
- 수정 파일:
|
||||||
|
- 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/archive/phase/<phase-slug>/... (archive 모드)
|
||||||
|
|
||||||
|
## 변경 사항
|
||||||
|
|
||||||
|
- Phase: <변경 없음 | 요약>
|
||||||
|
- Milestone: <변경 없음 | 요약>
|
||||||
|
- 삽입 단위: <Phase | Milestone | Epic | Task | 하위 작업 | 작업 컨텍스트/TODO | 변경 없음>
|
||||||
|
- 규모 판정: <phase | milestone | epic | task | subtask | context | 변경 없음> - <근거>
|
||||||
|
- 탐색 경로: <Phase 후보 -> Milestone 후보 -> Epic 후보 -> Task 후보 | 해당 없음>
|
||||||
|
- 신규/업데이트 판정: <신규 생성 | 기존 항목 업데이트 | 변경 없음> - <동일/유사 후보 근거>
|
||||||
|
- 배치: <사용자 지정 위치 반영 | 자동 배치 위치와 근거 | 변경 없음>
|
||||||
|
- 배치 후보: <자동 배치 시 1순위/2순위 후보와 선택/제외 근거 | 해당 없음>
|
||||||
|
- 템플릿 보정: <ROADMAP | local current.md | PHASE | Milestone | 이미 일치 | 변경 없음>
|
||||||
|
- 구현 잠금: <잠금 유지 | 잠금 추가 | 해제 | 변경 없음>; 결정 필요: <없음 | 항목 요약>
|
||||||
|
- 승격 조건: <해당 없음 | 추가/수정/미충족 유지/충족 요약>
|
||||||
|
- 완료 리뷰: <변경 없음 | 요청됨 | 승인됨 | 보완 필요 | 보류 | 폐기>
|
||||||
|
- runtime m-task 라우팅: <해당 없음 | origin-task -> target Milestone | target 불명확>
|
||||||
|
- Workspace 잠금: <변경 없음 | 관련 lock 없음 | entry 생성/갱신 | rely-on enable | rely-on disable | 미충족 | 런타임 해제 대기>
|
||||||
|
- 활성 항목: <변경 없음 | Phase/Milestone 추가/제거 요약>
|
||||||
|
- 아카이브: <변경 없음 | 이동 경로와 남긴 링크>
|
||||||
|
- 상태: <변경 없음 | 이전 -> 이후>
|
||||||
|
- Epic/Task: <추가/수정/완료/제거 요약>
|
||||||
|
|
||||||
|
## TODO 항목
|
||||||
|
|
||||||
|
- <확인이 필요한 항목> (해당 시)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 로드맵 파일이 없는데 새 구조를 임의로 만들지 않는다. 이 경우 `create-roadmap`을 사용한다.
|
||||||
|
- evidence 없이 Phase, Milestone, Epic, Task를 `[완료]` 또는 `[검토중]`으로 처리하지 않는다.
|
||||||
|
- 전체 `ROADMAP.md`를 모든 작업의 필수 로딩 파일로 만들지 않는다.
|
||||||
|
- `ROADMAP.md`에 Milestone 상세 작업 체크리스트를 남기지 않는다.
|
||||||
|
- 로컬 `current.md`에 개인별 현재 작업 위치나 완료 상태를 남기지 않는다.
|
||||||
|
- 로컬 `current.md`에 `agent-roadmap/archive/**` 경로를 남기지 않는다.
|
||||||
|
- `agent-roadmap/current.md`를 git 추적 대상으로 만들지 않는다.
|
||||||
|
- archive 문서를 명시 요청 없이 읽거나 최신 템플릿으로 재포맷하지 않는다.
|
||||||
|
- 완료된 Phase/Milestone 기록을 삭제하지 않는다.
|
||||||
|
- Epic과 Task를 별도 파일로 분리하지 않는다.
|
||||||
|
- Phase와 Milestone 이름 또는 파일명에 순번을 강제하지 않는다.
|
||||||
|
- 사용자만 결정할 수 있는 항목이 남아 있는데 Milestone의 `구현 잠금`을 `해제`로 바꾸지 않는다.
|
||||||
|
- 사용자가 지정한 Phase/Milestone/Epic/Task anchor를 무시하지 않는다.
|
||||||
|
- 사용자가 명시하지 않은 기존 epic-id나 item-id를 바꾸지 않는다.
|
||||||
|
- `rely-on.status=enable`만으로 다른 프로젝트 Milestone의 `구현 잠금`을 직접 해제하지 않는다.
|
||||||
99
agent-ops/skills/common/update-test/SKILL.md
Normal file
99
agent-ops/skills/common/update-test/SKILL.md
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
---
|
||||||
|
name: update-test
|
||||||
|
version: 1.1.0
|
||||||
|
description: 기존 agent-test 환경 rules.md 또는 도메인/검증 시나리오별 테스트 rule 문서를 수정하는 스킬
|
||||||
|
---
|
||||||
|
|
||||||
|
# update-test
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
기존 `agent-test/<env>/rules.md` 또는 `agent-test/<env>/<test-profile>.md`를 최신 테스트 기준에 맞게 갱신한다.
|
||||||
|
라우팅은 3홉 안에 유지하고, 도메인/검증 시나리오별 문서는 자체 완결되게 보완한다.
|
||||||
|
|
||||||
|
`test-case`는 기존 호출과의 호환을 위한 alias이며, 새 문서 기준 이름은 `test-profile`이다.
|
||||||
|
|
||||||
|
## 언제 호출할지
|
||||||
|
|
||||||
|
- 기존 테스트 환경 규칙을 수정할 때
|
||||||
|
- 도메인/검증 시나리오별 테스트 기준, 명령, 판정 기준을 보완할 때
|
||||||
|
- 테스트 라우팅을 추가, 제거, 정리할 때
|
||||||
|
|
||||||
|
## 입력
|
||||||
|
|
||||||
|
- `env`: `local`, `dev`, `qa`, `prod` 중 하나 (필수)
|
||||||
|
- `test-profile`: 수정할 도메인/검증 시나리오별 테스트 문서 이름, kebab-case (선택)
|
||||||
|
- `test-case`: `test-profile`의 호환 alias (선택)
|
||||||
|
- `domain`: 대상 도메인 이름, kebab-case (선택)
|
||||||
|
- `change`: 수정할 내용 요약 (필수)
|
||||||
|
|
||||||
|
## 먼저 확인할 것
|
||||||
|
|
||||||
|
- [ ] `agent-ops/rules/common/rules.md`의 스킬 규칙과 테스트 규칙이 분리되어 있는지 확인한다.
|
||||||
|
- [ ] `agent-ops/skills/common/router.md`에 `update-test` 라우팅이 있는지 확인한다.
|
||||||
|
- [ ] `test-case`가 있고 `test-profile`이 없으면 `test-profile`로 취급한다.
|
||||||
|
- [ ] `agent-test/<env>/rules.md` 존재 여부를 확인하고, 없으면 `create-test` 대상으로 보고 중단한다.
|
||||||
|
- [ ] `agent-test/<env>/rules.md`가 있으면 읽는다.
|
||||||
|
- [ ] `test-profile`이 있으면 `agent-test/<env>/<test-profile>.md` 존재 여부를 확인하고, 없으면 `create-test` 대상으로 보고 중단한다.
|
||||||
|
- [ ] `test-profile` 문서가 있으면 읽는다.
|
||||||
|
- [ ] `test-profile`이 없고 `domain` 또는 `change`가 특정 도메인/검증 시나리오를 가리키면 env rules의 라우팅에서 대상 문서를 찾는다.
|
||||||
|
- [ ] 템플릿 구조 확인이 필요하면 `agent-ops/rules/common/_templates/`의 테스트 템플릿을 읽는다.
|
||||||
|
- [ ] 기존 라우팅이 3홉 안에 있는지 확인한다.
|
||||||
|
|
||||||
|
## 실행 절차
|
||||||
|
|
||||||
|
1. **대상 확정**
|
||||||
|
- 환경 공통 규칙 변경이면 `agent-test/<env>/rules.md`만 수정한다.
|
||||||
|
- 특정 도메인/검증 기준 변경이면 해당 `test-profile` 문서를 수정한다.
|
||||||
|
- 특정 대상이 암시되지만 라우팅에서 찾지 못하면 생성하지 말고 `create-test` 대상이라고 보고한다.
|
||||||
|
- 대상 문서가 없으면 생성하지 말고 `create-test` 대상이라고 보고한다.
|
||||||
|
|
||||||
|
2. **문서 갱신**
|
||||||
|
- 기존 환경값, 명령, 금지 사항을 보존한다.
|
||||||
|
- 오래된 기준은 새 기준으로 교체하고 같은 뜻의 중복 문장은 줄인다.
|
||||||
|
- 도메인/검증 시나리오별 문서는 읽기 조건, 적용 범위, 명령, 필수 검증, 판정 기준, 차단 기준을 자체 포함하게 유지한다.
|
||||||
|
- `last_rule_updated_at`은 수정일 `YYYY-MM-DD`로 갱신한다.
|
||||||
|
|
||||||
|
3. **라우팅 갱신**
|
||||||
|
- env rules의 `## 라우팅`은 도메인/검증 시나리오별 문서로만 향하게 한다.
|
||||||
|
- 맞지 않는 라우팅은 제거하거나 더 정확한 `domain / verification-type / scope` 설명으로 바꾼다.
|
||||||
|
- 도메인/검증 시나리오별 문서에서 다른 테스트 문서로 이어지는 라우팅은 제거한다.
|
||||||
|
- 공통룰에서 스킬 최종 진입까지의 경로는 `rules.md` -> `router.md` -> `update-test/SKILL.md`로 유지한다.
|
||||||
|
|
||||||
|
4. **local 추적 제외 확인**
|
||||||
|
- `env`가 `local`이면 `.gitignore`에 `agent-test/local/`과 `agent-test/runs/`가 있는지 확인하고 없으면 추가한다.
|
||||||
|
|
||||||
|
5. **결과 보고**
|
||||||
|
- 수정한 파일
|
||||||
|
- 바꾼 라우팅
|
||||||
|
- 보존한 환경값
|
||||||
|
- 남은 확인 필요 항목
|
||||||
|
|
||||||
|
## 실행 결과 검증
|
||||||
|
|
||||||
|
- [ ] 수정 대상 문서가 여전히 필수 섹션을 포함하는가
|
||||||
|
- [ ] `rules.md` -> `router.md` -> `update-test/SKILL.md` 경로가 끊기지 않는가
|
||||||
|
- [ ] env rules 라우팅이 3홉 제한을 넘기지 않는가
|
||||||
|
- [ ] 도메인/검증 시나리오별 문서가 다른 테스트 문서로 라우팅하지 않는가
|
||||||
|
- [ ] local 수정 시 `.gitignore`에 local 경로가 반영되었는가
|
||||||
|
- [ ] secret, token, 개인 endpoint 원문이 tracked 파일에 추가되지 않았는가
|
||||||
|
- 검증 실패 시: 문제 문서만 다시 보완한다.
|
||||||
|
|
||||||
|
## 출력 형식
|
||||||
|
|
||||||
|
```md
|
||||||
|
## 수정 완료
|
||||||
|
|
||||||
|
- 환경: <env>
|
||||||
|
- 수정 파일: <path>
|
||||||
|
- 라우팅 변경: <내용 또는 없음>
|
||||||
|
- 보존한 환경값: <요약>
|
||||||
|
- 확인 필요: <항목 또는 없음>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 금지 사항
|
||||||
|
|
||||||
|
- 기존 local 환경값을 추측으로 바꾸지 않는다.
|
||||||
|
- 확인되지 않은 테스트 명령을 필수 검증으로 단정하지 않는다.
|
||||||
|
- 도메인/검증 시나리오별 문서를 router처럼 쓰지 않는다.
|
||||||
|
- secret, token, 개인 endpoint 원문을 tracked 파일에 기록하지 않는다.
|
||||||
52
agent-roadmap/ROADMAP.md
Normal file
52
agent-roadmap/ROADMAP.md
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Gito 로드맵
|
||||||
|
|
||||||
|
## 전체 목표
|
||||||
|
|
||||||
|
Gito는 GitHub, GitLab, Gitea 같은 플랫폼에 묶이지 않는 Git control plane을 제공한다. 여러 repository를 등록하고, workspace lease, Git operation, agent-shell/IOP 실행, provider adapter, normalized event를 하나의 운영 루프로 묶어 agent-driven development를 안전하게 실행할 수 있게 만든다.
|
||||||
|
|
||||||
|
## Phase 흐름
|
||||||
|
|
||||||
|
위에서 아래로 진행된 순서와 예정 흐름을 나타낸다.
|
||||||
|
완료된 Phase도 로드맵에서 제거하지 않고, archive의 Phase 문서로 연결한다.
|
||||||
|
검토중 또는 진행중 Phase는 계획 Phase보다 위에 두어, 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||||
|
스케치 Phase는 아직 구현 가능한 계획이 아니므로 계획 Phase보다 아래에 둔다.
|
||||||
|
|
||||||
|
- [진행중] Control Plane Foundation
|
||||||
|
- 경로: `agent-roadmap/phase/control-plane-foundation/PHASE.md`
|
||||||
|
- 요약: platformless Git control plane의 모듈 경계, repo/workspace/operation/event 원장, proto-socket 우선 transport 기준을 build 가능한 baseline으로 닫는다.
|
||||||
|
- [계획] Agent Shell IOP Execution
|
||||||
|
- 경로: `agent-roadmap/phase/agent-shell-iop-execution/PHASE.md`
|
||||||
|
- 요약: workspace command 실행 주체인 agent-shell과 IOP CLI를 연결해 Git 작업과 agent run을 안전하게 수행한다.
|
||||||
|
- [계획] Provider Change Request Integration
|
||||||
|
- 경로: `agent-roadmap/phase/provider-change-request-integration/PHASE.md`
|
||||||
|
- 요약: GitHub PR, GitLab MR, Gitea PR 같은 provider 기능을 ChangeRequest 추상화와 adapter 구조로 통합한다.
|
||||||
|
- [계획] Control Surface Operations UX
|
||||||
|
- 경로: `agent-roadmap/phase/control-surface-operations-ux/PHASE.md`
|
||||||
|
- 요약: Flutter control surface와 운영 관찰 화면을 통해 repository, operation, runner, event 흐름을 다룰 수 있게 한다.
|
||||||
|
|
||||||
|
## 로딩 정책
|
||||||
|
|
||||||
|
- 일반 작업에서는 `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는 `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 안에 `검증:`으로 통합한다.
|
||||||
|
- `[스케치]` Phase/Milestone은 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태이며 구현 계획 생성 대상이 아니다.
|
||||||
|
- `[스케치]` 항목은 `승격 조건`을 정리해 `[계획]`으로 전환한 뒤 구현 계획을 만든다.
|
||||||
|
- 모든 기능 Task와 Task 안에 명시된 검증이 충족된 Milestone은 먼저 `[검토중]`으로 두고, 사용자 완료 확인과 archive 승인을 받은 뒤 `[완료]`로 전환한다.
|
||||||
|
- 완료된 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/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다.
|
||||||
|
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 기존 구조/도메인 rule/플랫폼 관례로 정할 수 있는 작업은 표준선으로 기록하고 진행할 수 있다.
|
||||||
|
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `구현 잠금` 상태를 `해제`로 둔다.
|
||||||
|
|
||||||
35
agent-roadmap/phase/agent-shell-iop-execution/PHASE.md
Normal file
35
agent-roadmap/phase/agent-shell-iop-execution/PHASE.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Phase: Agent Shell IOP Execution
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
agent-shell을 실제 workspace command 실행 주체로 세우고 IOP CLI와 연결한다. control plane은 operation을 만들고, worker는 lease와 실행을 조율하며, agent-shell은 Git CLI와 IOP CLI 실행, 로그 streaming, cancel/timeout, dirty guard를 담당한다.
|
||||||
|
|
||||||
|
## Milestone 흐름
|
||||||
|
|
||||||
|
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
|
||||||
|
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||||
|
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||||
|
|
||||||
|
- [계획] Agent Shell Runtime Channel
|
||||||
|
- 경로: `agent-roadmap/phase/agent-shell-iop-execution/milestones/agent-shell-runtime-channel.md`
|
||||||
|
- 요약: agent-shell이 outbound proto-socket으로 control plane에 연결하고 command dispatch/heartbeat/log stream을 처리한다.
|
||||||
|
|
||||||
|
- [계획] IOP Agent Run Bridge
|
||||||
|
- 경로: `agent-roadmap/phase/agent-shell-iop-execution/milestones/iop-agent-run-bridge.md`
|
||||||
|
- 요약: IOP CLI를 workspace operation의 agent 실행 통로로 연결하고 run 결과를 Git operation과 event로 수렴시킨다.
|
||||||
|
|
||||||
|
- [계획] Command Policy and Cancellation
|
||||||
|
- 경로: `agent-roadmap/phase/agent-shell-iop-execution/milestones/command-policy-and-cancellation.md`
|
||||||
|
- 요약: command allowlist, timeout, cancel, dirty workspace guard, log redaction 기준을 실행 경계에 적용한다.
|
||||||
|
|
||||||
|
## Phase 경계
|
||||||
|
|
||||||
|
- agent-shell은 local workspace command 실행만 맡고 provider API 호출을 직접 소유하지 않는다.
|
||||||
|
- IOP 내부 모델 라우팅, RAG, output validation은 Gito의 소유 범위가 아니다.
|
||||||
|
- control plane은 arbitrary shell command를 직접 실행하지 않고 agent-shell capability로 위임한다.
|
||||||
|
- provider-specific PR/MR 작업은 ChangeRequest adapter Phase에서 처리한다.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
# Milestone: Agent Shell Runtime Channel
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/agent-shell-iop-execution/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
agent-shell이 runner machine에서 outbound proto-socket으로 control plane에 연결하고, heartbeat, capability registration, command dispatch, log stream을 처리한다. control plane은 연결된 shell에 workspace operation을 배정할 수 있어야 한다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 해제
|
||||||
|
- 결정 필요: 없음
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- agent-shell identity와 capability model
|
||||||
|
- outbound proto-socket 연결
|
||||||
|
- heartbeat와 runner 상태 event
|
||||||
|
- command dispatch request/response shape
|
||||||
|
- stdout/stderr log stream shape
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [shell-channel] Shell channel
|
||||||
|
|
||||||
|
agent-shell과 control plane 사이의 runtime channel을 만든다.
|
||||||
|
|
||||||
|
- [ ] [identity] `GITO_SHELL_ID`와 runner capability registration model을 확정한다.
|
||||||
|
- [ ] [heartbeat] shell heartbeat와 disconnect 상태를 operation event로 투영한다. 검증: fake shell disconnect가 runner offline event를 남긴다.
|
||||||
|
- [ ] [dispatch] command dispatch proto-socket action 후보를 구현한다. 검증: test shell이 no-op command request를 받고 response를 반환한다.
|
||||||
|
- [ ] [logs] stdout/stderr chunk stream shape를 정의하고 event stream에 연결한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- IOP CLI invocation 세부
|
||||||
|
- provider API 호출
|
||||||
|
- Flutter runner management UX
|
||||||
|
- remote shell installation 자동화
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `services/core/internal/agentshell/`, `services/core/internal/controlplane/`, `services/core/internal/events/`, `packages/contracts/notes/gito-control-plane.md`
|
||||||
|
- 표준선(선택): runner는 가능하면 outbound connection으로 control plane에 붙는다.
|
||||||
|
- 선행 작업: Operation Event Outbox
|
||||||
|
- 후속 작업: IOP Agent Run Bridge
|
||||||
|
- 확인 필요: 없음
|
||||||
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Milestone: Command Policy and Cancellation
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/agent-shell-iop-execution/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
agent-shell command execution에 policy gate, timeout, cancellation, log redaction, dirty workspace guard를 적용한다. agent가 Git과 IOP를 사용할 수 있어도 destructive action은 명시된 policy와 operation state를 통해 제어되어야 한다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 잠금
|
||||||
|
- 결정 필요:
|
||||||
|
- [ ] 기본 command allowlist와 destructive command 승인 기준을 확정한다.
|
||||||
|
- [ ] log redaction의 최소 secret pattern과 책임 경계를 확정한다.
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- command allowlist/denylist 후보
|
||||||
|
- operation별 timeout과 cancellation
|
||||||
|
- signal handling
|
||||||
|
- dirty workspace guard
|
||||||
|
- stdout/stderr secret redaction
|
||||||
|
- failed/cancelled event 정책
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [policy] Command policy
|
||||||
|
|
||||||
|
agent-shell이 실행할 수 있는 command 범위와 승인 조건을 제어한다.
|
||||||
|
|
||||||
|
- [ ] [allowlist] Git/IOP 중심 command allowlist를 정의한다.
|
||||||
|
- [ ] [destructive] destructive command는 policy gate 없이는 실행하지 않도록 막는다. 검증: deny 대상 command가 rejected event를 남긴다.
|
||||||
|
- [ ] [redaction] log stream에서 credential-like token을 redaction한다.
|
||||||
|
|
||||||
|
### Epic: [control] Timeout and cancel
|
||||||
|
|
||||||
|
긴 실행을 제어하고 중단 결과를 원장에 남긴다.
|
||||||
|
|
||||||
|
- [ ] [timeout] operation timeout을 command context에 적용한다.
|
||||||
|
- [ ] [cancel] running command cancel request를 처리한다. 검증: fake long command가 cancel 후 `cancelled` state로 종료된다.
|
||||||
|
- [ ] [dirty] command 종료 후 workspace dirty state를 lease에 반영한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- OS-level sandbox hardening
|
||||||
|
- secret manager 구현
|
||||||
|
- provider permission API
|
||||||
|
- UI approval workflow
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `services/core/internal/agentshell/`, `services/core/internal/worker/`, `services/core/internal/events/`
|
||||||
|
- 표준선(선택): policy는 allow by explicit capability, deny by default 방향을 따른다.
|
||||||
|
- 선행 작업: IOP Agent Run Bridge
|
||||||
|
- 후속 작업: Provider Adapter Foundation
|
||||||
|
- 확인 필요: command allowlist와 redaction 기준
|
||||||
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Milestone: IOP Agent Run Bridge
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/agent-shell-iop-execution/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
IOP CLI를 agent-shell command execution 경계에 연결해 workspace 안에서 agent-driven Git 작업을 수행한다. IOP run은 operation lifecycle과 Git revision event로 수렴해야 하며, 성공 기준은 구조화 응답이 아니라 workspace의 실제 Git 상태와 push 결과로 확인한다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 잠금
|
||||||
|
- 결정 필요:
|
||||||
|
- [ ] IOP CLI 실행 명령, profile/model 선택, 입력 파일 또는 stdin 계약을 확정한다.
|
||||||
|
- [ ] IOP credential과 workspace별 secret 주입 방식을 확정한다.
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- IOP CLI invocation contract
|
||||||
|
- workspace path, repo context, operation instruction 전달
|
||||||
|
- agent run state model
|
||||||
|
- IOP run success/failure 판정
|
||||||
|
- run 이후 Git status/diff/commit/push와 revision scan 연결
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [iop-run] IOP execution
|
||||||
|
|
||||||
|
IOP CLI를 workspace operation 실행 통로로 연결한다.
|
||||||
|
|
||||||
|
- [ ] [input] repo, branch, workspace path, user instruction, policy context를 IOP 입력으로 전달하는 형식을 정한다.
|
||||||
|
- [ ] [invoke] agent-shell이 IOP CLI를 실행하고 stdout/stderr를 stream한다. 검증: fake IOP command가 expected input을 받고 operation log를 남긴다.
|
||||||
|
- [ ] [state] `queued`, `running`, `succeeded`, `failed`, `cancelled` run state를 operation lifecycle에 매핑한다.
|
||||||
|
- [ ] [result] run 이후 Git status와 revision diff로 성공 여부를 확인한다.
|
||||||
|
|
||||||
|
### Epic: [git-result] Git result convergence
|
||||||
|
|
||||||
|
agent run 결과를 Git revision과 operation event로 수렴한다.
|
||||||
|
|
||||||
|
- [ ] [dirty-guard] run 종료 후 dirty workspace 정책을 적용한다.
|
||||||
|
- [ ] [commit-push] policy가 허용한 경우 commit/push operation으로 연결한다.
|
||||||
|
- [ ] [revision-event] push 이후 revision scan event를 발행한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- IOP 내부 모델 라우팅
|
||||||
|
- provider PR/MR 생성
|
||||||
|
- Plane/Jira work item lifecycle
|
||||||
|
- Flutter UI
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `services/core/internal/agentshell/`, `services/core/internal/worker/`, `services/core/internal/gitengine/`, `services/core/internal/events/`
|
||||||
|
- 표준선(선택): IOP run 결과는 Git 상태와 operation event로 검증한다.
|
||||||
|
- 선행 작업: Agent Shell Runtime Channel
|
||||||
|
- 후속 작업: Command Policy and Cancellation
|
||||||
|
- 확인 필요: IOP CLI invocation contract
|
||||||
|
|
||||||
40
agent-roadmap/phase/control-plane-foundation/PHASE.md
Normal file
40
agent-roadmap/phase/control-plane-foundation/PHASE.md
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Phase: Control Plane Foundation
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[진행중]
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
Gito의 초기 control plane을 build 가능한 modular monolith로 구성한다. platformless Git engine, repo/workspace/operation/event core model, Postgres 원장, proto-socket 우선 transport 경계를 정의하고 실제 구현 가능한 baseline으로 만든다.
|
||||||
|
|
||||||
|
## Milestone 흐름
|
||||||
|
|
||||||
|
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
|
||||||
|
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||||
|
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||||
|
|
||||||
|
- [진행중] Runtime Scaffold and Contract Baseline
|
||||||
|
- 경로: `agent-roadmap/phase/control-plane-foundation/milestones/runtime-scaffold-and-contract-baseline.md`
|
||||||
|
- 요약: Go command, Flutter control surface placeholder, contracts, agent-ops, README, architecture 문서를 실행 가능한 기준선으로 정리한다.
|
||||||
|
|
||||||
|
- [계획] Repo Registry and Workspace Lease
|
||||||
|
- 경로: `agent-roadmap/phase/control-plane-foundation/milestones/repo-registry-and-workspace-lease.md`
|
||||||
|
- 요약: 관리 대상 repo와 workspace slot/lease를 Postgres source of truth로 저장하고 안전하게 할당한다.
|
||||||
|
|
||||||
|
- [계획] Platformless Git Operation Engine
|
||||||
|
- 경로: `agent-roadmap/phase/control-plane-foundation/milestones/platformless-git-operation-engine.md`
|
||||||
|
- 요약: clone, fetch, status, diff, commit, push, revision scan을 provider 없이 local bare repo 기반으로 검증한다.
|
||||||
|
|
||||||
|
- [계획] Operation Event Outbox
|
||||||
|
- 경로: `agent-roadmap/phase/control-plane-foundation/milestones/operation-event-outbox.md`
|
||||||
|
- 요약: operation lifecycle, idempotency, audit event, outbox 발행을 PostgreSQL 기준으로 구성한다.
|
||||||
|
|
||||||
|
## Phase 경계
|
||||||
|
|
||||||
|
- 이 Phase는 Gito 자체 control plane과 platformless Git 기반만 다룬다.
|
||||||
|
- IOP CLI 실행과 agent-shell streaming은 다음 Phase에서 다룬다.
|
||||||
|
- PR/MR 같은 provider API는 provider integration Phase에서 다룬다.
|
||||||
|
- Flutter 화면의 실제 UX 완성은 control surface Phase에서 다룬다.
|
||||||
|
- Redis는 이 Phase의 source of truth가 아니며, 필요할 때 event fanout 가속 후보로만 남긴다.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Milestone: Operation Event Outbox
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/control-plane-foundation/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
operation lifecycle과 normalized event를 PostgreSQL 원장에 기록하고, proto-socket event stream 또는 future Redis fanout이 읽을 수 있는 outbox 경계를 만든다. 재시도와 중복 적용은 idempotency key로 제어한다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 해제
|
||||||
|
- 결정 필요: 없음
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- operation lifecycle model
|
||||||
|
- idempotency key와 duplicate guard
|
||||||
|
- operation event/outbox table
|
||||||
|
- worker가 pending operation을 pick하는 store boundary
|
||||||
|
- proto-socket event stream이 사용할 event shape
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [operation] Operation lifecycle
|
||||||
|
|
||||||
|
Git operation, agent run, provider projection을 같은 operation 원장으로 관리한다.
|
||||||
|
|
||||||
|
- [ ] [op-model] operation type/state/idempotency schema를 확정한다.
|
||||||
|
- [ ] [op-store] operation create/start/succeed/fail/cancel store boundary를 만든다. 검증: invalid transition과 idempotency duplicate를 테스트한다.
|
||||||
|
- [ ] [op-pick] worker가 pending operation을 안전하게 pick하는 기준을 만든다. 검증: 같은 operation이 중복 pick되지 않는다.
|
||||||
|
|
||||||
|
### Epic: [outbox] Durable events
|
||||||
|
|
||||||
|
operation 결과를 durable event로 남기고 fanout 대상이 읽을 수 있게 한다.
|
||||||
|
|
||||||
|
- [ ] [event-model] normalized event type과 payload 저장 형식을 정리한다.
|
||||||
|
- [ ] [event-store] event append/list/mark-published boundary를 만든다. 검증: event order와 retry 가능한 publish 상태를 확인한다.
|
||||||
|
- [ ] [protosocket-events] proto-socket `event` channel 후보와 outbox event mapping을 contracts에 기록한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- Redis Streams 구현
|
||||||
|
- provider-specific projection
|
||||||
|
- Flutter event UI
|
||||||
|
- distributed scheduler 최적화
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `services/core/internal/events/`, `services/core/internal/storage/`, `services/core/internal/worker/`, `services/core/migrations/`
|
||||||
|
- 표준선(선택): Postgres outbox가 event source of truth이며 Redis는 optional acceleration이다.
|
||||||
|
- 선행 작업: Platformless Git Operation Engine
|
||||||
|
- 후속 작업: Agent Shell Runtime Channel
|
||||||
|
- 확인 필요: 없음
|
||||||
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Milestone: Platformless Git Operation Engine
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/control-plane-foundation/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
GitHub/GitLab/Gitea 같은 플랫폼 API 없이 Git CLI와 local bare repository만으로 Git operation을 실행하고 검증한다. 이 Milestone은 Gito의 모든 provider adapter가 의존할 platformless Git 기준선을 만든다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 해제
|
||||||
|
- 결정 필요: 없음
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- clone, fetch, pull, checkout, status, diff, commit, push operation
|
||||||
|
- revision cursor와 changed file scan
|
||||||
|
- operation input/output DTO
|
||||||
|
- command timeout과 stderr/stdout capture boundary
|
||||||
|
- local bare repo 기반 integration test
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [ops] Git operations
|
||||||
|
|
||||||
|
Provider API에 의존하지 않는 Git command 기능을 만든다.
|
||||||
|
|
||||||
|
- [ ] [clone-fetch] clone/fetch operation을 구현한다. 검증: local bare repo를 remote로 사용해 fetch 후 revision을 확인한다.
|
||||||
|
- [ ] [status-diff] status/diff operation을 구현한다. 검증: staged/unstaged/clean workspace 상태를 테스트한다.
|
||||||
|
- [ ] [commit-push] commit/push operation을 구현한다. 검증: local bare repo에 push한 revision이 remote branch에 반영된다.
|
||||||
|
- [ ] [branch-checkout] branch checkout과 source branch 기준을 구현한다. 검증: branch 변경 후 worktree revision을 확인한다.
|
||||||
|
|
||||||
|
### Epic: [scan] Revision scan
|
||||||
|
|
||||||
|
branch revision 변화와 changed file을 normalized event 입력으로 만든다.
|
||||||
|
|
||||||
|
- [ ] [cursor] repo/branch별 last seen revision cursor를 저장한다.
|
||||||
|
- [ ] [changed-files] `before..after` changed file scan을 구현한다. 검증: 여러 commit 사이 변경 파일 목록이 기대와 일치한다.
|
||||||
|
- [ ] [event-input] scan 결과를 `RevisionEvent` 후보로 변환한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- PR/MR 생성
|
||||||
|
- provider webhook 처리
|
||||||
|
- IOP CLI 실행
|
||||||
|
- Flutter 표시
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `services/core/internal/gitengine/`, `services/core/internal/core/`, `services/core/internal/storage/`
|
||||||
|
- 표준선(선택): webhook 없이도 `fetch + revision diff + scan`만으로 변경을 확인할 수 있어야 한다.
|
||||||
|
- 선행 작업: Repo Registry and Workspace Lease
|
||||||
|
- 후속 작업: Operation Event Outbox
|
||||||
|
- 확인 필요: 없음
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Milestone: Repo Registry and Workspace Lease
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/control-plane-foundation/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
관리 대상 Git repository와 workspace slot/lease를 PostgreSQL source of truth로 저장한다. 여러 worker나 agent-shell이 같은 workspace를 동시에 잡지 않도록 lease, dirty state, credential ref 경계를 정의하고 테스트한다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 해제
|
||||||
|
- 결정 필요: 없음
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- repo registry model과 migration
|
||||||
|
- workspace root, slot, lease state model
|
||||||
|
- credential value가 아닌 `credential_ref` 저장 기준
|
||||||
|
- lease acquire/release, dirty/error state 전환
|
||||||
|
- local/worker가 같은 slot을 중복 배정받지 않도록 하는 DB 기준
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [registry] Repository registry
|
||||||
|
|
||||||
|
Gito가 관리할 repository와 기본 branch/workspace root/credential ref를 저장한다.
|
||||||
|
|
||||||
|
- [ ] [repo-model] `Repo` model과 Postgres schema를 정리한다. 검증: migration에 `remote_url`, `default_branch`, `workspace_root`, `credential_ref`가 포함된다.
|
||||||
|
- [ ] [repo-store] repo create/get/list/update store boundary를 만든다. 검증: storage test가 중복 id와 필수 필드 validation을 확인한다.
|
||||||
|
- [ ] [repo-contract] proto-socket `repo` channel 후보 DTO와 REST bootstrap 예외를 contracts에 기록한다.
|
||||||
|
|
||||||
|
### Epic: [lease] Workspace lease
|
||||||
|
|
||||||
|
작업 slot을 안전하게 예약하고 해제하는 원장을 만든다.
|
||||||
|
|
||||||
|
- [ ] [lease-model] `WorkspaceLease` state를 `available`, `leased`, `dirty`, `error` 기준으로 확정한다.
|
||||||
|
- [ ] [lease-store] DB transaction으로 하나의 available slot만 lease하는 store boundary를 만든다. 검증: 동시 lease 시 같은 slot이 중복 반환되지 않는 테스트를 둔다.
|
||||||
|
- [ ] [lease-release] release, dirty, error 전환 기준을 operation 결과와 연결한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- 실제 Git command 실행
|
||||||
|
- agent-shell 연결
|
||||||
|
- provider adapter 구현
|
||||||
|
- Flutter UX 구현
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `services/core/internal/core/`, `services/core/internal/storage/`, `services/core/migrations/`, `packages/contracts/notes/gito-control-plane.md`
|
||||||
|
- 표준선(선택): Postgres가 lease와 audit의 source of truth다.
|
||||||
|
- 선행 작업: Runtime Scaffold and Contract Baseline
|
||||||
|
- 후속 작업: Platformless Git Operation Engine
|
||||||
|
- 확인 필요: 없음
|
||||||
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
# Milestone: Runtime Scaffold and Contract Baseline
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/control-plane-foundation/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
Gito를 독립 프로젝트로 시작할 수 있도록 Go core, Flutter control surface scaffold, contracts, agent-ops 규칙, README, architecture 문서를 한 기준선으로 정리한다. 이 Milestone은 다음 구현 Milestone이 바로 `agent-task` 계획을 만들 수 있는 진입점을 제공하는 데서 끝난다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[진행중]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 해제
|
||||||
|
- 결정 필요: 없음
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- Go `server`, `worker`, `shell` command scaffold
|
||||||
|
- `controlplane`, `core`, `gitengine`, `worker`, `agentshell`, `provider`, `events`, `storage` package boundary
|
||||||
|
- Flutter control surface placeholder
|
||||||
|
- proto-socket 우선, REST 예외, gRPC 제외 transport 정책
|
||||||
|
- README와 architecture 문서
|
||||||
|
- agent-ops rules, skills, local test 진입점
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [scaffold] 프로젝트 기준선
|
||||||
|
|
||||||
|
Gito의 초기 작업자가 경계와 명령을 바로 이해할 수 있는 repository scaffold를 구성한다.
|
||||||
|
|
||||||
|
- [x] [go-cmds] Go `server`, `worker`, `shell` command를 build 가능한 상태로 둔다. 검증: `bin/build`가 `gito-server`, `gito-worker`, `gito-shell`을 생성한다.
|
||||||
|
- [x] [domain-packages] core domain, gitengine, provider, events, storage, worker, agentshell package boundary를 만든다. 검증: `cd services/core && go test ./...` PASS.
|
||||||
|
- [x] [contracts] proto-socket 우선 transport, REST 예외, gRPC 제외, event/DTO 후보를 contracts note에 기록한다.
|
||||||
|
- [x] [readme] README를 사람과 AI가 함께 읽는 작업 진입점으로 보강한다.
|
||||||
|
- [ ] [protosocket-surface] proto-socket placeholder를 channel/action registry scaffold로 전환한다. 검증: proto-socket route test가 operation/event channel placeholder를 확인한다.
|
||||||
|
- [ ] [storage-boundary] Postgres migration과 storage boundary를 실제 store interface 기준으로 연결한다. 검증: storage package test가 repo/operation/event 기본 CRUD 또는 interface contract를 확인한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 일부 scaffold와 문서 기준선은 생성되었지만 proto-socket surface와 storage boundary 연결이 남아 있다.
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- 실제 Git clone/fetch/commit/push operation 구현
|
||||||
|
- 실제 proto-socket client와 Flutter 연결
|
||||||
|
- IOP CLI 실행
|
||||||
|
- provider API adapter 구현
|
||||||
|
- production 배포 구성
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `README.md`, `docs/architecture.md`, `packages/contracts/notes/gito-control-plane.md`, `services/core/`, `apps/client/`, `agent-ops/`
|
||||||
|
- 표준선(선택): modular monolith로 시작하되 `server`, `worker`, `shell`은 분리 가능한 process role로 둔다.
|
||||||
|
- 선행 작업: 없음
|
||||||
|
- 후속 작업: Repo Registry and Workspace Lease
|
||||||
|
- 확인 필요: 없음
|
||||||
|
|
||||||
35
agent-roadmap/phase/control-surface-operations-ux/PHASE.md
Normal file
35
agent-roadmap/phase/control-surface-operations-ux/PHASE.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Phase: Control Surface Operations UX
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
Flutter control surface와 향후 `gitoctl`을 통해 repo, workspace, operation, agent-shell, provider event를 관찰하고 제어할 수 있게 한다. UI는 command 실행 주체가 아니라 control plane consumer로 남긴다.
|
||||||
|
|
||||||
|
## Milestone 흐름
|
||||||
|
|
||||||
|
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
|
||||||
|
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||||
|
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||||
|
|
||||||
|
- [계획] Flutter Control Surface Baseline
|
||||||
|
- 경로: `agent-roadmap/phase/control-surface-operations-ux/milestones/flutter-control-surface-baseline.md`
|
||||||
|
- 요약: Flutter 앱이 proto-socket으로 operation 상태와 event stream을 읽는 기본 workbench를 제공한다.
|
||||||
|
|
||||||
|
- [계획] Operations Observability
|
||||||
|
- 경로: `agent-roadmap/phase/control-surface-operations-ux/milestones/operations-observability.md`
|
||||||
|
- 요약: operation log, repo revision, workspace lease, runner heartbeat를 사람이 추적 가능한 화면과 API로 제공한다.
|
||||||
|
|
||||||
|
- [스케치] Multi Runner Management
|
||||||
|
- 경로: `agent-roadmap/phase/control-surface-operations-ux/milestones/multi-runner-management.md`
|
||||||
|
- 요약: 여러 agent-shell runner를 등록, 배정, 격리, 회수하는 운영 UX 후보를 정리한다.
|
||||||
|
|
||||||
|
## Phase 경계
|
||||||
|
|
||||||
|
- Flutter 앱은 Git command를 직접 실행하지 않는다.
|
||||||
|
- UI는 provider별 DTO에 직접 결합하지 않고 core domain/event 계약을 소비한다.
|
||||||
|
- multi-runner 운영 정책은 실제 사용 규모와 보안 요구가 확인된 뒤 계획으로 승격한다.
|
||||||
|
- 모바일/데스크톱 배포 범위는 별도 결정이 필요하다.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
# Milestone: Flutter Control Surface Baseline
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/control-surface-operations-ux/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
Flutter 앱을 Gito operation과 event를 보는 control surface로 구성한다. 앱은 Git command를 직접 실행하지 않고 proto-socket을 통해 control plane의 repo, workspace, operation, event 상태를 소비한다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 잠금
|
||||||
|
- 결정 필요:
|
||||||
|
- [ ] 초기 Flutter target을 desktop 우선으로 둘지 mobile/desktop 동시 기준으로 둘지 확정한다.
|
||||||
|
- [ ] 첫 화면에서 repo 중심, operation 중심, runner 중심 중 어떤 navigation을 우선할지 확정한다.
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- Flutter app scaffold 정리
|
||||||
|
- proto-socket endpoint 설정
|
||||||
|
- repo/operation/event 목록 read model
|
||||||
|
- 기본 workbench shell
|
||||||
|
- no-op safe bootstrap
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [app-shell] App shell
|
||||||
|
|
||||||
|
운영자가 repository와 operation 상태를 빠르게 확인하는 기본 shell을 만든다.
|
||||||
|
|
||||||
|
- [ ] [bootstrap] Flutter bootstrap과 env 기반 proto-socket 설정을 만든다.
|
||||||
|
- [ ] [layout] repo list, operation list, event panel이 들어갈 workbench layout을 만든다.
|
||||||
|
- [ ] [no-op] proto-socket endpoint가 없을 때도 앱이 안전하게 시작되도록 한다.
|
||||||
|
|
||||||
|
### Epic: [read-model] Read model
|
||||||
|
|
||||||
|
Control plane 상태를 읽어 UI에 표시한다.
|
||||||
|
|
||||||
|
- [ ] [repo-read] repo list/read DTO를 앱 모델로 표현한다.
|
||||||
|
- [ ] [op-read] operation state/read DTO를 앱 모델로 표현한다.
|
||||||
|
- [ ] [event-read] event stream snapshot을 앱 모델로 표현한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- Git command 직접 실행
|
||||||
|
- provider-specific 화면
|
||||||
|
- runner 설치/배포 UI
|
||||||
|
- mobile push notification
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `apps/client/`, `packages/contracts/notes/gito-control-plane.md`
|
||||||
|
- 표준선(선택): Flutter는 control plane consumer이며 command runtime이 아니다.
|
||||||
|
- 선행 작업: Webhook Revision Reconcile
|
||||||
|
- 후속 작업: Operations Observability
|
||||||
|
- 확인 필요: Flutter target과 초기 navigation 우선순위
|
||||||
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
# Milestone: Multi Runner Management
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/control-surface-operations-ux/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
여러 agent-shell runner를 등록, 배정, 격리, 회수하는 운영 UX와 정책 후보를 정리한다. 이 Milestone은 아직 구현 계획이 아니라 runner 수가 늘어날 때 필요한 제품/보안/운영 결정을 정리하는 스케치다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[스케치]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- [ ] runner 배정 기준을 repo affinity, capability, load, security boundary 중 어디에 우선할지 정한다.
|
||||||
|
- [ ] runner credential과 workspace isolation 수준을 확정한다.
|
||||||
|
- [ ] offline/stale runner 회수 정책과 lease recovery 기준을 정한다.
|
||||||
|
- [ ] 첫 구현을 UI 중심으로 할지 control plane policy 중심으로 할지 정한다.
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 잠금
|
||||||
|
- 결정 필요:
|
||||||
|
- [ ] multi-runner 운영이 필요한 최소 규모와 첫 target deployment 형태를 확정한다.
|
||||||
|
- [ ] runner isolation과 credential 보안 기준을 확정한다.
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- runner registry 후보
|
||||||
|
- capability-based scheduling 후보
|
||||||
|
- stale/offline runner recovery 후보
|
||||||
|
- workspace isolation 후보
|
||||||
|
- multi-runner UI 후보
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [runner-sketch] Runner 운영 스케치
|
||||||
|
|
||||||
|
multi-runner 기능을 구현 계획으로 승격하기 위한 결정을 모은다.
|
||||||
|
|
||||||
|
- [ ] [registry] runner registry와 capability shape 후보를 정리한다.
|
||||||
|
- [ ] [scheduling] repo/operation을 runner에 배정하는 scheduling 기준 후보를 비교한다.
|
||||||
|
- [ ] [recovery] stale lease와 offline runner recovery 후보를 정리한다.
|
||||||
|
- [ ] [ux] runner 상태와 lease 회수를 UI에서 어떻게 보여줄지 후보를 정리한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- 실제 runner scheduler 구현
|
||||||
|
- production deployment automation
|
||||||
|
- secret manager 구현
|
||||||
|
- enterprise multi-tenant permission model
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `apps/client/`, `services/core/internal/agentshell/`, `services/core/internal/worker/`
|
||||||
|
- 표준선(선택): 스케치 상태에서는 구현 계획이나 코드 구현을 시작하지 않는다.
|
||||||
|
- 선행 작업: Operations Observability
|
||||||
|
- 후속 작업: 없음
|
||||||
|
- 확인 필요: runner 운영 규모, isolation 기준, deployment 형태
|
||||||
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Milestone: Operations Observability
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/control-surface-operations-ux/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
operation log, repo revision, workspace lease, runner heartbeat, provider event를 사람이 추적할 수 있게 만든다. UI와 API는 실패 원인, retry 가능 여부, waiting gate를 명확히 보여줘야 한다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 해제
|
||||||
|
- 결정 필요: 없음
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- operation timeline
|
||||||
|
- command log stream display
|
||||||
|
- workspace lease/dirty/error 표시
|
||||||
|
- runner heartbeat 표시
|
||||||
|
- provider webhook/reconcile event 표시
|
||||||
|
- retry/cancel action entrypoint 후보
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [timeline] Operation timeline
|
||||||
|
|
||||||
|
작업 진행과 실패 지점을 추적 가능한 timeline으로 보여준다.
|
||||||
|
|
||||||
|
- [ ] [op-events] operation event를 시간순 timeline으로 표시한다.
|
||||||
|
- [ ] [logs] command stdout/stderr chunk를 operation log view로 표시한다.
|
||||||
|
- [ ] [state-badge] queued/running/succeeded/failed/cancelled state를 일관된 badge로 표현한다.
|
||||||
|
|
||||||
|
### Epic: [runtime-status] Runtime status
|
||||||
|
|
||||||
|
workspace와 runner의 현재 상태를 운영자가 파악할 수 있게 한다.
|
||||||
|
|
||||||
|
- [ ] [lease-view] workspace lease, dirty, error 상태를 표시한다.
|
||||||
|
- [ ] [runner-view] agent-shell heartbeat와 capability를 표시한다.
|
||||||
|
- [ ] [provider-view] provider webhook/reconcile event를 표시한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- complex analytics dashboard
|
||||||
|
- alerting integration
|
||||||
|
- mobile notification
|
||||||
|
- multi-tenant permission UI
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `apps/client/`, `services/core/internal/events/`, `packages/contracts/notes/gito-control-plane.md`
|
||||||
|
- 표준선(선택): 관찰 UI는 Postgres event/outbox와 proto-socket event stream의 read model을 소비한다.
|
||||||
|
- 선행 작업: Flutter Control Surface Baseline
|
||||||
|
- 후속 작업: Multi Runner Management
|
||||||
|
- 확인 필요: 없음
|
||||||
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Phase: Provider Change Request Integration
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
GitHub PR, GitLab MR, Gitea PR 같은 provider 기능을 provider-neutral ChangeRequest 인터페이스로 묶는다. Webhook은 빠른 wakeup signal로 사용하되, 최종 상태 판정은 Git revision/diff와 provider read API로 재검증한다.
|
||||||
|
|
||||||
|
## Milestone 흐름
|
||||||
|
|
||||||
|
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
|
||||||
|
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||||
|
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||||
|
|
||||||
|
- [계획] Provider Adapter Foundation
|
||||||
|
- 경로: `agent-roadmap/phase/provider-change-request-integration/milestones/provider-adapter-foundation.md`
|
||||||
|
- 요약: provider registry, credential ref, webhook intake, provider capability boundary를 만든다.
|
||||||
|
|
||||||
|
- [계획] Change Request Abstraction
|
||||||
|
- 경로: `agent-roadmap/phase/provider-change-request-integration/milestones/change-request-abstraction.md`
|
||||||
|
- 요약: GitHub PR, GitLab MR, Gitea PR을 공통 ChangeRequest action과 event로 표현한다.
|
||||||
|
|
||||||
|
- [계획] Webhook Revision Reconcile
|
||||||
|
- 경로: `agent-roadmap/phase/provider-change-request-integration/milestones/webhook-revision-reconcile.md`
|
||||||
|
- 요약: provider webhook, polling, Git revision scan을 같은 변경 event로 정규화하고 재검증한다.
|
||||||
|
|
||||||
|
## Phase 경계
|
||||||
|
|
||||||
|
- Git 자체 조작은 provider adapter가 아니라 platformless Git engine이 맡는다.
|
||||||
|
- provider adapter는 PR/MR/review/checks/comment/webhook 같은 플랫폼 API만 맡는다.
|
||||||
|
- provider별 credential 원문은 tracked 파일에 저장하지 않고 credential ref로만 연결한다.
|
||||||
|
- provider webhook만으로 상태를 확정하지 않고 Git revision 또는 provider read API로 확인한다.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Milestone: Change Request Abstraction
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/provider-change-request-integration/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
GitHub PR, GitLab MR, Gitea PR을 Gito의 provider-neutral `ChangeRequest`로 묶는다. 외부 소비자는 provider별 이름을 몰라도 create, update, comment, request review, merge, close 같은 공통 action을 사용할 수 있어야 한다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 해제
|
||||||
|
- 결정 필요: 없음
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- ChangeRequest domain DTO
|
||||||
|
- provider-neutral action set
|
||||||
|
- provider adapter mapping
|
||||||
|
- checks/review/comment 최소 공통 shape
|
||||||
|
- provider-specific extension field 경계
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [cr-model] ChangeRequest model
|
||||||
|
|
||||||
|
PR/MR-like 객체를 공통 domain으로 표현한다.
|
||||||
|
|
||||||
|
- [ ] [shape] source branch, target branch, title, body, draft, state, external id를 포함하는 ChangeRequest shape를 확정한다.
|
||||||
|
- [ ] [actions] create, update, comment, request review, merge, close action을 정의한다.
|
||||||
|
- [ ] [events] opened, updated, merged, closed event를 normalized event로 매핑한다.
|
||||||
|
|
||||||
|
### Epic: [adapter-map] Adapter mapping
|
||||||
|
|
||||||
|
provider별 API 차이를 adapter 안에 격리한다.
|
||||||
|
|
||||||
|
- [ ] [github-map] GitHub PR mapping 후보를 작성한다.
|
||||||
|
- [ ] [gitlab-map] GitLab MR mapping 후보를 작성한다.
|
||||||
|
- [ ] [gitea-map] Gitea PR mapping 후보를 작성한다.
|
||||||
|
- [ ] [extension] provider-specific field를 공통 DTO 밖 확장 영역에 둔다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- provider별 완전한 API client 구현
|
||||||
|
- CI provider integration
|
||||||
|
- branch protection/permission API
|
||||||
|
- Flutter PR/MR 화면
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `services/core/internal/core/`, `services/core/internal/provider/`, `packages/contracts/notes/gito-control-plane.md`
|
||||||
|
- 표준선(선택): provider-neutral interface를 먼저 정의하고 provider-specific DTO는 adapter 내부에 둔다.
|
||||||
|
- 선행 작업: Provider Adapter Foundation
|
||||||
|
- 후속 작업: Webhook Revision Reconcile
|
||||||
|
- 확인 필요: 없음
|
||||||
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
# Milestone: Provider Adapter Foundation
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/provider-change-request-integration/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
GitHub, GitLab, Gitea, Plane, Jira 같은 외부 시스템을 provider adapter로 붙일 수 있는 공통 foundation을 만든다. Git 자체 조작은 platformless Git engine에 남기고, provider adapter는 플랫폼 API와 webhook 세부만 소유한다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 잠금
|
||||||
|
- 결정 필요:
|
||||||
|
- [ ] 첫 구현 provider 우선순위를 GitHub, GitLab, Gitea 중에서 확정한다.
|
||||||
|
- [ ] credential ref가 가리킬 secret backend 또는 local secret 파일 기준을 확정한다.
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- provider registry와 capability model
|
||||||
|
- provider config와 credential ref
|
||||||
|
- webhook intake REST endpoint
|
||||||
|
- provider read/write client interface
|
||||||
|
- provider event normalization boundary
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [registry] Provider registry
|
||||||
|
|
||||||
|
provider별 capability와 config를 등록한다.
|
||||||
|
|
||||||
|
- [ ] [provider-model] provider id, endpoint, credential ref, capabilities를 model로 정의한다.
|
||||||
|
- [ ] [provider-store] provider config를 저장하고 조회하는 store boundary를 만든다.
|
||||||
|
- [ ] [capability] ChangeRequest, webhook, checks, comment 같은 capability flag를 정의한다.
|
||||||
|
|
||||||
|
### Epic: [webhook] Webhook intake
|
||||||
|
|
||||||
|
provider webhook을 normalized event 입력으로 받는다.
|
||||||
|
|
||||||
|
- [ ] [callback] provider callback REST endpoint 경계를 만든다. 검증: fake webhook이 `provider.webhook.received` event를 남긴다.
|
||||||
|
- [ ] [verify] webhook signature 검증 hook을 adapter별로 꽂을 수 있게 한다.
|
||||||
|
- [ ] [normalize] provider payload를 provider-neutral event 후보로 변환한다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- provider별 PR/MR 실제 생성
|
||||||
|
- provider별 CI/checks 상세 구현
|
||||||
|
- Git operation 실행
|
||||||
|
- UI 설정 화면
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `services/core/internal/provider/`, `services/core/internal/controlplane/`, `services/core/internal/events/`, `packages/contracts/notes/gito-control-plane.md`
|
||||||
|
- 표준선(선택): provider adapter는 platform API만 소유하고 Git object 상태는 Git engine으로 확인한다.
|
||||||
|
- 선행 작업: Command Policy and Cancellation
|
||||||
|
- 후속 작업: Change Request Abstraction
|
||||||
|
- 확인 필요: 첫 provider 우선순위와 credential backend
|
||||||
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Milestone: Webhook Revision Reconcile
|
||||||
|
|
||||||
|
## 위치
|
||||||
|
|
||||||
|
- Roadmap: `agent-roadmap/ROADMAP.md`
|
||||||
|
- Phase: `agent-roadmap/phase/provider-change-request-integration/PHASE.md`
|
||||||
|
|
||||||
|
## 목표
|
||||||
|
|
||||||
|
provider webhook, provider polling, Git revision scan을 같은 변경 입력으로 정규화한다. Webhook은 빠른 wakeup signal이지만 최종 판정은 Git revision/diff 또는 provider read API로 재검증해 중복 적용과 누락을 줄인다.
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
[계획]
|
||||||
|
|
||||||
|
## 승격 조건
|
||||||
|
|
||||||
|
- 없음
|
||||||
|
|
||||||
|
## 구현 잠금
|
||||||
|
|
||||||
|
- 상태: 해제
|
||||||
|
- 결정 필요: 없음
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
- webhook received event
|
||||||
|
- branch updated event
|
||||||
|
- provider polling fallback
|
||||||
|
- revision mismatch conflict
|
||||||
|
- idempotency key와 expected revision
|
||||||
|
- reconcile dry-run/apply action 후보
|
||||||
|
|
||||||
|
## 기능
|
||||||
|
|
||||||
|
### Epic: [sources] Change sources
|
||||||
|
|
||||||
|
여러 입력을 하나의 change event model로 정규화한다.
|
||||||
|
|
||||||
|
- [ ] [webhook-source] webhook payload를 wakeup signal event로 저장한다.
|
||||||
|
- [ ] [poll-source] provider polling fallback shape를 정의한다.
|
||||||
|
- [ ] [git-source] Git revision scan event와 provider event를 같은 identity로 연결한다.
|
||||||
|
|
||||||
|
### Epic: [reconcile] Reconcile policy
|
||||||
|
|
||||||
|
변경 적용 전 재검증과 conflict 처리를 수행한다.
|
||||||
|
|
||||||
|
- [ ] [expected-rev] expected revision이 맞지 않으면 conflict로 멈춘다.
|
||||||
|
- [ ] [dry-run] reconcile dry-run 결과로 drift/conflict/proposal을 반환한다.
|
||||||
|
- [ ] [apply] idempotency key로 중복 적용 없이 change를 반영한다. 검증: 같은 event 재처리 시 side effect가 한 번만 실행된다.
|
||||||
|
|
||||||
|
## 완료 리뷰
|
||||||
|
|
||||||
|
- 상태: 없음
|
||||||
|
- 요청일: 없음
|
||||||
|
- 완료 근거: 없음
|
||||||
|
- 리뷰 필요:
|
||||||
|
- [ ] 사용자가 완료 결과를 확인했다
|
||||||
|
- [ ] archive 이동을 승인했다
|
||||||
|
- 리뷰 코멘트: 없음
|
||||||
|
|
||||||
|
## 범위 제외
|
||||||
|
|
||||||
|
- provider별 모든 webhook payload 지원
|
||||||
|
- real-time delivery 보장
|
||||||
|
- Redis Streams fanout
|
||||||
|
- UI conflict resolution 화면
|
||||||
|
|
||||||
|
## 작업 컨텍스트
|
||||||
|
|
||||||
|
- 관련 경로: `services/core/internal/events/`, `services/core/internal/provider/`, `services/core/internal/gitengine/`, `services/core/internal/worker/`
|
||||||
|
- 표준선(선택): webhook은 빠른 신호이고 확정은 Git revision/diff 또는 provider read API로 수행한다.
|
||||||
|
- 선행 작업: Change Request Abstraction
|
||||||
|
- 후속 작업: Flutter Control Surface Baseline
|
||||||
|
- 확인 필요: 없음
|
||||||
|
|
||||||
|
|
@ -14,3 +14,13 @@ Read this file before validation work.
|
||||||
|
|
||||||
Report executed commands, pass/fail result, skipped tools, and remaining risk.
|
Report executed commands, pass/fail result, skipped tools, and remaining risk.
|
||||||
|
|
||||||
|
|
||||||
|
## 라우팅
|
||||||
|
|
||||||
|
- workspace-ops / smoke / 도메인 기본 smoke 검증: `agent-test/local/workspace-ops-smoke.md`
|
||||||
|
|
||||||
|
- core / smoke / 도메인 기본 smoke 검증: `agent-test/local/core-smoke.md`
|
||||||
|
|
||||||
|
- contracts / smoke / 도메인 기본 smoke 검증: `agent-test/local/contracts-smoke.md`
|
||||||
|
|
||||||
|
- client / smoke / 도메인 기본 smoke 검증: `agent-test/local/client-smoke.md`
|
||||||
|
|
|
||||||
17
opencode.json
Normal file
17
opencode.json
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://opencode.ai/config.json",
|
||||||
|
"permission": {
|
||||||
|
"read": {
|
||||||
|
"agent-task/archive/**": "deny"
|
||||||
|
},
|
||||||
|
"glob": {
|
||||||
|
"agent-task/archive/**": "deny"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"watcher": {
|
||||||
|
"ignore": [
|
||||||
|
"agent-task/archive/**",
|
||||||
|
"agent-roadmap/archive/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue